summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:45 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:45 -0800
commitd83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/java
parent076357b8567458d4b6dfdcf839ef751634cd2bfb (diff)
downloadframeworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.zip
frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.gz
frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/accounts/AccountMonitor.java174
-rw-r--r--core/java/android/accounts/AccountMonitorListener.java29
-rw-r--r--core/java/android/accounts/AccountsServiceConstants.java78
-rw-r--r--core/java/android/accounts/IAccountsService.aidl54
-rwxr-xr-xcore/java/android/accounts/package.html5
-rw-r--r--core/java/android/annotation/SdkConstant.java36
-rw-r--r--core/java/android/annotation/Widget.java37
-rw-r--r--core/java/android/app/Activity.java3598
-rw-r--r--core/java/android/app/ActivityGroup.java127
-rw-r--r--core/java/android/app/ActivityManager.java761
-rw-r--r--core/java/android/app/ActivityManagerNative.java2135
-rw-r--r--core/java/android/app/ActivityThread.java3916
-rw-r--r--core/java/android/app/AlarmManager.java276
-rw-r--r--core/java/android/app/AlertDialog.java795
-rw-r--r--core/java/android/app/AliasActivity.java123
-rw-r--r--core/java/android/app/Application.java74
-rw-r--r--core/java/android/app/ApplicationContext.java2728
-rw-r--r--core/java/android/app/ApplicationLoaders.java72
-rw-r--r--core/java/android/app/ApplicationThreadNative.java658
-rw-r--r--core/java/android/app/DatePickerDialog.java185
-rw-r--r--core/java/android/app/Dialog.java954
-rw-r--r--core/java/android/app/ExpandableListActivity.java323
-rw-r--r--core/java/android/app/IActivityManager.java368
-rw-r--r--core/java/android/app/IActivityPendingResult.aidl27
-rw-r--r--core/java/android/app/IActivityWatcher.aidl55
-rwxr-xr-xcore/java/android/app/IAlarmManager.aidl34
-rw-r--r--core/java/android/app/IApplicationThread.java118
-rw-r--r--core/java/android/app/IInstrumentationWatcher.aidl31
-rwxr-xr-xcore/java/android/app/IIntentReceiver.aidl33
-rw-r--r--core/java/android/app/IIntentSender.aidl27
-rw-r--r--core/java/android/app/INotificationManager.aidl34
-rw-r--r--core/java/android/app/ISearchManager.aidl25
-rw-r--r--core/java/android/app/IServiceConnection.aidl26
-rw-r--r--core/java/android/app/IStatusBar.aidl29
-rwxr-xr-xcore/java/android/app/IThumbnailReceiver.aidl30
-rw-r--r--core/java/android/app/ITransientNotification.aidl25
-rw-r--r--core/java/android/app/IWallpaperService.aidl55
-rw-r--r--core/java/android/app/IWallpaperServiceCallback.aidl31
-rw-r--r--core/java/android/app/Instrumentation.java1613
-rw-r--r--core/java/android/app/KeyguardManager.java155
-rw-r--r--core/java/android/app/LauncherActivity.java380
-rw-r--r--core/java/android/app/ListActivity.java316
-rw-r--r--core/java/android/app/LocalActivityManager.java627
-rw-r--r--core/java/android/app/Notification.aidl19
-rw-r--r--core/java/android/app/Notification.java483
-rw-r--r--core/java/android/app/NotificationManager.java136
-rw-r--r--core/java/android/app/PendingIntent.aidl20
-rw-r--r--core/java/android/app/PendingIntent.java508
-rw-r--r--core/java/android/app/ProgressDialog.java301
-rw-r--r--core/java/android/app/ResultInfo.java86
-rw-r--r--core/java/android/app/SearchDialog.java1593
-rw-r--r--core/java/android/app/SearchManager.java1377
-rw-r--r--core/java/android/app/Service.java378
-rw-r--r--core/java/android/app/StatusBarManager.java139
-rw-r--r--core/java/android/app/TabActivity.java148
-rw-r--r--core/java/android/app/TimePickerDialog.java162
-rw-r--r--core/java/android/app/package.html72
-rw-r--r--core/java/android/bluetooth/AtCommandHandler.java93
-rw-r--r--core/java/android/bluetooth/AtCommandResult.java117
-rw-r--r--core/java/android/bluetooth/AtParser.java370
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java247
-rw-r--r--core/java/android/bluetooth/BluetoothAudioGateway.java190
-rw-r--r--core/java/android/bluetooth/BluetoothClass.java191
-rw-r--r--core/java/android/bluetooth/BluetoothDevice.java578
-rw-r--r--core/java/android/bluetooth/BluetoothError.java42
-rw-r--r--core/java/android/bluetooth/BluetoothHeadset.java353
-rw-r--r--core/java/android/bluetooth/BluetoothIntent.java128
-rw-r--r--core/java/android/bluetooth/Database.java200
-rw-r--r--core/java/android/bluetooth/HeadsetBase.java285
-rw-r--r--core/java/android/bluetooth/IBluetoothA2dp.aidl31
-rw-r--r--core/java/android/bluetooth/IBluetoothDevice.aidl77
-rw-r--r--core/java/android/bluetooth/IBluetoothDeviceCallback.aidl27
-rw-r--r--core/java/android/bluetooth/IBluetoothHeadset.aidl34
-rw-r--r--core/java/android/bluetooth/RfcommSocket.java674
-rw-r--r--core/java/android/bluetooth/ScoSocket.java194
-rw-r--r--core/java/android/bluetooth/package.html13
-rw-r--r--core/java/android/content/AbstractSyncableContentProvider.java601
-rw-r--r--core/java/android/content/AbstractTableMerger.java582
-rw-r--r--core/java/android/content/ActivityNotFoundException.java35
-rw-r--r--core/java/android/content/AsyncQueryHandler.java360
-rw-r--r--core/java/android/content/BroadcastReceiver.java425
-rw-r--r--core/java/android/content/ComponentCallbacks.java54
-rw-r--r--core/java/android/content/ComponentName.aidl19
-rw-r--r--core/java/android/content/ComponentName.java276
-rw-r--r--core/java/android/content/ContentInsertHandler.java50
-rw-r--r--core/java/android/content/ContentProvider.java562
-rw-r--r--core/java/android/content/ContentProviderNative.java435
-rw-r--r--core/java/android/content/ContentQueryMap.java172
-rw-r--r--core/java/android/content/ContentResolver.java644
-rw-r--r--core/java/android/content/ContentService.java376
-rw-r--r--core/java/android/content/ContentServiceNative.java209
-rw-r--r--core/java/android/content/ContentUris.java67
-rw-r--r--core/java/android/content/ContentValues.java501
-rw-r--r--core/java/android/content/Context.java1654
-rw-r--r--core/java/android/content/ContextWrapper.java422
-rw-r--r--core/java/android/content/DefaultDataHandler.java262
-rw-r--r--core/java/android/content/DialogInterface.java144
-rw-r--r--core/java/android/content/IContentProvider.java68
-rw-r--r--core/java/android/content/IContentService.java53
-rw-r--r--core/java/android/content/ISyncAdapter.aidl43
-rw-r--r--core/java/android/content/ISyncContext.aidl38
-rw-r--r--core/java/android/content/Intent.aidl20
-rw-r--r--core/java/android/content/Intent.java4522
-rw-r--r--core/java/android/content/IntentFilter.aidl19
-rw-r--r--core/java/android/content/IntentFilter.java1408
-rw-r--r--core/java/android/content/MutableContextWrapper.java38
-rw-r--r--core/java/android/content/ReceiverCallNotAllowedException.java32
-rw-r--r--core/java/android/content/SearchRecentSuggestionsProvider.java385
-rw-r--r--core/java/android/content/ServiceConnection.java53
-rw-r--r--core/java/android/content/SharedPreferences.java282
-rw-r--r--core/java/android/content/SyncAdapter.java70
-rw-r--r--core/java/android/content/SyncContext.java73
-rw-r--r--core/java/android/content/SyncManager.java2175
-rw-r--r--core/java/android/content/SyncProvider.java53
-rw-r--r--core/java/android/content/SyncResult.aidl19
-rw-r--r--core/java/android/content/SyncResult.java178
-rw-r--r--core/java/android/content/SyncStateContentProviderHelper.java234
-rw-r--r--core/java/android/content/SyncStats.aidl19
-rw-r--r--core/java/android/content/SyncStats.java112
-rw-r--r--core/java/android/content/SyncStorageEngine.java758
-rw-r--r--core/java/android/content/SyncUIContext.java37
-rw-r--r--core/java/android/content/SyncableContentProvider.java228
-rw-r--r--core/java/android/content/TempProviderSyncAdapter.java550
-rw-r--r--core/java/android/content/TempProviderSyncResult.java36
-rw-r--r--core/java/android/content/UriMatcher.java262
-rw-r--r--core/java/android/content/package.html650
-rwxr-xr-xcore/java/android/content/pm/ActivityInfo.aidl20
-rw-r--r--core/java/android/content/pm/ActivityInfo.java353
-rwxr-xr-xcore/java/android/content/pm/ApplicationInfo.aidl20
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java310
-rw-r--r--core/java/android/content/pm/ComponentInfo.java138
-rwxr-xr-xcore/java/android/content/pm/ConfigurationInfo.java119
-rwxr-xr-xcore/java/android/content/pm/IPackageDataObserver.aidl28
-rw-r--r--core/java/android/content/pm/IPackageDeleteObserver.aidl28
-rw-r--r--core/java/android/content/pm/IPackageInstallObserver.aidl27
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl269
-rwxr-xr-xcore/java/android/content/pm/IPackageStatsObserver.aidl30
-rwxr-xr-xcore/java/android/content/pm/InstrumentationInfo.aidl20
-rw-r--r--core/java/android/content/pm/InstrumentationInfo.java98
-rwxr-xr-xcore/java/android/content/pm/PackageInfo.aidl20
-rw-r--r--core/java/android/content/pm/PackageInfo.java199
-rw-r--r--core/java/android/content/pm/PackageItemInfo.java191
-rw-r--r--core/java/android/content/pm/PackageManager.java1626
-rw-r--r--core/java/android/content/pm/PackageParser.java2352
-rwxr-xr-xcore/java/android/content/pm/PackageStats.aidl20
-rwxr-xr-xcore/java/android/content/pm/PackageStats.java63
-rwxr-xr-xcore/java/android/content/pm/PermissionGroupInfo.aidl20
-rw-r--r--core/java/android/content/pm/PermissionGroupInfo.java108
-rwxr-xr-xcore/java/android/content/pm/PermissionInfo.aidl20
-rw-r--r--core/java/android/content/pm/PermissionInfo.java156
-rwxr-xr-xcore/java/android/content/pm/ProviderInfo.aidl20
-rw-r--r--core/java/android/content/pm/ProviderInfo.java129
-rwxr-xr-xcore/java/android/content/pm/ResolveInfo.aidl20
-rw-r--r--core/java/android/content/pm/ResolveInfo.java280
-rwxr-xr-xcore/java/android/content/pm/ServiceInfo.aidl20
-rw-r--r--core/java/android/content/pm/ServiceInfo.java56
-rwxr-xr-xcore/java/android/content/pm/Signature.aidl20
-rw-r--r--core/java/android/content/pm/Signature.java158
-rw-r--r--core/java/android/content/pm/package.html7
-rw-r--r--core/java/android/content/res/AssetFileDescriptor.java81
-rw-r--r--core/java/android/content/res/AssetManager.java697
-rw-r--r--core/java/android/content/res/ColorStateList.java332
-rwxr-xr-xcore/java/android/content/res/Configuration.aidl21
-rw-r--r--core/java/android/content/res/Configuration.java436
-rw-r--r--core/java/android/content/res/PluralRules.java111
-rw-r--r--core/java/android/content/res/Resources.java1850
-rw-r--r--core/java/android/content/res/StringBlock.java345
-rw-r--r--core/java/android/content/res/TypedArray.java660
-rw-r--r--core/java/android/content/res/XmlBlock.java515
-rw-r--r--core/java/android/content/res/XmlResourceParser.java36
-rw-r--r--core/java/android/content/res/package.html8
-rw-r--r--core/java/android/database/AbstractCursor.java636
-rw-r--r--core/java/android/database/AbstractWindowedCursor.java204
-rw-r--r--core/java/android/database/BulkCursorNative.java440
-rw-r--r--core/java/android/database/BulkCursorToCursorAdaptor.java256
-rw-r--r--core/java/android/database/CharArrayBuffer.java33
-rw-r--r--core/java/android/database/ContentObservable.java56
-rw-r--r--core/java/android/database/ContentObserver.java138
-rw-r--r--core/java/android/database/CrossProcessCursor.java42
-rw-r--r--core/java/android/database/Cursor.java587
-rw-r--r--core/java/android/database/CursorIndexOutOfBoundsException.java31
-rw-r--r--core/java/android/database/CursorJoiner.java265
-rw-r--r--core/java/android/database/CursorToBulkCursorAdaptor.java233
-rw-r--r--core/java/android/database/CursorWindow.java483
-rw-r--r--core/java/android/database/CursorWrapper.java305
-rw-r--r--core/java/android/database/DataSetObservable.java47
-rw-r--r--core/java/android/database/DataSetObserver.java41
-rw-r--r--core/java/android/database/DatabaseUtils.java1018
-rw-r--r--core/java/android/database/IBulkCursor.java90
-rwxr-xr-xcore/java/android/database/IContentObserver.aidl31
-rw-r--r--core/java/android/database/MatrixCursor.java267
-rw-r--r--core/java/android/database/MergeCursor.java257
-rw-r--r--core/java/android/database/Observable.java78
-rw-r--r--core/java/android/database/SQLException.java30
-rw-r--r--core/java/android/database/StaleDataException.java34
-rw-r--r--core/java/android/database/package.html14
-rw-r--r--core/java/android/database/sqlite/SQLiteAbortException.java30
-rw-r--r--core/java/android/database/sqlite/SQLiteClosable.java55
-rw-r--r--core/java/android/database/sqlite/SQLiteConstraintException.java28
-rw-r--r--core/java/android/database/sqlite/SQLiteCursor.java606
-rw-r--r--core/java/android/database/sqlite/SQLiteCursorDriver.java58
-rw-r--r--core/java/android/database/sqlite/SQLiteDatabase.java1675
-rw-r--r--core/java/android/database/sqlite/SQLiteDatabaseCorruptException.java28
-rw-r--r--core/java/android/database/sqlite/SQLiteDebug.java107
-rw-r--r--core/java/android/database/sqlite/SQLiteDirectCursorDriver.java97
-rw-r--r--core/java/android/database/sqlite/SQLiteDiskIOException.java29
-rw-r--r--core/java/android/database/sqlite/SQLiteDoneException.java31
-rw-r--r--core/java/android/database/sqlite/SQLiteException.java30
-rw-r--r--core/java/android/database/sqlite/SQLiteFullException.java28
-rw-r--r--core/java/android/database/sqlite/SQLiteMisuseException.java25
-rw-r--r--core/java/android/database/sqlite/SQLiteOpenHelper.java229
-rw-r--r--core/java/android/database/sqlite/SQLiteProgram.java264
-rw-r--r--core/java/android/database/sqlite/SQLiteQuery.java194
-rw-r--r--core/java/android/database/sqlite/SQLiteQueryBuilder.java520
-rw-r--r--core/java/android/database/sqlite/SQLiteStatement.java146
-rw-r--r--core/java/android/database/sqlite/package.html20
-rw-r--r--core/java/android/ddm/DdmHandleAppName.java104
-rw-r--r--core/java/android/ddm/DdmHandleExit.java78
-rw-r--r--core/java/android/ddm/DdmHandleHeap.java194
-rw-r--r--core/java/android/ddm/DdmHandleHello.java138
-rw-r--r--core/java/android/ddm/DdmHandleNativeHeap.java92
-rw-r--r--core/java/android/ddm/DdmHandleThread.java182
-rw-r--r--core/java/android/ddm/DdmRegister.java58
-rw-r--r--core/java/android/ddm/README.txt6
-rwxr-xr-xcore/java/android/ddm/package.html5
-rw-r--r--core/java/android/debug/JNITest.java48
-rwxr-xr-xcore/java/android/debug/package.html5
-rw-r--r--core/java/android/gadget/GadgetHost.java241
-rw-r--r--core/java/android/gadget/GadgetHostView.java275
-rw-r--r--core/java/android/gadget/GadgetManager.java304
-rwxr-xr-xcore/java/android/gadget/GadgetProvider.java154
-rw-r--r--core/java/android/gadget/GadgetProviderInfo.aidl19
-rw-r--r--core/java/android/gadget/GadgetProviderInfo.java168
-rw-r--r--core/java/android/gadget/package.html136
-rw-r--r--core/java/android/hardware/Camera.java782
-rw-r--r--core/java/android/hardware/GeomagneticField.java409
-rw-r--r--core/java/android/hardware/ISensorService.aidl29
-rw-r--r--core/java/android/hardware/Sensor.java146
-rw-r--r--core/java/android/hardware/SensorEvent.java146
-rw-r--r--core/java/android/hardware/SensorEventListener.java49
-rw-r--r--core/java/android/hardware/SensorListener.java102
-rw-r--r--core/java/android/hardware/SensorManager.java1462
-rw-r--r--core/java/android/hardware/package.html5
-rw-r--r--core/java/android/inputmethodservice/AbstractInputMethodService.java180
-rw-r--r--core/java/android/inputmethodservice/ExtractEditText.java123
-rw-r--r--core/java/android/inputmethodservice/IInputMethodSessionWrapper.java152
-rw-r--r--core/java/android/inputmethodservice/IInputMethodWrapper.java236
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java1636
-rwxr-xr-xcore/java/android/inputmethodservice/Keyboard.java815
-rwxr-xr-xcore/java/android/inputmethodservice/KeyboardView.java1154
-rw-r--r--core/java/android/inputmethodservice/SoftInputWindow.java155
-rw-r--r--core/java/android/inputmethodservice/package.html8
-rw-r--r--core/java/android/net/ConnectivityManager.java294
-rw-r--r--core/java/android/net/Credentials.java48
-rw-r--r--core/java/android/net/DhcpInfo.aidl19
-rw-r--r--core/java/android/net/DhcpInfo.java96
-rw-r--r--core/java/android/net/IConnectivityManager.aidl51
-rw-r--r--core/java/android/net/LocalServerSocket.java117
-rw-r--r--core/java/android/net/LocalSocket.java288
-rw-r--r--core/java/android/net/LocalSocketAddress.java100
-rw-r--r--core/java/android/net/LocalSocketImpl.java490
-rw-r--r--core/java/android/net/MailTo.java172
-rw-r--r--core/java/android/net/MobileDataStateTracker.java493
-rw-r--r--core/java/android/net/NetworkConnectivityListener.java220
-rw-r--r--core/java/android/net/NetworkInfo.aidl19
-rw-r--r--core/java/android/net/NetworkInfo.java380
-rw-r--r--core/java/android/net/NetworkStateTracker.java348
-rw-r--r--core/java/android/net/NetworkUtils.java128
-rw-r--r--core/java/android/net/ParseException.java30
-rw-r--r--core/java/android/net/Proxy.java120
-rw-r--r--core/java/android/net/SSLCertificateSocketFactory.java254
-rw-r--r--core/java/android/net/SntpClient.java201
-rwxr-xr-xcore/java/android/net/Uri.aidl19
-rw-r--r--core/java/android/net/Uri.java2252
-rw-r--r--core/java/android/net/UrlQuerySanitizer.java913
-rw-r--r--core/java/android/net/WebAddress.java134
-rw-r--r--core/java/android/net/http/AndroidHttpClient.java463
-rw-r--r--core/java/android/net/http/AndroidHttpClientConnection.java464
-rw-r--r--core/java/android/net/http/CertificateChainValidator.java444
-rw-r--r--core/java/android/net/http/CertificateValidatorCache.java254
-rw-r--r--core/java/android/net/http/CharArrayBuffers.java89
-rw-r--r--core/java/android/net/http/Connection.java528
-rw-r--r--core/java/android/net/http/ConnectionThread.java137
-rw-r--r--core/java/android/net/http/DomainNameChecker.java277
-rw-r--r--core/java/android/net/http/EventHandler.java147
-rw-r--r--core/java/android/net/http/Headers.java447
-rw-r--r--core/java/android/net/http/HttpAuthHeader.java422
-rw-r--r--core/java/android/net/http/HttpConnection.java96
-rw-r--r--core/java/android/net/http/HttpLog.java44
-rw-r--r--core/java/android/net/http/HttpsConnection.java427
-rw-r--r--core/java/android/net/http/IdleCache.java175
-rw-r--r--core/java/android/net/http/LoggingEventHandler.java90
-rw-r--r--core/java/android/net/http/Request.java462
-rw-r--r--core/java/android/net/http/RequestFeeder.java42
-rw-r--r--core/java/android/net/http/RequestHandle.java424
-rw-r--r--core/java/android/net/http/RequestQueue.java647
-rw-r--r--core/java/android/net/http/SslCertificate.java251
-rw-r--r--core/java/android/net/http/SslError.java144
-rw-r--r--core/java/android/net/http/Timer.java41
-rwxr-xr-xcore/java/android/net/http/package.html2
-rwxr-xr-xcore/java/android/net/package.html5
-rw-r--r--core/java/android/os/AsyncResult.java68
-rw-r--r--core/java/android/os/AsyncTask.java454
-rw-r--r--core/java/android/os/BadParcelableException.java31
-rw-r--r--core/java/android/os/Base64Utils.java31
-rw-r--r--core/java/android/os/BatteryManager.java46
-rw-r--r--core/java/android/os/BatteryStats.java795
-rw-r--r--core/java/android/os/Binder.java355
-rw-r--r--core/java/android/os/Broadcaster.java212
-rw-r--r--core/java/android/os/Build.java92
-rw-r--r--core/java/android/os/Bundle.aidl20
-rw-r--r--core/java/android/os/Bundle.java1452
-rw-r--r--core/java/android/os/ConditionVariable.java141
-rw-r--r--core/java/android/os/CountDownTimer.java138
-rw-r--r--core/java/android/os/DeadObjectException.java28
-rw-r--r--core/java/android/os/Debug.java717
-rw-r--r--core/java/android/os/Environment.java131
-rw-r--r--core/java/android/os/Exec.java63
-rw-r--r--core/java/android/os/FileObserver.java146
-rw-r--r--core/java/android/os/FileUtils.java197
-rw-r--r--core/java/android/os/Handler.java594
-rw-r--r--core/java/android/os/HandlerState.java33
-rw-r--r--core/java/android/os/HandlerStateMachine.java290
-rw-r--r--core/java/android/os/HandlerThread.java93
-rw-r--r--core/java/android/os/Hardware.java42
-rw-r--r--core/java/android/os/IBinder.java223
-rw-r--r--core/java/android/os/ICheckinService.aidl53
-rwxr-xr-xcore/java/android/os/IHardwareService.aidl40
-rw-r--r--core/java/android/os/IInterface.java31
-rw-r--r--core/java/android/os/IMessenger.aidl25
-rw-r--r--core/java/android/os/IMountService.aidl66
-rw-r--r--core/java/android/os/INetStatService.aidl35
-rw-r--r--core/java/android/os/IParentalControlCallback.aidl27
-rw-r--r--core/java/android/os/IPermissionController.aidl23
-rw-r--r--core/java/android/os/IPowerManager.aidl33
-rw-r--r--core/java/android/os/IServiceManager.java70
-rw-r--r--core/java/android/os/LocalPowerManager.java42
-rw-r--r--core/java/android/os/Looper.java226
-rw-r--r--core/java/android/os/MailboxNotAvailableException.java37
-rw-r--r--core/java/android/os/MemoryFile.java258
-rw-r--r--core/java/android/os/Message.aidl20
-rw-r--r--core/java/android/os/Message.java405
-rw-r--r--core/java/android/os/MessageQueue.java329
-rw-r--r--core/java/android/os/Messenger.aidl20
-rw-r--r--core/java/android/os/Messenger.java141
-rw-r--r--core/java/android/os/NetStat.java212
-rw-r--r--core/java/android/os/Parcel.java2051
-rw-r--r--core/java/android/os/ParcelFileDescriptor.aidl20
-rw-r--r--core/java/android/os/ParcelFileDescriptor.java250
-rw-r--r--core/java/android/os/ParcelFormatException.java31
-rw-r--r--core/java/android/os/Parcelable.java112
-rw-r--r--core/java/android/os/PatternMatcher.aidl19
-rw-r--r--core/java/android/os/PatternMatcher.java197
-rw-r--r--core/java/android/os/Power.java130
-rw-r--r--core/java/android/os/PowerManager.java392
-rw-r--r--core/java/android/os/Process.java706
-rw-r--r--core/java/android/os/Registrant.java124
-rw-r--r--core/java/android/os/RegistrantList.java128
-rw-r--r--core/java/android/os/RemoteCallbackList.java259
-rw-r--r--core/java/android/os/RemoteException.java27
-rw-r--r--core/java/android/os/RemoteMailException.java31
-rw-r--r--core/java/android/os/ServiceManager.java122
-rw-r--r--core/java/android/os/ServiceManagerNative.java174
-rw-r--r--core/java/android/os/StatFs.java74
-rw-r--r--core/java/android/os/SystemClock.java154
-rw-r--r--core/java/android/os/SystemProperties.java143
-rw-r--r--core/java/android/os/SystemService.java31
-rwxr-xr-xcore/java/android/os/TokenWatcher.java197
-rw-r--r--core/java/android/os/UEventObserver.java191
-rw-r--r--core/java/android/os/Vibrator.java86
-rw-r--r--core/java/android/os/package.html6
-rw-r--r--core/java/android/package.html10
-rw-r--r--core/java/android/pim/ContactsAsyncHelper.java336
-rw-r--r--core/java/android/pim/DateException.java26
-rw-r--r--core/java/android/pim/EventRecurrence.java421
-rw-r--r--core/java/android/pim/ICalendar.java643
-rw-r--r--core/java/android/pim/RecurrenceSet.java398
-rw-r--r--core/java/android/pim/package.html7
-rw-r--r--core/java/android/preference/CheckBoxPreference.java295
-rw-r--r--core/java/android/preference/DialogPreference.java454
-rw-r--r--core/java/android/preference/EditTextPreference.java228
-rw-r--r--core/java/android/preference/GenericInflater.java520
-rw-r--r--core/java/android/preference/ListPreference.java291
-rw-r--r--core/java/android/preference/OnDependencyChangeListener.java32
-rw-r--r--core/java/android/preference/Preference.java1586
-rw-r--r--core/java/android/preference/PreferenceActivity.java287
-rw-r--r--core/java/android/preference/PreferenceCategory.java58
-rw-r--r--core/java/android/preference/PreferenceGroup.java324
-rw-r--r--core/java/android/preference/PreferenceGroupAdapter.java248
-rw-r--r--core/java/android/preference/PreferenceInflater.java103
-rw-r--r--core/java/android/preference/PreferenceManager.java799
-rw-r--r--core/java/android/preference/PreferenceScreen.java252
-rw-r--r--core/java/android/preference/RingtonePreference.java242
-rw-r--r--core/java/android/preference/SeekBarPreference.java62
-rw-r--r--core/java/android/preference/VolumePreference.java219
-rw-r--r--core/java/android/preference/package.html23
-rw-r--r--core/java/android/provider/BaseColumns.java32
-rw-r--r--core/java/android/provider/Browser.java448
-rw-r--r--core/java/android/provider/Calendar.java1143
-rw-r--r--core/java/android/provider/CallLog.java190
-rw-r--r--core/java/android/provider/Checkin.java308
-rw-r--r--core/java/android/provider/Contacts.java1678
-rw-r--r--core/java/android/provider/Downloads.java513
-rw-r--r--core/java/android/provider/DrmStore.java185
-rw-r--r--core/java/android/provider/Gmail.java2453
-rw-r--r--core/java/android/provider/Im.java2047
-rw-r--r--core/java/android/provider/LiveFolders.java298
-rw-r--r--core/java/android/provider/MediaStore.java1396
-rw-r--r--core/java/android/provider/OpenableColumns.java37
-rw-r--r--core/java/android/provider/SearchRecentSuggestions.java229
-rw-r--r--core/java/android/provider/Settings.java3078
-rw-r--r--core/java/android/provider/SubscribedFeeds.java204
-rw-r--r--core/java/android/provider/Sync.java633
-rw-r--r--core/java/android/provider/SyncConstValue.java71
-rw-r--r--core/java/android/provider/Telephony.java1574
-rw-r--r--core/java/android/provider/UserDictionary.java138
-rw-r--r--core/java/android/provider/package.html11
-rw-r--r--core/java/android/security/Md5MessageDigest.java42
-rw-r--r--core/java/android/security/MessageDigest.java64
-rw-r--r--core/java/android/security/Sha1MessageDigest.java42
-rw-r--r--core/java/android/security/package.html6
-rw-r--r--core/java/android/server/BluetoothA2dpService.java412
-rw-r--r--core/java/android/server/BluetoothDeviceService.java1107
-rw-r--r--core/java/android/server/BluetoothEventLoop.java373
-rw-r--r--core/java/android/server/data/BuildData.java89
-rw-r--r--core/java/android/server/data/CrashData.java145
-rw-r--r--core/java/android/server/data/StackTraceElementData.java80
-rw-r--r--core/java/android/server/data/ThrowableData.java138
-rwxr-xr-xcore/java/android/server/data/package.html5
-rwxr-xr-xcore/java/android/server/package.html5
-rw-r--r--core/java/android/server/search/SearchManagerService.java156
-rw-r--r--core/java/android/server/search/SearchableInfo.aidl19
-rw-r--r--core/java/android/server/search/SearchableInfo.java850
-rw-r--r--core/java/android/server/search/package.html5
-rw-r--r--core/java/android/speech/RecognizerIntent.java157
-rw-r--r--core/java/android/speech/srec/MicrophoneInputStream.java110
-rw-r--r--core/java/android/speech/srec/Recognizer.java719
-rw-r--r--core/java/android/speech/srec/UlawEncoderInputStream.java186
-rw-r--r--core/java/android/speech/srec/WaveHeader.java274
-rw-r--r--core/java/android/speech/srec/package.html5
-rw-r--r--core/java/android/syncml/package.html6
-rw-r--r--core/java/android/syncml/pim/PropertyNode.java40
-rw-r--r--core/java/android/syncml/pim/VBuilder.java62
-rw-r--r--core/java/android/syncml/pim/VDataBuilder.java142
-rw-r--r--core/java/android/syncml/pim/VNode.java29
-rw-r--r--core/java/android/syncml/pim/VParser.java723
-rw-r--r--core/java/android/syncml/pim/package.html6
-rw-r--r--core/java/android/syncml/pim/vcalendar/CalendarStruct.java56
-rw-r--r--core/java/android/syncml/pim/vcalendar/VCalComposer.java189
-rw-r--r--core/java/android/syncml/pim/vcalendar/VCalException.java41
-rw-r--r--core/java/android/syncml/pim/vcalendar/VCalParser.java116
-rw-r--r--core/java/android/syncml/pim/vcalendar/VCalParser_V10.java1628
-rw-r--r--core/java/android/syncml/pim/vcalendar/VCalParser_V20.java186
-rw-r--r--core/java/android/syncml/pim/vcalendar/package.html6
-rw-r--r--core/java/android/syncml/pim/vcard/ContactStruct.java91
-rw-r--r--core/java/android/syncml/pim/vcard/VCardComposer.java350
-rw-r--r--core/java/android/syncml/pim/vcard/VCardException.java41
-rw-r--r--core/java/android/syncml/pim/vcard/VCardParser.java142
-rw-r--r--core/java/android/syncml/pim/vcard/VCardParser_V21.java970
-rw-r--r--core/java/android/syncml/pim/vcard/VCardParser_V30.java157
-rw-r--r--core/java/android/syncml/pim/vcard/package.html6
-rw-r--r--core/java/android/test/AndroidTestCase.java86
-rw-r--r--core/java/android/test/FlakyTest.java41
-rw-r--r--core/java/android/test/InstrumentationTestCase.java306
-rw-r--r--core/java/android/test/InstrumentationTestSuite.java74
-rw-r--r--core/java/android/test/PerformanceTestCase.java65
-rw-r--r--core/java/android/test/UiThreadTest.java33
-rw-r--r--core/java/android/test/package.html5
-rw-r--r--core/java/android/test/suitebuilder/annotation/LargeTest.java30
-rw-r--r--core/java/android/test/suitebuilder/annotation/MediumTest.java31
-rw-r--r--core/java/android/test/suitebuilder/annotation/SmallTest.java30
-rw-r--r--core/java/android/test/suitebuilder/annotation/Smoke.java34
-rw-r--r--core/java/android/test/suitebuilder/annotation/Suppress.java33
-rw-r--r--core/java/android/text/AlteredCharSequence.java127
-rw-r--r--core/java/android/text/AndroidCharacter.java45
-rw-r--r--core/java/android/text/Annotation.java60
-rw-r--r--core/java/android/text/AutoText.java246
-rw-r--r--core/java/android/text/BoringLayout.java388
-rw-r--r--core/java/android/text/ClipboardManager.java88
-rw-r--r--core/java/android/text/DynamicLayout.java503
-rw-r--r--core/java/android/text/Editable.java142
-rw-r--r--core/java/android/text/GetChars.java33
-rw-r--r--core/java/android/text/GraphicsOperations.java46
-rw-r--r--core/java/android/text/Html.java784
-rw-r--r--core/java/android/text/IClipboard.aidl42
-rw-r--r--core/java/android/text/InputFilter.java97
-rw-r--r--core/java/android/text/InputType.java254
-rw-r--r--core/java/android/text/Layout.java1747
-rw-r--r--core/java/android/text/LoginFilter.java219
-rw-r--r--core/java/android/text/NoCopySpan.java31
-rw-r--r--core/java/android/text/PackedIntVector.java368
-rw-r--r--core/java/android/text/PackedObjectVector.java188
-rw-r--r--core/java/android/text/ParcelableSpan.java31
-rw-r--r--core/java/android/text/Selection.java429
-rw-r--r--core/java/android/text/SpanWatcher.java42
-rw-r--r--core/java/android/text/Spannable.java70
-rw-r--r--core/java/android/text/SpannableString.java56
-rw-r--r--core/java/android/text/SpannableStringBuilder.java1140
-rw-r--r--core/java/android/text/SpannableStringInternal.java372
-rw-r--r--core/java/android/text/Spanned.java182
-rw-r--r--core/java/android/text/SpannedString.java48
-rw-r--r--core/java/android/text/StaticLayout.java1195
-rw-r--r--core/java/android/text/Styled.java298
-rw-r--r--core/java/android/text/TextPaint.java55
-rw-r--r--core/java/android/text/TextUtils.java1620
-rw-r--r--core/java/android/text/TextWatcher.java57
-rw-r--r--core/java/android/text/format/DateFormat.java585
-rw-r--r--core/java/android/text/format/DateUtils.java1581
-rw-r--r--core/java/android/text/format/Formatter.java83
-rw-r--r--core/java/android/text/format/Time.java757
-rw-r--r--core/java/android/text/method/ArrowKeyMovementMethod.java286
-rw-r--r--core/java/android/text/method/BaseKeyListener.java160
-rw-r--r--core/java/android/text/method/CharacterPickerDialog.java134
-rw-r--r--core/java/android/text/method/DateKeyListener.java58
-rw-r--r--core/java/android/text/method/DateTimeKeyListener.java58
-rw-r--r--core/java/android/text/method/DialerKeyListener.java113
-rw-r--r--core/java/android/text/method/DigitsKeyListener.java218
-rw-r--r--core/java/android/text/method/HideReturnsTransformationMethod.java59
-rw-r--r--core/java/android/text/method/KeyListener.java79
-rw-r--r--core/java/android/text/method/LinkMovementMethod.java256
-rw-r--r--core/java/android/text/method/MetaKeyKeyListener.java485
-rw-r--r--core/java/android/text/method/MovementMethod.java51
-rw-r--r--core/java/android/text/method/MultiTapKeyListener.java286
-rw-r--r--core/java/android/text/method/NumberKeyListener.java131
-rw-r--r--core/java/android/text/method/PasswordTransformationMethod.java264
-rw-r--r--core/java/android/text/method/QwertyKeyListener.java451
-rw-r--r--core/java/android/text/method/ReplacementTransformationMethod.java205
-rw-r--r--core/java/android/text/method/ScrollingMovementMethod.java240
-rw-r--r--core/java/android/text/method/SingleLineTransformationMethod.java62
-rw-r--r--core/java/android/text/method/TextKeyListener.java297
-rw-r--r--core/java/android/text/method/TimeKeyListener.java58
-rw-r--r--core/java/android/text/method/Touch.java156
-rw-r--r--core/java/android/text/method/TransformationMethod.java46
-rw-r--r--core/java/android/text/method/package.html21
-rw-r--r--core/java/android/text/package.html13
-rw-r--r--core/java/android/text/style/AbsoluteSizeSpan.java61
-rw-r--r--core/java/android/text/style/AlignmentSpan.java55
-rw-r--r--core/java/android/text/style/BackgroundColorSpan.java57
-rw-r--r--core/java/android/text/style/BulletSpan.java102
-rw-r--r--core/java/android/text/style/CharacterStyle.java87
-rw-r--r--core/java/android/text/style/ClickableSpan.java43
-rw-r--r--core/java/android/text/style/DrawableMarginSpan.java79
-rw-r--r--core/java/android/text/style/DynamicDrawableSpan.java128
-rw-r--r--core/java/android/text/style/ForegroundColorSpan.java57
-rw-r--r--core/java/android/text/style/IconMarginSpan.java73
-rw-r--r--core/java/android/text/style/ImageSpan.java144
-rw-r--r--core/java/android/text/style/LeadingMarginSpan.java78
-rw-r--r--core/java/android/text/style/LineBackgroundSpan.java30
-rw-r--r--core/java/android/text/style/LineHeightSpan.java29
-rw-r--r--core/java/android/text/style/MaskFilterSpan.java38
-rw-r--r--core/java/android/text/style/MetricAffectingSpan.java85
-rw-r--r--core/java/android/text/style/ParagraphStyle.java26
-rw-r--r--core/java/android/text/style/QuoteSpan.java81
-rw-r--r--core/java/android/text/style/RasterizerSpan.java38
-rw-r--r--core/java/android/text/style/RelativeSizeSpan.java61
-rw-r--r--core/java/android/text/style/ReplacementSpan.java43
-rw-r--r--core/java/android/text/style/ScaleXSpan.java61
-rw-r--r--core/java/android/text/style/StrikethroughSpan.java47
-rw-r--r--core/java/android/text/style/StyleSpan.java112
-rw-r--r--core/java/android/text/style/SubscriptSpan.java51
-rw-r--r--core/java/android/text/style/SuperscriptSpan.java51
-rw-r--r--core/java/android/text/style/TabStopSpan.java37
-rw-r--r--core/java/android/text/style/TextAppearanceSpan.java250
-rw-r--r--core/java/android/text/style/TypefaceSpan.java96
-rw-r--r--core/java/android/text/style/URLSpan.java61
-rw-r--r--core/java/android/text/style/UnderlineSpan.java47
-rw-r--r--core/java/android/text/style/UpdateAppearance.java10
-rw-r--r--core/java/android/text/style/UpdateLayout.java25
-rw-r--r--core/java/android/text/style/WrapTogetherSpan.java23
-rw-r--r--core/java/android/text/style/package.html10
-rw-r--r--core/java/android/text/util/Linkify.java541
-rw-r--r--core/java/android/text/util/Regex.java204
-rw-r--r--core/java/android/text/util/Rfc822Token.java172
-rw-r--r--core/java/android/text/util/Rfc822Tokenizer.java292
-rw-r--r--core/java/android/text/util/Rfc822Validator.java132
-rw-r--r--core/java/android/text/util/package.html6
-rw-r--r--core/java/android/util/AndroidException.java34
-rw-r--r--core/java/android/util/AndroidRuntimeException.java34
-rw-r--r--core/java/android/util/AttributeSet.java269
-rw-r--r--core/java/android/util/Config.java51
-rw-r--r--core/java/android/util/DayOfMonthCursor.java187
-rw-r--r--core/java/android/util/DebugUtils.java104
-rw-r--r--core/java/android/util/DisplayMetrics.java98
-rw-r--r--core/java/android/util/EventLog.java288
-rw-r--r--core/java/android/util/EventLogTags.java90
-rw-r--r--core/java/android/util/FloatMath.java74
-rw-r--r--core/java/android/util/Log.java247
-rw-r--r--core/java/android/util/LogPrinter.java47
-rw-r--r--core/java/android/util/MonthDisplayHelper.java213
-rw-r--r--core/java/android/util/PrintStreamPrinter.java40
-rw-r--r--core/java/android/util/PrintWriterPrinter.java40
-rw-r--r--core/java/android/util/Printer.java31
-rw-r--r--core/java/android/util/SparseArray.java340
-rw-r--r--core/java/android/util/SparseBooleanArray.java245
-rw-r--r--core/java/android/util/SparseIntArray.java251
-rw-r--r--core/java/android/util/StateSet.java178
-rw-r--r--core/java/android/util/StringBuilderPrinter.java42
-rw-r--r--core/java/android/util/TimeFormatException.java26
-rw-r--r--core/java/android/util/TimeUtils.java133
-rw-r--r--core/java/android/util/TimingLogger.java144
-rw-r--r--core/java/android/util/TypedValue.java492
-rw-r--r--core/java/android/util/Xml.java185
-rw-r--r--core/java/android/util/XmlPullAttributes.java146
-rw-r--r--core/java/android/util/package.html6
-rw-r--r--core/java/android/view/AbsSavedState.java89
-rw-r--r--core/java/android/view/ContextMenu.java91
-rw-r--r--core/java/android/view/ContextThemeWrapper.java103
-rw-r--r--core/java/android/view/Display.java121
-rw-r--r--core/java/android/view/FocusFinder.java480
-rw-r--r--core/java/android/view/FocusFinderHelper.java59
-rw-r--r--core/java/android/view/GestureDetector.java513
-rw-r--r--core/java/android/view/Gravity.java306
-rw-r--r--core/java/android/view/HapticFeedbackConstants.java45
-rw-r--r--core/java/android/view/IApplicationToken.aidl28
-rw-r--r--core/java/android/view/IOnKeyguardExitResult.aidl25
-rw-r--r--core/java/android/view/IRotationWatcher.aidl25
-rw-r--r--core/java/android/view/IWindow.aidl59
-rw-r--r--core/java/android/view/IWindowManager.aidl136
-rw-r--r--core/java/android/view/IWindowSession.aidl111
-rw-r--r--core/java/android/view/InflateException.java40
-rw-r--r--core/java/android/view/KeyCharacterMap.java545
-rw-r--r--core/java/android/view/KeyEvent.aidl20
-rw-r--r--core/java/android/view/KeyEvent.java880
-rw-r--r--core/java/android/view/LayoutInflater.java744
-rw-r--r--core/java/android/view/Menu.java441
-rw-r--r--core/java/android/view/MenuInflater.java325
-rw-r--r--core/java/android/view/MenuItem.java384
-rw-r--r--core/java/android/view/MotionEvent.aidl20
-rw-r--r--core/java/android/view/MotionEvent.java685
-rwxr-xr-xcore/java/android/view/OrientationEventListener.java174
-rw-r--r--core/java/android/view/OrientationListener.java110
-rw-r--r--core/java/android/view/RawInputEvent.java170
-rw-r--r--core/java/android/view/RemotableViewMethod.java35
-rw-r--r--core/java/android/view/SoundEffectConstants.java57
-rw-r--r--core/java/android/view/SubMenu.java103
-rw-r--r--core/java/android/view/Surface.aidl20
-rw-r--r--core/java/android/view/Surface.java298
-rw-r--r--core/java/android/view/SurfaceHolder.java284
-rw-r--r--core/java/android/view/SurfaceSession.java49
-rw-r--r--core/java/android/view/SurfaceView.java614
-rw-r--r--core/java/android/view/TouchDelegate.java153
-rw-r--r--core/java/android/view/VelocityTracker.java215
-rw-r--r--core/java/android/view/View.java8067
-rw-r--r--core/java/android/view/ViewConfiguration.java424
-rw-r--r--core/java/android/view/ViewDebug.java1128
-rw-r--r--core/java/android/view/ViewGroup.java3478
-rw-r--r--core/java/android/view/ViewManager.java27
-rw-r--r--core/java/android/view/ViewParent.java211
-rw-r--r--core/java/android/view/ViewRoot.java2845
-rw-r--r--core/java/android/view/ViewStub.java279
-rw-r--r--core/java/android/view/ViewTreeObserver.java613
-rw-r--r--core/java/android/view/VolumePanel.java410
-rw-r--r--core/java/android/view/Window.java1005
-rwxr-xr-xcore/java/android/view/WindowManager.aidl21
-rw-r--r--core/java/android/view/WindowManager.java959
-rw-r--r--core/java/android/view/WindowManagerImpl.java364
-rw-r--r--core/java/android/view/WindowManagerPolicy.java796
-rwxr-xr-xcore/java/android/view/WindowOrientationListener.java180
-rw-r--r--core/java/android/view/animation/AccelerateDecelerateInterpolator.java37
-rw-r--r--core/java/android/view/animation/AccelerateInterpolator.java62
-rw-r--r--core/java/android/view/animation/AlphaAnimation.java81
-rw-r--r--core/java/android/view/animation/Animation.java925
-rw-r--r--core/java/android/view/animation/AnimationSet.java472
-rw-r--r--core/java/android/view/animation/AnimationUtils.java329
-rw-r--r--core/java/android/view/animation/CycleInterpolator.java47
-rw-r--r--core/java/android/view/animation/DecelerateInterpolator.java61
-rw-r--r--core/java/android/view/animation/GridLayoutAnimationController.java424
-rw-r--r--core/java/android/view/animation/Interpolator.java39
-rw-r--r--core/java/android/view/animation/LayoutAnimationController.java435
-rw-r--r--core/java/android/view/animation/LinearInterpolator.java37
-rw-r--r--core/java/android/view/animation/RotateAnimation.java165
-rw-r--r--core/java/android/view/animation/ScaleAnimation.java186
-rw-r--r--core/java/android/view/animation/Transformation.java147
-rw-r--r--core/java/android/view/animation/TranslateAnimation.java171
-rwxr-xr-xcore/java/android/view/animation/package.html20
-rw-r--r--core/java/android/view/inputmethod/BaseInputConnection.java564
-rw-r--r--core/java/android/view/inputmethod/CompletionInfo.aidl19
-rw-r--r--core/java/android/view/inputmethod/CompletionInfo.java131
-rw-r--r--core/java/android/view/inputmethod/EditorInfo.aidl19
-rw-r--r--core/java/android/view/inputmethod/EditorInfo.java171
-rw-r--r--core/java/android/view/inputmethod/ExtractedText.aidl19
-rw-r--r--core/java/android/view/inputmethod/ExtractedText.java102
-rw-r--r--core/java/android/view/inputmethod/ExtractedTextRequest.aidl19
-rw-r--r--core/java/android/view/inputmethod/ExtractedTextRequest.java70
-rw-r--r--core/java/android/view/inputmethod/InputBinding.aidl19
-rw-r--r--core/java/android/view/inputmethod/InputBinding.java152
-rw-r--r--core/java/android/view/inputmethod/InputConnection.java306
-rw-r--r--core/java/android/view/inputmethod/InputMethod.java200
-rw-r--r--core/java/android/view/inputmethod/InputMethodInfo.aidl19
-rw-r--r--core/java/android/view/inputmethod/InputMethodInfo.java300
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java1185
-rw-r--r--core/java/android/view/inputmethod/InputMethodSession.java142
-rw-r--r--core/java/android/view/inputmethod/package.html12
-rw-r--r--core/java/android/view/package.html6
-rw-r--r--core/java/android/webkit/BrowserFrame.java786
-rw-r--r--core/java/android/webkit/ByteArrayBuilder.java142
-rw-r--r--core/java/android/webkit/CacheLoader.java65
-rw-r--r--core/java/android/webkit/CacheManager.java703
-rw-r--r--core/java/android/webkit/CallbackProxy.java1018
-rw-r--r--core/java/android/webkit/ContentLoader.java123
-rw-r--r--core/java/android/webkit/CookieManager.java934
-rw-r--r--core/java/android/webkit/CookieSyncManager.java205
-rw-r--r--core/java/android/webkit/DataLoader.java80
-rw-r--r--core/java/android/webkit/DateSorter.java124
-rw-r--r--core/java/android/webkit/DownloadListener.java33
-rw-r--r--core/java/android/webkit/FileLoader.java136
-rw-r--r--core/java/android/webkit/FrameLoader.java370
-rw-r--r--core/java/android/webkit/HttpAuthHandler.java186
-rw-r--r--core/java/android/webkit/HttpDateTime.java195
-rw-r--r--core/java/android/webkit/JWebCoreJavaBridge.java195
-rw-r--r--core/java/android/webkit/JsPromptResult.java52
-rw-r--r--core/java/android/webkit/JsResult.java82
-rw-r--r--core/java/android/webkit/LoadListener.java1499
-rw-r--r--core/java/android/webkit/MimeTypeMap.java503
-rw-r--r--core/java/android/webkit/Network.java349
-rw-r--r--core/java/android/webkit/PerfChecker.java49
-rw-r--r--core/java/android/webkit/Plugin.java126
-rw-r--r--core/java/android/webkit/PluginList.java83
-rw-r--r--core/java/android/webkit/SslErrorHandler.java255
-rw-r--r--core/java/android/webkit/StreamLoader.java199
-rw-r--r--core/java/android/webkit/TextDialog.java653
-rw-r--r--core/java/android/webkit/URLUtil.java363
-rw-r--r--core/java/android/webkit/UrlInterceptHandler.java34
-rw-r--r--core/java/android/webkit/UrlInterceptRegistry.java106
-rw-r--r--core/java/android/webkit/WebBackForwardList.java188
-rw-r--r--core/java/android/webkit/WebChromeClient.java160
-rw-r--r--core/java/android/webkit/WebHistoryItem.java179
-rw-r--r--core/java/android/webkit/WebIconDatabase.java251
-rw-r--r--core/java/android/webkit/WebSettings.java1112
-rw-r--r--core/java/android/webkit/WebSyncManager.java162
-rw-r--r--core/java/android/webkit/WebView.java5338
-rw-r--r--core/java/android/webkit/WebViewClient.java206
-rw-r--r--core/java/android/webkit/WebViewCore.java1672
-rw-r--r--core/java/android/webkit/WebViewDatabase.java967
-rw-r--r--core/java/android/webkit/gears/AndroidGpsLocationProvider.java156
-rw-r--r--core/java/android/webkit/gears/AndroidRadioDataProvider.java244
-rw-r--r--core/java/android/webkit/gears/AndroidWifiDataProvider.java136
-rw-r--r--core/java/android/webkit/gears/ApacheHttpRequestAndroid.java1122
-rw-r--r--core/java/android/webkit/gears/DesktopAndroid.java109
-rw-r--r--core/java/android/webkit/gears/NativeDialog.java142
-rw-r--r--core/java/android/webkit/gears/PluginSettings.java79
-rw-r--r--core/java/android/webkit/gears/UrlInterceptHandlerGears.java501
-rw-r--r--core/java/android/webkit/gears/VersionExtractor.java147
-rw-r--r--core/java/android/webkit/gears/ZipInflater.java200
-rw-r--r--core/java/android/webkit/gears/package.html3
-rw-r--r--core/java/android/webkit/package.html7
-rw-r--r--core/java/android/widget/AbsListView.java3425
-rw-r--r--core/java/android/widget/AbsSeekBar.java336
-rw-r--r--core/java/android/widget/AbsSpinner.java490
-rw-r--r--core/java/android/widget/AbsoluteLayout.java220
-rw-r--r--core/java/android/widget/Adapter.java149
-rw-r--r--core/java/android/widget/AdapterView.java1097
-rw-r--r--core/java/android/widget/AlphabetIndexer.java283
-rw-r--r--core/java/android/widget/AnalogClock.java243
-rwxr-xr-xcore/java/android/widget/AppSecurityPermissions.java504
-rw-r--r--core/java/android/widget/ArrayAdapter.java455
-rw-r--r--core/java/android/widget/AutoCompleteTextView.java1071
-rw-r--r--core/java/android/widget/BaseAdapter.java76
-rw-r--r--core/java/android/widget/BaseExpandableListAdapter.java106
-rw-r--r--core/java/android/widget/Button.java71
-rw-r--r--core/java/android/widget/CheckBox.java65
-rw-r--r--core/java/android/widget/Checkable.java42
-rw-r--r--core/java/android/widget/CheckedTextView.java198
-rw-r--r--core/java/android/widget/Chronometer.java271
-rw-r--r--core/java/android/widget/CompoundButton.java323
-rw-r--r--core/java/android/widget/CursorAdapter.java384
-rw-r--r--core/java/android/widget/CursorFilter.java70
-rw-r--r--core/java/android/widget/CursorTreeAdapter.java521
-rw-r--r--core/java/android/widget/DatePicker.java321
-rw-r--r--core/java/android/widget/DialerFilter.java431
-rw-r--r--core/java/android/widget/DigitalClock.java129
-rw-r--r--core/java/android/widget/DoubleDigitManager.java105
-rw-r--r--core/java/android/widget/EditText.java110
-rw-r--r--core/java/android/widget/ExpandableListAdapter.java210
-rw-r--r--core/java/android/widget/ExpandableListConnector.java1009
-rw-r--r--core/java/android/widget/ExpandableListPosition.java135
-rw-r--r--core/java/android/widget/ExpandableListView.java1094
-rw-r--r--core/java/android/widget/FastScroller.java482
-rw-r--r--core/java/android/widget/Filter.java302
-rw-r--r--core/java/android/widget/FilterQueryProvider.java42
-rw-r--r--core/java/android/widget/Filterable.java37
-rw-r--r--core/java/android/widget/FrameLayout.java450
-rw-r--r--core/java/android/widget/Gallery.java1408
-rw-r--r--core/java/android/widget/GridView.java1842
-rw-r--r--core/java/android/widget/HeaderViewListAdapter.java241
-rw-r--r--core/java/android/widget/HorizontalScrollView.java1197
-rw-r--r--core/java/android/widget/ImageButton.java59
-rw-r--r--core/java/android/widget/ImageSwitcher.java59
-rw-r--r--core/java/android/widget/ImageView.java891
-rw-r--r--core/java/android/widget/LinearLayout.java1318
-rw-r--r--core/java/android/widget/ListAdapter.java44
-rw-r--r--core/java/android/widget/ListView.java3274
-rw-r--r--core/java/android/widget/MediaController.java552
-rw-r--r--core/java/android/widget/MultiAutoCompleteTextView.java282
-rw-r--r--core/java/android/widget/PopupWindow.java1218
-rw-r--r--core/java/android/widget/ProgressBar.java918
-rw-r--r--core/java/android/widget/RadioButton.java72
-rw-r--r--core/java/android/widget/RadioGroup.java388
-rw-r--r--core/java/android/widget/RatingBar.java317
-rw-r--r--core/java/android/widget/RelativeLayout.java954
-rw-r--r--core/java/android/widget/RemoteViews.aidl19
-rw-r--r--core/java/android/widget/RemoteViews.java834
-rw-r--r--core/java/android/widget/ResourceCursorAdapter.java85
-rw-r--r--core/java/android/widget/ResourceCursorTreeAdapter.java109
-rw-r--r--core/java/android/widget/ScrollBarDrawable.java253
-rw-r--r--core/java/android/widget/ScrollView.java1232
-rw-r--r--core/java/android/widget/Scroller.java388
-rw-r--r--core/java/android/widget/SectionIndexer.java52
-rw-r--r--core/java/android/widget/SeekBar.java119
-rw-r--r--core/java/android/widget/SimpleAdapter.java393
-rw-r--r--core/java/android/widget/SimpleCursorAdapter.java416
-rw-r--r--core/java/android/widget/SimpleCursorTreeAdapter.java241
-rw-r--r--core/java/android/widget/SimpleExpandableListAdapter.java301
-rw-r--r--core/java/android/widget/SlidingDrawer.java938
-rw-r--r--core/java/android/widget/Spinner.java364
-rw-r--r--core/java/android/widget/SpinnerAdapter.java43
-rw-r--r--core/java/android/widget/TabHost.java632
-rw-r--r--core/java/android/widget/TabWidget.java289
-rw-r--r--core/java/android/widget/TableLayout.java751
-rw-r--r--core/java/android/widget/TableRow.java531
-rw-r--r--core/java/android/widget/TextSwitcher.java91
-rw-r--r--core/java/android/widget/TextView.java6507
-rw-r--r--core/java/android/widget/TimePicker.java360
-rw-r--r--core/java/android/widget/Toast.java399
-rw-r--r--core/java/android/widget/ToggleButton.java147
-rw-r--r--core/java/android/widget/TwoLineListItem.java90
-rw-r--r--core/java/android/widget/VideoView.java533
-rw-r--r--core/java/android/widget/ViewAnimator.java300
-rw-r--r--core/java/android/widget/ViewFlipper.java103
-rw-r--r--core/java/android/widget/ViewSwitcher.java135
-rw-r--r--core/java/android/widget/WrapperListAdapter.java32
-rw-r--r--core/java/android/widget/ZoomButton.java112
-rw-r--r--core/java/android/widget/ZoomControls.java112
-rw-r--r--core/java/android/widget/ZoomRing.java960
-rw-r--r--core/java/android/widget/ZoomRingController.java1100
-rw-r--r--core/java/android/widget/package.html32
-rw-r--r--core/java/com/android/internal/app/AlertActivity.java90
-rw-r--r--core/java/com/android/internal/app/AlertController.java888
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java33
-rw-r--r--core/java/com/android/internal/app/ExternalMediaFormatActivity.java114
-rw-r--r--core/java/com/android/internal/app/IBatteryStats.aidl34
-rwxr-xr-xcore/java/com/android/internal/app/IUsageStats.aidl27
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java382
-rw-r--r--core/java/com/android/internal/app/RingtonePickerActivity.java346
-rw-r--r--core/java/com/android/internal/app/UsbStorageActivity.java124
-rw-r--r--core/java/com/android/internal/app/UsbStorageStopActivity.java123
-rw-r--r--core/java/com/android/internal/app/package.html3
-rw-r--r--core/java/com/android/internal/database/ArrayListCursor.java171
-rw-r--r--core/java/com/android/internal/database/SortCursor.java313
-rw-r--r--core/java/com/android/internal/gadget/IGadgetHost.aidl28
-rw-r--r--core/java/com/android/internal/gadget/IGadgetService.aidl49
-rw-r--r--core/java/com/android/internal/gadget/package.html3
-rw-r--r--core/java/com/android/internal/http/multipart/ByteArrayPartSource.java86
-rw-r--r--core/java/com/android/internal/http/multipart/FilePart.java254
-rw-r--r--core/java/com/android/internal/http/multipart/FilePartSource.java131
-rw-r--r--core/java/com/android/internal/http/multipart/MultipartEntity.java230
-rw-r--r--core/java/com/android/internal/http/multipart/Part.java439
-rw-r--r--core/java/com/android/internal/http/multipart/PartBase.java150
-rw-r--r--core/java/com/android/internal/http/multipart/PartSource.java72
-rw-r--r--core/java/com/android/internal/http/multipart/StringPart.java150
-rw-r--r--core/java/com/android/internal/logging/AndroidConfig.java44
-rw-r--r--core/java/com/android/internal/logging/AndroidHandler.java150
-rw-r--r--core/java/com/android/internal/os/AndroidPrintStream.java49
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.aidl19
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java1983
-rw-r--r--core/java/com/android/internal/os/BinderInternal.java89
-rw-r--r--core/java/com/android/internal/os/HandlerCaller.java195
-rw-r--r--core/java/com/android/internal/os/LoggingPrintStream.java290
-rwxr-xr-xcore/java/com/android/internal/os/PkgUsageStats.aidl20
-rwxr-xr-xcore/java/com/android/internal/os/PkgUsageStats.java60
-rw-r--r--core/java/com/android/internal/os/RecoverySystem.java128
-rw-r--r--core/java/com/android/internal/os/RuntimeInit.java440
-rw-r--r--core/java/com/android/internal/os/ZygoteConnection.java834
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java759
-rw-r--r--core/java/com/android/internal/os/ZygoteSecurityException.java26
-rw-r--r--core/java/com/android/internal/package.html3
-rw-r--r--core/java/com/android/internal/policy/IPolicy.java36
-rw-r--r--core/java/com/android/internal/policy/PolicyManager.java68
-rw-r--r--core/java/com/android/internal/policy/package.html5
-rw-r--r--core/java/com/android/internal/preference/YesNoPreference.java151
-rw-r--r--core/java/com/android/internal/util/ArrayUtils.java136
-rw-r--r--core/java/com/android/internal/util/CharSequences.java131
-rw-r--r--core/java/com/android/internal/util/FastMath.java33
-rw-r--r--core/java/com/android/internal/util/FastXmlSerializer.java365
-rw-r--r--core/java/com/android/internal/util/HexDump.java164
-rw-r--r--core/java/com/android/internal/util/Objects.java49
-rw-r--r--core/java/com/android/internal/util/Predicate.java32
-rw-r--r--core/java/com/android/internal/util/Predicates.java125
-rw-r--r--core/java/com/android/internal/util/WithFramework.java58
-rw-r--r--core/java/com/android/internal/util/XmlUtils.java796
-rw-r--r--core/java/com/android/internal/view/IInputConnectionCallback.aidl31
-rw-r--r--core/java/com/android/internal/view/IInputConnectionWrapper.java388
-rw-r--r--core/java/com/android/internal/view/IInputContext.aidl66
-rw-r--r--core/java/com/android/internal/view/IInputContextCallback.aidl29
-rw-r--r--core/java/com/android/internal/view/IInputMethod.aidl54
-rw-r--r--core/java/com/android/internal/view/IInputMethodCallback.aidl34
-rw-r--r--core/java/com/android/internal/view/IInputMethodClient.aidl30
-rw-r--r--core/java/com/android/internal/view/IInputMethodManager.aidl54
-rw-r--r--core/java/com/android/internal/view/IInputMethodSession.aidl49
-rw-r--r--core/java/com/android/internal/view/InputBindResult.aidl19
-rw-r--r--core/java/com/android/internal/view/InputBindResult.java91
-rw-r--r--core/java/com/android/internal/view/InputConnectionWrapper.java342
-rw-r--r--core/java/com/android/internal/view/menu/ContextMenuBuilder.java96
-rw-r--r--core/java/com/android/internal/view/menu/ExpandedMenuView.java95
-rw-r--r--core/java/com/android/internal/view/menu/IconMenuItemView.java284
-rw-r--r--core/java/com/android/internal/view/menu/IconMenuView.java822
-rw-r--r--core/java/com/android/internal/view/menu/ListMenuItemView.java242
-rw-r--r--core/java/com/android/internal/view/menu/MenuBuilder.java1120
-rw-r--r--core/java/com/android/internal/view/menu/MenuDialogHelper.java122
-rw-r--r--core/java/com/android/internal/view/menu/MenuItemImpl.java625
-rw-r--r--core/java/com/android/internal/view/menu/MenuView.java133
-rw-r--r--core/java/com/android/internal/view/menu/SubMenuBuilder.java114
-rw-r--r--core/java/com/android/internal/view/package.html3
-rw-r--r--core/java/com/android/internal/widget/DialogTitle.java71
-rw-r--r--core/java/com/android/internal/widget/EditableInputConnection.java116
-rw-r--r--core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java66
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java359
-rw-r--r--core/java/com/android/internal/widget/LockPatternView.java1024
-rw-r--r--core/java/com/android/internal/widget/NumberPicker.java406
-rw-r--r--core/java/com/android/internal/widget/NumberPickerButton.java86
-rw-r--r--core/java/com/android/internal/widget/TextProgressBar.java178
-rw-r--r--core/java/com/android/internal/widget/VerticalTextSpinner.java467
-rw-r--r--core/java/com/android/server/ResettableTimeout.java132
-rw-r--r--core/java/com/google/android/collect/Lists.java64
-rw-r--r--core/java/com/google/android/collect/Maps.java33
-rw-r--r--core/java/com/google/android/collect/Sets.java84
-rw-r--r--core/java/com/google/android/gdata/client/AndroidGDataClient.java467
-rw-r--r--core/java/com/google/android/gdata/client/AndroidXmlParserFactory.java31
-rw-r--r--core/java/com/google/android/gdata/client/QueryParamsImpl.java100
-rw-r--r--core/java/com/google/android/mms/ContentType.java222
-rw-r--r--core/java/com/google/android/mms/InvalidHeaderValueException.java41
-rw-r--r--core/java/com/google/android/mms/MmsException.java60
-rwxr-xr-xcore/java/com/google/android/mms/package.html5
-rw-r--r--core/java/com/google/android/mms/pdu/AcknowledgeInd.java89
-rw-r--r--core/java/com/google/android/mms/pdu/Base64.java167
-rw-r--r--core/java/com/google/android/mms/pdu/CharacterSets.java172
-rw-r--r--core/java/com/google/android/mms/pdu/DeliveryInd.java138
-rw-r--r--core/java/com/google/android/mms/pdu/EncodedStringValue.java272
-rw-r--r--core/java/com/google/android/mms/pdu/GenericPdu.java92
-rw-r--r--core/java/com/google/android/mms/pdu/MultimediaMessagePdu.java150
-rw-r--r--core/java/com/google/android/mms/pdu/NotificationInd.java285
-rw-r--r--core/java/com/google/android/mms/pdu/NotifyRespInd.java114
-rw-r--r--core/java/com/google/android/mms/pdu/PduBody.java191
-rw-r--r--core/java/com/google/android/mms/pdu/PduComposer.java1163
-rw-r--r--core/java/com/google/android/mms/pdu/PduContentTypes.java110
-rw-r--r--core/java/com/google/android/mms/pdu/PduHeaders.java721
-rw-r--r--core/java/com/google/android/mms/pdu/PduParser.java1868
-rw-r--r--core/java/com/google/android/mms/pdu/PduPart.java402
-rw-r--r--core/java/com/google/android/mms/pdu/PduPersister.java1225
-rw-r--r--core/java/com/google/android/mms/pdu/QuotedPrintable.java68
-rw-r--r--core/java/com/google/android/mms/pdu/ReadOrigInd.java153
-rw-r--r--core/java/com/google/android/mms/pdu/ReadRecInd.java165
-rw-r--r--core/java/com/google/android/mms/pdu/RetrieveConf.java300
-rw-r--r--core/java/com/google/android/mms/pdu/SendConf.java117
-rw-r--r--core/java/com/google/android/mms/pdu/SendReq.java346
-rwxr-xr-xcore/java/com/google/android/mms/pdu/package.html5
-rw-r--r--core/java/com/google/android/mms/util/AbstractCache.java113
-rw-r--r--core/java/com/google/android/mms/util/PduCache.java243
-rw-r--r--core/java/com/google/android/mms/util/PduCacheEntry.java44
-rw-r--r--core/java/com/google/android/mms/util/SqliteWrapper.java120
-rwxr-xr-xcore/java/com/google/android/mms/util/package.html5
-rw-r--r--core/java/com/google/android/net/GoogleHttpClient.java314
-rw-r--r--core/java/com/google/android/net/NetworkStatsEntity.java85
-rw-r--r--core/java/com/google/android/net/ParentalControl.java73
-rw-r--r--core/java/com/google/android/net/ParentalControlState.aidl18
-rw-r--r--core/java/com/google/android/net/ParentalControlState.java56
-rw-r--r--core/java/com/google/android/net/UrlRules.java229
-rw-r--r--core/java/com/google/android/util/AbstractMessageParser.java1496
-rw-r--r--core/java/com/google/android/util/GoogleWebContentHelper.java270
-rw-r--r--core/java/com/google/android/util/Procedure.java28
-rw-r--r--core/java/com/google/android/util/SimplePullParser.java391
-rw-r--r--core/java/com/google/android/util/SmileyParser.java83
-rw-r--r--core/java/com/google/android/util/SmileyResources.java74
-rw-r--r--core/java/jarjar-rules.txt2
-rw-r--r--core/java/overview.html3
975 files changed, 0 insertions, 312106 deletions
diff --git a/core/java/android/accounts/AccountMonitor.java b/core/java/android/accounts/AccountMonitor.java
deleted file mode 100644
index f21385e..0000000
--- a/core/java/android/accounts/AccountMonitor.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.accounts;
-
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.ServiceConnection;
-import android.database.SQLException;
-import android.os.IBinder;
-import android.os.Process;
-import android.os.RemoteException;
-import android.util.Log;
-
-/**
- * A helper class that calls back on the provided
- * AccountMonitorListener with the set of current accounts both when
- * it gets created and whenever the set changes. It does this by
- * binding to the AccountsService and registering to receive the
- * intent broadcast when the set of accounts is changed. The
- * connection to the accounts service is only made when it needs to
- * fetch the current list of accounts (that is, when the
- * AccountMonitor is first created, and when the intent is received).
- */
-public class AccountMonitor extends BroadcastReceiver implements ServiceConnection {
- private final Context mContext;
- private final AccountMonitorListener mListener;
- private boolean mClosed = false;
- private int pending = 0;
-
- // This thread runs in the background and runs the code to update accounts
- // in the listener.
- private class AccountUpdater extends Thread {
- private IBinder mService;
-
- public AccountUpdater(IBinder service) {
- mService = service;
- }
-
- @Override
- public void run() {
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- IAccountsService accountsService = IAccountsService.Stub.asInterface(mService);
- String[] accounts = null;
- do {
- try {
- accounts = accountsService.getAccounts();
- } catch (RemoteException e) {
- // if the service was killed then the system will restart it and when it does we
- // will get another onServiceConnected, at which point we will do a notify.
- Log.w("AccountMonitor", "Remote exception when getting accounts", e);
- return;
- }
-
- synchronized (AccountMonitor.this) {
- --pending;
- if (pending == 0) {
- break;
- }
- }
- } while (true);
-
- mContext.unbindService(AccountMonitor.this);
-
- try {
- mListener.onAccountsUpdated(accounts);
- } catch (SQLException e) {
- // Better luck next time. If the problem was disk-full,
- // the STORAGE_OK intent will re-trigger the update.
- Log.e("AccountMonitor", "Can't update accounts", e);
- }
- }
- }
-
- /**
- * Initializes the AccountMonitor and initiates a bind to the
- * AccountsService to get the initial account list. For 1.0,
- * the "list" is always a single account.
- *
- * @param context the context we are running in
- * @param listener the user to notify when the account set changes
- */
- public AccountMonitor(Context context, AccountMonitorListener listener) {
- if (listener == null) {
- throw new IllegalArgumentException("listener is null");
- }
-
- mContext = context;
- mListener = listener;
-
- // Register a broadcast receiver to monitor account changes
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(AccountsServiceConstants.LOGIN_ACCOUNTS_CHANGED_ACTION);
- intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK); // To recover from disk-full.
- mContext.registerReceiver(this, intentFilter);
-
- // Send the listener the initial state now.
- notifyListener();
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- notifyListener();
- }
-
- public void onServiceConnected(ComponentName className, IBinder service) {
- // Create a background thread to update the accounts.
- new AccountUpdater(service).start();
- }
-
- public void onServiceDisconnected(ComponentName className) {
- }
-
- private synchronized void notifyListener() {
- if (pending == 0) {
- // initiate the bind
- if (!mContext.bindService(AccountsServiceConstants.SERVICE_INTENT,
- this, Context.BIND_AUTO_CREATE)) {
- // This is normal if GLS isn't part of this build.
- Log.w("AccountMonitor",
- "Couldn't connect to " +
- AccountsServiceConstants.SERVICE_INTENT +
- " (Missing service?)");
- }
- } else {
- // already bound. bindService will not trigger another
- // call to onServiceConnected, so instead we make sure
- // that the existing background thread will call
- // getAccounts() after this function returns, by
- // incrementing pending.
- //
- // Yes, this else clause contains only a comment.
- }
- ++pending;
- }
-
- /**
- * calls close()
- * @throws Throwable
- */
- @Override
- protected void finalize() throws Throwable {
- close();
- super.finalize();
- }
-
- /**
- * Unregisters the account receiver. Consecutive calls to this
- * method are harmless, but also do nothing. Once this call is
- * made no more notifications will occur.
- */
- public synchronized void close() {
- if (!mClosed) {
- mContext.unregisterReceiver(this);
- mClosed = true;
- }
- }
-}
diff --git a/core/java/android/accounts/AccountMonitorListener.java b/core/java/android/accounts/AccountMonitorListener.java
deleted file mode 100644
index d0bd9a9..0000000
--- a/core/java/android/accounts/AccountMonitorListener.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.accounts;
-
-/**
- * An interface that contains the callback used by the AccountMonitor
- */
-public interface AccountMonitorListener {
- /**
- * This invoked when the AccountMonitor starts up and whenever the account
- * set changes.
- * @param currentAccounts the current accounts
- */
- void onAccountsUpdated(String[] currentAccounts);
-}
diff --git a/core/java/android/accounts/AccountsServiceConstants.java b/core/java/android/accounts/AccountsServiceConstants.java
deleted file mode 100644
index b882e7b..0000000
--- a/core/java/android/accounts/AccountsServiceConstants.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.accounts;
-
-import android.content.Intent;
-
-/**
- * Miscellaneous constants used by the AccountsService and its
- * clients.
- */
-// TODO: These constants *could* come directly from the
-// IAccountsService interface, but that's not possible since the
-// aidl compiler doesn't let you define constants (yet.)
-public class AccountsServiceConstants {
- /** This class is never instantiated. */
- private AccountsServiceConstants() {
- }
-
- /**
- * Action sent as a broadcast Intent by the AccountsService
- * when accounts are added to and/or removed from the device's
- * database, or when the primary account is changed.
- */
- public static final String LOGIN_ACCOUNTS_CHANGED_ACTION =
- "android.accounts.LOGIN_ACCOUNTS_CHANGED";
-
- /**
- * Action sent as a broadcast Intent by the AccountsService
- * when it starts up and no accounts are available (so some should be added).
- */
- public static final String LOGIN_ACCOUNTS_MISSING_ACTION =
- "android.accounts.LOGIN_ACCOUNTS_MISSING";
-
- /**
- * Action on the intent used to bind to the IAccountsService interface. This
- * is used for services that have multiple interfaces (allowing
- * them to differentiate the interface intended, and return the proper
- * Binder.)
- */
- private static final String ACCOUNTS_SERVICE_ACTION = "android.accounts.IAccountsService";
-
- /*
- * The intent uses a component in addition to the action to ensure the actual
- * accounts service is bound to (a malicious third-party app could
- * theoretically have a service with the same action).
- */
- /** The intent used to bind to the accounts service. */
- public static final Intent SERVICE_INTENT =
- new Intent()
- .setClassName("com.google.android.googleapps",
- "com.google.android.googleapps.GoogleLoginService")
- .setAction(ACCOUNTS_SERVICE_ACTION);
-
- /**
- * Checks whether the intent is to bind to the accounts service.
- *
- * @param bindIntent The Intent used to bind to the service.
- * @return Whether the intent is to bind to the accounts service.
- */
- public static final boolean isForAccountsService(Intent bindIntent) {
- String otherAction = bindIntent.getAction();
- return otherAction != null && otherAction.equals(ACCOUNTS_SERVICE_ACTION);
- }
-}
diff --git a/core/java/android/accounts/IAccountsService.aidl b/core/java/android/accounts/IAccountsService.aidl
deleted file mode 100644
index dda513c..0000000
--- a/core/java/android/accounts/IAccountsService.aidl
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.accounts;
-
-/**
- * Central application service that allows querying the list of accounts.
- */
-interface IAccountsService {
- /**
- * Gets the list of Accounts the user has previously logged
- * in to. Accounts are of the form "username@domain".
- * <p>
- * This method will return an empty array if the device doesn't
- * know about any accounts (yet).
- *
- * @return The accounts. The array will be zero-length if the
- * AccountsService doesn't know about any accounts yet.
- */
- String[] getAccounts();
-
- /**
- * This is an interim solution for bypassing a forgotten gesture on the
- * unlock screen (it is hidden, please make sure it stays this way!). This
- * will be *removed* when the unlock screen design supports additional
- * authenticators.
- * <p>
- * The user will be presented with username and password fields that are
- * called as parameters to this method. If true is returned, the user is
- * able to define a new gesture and get back into the system. If false, the
- * user can try again.
- *
- * @param username The username entered.
- * @param password The password entered.
- * @return Whether to allow the user to bypass the lock screen and define a
- * new gesture.
- * @hide (The package is already hidden, but just in case someone
- * unhides that, this should not be revealed.)
- */
- boolean shouldUnlock(String username, String password);
-}
diff --git a/core/java/android/accounts/package.html b/core/java/android/accounts/package.html
deleted file mode 100755
index c9f96a6..0000000
--- a/core/java/android/accounts/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>
diff --git a/core/java/android/annotation/SdkConstant.java b/core/java/android/annotation/SdkConstant.java
deleted file mode 100644
index 6ac70f0..0000000
--- a/core/java/android/annotation/SdkConstant.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.annotation;
-
-import java.lang.annotation.Target;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Indicates a constant field value should be exported to be used in the SDK tools.
- * @hide
- */
-@Target({ ElementType.FIELD })
-@Retention(RetentionPolicy.SOURCE)
-public @interface SdkConstant {
- public static enum SdkConstantType {
- ACTIVITY_INTENT_ACTION, BROADCAST_INTENT_ACTION, SERVICE_ACTION, INTENT_CATEGORY;
- }
-
- SdkConstantType value();
-}
diff --git a/core/java/android/annotation/Widget.java b/core/java/android/annotation/Widget.java
deleted file mode 100644
index 6756cd7..0000000
--- a/core/java/android/annotation/Widget.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.annotation;
-
-import java.lang.annotation.Target;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Indicates a class is a widget usable by application developers to create UI.
- * <p>
- * This must be used in cases where:
- * <ul>
- * <li>The widget is not in the package <code>android.widget</code></li>
- * <li>The widget extends <code>android.view.ViewGroup</code></li>
- * </ul>
- * @hide
- */
-@Target({ ElementType.TYPE })
-@Retention(RetentionPolicy.SOURCE)
-public @interface Widget {
-}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
deleted file mode 100644
index 849a37d..0000000
--- a/core/java/android/app/Activity.java
+++ /dev/null
@@ -1,3598 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.ComponentCallbacks;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.media.AudioManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.Handler;
-import android.os.IBinder;
-import android.text.Selection;
-import android.text.SpannableStringBuilder;
-import android.text.method.TextKeyListener;
-import android.util.AttributeSet;
-import android.util.Config;
-import android.util.EventLog;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.ContextMenu;
-import android.view.ContextThemeWrapper;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewManager;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.View.OnCreateContextMenuListener;
-import android.widget.AdapterView;
-
-import com.android.internal.policy.PolicyManager;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-/**
- * An activity is a single, focused thing that the user can do. Almost all
- * activities interact with the user, so the Activity class takes care of
- * creating a window for you in which you can place your UI with
- * {@link #setContentView}. While activities are often presented to the user
- * as full-screen windows, they can also be used in other ways: as floating
- * windows (via a theme with {@link android.R.attr#windowIsFloating} set)
- * or embedded inside of another activity (using {@link ActivityGroup}).
- *
- * There are two methods almost all subclasses of Activity will implement:
- *
- * <ul>
- * <li> {@link #onCreate} is where you initialize your activity. Most
- * importantly, here you will usually call {@link #setContentView(int)}
- * with a layout resource defining your UI, and using {@link #findViewById}
- * to retrieve the widgets in that UI that you need to interact with
- * programmatically.
- *
- * <li> {@link #onPause} is where you deal with the user leaving your
- * activity. Most importantly, any changes made by the user should at this
- * point be committed (usually to the
- * {@link android.content.ContentProvider} holding the data).
- * </ul>
- *
- * <p>To be of use with {@link android.content.Context#startActivity Context.startActivity()}, all
- * activity classes must have a corresponding
- * {@link android.R.styleable#AndroidManifestActivity &lt;activity&gt;}
- * declaration in their package's <code>AndroidManifest.xml</code>.</p>
- *
- * <p>The Activity class is an important part of an application's overall lifecycle,
- * and the way activities are launched and put together is a fundamental
- * part of the platform's application model. For a detailed perspective on the structure of
- * Android applications and lifecycles, please read the <em>Dev Guide</em> document on
- * <a href="{@docRoot}guide/topics/fundamentals.html">Application Fundamentals</a>.</p>
- *
- * <p>Topics covered here:
- * <ol>
- * <li><a href="#ActivityLifecycle">Activity Lifecycle</a>
- * <li><a href="#ConfigurationChanges">Configuration Changes</a>
- * <li><a href="#StartingActivities">Starting Activities and Getting Results</a>
- * <li><a href="#SavingPersistentState">Saving Persistent State</a>
- * <li><a href="#Permissions">Permissions</a>
- * <li><a href="#ProcessLifecycle">Process Lifecycle</a>
- * </ol>
- *
- * <a name="ActivityLifecycle"></a>
- * <h3>Activity Lifecycle</h3>
- *
- * <p>Activities in the system are managed as an <em>activity stack</em>.
- * When a new activity is started, it is placed on the top of the stack
- * and becomes the running activity -- the previous activity always remains
- * below it in the stack, and will not come to the foreground again until
- * the new activity exits.</p>
- *
- * <p>An activity has essentially four states:</p>
- * <ul>
- * <li> If an activity in the foreground of the screen (at the top of
- * the stack),
- * it is <em>active</em> or <em>running</em>. </li>
- * <li>If an activity has lost focus but is still visible (that is, a new non-full-sized
- * or transparent activity has focus on top of your activity), it
- * is <em>paused</em>. A paused activity is completely alive (it
- * maintains all state and member information and remains attached to
- * the window manager), but can be killed by the system in extreme
- * low memory situations.
- * <li>If an activity is completely obscured by another activity,
- * it is <em>stopped</em>. It still retains all state and member information,
- * however, it is no longer visible to the user so its window is hidden
- * and it will often be killed by the system when memory is needed
- * elsewhere.</li>
- * <li>If an activity is paused or stopped, the system can drop the activity
- * from memory by either asking it to finish, or simply killing its
- * process. When it is displayed again to the user, it must be
- * completely restarted and restored to its previous state.</li>
- * </ul>
- *
- * <p>The following diagram shows the important state paths of an Activity.
- * The square rectangles represent callback methods you can implement to
- * perform operations when the Activity moves between states. The colored
- * ovals are major states the Activity can be in.</p>
- *
- * <p><img src="../../../images/activity_lifecycle.png"
- * alt="State diagram for an Android Activity Lifecycle." border="0" /></p>
- *
- * <p>There are three key loops you may be interested in monitoring within your
- * activity:
- *
- * <ul>
- * <li>The <b>entire lifetime</b> of an activity happens between the first call
- * to {@link android.app.Activity#onCreate} through to a single final call
- * to {@link android.app.Activity#onDestroy}. An activity will do all setup
- * of "global" state in onCreate(), and release all remaining resources in
- * onDestroy(). For example, if it has a thread running in the background
- * to download data from the network, it may create that thread in onCreate()
- * and then stop the thread in onDestroy().
- *
- * <li>The <b>visible lifetime</b> of an activity happens between a call to
- * {@link android.app.Activity#onStart} until a corresponding call to
- * {@link android.app.Activity#onStop}. During this time the user can see the
- * activity on-screen, though it may not be in the foreground and interacting
- * with the user. Between these two methods you can maintain resources that
- * are needed to show the activity to the user. For example, you can register
- * a {@link android.content.BroadcastReceiver} in onStart() to monitor for changes
- * that impact your UI, and unregister it in onStop() when the user an no
- * longer see what you are displaying. The onStart() and onStop() methods
- * can be called multiple times, as the activity becomes visible and hidden
- * to the user.
- *
- * <li>The <b>foreground lifetime</b> of an activity happens between a call to
- * {@link android.app.Activity#onResume} until a corresponding call to
- * {@link android.app.Activity#onPause}. During this time the activity is
- * in front of all other activities and interacting with the user. An activity
- * can frequently go between the resumed and paused states -- for example when
- * the device goes to sleep, when an activity result is delivered, when a new
- * intent is delivered -- so the code in these methods should be fairly
- * lightweight.
- * </ul>
- *
- * <p>The entire lifecycle of an activity is defined by the following
- * Activity methods. All of these are hooks that you can override
- * to do appropriate work when the activity changes state. All
- * activities will implement {@link android.app.Activity#onCreate}
- * to do their initial setup; many will also implement
- * {@link android.app.Activity#onPause} to commit changes to data and
- * otherwise prepare to stop interacting with the user. You should always
- * call up to your superclass when implementing these methods.</p>
- *
- * </p>
- * <pre class="prettyprint">
- * public class Activity extends ApplicationContext {
- * protected void onCreate(Bundle savedInstanceState);
- *
- * protected void onStart();
- *
- * protected void onRestart();
- *
- * protected void onResume();
- *
- * protected void onPause();
- *
- * protected void onStop();
- *
- * protected void onDestroy();
- * }
- * </pre>
- *
- * <p>In general the movement through an activity's lifecycle looks like
- * this:</p>
- *
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
- * <colgroup align="left" span="3" />
- * <colgroup align="left" />
- * <colgroup align="center" />
- * <colgroup align="center" />
- *
- * <thead>
- * <tr><th colspan="3">Method</th> <th>Description</th> <th>Killable?</th> <th>Next</th></tr>
- * </thead>
- *
- * <tbody>
- * <tr><th colspan="3" align="left" border="0">{@link android.app.Activity#onCreate onCreate()}</th>
- * <td>Called when the activity is first created.
- * This is where you should do all of your normal static set up:
- * create views, bind data to lists, etc. This method also
- * provides you with a Bundle containing the activity's previously
- * frozen state, if there was one.
- * <p>Always followed by <code>onStart()</code>.</td>
- * <td align="center">No</td>
- * <td align="center"><code>onStart()</code></td>
- * </tr>
- *
- * <tr><td rowspan="5" style="border-left: none; border-right: none;">&nbsp;&nbsp;&nbsp;&nbsp;</td>
- * <th colspan="2" align="left" border="0">{@link android.app.Activity#onRestart onRestart()}</th>
- * <td>Called after your activity has been stopped, prior to it being
- * started again.
- * <p>Always followed by <code>onStart()</code></td>
- * <td align="center">No</td>
- * <td align="center"><code>onStart()</code></td>
- * </tr>
- *
- * <tr><th colspan="2" align="left" border="0">{@link android.app.Activity#onStart onStart()}</th>
- * <td>Called when the activity is becoming visible to the user.
- * <p>Followed by <code>onResume()</code> if the activity comes
- * to the foreground, or <code>onStop()</code> if it becomes hidden.</td>
- * <td align="center">No</td>
- * <td align="center"><code>onResume()</code> or <code>onStop()</code></td>
- * </tr>
- *
- * <tr><td rowspan="2" style="border-left: none;">&nbsp;&nbsp;&nbsp;&nbsp;</td>
- * <th align="left" border="0">{@link android.app.Activity#onResume onResume()}</th>
- * <td>Called when the activity will start
- * interacting with the user. At this point your activity is at
- * the top of the activity stack, with user input going to it.
- * <p>Always followed by <code>onPause()</code>.</td>
- * <td align="center">No</td>
- * <td align="center"><code>onPause()</code></td>
- * </tr>
- *
- * <tr><th align="left" border="0">{@link android.app.Activity#onPause onPause()}</th>
- * <td>Called when the system is about to start resuming a previous
- * activity. This is typically used to commit unsaved changes to
- * persistent data, stop animations and other things that may be consuming
- * CPU, etc. Implementations of this method must be very quick because
- * the next activity will not be resumed until this method returns.
- * <p>Followed by either <code>onResume()</code> if the activity
- * returns back to the front, or <code>onStop()</code> if it becomes
- * invisible to the user.</td>
- * <td align="center"><font color="#800000"><strong>Yes</strong></font></td>
- * <td align="center"><code>onResume()</code> or<br>
- * <code>onStop()</code></td>
- * </tr>
- *
- * <tr><th colspan="2" align="left" border="0">{@link android.app.Activity#onStop onStop()}</th>
- * <td>Called when the activity is no longer visible to the user, because
- * another activity has been resumed and is covering this one. This
- * may happen either because a new activity is being started, an existing
- * one is being brought in front of this one, or this one is being
- * destroyed.
- * <p>Followed by either <code>onRestart()</code> if
- * this activity is coming back to interact with the user, or
- * <code>onDestroy()</code> if this activity is going away.</td>
- * <td align="center"><font color="#800000"><strong>Yes</strong></font></td>
- * <td align="center"><code>onRestart()</code> or<br>
- * <code>onDestroy()</code></td>
- * </tr>
- *
- * <tr><th colspan="3" align="left" border="0">{@link android.app.Activity#onDestroy onDestroy()}</th>
- * <td>The final call you receive before your
- * activity is destroyed. This can happen either because the
- * activity is finishing (someone called {@link Activity#finish} on
- * it, or because the system is temporarily destroying this
- * instance of the activity to save space. You can distinguish
- * between these two scenarios with the {@link
- * Activity#isFinishing} method.</td>
- * <td align="center"><font color="#800000"><strong>Yes</strong></font></td>
- * <td align="center"><em>nothing</em></td>
- * </tr>
- * </tbody>
- * </table>
- *
- * <p>Note the "Killable" column in the above table -- for those methods that
- * are marked as being killable, after that method returns the process hosting the
- * activity may killed by the system <em>at any time</em> without another line
- * of its code being executed. Because of this, you should use the
- * {@link #onPause} method to write any persistent data (such as user edits)
- * to storage. In addition, the method
- * {@link #onSaveInstanceState(Bundle)} is called before placing the activity
- * in such a background state, allowing you to save away any dynamic instance
- * state in your activity into the given Bundle, to be later received in
- * {@link #onCreate} if the activity needs to be re-created.
- * See the <a href="#ProcessLifecycle">Process Lifecycle</a>
- * section for more information on how the lifecycle of a process is tied
- * to the activities it is hosting. Note that it is important to save
- * persistent data in {@link #onPause} instead of {@link #onSaveInstanceState}
- * because the later is not part of the lifecycle callbacks, so will not
- * be called in every situation as described in its documentation.</p>
- *
- * <p>For those methods that are not marked as being killable, the activity's
- * process will not be killed by the system starting from the time the method
- * is called and continuing after it returns. Thus an activity is in the killable
- * state, for example, between after <code>onPause()</code> to the start of
- * <code>onResume()</code>.</p>
- *
- * <a name="ConfigurationChanges"></a>
- * <h3>Configuration Changes</h3>
- *
- * <p>If the configuration of the device (as defined by the
- * {@link Configuration Resources.Configuration} class) changes,
- * then anything displaying a user interface will need to update to match that
- * configuration. Because Activity is the primary mechanism for interacting
- * with the user, it includes special support for handling configuration
- * changes.</p>
- *
- * <p>Unless you specify otherwise, a configuration change (such as a change
- * in screen orientation, language, input devices, etc) will cause your
- * current activity to be <em>destroyed</em>, going through the normal activity
- * lifecycle process of {@link #onPause},
- * {@link #onStop}, and {@link #onDestroy} as appropriate. If the activity
- * had been in the foreground or visible to the user, once {@link #onDestroy} is
- * called in that instance then a new instance of the activity will be
- * created, with whatever savedInstanceState the previous instance had generated
- * from {@link #onSaveInstanceState}.</p>
- *
- * <p>This is done because any application resource,
- * including layout files, can change based on any configuration value. Thus
- * the only safe way to handle a configuration change is to re-retrieve all
- * resources, including layouts, drawables, and strings. Because activities
- * must already know how to save their state and re-create themselves from
- * that state, this is a convenient way to have an activity restart itself
- * with a new configuration.</p>
- *
- * <p>In some special cases, you may want to bypass restarting of your
- * activity based on one or more types of configuration changes. This is
- * done with the {@link android.R.attr#configChanges android:configChanges}
- * attribute in its manifest. For any types of configuration changes you say
- * that you handle there, you will receive a call to your current activity's
- * {@link #onConfigurationChanged} method instead of being restarted. If
- * a configuration change involves any that you do not handle, however, the
- * activity will still be restarted and {@link #onConfigurationChanged}
- * will not be called.</p>
- *
- * <a name="StartingActivities"></a>
- * <h3>Starting Activities and Getting Results</h3>
- *
- * <p>The {@link android.app.Activity#startActivity}
- * method is used to start a
- * new activity, which will be placed at the top of the activity stack. It
- * takes a single argument, an {@link android.content.Intent Intent},
- * which describes the activity
- * to be executed.</p>
- *
- * <p>Sometimes you want to get a result back from an activity when it
- * ends. For example, you may start an activity that lets the user pick
- * a person in a list of contacts; when it ends, it returns the person
- * that was selected. To do this, you call the
- * {@link android.app.Activity#startActivityForResult(Intent, int)}
- * version with a second integer parameter identifying the call. The result
- * will come back through your {@link android.app.Activity#onActivityResult}
- * method.</p>
- *
- * <p>When an activity exits, it can call
- * {@link android.app.Activity#setResult(int)}
- * to return data back to its parent. It must always supply a result code,
- * which can be the standard results RESULT_CANCELED, RESULT_OK, or any
- * custom values starting at RESULT_FIRST_USER. In addition, it can optionally
- * return back an Intent containing any additional data it wants. All of this
- * information appears back on the
- * parent's <code>Activity.onActivityResult()</code>, along with the integer
- * identifier it originally supplied.</p>
- *
- * <p>If a child activity fails for any reason (such as crashing), the parent
- * activity will receive a result with the code RESULT_CANCELED.</p>
- *
- * <pre class="prettyprint">
- * public class MyActivity extends Activity {
- * ...
- *
- * static final int PICK_CONTACT_REQUEST = 0;
- *
- * protected boolean onKeyDown(int keyCode, KeyEvent event) {
- * if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
- * // When the user center presses, let them pick a contact.
- * startActivityForResult(
- * new Intent(Intent.ACTION_PICK,
- * new Uri("content://contacts")),
- * PICK_CONTACT_REQUEST);
- * return true;
- * }
- * return false;
- * }
- *
- * protected void onActivityResult(int requestCode, int resultCode,
- * Intent data) {
- * if (requestCode == PICK_CONTACT_REQUEST) {
- * if (resultCode == RESULT_OK) {
- * // A contact was picked. Here we will just display it
- * // to the user.
- * startActivity(new Intent(Intent.ACTION_VIEW, data));
- * }
- * }
- * }
- * }
- * </pre>
- *
- * <a name="SavingPersistentState"></a>
- * <h3>Saving Persistent State</h3>
- *
- * <p>There are generally two kinds of persistent state than an activity
- * will deal with: shared document-like data (typically stored in a SQLite
- * database using a {@linkplain android.content.ContentProvider content provider})
- * and internal state such as user preferences.</p>
- *
- * <p>For content provider data, we suggest that activities use a
- * "edit in place" user model. That is, any edits a user makes are effectively
- * made immediately without requiring an additional confirmation step.
- * Supporting this model is generally a simple matter of following two rules:</p>
- *
- * <ul>
- * <li> <p>When creating a new document, the backing database entry or file for
- * it is created immediately. For example, if the user chooses to write
- * a new e-mail, a new entry for that e-mail is created as soon as they
- * start entering data, so that if they go to any other activity after
- * that point this e-mail will now appear in the list of drafts.</p>
- * <li> <p>When an activity's <code>onPause()</code> method is called, it should
- * commit to the backing content provider or file any changes the user
- * has made. This ensures that those changes will be seen by any other
- * activity that is about to run. You will probably want to commit
- * your data even more aggressively at key times during your
- * activity's lifecycle: for example before starting a new
- * activity, before finishing your own activity, when the user
- * switches between input fields, etc.</p>
- * </ul>
- *
- * <p>This model is designed to prevent data loss when a user is navigating
- * between activities, and allows the system to safely kill an activity (because
- * system resources are needed somewhere else) at any time after it has been
- * paused. Note this implies
- * that the user pressing BACK from your activity does <em>not</em>
- * mean "cancel" -- it means to leave the activity with its current contents
- * saved away. Cancelling edits in an activity must be provided through
- * some other mechanism, such as an explicit "revert" or "undo" option.</p>
- *
- * <p>See the {@linkplain android.content.ContentProvider content package} for
- * more information about content providers. These are a key aspect of how
- * different activities invoke and propagate data between themselves.</p>
- *
- * <p>The Activity class also provides an API for managing internal persistent state
- * associated with an activity. This can be used, for example, to remember
- * the user's preferred initial display in a calendar (day view or week view)
- * or the user's default home page in a web browser.</p>
- *
- * <p>Activity persistent state is managed
- * with the method {@link #getPreferences},
- * allowing you to retrieve and
- * modify a set of name/value pairs associated with the activity. To use
- * preferences that are shared across multiple application components
- * (activities, receivers, services, providers), you can use the underlying
- * {@link Context#getSharedPreferences Context.getSharedPreferences()} method
- * to retrieve a preferences
- * object stored under a specific name.
- * (Note that it is not possible to share settings data across application
- * packages -- for that you will need a content provider.)</p>
- *
- * <p>Here is an excerpt from a calendar activity that stores the user's
- * preferred view mode in its persistent settings:</p>
- *
- * <pre class="prettyprint">
- * public class CalendarActivity extends Activity {
- * ...
- *
- * static final int DAY_VIEW_MODE = 0;
- * static final int WEEK_VIEW_MODE = 1;
- *
- * private SharedPreferences mPrefs;
- * private int mCurViewMode;
- *
- * protected void onCreate(Bundle savedInstanceState) {
- * super.onCreate(savedInstanceState);
- *
- * SharedPreferences mPrefs = getSharedPreferences();
- * mCurViewMode = mPrefs.getInt("view_mode" DAY_VIEW_MODE);
- * }
- *
- * protected void onPause() {
- * super.onPause();
- *
- * SharedPreferences.Editor ed = mPrefs.edit();
- * ed.putInt("view_mode", mCurViewMode);
- * ed.commit();
- * }
- * }
- * </pre>
- *
- * <a name="Permissions"></a>
- * <h3>Permissions</h3>
- *
- * <p>The ability to start a particular Activity can be enforced when it is
- * declared in its
- * manifest's {@link android.R.styleable#AndroidManifestActivity &lt;activity&gt;}
- * tag. By doing so, other applications will need to declare a corresponding
- * {@link android.R.styleable#AndroidManifestUsesPermission &lt;uses-permission&gt;}
- * element in their own manifest to be able to start that activity.
- *
- * <p>See the <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a>
- * document for more information on permissions and security in general.
- *
- * <a name="ProcessLifecycle"></a>
- * <h3>Process Lifecycle</h3>
- *
- * <p>The Android system attempts to keep application process around for as
- * long as possible, but eventually will need to remove old processes when
- * memory runs low. As described in <a href="#ActivityLifecycle">Activity
- * Lifecycle</a>, the decision about which process to remove is intimately
- * tied to the state of the user's interaction with it. In general, there
- * are four states a process can be in based on the activities running in it,
- * listed here in order of importance. The system will kill less important
- * processes (the last ones) before it resorts to killing more important
- * processes (the first ones).
- *
- * <ol>
- * <li> <p>The <b>foreground activity</b> (the activity at the top of the screen
- * that the user is currently interacting with) is considered the most important.
- * Its process will only be killed as a last resort, if it uses more memory
- * than is available on the device. Generally at this point the device has
- * reached a memory paging state, so this is required in order to keep the user
- * interface responsive.
- * <li> <p>A <b>visible activity</b> (an activity that is visible to the user
- * but not in the foreground, such as one sitting behind a foreground dialog)
- * is considered extremely important and will not be killed unless that is
- * required to keep the foreground activity running.
- * <li> <p>A <b>background activity</b> (an activity that is not visible to
- * the user and has been paused) is no longer critical, so the system may
- * safely kill its process to reclaim memory for other foreground or
- * visible processes. If its process needs to be killed, when the user navigates
- * back to the activity (making it visible on the screen again), its
- * {@link #onCreate} method will be called with the savedInstanceState it had previously
- * supplied in {@link #onSaveInstanceState} so that it can restart itself in the same
- * state as the user last left it.
- * <li> <p>An <b>empty process</b> is one hosting no activities or other
- * application components (such as {@link Service} or
- * {@link android.content.BroadcastReceiver} classes). These are killed very
- * quickly by the system as memory becomes low. For this reason, any
- * background operation you do outside of an activity must be executed in the
- * context of an activity BroadcastReceiver or Service to ensure that the system
- * knows it needs to keep your process around.
- * </ol>
- *
- * <p>Sometimes an Activity may need to do a long-running operation that exists
- * independently of the activity lifecycle itself. An example may be a camera
- * application that allows you to upload a picture to a web site. The upload
- * may take a long time, and the application should allow the user to leave
- * the application will it is executing. To accomplish this, your Activity
- * should start a {@link Service} in which the upload takes place. This allows
- * the system to properly prioritize your process (considering it to be more
- * important than other non-visible applications) for the duration of the
- * upload, independent of whether the original activity is paused, stopped,
- * or finished.
- */
-public class Activity extends ContextThemeWrapper
- implements LayoutInflater.Factory,
- Window.Callback, KeyEvent.Callback,
- OnCreateContextMenuListener, ComponentCallbacks {
- private static final String TAG = "Activity";
-
- /** Standard activity result: operation canceled. */
- public static final int RESULT_CANCELED = 0;
- /** Standard activity result: operation succeeded. */
- public static final int RESULT_OK = -1;
- /** Start of user-defined activity results. */
- public static final int RESULT_FIRST_USER = 1;
-
- private static long sInstanceCount = 0;
-
- private static final String WINDOW_HIERARCHY_TAG = "android:viewHierarchyState";
- private static final String SAVED_DIALOG_IDS_KEY = "android:savedDialogIds";
- private static final String SAVED_DIALOGS_TAG = "android:savedDialogs";
- private static final String SAVED_DIALOG_KEY_PREFIX = "android:dialog_";
- private static final String SAVED_SEARCH_DIALOG_KEY = "android:search_dialog";
-
- private SparseArray<Dialog> mManagedDialogs;
-
- // set by the thread after the constructor and before onCreate(Bundle savedInstanceState) is called.
- private Instrumentation mInstrumentation;
- private IBinder mToken;
- /*package*/ String mEmbeddedID;
- private Application mApplication;
- private Intent mIntent;
- private ComponentName mComponent;
- /*package*/ ActivityInfo mActivityInfo;
- /*package*/ ActivityThread mMainThread;
- /*package*/ Object mLastNonConfigurationInstance;
- /*package*/ HashMap<String,Object> mLastNonConfigurationChildInstances;
- Activity mParent;
- boolean mCalled;
- private boolean mResumed;
- private boolean mStopped;
- boolean mFinished;
- boolean mStartedActivity;
- /*package*/ int mConfigChangeFlags;
- /*package*/ Configuration mCurrentConfig;
-
- private Window mWindow;
-
- private WindowManager mWindowManager;
- /*package*/ View mDecor = null;
- /*package*/ boolean mWindowAdded = false;
- /*package*/ boolean mVisibleFromServer = false;
- /*package*/ boolean mVisibleFromClient = true;
-
- private CharSequence mTitle;
- private int mTitleColor = 0;
-
- private static final class ManagedCursor {
- ManagedCursor(Cursor cursor) {
- mCursor = cursor;
- mReleased = false;
- mUpdated = false;
- }
-
- private final Cursor mCursor;
- private boolean mReleased;
- private boolean mUpdated;
- }
- private final ArrayList<ManagedCursor> mManagedCursors =
- new ArrayList<ManagedCursor>();
-
- // protected by synchronized (this)
- int mResultCode = RESULT_CANCELED;
- Intent mResultData = null;
-
- private boolean mTitleReady = false;
-
- private int mDefaultKeyMode = DEFAULT_KEYS_DISABLE;
- private SpannableStringBuilder mDefaultKeySsb = null;
-
- protected static final int[] FOCUSED_STATE_SET = {com.android.internal.R.attr.state_focused};
-
- private Thread mUiThread;
- private final Handler mHandler = new Handler();
-
- public Activity() {
- ++sInstanceCount;
- }
-
-
- @Override
- protected void finalize() throws Throwable {
- super.finalize();
- --sInstanceCount;
- }
-
- public static long getInstanceCount() {
- return sInstanceCount;
- }
-
- /** Return the intent that started this activity. */
- public Intent getIntent() {
- return mIntent;
- }
-
- /**
- * Change the intent returned by {@link #getIntent}. This holds a
- * reference to the given intent; it does not copy it. Often used in
- * conjunction with {@link #onNewIntent}.
- *
- * @param newIntent The new Intent object to return from getIntent
- *
- * @see #getIntent
- * @see #onNewIntent
- */
- public void setIntent(Intent newIntent) {
- mIntent = newIntent;
- }
-
- /** Return the application that owns this activity. */
- public final Application getApplication() {
- return mApplication;
- }
-
- /** Is this activity embedded inside of another activity? */
- public final boolean isChild() {
- return mParent != null;
- }
-
- /** Return the parent activity if this view is an embedded child. */
- public final Activity getParent() {
- return mParent;
- }
-
- /** Retrieve the window manager for showing custom windows. */
- public WindowManager getWindowManager() {
- return mWindowManager;
- }
-
- /**
- * Retrieve the current {@link android.view.Window} for the activity.
- * This can be used to directly access parts of the Window API that
- * are not available through Activity/Screen.
- *
- * @return Window The current window, or null if the activity is not
- * visual.
- */
- public Window getWindow() {
- return mWindow;
- }
-
- /**
- * Calls {@link android.view.Window#getCurrentFocus} on the
- * Window of this Activity to return the currently focused view.
- *
- * @return View The current View with focus or null.
- *
- * @see #getWindow
- * @see android.view.Window#getCurrentFocus
- */
- public View getCurrentFocus() {
- return mWindow != null ? mWindow.getCurrentFocus() : null;
- }
-
- @Override
- public int getWallpaperDesiredMinimumWidth() {
- int width = super.getWallpaperDesiredMinimumWidth();
- return width <= 0 ? getWindowManager().getDefaultDisplay().getWidth() : width;
- }
-
- @Override
- public int getWallpaperDesiredMinimumHeight() {
- int height = super.getWallpaperDesiredMinimumHeight();
- return height <= 0 ? getWindowManager().getDefaultDisplay().getHeight() : height;
- }
-
- /**
- * Called when the activity is starting. This is where most initialization
- * should go: calling {@link #setContentView(int)} to inflate the
- * activity's UI, using {@link #findViewById} to programmatically interact
- * with widgets in the UI, calling
- * {@link #managedQuery(android.net.Uri , String[], String, String[], String)} to retrieve
- * cursors for data being displayed, etc.
- *
- * <p>You can call {@link #finish} from within this function, in
- * which case onDestroy() will be immediately called without any of the rest
- * of the activity lifecycle ({@link #onStart}, {@link #onResume},
- * {@link #onPause}, etc) executing.
- *
- * <p><em>Derived classes must call through to the super class's
- * implementation of this method. If they do not, an exception will be
- * thrown.</em></p>
- *
- * @param savedInstanceState If the activity is being re-initialized after
- * previously being shut down then this Bundle contains the data it most
- * recently supplied in {@link #onSaveInstanceState}. <b><i>Note: Otherwise it is null.</i></b>
- *
- * @see #onStart
- * @see #onSaveInstanceState
- * @see #onRestoreInstanceState
- * @see #onPostCreate
- */
- protected void onCreate(Bundle savedInstanceState) {
- mVisibleFromClient = mWindow.getWindowStyle().getBoolean(
- com.android.internal.R.styleable.Window_windowNoDisplay, true);
- mCalled = true;
- }
-
- /**
- * The hook for {@link ActivityThread} to restore the state of this activity.
- *
- * Calls {@link #onSaveInstanceState(android.os.Bundle)} and
- * {@link #restoreManagedDialogs(android.os.Bundle)}.
- *
- * @param savedInstanceState contains the saved state
- */
- final void performRestoreInstanceState(Bundle savedInstanceState) {
- onRestoreInstanceState(savedInstanceState);
- restoreManagedDialogs(savedInstanceState);
-
- // Also restore the state of a search dialog (if any)
- // TODO more generic than just this manager
- SearchManager searchManager =
- (SearchManager) getSystemService(Context.SEARCH_SERVICE);
- searchManager.restoreSearchDialog(savedInstanceState, SAVED_SEARCH_DIALOG_KEY);
- }
-
- /**
- * This method is called after {@link #onStart} when the activity is
- * being re-initialized from a previously saved state, given here in
- * <var>state</var>. Most implementations will simply use {@link #onCreate}
- * to restore their state, but it is sometimes convenient to do it here
- * after all of the initialization has been done or to allow subclasses to
- * decide whether to use your default implementation. The default
- * implementation of this method performs a restore of any view state that
- * had previously been frozen by {@link #onSaveInstanceState}.
- *
- * <p>This method is called between {@link #onStart} and
- * {@link #onPostCreate}.
- *
- * @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}.
- *
- * @see #onCreate
- * @see #onPostCreate
- * @see #onResume
- * @see #onSaveInstanceState
- */
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- if (mWindow != null) {
- Bundle windowState = savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG);
- if (windowState != null) {
- mWindow.restoreHierarchyState(windowState);
- }
- }
- }
-
- /**
- * Restore the state of any saved managed dialogs.
- *
- * @param savedInstanceState The bundle to restore from.
- */
- private void restoreManagedDialogs(Bundle savedInstanceState) {
- final Bundle b = savedInstanceState.getBundle(SAVED_DIALOGS_TAG);
- if (b == null) {
- return;
- }
-
- final int[] ids = b.getIntArray(SAVED_DIALOG_IDS_KEY);
- final int numDialogs = ids.length;
- mManagedDialogs = new SparseArray<Dialog>(numDialogs);
- for (int i = 0; i < numDialogs; i++) {
- final Integer dialogId = ids[i];
- Bundle dialogState = b.getBundle(savedDialogKeyFor(dialogId));
- if (dialogState != null) {
- final Dialog dialog = onCreateDialog(dialogId);
- dialog.onRestoreInstanceState(dialogState);
- mManagedDialogs.put(dialogId, dialog);
- }
- }
- }
-
- private String savedDialogKeyFor(int key) {
- return SAVED_DIALOG_KEY_PREFIX + key;
- }
-
-
- /**
- * Called when activity start-up is complete (after {@link #onStart}
- * and {@link #onRestoreInstanceState} have been called). Applications will
- * generally not implement this method; it is intended for system
- * classes to do final initialization after application code has run.
- *
- * <p><em>Derived classes must call through to the super class's
- * implementation of this method. If they do not, an exception will be
- * thrown.</em></p>
- *
- * @param savedInstanceState If the activity is being re-initialized after
- * previously being shut down then this Bundle contains the data it most
- * recently supplied in {@link #onSaveInstanceState}. <b><i>Note: Otherwise it is null.</i></b>
- * @see #onCreate
- */
- protected void onPostCreate(Bundle savedInstanceState) {
- if (!isChild()) {
- mTitleReady = true;
- onTitleChanged(getTitle(), getTitleColor());
- }
- mCalled = true;
- }
-
- /**
- * Called after {@link #onCreate} &mdash; or after {@link #onRestart} when
- * the activity had been stopped, but is now again being displayed to the
- * user. It will be followed by {@link #onResume}.
- *
- * <p><em>Derived classes must call through to the super class's
- * implementation of this method. If they do not, an exception will be
- * thrown.</em></p>
- *
- * @see #onCreate
- * @see #onStop
- * @see #onResume
- */
- protected void onStart() {
- mCalled = true;
- }
-
- /**
- * Called after {@link #onStop} when the current activity is being
- * re-displayed to the user (the user has navigated back to it). It will
- * be followed by {@link #onStart} and then {@link #onResume}.
- *
- * <p>For activities that are using raw {@link Cursor} objects (instead of
- * creating them through
- * {@link #managedQuery(android.net.Uri , String[], String, String[], String)},
- * this is usually the place
- * where the cursor should be requeried (because you had deactivated it in
- * {@link #onStop}.
- *
- * <p><em>Derived classes must call through to the super class's
- * implementation of this method. If they do not, an exception will be
- * thrown.</em></p>
- *
- * @see #onStop
- * @see #onStart
- * @see #onResume
- */
- protected void onRestart() {
- mCalled = true;
- }
-
- /**
- * Called after {@link #onRestoreInstanceState}, {@link #onRestart}, or
- * {@link #onPause}, for your activity to start interacting with the user.
- * This is a good place to begin animations, open exclusive-access devices
- * (such as the camera), etc.
- *
- * <p>Keep in mind that onResume is not the best indicator that your activity
- * is visible to the user; a system window such as the keyguard may be in
- * front. Use {@link #onWindowFocusChanged} to know for certain that your
- * activity is visible to the user (for example, to resume a game).
- *
- * <p><em>Derived classes must call through to the super class's
- * implementation of this method. If they do not, an exception will be
- * thrown.</em></p>
- *
- * @see #onRestoreInstanceState
- * @see #onRestart
- * @see #onPostResume
- * @see #onPause
- */
- protected void onResume() {
- mCalled = true;
- }
-
- /**
- * Called when activity resume is complete (after {@link #onResume} has
- * been called). Applications will generally not implement this method;
- * it is intended for system classes to do final setup after application
- * resume code has run.
- *
- * <p><em>Derived classes must call through to the super class's
- * implementation of this method. If they do not, an exception will be
- * thrown.</em></p>
- *
- * @see #onResume
- */
- protected void onPostResume() {
- final Window win = getWindow();
- if (win != null) win.makeActive();
- mCalled = true;
- }
-
- /**
- * This is called for activities that set launchMode to "singleTop" in
- * their package, or if a client used the {@link Intent#FLAG_ACTIVITY_SINGLE_TOP}
- * flag when calling {@link #startActivity}. In either case, when the
- * activity is re-launched while at the top of the activity stack instead
- * of a new instance of the activity being started, onNewIntent() will be
- * called on the existing instance with the Intent that was used to
- * re-launch it.
- *
- * <p>An activity will always be paused before receiving a new intent, so
- * you can count on {@link #onResume} being called after this method.
- *
- * <p>Note that {@link #getIntent} still returns the original Intent. You
- * can use {@link #setIntent} to update it to this new Intent.
- *
- * @param intent The new intent that was started for the activity.
- *
- * @see #getIntent
- * @see #setIntent
- * @see #onResume
- */
- protected void onNewIntent(Intent intent) {
- }
-
- /**
- * The hook for {@link ActivityThread} to save the state of this activity.
- *
- * Calls {@link #onSaveInstanceState(android.os.Bundle)}
- * and {@link #saveManagedDialogs(android.os.Bundle)}.
- *
- * @param outState The bundle to save the state to.
- */
- final void performSaveInstanceState(Bundle outState) {
- onSaveInstanceState(outState);
- saveManagedDialogs(outState);
-
- // Also save the state of a search dialog (if any)
- // TODO more generic than just this manager
- SearchManager searchManager =
- (SearchManager) getSystemService(Context.SEARCH_SERVICE);
- searchManager.saveSearchDialog(outState, SAVED_SEARCH_DIALOG_KEY);
- }
-
- /**
- * Called to retrieve per-instance state from an activity before being killed
- * so that the state can be restored in {@link #onCreate} or
- * {@link #onRestoreInstanceState} (the {@link Bundle} populated by this method
- * will be passed to both).
- *
- * <p>This method is called before an activity may be killed so that when it
- * comes back some time in the future it can restore its state. For example,
- * if activity B is launched in front of activity A, and at some point activity
- * A is killed to reclaim resources, activity A will have a chance to save the
- * current state of its user interface via this method so that when the user
- * returns to activity A, the state of the user interface can be restored
- * via {@link #onCreate} or {@link #onRestoreInstanceState}.
- *
- * <p>Do not confuse this method with activity lifecycle callbacks such as
- * {@link #onPause}, which is always called when an activity is being placed
- * in the background or on its way to destruction, or {@link #onStop} which
- * is called before destruction. One example of when {@link #onPause} and
- * {@link #onStop} is called and not this method is when a user navigates back
- * from activity B to activity A: there is no need to call {@link #onSaveInstanceState}
- * on B because that particular instance will never be restored, so the
- * system avoids calling it. An example when {@link #onPause} is called and
- * not {@link #onSaveInstanceState} is when activity B is launched in front of activity A:
- * the system may avoid calling {@link #onSaveInstanceState} on activity A if it isn't
- * killed during the lifetime of B since the state of the user interface of
- * A will stay intact.
- *
- * <p>The default implementation takes care of most of the UI per-instance
- * state for you by calling {@link android.view.View#onSaveInstanceState()} on each
- * view in the hierarchy that has an id, and by saving the id of the currently
- * focused view (all of which is restored by the default implementation of
- * {@link #onRestoreInstanceState}). If you override this method to save additional
- * information not captured by each individual view, you will likely want to
- * call through to the default implementation, otherwise be prepared to save
- * all of the state of each view yourself.
- *
- * <p>If called, this method will occur before {@link #onStop}. There are
- * no guarantees about whether it will occur before or after {@link #onPause}.
- *
- * @param outState Bundle in which to place your saved state.
- *
- * @see #onCreate
- * @see #onRestoreInstanceState
- * @see #onPause
- */
- protected void onSaveInstanceState(Bundle outState) {
- outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
- }
-
- /**
- * Save the state of any managed dialogs.
- *
- * @param outState place to store the saved state.
- */
- private void saveManagedDialogs(Bundle outState) {
- if (mManagedDialogs == null) {
- return;
- }
-
- final int numDialogs = mManagedDialogs.size();
- if (numDialogs == 0) {
- return;
- }
-
- Bundle dialogState = new Bundle();
-
- int[] ids = new int[mManagedDialogs.size()];
-
- // save each dialog's bundle, gather the ids
- for (int i = 0; i < numDialogs; i++) {
- final int key = mManagedDialogs.keyAt(i);
- ids[i] = key;
- final Dialog dialog = mManagedDialogs.valueAt(i);
- dialogState.putBundle(savedDialogKeyFor(key), dialog.onSaveInstanceState());
- }
-
- dialogState.putIntArray(SAVED_DIALOG_IDS_KEY, ids);
- outState.putBundle(SAVED_DIALOGS_TAG, dialogState);
- }
-
-
- /**
- * Called as part of the activity lifecycle when an activity is going into
- * the background, but has not (yet) been killed. The counterpart to
- * {@link #onResume}.
- *
- * <p>When activity B is launched in front of activity A, this callback will
- * be invoked on A. B will not be created until A's {@link #onPause} returns,
- * so be sure to not do anything lengthy here.
- *
- * <p>This callback is mostly used for saving any persistent state the
- * activity is editing, to present a "edit in place" model to the user and
- * making sure nothing is lost if there are not enough resources to start
- * the new activity without first killing this one. This is also a good
- * place to do things like stop animations and other things that consume a
- * noticeable mount of CPU in order to make the switch to the next activity
- * as fast as possible, or to close resources that are exclusive access
- * such as the camera.
- *
- * <p>In situations where the system needs more memory it may kill paused
- * processes to reclaim resources. Because of this, you should be sure
- * that all of your state is saved by the time you return from
- * this function. In general {@link #onSaveInstanceState} is used to save
- * per-instance state in the activity and this method is used to store
- * global persistent data (in content providers, files, etc.)
- *
- * <p>After receiving this call you will usually receive a following call
- * to {@link #onStop} (after the next activity has been resumed and
- * displayed), however in some cases there will be a direct call back to
- * {@link #onResume} without going through the stopped state.
- *
- * <p><em>Derived classes must call through to the super class's
- * implementation of this method. If they do not, an exception will be
- * thrown.</em></p>
- *
- * @see #onResume
- * @see #onSaveInstanceState
- * @see #onStop
- */
- protected void onPause() {
- mCalled = true;
- }
-
- /**
- * Called as part of the activity lifecycle when an activity is about to go
- * into the background as the result of user choice. For example, when the
- * user presses the Home key, {@link #onUserLeaveHint} will be called, but
- * when an incoming phone call causes the in-call Activity to be automatically
- * brought to the foreground, {@link #onUserLeaveHint} will not be called on
- * the activity being interrupted. In cases when it is invoked, this method
- * is called right before the activity's {@link #onPause} callback.
- *
- * <p>This callback and {@link #onUserInteraction} are intended to help
- * activities manage status bar notifications intelligently; specifically,
- * for helping activities determine the proper time to cancel a notfication.
- *
- * @see #onUserInteraction()
- */
- protected void onUserLeaveHint() {
- }
-
- /**
- * Generate a new thumbnail for this activity. This method is called before
- * pausing the activity, and should draw into <var>outBitmap</var> the
- * imagery for the desired thumbnail in the dimensions of that bitmap. It
- * can use the given <var>canvas</var>, which is configured to draw into the
- * bitmap, for rendering if desired.
- *
- * <p>The default implementation renders the Screen's current view
- * hierarchy into the canvas to generate a thumbnail.
- *
- * <p>If you return false, the bitmap will be filled with a default
- * thumbnail.
- *
- * @param outBitmap The bitmap to contain the thumbnail.
- * @param canvas Can be used to render into the bitmap.
- *
- * @return Return true if you have drawn into the bitmap; otherwise after
- * you return it will be filled with a default thumbnail.
- *
- * @see #onCreateDescription
- * @see #onSaveInstanceState
- * @see #onPause
- */
- public boolean onCreateThumbnail(Bitmap outBitmap, Canvas canvas) {
- final View view = mDecor;
- if (view == null) {
- return false;
- }
-
- final int vw = view.getWidth();
- final int vh = view.getHeight();
- final int dw = outBitmap.getWidth();
- final int dh = outBitmap.getHeight();
-
- canvas.save();
- canvas.scale(((float)dw)/vw, ((float)dh)/vh);
- view.draw(canvas);
- canvas.restore();
-
- return true;
- }
-
- /**
- * Generate a new description for this activity. This method is called
- * before pausing the activity and can, if desired, return some textual
- * description of its current state to be displayed to the user.
- *
- * <p>The default implementation returns null, which will cause you to
- * inherit the description from the previous activity. If all activities
- * return null, generally the label of the top activity will be used as the
- * description.
- *
- * @return A description of what the user is doing. It should be short and
- * sweet (only a few words).
- *
- * @see #onCreateThumbnail
- * @see #onSaveInstanceState
- * @see #onPause
- */
- public CharSequence onCreateDescription() {
- return null;
- }
-
- /**
- * Called when you are no longer visible to the user. You will next
- * receive either {@link #onRestart}, {@link #onDestroy}, or nothing,
- * depending on later user activity.
- *
- * <p>Note that this method may never be called, in low memory situations
- * where the system does not have enough memory to keep your activity's
- * process running after its {@link #onPause} method is called.
- *
- * <p><em>Derived classes must call through to the super class's
- * implementation of this method. If they do not, an exception will be
- * thrown.</em></p>
- *
- * @see #onRestart
- * @see #onResume
- * @see #onSaveInstanceState
- * @see #onDestroy
- */
- protected void onStop() {
- mCalled = true;
- }
-
- /**
- * Perform any final cleanup before an activity is destroyed. This can
- * happen either because the activity is finishing (someone called
- * {@link #finish} on it, or because the system is temporarily destroying
- * this instance of the activity to save space. You can distinguish
- * between these two scenarios with the {@link #isFinishing} method.
- *
- * <p><em>Note: do not count on this method being called as a place for
- * saving data! For example, if an activity is editing data in a content
- * provider, those edits should be committed in either {@link #onPause} or
- * {@link #onSaveInstanceState}, not here.</em> This method is usually implemented to
- * free resources like threads that are associated with an activity, so
- * that a destroyed activity does not leave such things around while the
- * rest of its application is still running. There are situations where
- * the system will simply kill the activity's hosting process without
- * calling this method (or any others) in it, so it should not be used to
- * do things that are intended to remain around after the process goes
- * away.
- *
- * <p><em>Derived classes must call through to the super class's
- * implementation of this method. If they do not, an exception will be
- * thrown.</em></p>
- *
- * @see #onPause
- * @see #onStop
- * @see #finish
- * @see #isFinishing
- */
- protected void onDestroy() {
- mCalled = true;
-
- // dismiss any dialogs we are managing.
- if (mManagedDialogs != null) {
-
- final int numDialogs = mManagedDialogs.size();
- for (int i = 0; i < numDialogs; i++) {
- final Dialog dialog = mManagedDialogs.valueAt(i);
- if (dialog.isShowing()) {
- dialog.dismiss();
- }
- }
- }
-
- // also dismiss search dialog if showing
- // TODO more generic than just this manager
- SearchManager searchManager =
- (SearchManager) getSystemService(Context.SEARCH_SERVICE);
- searchManager.stopSearch();
-
- // close any cursors we are managing.
- int numCursors = mManagedCursors.size();
- for (int i = 0; i < numCursors; i++) {
- ManagedCursor c = mManagedCursors.get(i);
- if (c != null) {
- c.mCursor.close();
- }
- }
- }
-
- /**
- * Called by the system when the device configuration changes while your
- * activity is running. Note that this will <em>only</em> be called if
- * you have selected configurations you would like to handle with the
- * {@link android.R.attr#configChanges} attribute in your manifest. If
- * any configuration change occurs that is not selected to be reported
- * by that attribute, then instead of reporting it the system will stop
- * and restart the activity (to have it launched with the new
- * configuration).
- *
- * <p>At the time that this function has been called, your Resources
- * object will have been updated to return resource values matching the
- * new configuration.
- *
- * @param newConfig The new device configuration.
- */
- public void onConfigurationChanged(Configuration newConfig) {
- mCalled = true;
-
- // also update search dialog if showing
- // TODO more generic than just this manager
- SearchManager searchManager =
- (SearchManager) getSystemService(Context.SEARCH_SERVICE);
- searchManager.onConfigurationChanged(newConfig);
-
- if (mWindow != null) {
- // Pass the configuration changed event to the window
- mWindow.onConfigurationChanged(newConfig);
- }
- }
-
- /**
- * If this activity is being destroyed because it can not handle a
- * configuration parameter being changed (and thus its
- * {@link #onConfigurationChanged(Configuration)} method is
- * <em>not</em> being called), then you can use this method to discover
- * the set of changes that have occurred while in the process of being
- * destroyed. Note that there is no guarantee that these will be
- * accurate (other changes could have happened at any time), so you should
- * only use this as an optimization hint.
- *
- * @return Returns a bit field of the configuration parameters that are
- * changing, as defined by the {@link android.content.res.Configuration}
- * class.
- */
- public int getChangingConfigurations() {
- return mConfigChangeFlags;
- }
-
- /**
- * Retrieve the non-configuration instance data that was previously
- * returned by {@link #onRetainNonConfigurationInstance()}. This will
- * be available from the initial {@link #onCreate} and
- * {@link #onStart} calls to the new instance, allowing you to extract
- * any useful dynamic state from the previous instance.
- *
- * <p>Note that the data you retrieve here should <em>only</em> be used
- * as an optimization for handling configuration changes. You should always
- * be able to handle getting a null pointer back, and an activity must
- * still be able to restore itself to its previous state (through the
- * normal {@link #onSaveInstanceState(Bundle)} mechanism) even if this
- * function returns null.
- *
- * @return Returns the object previously returned by
- * {@link #onRetainNonConfigurationInstance()}.
- */
- public Object getLastNonConfigurationInstance() {
- return mLastNonConfigurationInstance;
- }
-
- /**
- * Called by the system, as part of destroying an
- * activity due to a configuration change, when it is known that a new
- * instance will immediately be created for the new configuration. You
- * can return any object you like here, including the activity instance
- * itself, which can later be retrieved by calling
- * {@link #getLastNonConfigurationInstance()} in the new activity
- * instance.
- *
- * <p>This function is called purely as an optimization, and you must
- * not rely on it being called. When it is called, a number of guarantees
- * will be made to help optimize configuration switching:
- * <ul>
- * <li> The function will be called between {@link #onStop} and
- * {@link #onDestroy}.
- * <li> A new instance of the activity will <em>always</em> be immediately
- * created after this one's {@link #onDestroy()} is called.
- * <li> The object you return here will <em>always</em> be available from
- * the {@link #getLastNonConfigurationInstance()} method of the following
- * activity instance as described there.
- * </ul>
- *
- * <p>These guarantees are designed so that an activity can use this API
- * to propagate extensive state from the old to new activity instance, from
- * loaded bitmaps, to network connections, to evenly actively running
- * threads. Note that you should <em>not</em> propagate any data that
- * may change based on the configuration, including any data loaded from
- * resources such as strings, layouts, or drawables.
- *
- * @return Return any Object holding the desired state to propagate to the
- * next activity instance.
- */
- public Object onRetainNonConfigurationInstance() {
- return null;
- }
-
- /**
- * Retrieve the non-configuration instance data that was previously
- * returned by {@link #onRetainNonConfigurationChildInstances()}. This will
- * be available from the initial {@link #onCreate} and
- * {@link #onStart} calls to the new instance, allowing you to extract
- * any useful dynamic state from the previous instance.
- *
- * <p>Note that the data you retrieve here should <em>only</em> be used
- * as an optimization for handling configuration changes. You should always
- * be able to handle getting a null pointer back, and an activity must
- * still be able to restore itself to its previous state (through the
- * normal {@link #onSaveInstanceState(Bundle)} mechanism) even if this
- * function returns null.
- *
- * @return Returns the object previously returned by
- * {@link #onRetainNonConfigurationChildInstances()}
- */
- HashMap<String,Object> getLastNonConfigurationChildInstances() {
- return mLastNonConfigurationChildInstances;
- }
-
- /**
- * This method is similar to {@link #onRetainNonConfigurationInstance()} except that
- * it should return either a mapping from child activity id strings to arbitrary objects,
- * or null. This method is intended to be used by Activity framework subclasses that control a
- * set of child activities, such as ActivityGroup. The same guarantees and restrictions apply
- * as for {@link #onRetainNonConfigurationInstance()}. The default implementation returns null.
- */
- HashMap<String,Object> onRetainNonConfigurationChildInstances() {
- return null;
- }
-
- public void onLowMemory() {
- mCalled = true;
- }
-
- /**
- * Wrapper around
- * {@link ContentResolver#query(android.net.Uri , String[], String, String[], String)}
- * that gives the resulting {@link Cursor} to call
- * {@link #startManagingCursor} so that the activity will manage its
- * lifecycle for you.
- *
- * @param uri The URI of the content provider to query.
- * @param projection List of columns to return.
- * @param selection SQL WHERE clause.
- * @param sortOrder SQL ORDER BY clause.
- *
- * @return The Cursor that was returned by query().
- *
- * @see ContentResolver#query(android.net.Uri , String[], String, String[], String)
- * @see #startManagingCursor
- * @hide
- */
- public final Cursor managedQuery(Uri uri,
- String[] projection,
- String selection,
- String sortOrder)
- {
- Cursor c = getContentResolver().query(uri, projection, selection, null, sortOrder);
- if (c != null) {
- startManagingCursor(c);
- }
- return c;
- }
-
- /**
- * Wrapper around
- * {@link ContentResolver#query(android.net.Uri , String[], String, String[], String)}
- * that gives the resulting {@link Cursor} to call
- * {@link #startManagingCursor} so that the activity will manage its
- * lifecycle for you.
- *
- * @param uri The URI of the content provider to query.
- * @param projection List of columns to return.
- * @param selection SQL WHERE clause.
- * @param selectionArgs The arguments to selection, if any ?s are pesent
- * @param sortOrder SQL ORDER BY clause.
- *
- * @return The Cursor that was returned by query().
- *
- * @see ContentResolver#query(android.net.Uri , String[], String, String[], String)
- * @see #startManagingCursor
- */
- public final Cursor managedQuery(Uri uri,
- String[] projection,
- String selection,
- String[] selectionArgs,
- String sortOrder)
- {
- Cursor c = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
- if (c != null) {
- startManagingCursor(c);
- }
- return c;
- }
-
- /**
- * Wrapper around {@link Cursor#commitUpdates()} that takes care of noting
- * that the Cursor needs to be requeried. You can call this method in
- * {@link #onPause} or {@link #onStop} to have the system call
- * {@link Cursor#requery} for you if the activity is later resumed. This
- * allows you to avoid determing when to do the requery yourself (which is
- * required for the Cursor to see any data changes that were committed with
- * it).
- *
- * @param c The Cursor whose changes are to be committed.
- *
- * @see #managedQuery(android.net.Uri , String[], String, String[], String)
- * @see #startManagingCursor
- * @see Cursor#commitUpdates()
- * @see Cursor#requery
- * @hide
- */
- @Deprecated
- public void managedCommitUpdates(Cursor c) {
- synchronized (mManagedCursors) {
- final int N = mManagedCursors.size();
- for (int i=0; i<N; i++) {
- ManagedCursor mc = mManagedCursors.get(i);
- if (mc.mCursor == c) {
- c.commitUpdates();
- mc.mUpdated = true;
- return;
- }
- }
- throw new RuntimeException(
- "Cursor " + c + " is not currently managed");
- }
- }
-
- /**
- * This method allows the activity to take care of managing the given
- * {@link Cursor}'s lifecycle for you based on the activity's lifecycle.
- * That is, when the activity is stopped it will automatically call
- * {@link Cursor#deactivate} on the given Cursor, and when it is later restarted
- * it will call {@link Cursor#requery} for you. When the activity is
- * destroyed, all managed Cursors will be closed automatically.
- *
- * @param c The Cursor to be managed.
- *
- * @see #managedQuery(android.net.Uri , String[], String, String[], String)
- * @see #stopManagingCursor
- */
- public void startManagingCursor(Cursor c) {
- synchronized (mManagedCursors) {
- mManagedCursors.add(new ManagedCursor(c));
- }
- }
-
- /**
- * Given a Cursor that was previously given to
- * {@link #startManagingCursor}, stop the activity's management of that
- * cursor.
- *
- * @param c The Cursor that was being managed.
- *
- * @see #startManagingCursor
- */
- public void stopManagingCursor(Cursor c) {
- synchronized (mManagedCursors) {
- final int N = mManagedCursors.size();
- for (int i=0; i<N; i++) {
- ManagedCursor mc = mManagedCursors.get(i);
- if (mc.mCursor == c) {
- mManagedCursors.remove(i);
- break;
- }
- }
- }
- }
-
- /**
- * Control whether this activity is required to be persistent. By default
- * activities are not persistent; setting this to true will prevent the
- * system from stopping this activity or its process when running low on
- * resources.
- *
- * <p><em>You should avoid using this method</em>, it has severe negative
- * consequences on how well the system can manage its resources. A better
- * approach is to implement an application service that you control with
- * {@link Context#startService} and {@link Context#stopService}.
- *
- * @param isPersistent Control whether the current activity must be
- * persistent, true if so, false for the normal
- * behavior.
- */
- public void setPersistent(boolean isPersistent) {
- if (mParent == null) {
- try {
- ActivityManagerNative.getDefault()
- .setPersistent(mToken, isPersistent);
- } catch (RemoteException e) {
- // Empty
- }
- } else {
- throw new RuntimeException("setPersistent() not yet supported for embedded activities");
- }
- }
-
- /**
- * Finds a view that was identified by the id attribute from the XML that
- * was processed in {@link #onCreate}.
- *
- * @return The view if found or null otherwise.
- */
- public View findViewById(int id) {
- return getWindow().findViewById(id);
- }
-
- /**
- * Set the activity content from a layout resource. The resource will be
- * inflated, adding all top-level views to the activity.
- *
- * @param layoutResID Resource ID to be inflated.
- */
- public void setContentView(int layoutResID) {
- getWindow().setContentView(layoutResID);
- }
-
- /**
- * Set the activity content to an explicit view. This view is placed
- * directly into the activity's view hierarchy. It can itself be a complex
- * view hierarhcy.
- *
- * @param view The desired content to display.
- */
- public void setContentView(View view) {
- getWindow().setContentView(view);
- }
-
- /**
- * Set the activity content to an explicit view. This view is placed
- * directly into the activity's view hierarchy. It can itself be a complex
- * view hierarhcy.
- *
- * @param view The desired content to display.
- * @param params Layout parameters for the view.
- */
- public void setContentView(View view, ViewGroup.LayoutParams params) {
- getWindow().setContentView(view, params);
- }
-
- /**
- * Add an additional content view to the activity. Added after any existing
- * ones in the activity -- existing views are NOT removed.
- *
- * @param view The desired content to display.
- * @param params Layout parameters for the view.
- */
- public void addContentView(View view, ViewGroup.LayoutParams params) {
- getWindow().addContentView(view, params);
- }
-
- /**
- * Use with {@link #setDefaultKeyMode} to turn off default handling of
- * keys.
- *
- * @see #setDefaultKeyMode
- */
- static public final int DEFAULT_KEYS_DISABLE = 0;
- /**
- * Use with {@link #setDefaultKeyMode} to launch the dialer during default
- * key handling.
- *
- * @see #setDefaultKeyMode
- */
- static public final int DEFAULT_KEYS_DIALER = 1;
- /**
- * Use with {@link #setDefaultKeyMode} to execute a menu shortcut in
- * default key handling.
- *
- * <p>That is, the user does not need to hold down the menu key to execute menu shortcuts.
- *
- * @see #setDefaultKeyMode
- */
- static public final int DEFAULT_KEYS_SHORTCUT = 2;
- /**
- * Use with {@link #setDefaultKeyMode} to specify that unhandled keystrokes
- * will start an application-defined search. (If the application or activity does not
- * actually define a search, the the keys will be ignored.)
- *
- * <p>See {@link android.app.SearchManager android.app.SearchManager} for more details.
- *
- * @see #setDefaultKeyMode
- */
- static public final int DEFAULT_KEYS_SEARCH_LOCAL = 3;
-
- /**
- * Use with {@link #setDefaultKeyMode} to specify that unhandled keystrokes
- * will start a global search (typically web search, but some platforms may define alternate
- * methods for global search)
- *
- * <p>See {@link android.app.SearchManager android.app.SearchManager} for more details.
- *
- * @see #setDefaultKeyMode
- */
- static public final int DEFAULT_KEYS_SEARCH_GLOBAL = 4;
-
- /**
- * Select the default key handling for this activity. This controls what
- * will happen to key events that are not otherwise handled. The default
- * mode ({@link #DEFAULT_KEYS_DISABLE}) will simply drop them on the
- * floor. Other modes allow you to launch the dialer
- * ({@link #DEFAULT_KEYS_DIALER}), execute a shortcut in your options
- * menu without requiring the menu key be held down
- * ({@link #DEFAULT_KEYS_SHORTCUT}), or launch a search ({@link #DEFAULT_KEYS_SEARCH_LOCAL}
- * and {@link #DEFAULT_KEYS_SEARCH_GLOBAL}).
- *
- * <p>Note that the mode selected here does not impact the default
- * handling of system keys, such as the "back" and "menu" keys, and your
- * activity and its views always get a first chance to receive and handle
- * all application keys.
- *
- * @param mode The desired default key mode constant.
- *
- * @see #DEFAULT_KEYS_DISABLE
- * @see #DEFAULT_KEYS_DIALER
- * @see #DEFAULT_KEYS_SHORTCUT
- * @see #DEFAULT_KEYS_SEARCH_LOCAL
- * @see #DEFAULT_KEYS_SEARCH_GLOBAL
- * @see #onKeyDown
- */
- public final void setDefaultKeyMode(int mode) {
- mDefaultKeyMode = mode;
-
- // Some modes use a SpannableStringBuilder to track & dispatch input events
- // This list must remain in sync with the switch in onKeyDown()
- switch (mode) {
- case DEFAULT_KEYS_DISABLE:
- case DEFAULT_KEYS_SHORTCUT:
- mDefaultKeySsb = null; // not used in these modes
- break;
- case DEFAULT_KEYS_DIALER:
- case DEFAULT_KEYS_SEARCH_LOCAL:
- case DEFAULT_KEYS_SEARCH_GLOBAL:
- mDefaultKeySsb = new SpannableStringBuilder();
- Selection.setSelection(mDefaultKeySsb,0);
- break;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- /**
- * Called when a key was pressed down and not handled by any of the views
- * inside of the activity. So, for example, key presses while the cursor
- * is inside a TextView will not trigger the event (unless it is a navigation
- * to another object) because TextView handles its own key presses.
- *
- * <p>If the focused view didn't want this event, this method is called.
- *
- * <p>The default implementation handles KEYCODE_BACK to stop the activity
- * and go back, and other default key handling if configured with {@link #setDefaultKeyMode}.
- *
- * @return Return <code>true</code> to prevent this event from being propagated
- * further, or <code>false</code> to indicate that you have not handled
- * this event and it should continue to be propagated.
- * @see #onKeyUp
- * @see android.view.KeyEvent
- */
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
- finish();
- return true;
- }
-
- if (mDefaultKeyMode == DEFAULT_KEYS_DISABLE) {
- return false;
- } else if (mDefaultKeyMode == DEFAULT_KEYS_SHORTCUT) {
- return getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL,
- keyCode, event, Menu.FLAG_ALWAYS_PERFORM_CLOSE);
- } else {
- // Common code for DEFAULT_KEYS_DIALER & DEFAULT_KEYS_SEARCH_*
- boolean clearSpannable = false;
- boolean handled;
- if ((event.getRepeatCount() != 0) || event.isSystem()) {
- clearSpannable = true;
- handled = false;
- } else {
- handled = TextKeyListener.getInstance().onKeyDown(null, mDefaultKeySsb,
- keyCode, event);
- if (handled && mDefaultKeySsb.length() > 0) {
- // something useable has been typed - dispatch it now.
-
- final String str = mDefaultKeySsb.toString();
- clearSpannable = true;
-
- switch (mDefaultKeyMode) {
- case DEFAULT_KEYS_DIALER:
- Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + str));
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
- break;
- case DEFAULT_KEYS_SEARCH_LOCAL:
- startSearch(str, false, null, false);
- break;
- case DEFAULT_KEYS_SEARCH_GLOBAL:
- startSearch(str, false, null, true);
- break;
- }
- }
- }
- if (clearSpannable) {
- mDefaultKeySsb.clear();
- mDefaultKeySsb.clearSpans();
- Selection.setSelection(mDefaultKeySsb,0);
- }
- return handled;
- }
- }
-
- /**
- * Called when a key was released and not handled by any of the views
- * inside of the activity. So, for example, key presses while the cursor
- * is inside a TextView will not trigger the event (unless it is a navigation
- * to another object) because TextView handles its own key presses.
- *
- * @return Return <code>true</code> to prevent this event from being propagated
- * further, or <code>false</code> to indicate that you have not handled
- * this event and it should continue to be propagated.
- * @see #onKeyDown
- * @see KeyEvent
- */
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- return false;
- }
-
- /**
- * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
- * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
- * the event).
- */
- public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
- return false;
- }
-
- /**
- * Called when a touch screen event was not handled by any of the views
- * under it. This is most useful to process touch events that happen
- * outside of your window bounds, where there is no view to receive it.
- *
- * @param event The touch screen event being processed.
- *
- * @return Return true if you have consumed the event, false if you haven't.
- * The default implementation always returns false.
- */
- public boolean onTouchEvent(MotionEvent event) {
- return false;
- }
-
- /**
- * Called when the trackball was moved and not handled by any of the
- * views inside of the activity. So, for example, if the trackball moves
- * while focus is on a button, you will receive a call here because
- * buttons do not normally do anything with trackball events. The call
- * here happens <em>before</em> trackball movements are converted to
- * DPAD key events, which then get sent back to the view hierarchy, and
- * will be processed at the point for things like focus navigation.
- *
- * @param event The trackball event being processed.
- *
- * @return Return true if you have consumed the event, false if you haven't.
- * The default implementation always returns false.
- */
- public boolean onTrackballEvent(MotionEvent event) {
- return false;
- }
-
- /**
- * Called whenever a key, touch, or trackball event is dispatched to the
- * activity. Implement this method if you wish to know that the user has
- * interacted with the device in some way while your activity is running.
- * This callback and {@link #onUserLeaveHint} are intended to help
- * activities manage status bar notifications intelligently; specifically,
- * for helping activities determine the proper time to cancel a notfication.
- *
- * <p>All calls to your activity's {@link #onUserLeaveHint} callback will
- * be accompanied by calls to {@link #onUserInteraction}. This
- * ensures that your activity will be told of relevant user activity such
- * as pulling down the notification pane and touching an item there.
- *
- * <p>Note that this callback will be invoked for the touch down action
- * that begins a touch gesture, but may not be invoked for the touch-moved
- * and touch-up actions that follow.
- *
- * @see #onUserLeaveHint()
- */
- public void onUserInteraction() {
- }
-
- public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
- // Update window manager if: we have a view, that view is
- // attached to its parent (which will be a RootView), and
- // this activity is not embedded.
- if (mParent == null) {
- View decor = mDecor;
- if (decor != null && decor.getParent() != null) {
- getWindowManager().updateViewLayout(decor, params);
- }
- }
- }
-
- public void onContentChanged() {
- }
-
- /**
- * Called when the current {@link Window} of the activity gains or loses
- * focus. This is the best indicator of whether this activity is visible
- * to the user.
- *
- * <p>Note that this provides information what global focus state, which
- * is managed independently of activity lifecycles. As such, while focus
- * changes will generally have some relation to lifecycle changes (an
- * activity that is stopped will not generally get window focus), you
- * should not rely on any particular order between the callbacks here and
- * those in the other lifecycle methods such as {@link #onResume}.
- *
- * <p>As a general rule, however, a resumed activity will have window
- * focus... unless it has displayed other dialogs or popups that take
- * input focus, in which case the activity itself will not have focus
- * when the other windows have it. Likewise, the system may display
- * system-level windows (such as the status bar notification panel or
- * a system alert) which will temporarily take window input focus without
- * pausing the foreground activity.
- *
- * @param hasFocus Whether the window of this activity has focus.
- *
- * @see #hasWindowFocus()
- * @see #onResume
- */
- public void onWindowFocusChanged(boolean hasFocus) {
- }
-
- /**
- * Returns true if this activity's <em>main</em> window currently has window focus.
- * Note that this is not the same as the view itself having focus.
- *
- * @return True if this activity's main window currently has window focus.
- *
- * @see #onWindowAttributesChanged(android.view.WindowManager.LayoutParams)
- */
- public boolean hasWindowFocus() {
- Window w = getWindow();
- if (w != null) {
- View d = w.getDecorView();
- if (d != null) {
- return d.hasWindowFocus();
- }
- }
- return false;
- }
-
- /**
- * Called to process key events. You can override this to intercept all
- * key events before they are dispatched to the window. Be sure to call
- * this implementation for key events that should be handled normally.
- *
- * @param event The key event.
- *
- * @return boolean Return true if this event was consumed.
- */
- public boolean dispatchKeyEvent(KeyEvent event) {
- onUserInteraction();
- if (getWindow().superDispatchKeyEvent(event)) {
- return true;
- }
- return event.dispatch(this);
- }
-
- /**
- * Called to process touch screen events. You can override this to
- * intercept all touch screen events before they are dispatched to the
- * window. Be sure to call this implementation for touch screen events
- * that should be handled normally.
- *
- * @param ev The touch screen event.
- *
- * @return boolean Return true if this event was consumed.
- */
- public boolean dispatchTouchEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- onUserInteraction();
- }
- if (getWindow().superDispatchTouchEvent(ev)) {
- return true;
- }
- return onTouchEvent(ev);
- }
-
- /**
- * Called to process trackball events. You can override this to
- * intercept all trackball events before they are dispatched to the
- * window. Be sure to call this implementation for trackball events
- * that should be handled normally.
- *
- * @param ev The trackball event.
- *
- * @return boolean Return true if this event was consumed.
- */
- public boolean dispatchTrackballEvent(MotionEvent ev) {
- onUserInteraction();
- if (getWindow().superDispatchTrackballEvent(ev)) {
- return true;
- }
- return onTrackballEvent(ev);
- }
-
- /**
- * Default implementation of
- * {@link android.view.Window.Callback#onCreatePanelView}
- * for activities. This
- * simply returns null so that all panel sub-windows will have the default
- * menu behavior.
- */
- public View onCreatePanelView(int featureId) {
- return null;
- }
-
- /**
- * Default implementation of
- * {@link android.view.Window.Callback#onCreatePanelMenu}
- * for activities. This calls through to the new
- * {@link #onCreateOptionsMenu} method for the
- * {@link android.view.Window#FEATURE_OPTIONS_PANEL} panel,
- * so that subclasses of Activity don't need to deal with feature codes.
- */
- public boolean onCreatePanelMenu(int featureId, Menu menu) {
- if (featureId == Window.FEATURE_OPTIONS_PANEL) {
- return onCreateOptionsMenu(menu);
- }
- return false;
- }
-
- /**
- * Default implementation of
- * {@link android.view.Window.Callback#onPreparePanel}
- * for activities. This
- * calls through to the new {@link #onPrepareOptionsMenu} method for the
- * {@link android.view.Window#FEATURE_OPTIONS_PANEL}
- * panel, so that subclasses of
- * Activity don't need to deal with feature codes.
- */
- public boolean onPreparePanel(int featureId, View view, Menu menu) {
- if (featureId == Window.FEATURE_OPTIONS_PANEL && menu != null) {
- boolean goforit = onPrepareOptionsMenu(menu);
- return goforit && menu.hasVisibleItems();
- }
- return true;
- }
-
- /**
- * {@inheritDoc}
- *
- * @return The default implementation returns true.
- */
- public boolean onMenuOpened(int featureId, Menu menu) {
- return true;
- }
-
- /**
- * Default implementation of
- * {@link android.view.Window.Callback#onMenuItemSelected}
- * for activities. This calls through to the new
- * {@link #onOptionsItemSelected} method for the
- * {@link android.view.Window#FEATURE_OPTIONS_PANEL}
- * panel, so that subclasses of
- * Activity don't need to deal with feature codes.
- */
- public boolean onMenuItemSelected(int featureId, MenuItem item) {
- switch (featureId) {
- case Window.FEATURE_OPTIONS_PANEL:
- // Put event logging here so it gets called even if subclass
- // doesn't call through to superclass's implmeentation of each
- // of these methods below
- EventLog.writeEvent(50000, 0, item.getTitleCondensed());
- return onOptionsItemSelected(item);
-
- case Window.FEATURE_CONTEXT_MENU:
- EventLog.writeEvent(50000, 1, item.getTitleCondensed());
- return onContextItemSelected(item);
-
- default:
- return false;
- }
- }
-
- /**
- * Default implementation of
- * {@link android.view.Window.Callback#onPanelClosed(int, Menu)} for
- * activities. This calls through to {@link #onOptionsMenuClosed(Menu)}
- * method for the {@link android.view.Window#FEATURE_OPTIONS_PANEL} panel,
- * so that subclasses of Activity don't need to deal with feature codes.
- * For context menus ({@link Window#FEATURE_CONTEXT_MENU}), the
- * {@link #onContextMenuClosed(Menu)} will be called.
- */
- public void onPanelClosed(int featureId, Menu menu) {
- switch (featureId) {
- case Window.FEATURE_OPTIONS_PANEL:
- onOptionsMenuClosed(menu);
- break;
-
- case Window.FEATURE_CONTEXT_MENU:
- onContextMenuClosed(menu);
- break;
- }
- }
-
- /**
- * Initialize the contents of the Activity's standard options menu. You
- * should place your menu items in to <var>menu</var>.
- *
- * <p>This is only called once, the first time the options menu is
- * displayed. To update the menu every time it is displayed, see
- * {@link #onPrepareOptionsMenu}.
- *
- * <p>The default implementation populates the menu with standard system
- * menu items. These are placed in the {@link Menu#CATEGORY_SYSTEM} group so that
- * they will be correctly ordered with application-defined menu items.
- * Deriving classes should always call through to the base implementation.
- *
- * <p>You can safely hold on to <var>menu</var> (and any items created
- * from it), making modifications to it as desired, until the next
- * time onCreateOptionsMenu() is called.
- *
- * <p>When you add items to the menu, you can implement the Activity's
- * {@link #onOptionsItemSelected} method to handle them there.
- *
- * @param menu The options menu in which you place your items.
- *
- * @return You must return true for the menu to be displayed;
- * if you return false it will not be shown.
- *
- * @see #onPrepareOptionsMenu
- * @see #onOptionsItemSelected
- */
- public boolean onCreateOptionsMenu(Menu menu) {
- if (mParent != null) {
- return mParent.onCreateOptionsMenu(menu);
- }
- return true;
- }
-
- /**
- * Prepare the Screen's standard options menu to be displayed. This is
- * called right before the menu is shown, every time it is shown. You can
- * use this method to efficiently enable/disable items or otherwise
- * dynamically modify the contents.
- *
- * <p>The default implementation updates the system menu items based on the
- * activity's state. Deriving classes should always call through to the
- * base class implementation.
- *
- * @param menu The options menu as last shown or first initialized by
- * onCreateOptionsMenu().
- *
- * @return You must return true for the menu to be displayed;
- * if you return false it will not be shown.
- *
- * @see #onCreateOptionsMenu
- */
- public boolean onPrepareOptionsMenu(Menu menu) {
- if (mParent != null) {
- return mParent.onPrepareOptionsMenu(menu);
- }
- return true;
- }
-
- /**
- * This hook is called whenever an item in your options menu is selected.
- * The default implementation simply returns false to have the normal
- * processing happen (calling the item's Runnable or sending a message to
- * its Handler as appropriate). You can use this method for any items
- * for which you would like to do processing without those other
- * facilities.
- *
- * <p>Derived classes should call through to the base class for it to
- * perform the default menu handling.
- *
- * @param item The menu item that was selected.
- *
- * @return boolean Return false to allow normal menu processing to
- * proceed, true to consume it here.
- *
- * @see #onCreateOptionsMenu
- */
- public boolean onOptionsItemSelected(MenuItem item) {
- if (mParent != null) {
- return mParent.onOptionsItemSelected(item);
- }
- return false;
- }
-
- /**
- * This hook is called whenever the options menu is being closed (either by the user canceling
- * the menu with the back/menu button, or when an item is selected).
- *
- * @param menu The options menu as last shown or first initialized by
- * onCreateOptionsMenu().
- */
- public void onOptionsMenuClosed(Menu menu) {
- if (mParent != null) {
- mParent.onOptionsMenuClosed(menu);
- }
- }
-
- /**
- * Programmatically opens the options menu. If the options menu is already
- * open, this method does nothing.
- */
- public void openOptionsMenu() {
- mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null);
- }
-
- /**
- * Progammatically closes the options menu. If the options menu is already
- * closed, this method does nothing.
- */
- public void closeOptionsMenu() {
- mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
- }
-
- /**
- * Called when a context menu for the {@code view} is about to be shown.
- * Unlike {@link #onCreateOptionsMenu(Menu)}, this will be called every
- * time the context menu is about to be shown and should be populated for
- * the view (or item inside the view for {@link AdapterView} subclasses,
- * this can be found in the {@code menuInfo})).
- * <p>
- * Use {@link #onContextItemSelected(android.view.MenuItem)} to know when an
- * item has been selected.
- * <p>
- * It is not safe to hold onto the context menu after this method returns.
- * {@inheritDoc}
- */
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- }
-
- /**
- * Registers a context menu to be shown for the given view (multiple views
- * can show the context menu). This method will set the
- * {@link OnCreateContextMenuListener} on the view to this activity, so
- * {@link #onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} will be
- * called when it is time to show the context menu.
- *
- * @see #unregisterForContextMenu(View)
- * @param view The view that should show a context menu.
- */
- public void registerForContextMenu(View view) {
- view.setOnCreateContextMenuListener(this);
- }
-
- /**
- * Prevents a context menu to be shown for the given view. This method will remove the
- * {@link OnCreateContextMenuListener} on the view.
- *
- * @see #registerForContextMenu(View)
- * @param view The view that should stop showing a context menu.
- */
- public void unregisterForContextMenu(View view) {
- view.setOnCreateContextMenuListener(null);
- }
-
- /**
- * Programmatically opens the context menu for a particular {@code view}.
- * The {@code view} should have been added via
- * {@link #registerForContextMenu(View)}.
- *
- * @param view The view to show the context menu for.
- */
- public void openContextMenu(View view) {
- view.showContextMenu();
- }
-
- /**
- * Programmatically closes the most recently opened context menu, if showing.
- */
- public void closeContextMenu() {
- mWindow.closePanel(Window.FEATURE_CONTEXT_MENU);
- }
-
- /**
- * This hook is called whenever an item in a context menu is selected. The
- * default implementation simply returns false to have the normal processing
- * happen (calling the item's Runnable or sending a message to its Handler
- * as appropriate). You can use this method for any items for which you
- * would like to do processing without those other facilities.
- * <p>
- * Use {@link MenuItem#getMenuInfo()} to get extra information set by the
- * View that added this menu item.
- * <p>
- * Derived classes should call through to the base class for it to perform
- * the default menu handling.
- *
- * @param item The context menu item that was selected.
- * @return boolean Return false to allow normal context menu processing to
- * proceed, true to consume it here.
- */
- public boolean onContextItemSelected(MenuItem item) {
- if (mParent != null) {
- return mParent.onContextItemSelected(item);
- }
- return false;
- }
-
- /**
- * This hook is called whenever the context menu is being closed (either by
- * the user canceling the menu with the back/menu button, or when an item is
- * selected).
- *
- * @param menu The context menu that is being closed.
- */
- public void onContextMenuClosed(Menu menu) {
- if (mParent != null) {
- mParent.onContextMenuClosed(menu);
- }
- }
-
- /**
- * Callback for creating dialogs that are managed (saved and restored) for you
- * by the activity.
- *
- * If you use {@link #showDialog(int)}, the activity will call through to
- * this method the first time, and hang onto it thereafter. Any dialog
- * that is created by this method will automatically be saved and restored
- * for you, including whether it is showing.
- *
- * If you would like the activity to manage the saving and restoring dialogs
- * for you, you should override this method and handle any ids that are
- * passed to {@link #showDialog}.
- *
- * If you would like an opportunity to prepare your dialog before it is shown,
- * override {@link #onPrepareDialog(int, Dialog)}.
- *
- * @param id The id of the dialog.
- * @return The dialog
- *
- * @see #onPrepareDialog(int, Dialog)
- * @see #showDialog(int)
- * @see #dismissDialog(int)
- * @see #removeDialog(int)
- */
- protected Dialog onCreateDialog(int id) {
- return null;
- }
-
- /**
- * Provides an opportunity to prepare a managed dialog before it is being
- * shown.
- * <p>
- * Override this if you need to update a managed dialog based on the state
- * of the application each time it is shown. For example, a time picker
- * dialog might want to be updated with the current time. You should call
- * through to the superclass's implementation. The default implementation
- * will set this Activity as the owner activity on the Dialog.
- *
- * @param id The id of the managed dialog.
- * @param dialog The dialog.
- * @see #onCreateDialog(int)
- * @see #showDialog(int)
- * @see #dismissDialog(int)
- * @see #removeDialog(int)
- */
- protected void onPrepareDialog(int id, Dialog dialog) {
- dialog.setOwnerActivity(this);
- }
-
- /**
- * Show a dialog managed by this activity. A call to {@link #onCreateDialog(int)}
- * will be made with the same id the first time this is called for a given
- * id. From thereafter, the dialog will be automatically saved and restored.
- *
- * Each time a dialog is shown, {@link #onPrepareDialog(int, Dialog)} will
- * be made to provide an opportunity to do any timely preparation.
- *
- * @param id The id of the managed dialog.
- *
- * @see #onCreateDialog(int)
- * @see #onPrepareDialog(int, Dialog)
- * @see #dismissDialog(int)
- * @see #removeDialog(int)
- */
- public final void showDialog(int id) {
- if (mManagedDialogs == null) {
- mManagedDialogs = new SparseArray<Dialog>();
- }
- Dialog dialog = mManagedDialogs.get(id);
- if (dialog == null) {
- dialog = onCreateDialog(id);
- if (dialog == null) {
- throw new IllegalArgumentException("Activity#onCreateDialog did "
- + "not create a dialog for id " + id);
- }
- dialog.dispatchOnCreate(null);
- mManagedDialogs.put(id, dialog);
- }
-
- onPrepareDialog(id, dialog);
- dialog.show();
- }
-
- /**
- * Dismiss a dialog that was previously shown via {@link #showDialog(int)}.
- *
- * @param id The id of the managed dialog.
- *
- * @throws IllegalArgumentException if the id was not previously shown via
- * {@link #showDialog(int)}.
- *
- * @see #onCreateDialog(int)
- * @see #onPrepareDialog(int, Dialog)
- * @see #showDialog(int)
- * @see #removeDialog(int)
- */
- public final void dismissDialog(int id) {
- if (mManagedDialogs == null) {
- throw missingDialog(id);
-
- }
- final Dialog dialog = mManagedDialogs.get(id);
- if (dialog == null) {
- throw missingDialog(id);
- }
- dialog.dismiss();
- }
-
- /**
- * Creates an exception to throw if a user passed in a dialog id that is
- * unexpected.
- */
- private IllegalArgumentException missingDialog(int id) {
- return new IllegalArgumentException("no dialog with id " + id + " was ever "
- + "shown via Activity#showDialog");
- }
-
- /**
- * Removes any internal references to a dialog managed by this Activity.
- * If the dialog is showing, it will dismiss it as part of the clean up.
- *
- * This can be useful if you know that you will never show a dialog again and
- * want to avoid the overhead of saving and restoring it in the future.
- *
- * @param id The id of the managed dialog.
- *
- * @see #onCreateDialog(int)
- * @see #onPrepareDialog(int, Dialog)
- * @see #showDialog(int)
- * @see #dismissDialog(int)
- */
- public final void removeDialog(int id) {
-
- if (mManagedDialogs == null) {
- return;
- }
-
- final Dialog dialog = mManagedDialogs.get(id);
- if (dialog == null) {
- return;
- }
-
- dialog.dismiss();
- mManagedDialogs.remove(id);
- }
-
- /**
- * This hook is called when the user signals the desire to start a search.
- *
- * <p>You can use this function as a simple way to launch the search UI, in response to a
- * menu item, search button, or other widgets within your activity. Unless overidden,
- * calling this function is the same as calling:
- * <p>The default implementation simply calls
- * {@link #startSearch startSearch(null, false, null, false)}, launching a local search.
- *
- * <p>You can override this function to force global search, e.g. in response to a dedicated
- * search key, or to block search entirely (by simply returning false).
- *
- * @return Returns true if search launched, false if activity blocks it
- *
- * @see android.app.SearchManager
- */
- public boolean onSearchRequested() {
- startSearch(null, false, null, false);
- return true;
- }
-
- /**
- * This hook is called to launch the search UI.
- *
- * <p>It is typically called from onSearchRequested(), either directly from
- * Activity.onSearchRequested() or from an overridden version in any given
- * Activity. If your goal is simply to activate search, it is preferred to call
- * onSearchRequested(), which may have been overriden elsewhere in your Activity. If your goal
- * is to inject specific data such as context data, it is preferred to <i>override</i>
- * onSearchRequested(), so that any callers to it will benefit from the override.
- *
- * @param initialQuery Any non-null non-empty string will be inserted as
- * pre-entered text in the search query box.
- * @param selectInitialQuery If true, the intial query will be preselected, which means that
- * any further typing will replace it. This is useful for cases where an entire pre-formed
- * query is being inserted. If false, the selection point will be placed at the end of the
- * inserted query. This is useful when the inserted query is text that the user entered,
- * and the user would expect to be able to keep typing. <i>This parameter is only meaningful
- * if initialQuery is a non-empty string.</i>
- * @param appSearchData An application can insert application-specific
- * context here, in order to improve quality or specificity of its own
- * searches. This data will be returned with SEARCH intent(s). Null if
- * no extra data is required.
- * @param globalSearch If false, this will only launch the search that has been specifically
- * defined by the application (which is usually defined as a local search). If no default
- * search is defined in the current application or activity, no search will be launched.
- * If true, this will always launch a platform-global (e.g. web-based) search instead.
- *
- * @see android.app.SearchManager
- * @see #onSearchRequested
- */
- public void startSearch(String initialQuery, boolean selectInitialQuery,
- Bundle appSearchData, boolean globalSearch) {
- // activate the search manager and start it up!
- SearchManager searchManager = (SearchManager)
- getSystemService(Context.SEARCH_SERVICE);
- searchManager.startSearch(initialQuery, selectInitialQuery, getComponentName(),
- appSearchData, globalSearch);
- }
-
- /**
- * Request that key events come to this activity. Use this if your
- * activity has no views with focus, but the activity still wants
- * a chance to process key events.
- *
- * @see android.view.Window#takeKeyEvents
- */
- public void takeKeyEvents(boolean get) {
- getWindow().takeKeyEvents(get);
- }
-
- /**
- * Enable extended window features. This is a convenience for calling
- * {@link android.view.Window#requestFeature getWindow().requestFeature()}.
- *
- * @param featureId The desired feature as defined in
- * {@link android.view.Window}.
- * @return Returns true if the requested feature is supported and now
- * enabled.
- *
- * @see android.view.Window#requestFeature
- */
- public final boolean requestWindowFeature(int featureId) {
- return getWindow().requestFeature(featureId);
- }
-
- /**
- * Convenience for calling
- * {@link android.view.Window#setFeatureDrawableResource}.
- */
- public final void setFeatureDrawableResource(int featureId, int resId) {
- getWindow().setFeatureDrawableResource(featureId, resId);
- }
-
- /**
- * Convenience for calling
- * {@link android.view.Window#setFeatureDrawableUri}.
- */
- public final void setFeatureDrawableUri(int featureId, Uri uri) {
- getWindow().setFeatureDrawableUri(featureId, uri);
- }
-
- /**
- * Convenience for calling
- * {@link android.view.Window#setFeatureDrawable(int, Drawable)}.
- */
- public final void setFeatureDrawable(int featureId, Drawable drawable) {
- getWindow().setFeatureDrawable(featureId, drawable);
- }
-
- /**
- * Convenience for calling
- * {@link android.view.Window#setFeatureDrawableAlpha}.
- */
- public final void setFeatureDrawableAlpha(int featureId, int alpha) {
- getWindow().setFeatureDrawableAlpha(featureId, alpha);
- }
-
- /**
- * Convenience for calling
- * {@link android.view.Window#getLayoutInflater}.
- */
- public LayoutInflater getLayoutInflater() {
- return getWindow().getLayoutInflater();
- }
-
- /**
- * Returns a {@link MenuInflater} with this context.
- */
- public MenuInflater getMenuInflater() {
- return new MenuInflater(this);
- }
-
- @Override
- protected void onApplyThemeResource(Resources.Theme theme,
- int resid,
- boolean first)
- {
- if (mParent == null) {
- super.onApplyThemeResource(theme, resid, first);
- } else {
- try {
- theme.setTo(mParent.getTheme());
- } catch (Exception e) {
- // Empty
- }
- theme.applyStyle(resid, false);
- }
- }
-
- /**
- * Launch an activity for which you would like a result when it finished.
- * When this activity exits, your
- * onActivityResult() method will be called with the given requestCode.
- * Using a negative requestCode is the same as calling
- * {@link #startActivity} (the activity is not launched as a sub-activity).
- *
- * <p>Note that this method should only be used with Intent protocols
- * that are defined to return a result. In other protocols (such as
- * {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may
- * not get the result when you expect. For example, if the activity you
- * are launching uses the singleTask launch mode, it will not run in your
- * task and thus you will immediately receive a cancel result.
- *
- * <p>As a special case, if you call startActivityForResult() with a requestCode
- * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your
- * activity, then your window will not be displayed until a result is
- * returned back from the started activity. This is to avoid visible
- * flickering when redirecting to another activity.
- *
- * <p>This method throws {@link android.content.ActivityNotFoundException}
- * if there was no Activity found to run the given Intent.
- *
- * @param intent The intent to start.
- * @param requestCode If >= 0, this code will be returned in
- * onActivityResult() when the activity exits.
- *
- * @throws android.content.ActivityNotFoundException
- *
- * @see #startActivity
- */
- public void startActivityForResult(Intent intent, int requestCode) {
- if (mParent == null) {
- Instrumentation.ActivityResult ar =
- mInstrumentation.execStartActivity(
- this, mMainThread.getApplicationThread(), mToken, this,
- intent, requestCode);
- if (ar != null) {
- mMainThread.sendActivityResult(
- mToken, mEmbeddedID, requestCode, ar.getResultCode(),
- ar.getResultData());
- }
- if (requestCode >= 0) {
- // If this start is requesting a result, we can avoid making
- // the activity visible until the result is received. Setting
- // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
- // activity hidden during this time, to avoid flickering.
- // This can only be done when a result is requested because
- // that guarantees we will get information back when the
- // activity is finished, no matter what happens to it.
- mStartedActivity = true;
- }
- } else {
- mParent.startActivityFromChild(this, intent, requestCode);
- }
- }
-
- /**
- * Launch a new activity. You will not receive any information about when
- * the activity exits. This implementation overrides the base version,
- * providing information about
- * the activity performing the launch. Because of this additional
- * information, the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag is not
- * required; if not specified, the new activity will be added to the
- * task of the caller.
- *
- * <p>This method throws {@link android.content.ActivityNotFoundException}
- * if there was no Activity found to run the given Intent.
- *
- * @param intent The intent to start.
- *
- * @throws android.content.ActivityNotFoundException
- *
- * @see #startActivityForResult
- */
- @Override
- public void startActivity(Intent intent) {
- startActivityForResult(intent, -1);
- }
-
- /**
- * A special variation to launch an activity only if a new activity
- * instance is needed to handle the given Intent. In other words, this is
- * just like {@link #startActivityForResult(Intent, int)} except: if you are
- * using the {@link Intent#FLAG_ACTIVITY_SINGLE_TOP} flag, or
- * singleTask or singleTop
- * {@link android.R.styleable#AndroidManifestActivity_launchMode launchMode},
- * and the activity
- * that handles <var>intent</var> is the same as your currently running
- * activity, then a new instance is not needed. In this case, instead of
- * the normal behavior of calling {@link #onNewIntent} this function will
- * return and you can handle the Intent yourself.
- *
- * <p>This function can only be called from a top-level activity; if it is
- * called from a child activity, a runtime exception will be thrown.
- *
- * @param intent The intent to start.
- * @param requestCode If >= 0, this code will be returned in
- * onActivityResult() when the activity exits, as described in
- * {@link #startActivityForResult}.
- *
- * @return If a new activity was launched then true is returned; otherwise
- * false is returned and you must handle the Intent yourself.
- *
- * @see #startActivity
- * @see #startActivityForResult
- */
- public boolean startActivityIfNeeded(Intent intent, int requestCode) {
- if (mParent == null) {
- int result = IActivityManager.START_RETURN_INTENT_TO_CALLER;
- try {
- result = ActivityManagerNative.getDefault()
- .startActivity(mMainThread.getApplicationThread(),
- intent, intent.resolveTypeIfNeeded(
- getContentResolver()),
- null, 0,
- mToken, mEmbeddedID, requestCode, true, false);
- } catch (RemoteException e) {
- // Empty
- }
-
- Instrumentation.checkStartActivityResult(result, intent);
-
- if (requestCode >= 0) {
- // If this start is requesting a result, we can avoid making
- // the activity visible until the result is received. Setting
- // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
- // activity hidden during this time, to avoid flickering.
- // This can only be done when a result is requested because
- // that guarantees we will get information back when the
- // activity is finished, no matter what happens to it.
- mStartedActivity = true;
- }
- return result != IActivityManager.START_RETURN_INTENT_TO_CALLER;
- }
-
- throw new UnsupportedOperationException(
- "startActivityIfNeeded can only be called from a top-level activity");
- }
-
- /**
- * Special version of starting an activity, for use when you are replacing
- * other activity components. You can use this to hand the Intent off
- * to the next Activity that can handle it. You typically call this in
- * {@link #onCreate} with the Intent returned by {@link #getIntent}.
- *
- * @param intent The intent to dispatch to the next activity. For
- * correct behavior, this must be the same as the Intent that started
- * your own activity; the only changes you can make are to the extras
- * inside of it.
- *
- * @return Returns a boolean indicating whether there was another Activity
- * to start: true if there was a next activity to start, false if there
- * wasn't. In general, if true is returned you will then want to call
- * finish() on yourself.
- */
- public boolean startNextMatchingActivity(Intent intent) {
- if (mParent == null) {
- try {
- return ActivityManagerNative.getDefault()
- .startNextMatchingActivity(mToken, intent);
- } catch (RemoteException e) {
- // Empty
- }
- return false;
- }
-
- throw new UnsupportedOperationException(
- "startNextMatchingActivity can only be called from a top-level activity");
- }
-
- /**
- * This is called when a child activity of this one calls its
- * {@link #startActivity} or {@link #startActivityForResult} method.
- *
- * <p>This method throws {@link android.content.ActivityNotFoundException}
- * if there was no Activity found to run the given Intent.
- *
- * @param child The activity making the call.
- * @param intent The intent to start.
- * @param requestCode Reply request code. < 0 if reply is not requested.
- *
- * @throws android.content.ActivityNotFoundException
- *
- * @see #startActivity
- * @see #startActivityForResult
- */
- public void startActivityFromChild(Activity child, Intent intent,
- int requestCode) {
- Instrumentation.ActivityResult ar =
- mInstrumentation.execStartActivity(
- this, mMainThread.getApplicationThread(), mToken, child,
- intent, requestCode);
- if (ar != null) {
- mMainThread.sendActivityResult(
- mToken, child.mEmbeddedID, requestCode,
- ar.getResultCode(), ar.getResultData());
- }
- }
-
- /**
- * Call this to set the result that your activity will return to its
- * caller.
- *
- * @param resultCode The result code to propagate back to the originating
- * activity, often RESULT_CANCELED or RESULT_OK
- *
- * @see #RESULT_CANCELED
- * @see #RESULT_OK
- * @see #RESULT_FIRST_USER
- * @see #setResult(int, Intent)
- */
- public final void setResult(int resultCode) {
- synchronized (this) {
- mResultCode = resultCode;
- mResultData = null;
- }
- }
-
- /**
- * Call this to set the result that your activity will return to its
- * caller.
- *
- * @param resultCode The result code to propagate back to the originating
- * activity, often RESULT_CANCELED or RESULT_OK
- * @param data The data to propagate back to the originating activity.
- *
- * @see #RESULT_CANCELED
- * @see #RESULT_OK
- * @see #RESULT_FIRST_USER
- * @see #setResult(int)
- */
- public final void setResult(int resultCode, Intent data) {
- synchronized (this) {
- mResultCode = resultCode;
- mResultData = data;
- }
- }
-
- /**
- * Return the name of the package that invoked this activity. This is who
- * the data in {@link #setResult setResult()} will be sent to. You can
- * use this information to validate that the recipient is allowed to
- * receive the data.
- *
- * <p>Note: if the calling activity is not expecting a result (that is it
- * did not use the {@link #startActivityForResult}
- * form that includes a request code), then the calling package will be
- * null.
- *
- * @return The package of the activity that will receive your
- * reply, or null if none.
- */
- public String getCallingPackage() {
- try {
- return ActivityManagerNative.getDefault().getCallingPackage(mToken);
- } catch (RemoteException e) {
- return null;
- }
- }
-
- /**
- * Return the name of the activity that invoked this activity. This is
- * who the data in {@link #setResult setResult()} will be sent to. You
- * can use this information to validate that the recipient is allowed to
- * receive the data.
- *
- * <p>Note: if the calling activity is not expecting a result (that is it
- * did not use the {@link #startActivityForResult}
- * form that includes a request code), then the calling package will be
- * null.
- *
- * @return String The full name of the activity that will receive your
- * reply, or null if none.
- */
- public ComponentName getCallingActivity() {
- try {
- return ActivityManagerNative.getDefault().getCallingActivity(mToken);
- } catch (RemoteException e) {
- return null;
- }
- }
-
- /**
- * Control whether this activity's main window is visible. This is intended
- * only for the special case of an activity that is not going to show a
- * UI itself, but can't just finish prior to onResume() because it needs
- * to wait for a service binding or such. Setting this to false allows
- * you to prevent your UI from being shown during that time.
- *
- * <p>The default value for this is taken from the
- * {@link android.R.attr#windowNoDisplay} attribute of the activity's theme.
- */
- public void setVisible(boolean visible) {
- if (mVisibleFromClient != visible) {
- mVisibleFromClient = visible;
- if (mVisibleFromServer) {
- if (visible) makeVisible();
- else mDecor.setVisibility(View.INVISIBLE);
- }
- }
- }
-
- void makeVisible() {
- if (!mWindowAdded) {
- ViewManager wm = getWindowManager();
- wm.addView(mDecor, getWindow().getAttributes());
- mWindowAdded = true;
- }
- mDecor.setVisibility(View.VISIBLE);
- }
-
- /**
- * Check to see whether this activity is in the process of finishing,
- * either because you called {@link #finish} on it or someone else
- * has requested that it finished. This is often used in
- * {@link #onPause} to determine whether the activity is simply pausing or
- * completely finishing.
- *
- * @return If the activity is finishing, returns true; else returns false.
- *
- * @see #finish
- */
- public boolean isFinishing() {
- return mFinished;
- }
-
- /**
- * Call this when your activity is done and should be closed. The
- * ActivityResult is propagated back to whoever launched you via
- * onActivityResult().
- */
- public void finish() {
- if (mParent == null) {
- int resultCode;
- Intent resultData;
- synchronized (this) {
- resultCode = mResultCode;
- resultData = mResultData;
- }
- if (Config.LOGV) Log.v(TAG, "Finishing self: token=" + mToken);
- try {
- if (ActivityManagerNative.getDefault()
- .finishActivity(mToken, resultCode, resultData)) {
- mFinished = true;
- }
- } catch (RemoteException e) {
- // Empty
- }
- } else {
- mParent.finishFromChild(this);
- }
- }
-
- /**
- * This is called when a child activity of this one calls its
- * {@link #finish} method. The default implementation simply calls
- * finish() on this activity (the parent), finishing the entire group.
- *
- * @param child The activity making the call.
- *
- * @see #finish
- */
- public void finishFromChild(Activity child) {
- finish();
- }
-
- /**
- * Force finish another activity that you had previously started with
- * {@link #startActivityForResult}.
- *
- * @param requestCode The request code of the activity that you had
- * given to startActivityForResult(). If there are multiple
- * activities started with this request code, they
- * will all be finished.
- */
- public void finishActivity(int requestCode) {
- if (mParent == null) {
- try {
- ActivityManagerNative.getDefault()
- .finishSubActivity(mToken, mEmbeddedID, requestCode);
- } catch (RemoteException e) {
- // Empty
- }
- } else {
- mParent.finishActivityFromChild(this, requestCode);
- }
- }
-
- /**
- * This is called when a child activity of this one calls its
- * finishActivity().
- *
- * @param child The activity making the call.
- * @param requestCode Request code that had been used to start the
- * activity.
- */
- public void finishActivityFromChild(Activity child, int requestCode) {
- try {
- ActivityManagerNative.getDefault()
- .finishSubActivity(mToken, child.mEmbeddedID, requestCode);
- } catch (RemoteException e) {
- // Empty
- }
- }
-
- /**
- * Called when an activity you launched exits, giving you the requestCode
- * you started it with, the resultCode it returned, and any additional
- * data from it. The <var>resultCode</var> will be
- * {@link #RESULT_CANCELED} if the activity explicitly returned that,
- * didn't return any result, or crashed during its operation.
- *
- * <p>You will receive this call immediately before onResume() when your
- * activity is re-starting.
- *
- * @param requestCode The integer request code originally supplied to
- * startActivityForResult(), allowing you to identify who this
- * result came from.
- * @param resultCode The integer result code returned by the child activity
- * through its setResult().
- * @param data An Intent, which can return result data to the caller
- * (various data can be attached to Intent "extras").
- *
- * @see #startActivityForResult
- * @see #createPendingResult
- * @see #setResult(int)
- */
- protected void onActivityResult(int requestCode, int resultCode,
- Intent data) {
- }
-
- /**
- * Create a new PendingIntent object which you can hand to others
- * for them to use to send result data back to your
- * {@link #onActivityResult} callback. The created object will be either
- * one-shot (becoming invalid after a result is sent back) or multiple
- * (allowing any number of results to be sent through it).
- *
- * @param requestCode Private request code for the sender that will be
- * associated with the result data when it is returned. The sender can not
- * modify this value, allowing you to identify incoming results.
- * @param data Default data to supply in the result, which may be modified
- * by the sender.
- * @param flags May be {@link PendingIntent#FLAG_ONE_SHOT PendingIntent.FLAG_ONE_SHOT},
- * {@link PendingIntent#FLAG_NO_CREATE PendingIntent.FLAG_NO_CREATE},
- * {@link PendingIntent#FLAG_CANCEL_CURRENT PendingIntent.FLAG_CANCEL_CURRENT},
- * {@link PendingIntent#FLAG_UPDATE_CURRENT PendingIntent.FLAG_UPDATE_CURRENT},
- * or any of the flags as supported by
- * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
- * of the intent that can be supplied when the actual send happens.
- *
- * @return Returns an existing or new PendingIntent matching the given
- * parameters. May return null only if
- * {@link PendingIntent#FLAG_NO_CREATE PendingIntent.FLAG_NO_CREATE} has been
- * supplied.
- *
- * @see PendingIntent
- */
- public PendingIntent createPendingResult(int requestCode, Intent data,
- int flags) {
- String packageName = getPackageName();
- try {
- IIntentSender target =
- ActivityManagerNative.getDefault().getIntentSender(
- IActivityManager.INTENT_SENDER_ACTIVITY_RESULT, packageName,
- mParent == null ? mToken : mParent.mToken,
- mEmbeddedID, requestCode, data, null, flags);
- return target != null ? new PendingIntent(target) : null;
- } catch (RemoteException e) {
- // Empty
- }
- return null;
- }
-
- /**
- * Change the desired orientation of this activity. If the activity
- * is currently in the foreground or otherwise impacting the screen
- * orientation, the screen will immediately be changed (possibly causing
- * the activity to be restarted). Otherwise, this will be used the next
- * time the activity is visible.
- *
- * @param requestedOrientation An orientation constant as used in
- * {@link ActivityInfo#screenOrientation ActivityInfo.screenOrientation}.
- */
- public void setRequestedOrientation(int requestedOrientation) {
- if (mParent == null) {
- try {
- ActivityManagerNative.getDefault().setRequestedOrientation(
- mToken, requestedOrientation);
- } catch (RemoteException e) {
- // Empty
- }
- } else {
- mParent.setRequestedOrientation(requestedOrientation);
- }
- }
-
- /**
- * Return the current requested orientation of the activity. This will
- * either be the orientation requested in its component's manifest, or
- * the last requested orientation given to
- * {@link #setRequestedOrientation(int)}.
- *
- * @return Returns an orientation constant as used in
- * {@link ActivityInfo#screenOrientation ActivityInfo.screenOrientation}.
- */
- public int getRequestedOrientation() {
- if (mParent == null) {
- try {
- return ActivityManagerNative.getDefault()
- .getRequestedOrientation(mToken);
- } catch (RemoteException e) {
- // Empty
- }
- } else {
- return mParent.getRequestedOrientation();
- }
- return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
- }
-
- /**
- * Return the identifier of the task this activity is in. This identifier
- * will remain the same for the lifetime of the activity.
- *
- * @return Task identifier, an opaque integer.
- */
- public int getTaskId() {
- try {
- return ActivityManagerNative.getDefault()
- .getTaskForActivity(mToken, false);
- } catch (RemoteException e) {
- return -1;
- }
- }
-
- /**
- * Return whether this activity is the root of a task. The root is the
- * first activity in a task.
- *
- * @return True if this is the root activity, else false.
- */
- public boolean isTaskRoot() {
- try {
- return ActivityManagerNative.getDefault()
- .getTaskForActivity(mToken, true) >= 0;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- /**
- * Move the task containing this activity to the back of the activity
- * stack. The activity's order within the task is unchanged.
- *
- * @param nonRoot If false then this only works if the activity is the root
- * of a task; if true it will work for any activity in
- * a task.
- *
- * @return If the task was moved (or it was already at the
- * back) true is returned, else false.
- */
- public boolean moveTaskToBack(boolean nonRoot) {
- try {
- return ActivityManagerNative.getDefault().moveActivityTaskToBack(
- mToken, nonRoot);
- } catch (RemoteException e) {
- // Empty
- }
- return false;
- }
-
- /**
- * Returns class name for this activity with the package prefix removed.
- * This is the default name used to read and write settings.
- *
- * @return The local class name.
- */
- public String getLocalClassName() {
- final String pkg = getPackageName();
- final String cls = mComponent.getClassName();
- int packageLen = pkg.length();
- if (!cls.startsWith(pkg) || cls.length() <= packageLen
- || cls.charAt(packageLen) != '.') {
- return cls;
- }
- return cls.substring(packageLen+1);
- }
-
- /**
- * Returns complete component name of this activity.
- *
- * @return Returns the complete component name for this activity
- */
- public ComponentName getComponentName()
- {
- return mComponent;
- }
-
- /**
- * Retrieve a {@link SharedPreferences} object for accessing preferences
- * that are private to this activity. This simply calls the underlying
- * {@link #getSharedPreferences(String, int)} method by passing in this activity's
- * class name as the preferences name.
- *
- * @param mode Operating mode. Use {@link #MODE_PRIVATE} for the default
- * operation, {@link #MODE_WORLD_READABLE} and
- * {@link #MODE_WORLD_WRITEABLE} to control permissions.
- *
- * @return Returns the single SharedPreferences instance that can be used
- * to retrieve and modify the preference values.
- */
- public SharedPreferences getPreferences(int mode) {
- return getSharedPreferences(getLocalClassName(), mode);
- }
-
- @Override
- public Object getSystemService(String name) {
- if (getBaseContext() == null) {
- throw new IllegalStateException(
- "System services not available to Activities before onCreate()");
- }
-
- if (WINDOW_SERVICE.equals(name)) {
- return mWindowManager;
- }
- return super.getSystemService(name);
- }
-
- /**
- * Change the title associated with this activity. If this is a
- * top-level activity, the title for its window will change. If it
- * is an embedded activity, the parent can do whatever it wants
- * with it.
- */
- public void setTitle(CharSequence title) {
- mTitle = title;
- onTitleChanged(title, mTitleColor);
-
- if (mParent != null) {
- mParent.onChildTitleChanged(this, title);
- }
- }
-
- /**
- * Change the title associated with this activity. If this is a
- * top-level activity, the title for its window will change. If it
- * is an embedded activity, the parent can do whatever it wants
- * with it.
- */
- public void setTitle(int titleId) {
- setTitle(getText(titleId));
- }
-
- public void setTitleColor(int textColor) {
- mTitleColor = textColor;
- onTitleChanged(mTitle, textColor);
- }
-
- public final CharSequence getTitle() {
- return mTitle;
- }
-
- public final int getTitleColor() {
- return mTitleColor;
- }
-
- protected void onTitleChanged(CharSequence title, int color) {
- if (mTitleReady) {
- final Window win = getWindow();
- if (win != null) {
- win.setTitle(title);
- if (color != 0) {
- win.setTitleColor(color);
- }
- }
- }
- }
-
- protected void onChildTitleChanged(Activity childActivity, CharSequence title) {
- }
-
- /**
- * Sets the visibility of the progress bar in the title.
- * <p>
- * In order for the progress bar to be shown, the feature must be requested
- * via {@link #requestWindowFeature(int)}.
- *
- * @param visible Whether to show the progress bars in the title.
- */
- public final void setProgressBarVisibility(boolean visible) {
- getWindow().setFeatureInt(Window.FEATURE_PROGRESS, visible ? Window.PROGRESS_VISIBILITY_ON :
- Window.PROGRESS_VISIBILITY_OFF);
- }
-
- /**
- * Sets the visibility of the indeterminate progress bar in the title.
- * <p>
- * In order for the progress bar to be shown, the feature must be requested
- * via {@link #requestWindowFeature(int)}.
- *
- * @param visible Whether to show the progress bars in the title.
- */
- public final void setProgressBarIndeterminateVisibility(boolean visible) {
- getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS,
- visible ? Window.PROGRESS_VISIBILITY_ON : Window.PROGRESS_VISIBILITY_OFF);
- }
-
- /**
- * Sets whether the horizontal progress bar in the title should be indeterminate (the circular
- * is always indeterminate).
- * <p>
- * In order for the progress bar to be shown, the feature must be requested
- * via {@link #requestWindowFeature(int)}.
- *
- * @param indeterminate Whether the horizontal progress bar should be indeterminate.
- */
- public final void setProgressBarIndeterminate(boolean indeterminate) {
- getWindow().setFeatureInt(Window.FEATURE_PROGRESS,
- indeterminate ? Window.PROGRESS_INDETERMINATE_ON : Window.PROGRESS_INDETERMINATE_OFF);
- }
-
- /**
- * Sets the progress for the progress bars in the title.
- * <p>
- * In order for the progress bar to be shown, the feature must be requested
- * via {@link #requestWindowFeature(int)}.
- *
- * @param progress The progress for the progress bar. Valid ranges are from
- * 0 to 10000 (both inclusive). If 10000 is given, the progress
- * bar will be completely filled and will fade out.
- */
- public final void setProgress(int progress) {
- getWindow().setFeatureInt(Window.FEATURE_PROGRESS, progress + Window.PROGRESS_START);
- }
-
- /**
- * Sets the secondary progress for the progress bar in the title. This
- * progress is drawn between the primary progress (set via
- * {@link #setProgress(int)} and the background. It can be ideal for media
- * scenarios such as showing the buffering progress while the default
- * progress shows the play progress.
- * <p>
- * In order for the progress bar to be shown, the feature must be requested
- * via {@link #requestWindowFeature(int)}.
- *
- * @param secondaryProgress The secondary progress for the progress bar. Valid ranges are from
- * 0 to 10000 (both inclusive).
- */
- public final void setSecondaryProgress(int secondaryProgress) {
- getWindow().setFeatureInt(Window.FEATURE_PROGRESS,
- secondaryProgress + Window.PROGRESS_SECONDARY_START);
- }
-
- /**
- * Suggests an audio stream whose volume should be changed by the hardware
- * volume controls.
- * <p>
- * The suggested audio stream will be tied to the window of this Activity.
- * If the Activity is switched, the stream set here is no longer the
- * suggested stream. The client does not need to save and restore the old
- * suggested stream value in onPause and onResume.
- *
- * @param streamType The type of the audio stream whose volume should be
- * changed by the hardware volume controls. It is not guaranteed that
- * the hardware volume controls will always change this stream's
- * volume (for example, if a call is in progress, its stream's volume
- * may be changed instead). To reset back to the default, use
- * {@link AudioManager#USE_DEFAULT_STREAM_TYPE}.
- */
- public final void setVolumeControlStream(int streamType) {
- getWindow().setVolumeControlStream(streamType);
- }
-
- /**
- * Gets the suggested audio stream whose volume should be changed by the
- * harwdare volume controls.
- *
- * @return The suggested audio stream type whose volume should be changed by
- * the hardware volume controls.
- * @see #setVolumeControlStream(int)
- */
- public final int getVolumeControlStream() {
- return getWindow().getVolumeControlStream();
- }
-
- /**
- * Runs the specified action on the UI thread. If the current thread is the UI
- * thread, then the action is executed immediately. If the current thread is
- * not the UI thread, the action is posted to the event queue of the UI thread.
- *
- * @param action the action to run on the UI thread
- */
- public final void runOnUiThread(Runnable action) {
- if (Thread.currentThread() != mUiThread) {
- mHandler.post(action);
- } else {
- action.run();
- }
- }
-
- /**
- * Stub implementation of {@link android.view.LayoutInflater.Factory#onCreateView} used when
- * inflating with the LayoutInflater returned by {@link #getSystemService}. This
- * implementation simply returns null for all view names.
- *
- * @see android.view.LayoutInflater#createView
- * @see android.view.Window#getLayoutInflater
- */
- public View onCreateView(String name, Context context, AttributeSet attrs) {
- return null;
- }
-
- // ------------------ Internal API ------------------
-
- final void setParent(Activity parent) {
- mParent = parent;
- }
-
- final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token,
- Application application, Intent intent, ActivityInfo info, CharSequence title,
- Activity parent, String id, Object lastNonConfigurationInstance,
- Configuration config) {
- attach(context, aThread, instr, token, application, intent, info, title, parent, id,
- lastNonConfigurationInstance, null, config);
- }
-
- final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token,
- Application application, Intent intent, ActivityInfo info, CharSequence title,
- Activity parent, String id, Object lastNonConfigurationInstance,
- HashMap<String,Object> lastNonConfigurationChildInstances, Configuration config) {
- attachBaseContext(context);
-
- mWindow = PolicyManager.makeNewWindow(this);
- mWindow.setCallback(this);
- if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
- mWindow.setSoftInputMode(info.softInputMode);
- }
- mUiThread = Thread.currentThread();
-
- mMainThread = aThread;
- mInstrumentation = instr;
- mToken = token;
- mApplication = application;
- mIntent = intent;
- mComponent = intent.getComponent();
- mActivityInfo = info;
- mTitle = title;
- mParent = parent;
- mEmbeddedID = id;
- mLastNonConfigurationInstance = lastNonConfigurationInstance;
- mLastNonConfigurationChildInstances = lastNonConfigurationChildInstances;
-
- mWindow.setWindowManager(null, mToken, mComponent.flattenToString());
- if (mParent != null) {
- mWindow.setContainer(mParent.getWindow());
- }
- mWindowManager = mWindow.getWindowManager();
- mCurrentConfig = config;
- }
-
- final IBinder getActivityToken() {
- return mParent != null ? mParent.getActivityToken() : mToken;
- }
-
- final void performStart() {
- mCalled = false;
- mInstrumentation.callActivityOnStart(this);
- if (!mCalled) {
- throw new SuperNotCalledException(
- "Activity " + mComponent.toShortString() +
- " did not call through to super.onStart()");
- }
- }
-
- final void performRestart() {
- final int N = mManagedCursors.size();
- for (int i=0; i<N; i++) {
- ManagedCursor mc = mManagedCursors.get(i);
- if (mc.mReleased || mc.mUpdated) {
- mc.mCursor.requery();
- mc.mReleased = false;
- mc.mUpdated = false;
- }
- }
-
- if (mStopped) {
- mStopped = false;
- mCalled = false;
- mInstrumentation.callActivityOnRestart(this);
- if (!mCalled) {
- throw new SuperNotCalledException(
- "Activity " + mComponent.toShortString() +
- " did not call through to super.onRestart()");
- }
- performStart();
- }
- }
-
- final void performResume() {
- performRestart();
-
- mLastNonConfigurationInstance = null;
-
- // First call onResume() -before- setting mResumed, so we don't
- // send out any status bar / menu notifications the client makes.
- mCalled = false;
- mInstrumentation.callActivityOnResume(this);
- if (!mCalled) {
- throw new SuperNotCalledException(
- "Activity " + mComponent.toShortString() +
- " did not call through to super.onResume()");
- }
-
- // Now really resume, and install the current status bar and menu.
- mResumed = true;
- mCalled = false;
- onPostResume();
- if (!mCalled) {
- throw new SuperNotCalledException(
- "Activity " + mComponent.toShortString() +
- " did not call through to super.onPostResume()");
- }
- }
-
- final void performPause() {
- onPause();
- }
-
- final void performUserLeaving() {
- onUserInteraction();
- onUserLeaveHint();
- }
-
- final void performStop() {
- if (!mStopped) {
- if (mWindow != null) {
- mWindow.closeAllPanels();
- }
-
- mCalled = false;
- mInstrumentation.callActivityOnStop(this);
- if (!mCalled) {
- throw new SuperNotCalledException(
- "Activity " + mComponent.toShortString() +
- " did not call through to super.onStop()");
- }
-
- final int N = mManagedCursors.size();
- for (int i=0; i<N; i++) {
- ManagedCursor mc = mManagedCursors.get(i);
- if (!mc.mReleased) {
- mc.mCursor.deactivate();
- mc.mReleased = true;
- }
- }
-
- mStopped = true;
- }
- mResumed = false;
- }
-
- final boolean isResumed() {
- return mResumed;
- }
-
- void dispatchActivityResult(String who, int requestCode,
- int resultCode, Intent data) {
- if (Config.LOGV) Log.v(
- TAG, "Dispatching result: who=" + who + ", reqCode=" + requestCode
- + ", resCode=" + resultCode + ", data=" + data);
- if (who == null) {
- onActivityResult(requestCode, resultCode, data);
- }
- }
-}
diff --git a/core/java/android/app/ActivityGroup.java b/core/java/android/app/ActivityGroup.java
deleted file mode 100644
index f1216f9..0000000
--- a/core/java/android/app/ActivityGroup.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import java.util.HashMap;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-
-/**
- * A screen that contains and runs multiple embedded activities.
- */
-public class ActivityGroup extends Activity {
- private static final String TAG = "ActivityGroup";
- private static final String STATES_KEY = "android:states";
- static final String PARENT_NON_CONFIG_INSTANCE_KEY = "android:parent_non_config_instance";
-
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected LocalActivityManager mLocalActivityManager;
-
- public ActivityGroup() {
- this(true);
- }
-
- public ActivityGroup(boolean singleActivityMode) {
- mLocalActivityManager = new LocalActivityManager(this, singleActivityMode);
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Bundle states = savedInstanceState != null
- ? (Bundle) savedInstanceState.getBundle(STATES_KEY) : null;
- mLocalActivityManager.dispatchCreate(states);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- mLocalActivityManager.dispatchResume();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- Bundle state = mLocalActivityManager.saveInstanceState();
- if (state != null) {
- outState.putBundle(STATES_KEY, state);
- }
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- mLocalActivityManager.dispatchPause(isFinishing());
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- mLocalActivityManager.dispatchStop();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mLocalActivityManager.dispatchDestroy(isFinishing());
- }
-
- /**
- * Returns a HashMap mapping from child activity ids to the return values
- * from calls to their onRetainNonConfigurationInstance methods.
- *
- * {@hide}
- */
- @Override
- public HashMap<String,Object> onRetainNonConfigurationChildInstances() {
- return mLocalActivityManager.dispatchRetainNonConfigurationInstance();
- }
-
- public Activity getCurrentActivity() {
- return mLocalActivityManager.getCurrentActivity();
- }
-
- public final LocalActivityManager getLocalActivityManager() {
- return mLocalActivityManager;
- }
-
- @Override
- void dispatchActivityResult(String who, int requestCode, int resultCode,
- Intent data) {
- if (who != null) {
- Activity act = mLocalActivityManager.getActivity(who);
- /*
- if (Config.LOGV) Log.v(
- TAG, "Dispatching result: who=" + who + ", reqCode=" + requestCode
- + ", resCode=" + resultCode + ", data=" + data
- + ", rec=" + rec);
- */
- if (act != null) {
- act.onActivityResult(requestCode, resultCode, data);
- return;
- }
- }
- super.dispatchActivityResult(who, requestCode, resultCode, data);
- }
-}
-
-
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
deleted file mode 100644
index 07520c9d..0000000
--- a/core/java/android/app/ActivityManager.java
+++ /dev/null
@@ -1,761 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ConfigurationInfo;
-import android.content.pm.IPackageDataObserver;
-import android.graphics.Bitmap;
-import android.os.RemoteException;
-import android.os.Handler;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import java.util.List;
-
-/**
- * Interact with the overall activities running in the system.
- */
-public class ActivityManager {
- private static String TAG = "ActivityManager";
- private static boolean DEBUG = false;
- private static boolean localLOGV = DEBUG || android.util.Config.LOGV;
-
- private final Context mContext;
- private final Handler mHandler;
-
- /*package*/ ActivityManager(Context context, Handler handler) {
- mContext = context;
- mHandler = handler;
- }
-
- /**
- * Information you can retrieve about tasks that the user has most recently
- * started or visited.
- */
- public static class RecentTaskInfo implements Parcelable {
- /**
- * If this task is currently running, this is the identifier for it.
- * If it is not running, this will be -1.
- */
- public int id;
-
- /**
- * The original Intent used to launch the task. You can use this
- * Intent to re-launch the task (if it is no longer running) or bring
- * the current task to the front.
- */
- public Intent baseIntent;
-
- /**
- * If this task was started from an alias, this is the actual
- * activity component that was initially started; the component of
- * the baseIntent in this case is the name of the actual activity
- * implementation that the alias referred to. Otherwise, this is null.
- */
- public ComponentName origActivity;
-
- public RecentTaskInfo() {
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(id);
- if (baseIntent != null) {
- dest.writeInt(1);
- baseIntent.writeToParcel(dest, 0);
- } else {
- dest.writeInt(0);
- }
- ComponentName.writeToParcel(origActivity, dest);
- }
-
- public void readFromParcel(Parcel source) {
- id = source.readInt();
- if (source.readInt() != 0) {
- baseIntent = Intent.CREATOR.createFromParcel(source);
- } else {
- baseIntent = null;
- }
- origActivity = ComponentName.readFromParcel(source);
- }
-
- public static final Creator<RecentTaskInfo> CREATOR
- = new Creator<RecentTaskInfo>() {
- public RecentTaskInfo createFromParcel(Parcel source) {
- return new RecentTaskInfo(source);
- }
- public RecentTaskInfo[] newArray(int size) {
- return new RecentTaskInfo[size];
- }
- };
-
- private RecentTaskInfo(Parcel source) {
- readFromParcel(source);
- }
- }
-
- /**
- * Flag for use with {@link #getRecentTasks}: return all tasks, even those
- * that have set their
- * {@link android.content.Intent#FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS} flag.
- */
- public static final int RECENT_WITH_EXCLUDED = 0x0001;
-
- /**
- * Return a list of the tasks that the user has recently launched, with
- * the most recent being first and older ones after in order.
- *
- * @param maxNum The maximum number of entries to return in the list. The
- * actual number returned may be smaller, depending on how many tasks the
- * user has started and the maximum number the system can remember.
- *
- * @return Returns a list of RecentTaskInfo records describing each of
- * the recent tasks.
- *
- * @throws SecurityException Throws SecurityException if the caller does
- * not hold the {@link android.Manifest.permission#GET_TASKS} permission.
- */
- public List<RecentTaskInfo> getRecentTasks(int maxNum, int flags)
- throws SecurityException {
- try {
- return ActivityManagerNative.getDefault().getRecentTasks(maxNum,
- flags);
- } catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return null;
- }
- }
-
- /**
- * Information you can retrieve about a particular task that is currently
- * "running" in the system. Note that a running task does not mean the
- * given task actual has a process it is actively running in; it simply
- * means that the user has gone to it and never closed it, but currently
- * the system may have killed its process and is only holding on to its
- * last state in order to restart it when the user returns.
- */
- public static class RunningTaskInfo implements Parcelable {
- /**
- * A unique identifier for this task.
- */
- public int id;
-
- /**
- * The component launched as the first activity in the task. This can
- * be considered the "application" of this task.
- */
- public ComponentName baseActivity;
-
- /**
- * The activity component at the top of the history stack of the task.
- * This is what the user is currently doing.
- */
- public ComponentName topActivity;
-
- /**
- * Thumbnail representation of the task's current state.
- */
- public Bitmap thumbnail;
-
- /**
- * Description of the task's current state.
- */
- public CharSequence description;
-
- /**
- * Number of activities in this task.
- */
- public int numActivities;
-
- /**
- * Number of activities that are currently running (not stopped
- * and persisted) in this task.
- */
- public int numRunning;
-
- public RunningTaskInfo() {
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(id);
- ComponentName.writeToParcel(baseActivity, dest);
- ComponentName.writeToParcel(topActivity, dest);
- if (thumbnail != null) {
- dest.writeInt(1);
- thumbnail.writeToParcel(dest, 0);
- } else {
- dest.writeInt(0);
- }
- TextUtils.writeToParcel(description, dest,
- Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- dest.writeInt(numActivities);
- dest.writeInt(numRunning);
- }
-
- public void readFromParcel(Parcel source) {
- id = source.readInt();
- baseActivity = ComponentName.readFromParcel(source);
- topActivity = ComponentName.readFromParcel(source);
- if (source.readInt() != 0) {
- thumbnail = Bitmap.CREATOR.createFromParcel(source);
- } else {
- thumbnail = null;
- }
- description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- numActivities = source.readInt();
- numRunning = source.readInt();
- }
-
- public static final Creator<RunningTaskInfo> CREATOR = new Creator<RunningTaskInfo>() {
- public RunningTaskInfo createFromParcel(Parcel source) {
- return new RunningTaskInfo(source);
- }
- public RunningTaskInfo[] newArray(int size) {
- return new RunningTaskInfo[size];
- }
- };
-
- private RunningTaskInfo(Parcel source) {
- readFromParcel(source);
- }
- }
-
- /**
- * Return a list of the tasks that are currently running, with
- * the most recent being first and older ones after in order. Note that
- * "running" does not mean any of the task's code is currently loaded or
- * activity -- the task may have been frozen by the system, so that it
- * can be restarted in its previous state when next brought to the
- * foreground.
- *
- * @param maxNum The maximum number of entries to return in the list. The
- * actual number returned may be smaller, depending on how many tasks the
- * user has started.
- *
- * @return Returns a list of RunningTaskInfo records describing each of
- * the running tasks.
- *
- * @throws SecurityException Throws SecurityException if the caller does
- * not hold the {@link android.Manifest.permission#GET_TASKS} permission.
- */
- public List<RunningTaskInfo> getRunningTasks(int maxNum)
- throws SecurityException {
- try {
- return (List<RunningTaskInfo>)ActivityManagerNative.getDefault()
- .getTasks(maxNum, 0, null);
- } catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return null;
- }
- }
-
- /**
- * Information you can retrieve about a particular Service that is
- * currently running in the system.
- */
- public static class RunningServiceInfo implements Parcelable {
- /**
- * The service component.
- */
- public ComponentName service;
-
- /**
- * If non-zero, this is the process the service is running in.
- */
- public int pid;
-
- /**
- * The name of the process this service runs in.
- */
- public String process;
-
- /**
- * Set to true if the service has asked to run as a foreground process.
- */
- public boolean foreground;
-
- /**
- * The time when the service was first made activity, either by someone
- * starting or binding to it.
- */
- public long activeSince;
-
- /**
- * Set to true if this service has been explicitly started.
- */
- public boolean started;
-
- /**
- * Number of clients connected to the service.
- */
- public int clientCount;
-
- /**
- * Number of times the service's process has crashed while the service
- * is running.
- */
- public int crashCount;
-
- /**
- * The time when there was last activity in the service (either
- * explicit requests to start it or clients binding to it).
- */
- public long lastActivityTime;
-
- /**
- * If non-zero, this service is not currently running, but scheduled to
- * restart at the given time.
- */
- public long restarting;
-
- public RunningServiceInfo() {
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- ComponentName.writeToParcel(service, dest);
- dest.writeInt(pid);
- dest.writeString(process);
- dest.writeInt(foreground ? 1 : 0);
- dest.writeLong(activeSince);
- dest.writeInt(started ? 1 : 0);
- dest.writeInt(clientCount);
- dest.writeInt(crashCount);
- dest.writeLong(lastActivityTime);
- dest.writeLong(restarting);
- }
-
- public void readFromParcel(Parcel source) {
- service = ComponentName.readFromParcel(source);
- pid = source.readInt();
- process = source.readString();
- foreground = source.readInt() != 0;
- activeSince = source.readLong();
- started = source.readInt() != 0;
- clientCount = source.readInt();
- crashCount = source.readInt();
- lastActivityTime = source.readLong();
- restarting = source.readLong();
- }
-
- public static final Creator<RunningServiceInfo> CREATOR = new Creator<RunningServiceInfo>() {
- public RunningServiceInfo createFromParcel(Parcel source) {
- return new RunningServiceInfo(source);
- }
- public RunningServiceInfo[] newArray(int size) {
- return new RunningServiceInfo[size];
- }
- };
-
- private RunningServiceInfo(Parcel source) {
- readFromParcel(source);
- }
- }
-
- /**
- * Return a list of the services that are currently running.
- *
- * @param maxNum The maximum number of entries to return in the list. The
- * actual number returned may be smaller, depending on how many services
- * are running.
- *
- * @return Returns a list of RunningServiceInfo records describing each of
- * the running tasks.
- */
- public List<RunningServiceInfo> getRunningServices(int maxNum)
- throws SecurityException {
- try {
- return (List<RunningServiceInfo>)ActivityManagerNative.getDefault()
- .getServices(maxNum, 0);
- } catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return null;
- }
- }
-
- /**
- * Information you can retrieve about the available memory through
- * {@link ActivityManager#getMemoryInfo}.
- */
- public static class MemoryInfo implements Parcelable {
- /**
- * The total available memory on the system. This number should not
- * be considered absolute: due to the nature of the kernel, a significant
- * portion of this memory is actually in use and needed for the overall
- * system to run well.
- */
- public long availMem;
-
- /**
- * The threshold of {@link #availMem} at which we consider memory to be
- * low and start killing background services and other non-extraneous
- * processes.
- */
- public long threshold;
-
- /**
- * Set to true if the system considers itself to currently be in a low
- * memory situation.
- */
- public boolean lowMemory;
-
- public MemoryInfo() {
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(availMem);
- dest.writeLong(threshold);
- dest.writeInt(lowMemory ? 1 : 0);
- }
-
- public void readFromParcel(Parcel source) {
- availMem = source.readLong();
- threshold = source.readLong();
- lowMemory = source.readInt() != 0;
- }
-
- public static final Creator<MemoryInfo> CREATOR
- = new Creator<MemoryInfo>() {
- public MemoryInfo createFromParcel(Parcel source) {
- return new MemoryInfo(source);
- }
- public MemoryInfo[] newArray(int size) {
- return new MemoryInfo[size];
- }
- };
-
- private MemoryInfo(Parcel source) {
- readFromParcel(source);
- }
- }
-
- public void getMemoryInfo(MemoryInfo outInfo) {
- try {
- ActivityManagerNative.getDefault().getMemoryInfo(outInfo);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * @hide
- */
- public boolean clearApplicationUserData(String packageName, IPackageDataObserver observer) {
- try {
- return ActivityManagerNative.getDefault().clearApplicationUserData(packageName,
- observer);
- } catch (RemoteException e) {
- return false;
- }
- }
-
- /**
- * Information you can retrieve about any processes that are in an error condition.
- */
- public static class ProcessErrorStateInfo implements Parcelable {
- /**
- * Condition codes
- */
- public static final int NO_ERROR = 0;
- public static final int CRASHED = 1;
- public static final int NOT_RESPONDING = 2;
-
- /**
- * The condition that the process is in.
- */
- public int condition;
-
- /**
- * The process name in which the crash or error occurred.
- */
- public String processName;
-
- /**
- * The pid of this process; 0 if none
- */
- public int pid;
-
- /**
- * The kernel user-ID that has been assigned to this process;
- * currently this is not a unique ID (multiple applications can have
- * the same uid).
- */
- public int uid;
-
- /**
- * The tag that was provided when the process crashed.
- */
- public String tag;
-
- /**
- * A short message describing the error condition.
- */
- public String shortMsg;
-
- /**
- * A long message describing the error condition.
- */
- public String longMsg;
-
- /**
- * Raw data about the crash (typically a stack trace).
- */
- public byte[] crashData;
-
- public ProcessErrorStateInfo() {
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(condition);
- dest.writeString(processName);
- dest.writeInt(pid);
- dest.writeInt(uid);
- dest.writeString(tag);
- dest.writeString(shortMsg);
- dest.writeString(longMsg);
- dest.writeInt(crashData == null ? -1 : crashData.length);
- dest.writeByteArray(crashData);
- }
-
- public void readFromParcel(Parcel source) {
- condition = source.readInt();
- processName = source.readString();
- pid = source.readInt();
- uid = source.readInt();
- tag = source.readString();
- shortMsg = source.readString();
- longMsg = source.readString();
- int cdLen = source.readInt();
- if (cdLen == -1) {
- crashData = null;
- } else {
- crashData = new byte[cdLen];
- source.readByteArray(crashData);
- }
- }
-
- public static final Creator<ProcessErrorStateInfo> CREATOR =
- new Creator<ProcessErrorStateInfo>() {
- public ProcessErrorStateInfo createFromParcel(Parcel source) {
- return new ProcessErrorStateInfo(source);
- }
- public ProcessErrorStateInfo[] newArray(int size) {
- return new ProcessErrorStateInfo[size];
- }
- };
-
- private ProcessErrorStateInfo(Parcel source) {
- readFromParcel(source);
- }
- }
-
- /**
- * Returns a list of any processes that are currently in an error condition. The result
- * will be null if all processes are running properly at this time.
- *
- * @return Returns a list of ProcessErrorStateInfo records, or null if there are no
- * current error conditions (it will not return an empty list). This list ordering is not
- * specified.
- */
- public List<ProcessErrorStateInfo> getProcessesInErrorState() {
- try {
- return ActivityManagerNative.getDefault().getProcessesInErrorState();
- } catch (RemoteException e) {
- return null;
- }
- }
-
- /**
- * Information you can retrieve about a running process.
- */
- public static class RunningAppProcessInfo implements Parcelable {
- /**
- * The name of the process that this object is associated with
- */
- public String processName;
-
- /**
- * The pid of this process; 0 if none
- */
- public int pid;
-
- public String pkgList[];
-
- /**
- * Constant for {@link #importance}: this process is running the
- * foreground UI.
- */
- public static final int IMPORTANCE_FOREGROUND = 100;
-
- /**
- * Constant for {@link #importance}: this process is running something
- * that is considered to be actively visible to the user.
- */
- public static final int IMPORTANCE_VISIBLE = 200;
-
- /**
- * Constant for {@link #importance}: this process is contains services
- * that should remain running.
- */
- public static final int IMPORTANCE_SERVICE = 300;
-
- /**
- * Constant for {@link #importance}: this process process contains
- * background code that is expendable.
- */
- public static final int IMPORTANCE_BACKGROUND = 400;
-
- /**
- * Constant for {@link #importance}: this process is empty of any
- * actively running code.
- */
- public static final int IMPORTANCE_EMPTY = 500;
-
- /**
- * The relative importance level that the system places on this
- * process. May be one of {@link #IMPORTANCE_FOREGROUND},
- * {@link #IMPORTANCE_VISIBLE}, {@link #IMPORTANCE_SERVICE},
- * {@link #IMPORTANCE_BACKGROUND}, or {@link #IMPORTANCE_EMPTY}. These
- * constants are numbered so that "more important" values are always
- * smaller than "less important" values.
- */
- public int importance;
-
- /**
- * An additional ordering within a particular {@link #importance}
- * category, providing finer-grained information about the relative
- * utility of processes within a category. This number means nothing
- * except that a smaller values are more recently used (and thus
- * more important). Currently an LRU value is only maintained for
- * the {@link #IMPORTANCE_BACKGROUND} category, though others may
- * be maintained in the future.
- */
- public int lru;
-
- public RunningAppProcessInfo() {
- importance = IMPORTANCE_FOREGROUND;
- }
-
- public RunningAppProcessInfo(String pProcessName, int pPid, String pArr[]) {
- processName = pProcessName;
- pid = pPid;
- pkgList = pArr;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(processName);
- dest.writeInt(pid);
- dest.writeStringArray(pkgList);
- dest.writeInt(importance);
- dest.writeInt(lru);
- }
-
- public void readFromParcel(Parcel source) {
- processName = source.readString();
- pid = source.readInt();
- pkgList = source.readStringArray();
- importance = source.readInt();
- lru = source.readInt();
- }
-
- public static final Creator<RunningAppProcessInfo> CREATOR =
- new Creator<RunningAppProcessInfo>() {
- public RunningAppProcessInfo createFromParcel(Parcel source) {
- return new RunningAppProcessInfo(source);
- }
- public RunningAppProcessInfo[] newArray(int size) {
- return new RunningAppProcessInfo[size];
- }
- };
-
- private RunningAppProcessInfo(Parcel source) {
- readFromParcel(source);
- }
- }
-
- /**
- * Returns a list of application processes that are running on the device.
- *
- * @return Returns a list of RunningAppProcessInfo records, or null if there are no
- * running processes (it will not return an empty list). This list ordering is not
- * specified.
- */
- public List<RunningAppProcessInfo> getRunningAppProcesses() {
- try {
- return ActivityManagerNative.getDefault().getRunningAppProcesses();
- } catch (RemoteException e) {
- return null;
- }
- }
-
- /**
- * Have the system perform a force stop of everything associated with
- * the given application package. All processes that share its uid
- * will be killed, all services it has running stopped, all activities
- * removed, etc. In addition, a {@link Intent#ACTION_PACKAGE_RESTARTED}
- * broadcast will be sent, so that any of its registered alarms can
- * be stopped, notifications removed, etc.
- *
- * <p>You must hold the permission
- * {@link android.Manifest.permission#RESTART_PACKAGES} to be able to
- * call this method.
- *
- * @param packageName The name of the package to be stopped.
- */
- public void restartPackage(String packageName) {
- try {
- ActivityManagerNative.getDefault().restartPackage(packageName);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Get the device configuration attributes.
- */
- public ConfigurationInfo getDeviceConfigurationInfo() {
- try {
- return ActivityManagerNative.getDefault().getDeviceConfigurationInfo();
- } catch (RemoteException e) {
- }
- return null;
- }
-
-}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
deleted file mode 100644
index f11dbec..0000000
--- a/core/java/android/app/ActivityManagerNative.java
+++ /dev/null
@@ -1,2135 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ConfigurationInfo;
-import android.content.pm.IPackageDataObserver;
-import android.content.res.Configuration;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.ServiceManager;
-import android.text.TextUtils;
-import android.util.Config;
-import android.util.Log;
-
-import java.io.FileNotFoundException;
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-/** {@hide} */
-public abstract class ActivityManagerNative extends Binder implements IActivityManager
-{
- /**
- * Cast a Binder object into an activity manager interface, generating
- * a proxy if needed.
- */
- static public IActivityManager asInterface(IBinder obj)
- {
- if (obj == null) {
- return null;
- }
- IActivityManager in =
- (IActivityManager)obj.queryLocalInterface(descriptor);
- if (in != null) {
- return in;
- }
-
- return new ActivityManagerProxy(obj);
- }
-
- /**
- * Retrieve the system's default/global activity manager.
- */
- static public IActivityManager getDefault()
- {
- if (gDefault != null) {
- //if (Config.LOGV) Log.v(
- // "ActivityManager", "returning cur default = " + gDefault);
- return gDefault;
- }
- IBinder b = ServiceManager.getService("activity");
- if (Config.LOGV) Log.v(
- "ActivityManager", "default service binder = " + b);
- gDefault = asInterface(b);
- if (Config.LOGV) Log.v(
- "ActivityManager", "default service = " + gDefault);
- return gDefault;
- }
-
- /**
- * Convenience for checking whether the system is ready. For internal use only.
- */
- static public boolean isSystemReady() {
- if (!sSystemReady) {
- sSystemReady = getDefault().testIsSystemReady();
- }
- return sSystemReady;
- }
- static boolean sSystemReady = false;
-
- /**
- * Convenience for sending a sticky broadcast. For internal use only.
- * If you don't care about permission, use null.
- */
- static public void broadcastStickyIntent(Intent intent, String permission)
- {
- try {
- getDefault().broadcastIntent(
- null, intent, null, null, Activity.RESULT_OK, null, null,
- null /*permission*/, false, true);
- } catch (RemoteException ex) {
- }
- }
-
- static public void noteWakeupAlarm(PendingIntent ps) {
- try {
- getDefault().noteWakeupAlarm(ps.getTarget());
- } catch (RemoteException ex) {
- }
- }
-
- public ActivityManagerNative()
- {
- attachInterface(this, descriptor);
- }
-
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
- throws RemoteException {
- switch (code) {
- case START_ACTIVITY_TRANSACTION:
- {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app = ApplicationThreadNative.asInterface(b);
- Intent intent = Intent.CREATOR.createFromParcel(data);
- String resolvedType = data.readString();
- Uri[] grantedUriPermissions = data.createTypedArray(Uri.CREATOR);
- int grantedMode = data.readInt();
- IBinder resultTo = data.readStrongBinder();
- String resultWho = data.readString();
- int requestCode = data.readInt();
- boolean onlyIfNeeded = data.readInt() != 0;
- boolean debug = data.readInt() != 0;
- int result = startActivity(app, intent, resolvedType,
- grantedUriPermissions, grantedMode, resultTo, resultWho,
- requestCode, onlyIfNeeded, debug);
- reply.writeNoException();
- reply.writeInt(result);
- return true;
- }
-
- case START_NEXT_MATCHING_ACTIVITY_TRANSACTION:
- {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder callingActivity = data.readStrongBinder();
- Intent intent = Intent.CREATOR.createFromParcel(data);
- boolean result = startNextMatchingActivity(callingActivity, intent);
- reply.writeNoException();
- reply.writeInt(result ? 1 : 0);
- return true;
- }
-
- case FINISH_ACTIVITY_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- Intent resultData = null;
- int resultCode = data.readInt();
- if (data.readInt() != 0) {
- resultData = Intent.CREATOR.createFromParcel(data);
- }
- boolean res = finishActivity(token, resultCode, resultData);
- reply.writeNoException();
- reply.writeInt(res ? 1 : 0);
- return true;
- }
-
- case FINISH_SUB_ACTIVITY_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- String resultWho = data.readString();
- int requestCode = data.readInt();
- finishSubActivity(token, resultWho, requestCode);
- reply.writeNoException();
- return true;
- }
-
- case REGISTER_RECEIVER_TRANSACTION:
- {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app =
- b != null ? ApplicationThreadNative.asInterface(b) : null;
- b = data.readStrongBinder();
- IIntentReceiver rec
- = b != null ? IIntentReceiver.Stub.asInterface(b) : null;
- IntentFilter filter = IntentFilter.CREATOR.createFromParcel(data);
- String perm = data.readString();
- Intent intent = registerReceiver(app, rec, filter, perm);
- reply.writeNoException();
- if (intent != null) {
- reply.writeInt(1);
- intent.writeToParcel(reply, 0);
- } else {
- reply.writeInt(0);
- }
- return true;
- }
-
- case UNREGISTER_RECEIVER_TRANSACTION:
- {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- if (b == null) {
- return true;
- }
- IIntentReceiver rec = IIntentReceiver.Stub.asInterface(b);
- unregisterReceiver(rec);
- reply.writeNoException();
- return true;
- }
-
- case BROADCAST_INTENT_TRANSACTION:
- {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app =
- b != null ? ApplicationThreadNative.asInterface(b) : null;
- Intent intent = Intent.CREATOR.createFromParcel(data);
- String resolvedType = data.readString();
- b = data.readStrongBinder();
- IIntentReceiver resultTo =
- b != null ? IIntentReceiver.Stub.asInterface(b) : null;
- int resultCode = data.readInt();
- String resultData = data.readString();
- Bundle resultExtras = data.readBundle();
- String perm = data.readString();
- boolean serialized = data.readInt() != 0;
- boolean sticky = data.readInt() != 0;
- int res = broadcastIntent(app, intent, resolvedType, resultTo,
- resultCode, resultData, resultExtras, perm,
- serialized, sticky);
- reply.writeNoException();
- reply.writeInt(res);
- return true;
- }
-
- case UNBROADCAST_INTENT_TRANSACTION:
- {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app = b != null ? ApplicationThreadNative.asInterface(b) : null;
- Intent intent = Intent.CREATOR.createFromParcel(data);
- unbroadcastIntent(app, intent);
- reply.writeNoException();
- return true;
- }
-
- case FINISH_RECEIVER_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder who = data.readStrongBinder();
- int resultCode = data.readInt();
- String resultData = data.readString();
- Bundle resultExtras = data.readBundle();
- boolean resultAbort = data.readInt() != 0;
- if (who != null) {
- finishReceiver(who, resultCode, resultData, resultExtras, resultAbort);
- }
- reply.writeNoException();
- return true;
- }
-
- case SET_PERSISTENT_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- boolean isPersistent = data.readInt() != 0;
- if (token != null) {
- setPersistent(token, isPersistent);
- }
- reply.writeNoException();
- return true;
- }
-
- case ATTACH_APPLICATION_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IApplicationThread app = ApplicationThreadNative.asInterface(
- data.readStrongBinder());
- if (app != null) {
- attachApplication(app);
- }
- reply.writeNoException();
- return true;
- }
-
- case ACTIVITY_IDLE_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- if (token != null) {
- activityIdle(token);
- }
- reply.writeNoException();
- return true;
- }
-
- case ACTIVITY_PAUSED_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- Bundle map = data.readBundle();
- activityPaused(token, map);
- reply.writeNoException();
- return true;
- }
-
- case ACTIVITY_STOPPED_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- Bitmap thumbnail = data.readInt() != 0
- ? Bitmap.CREATOR.createFromParcel(data) : null;
- CharSequence description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data);
- activityStopped(token, thumbnail, description);
- reply.writeNoException();
- return true;
- }
-
- case ACTIVITY_DESTROYED_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- activityDestroyed(token);
- reply.writeNoException();
- return true;
- }
-
- case GET_CALLING_PACKAGE_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- String res = token != null ? getCallingPackage(token) : null;
- reply.writeNoException();
- reply.writeString(res);
- return true;
- }
-
- case GET_CALLING_ACTIVITY_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- ComponentName cn = getCallingActivity(token);
- reply.writeNoException();
- ComponentName.writeToParcel(cn, reply);
- return true;
- }
-
- case GET_TASKS_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- int maxNum = data.readInt();
- int fl = data.readInt();
- IBinder receiverBinder = data.readStrongBinder();
- IThumbnailReceiver receiver = receiverBinder != null
- ? IThumbnailReceiver.Stub.asInterface(receiverBinder)
- : null;
- List list = getTasks(maxNum, fl, receiver);
- reply.writeNoException();
- int N = list != null ? list.size() : -1;
- reply.writeInt(N);
- int i;
- for (i=0; i<N; i++) {
- ActivityManager.RunningTaskInfo info =
- (ActivityManager.RunningTaskInfo)list.get(i);
- info.writeToParcel(reply, 0);
- }
- return true;
- }
-
- case GET_RECENT_TASKS_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- int maxNum = data.readInt();
- int fl = data.readInt();
- List<ActivityManager.RecentTaskInfo> list = getRecentTasks(maxNum,
- fl);
- reply.writeNoException();
- reply.writeTypedList(list);
- return true;
- }
-
- case GET_SERVICES_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- int maxNum = data.readInt();
- int fl = data.readInt();
- List list = getServices(maxNum, fl);
- reply.writeNoException();
- int N = list != null ? list.size() : -1;
- reply.writeInt(N);
- int i;
- for (i=0; i<N; i++) {
- ActivityManager.RunningServiceInfo info =
- (ActivityManager.RunningServiceInfo)list.get(i);
- info.writeToParcel(reply, 0);
- }
- return true;
- }
-
- case GET_PROCESSES_IN_ERROR_STATE_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- List<ActivityManager.ProcessErrorStateInfo> list = getProcessesInErrorState();
- reply.writeNoException();
- reply.writeTypedList(list);
- return true;
- }
-
- case GET_RUNNING_APP_PROCESSES_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- List<ActivityManager.RunningAppProcessInfo> list = getRunningAppProcesses();
- reply.writeNoException();
- reply.writeTypedList(list);
- return true;
- }
-
- case MOVE_TASK_TO_FRONT_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- int task = data.readInt();
- moveTaskToFront(task);
- reply.writeNoException();
- return true;
- }
-
- case MOVE_TASK_TO_BACK_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- int task = data.readInt();
- moveTaskToBack(task);
- reply.writeNoException();
- return true;
- }
-
- case MOVE_ACTIVITY_TASK_TO_BACK_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- boolean nonRoot = data.readInt() != 0;
- boolean res = moveActivityTaskToBack(token, nonRoot);
- reply.writeNoException();
- reply.writeInt(res ? 1 : 0);
- return true;
- }
-
- case MOVE_TASK_BACKWARDS_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- int task = data.readInt();
- moveTaskBackwards(task);
- reply.writeNoException();
- return true;
- }
-
- case GET_TASK_FOR_ACTIVITY_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- boolean onlyRoot = data.readInt() != 0;
- int res = token != null
- ? getTaskForActivity(token, onlyRoot) : -1;
- reply.writeNoException();
- reply.writeInt(res);
- return true;
- }
-
- case FINISH_OTHER_INSTANCES_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- ComponentName className = ComponentName.readFromParcel(data);
- finishOtherInstances(token, className);
- reply.writeNoException();
- return true;
- }
-
- case REPORT_THUMBNAIL_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- Bitmap thumbnail = data.readInt() != 0
- ? Bitmap.CREATOR.createFromParcel(data) : null;
- CharSequence description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data);
- reportThumbnail(token, thumbnail, description);
- reply.writeNoException();
- return true;
- }
-
- case GET_CONTENT_PROVIDER_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app = ApplicationThreadNative.asInterface(b);
- String name = data.readString();
- ContentProviderHolder cph = getContentProvider(app, name);
- reply.writeNoException();
- if (cph != null) {
- reply.writeInt(1);
- cph.writeToParcel(reply, 0);
- } else {
- reply.writeInt(0);
- }
- return true;
- }
-
- case PUBLISH_CONTENT_PROVIDERS_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app = ApplicationThreadNative.asInterface(b);
- ArrayList<ContentProviderHolder> providers =
- data.createTypedArrayList(ContentProviderHolder.CREATOR);
- publishContentProviders(app, providers);
- reply.writeNoException();
- return true;
- }
-
- case REMOVE_CONTENT_PROVIDER_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app = ApplicationThreadNative.asInterface(b);
- String name = data.readString();
- removeContentProvider(app, name);
- reply.writeNoException();
- return true;
- }
-
- case START_SERVICE_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app = ApplicationThreadNative.asInterface(b);
- Intent service = Intent.CREATOR.createFromParcel(data);
- String resolvedType = data.readString();
- ComponentName cn = startService(app, service, resolvedType);
- reply.writeNoException();
- ComponentName.writeToParcel(cn, reply);
- return true;
- }
-
- case STOP_SERVICE_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app = ApplicationThreadNative.asInterface(b);
- Intent service = Intent.CREATOR.createFromParcel(data);
- String resolvedType = data.readString();
- int res = stopService(app, service, resolvedType);
- reply.writeNoException();
- reply.writeInt(res);
- return true;
- }
-
- case STOP_SERVICE_TOKEN_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- ComponentName className = ComponentName.readFromParcel(data);
- IBinder token = data.readStrongBinder();
- int startId = data.readInt();
- boolean res = stopServiceToken(className, token, startId);
- reply.writeNoException();
- reply.writeInt(res ? 1 : 0);
- return true;
- }
-
- case SET_SERVICE_FOREGROUND_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- ComponentName className = ComponentName.readFromParcel(data);
- IBinder token = data.readStrongBinder();
- boolean isForeground = data.readInt() != 0;
- setServiceForeground(className, token, isForeground);
- reply.writeNoException();
- return true;
- }
-
- case BIND_SERVICE_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app = ApplicationThreadNative.asInterface(b);
- IBinder token = data.readStrongBinder();
- Intent service = Intent.CREATOR.createFromParcel(data);
- String resolvedType = data.readString();
- b = data.readStrongBinder();
- int fl = data.readInt();
- IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
- int res = bindService(app, token, service, resolvedType, conn, fl);
- reply.writeNoException();
- reply.writeInt(res);
- return true;
- }
-
- case UNBIND_SERVICE_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
- boolean res = unbindService(conn);
- reply.writeNoException();
- reply.writeInt(res ? 1 : 0);
- return true;
- }
-
- case PUBLISH_SERVICE_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- Intent intent = Intent.CREATOR.createFromParcel(data);
- IBinder service = data.readStrongBinder();
- publishService(token, intent, service);
- reply.writeNoException();
- return true;
- }
-
- case UNBIND_FINISHED_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- Intent intent = Intent.CREATOR.createFromParcel(data);
- boolean doRebind = data.readInt() != 0;
- unbindFinished(token, intent, doRebind);
- reply.writeNoException();
- return true;
- }
-
- case SERVICE_DONE_EXECUTING_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- serviceDoneExecuting(token);
- reply.writeNoException();
- return true;
- }
-
- case START_INSTRUMENTATION_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- ComponentName className = ComponentName.readFromParcel(data);
- String profileFile = data.readString();
- int fl = data.readInt();
- Bundle arguments = data.readBundle();
- IBinder b = data.readStrongBinder();
- IInstrumentationWatcher w = IInstrumentationWatcher.Stub.asInterface(b);
- boolean res = startInstrumentation(className, profileFile, fl, arguments, w);
- reply.writeNoException();
- reply.writeInt(res ? 1 : 0);
- return true;
- }
-
-
- case FINISH_INSTRUMENTATION_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app = ApplicationThreadNative.asInterface(b);
- int resultCode = data.readInt();
- Bundle results = data.readBundle();
- finishInstrumentation(app, resultCode, results);
- reply.writeNoException();
- return true;
- }
-
- case GET_CONFIGURATION_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- Configuration config = getConfiguration();
- reply.writeNoException();
- config.writeToParcel(reply, 0);
- return true;
- }
-
- case UPDATE_CONFIGURATION_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- Configuration config = Configuration.CREATOR.createFromParcel(data);
- updateConfiguration(config);
- reply.writeNoException();
- return true;
- }
-
- case SET_REQUESTED_ORIENTATION_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- int requestedOrientation = data.readInt();
- setRequestedOrientation(token, requestedOrientation);
- reply.writeNoException();
- return true;
- }
-
- case GET_REQUESTED_ORIENTATION_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- int req = getRequestedOrientation(token);
- reply.writeNoException();
- reply.writeInt(req);
- return true;
- }
-
- case GET_ACTIVITY_CLASS_FOR_TOKEN_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- ComponentName cn = getActivityClassForToken(token);
- reply.writeNoException();
- ComponentName.writeToParcel(cn, reply);
- return true;
- }
-
- case GET_PACKAGE_FOR_TOKEN_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- reply.writeNoException();
- reply.writeString(getPackageForToken(token));
- return true;
- }
-
- case GET_INTENT_SENDER_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- int type = data.readInt();
- String packageName = data.readString();
- IBinder token = data.readStrongBinder();
- String resultWho = data.readString();
- int requestCode = data.readInt();
- Intent requestIntent = data.readInt() != 0
- ? Intent.CREATOR.createFromParcel(data) : null;
- String requestResolvedType = data.readString();
- int fl = data.readInt();
- IIntentSender res = getIntentSender(type, packageName, token,
- resultWho, requestCode, requestIntent,
- requestResolvedType, fl);
- reply.writeNoException();
- reply.writeStrongBinder(res != null ? res.asBinder() : null);
- return true;
- }
-
- case CANCEL_INTENT_SENDER_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IIntentSender r = IIntentSender.Stub.asInterface(
- data.readStrongBinder());
- cancelIntentSender(r);
- reply.writeNoException();
- return true;
- }
-
- case GET_PACKAGE_FOR_INTENT_SENDER_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IIntentSender r = IIntentSender.Stub.asInterface(
- data.readStrongBinder());
- String res = getPackageForIntentSender(r);
- reply.writeNoException();
- reply.writeString(res);
- return true;
- }
-
- case SET_PROCESS_LIMIT_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- int max = data.readInt();
- setProcessLimit(max);
- reply.writeNoException();
- return true;
- }
-
- case GET_PROCESS_LIMIT_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- int limit = getProcessLimit();
- reply.writeNoException();
- reply.writeInt(limit);
- return true;
- }
-
- case SET_PROCESS_FOREGROUND_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- int pid = data.readInt();
- boolean isForeground = data.readInt() != 0;
- setProcessForeground(token, pid, isForeground);
- reply.writeNoException();
- return true;
- }
-
- case CHECK_PERMISSION_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- String perm = data.readString();
- int pid = data.readInt();
- int uid = data.readInt();
- int res = checkPermission(perm, pid, uid);
- reply.writeNoException();
- reply.writeInt(res);
- return true;
- }
-
- case CHECK_URI_PERMISSION_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- Uri uri = Uri.CREATOR.createFromParcel(data);
- int pid = data.readInt();
- int uid = data.readInt();
- int mode = data.readInt();
- int res = checkUriPermission(uri, pid, uid, mode);
- reply.writeNoException();
- reply.writeInt(res);
- return true;
- }
-
- case CLEAR_APP_DATA_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- String packageName = data.readString();
- IPackageDataObserver observer = IPackageDataObserver.Stub.asInterface(
- data.readStrongBinder());
- boolean res = clearApplicationUserData(packageName, observer);
- reply.writeNoException();
- reply.writeInt(res ? 1 : 0);
- return true;
- }
-
- case GRANT_URI_PERMISSION_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app = ApplicationThreadNative.asInterface(b);
- String targetPkg = data.readString();
- Uri uri = Uri.CREATOR.createFromParcel(data);
- int mode = data.readInt();
- grantUriPermission(app, targetPkg, uri, mode);
- reply.writeNoException();
- return true;
- }
-
- case REVOKE_URI_PERMISSION_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app = ApplicationThreadNative.asInterface(b);
- Uri uri = Uri.CREATOR.createFromParcel(data);
- int mode = data.readInt();
- revokeUriPermission(app, uri, mode);
- reply.writeNoException();
- return true;
- }
-
- case SHOW_WAITING_FOR_DEBUGGER_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app = ApplicationThreadNative.asInterface(b);
- boolean waiting = data.readInt() != 0;
- showWaitingForDebugger(app, waiting);
- reply.writeNoException();
- return true;
- }
-
- case GET_MEMORY_INFO_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
- getMemoryInfo(mi);
- reply.writeNoException();
- mi.writeToParcel(reply, 0);
- return true;
- }
-
- case UNHANDLED_BACK_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- unhandledBack();
- reply.writeNoException();
- return true;
- }
-
- case OPEN_CONTENT_URI_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- Uri uri = Uri.parse(data.readString());
- ParcelFileDescriptor pfd = openContentUri(uri);
- reply.writeNoException();
- if (pfd != null) {
- reply.writeInt(1);
- pfd.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- } else {
- reply.writeInt(0);
- }
- return true;
- }
-
- case GOING_TO_SLEEP_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- goingToSleep();
- reply.writeNoException();
- return true;
- }
-
- case WAKING_UP_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- wakingUp();
- reply.writeNoException();
- return true;
- }
-
- case SET_DEBUG_APP_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- String pn = data.readString();
- boolean wfd = data.readInt() != 0;
- boolean per = data.readInt() != 0;
- setDebugApp(pn, wfd, per);
- reply.writeNoException();
- return true;
- }
-
- case SET_ALWAYS_FINISH_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- boolean enabled = data.readInt() != 0;
- setAlwaysFinish(enabled);
- reply.writeNoException();
- return true;
- }
-
- case SET_ACTIVITY_WATCHER_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IActivityWatcher watcher = IActivityWatcher.Stub.asInterface(
- data.readStrongBinder());
- setActivityWatcher(watcher);
- return true;
- }
-
- case ENTER_SAFE_MODE_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- enterSafeMode();
- reply.writeNoException();
- return true;
- }
-
- case NOTE_WAKEUP_ALARM_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IIntentSender is = IIntentSender.Stub.asInterface(
- data.readStrongBinder());
- noteWakeupAlarm(is);
- reply.writeNoException();
- return true;
- }
-
- case KILL_PIDS_FOR_MEMORY_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- int[] pids = data.createIntArray();
- boolean res = killPidsForMemory(pids);
- reply.writeNoException();
- reply.writeInt(res ? 1 : 0);
- return true;
- }
-
- case REPORT_PSS_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app = ApplicationThreadNative.asInterface(b);
- int pss = data.readInt();
- reportPss(app, pss);
- reply.writeNoException();
- return true;
- }
-
- case START_RUNNING_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- String pkg = data.readString();
- String cls = data.readString();
- String action = data.readString();
- String indata = data.readString();
- startRunning(pkg, cls, action, indata);
- reply.writeNoException();
- return true;
- }
-
- case SYSTEM_READY_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- systemReady();
- reply.writeNoException();
- return true;
- }
-
- case HANDLE_APPLICATION_ERROR_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder app = data.readStrongBinder();
- int fl = data.readInt();
- String tag = data.readString();
- String shortMsg = data.readString();
- String longMsg = data.readString();
- byte[] crashData = data.createByteArray();
- int res = handleApplicationError(app, fl, tag, shortMsg, longMsg,
- crashData);
- reply.writeNoException();
- reply.writeInt(res);
- return true;
- }
-
- case SIGNAL_PERSISTENT_PROCESSES_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- int sig = data.readInt();
- signalPersistentProcesses(sig);
- reply.writeNoException();
- return true;
- }
-
- case RESTART_PACKAGE_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- String packageName = data.readString();
- restartPackage(packageName);
- reply.writeNoException();
- return true;
- }
-
- case GET_DEVICE_CONFIGURATION_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- ConfigurationInfo config = getDeviceConfigurationInfo();
- reply.writeNoException();
- config.writeToParcel(reply, 0);
- return true;
- }
-
- case PEEK_SERVICE_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- Intent service = Intent.CREATOR.createFromParcel(data);
- String resolvedType = data.readString();
- IBinder binder = peekService(service, resolvedType);
- reply.writeNoException();
- reply.writeStrongBinder(binder);
- return true;
- }
- }
-
- return super.onTransact(code, data, reply, flags);
- }
-
- public IBinder asBinder()
- {
- return this;
- }
-
- private static IActivityManager gDefault;
-}
-
-class ActivityManagerProxy implements IActivityManager
-{
- public ActivityManagerProxy(IBinder remote)
- {
- mRemote = remote;
- }
-
- public IBinder asBinder()
- {
- return mRemote;
- }
-
- public int startActivity(IApplicationThread caller, Intent intent,
- String resolvedType, Uri[] grantedUriPermissions, int grantedMode,
- IBinder resultTo, String resultWho,
- int requestCode, boolean onlyIfNeeded,
- boolean debug) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- intent.writeToParcel(data, 0);
- data.writeString(resolvedType);
- data.writeTypedArray(grantedUriPermissions, 0);
- data.writeInt(grantedMode);
- data.writeStrongBinder(resultTo);
- data.writeString(resultWho);
- data.writeInt(requestCode);
- data.writeInt(onlyIfNeeded ? 1 : 0);
- data.writeInt(debug ? 1 : 0);
- mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
- reply.readException();
- int result = reply.readInt();
- reply.recycle();
- data.recycle();
- return result;
- }
- public boolean startNextMatchingActivity(IBinder callingActivity,
- Intent intent) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(callingActivity);
- intent.writeToParcel(data, 0);
- mRemote.transact(START_NEXT_MATCHING_ACTIVITY_TRANSACTION, data, reply, 0);
- reply.readException();
- int result = reply.readInt();
- reply.recycle();
- data.recycle();
- return result != 0;
- }
- public boolean finishActivity(IBinder token, int resultCode, Intent resultData)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- data.writeInt(resultCode);
- if (resultData != null) {
- data.writeInt(1);
- resultData.writeToParcel(data, 0);
- } else {
- data.writeInt(0);
- }
- mRemote.transact(FINISH_ACTIVITY_TRANSACTION, data, reply, 0);
- reply.readException();
- boolean res = reply.readInt() != 0;
- data.recycle();
- reply.recycle();
- return res;
- }
- public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- data.writeString(resultWho);
- data.writeInt(requestCode);
- mRemote.transact(FINISH_SUB_ACTIVITY_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public Intent registerReceiver(IApplicationThread caller,
- IIntentReceiver receiver,
- IntentFilter filter, String perm) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
- filter.writeToParcel(data, 0);
- data.writeString(perm);
- mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);
- reply.readException();
- Intent intent = null;
- int haveIntent = reply.readInt();
- if (haveIntent != 0) {
- intent = Intent.CREATOR.createFromParcel(reply);
- }
- reply.recycle();
- data.recycle();
- return intent;
- }
- public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(receiver.asBinder());
- mRemote.transact(UNREGISTER_RECEIVER_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public int broadcastIntent(IApplicationThread caller,
- Intent intent, String resolvedType, IIntentReceiver resultTo,
- int resultCode, String resultData, Bundle map,
- String requiredPermission, boolean serialized,
- boolean sticky) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- intent.writeToParcel(data, 0);
- data.writeString(resolvedType);
- data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);
- data.writeInt(resultCode);
- data.writeString(resultData);
- data.writeBundle(map);
- data.writeString(requiredPermission);
- data.writeInt(serialized ? 1 : 0);
- data.writeInt(sticky ? 1 : 0);
- mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
- reply.readException();
- int res = reply.readInt();
- reply.recycle();
- data.recycle();
- return res;
- }
- public void unbroadcastIntent(IApplicationThread caller, Intent intent) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- intent.writeToParcel(data, 0);
- mRemote.transact(UNBROADCAST_INTENT_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle map, boolean abortBroadcast) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(who);
- data.writeInt(resultCode);
- data.writeString(resultData);
- data.writeBundle(map);
- data.writeInt(abortBroadcast ? 1 : 0);
- mRemote.transact(FINISH_RECEIVER_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void setPersistent(IBinder token, boolean isPersistent) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- data.writeInt(isPersistent ? 1 : 0);
- mRemote.transact(SET_PERSISTENT_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void attachApplication(IApplicationThread app) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(app.asBinder());
- mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void activityIdle(IBinder token) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- mRemote.transact(ACTIVITY_IDLE_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void activityPaused(IBinder token, Bundle state) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- data.writeBundle(state);
- mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void activityStopped(IBinder token,
- Bitmap thumbnail, CharSequence description) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- if (thumbnail != null) {
- data.writeInt(1);
- thumbnail.writeToParcel(data, 0);
- } else {
- data.writeInt(0);
- }
- TextUtils.writeToParcel(description, data, 0);
- mRemote.transact(ACTIVITY_STOPPED_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void activityDestroyed(IBinder token) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- mRemote.transact(ACTIVITY_DESTROYED_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public String getCallingPackage(IBinder token) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- mRemote.transact(GET_CALLING_PACKAGE_TRANSACTION, data, reply, 0);
- reply.readException();
- String res = reply.readString();
- data.recycle();
- reply.recycle();
- return res;
- }
- public ComponentName getCallingActivity(IBinder token)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- mRemote.transact(GET_CALLING_ACTIVITY_TRANSACTION, data, reply, 0);
- reply.readException();
- ComponentName res = ComponentName.readFromParcel(reply);
- data.recycle();
- reply.recycle();
- return res;
- }
- public List getTasks(int maxNum, int flags,
- IThumbnailReceiver receiver) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeInt(maxNum);
- data.writeInt(flags);
- data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
- mRemote.transact(GET_TASKS_TRANSACTION, data, reply, 0);
- reply.readException();
- ArrayList list = null;
- int N = reply.readInt();
- if (N >= 0) {
- list = new ArrayList();
- while (N > 0) {
- ActivityManager.RunningTaskInfo info =
- ActivityManager.RunningTaskInfo.CREATOR
- .createFromParcel(reply);
- list.add(info);
- N--;
- }
- }
- data.recycle();
- reply.recycle();
- return list;
- }
- public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
- int flags) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeInt(maxNum);
- data.writeInt(flags);
- mRemote.transact(GET_RECENT_TASKS_TRANSACTION, data, reply, 0);
- reply.readException();
- ArrayList<ActivityManager.RecentTaskInfo> list
- = reply.createTypedArrayList(ActivityManager.RecentTaskInfo.CREATOR);
- data.recycle();
- reply.recycle();
- return list;
- }
- public List getServices(int maxNum, int flags) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeInt(maxNum);
- data.writeInt(flags);
- mRemote.transact(GET_SERVICES_TRANSACTION, data, reply, 0);
- reply.readException();
- ArrayList list = null;
- int N = reply.readInt();
- if (N >= 0) {
- list = new ArrayList();
- while (N > 0) {
- ActivityManager.RunningServiceInfo info =
- ActivityManager.RunningServiceInfo.CREATOR
- .createFromParcel(reply);
- list.add(info);
- N--;
- }
- }
- data.recycle();
- reply.recycle();
- return list;
- }
- public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState()
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(GET_PROCESSES_IN_ERROR_STATE_TRANSACTION, data, reply, 0);
- reply.readException();
- ArrayList<ActivityManager.ProcessErrorStateInfo> list
- = reply.createTypedArrayList(ActivityManager.ProcessErrorStateInfo.CREATOR);
- data.recycle();
- reply.recycle();
- return list;
- }
- public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses()
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(GET_RUNNING_APP_PROCESSES_TRANSACTION, data, reply, 0);
- reply.readException();
- ArrayList<ActivityManager.RunningAppProcessInfo> list
- = reply.createTypedArrayList(ActivityManager.RunningAppProcessInfo.CREATOR);
- data.recycle();
- reply.recycle();
- return list;
- }
- public void moveTaskToFront(int task) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeInt(task);
- mRemote.transact(MOVE_TASK_TO_FRONT_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void moveTaskToBack(int task) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeInt(task);
- mRemote.transact(MOVE_TASK_TO_BACK_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- data.writeInt(nonRoot ? 1 : 0);
- mRemote.transact(MOVE_ACTIVITY_TASK_TO_BACK_TRANSACTION, data, reply, 0);
- reply.readException();
- boolean res = reply.readInt() != 0;
- data.recycle();
- reply.recycle();
- return res;
- }
- public void moveTaskBackwards(int task) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeInt(task);
- mRemote.transact(MOVE_TASK_BACKWARDS_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- data.writeInt(onlyRoot ? 1 : 0);
- mRemote.transact(GET_TASK_FOR_ACTIVITY_TRANSACTION, data, reply, 0);
- reply.readException();
- int res = reply.readInt();
- data.recycle();
- reply.recycle();
- return res;
- }
- public void finishOtherInstances(IBinder token, ComponentName className) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- ComponentName.writeToParcel(className, data);
- mRemote.transact(FINISH_OTHER_INSTANCES_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void reportThumbnail(IBinder token,
- Bitmap thumbnail, CharSequence description) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- if (thumbnail != null) {
- data.writeInt(1);
- thumbnail.writeToParcel(data, 0);
- } else {
- data.writeInt(0);
- }
- TextUtils.writeToParcel(description, data, 0);
- mRemote.transact(REPORT_THUMBNAIL_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public ContentProviderHolder getContentProvider(IApplicationThread caller,
- String name) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- data.writeString(name);
- mRemote.transact(GET_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
- reply.readException();
- int res = reply.readInt();
- ContentProviderHolder cph = null;
- if (res != 0) {
- cph = ContentProviderHolder.CREATOR.createFromParcel(reply);
- }
- data.recycle();
- reply.recycle();
- return cph;
- }
- public void publishContentProviders(IApplicationThread caller,
- List<ContentProviderHolder> providers) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- data.writeTypedList(providers);
- mRemote.transact(PUBLISH_CONTENT_PROVIDERS_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
-
- public void removeContentProvider(IApplicationThread caller,
- String name) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- data.writeString(name);
- mRemote.transact(REMOVE_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
-
- public ComponentName startService(IApplicationThread caller, Intent service,
- String resolvedType) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- service.writeToParcel(data, 0);
- data.writeString(resolvedType);
- mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
- reply.readException();
- ComponentName res = ComponentName.readFromParcel(reply);
- data.recycle();
- reply.recycle();
- return res;
- }
- public int stopService(IApplicationThread caller, Intent service,
- String resolvedType) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- service.writeToParcel(data, 0);
- data.writeString(resolvedType);
- mRemote.transact(STOP_SERVICE_TRANSACTION, data, reply, 0);
- reply.readException();
- int res = reply.readInt();
- reply.recycle();
- data.recycle();
- return res;
- }
- public boolean stopServiceToken(ComponentName className, IBinder token,
- int startId) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- ComponentName.writeToParcel(className, data);
- data.writeStrongBinder(token);
- data.writeInt(startId);
- mRemote.transact(STOP_SERVICE_TOKEN_TRANSACTION, data, reply, 0);
- reply.readException();
- boolean res = reply.readInt() != 0;
- data.recycle();
- reply.recycle();
- return res;
- }
- public void setServiceForeground(ComponentName className, IBinder token,
- boolean isForeground) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- ComponentName.writeToParcel(className, data);
- data.writeStrongBinder(token);
- data.writeInt(isForeground ? 1 : 0);
- mRemote.transact(SET_SERVICE_FOREGROUND_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public int bindService(IApplicationThread caller, IBinder token,
- Intent service, String resolvedType, IServiceConnection connection,
- int flags) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- data.writeStrongBinder(token);
- service.writeToParcel(data, 0);
- data.writeString(resolvedType);
- data.writeStrongBinder(connection.asBinder());
- data.writeInt(flags);
- mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
- reply.readException();
- int res = reply.readInt();
- data.recycle();
- reply.recycle();
- return res;
- }
- public boolean unbindService(IServiceConnection connection) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(connection.asBinder());
- mRemote.transact(UNBIND_SERVICE_TRANSACTION, data, reply, 0);
- reply.readException();
- boolean res = reply.readInt() != 0;
- data.recycle();
- reply.recycle();
- return res;
- }
-
- public void publishService(IBinder token,
- Intent intent, IBinder service) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- intent.writeToParcel(data, 0);
- data.writeStrongBinder(service);
- mRemote.transact(PUBLISH_SERVICE_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
-
- public void unbindFinished(IBinder token, Intent intent, boolean doRebind)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- intent.writeToParcel(data, 0);
- data.writeInt(doRebind ? 1 : 0);
- mRemote.transact(UNBIND_FINISHED_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
-
- public void serviceDoneExecuting(IBinder token) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- mRemote.transact(SERVICE_DONE_EXECUTING_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
-
- public IBinder peekService(Intent service, String resolvedType) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- service.writeToParcel(data, 0);
- data.writeString(resolvedType);
- mRemote.transact(PEEK_SERVICE_TRANSACTION, data, reply, 0);
- reply.readException();
- IBinder binder = reply.readStrongBinder();
- reply.recycle();
- data.recycle();
- return binder;
- }
-
- public boolean startInstrumentation(ComponentName className, String profileFile,
- int flags, Bundle arguments, IInstrumentationWatcher watcher)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- ComponentName.writeToParcel(className, data);
- data.writeString(profileFile);
- data.writeInt(flags);
- data.writeBundle(arguments);
- data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
- mRemote.transact(START_INSTRUMENTATION_TRANSACTION, data, reply, 0);
- reply.readException();
- boolean res = reply.readInt() != 0;
- reply.recycle();
- data.recycle();
- return res;
- }
-
- public void finishInstrumentation(IApplicationThread target,
- int resultCode, Bundle results) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(target != null ? target.asBinder() : null);
- data.writeInt(resultCode);
- data.writeBundle(results);
- mRemote.transact(FINISH_INSTRUMENTATION_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public Configuration getConfiguration() throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(GET_CONFIGURATION_TRANSACTION, data, reply, 0);
- reply.readException();
- Configuration res = Configuration.CREATOR.createFromParcel(reply);
- reply.recycle();
- data.recycle();
- return res;
- }
- public void updateConfiguration(Configuration values) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- values.writeToParcel(data, 0);
- mRemote.transact(UPDATE_CONFIGURATION_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void setRequestedOrientation(IBinder token, int requestedOrientation)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- data.writeInt(requestedOrientation);
- mRemote.transact(SET_REQUESTED_ORIENTATION_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public int getRequestedOrientation(IBinder token) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- mRemote.transact(GET_REQUESTED_ORIENTATION_TRANSACTION, data, reply, 0);
- reply.readException();
- int res = reply.readInt();
- data.recycle();
- reply.recycle();
- return res;
- }
- public ComponentName getActivityClassForToken(IBinder token)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- mRemote.transact(GET_ACTIVITY_CLASS_FOR_TOKEN_TRANSACTION, data, reply, 0);
- reply.readException();
- ComponentName res = ComponentName.readFromParcel(reply);
- data.recycle();
- reply.recycle();
- return res;
- }
- public String getPackageForToken(IBinder token) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- mRemote.transact(GET_PACKAGE_FOR_TOKEN_TRANSACTION, data, reply, 0);
- reply.readException();
- String res = reply.readString();
- data.recycle();
- reply.recycle();
- return res;
- }
- public IIntentSender getIntentSender(int type,
- String packageName, IBinder token, String resultWho,
- int requestCode, Intent intent, String resolvedType, int flags)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeInt(type);
- data.writeString(packageName);
- data.writeStrongBinder(token);
- data.writeString(resultWho);
- data.writeInt(requestCode);
- if (intent != null) {
- data.writeInt(1);
- intent.writeToParcel(data, 0);
- } else {
- data.writeInt(0);
- }
- data.writeString(resolvedType);
- data.writeInt(flags);
- mRemote.transact(GET_INTENT_SENDER_TRANSACTION, data, reply, 0);
- reply.readException();
- IIntentSender res = IIntentSender.Stub.asInterface(
- reply.readStrongBinder());
- data.recycle();
- reply.recycle();
- return res;
- }
- public void cancelIntentSender(IIntentSender sender) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(sender.asBinder());
- mRemote.transact(CANCEL_INTENT_SENDER_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public String getPackageForIntentSender(IIntentSender sender) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(sender.asBinder());
- mRemote.transact(GET_PACKAGE_FOR_INTENT_SENDER_TRANSACTION, data, reply, 0);
- reply.readException();
- String res = reply.readString();
- data.recycle();
- reply.recycle();
- return res;
- }
- public void setProcessLimit(int max) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeInt(max);
- mRemote.transact(SET_PROCESS_LIMIT_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public int getProcessLimit() throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(GET_PROCESS_LIMIT_TRANSACTION, data, reply, 0);
- reply.readException();
- int res = reply.readInt();
- data.recycle();
- reply.recycle();
- return res;
- }
- public void setProcessForeground(IBinder token, int pid,
- boolean isForeground) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- data.writeInt(pid);
- data.writeInt(isForeground ? 1 : 0);
- mRemote.transact(SET_PROCESS_FOREGROUND_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public int checkPermission(String permission, int pid, int uid)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeString(permission);
- data.writeInt(pid);
- data.writeInt(uid);
- mRemote.transact(CHECK_PERMISSION_TRANSACTION, data, reply, 0);
- reply.readException();
- int res = reply.readInt();
- data.recycle();
- reply.recycle();
- return res;
- }
- public boolean clearApplicationUserData(final String packageName,
- final IPackageDataObserver observer) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeString(packageName);
- data.writeStrongBinder(observer.asBinder());
- mRemote.transact(CLEAR_APP_DATA_TRANSACTION, data, reply, 0);
- reply.readException();
- boolean res = reply.readInt() != 0;
- data.recycle();
- reply.recycle();
- return res;
- }
- public int checkUriPermission(Uri uri, int pid, int uid, int mode)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- uri.writeToParcel(data, 0);
- data.writeInt(pid);
- data.writeInt(uid);
- data.writeInt(mode);
- mRemote.transact(CHECK_URI_PERMISSION_TRANSACTION, data, reply, 0);
- reply.readException();
- int res = reply.readInt();
- data.recycle();
- reply.recycle();
- return res;
- }
- public void grantUriPermission(IApplicationThread caller, String targetPkg,
- Uri uri, int mode) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller.asBinder());
- data.writeString(targetPkg);
- uri.writeToParcel(data, 0);
- data.writeInt(mode);
- mRemote.transact(GRANT_URI_PERMISSION_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void revokeUriPermission(IApplicationThread caller, Uri uri,
- int mode) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller.asBinder());
- uri.writeToParcel(data, 0);
- data.writeInt(mode);
- mRemote.transact(REVOKE_URI_PERMISSION_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void showWaitingForDebugger(IApplicationThread who, boolean waiting)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(who.asBinder());
- data.writeInt(waiting ? 1 : 0);
- mRemote.transact(SHOW_WAITING_FOR_DEBUGGER_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(GET_MEMORY_INFO_TRANSACTION, data, reply, 0);
- reply.readException();
- outInfo.readFromParcel(reply);
- data.recycle();
- reply.recycle();
- }
- public void unhandledBack() throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(UNHANDLED_BACK_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(OPEN_CONTENT_URI_TRANSACTION, data, reply, 0);
- reply.readException();
- ParcelFileDescriptor pfd = null;
- if (reply.readInt() != 0) {
- pfd = ParcelFileDescriptor.CREATOR.createFromParcel(reply);
- }
- data.recycle();
- reply.recycle();
- return pfd;
- }
- public void goingToSleep() throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(GOING_TO_SLEEP_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void wakingUp() throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(WAKING_UP_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void setDebugApp(
- String packageName, boolean waitForDebugger, boolean persistent)
- throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeString(packageName);
- data.writeInt(waitForDebugger ? 1 : 0);
- data.writeInt(persistent ? 1 : 0);
- mRemote.transact(SET_DEBUG_APP_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void setAlwaysFinish(boolean enabled) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeInt(enabled ? 1 : 0);
- mRemote.transact(SET_ALWAYS_FINISH_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void setActivityWatcher(IActivityWatcher watcher) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
- mRemote.transact(SET_ACTIVITY_WATCHER_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void enterSafeMode() throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(ENTER_SAFE_MODE_TRANSACTION, data, null, 0);
- data.recycle();
- }
- public void noteWakeupAlarm(IIntentSender sender) throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeStrongBinder(sender.asBinder());
- data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(NOTE_WAKEUP_ALARM_TRANSACTION, data, null, 0);
- data.recycle();
- }
- public boolean killPidsForMemory(int[] pids) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeIntArray(pids);
- mRemote.transact(KILL_PIDS_FOR_MEMORY_TRANSACTION, data, reply, 0);
- boolean res = reply.readInt() != 0;
- data.recycle();
- reply.recycle();
- return res;
- }
- public void reportPss(IApplicationThread caller, int pss) throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller.asBinder());
- data.writeInt(pss);
- mRemote.transact(REPORT_PSS_TRANSACTION, data, null, 0);
- data.recycle();
- }
- public void startRunning(String pkg, String cls, String action,
- String indata) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeString(pkg);
- data.writeString(cls);
- data.writeString(action);
- data.writeString(indata);
- mRemote.transact(START_RUNNING_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public void systemReady() throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(SYSTEM_READY_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
- public boolean testIsSystemReady()
- {
- /* this base class version is never called */
- return true;
- }
- public int handleApplicationError(IBinder app, int flags,
- String tag, String shortMsg, String longMsg,
- byte[] crashData) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(app);
- data.writeInt(flags);
- data.writeString(tag);
- data.writeString(shortMsg);
- data.writeString(longMsg);
- data.writeByteArray(crashData);
- mRemote.transact(HANDLE_APPLICATION_ERROR_TRANSACTION, data, reply, 0);
- reply.readException();
- int res = reply.readInt();
- reply.recycle();
- data.recycle();
- return res;
- }
-
- public void signalPersistentProcesses(int sig) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeInt(sig);
- mRemote.transact(SIGNAL_PERSISTENT_PROCESSES_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
-
- public void restartPackage(String packageName) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeString(packageName);
- mRemote.transact(RESTART_PACKAGE_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
-
- public ConfigurationInfo getDeviceConfigurationInfo() throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(GET_DEVICE_CONFIGURATION_TRANSACTION, data, reply, 0);
- reply.readException();
- ConfigurationInfo res = ConfigurationInfo.CREATOR.createFromParcel(reply);
- reply.recycle();
- data.recycle();
- return res;
- }
- private IBinder mRemote;
-}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
deleted file mode 100644
index bf5616e..0000000
--- a/core/java/android/app/ActivityThread.java
+++ /dev/null
@@ -1,3916 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.BroadcastReceiver;
-import android.content.ComponentCallbacks;
-import android.content.ComponentName;
-import android.content.ContentProvider;
-import android.content.Context;
-import android.content.IContentProvider;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.InstrumentationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ServiceInfo;
-import android.content.res.AssetManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteDebug;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.net.http.AndroidHttpClient;
-import android.os.Bundle;
-import android.os.Debug;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.MessageQueue;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.util.AndroidRuntimeException;
-import android.util.Config;
-import android.util.DisplayMetrics;
-import android.util.EventLog;
-import android.util.Log;
-import android.view.Display;
-import android.view.View;
-import android.view.ViewDebug;
-import android.view.ViewManager;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.WindowManagerImpl;
-
-import com.android.internal.os.BinderInternal;
-import com.android.internal.os.RuntimeInit;
-import com.android.internal.util.ArrayUtils;
-
-import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
-
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.regex.Pattern;
-
-final class IntentReceiverLeaked extends AndroidRuntimeException {
- public IntentReceiverLeaked(String msg) {
- super(msg);
- }
-}
-
-final class ServiceConnectionLeaked extends AndroidRuntimeException {
- public ServiceConnectionLeaked(String msg) {
- super(msg);
- }
-}
-
-final class SuperNotCalledException extends AndroidRuntimeException {
- public SuperNotCalledException(String msg) {
- super(msg);
- }
-}
-
-/**
- * This manages the execution of the main thread in an
- * application process, scheduling and executing activities,
- * broadcasts, and other operations on it as the activity
- * manager requests.
- *
- * {@hide}
- */
-public final class ActivityThread {
- private static final String TAG = "ActivityThread";
- private static final boolean DEBUG = false;
- private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
- private static final boolean DEBUG_BROADCAST = false;
- private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
- private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";");
- private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
- private static final int LOG_ON_PAUSE_CALLED = 30021;
- private static final int LOG_ON_RESUME_CALLED = 30022;
-
-
- public static final ActivityThread currentActivityThread() {
- return (ActivityThread)sThreadLocal.get();
- }
-
- public static final String currentPackageName()
- {
- ActivityThread am = currentActivityThread();
- return (am != null && am.mBoundApplication != null)
- ? am.mBoundApplication.processName : null;
- }
-
- public static IPackageManager getPackageManager() {
- if (sPackageManager != null) {
- //Log.v("PackageManager", "returning cur default = " + sPackageManager);
- return sPackageManager;
- }
- IBinder b = ServiceManager.getService("package");
- //Log.v("PackageManager", "default service binder = " + b);
- sPackageManager = IPackageManager.Stub.asInterface(b);
- //Log.v("PackageManager", "default service = " + sPackageManager);
- return sPackageManager;
- }
-
- DisplayMetrics getDisplayMetricsLocked(boolean forceUpdate) {
- if (mDisplayMetrics != null && !forceUpdate) {
- return mDisplayMetrics;
- }
- if (mDisplay == null) {
- WindowManager wm = WindowManagerImpl.getDefault();
- mDisplay = wm.getDefaultDisplay();
- }
- DisplayMetrics metrics = mDisplayMetrics = new DisplayMetrics();
- mDisplay.getMetrics(metrics);
- //Log.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
- // + metrics.heightPixels + " den=" + metrics.density
- // + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
- return metrics;
- }
-
- Resources getTopLevelResources(String appDir) {
- synchronized (mPackages) {
- //Log.w(TAG, "getTopLevelResources: " + appDir);
- WeakReference<Resources> wr = mActiveResources.get(appDir);
- Resources r = wr != null ? wr.get() : null;
- if (r != null && r.getAssets().isUpToDate()) {
- //Log.w(TAG, "Returning cached resources " + r + " " + appDir);
- return r;
- }
-
- //if (r != null) {
- // Log.w(TAG, "Throwing away out-of-date resources!!!! "
- // + r + " " + appDir);
- //}
-
- AssetManager assets = new AssetManager();
- if (assets.addAssetPath(appDir) == 0) {
- return null;
- }
- DisplayMetrics metrics = getDisplayMetricsLocked(false);
- r = new Resources(assets, metrics, getConfiguration());
- //Log.i(TAG, "Created app resources " + r + ": " + r.getConfiguration());
- // XXX need to remove entries when weak references go away
- mActiveResources.put(appDir, new WeakReference<Resources>(r));
- return r;
- }
- }
-
- final Handler getHandler() {
- return mH;
- }
-
- public final static class PackageInfo {
-
- private final ActivityThread mActivityThread;
- private final ApplicationInfo mApplicationInfo;
- private final String mPackageName;
- private final String mAppDir;
- private final String mResDir;
- private final String[] mSharedLibraries;
- private final String mDataDir;
- private final File mDataDirFile;
- private final ClassLoader mBaseClassLoader;
- private final boolean mSecurityViolation;
- private final boolean mIncludeCode;
- private Resources mResources;
- private ClassLoader mClassLoader;
- private Application mApplication;
- private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
- = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
- private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mUnregisteredReceivers
- = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
- private final HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>> mServices
- = new HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>>();
- private final HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>> mUnboundServices
- = new HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>>();
-
- int mClientCount = 0;
-
- public PackageInfo(ActivityThread activityThread, ApplicationInfo aInfo,
- ActivityThread mainThread, ClassLoader baseLoader,
- boolean securityViolation, boolean includeCode) {
- mActivityThread = activityThread;
- mApplicationInfo = aInfo;
- mPackageName = aInfo.packageName;
- mAppDir = aInfo.sourceDir;
- mResDir = aInfo.uid == Process.myUid() ? aInfo.sourceDir
- : aInfo.publicSourceDir;
- mSharedLibraries = aInfo.sharedLibraryFiles;
- mDataDir = aInfo.dataDir;
- mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
- mBaseClassLoader = baseLoader;
- mSecurityViolation = securityViolation;
- mIncludeCode = includeCode;
-
- if (mAppDir == null) {
- if (mSystemContext == null) {
- mSystemContext =
- ApplicationContext.createSystemContext(mainThread);
- mSystemContext.getResources().updateConfiguration(
- mainThread.getConfiguration(),
- mainThread.getDisplayMetricsLocked(false));
- //Log.i(TAG, "Created system resources "
- // + mSystemContext.getResources() + ": "
- // + mSystemContext.getResources().getConfiguration());
- }
- mClassLoader = mSystemContext.getClassLoader();
- mResources = mSystemContext.getResources();
- }
- }
-
- public PackageInfo(ActivityThread activityThread, String name,
- Context systemContext) {
- mActivityThread = activityThread;
- mApplicationInfo = new ApplicationInfo();
- mApplicationInfo.packageName = name;
- mPackageName = name;
- mAppDir = null;
- mResDir = null;
- mSharedLibraries = null;
- mDataDir = null;
- mDataDirFile = null;
- mBaseClassLoader = null;
- mSecurityViolation = false;
- mIncludeCode = true;
- mClassLoader = systemContext.getClassLoader();
- mResources = systemContext.getResources();
- }
-
- public String getPackageName() {
- return mPackageName;
- }
-
- public boolean isSecurityViolation() {
- return mSecurityViolation;
- }
-
- /**
- * Gets the array of shared libraries that are listed as
- * used by the given package.
- *
- * @param packageName the name of the package (note: not its
- * file name)
- * @return null-ok; the array of shared libraries, each one
- * a fully-qualified path
- */
- private static String[] getLibrariesFor(String packageName) {
- ApplicationInfo ai = null;
- try {
- ai = getPackageManager().getApplicationInfo(packageName,
- PackageManager.GET_SHARED_LIBRARY_FILES);
- } catch (RemoteException e) {
- throw new AssertionError(e);
- }
-
- if (ai == null) {
- return null;
- }
-
- return ai.sharedLibraryFiles;
- }
-
- /**
- * Combines two arrays (of library names) such that they are
- * concatenated in order but are devoid of duplicates. The
- * result is a single string with the names of the libraries
- * separated by colons, or <code>null</code> if both lists
- * were <code>null</code> or empty.
- *
- * @param list1 null-ok; the first list
- * @param list2 null-ok; the second list
- * @return null-ok; the combination
- */
- private static String combineLibs(String[] list1, String[] list2) {
- StringBuilder result = new StringBuilder(300);
- boolean first = true;
-
- if (list1 != null) {
- for (String s : list1) {
- if (first) {
- first = false;
- } else {
- result.append(':');
- }
- result.append(s);
- }
- }
-
- // Only need to check for duplicates if list1 was non-empty.
- boolean dupCheck = !first;
-
- if (list2 != null) {
- for (String s : list2) {
- if (dupCheck && ArrayUtils.contains(list1, s)) {
- continue;
- }
-
- if (first) {
- first = false;
- } else {
- result.append(':');
- }
- result.append(s);
- }
- }
-
- return result.toString();
- }
-
- public ClassLoader getClassLoader() {
- synchronized (this) {
- if (mClassLoader != null) {
- return mClassLoader;
- }
-
- if (mIncludeCode && !mPackageName.equals("android")) {
- String zip = mAppDir;
-
- /*
- * The following is a bit of a hack to inject
- * instrumentation into the system: If the app
- * being started matches one of the instrumentation names,
- * then we combine both the "instrumentation" and
- * "instrumented" app into the path, along with the
- * concatenation of both apps' shared library lists.
- */
-
- String instrumentationAppDir =
- mActivityThread.mInstrumentationAppDir;
- String instrumentationAppPackage =
- mActivityThread.mInstrumentationAppPackage;
- String instrumentedAppDir =
- mActivityThread.mInstrumentedAppDir;
- String[] instrumentationLibs = null;
-
- if (mAppDir.equals(instrumentationAppDir)
- || mAppDir.equals(instrumentedAppDir)) {
- zip = instrumentationAppDir + ":" + instrumentedAppDir;
- if (! instrumentedAppDir.equals(instrumentationAppDir)) {
- instrumentationLibs =
- getLibrariesFor(instrumentationAppPackage);
- }
- }
-
- if ((mSharedLibraries != null) ||
- (instrumentationLibs != null)) {
- zip =
- combineLibs(mSharedLibraries, instrumentationLibs)
- + ':' + zip;
- }
-
- /*
- * With all the combination done (if necessary, actually
- * create the class loader.
- */
-
- if (localLOGV) Log.v(TAG, "Class path: " + zip);
-
- mClassLoader =
- ApplicationLoaders.getDefault().getClassLoader(
- zip, mDataDir, mBaseClassLoader);
- } else {
- if (mBaseClassLoader == null) {
- mClassLoader = ClassLoader.getSystemClassLoader();
- } else {
- mClassLoader = mBaseClassLoader;
- }
- }
- return mClassLoader;
- }
- }
-
- public String getAppDir() {
- return mAppDir;
- }
-
- public String getResDir() {
- return mResDir;
- }
-
- public String getDataDir() {
- return mDataDir;
- }
-
- public File getDataDirFile() {
- return mDataDirFile;
- }
-
- public AssetManager getAssets(ActivityThread mainThread) {
- return getResources(mainThread).getAssets();
- }
-
- public Resources getResources(ActivityThread mainThread) {
- if (mResources == null) {
- mResources = mainThread.getTopLevelResources(mResDir);
- }
- return mResources;
- }
-
- public Application makeApplication() {
- if (mApplication != null) {
- return mApplication;
- }
-
- Application app = null;
-
- String appClass = mApplicationInfo.className;
- if (appClass == null) {
- appClass = "android.app.Application";
- }
-
- try {
- java.lang.ClassLoader cl = getClassLoader();
- ApplicationContext appContext = new ApplicationContext();
- appContext.init(this, null, mActivityThread);
- app = mActivityThread.mInstrumentation.newApplication(
- cl, appClass, appContext);
- appContext.setOuterContext(app);
- } catch (Exception e) {
- if (!mActivityThread.mInstrumentation.onException(app, e)) {
- throw new RuntimeException(
- "Unable to instantiate application " + appClass
- + ": " + e.toString(), e);
- }
- }
- mActivityThread.mAllApplications.add(app);
- return mApplication = app;
- }
-
- public void removeContextRegistrations(Context context,
- String who, String what) {
- HashMap<BroadcastReceiver, ReceiverDispatcher> rmap =
- mReceivers.remove(context);
- if (rmap != null) {
- Iterator<ReceiverDispatcher> it = rmap.values().iterator();
- while (it.hasNext()) {
- ReceiverDispatcher rd = it.next();
- IntentReceiverLeaked leak = new IntentReceiverLeaked(
- what + " " + who + " has leaked IntentReceiver "
- + rd.getIntentReceiver() + " that was " +
- "originally registered here. Are you missing a " +
- "call to unregisterReceiver()?");
- leak.setStackTrace(rd.getLocation().getStackTrace());
- Log.e(TAG, leak.getMessage(), leak);
- try {
- ActivityManagerNative.getDefault().unregisterReceiver(
- rd.getIIntentReceiver());
- } catch (RemoteException e) {
- // system crashed, nothing we can do
- }
- }
- }
- mUnregisteredReceivers.remove(context);
- //Log.i(TAG, "Receiver registrations: " + mReceivers);
- HashMap<ServiceConnection, ServiceDispatcher> smap =
- mServices.remove(context);
- if (smap != null) {
- Iterator<ServiceDispatcher> it = smap.values().iterator();
- while (it.hasNext()) {
- ServiceDispatcher sd = it.next();
- ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
- what + " " + who + " has leaked ServiceConnection "
- + sd.getServiceConnection() + " that was originally bound here");
- leak.setStackTrace(sd.getLocation().getStackTrace());
- Log.e(TAG, leak.getMessage(), leak);
- try {
- ActivityManagerNative.getDefault().unbindService(
- sd.getIServiceConnection());
- } catch (RemoteException e) {
- // system crashed, nothing we can do
- }
- sd.doForget();
- }
- }
- mUnboundServices.remove(context);
- //Log.i(TAG, "Service registrations: " + mServices);
- }
-
- public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
- Context context, Handler handler,
- Instrumentation instrumentation, boolean registered) {
- synchronized (mReceivers) {
- ReceiverDispatcher rd = null;
- HashMap<BroadcastReceiver, ReceiverDispatcher> map = null;
- if (registered) {
- map = mReceivers.get(context);
- if (map != null) {
- rd = map.get(r);
- }
- }
- if (rd == null) {
- rd = new ReceiverDispatcher(r, context, handler,
- instrumentation, registered);
- if (registered) {
- if (map == null) {
- map = new HashMap<BroadcastReceiver, ReceiverDispatcher>();
- mReceivers.put(context, map);
- }
- map.put(r, rd);
- }
- } else {
- rd.validate(context, handler);
- }
- return rd.getIIntentReceiver();
- }
- }
-
- public IIntentReceiver forgetReceiverDispatcher(Context context,
- BroadcastReceiver r) {
- synchronized (mReceivers) {
- HashMap<BroadcastReceiver, ReceiverDispatcher> map = mReceivers.get(context);
- ReceiverDispatcher rd = null;
- if (map != null) {
- rd = map.get(r);
- if (rd != null) {
- map.remove(r);
- if (map.size() == 0) {
- mReceivers.remove(context);
- }
- if (r.getDebugUnregister()) {
- HashMap<BroadcastReceiver, ReceiverDispatcher> holder
- = mUnregisteredReceivers.get(context);
- if (holder == null) {
- holder = new HashMap<BroadcastReceiver, ReceiverDispatcher>();
- mUnregisteredReceivers.put(context, holder);
- }
- RuntimeException ex = new IllegalArgumentException(
- "Originally unregistered here:");
- ex.fillInStackTrace();
- rd.setUnregisterLocation(ex);
- holder.put(r, rd);
- }
- return rd.getIIntentReceiver();
- }
- }
- HashMap<BroadcastReceiver, ReceiverDispatcher> holder
- = mUnregisteredReceivers.get(context);
- if (holder != null) {
- rd = holder.get(r);
- if (rd != null) {
- RuntimeException ex = rd.getUnregisterLocation();
- throw new IllegalArgumentException(
- "Unregistering Receiver " + r
- + " that was already unregistered", ex);
- }
- }
- if (context == null) {
- throw new IllegalStateException("Unbinding Receiver " + r
- + " from Context that is no longer in use: " + context);
- } else {
- throw new IllegalArgumentException("Receiver not registered: " + r);
- }
-
- }
- }
-
- static final class ReceiverDispatcher {
-
- final static class InnerReceiver extends IIntentReceiver.Stub {
- final WeakReference<ReceiverDispatcher> mDispatcher;
- final ReceiverDispatcher mStrongRef;
-
- InnerReceiver(ReceiverDispatcher rd, boolean strong) {
- mDispatcher = new WeakReference<ReceiverDispatcher>(rd);
- mStrongRef = strong ? rd : null;
- }
- public void performReceive(Intent intent, int resultCode,
- String data, Bundle extras, boolean ordered) {
- ReceiverDispatcher rd = mDispatcher.get();
- if (DEBUG_BROADCAST) {
- int seq = intent.getIntExtra("seq", -1);
- Log.i(TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
- + " to " + rd);
- }
- if (rd != null) {
- rd.performReceive(intent, resultCode, data, extras, ordered);
- }
- }
- }
-
- final IIntentReceiver.Stub mIIntentReceiver;
- final BroadcastReceiver mReceiver;
- final Context mContext;
- final Handler mActivityThread;
- final Instrumentation mInstrumentation;
- final boolean mRegistered;
- final IntentReceiverLeaked mLocation;
- RuntimeException mUnregisterLocation;
-
- final class Args implements Runnable {
- private Intent mCurIntent;
- private int mCurCode;
- private String mCurData;
- private Bundle mCurMap;
- private boolean mCurOrdered;
-
- public void run() {
- BroadcastReceiver receiver = mReceiver;
- if (DEBUG_BROADCAST) {
- int seq = mCurIntent.getIntExtra("seq", -1);
- Log.i(TAG, "Dispathing broadcast " + mCurIntent.getAction() + " seq=" + seq
- + " to " + mReceiver);
- }
- if (receiver == null) {
- return;
- }
-
- IActivityManager mgr = ActivityManagerNative.getDefault();
- Intent intent = mCurIntent;
- mCurIntent = null;
- try {
- ClassLoader cl = mReceiver.getClass().getClassLoader();
- intent.setExtrasClassLoader(cl);
- if (mCurMap != null) {
- mCurMap.setClassLoader(cl);
- }
- receiver.setOrderedHint(true);
- receiver.setResult(mCurCode, mCurData, mCurMap);
- receiver.clearAbortBroadcast();
- receiver.setOrderedHint(mCurOrdered);
- receiver.onReceive(mContext, intent);
- } catch (Exception e) {
- if (mRegistered && mCurOrdered) {
- try {
- mgr.finishReceiver(mIIntentReceiver,
- mCurCode, mCurData, mCurMap, false);
- } catch (RemoteException ex) {
- }
- }
- if (mInstrumentation == null ||
- !mInstrumentation.onException(mReceiver, e)) {
- throw new RuntimeException(
- "Error receiving broadcast " + intent
- + " in " + mReceiver, e);
- }
- }
- if (mRegistered && mCurOrdered) {
- try {
- mgr.finishReceiver(mIIntentReceiver,
- receiver.getResultCode(),
- receiver.getResultData(),
- receiver.getResultExtras(false),
- receiver.getAbortBroadcast());
- } catch (RemoteException ex) {
- }
- }
- }
- }
-
- ReceiverDispatcher(BroadcastReceiver receiver, Context context,
- Handler activityThread, Instrumentation instrumentation,
- boolean registered) {
- if (activityThread == null) {
- throw new NullPointerException("Handler must not be null");
- }
-
- mIIntentReceiver = new InnerReceiver(this, !registered);
- mReceiver = receiver;
- mContext = context;
- mActivityThread = activityThread;
- mInstrumentation = instrumentation;
- mRegistered = registered;
- mLocation = new IntentReceiverLeaked(null);
- mLocation.fillInStackTrace();
- }
-
- void validate(Context context, Handler activityThread) {
- if (mContext != context) {
- throw new IllegalStateException(
- "Receiver " + mReceiver +
- " registered with differing Context (was " +
- mContext + " now " + context + ")");
- }
- if (mActivityThread != activityThread) {
- throw new IllegalStateException(
- "Receiver " + mReceiver +
- " registered with differing handler (was " +
- mActivityThread + " now " + activityThread + ")");
- }
- }
-
- IntentReceiverLeaked getLocation() {
- return mLocation;
- }
-
- BroadcastReceiver getIntentReceiver() {
- return mReceiver;
- }
-
- IIntentReceiver getIIntentReceiver() {
- return mIIntentReceiver;
- }
-
- void setUnregisterLocation(RuntimeException ex) {
- mUnregisterLocation = ex;
- }
-
- RuntimeException getUnregisterLocation() {
- return mUnregisterLocation;
- }
-
- public void performReceive(Intent intent, int resultCode,
- String data, Bundle extras, boolean ordered) {
- if (DEBUG_BROADCAST) {
- int seq = intent.getIntExtra("seq", -1);
- Log.i(TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
- + " to " + mReceiver);
- }
- Args args = new Args();
- args.mCurIntent = intent;
- args.mCurCode = resultCode;
- args.mCurData = data;
- args.mCurMap = extras;
- args.mCurOrdered = ordered;
- if (!mActivityThread.post(args)) {
- if (mRegistered) {
- IActivityManager mgr = ActivityManagerNative.getDefault();
- try {
- mgr.finishReceiver(mIIntentReceiver, args.mCurCode,
- args.mCurData, args.mCurMap, false);
- } catch (RemoteException ex) {
- }
- }
- }
- }
-
- }
-
- public final IServiceConnection getServiceDispatcher(ServiceConnection c,
- Context context, Handler handler, int flags) {
- synchronized (mServices) {
- ServiceDispatcher sd = null;
- HashMap<ServiceConnection, ServiceDispatcher> map = mServices.get(context);
- if (map != null) {
- sd = map.get(c);
- }
- if (sd == null) {
- sd = new ServiceDispatcher(c, context, handler, flags);
- if (map == null) {
- map = new HashMap<ServiceConnection, ServiceDispatcher>();
- mServices.put(context, map);
- }
- map.put(c, sd);
- } else {
- sd.validate(context, handler);
- }
- return sd.getIServiceConnection();
- }
- }
-
- public final IServiceConnection forgetServiceDispatcher(Context context,
- ServiceConnection c) {
- synchronized (mServices) {
- HashMap<ServiceConnection, ServiceDispatcher> map
- = mServices.get(context);
- ServiceDispatcher sd = null;
- if (map != null) {
- sd = map.get(c);
- if (sd != null) {
- map.remove(c);
- sd.doForget();
- if (map.size() == 0) {
- mServices.remove(context);
- }
- if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
- HashMap<ServiceConnection, ServiceDispatcher> holder
- = mUnboundServices.get(context);
- if (holder == null) {
- holder = new HashMap<ServiceConnection, ServiceDispatcher>();
- mUnboundServices.put(context, holder);
- }
- RuntimeException ex = new IllegalArgumentException(
- "Originally unbound here:");
- ex.fillInStackTrace();
- sd.setUnbindLocation(ex);
- holder.put(c, sd);
- }
- return sd.getIServiceConnection();
- }
- }
- HashMap<ServiceConnection, ServiceDispatcher> holder
- = mUnboundServices.get(context);
- if (holder != null) {
- sd = holder.get(c);
- if (sd != null) {
- RuntimeException ex = sd.getUnbindLocation();
- throw new IllegalArgumentException(
- "Unbinding Service " + c
- + " that was already unbound", ex);
- }
- }
- if (context == null) {
- throw new IllegalStateException("Unbinding Service " + c
- + " from Context that is no longer in use: " + context);
- } else {
- throw new IllegalArgumentException("Service not registered: " + c);
- }
- }
- }
-
- static final class ServiceDispatcher {
- private final InnerConnection mIServiceConnection;
- private final ServiceConnection mConnection;
- private final Context mContext;
- private final Handler mActivityThread;
- private final ServiceConnectionLeaked mLocation;
- private final int mFlags;
-
- private RuntimeException mUnbindLocation;
-
- private boolean mDied;
-
- private static class ConnectionInfo {
- IBinder binder;
- IBinder.DeathRecipient deathMonitor;
- }
-
- private static class InnerConnection extends IServiceConnection.Stub {
- final WeakReference<ServiceDispatcher> mDispatcher;
-
- InnerConnection(ServiceDispatcher sd) {
- mDispatcher = new WeakReference<ServiceDispatcher>(sd);
- }
-
- public void connected(ComponentName name, IBinder service) throws RemoteException {
- ServiceDispatcher sd = mDispatcher.get();
- if (sd != null) {
- sd.connected(name, service);
- }
- }
- }
-
- private final HashMap<ComponentName, ConnectionInfo> mActiveConnections
- = new HashMap<ComponentName, ConnectionInfo>();
-
- ServiceDispatcher(ServiceConnection conn,
- Context context, Handler activityThread, int flags) {
- mIServiceConnection = new InnerConnection(this);
- mConnection = conn;
- mContext = context;
- mActivityThread = activityThread;
- mLocation = new ServiceConnectionLeaked(null);
- mLocation.fillInStackTrace();
- mFlags = flags;
- }
-
- void validate(Context context, Handler activityThread) {
- if (mContext != context) {
- throw new RuntimeException(
- "ServiceConnection " + mConnection +
- " registered with differing Context (was " +
- mContext + " now " + context + ")");
- }
- if (mActivityThread != activityThread) {
- throw new RuntimeException(
- "ServiceConnection " + mConnection +
- " registered with differing handler (was " +
- mActivityThread + " now " + activityThread + ")");
- }
- }
-
- void doForget() {
- synchronized(this) {
- Iterator<ConnectionInfo> it = mActiveConnections.values().iterator();
- while (it.hasNext()) {
- ConnectionInfo ci = it.next();
- ci.binder.unlinkToDeath(ci.deathMonitor, 0);
- }
- mActiveConnections.clear();
- }
- }
-
- ServiceConnectionLeaked getLocation() {
- return mLocation;
- }
-
- ServiceConnection getServiceConnection() {
- return mConnection;
- }
-
- IServiceConnection getIServiceConnection() {
- return mIServiceConnection;
- }
-
- int getFlags() {
- return mFlags;
- }
-
- void setUnbindLocation(RuntimeException ex) {
- mUnbindLocation = ex;
- }
-
- RuntimeException getUnbindLocation() {
- return mUnbindLocation;
- }
-
- public void connected(ComponentName name, IBinder service) {
- if (mActivityThread != null) {
- mActivityThread.post(new RunConnection(name, service, 0));
- } else {
- doConnected(name, service);
- }
- }
-
- public void death(ComponentName name, IBinder service) {
- ConnectionInfo old;
-
- synchronized (this) {
- mDied = true;
- old = mActiveConnections.remove(name);
- if (old == null || old.binder != service) {
- // Death for someone different than who we last
- // reported... just ignore it.
- return;
- }
- old.binder.unlinkToDeath(old.deathMonitor, 0);
- }
-
- if (mActivityThread != null) {
- mActivityThread.post(new RunConnection(name, service, 1));
- } else {
- doDeath(name, service);
- }
- }
-
- public void doConnected(ComponentName name, IBinder service) {
- ConnectionInfo old;
- ConnectionInfo info;
-
- synchronized (this) {
- old = mActiveConnections.get(name);
- if (old != null && old.binder == service) {
- // Huh, already have this one. Oh well!
- return;
- }
-
- if (service != null) {
- // A new service is being connected... set it all up.
- mDied = false;
- info = new ConnectionInfo();
- info.binder = service;
- info.deathMonitor = new DeathMonitor(name, service);
- try {
- service.linkToDeath(info.deathMonitor, 0);
- mActiveConnections.put(name, info);
- } catch (RemoteException e) {
- // This service was dead before we got it... just
- // don't do anything with it.
- mActiveConnections.remove(name);
- return;
- }
-
- } else {
- // The named service is being disconnected... clean up.
- mActiveConnections.remove(name);
- }
-
- if (old != null) {
- old.binder.unlinkToDeath(old.deathMonitor, 0);
- }
- }
-
- // If there was an old service, it is not disconnected.
- if (old != null) {
- mConnection.onServiceDisconnected(name);
- }
- // If there is a new service, it is now connected.
- if (service != null) {
- mConnection.onServiceConnected(name, service);
- }
- }
-
- public void doDeath(ComponentName name, IBinder service) {
- mConnection.onServiceDisconnected(name);
- }
-
- private final class RunConnection implements Runnable {
- RunConnection(ComponentName name, IBinder service, int command) {
- mName = name;
- mService = service;
- mCommand = command;
- }
-
- public void run() {
- if (mCommand == 0) {
- doConnected(mName, mService);
- } else if (mCommand == 1) {
- doDeath(mName, mService);
- }
- }
-
- final ComponentName mName;
- final IBinder mService;
- final int mCommand;
- }
-
- private final class DeathMonitor implements IBinder.DeathRecipient
- {
- DeathMonitor(ComponentName name, IBinder service) {
- mName = name;
- mService = service;
- }
-
- public void binderDied() {
- death(mName, mService);
- }
-
- final ComponentName mName;
- final IBinder mService;
- }
- }
- }
-
- private static ApplicationContext mSystemContext = null;
-
- private static final class ActivityRecord {
- IBinder token;
- Intent intent;
- Bundle state;
- Activity activity;
- Window window;
- Activity parent;
- String embeddedID;
- Object lastNonConfigurationInstance;
- HashMap<String,Object> lastNonConfigurationChildInstances;
- boolean paused;
- boolean stopped;
- boolean hideForNow;
- Configuration newConfig;
- ActivityRecord nextIdle;
-
- ActivityInfo activityInfo;
- PackageInfo packageInfo;
-
- List<ResultInfo> pendingResults;
- List<Intent> pendingIntents;
-
- boolean startsNotResumed;
- boolean isForward;
-
- ActivityRecord() {
- parent = null;
- embeddedID = null;
- paused = false;
- stopped = false;
- hideForNow = false;
- nextIdle = null;
- }
-
- public String toString() {
- ComponentName componentName = intent.getComponent();
- return "ActivityRecord{"
- + Integer.toHexString(System.identityHashCode(this))
- + " token=" + token + " " + (componentName == null
- ? "no component name" : componentName.toShortString())
- + "}";
- }
- }
-
- private final class ProviderRecord implements IBinder.DeathRecipient {
- final String mName;
- final IContentProvider mProvider;
- final ContentProvider mLocalProvider;
-
- ProviderRecord(String name, IContentProvider provider,
- ContentProvider localProvider) {
- mName = name;
- mProvider = provider;
- mLocalProvider = localProvider;
- }
-
- public void binderDied() {
- removeDeadProvider(mName, mProvider);
- }
- }
-
- private static final class NewIntentData {
- List<Intent> intents;
- IBinder token;
- public String toString() {
- return "NewIntentData{intents=" + intents + " token=" + token + "}";
- }
- }
-
- private static final class ReceiverData {
- Intent intent;
- ActivityInfo info;
- int resultCode;
- String resultData;
- Bundle resultExtras;
- boolean sync;
- boolean resultAbort;
- public String toString() {
- return "ReceiverData{intent=" + intent + " packageName=" +
- info.packageName + " resultCode=" + resultCode
- + " resultData=" + resultData + " resultExtras=" + resultExtras + "}";
- }
- }
-
- private static final class CreateServiceData {
- IBinder token;
- ServiceInfo info;
- Intent intent;
- public String toString() {
- return "CreateServiceData{token=" + token + " className="
- + info.name + " packageName=" + info.packageName
- + " intent=" + intent + "}";
- }
- }
-
- private static final class BindServiceData {
- IBinder token;
- Intent intent;
- boolean rebind;
- public String toString() {
- return "BindServiceData{token=" + token + " intent=" + intent + "}";
- }
- }
-
- private static final class ServiceArgsData {
- IBinder token;
- int startId;
- Intent args;
- public String toString() {
- return "ServiceArgsData{token=" + token + " startId=" + startId
- + " args=" + args + "}";
- }
- }
-
- private static final class AppBindData {
- PackageInfo info;
- String processName;
- ApplicationInfo appInfo;
- List<ProviderInfo> providers;
- ComponentName instrumentationName;
- String profileFile;
- Bundle instrumentationArgs;
- IInstrumentationWatcher instrumentationWatcher;
- int debugMode;
- Configuration config;
- boolean handlingProfiling;
- public String toString() {
- return "AppBindData{appInfo=" + appInfo + "}";
- }
- }
-
- private static final class DumpServiceInfo {
- FileDescriptor fd;
- IBinder service;
- String[] args;
- boolean dumped;
- }
-
- private static final class ResultData {
- IBinder token;
- List<ResultInfo> results;
- public String toString() {
- return "ResultData{token=" + token + " results" + results + "}";
- }
- }
-
- private static final class ContextCleanupInfo {
- ApplicationContext context;
- String what;
- String who;
- }
-
- private final class ApplicationThread extends ApplicationThreadNative {
- private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
- private static final String ONE_COUNT_COLUMN = "%17s %8d";
- private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d";
-
- // Formatting for checkin service - update version if row format changes
- private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
-
- public final void schedulePauseActivity(IBinder token, boolean finished,
- boolean userLeaving, int configChanges) {
- queueOrSendMessage(
- finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
- token,
- (userLeaving ? 1 : 0),
- configChanges);
- }
-
- public final void scheduleStopActivity(IBinder token, boolean showWindow,
- int configChanges) {
- queueOrSendMessage(
- showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
- token, 0, configChanges);
- }
-
- public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {
- queueOrSendMessage(
- showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW,
- token);
- }
-
- public final void scheduleResumeActivity(IBinder token, boolean isForward) {
- queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
- }
-
- public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
- ResultData res = new ResultData();
- res.token = token;
- res.results = results;
- queueOrSendMessage(H.SEND_RESULT, res);
- }
-
- // we use token to identify this activity without having to send the
- // activity itself back to the activity manager. (matters more with ipc)
- public final void scheduleLaunchActivity(Intent intent, IBinder token,
- ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
- List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) {
- ActivityRecord r = new ActivityRecord();
-
- r.token = token;
- r.intent = intent;
- r.activityInfo = info;
- r.state = state;
-
- r.pendingResults = pendingResults;
- r.pendingIntents = pendingNewIntents;
-
- r.startsNotResumed = notResumed;
- r.isForward = isForward;
-
- queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
- }
-
- public final void scheduleRelaunchActivity(IBinder token,
- List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
- int configChanges, boolean notResumed) {
- ActivityRecord r = new ActivityRecord();
-
- r.token = token;
- r.pendingResults = pendingResults;
- r.pendingIntents = pendingNewIntents;
- r.startsNotResumed = notResumed;
-
- synchronized (mRelaunchingActivities) {
- mRelaunchingActivities.add(r);
- }
-
- queueOrSendMessage(H.RELAUNCH_ACTIVITY, r, configChanges);
- }
-
- public final void scheduleNewIntent(List<Intent> intents, IBinder token) {
- NewIntentData data = new NewIntentData();
- data.intents = intents;
- data.token = token;
-
- queueOrSendMessage(H.NEW_INTENT, data);
- }
-
- public final void scheduleDestroyActivity(IBinder token, boolean finishing,
- int configChanges) {
- queueOrSendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
- configChanges);
- }
-
- public final void scheduleReceiver(Intent intent, ActivityInfo info,
- int resultCode, String data, Bundle extras, boolean sync) {
- ReceiverData r = new ReceiverData();
-
- r.intent = intent;
- r.info = info;
- r.resultCode = resultCode;
- r.resultData = data;
- r.resultExtras = extras;
- r.sync = sync;
-
- queueOrSendMessage(H.RECEIVER, r);
- }
-
- public final void scheduleCreateService(IBinder token,
- ServiceInfo info) {
- CreateServiceData s = new CreateServiceData();
- s.token = token;
- s.info = info;
-
- queueOrSendMessage(H.CREATE_SERVICE, s);
- }
-
- public final void scheduleBindService(IBinder token, Intent intent,
- boolean rebind) {
- BindServiceData s = new BindServiceData();
- s.token = token;
- s.intent = intent;
- s.rebind = rebind;
-
- queueOrSendMessage(H.BIND_SERVICE, s);
- }
-
- public final void scheduleUnbindService(IBinder token, Intent intent) {
- BindServiceData s = new BindServiceData();
- s.token = token;
- s.intent = intent;
-
- queueOrSendMessage(H.UNBIND_SERVICE, s);
- }
-
- public final void scheduleServiceArgs(IBinder token, int startId,
- Intent args) {
- ServiceArgsData s = new ServiceArgsData();
- s.token = token;
- s.startId = startId;
- s.args = args;
-
- queueOrSendMessage(H.SERVICE_ARGS, s);
- }
-
- public final void scheduleStopService(IBinder token) {
- queueOrSendMessage(H.STOP_SERVICE, token);
- }
-
- public final void bindApplication(String processName,
- ApplicationInfo appInfo, List<ProviderInfo> providers,
- ComponentName instrumentationName, String profileFile,
- Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
- int debugMode, Configuration config,
- Map<String, IBinder> services) {
- Process.setArgV0(processName);
-
- if (services != null) {
- // Setup the service cache in the ServiceManager
- ServiceManager.initServiceCache(services);
- }
-
- AppBindData data = new AppBindData();
- data.processName = processName;
- data.appInfo = appInfo;
- data.providers = providers;
- data.instrumentationName = instrumentationName;
- data.profileFile = profileFile;
- data.instrumentationArgs = instrumentationArgs;
- data.instrumentationWatcher = instrumentationWatcher;
- data.debugMode = debugMode;
- data.config = config;
- queueOrSendMessage(H.BIND_APPLICATION, data);
- }
-
- public final void scheduleExit() {
- queueOrSendMessage(H.EXIT_APPLICATION, null);
- }
-
- public void requestThumbnail(IBinder token) {
- queueOrSendMessage(H.REQUEST_THUMBNAIL, token);
- }
-
- public void scheduleConfigurationChanged(Configuration config) {
- synchronized (mRelaunchingActivities) {
- mPendingConfiguration = config;
- }
- queueOrSendMessage(H.CONFIGURATION_CHANGED, config);
- }
-
- public void updateTimeZone() {
- TimeZone.setDefault(null);
- }
-
- public void processInBackground() {
- mH.removeMessages(H.GC_WHEN_IDLE);
- mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
- }
-
- public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) {
- DumpServiceInfo data = new DumpServiceInfo();
- data.fd = fd;
- data.service = servicetoken;
- data.args = args;
- data.dumped = false;
- queueOrSendMessage(H.DUMP_SERVICE, data);
- synchronized (data) {
- while (!data.dumped) {
- try {
- data.wait();
- } catch (InterruptedException e) {
- // no need to do anything here, we will keep waiting until
- // dumped is set
- }
- }
- }
- }
-
- // This function exists to make sure all receiver dispatching is
- // correctly ordered, since these are one-way calls and the binder driver
- // applies transaction ordering per object for such calls.
- public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
- int resultCode, String dataStr, Bundle extras, boolean ordered)
- throws RemoteException {
- receiver.performReceive(intent, resultCode, dataStr, extras, ordered);
- }
-
- public void scheduleLowMemory() {
- queueOrSendMessage(H.LOW_MEMORY, null);
- }
-
- public void scheduleActivityConfigurationChanged(IBinder token) {
- queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
- }
-
- public void requestPss() {
- try {
- ActivityManagerNative.getDefault().reportPss(this,
- (int)Process.getPss(Process.myPid()));
- } catch (RemoteException e) {
- }
- }
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- long nativeMax = Debug.getNativeHeapSize() / 1024;
- long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
- long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
-
- Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
- Debug.getMemoryInfo(memInfo);
-
- final int nativeShared = memInfo.nativeSharedDirty;
- final int dalvikShared = memInfo.dalvikSharedDirty;
- final int otherShared = memInfo.otherSharedDirty;
-
- final int nativePrivate = memInfo.nativePrivateDirty;
- final int dalvikPrivate = memInfo.dalvikPrivateDirty;
- final int otherPrivate = memInfo.otherPrivateDirty;
-
- Runtime runtime = Runtime.getRuntime();
-
- long dalvikMax = runtime.totalMemory() / 1024;
- long dalvikFree = runtime.freeMemory() / 1024;
- long dalvikAllocated = dalvikMax - dalvikFree;
- long viewInstanceCount = ViewDebug.getViewInstanceCount();
- long viewRootInstanceCount = ViewDebug.getViewRootInstanceCount();
- long appContextInstanceCount = ApplicationContext.getInstanceCount();
- long activityInstanceCount = Activity.getInstanceCount();
- int globalAssetCount = AssetManager.getGlobalAssetCount();
- int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
- int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
- int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
- int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
- int openSslSocketCount = OpenSSLSocketImpl.getInstanceCount();
- long sqliteAllocated = SQLiteDebug.getHeapAllocatedSize() / 1024;
- SQLiteDebug.PagerStats stats = new SQLiteDebug.PagerStats();
- SQLiteDebug.getPagerStats(stats);
-
- // Check to see if we were called by checkin server. If so, print terse format.
- boolean doCheckinFormat = false;
- if (args != null) {
- for (String arg : args) {
- if ("-c".equals(arg)) doCheckinFormat = true;
- }
- }
-
- // For checkin, we print one long comma-separated list of values
- if (doCheckinFormat) {
- // NOTE: if you change anything significant below, also consider changing
- // ACTIVITY_THREAD_CHECKIN_VERSION.
- String processName = (mBoundApplication != null)
- ? mBoundApplication.processName : "unknown";
-
- // Header
- pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(',');
- pw.print(Process.myPid()); pw.print(',');
- pw.print(processName); pw.print(',');
-
- // Heap info - max
- pw.print(nativeMax); pw.print(',');
- pw.print(dalvikMax); pw.print(',');
- pw.print("N/A,");
- pw.print(nativeMax + dalvikMax); pw.print(',');
-
- // Heap info - allocated
- pw.print(nativeAllocated); pw.print(',');
- pw.print(dalvikAllocated); pw.print(',');
- pw.print("N/A,");
- pw.print(nativeAllocated + dalvikAllocated); pw.print(',');
-
- // Heap info - free
- pw.print(nativeFree); pw.print(',');
- pw.print(dalvikFree); pw.print(',');
- pw.print("N/A,");
- pw.print(nativeFree + dalvikFree); pw.print(',');
-
- // Heap info - proportional set size
- pw.print(memInfo.nativePss); pw.print(',');
- pw.print(memInfo.dalvikPss); pw.print(',');
- pw.print(memInfo.otherPss); pw.print(',');
- pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(',');
-
- // Heap info - shared
- pw.print(nativeShared); pw.print(',');
- pw.print(dalvikShared); pw.print(',');
- pw.print(otherShared); pw.print(',');
- pw.print(nativeShared + dalvikShared + otherShared); pw.print(',');
-
- // Heap info - private
- pw.print(nativePrivate); pw.print(',');
- pw.print(dalvikPrivate); pw.print(',');
- pw.print(otherPrivate); pw.print(',');
- pw.print(nativePrivate + dalvikPrivate + otherPrivate); pw.print(',');
-
- // Object counts
- pw.print(viewInstanceCount); pw.print(',');
- pw.print(viewRootInstanceCount); pw.print(',');
- pw.print(appContextInstanceCount); pw.print(',');
- pw.print(activityInstanceCount); pw.print(',');
-
- pw.print(globalAssetCount); pw.print(',');
- pw.print(globalAssetManagerCount); pw.print(',');
- pw.print(binderLocalObjectCount); pw.print(',');
- pw.print(binderProxyObjectCount); pw.print(',');
-
- pw.print(binderDeathObjectCount); pw.print(',');
- pw.print(openSslSocketCount); pw.print(',');
-
- // SQL
- pw.print(sqliteAllocated); pw.print(',');
- pw.print(stats.databaseBytes / 1024); pw.print(',');
- pw.print(stats.numPagers); pw.print(',');
- pw.print((stats.totalBytes - stats.referencedBytes) / 1024); pw.print(',');
- pw.print(stats.referencedBytes / 1024); pw.print('\n');
-
- return;
- }
-
- // otherwise, show human-readable format
- printRow(pw, HEAP_COLUMN, "", "native", "dalvik", "other", "total");
- printRow(pw, HEAP_COLUMN, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax);
- printRow(pw, HEAP_COLUMN, "allocated:", nativeAllocated, dalvikAllocated, "N/A",
- nativeAllocated + dalvikAllocated);
- printRow(pw, HEAP_COLUMN, "free:", nativeFree, dalvikFree, "N/A",
- nativeFree + dalvikFree);
-
- printRow(pw, HEAP_COLUMN, "(Pss):", memInfo.nativePss, memInfo.dalvikPss,
- memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss);
-
- printRow(pw, HEAP_COLUMN, "(shared dirty):", nativeShared, dalvikShared, otherShared,
- nativeShared + dalvikShared + otherShared);
- printRow(pw, HEAP_COLUMN, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate,
- nativePrivate + dalvikPrivate + otherPrivate);
-
- pw.println(" ");
- pw.println(" Objects");
- printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRoots:",
- viewRootInstanceCount);
-
- printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
- "Activities:", activityInstanceCount);
-
- printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount,
- "AssetManagers:", globalAssetManagerCount);
-
- printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount,
- "Proxy Binders:", binderProxyObjectCount);
- printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount);
-
- printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount);
-
- // SQLite mem info
- pw.println(" ");
- pw.println(" SQL");
- printRow(pw, TWO_COUNT_COLUMNS, "heap:", sqliteAllocated, "dbFiles:",
- stats.databaseBytes / 1024);
- printRow(pw, TWO_COUNT_COLUMNS, "numPagers:", stats.numPagers, "inactivePageKB:",
- (stats.totalBytes - stats.referencedBytes) / 1024);
- printRow(pw, ONE_COUNT_COLUMN, "activePageKB:", stats.referencedBytes / 1024);
- }
-
- private void printRow(PrintWriter pw, String format, Object...objs) {
- pw.println(String.format(format, objs));
- }
- }
-
- private final class H extends Handler {
- public static final int LAUNCH_ACTIVITY = 100;
- public static final int PAUSE_ACTIVITY = 101;
- public static final int PAUSE_ACTIVITY_FINISHING= 102;
- public static final int STOP_ACTIVITY_SHOW = 103;
- public static final int STOP_ACTIVITY_HIDE = 104;
- public static final int SHOW_WINDOW = 105;
- public static final int HIDE_WINDOW = 106;
- public static final int RESUME_ACTIVITY = 107;
- public static final int SEND_RESULT = 108;
- public static final int DESTROY_ACTIVITY = 109;
- public static final int BIND_APPLICATION = 110;
- public static final int EXIT_APPLICATION = 111;
- public static final int NEW_INTENT = 112;
- public static final int RECEIVER = 113;
- public static final int CREATE_SERVICE = 114;
- public static final int SERVICE_ARGS = 115;
- public static final int STOP_SERVICE = 116;
- public static final int REQUEST_THUMBNAIL = 117;
- public static final int CONFIGURATION_CHANGED = 118;
- public static final int CLEAN_UP_CONTEXT = 119;
- public static final int GC_WHEN_IDLE = 120;
- public static final int BIND_SERVICE = 121;
- public static final int UNBIND_SERVICE = 122;
- public static final int DUMP_SERVICE = 123;
- public static final int LOW_MEMORY = 124;
- public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
- public static final int RELAUNCH_ACTIVITY = 126;
- String codeToString(int code) {
- if (localLOGV) {
- switch (code) {
- case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
- case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
- case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
- case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
- case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
- case SHOW_WINDOW: return "SHOW_WINDOW";
- case HIDE_WINDOW: return "HIDE_WINDOW";
- case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
- case SEND_RESULT: return "SEND_RESULT";
- case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
- case BIND_APPLICATION: return "BIND_APPLICATION";
- case EXIT_APPLICATION: return "EXIT_APPLICATION";
- case NEW_INTENT: return "NEW_INTENT";
- case RECEIVER: return "RECEIVER";
- case CREATE_SERVICE: return "CREATE_SERVICE";
- case SERVICE_ARGS: return "SERVICE_ARGS";
- case STOP_SERVICE: return "STOP_SERVICE";
- case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL";
- case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
- case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
- case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
- case BIND_SERVICE: return "BIND_SERVICE";
- case UNBIND_SERVICE: return "UNBIND_SERVICE";
- case DUMP_SERVICE: return "DUMP_SERVICE";
- case LOW_MEMORY: return "LOW_MEMORY";
- case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
- case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
- }
- }
- return "(unknown)";
- }
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case LAUNCH_ACTIVITY: {
- ActivityRecord r = (ActivityRecord)msg.obj;
-
- r.packageInfo = getPackageInfoNoCheck(
- r.activityInfo.applicationInfo);
- handleLaunchActivity(r);
- } break;
- case RELAUNCH_ACTIVITY: {
- ActivityRecord r = (ActivityRecord)msg.obj;
- handleRelaunchActivity(r, msg.arg1);
- } break;
- case PAUSE_ACTIVITY:
- handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
- break;
- case PAUSE_ACTIVITY_FINISHING:
- handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
- break;
- case STOP_ACTIVITY_SHOW:
- handleStopActivity((IBinder)msg.obj, true, msg.arg2);
- break;
- case STOP_ACTIVITY_HIDE:
- handleStopActivity((IBinder)msg.obj, false, msg.arg2);
- break;
- case SHOW_WINDOW:
- handleWindowVisibility((IBinder)msg.obj, true);
- break;
- case HIDE_WINDOW:
- handleWindowVisibility((IBinder)msg.obj, false);
- break;
- case RESUME_ACTIVITY:
- handleResumeActivity((IBinder)msg.obj, true,
- msg.arg1 != 0);
- break;
- case SEND_RESULT:
- handleSendResult((ResultData)msg.obj);
- break;
- case DESTROY_ACTIVITY:
- handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
- msg.arg2, false);
- break;
- case BIND_APPLICATION:
- AppBindData data = (AppBindData)msg.obj;
- handleBindApplication(data);
- break;
- case EXIT_APPLICATION:
- if (mInitialApplication != null) {
- mInitialApplication.onTerminate();
- }
- Looper.myLooper().quit();
- break;
- case NEW_INTENT:
- handleNewIntent((NewIntentData)msg.obj);
- break;
- case RECEIVER:
- handleReceiver((ReceiverData)msg.obj);
- break;
- case CREATE_SERVICE:
- handleCreateService((CreateServiceData)msg.obj);
- break;
- case BIND_SERVICE:
- handleBindService((BindServiceData)msg.obj);
- break;
- case UNBIND_SERVICE:
- handleUnbindService((BindServiceData)msg.obj);
- break;
- case SERVICE_ARGS:
- handleServiceArgs((ServiceArgsData)msg.obj);
- break;
- case STOP_SERVICE:
- handleStopService((IBinder)msg.obj);
- break;
- case REQUEST_THUMBNAIL:
- handleRequestThumbnail((IBinder)msg.obj);
- break;
- case CONFIGURATION_CHANGED:
- handleConfigurationChanged((Configuration)msg.obj);
- break;
- case CLEAN_UP_CONTEXT:
- ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
- cci.context.performFinalCleanup(cci.who, cci.what);
- break;
- case GC_WHEN_IDLE:
- scheduleGcIdler();
- break;
- case DUMP_SERVICE:
- handleDumpService((DumpServiceInfo)msg.obj);
- break;
- case LOW_MEMORY:
- handleLowMemory();
- break;
- case ACTIVITY_CONFIGURATION_CHANGED:
- handleActivityConfigurationChanged((IBinder)msg.obj);
- break;
- }
- }
- }
-
- private final class Idler implements MessageQueue.IdleHandler {
- public final boolean queueIdle() {
- ActivityRecord a = mNewActivities;
- if (a != null) {
- mNewActivities = null;
- IActivityManager am = ActivityManagerNative.getDefault();
- ActivityRecord prev;
- do {
- if (localLOGV) Log.v(
- TAG, "Reporting idle of " + a +
- " finished=" +
- (a.activity != null ? a.activity.mFinished : false));
- if (a.activity != null && !a.activity.mFinished) {
- try {
- am.activityIdle(a.token);
- } catch (RemoteException ex) {
- }
- }
- prev = a;
- a = a.nextIdle;
- prev.nextIdle = null;
- } while (a != null);
- }
- return false;
- }
- }
-
- final class GcIdler implements MessageQueue.IdleHandler {
- public final boolean queueIdle() {
- doGcIfNeeded();
- return false;
- }
- }
-
- static IPackageManager sPackageManager;
-
- final ApplicationThread mAppThread = new ApplicationThread();
- final Looper mLooper = Looper.myLooper();
- final H mH = new H();
- final HashMap<IBinder, ActivityRecord> mActivities
- = new HashMap<IBinder, ActivityRecord>();
- // List of new activities (via ActivityRecord.nextIdle) that should
- // be reported when next we idle.
- ActivityRecord mNewActivities = null;
- // Number of activities that are currently visible on-screen.
- int mNumVisibleActivities = 0;
- final HashMap<IBinder, Service> mServices
- = new HashMap<IBinder, Service>();
- AppBindData mBoundApplication;
- Configuration mConfiguration;
- Application mInitialApplication;
- final ArrayList<Application> mAllApplications
- = new ArrayList<Application>();
- static final ThreadLocal sThreadLocal = new ThreadLocal();
- Instrumentation mInstrumentation;
- String mInstrumentationAppDir = null;
- String mInstrumentationAppPackage = null;
- String mInstrumentedAppDir = null;
- boolean mSystemThread = false;
-
- /**
- * Activities that are enqueued to be relaunched. This list is accessed
- * by multiple threads, so you must synchronize on it when accessing it.
- */
- final ArrayList<ActivityRecord> mRelaunchingActivities
- = new ArrayList<ActivityRecord>();
- Configuration mPendingConfiguration = null;
-
- // These can be accessed by multiple threads; mPackages is the lock.
- // XXX For now we keep around information about all packages we have
- // seen, not removing entries from this map.
- final HashMap<String, WeakReference<PackageInfo>> mPackages
- = new HashMap<String, WeakReference<PackageInfo>>();
- final HashMap<String, WeakReference<PackageInfo>> mResourcePackages
- = new HashMap<String, WeakReference<PackageInfo>>();
- Display mDisplay = null;
- DisplayMetrics mDisplayMetrics = null;
- HashMap<String, WeakReference<Resources> > mActiveResources
- = new HashMap<String, WeakReference<Resources> >();
-
- // The lock of mProviderMap protects the following variables.
- final HashMap<String, ProviderRecord> mProviderMap
- = new HashMap<String, ProviderRecord>();
- final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap
- = new HashMap<IBinder, ProviderRefCount>();
- final HashMap<IBinder, ProviderRecord> mLocalProviders
- = new HashMap<IBinder, ProviderRecord>();
-
- final GcIdler mGcIdler = new GcIdler();
- boolean mGcIdlerScheduled = false;
-
- public final PackageInfo getPackageInfo(String packageName, int flags) {
- synchronized (mPackages) {
- WeakReference<PackageInfo> ref;
- if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
- ref = mPackages.get(packageName);
- } else {
- ref = mResourcePackages.get(packageName);
- }
- PackageInfo packageInfo = ref != null ? ref.get() : null;
- //Log.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
- if (packageInfo != null && (packageInfo.mResources == null
- || packageInfo.mResources.getAssets().isUpToDate())) {
- if (packageInfo.isSecurityViolation()
- && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
- throw new SecurityException(
- "Requesting code from " + packageName
- + " to be run in process "
- + mBoundApplication.processName
- + "/" + mBoundApplication.appInfo.uid);
- }
- return packageInfo;
- }
- }
-
- ApplicationInfo ai = null;
- try {
- ai = getPackageManager().getApplicationInfo(packageName,
- PackageManager.GET_SHARED_LIBRARY_FILES);
- } catch (RemoteException e) {
- }
-
- if (ai != null) {
- return getPackageInfo(ai, flags);
- }
-
- return null;
- }
-
- public final PackageInfo getPackageInfo(ApplicationInfo ai, int flags) {
- boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
- boolean securityViolation = includeCode && ai.uid != 0
- && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
- ? ai.uid != mBoundApplication.appInfo.uid : true);
- if ((flags&(Context.CONTEXT_INCLUDE_CODE
- |Context.CONTEXT_IGNORE_SECURITY))
- == Context.CONTEXT_INCLUDE_CODE) {
- if (securityViolation) {
- String msg = "Requesting code from " + ai.packageName
- + " (with uid " + ai.uid + ")";
- if (mBoundApplication != null) {
- msg = msg + " to be run in process "
- + mBoundApplication.processName + " (with uid "
- + mBoundApplication.appInfo.uid + ")";
- }
- throw new SecurityException(msg);
- }
- }
- return getPackageInfo(ai, null, securityViolation, includeCode);
- }
-
- public final PackageInfo getPackageInfoNoCheck(ApplicationInfo ai) {
- return getPackageInfo(ai, null, false, true);
- }
-
- private final PackageInfo getPackageInfo(ApplicationInfo aInfo,
- ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
- synchronized (mPackages) {
- WeakReference<PackageInfo> ref;
- if (includeCode) {
- ref = mPackages.get(aInfo.packageName);
- } else {
- ref = mResourcePackages.get(aInfo.packageName);
- }
- PackageInfo packageInfo = ref != null ? ref.get() : null;
- if (packageInfo == null || (packageInfo.mResources != null
- && !packageInfo.mResources.getAssets().isUpToDate())) {
- if (localLOGV) Log.v(TAG, (includeCode ? "Loading code package "
- : "Loading resource-only package ") + aInfo.packageName
- + " (in " + (mBoundApplication != null
- ? mBoundApplication.processName : null)
- + ")");
- packageInfo =
- new PackageInfo(this, aInfo, this, baseLoader,
- securityViolation, includeCode &&
- (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
- if (includeCode) {
- mPackages.put(aInfo.packageName,
- new WeakReference<PackageInfo>(packageInfo));
- } else {
- mResourcePackages.put(aInfo.packageName,
- new WeakReference<PackageInfo>(packageInfo));
- }
- }
- return packageInfo;
- }
- }
-
- public final boolean hasPackageInfo(String packageName) {
- synchronized (mPackages) {
- WeakReference<PackageInfo> ref;
- ref = mPackages.get(packageName);
- if (ref != null && ref.get() != null) {
- return true;
- }
- ref = mResourcePackages.get(packageName);
- if (ref != null && ref.get() != null) {
- return true;
- }
- return false;
- }
- }
-
- ActivityThread() {
- }
-
- public ApplicationThread getApplicationThread()
- {
- return mAppThread;
- }
-
- public Instrumentation getInstrumentation()
- {
- return mInstrumentation;
- }
-
- public Configuration getConfiguration() {
- return mConfiguration;
- }
-
- public boolean isProfiling() {
- return mBoundApplication != null && mBoundApplication.profileFile != null;
- }
-
- public String getProfileFilePath() {
- return mBoundApplication.profileFile;
- }
-
- public Looper getLooper() {
- return mLooper;
- }
-
- public Application getApplication() {
- return mInitialApplication;
- }
-
- public ApplicationContext getSystemContext() {
- synchronized (this) {
- if (mSystemContext == null) {
- ApplicationContext context =
- ApplicationContext.createSystemContext(this);
- PackageInfo info = new PackageInfo(this, "android", context);
- context.init(info, null, this);
- context.getResources().updateConfiguration(
- getConfiguration(), getDisplayMetricsLocked(false));
- mSystemContext = context;
- //Log.i(TAG, "Created system resources " + context.getResources()
- // + ": " + context.getResources().getConfiguration());
- }
- }
- return mSystemContext;
- }
-
- void scheduleGcIdler() {
- if (!mGcIdlerScheduled) {
- mGcIdlerScheduled = true;
- Looper.myQueue().addIdleHandler(mGcIdler);
- }
- mH.removeMessages(H.GC_WHEN_IDLE);
- }
-
- void unscheduleGcIdler() {
- if (mGcIdlerScheduled) {
- mGcIdlerScheduled = false;
- Looper.myQueue().removeIdleHandler(mGcIdler);
- }
- mH.removeMessages(H.GC_WHEN_IDLE);
- }
-
- void doGcIfNeeded() {
- mGcIdlerScheduled = false;
- final long now = SystemClock.uptimeMillis();
- //Log.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime()
- // + "m now=" + now);
- if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) {
- //Log.i(TAG, "**** WE DO, WE DO WANT TO GC!");
- BinderInternal.forceGc("bg");
- }
- }
-
- public final ActivityInfo resolveActivityInfo(Intent intent) {
- ActivityInfo aInfo = intent.resolveActivityInfo(
- mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
- if (aInfo == null) {
- // Throw an exception.
- Instrumentation.checkStartActivityResult(
- IActivityManager.START_CLASS_NOT_FOUND, intent);
- }
- return aInfo;
- }
-
- public final Activity startActivityNow(Activity parent, String id,
- Intent intent, IBinder token, Bundle state) {
- ActivityInfo aInfo = resolveActivityInfo(intent);
- return startActivityNow(parent, id, intent, aInfo, token, state);
- }
-
- public final Activity startActivityNow(Activity parent, String id,
- Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state) {
- return startActivityNow(parent, id, intent, activityInfo, token, state, null);
- }
-
- public final Activity startActivityNow(Activity parent, String id,
- Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
- Object lastNonConfigurationInstance) {
- ActivityRecord r = new ActivityRecord();
- r.token = token;
- r.intent = intent;
- r.state = state;
- r.parent = parent;
- r.embeddedID = id;
- r.activityInfo = activityInfo;
- r.lastNonConfigurationInstance = lastNonConfigurationInstance;
- if (localLOGV) {
- ComponentName compname = intent.getComponent();
- String name;
- if (compname != null) {
- name = compname.toShortString();
- } else {
- name = "(Intent " + intent + ").getComponent() returned null";
- }
- Log.v(TAG, "Performing launch: action=" + intent.getAction()
- + ", comp=" + name
- + ", token=" + token);
- }
- return performLaunchActivity(r);
- }
-
- public final Activity getActivity(IBinder token) {
- return mActivities.get(token).activity;
- }
-
- public final void sendActivityResult(
- IBinder token, String id, int requestCode,
- int resultCode, Intent data) {
- ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
- list.add(new ResultInfo(id, requestCode, resultCode, data));
- mAppThread.scheduleSendResult(token, list);
- }
-
- // if the thread hasn't started yet, we don't have the handler, so just
- // save the messages until we're ready.
- private final void queueOrSendMessage(int what, Object obj) {
- queueOrSendMessage(what, obj, 0, 0);
- }
-
- private final void queueOrSendMessage(int what, Object obj, int arg1) {
- queueOrSendMessage(what, obj, arg1, 0);
- }
-
- private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
- synchronized (this) {
- if (localLOGV) Log.v(
- TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
- + ": " + arg1 + " / " + obj);
- Message msg = Message.obtain();
- msg.what = what;
- msg.obj = obj;
- msg.arg1 = arg1;
- msg.arg2 = arg2;
- mH.sendMessage(msg);
- }
- }
-
- final void scheduleContextCleanup(ApplicationContext context, String who,
- String what) {
- ContextCleanupInfo cci = new ContextCleanupInfo();
- cci.context = context;
- cci.who = who;
- cci.what = what;
- queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
- }
-
- private final Activity performLaunchActivity(ActivityRecord r) {
- // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
-
- ActivityInfo aInfo = r.activityInfo;
- if (r.packageInfo == null) {
- r.packageInfo = getPackageInfo(aInfo.applicationInfo,
- Context.CONTEXT_INCLUDE_CODE);
- }
-
- ComponentName component = r.intent.getComponent();
- if (component == null) {
- component = r.intent.resolveActivity(
- mInitialApplication.getPackageManager());
- r.intent.setComponent(component);
- }
-
- if (r.activityInfo.targetActivity != null) {
- component = new ComponentName(r.activityInfo.packageName,
- r.activityInfo.targetActivity);
- }
-
- Activity activity = null;
- try {
- java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
- activity = mInstrumentation.newActivity(
- cl, component.getClassName(), r.intent);
- r.intent.setExtrasClassLoader(cl);
- if (r.state != null) {
- r.state.setClassLoader(cl);
- }
- } catch (Exception e) {
- if (!mInstrumentation.onException(activity, e)) {
- throw new RuntimeException(
- "Unable to instantiate activity " + component
- + ": " + e.toString(), e);
- }
- }
-
- try {
- Application app = r.packageInfo.makeApplication();
-
- if (localLOGV) Log.v(TAG, "Performing launch of " + r);
- if (localLOGV) Log.v(
- TAG, r + ": app=" + app
- + ", appName=" + app.getPackageName()
- + ", pkg=" + r.packageInfo.getPackageName()
- + ", comp=" + r.intent.getComponent().toShortString()
- + ", dir=" + r.packageInfo.getAppDir());
-
- if (activity != null) {
- ApplicationContext appContext = new ApplicationContext();
- appContext.init(r.packageInfo, r.token, this);
- appContext.setOuterContext(activity);
- CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
- Configuration config = new Configuration(mConfiguration);
- activity.attach(appContext, this, getInstrumentation(), r.token, app,
- r.intent, r.activityInfo, title, r.parent, r.embeddedID,
- r.lastNonConfigurationInstance, r.lastNonConfigurationChildInstances,
- config);
-
- r.lastNonConfigurationInstance = null;
- r.lastNonConfigurationChildInstances = null;
- activity.mStartedActivity = false;
- int theme = r.activityInfo.getThemeResource();
- if (theme != 0) {
- activity.setTheme(theme);
- }
-
- activity.mCalled = false;
- mInstrumentation.callActivityOnCreate(activity, r.state);
- if (!activity.mCalled) {
- throw new SuperNotCalledException(
- "Activity " + r.intent.getComponent().toShortString() +
- " did not call through to super.onCreate()");
- }
- r.activity = activity;
- r.stopped = true;
- if (!r.activity.mFinished) {
- activity.performStart();
- r.stopped = false;
- }
- if (!r.activity.mFinished) {
- if (r.state != null) {
- mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
- }
- }
- if (!r.activity.mFinished) {
- activity.mCalled = false;
- mInstrumentation.callActivityOnPostCreate(activity, r.state);
- if (!activity.mCalled) {
- throw new SuperNotCalledException(
- "Activity " + r.intent.getComponent().toShortString() +
- " did not call through to super.onPostCreate()");
- }
- }
- r.state = null;
- }
- r.paused = true;
-
- mActivities.put(r.token, r);
-
- } catch (SuperNotCalledException e) {
- throw e;
-
- } catch (Exception e) {
- if (!mInstrumentation.onException(activity, e)) {
- throw new RuntimeException(
- "Unable to start activity " + component
- + ": " + e.toString(), e);
- }
- }
-
- return activity;
- }
-
- private final void handleLaunchActivity(ActivityRecord r) {
- // If we are getting ready to gc after going to the background, well
- // we are back active so skip it.
- unscheduleGcIdler();
-
- if (localLOGV) Log.v(
- TAG, "Handling launch of " + r);
- Activity a = performLaunchActivity(r);
-
- if (a != null) {
- handleResumeActivity(r.token, false, r.isForward);
-
- if (!r.activity.mFinished && r.startsNotResumed) {
- // The activity manager actually wants this one to start out
- // paused, because it needs to be visible but isn't in the
- // foreground. We accomplish this by going through the
- // normal startup (because activities expect to go through
- // onResume() the first time they run, before their window
- // is displayed), and then pausing it. However, in this case
- // we do -not- need to do the full pause cycle (of freezing
- // and such) because the activity manager assumes it can just
- // retain the current state it has.
- try {
- r.activity.mCalled = false;
- mInstrumentation.callActivityOnPause(r.activity);
- if (!r.activity.mCalled) {
- throw new SuperNotCalledException(
- "Activity " + r.intent.getComponent().toShortString() +
- " did not call through to super.onPause()");
- }
-
- } catch (SuperNotCalledException e) {
- throw e;
-
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to pause activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- r.paused = true;
- }
- } else {
- // If there was an error, for any reason, tell the activity
- // manager to stop us.
- try {
- ActivityManagerNative.getDefault()
- .finishActivity(r.token, Activity.RESULT_CANCELED, null);
- } catch (RemoteException ex) {
- }
- }
- }
-
- private final void deliverNewIntents(ActivityRecord r,
- List<Intent> intents) {
- final int N = intents.size();
- for (int i=0; i<N; i++) {
- Intent intent = intents.get(i);
- intent.setExtrasClassLoader(r.activity.getClassLoader());
- mInstrumentation.callActivityOnNewIntent(r.activity, intent);
- }
- }
-
- public final void performNewIntents(IBinder token,
- List<Intent> intents) {
- ActivityRecord r = mActivities.get(token);
- if (r != null) {
- final boolean resumed = !r.paused;
- if (resumed) {
- mInstrumentation.callActivityOnPause(r.activity);
- }
- deliverNewIntents(r, intents);
- if (resumed) {
- mInstrumentation.callActivityOnResume(r.activity);
- }
- }
- }
-
- private final void handleNewIntent(NewIntentData data) {
- performNewIntents(data.token, data.intents);
- }
-
- private final void handleReceiver(ReceiverData data) {
- // If we are getting ready to gc after going to the background, well
- // we are back active so skip it.
- unscheduleGcIdler();
-
- String component = data.intent.getComponent().getClassName();
-
- PackageInfo packageInfo = getPackageInfoNoCheck(
- data.info.applicationInfo);
-
- IActivityManager mgr = ActivityManagerNative.getDefault();
-
- BroadcastReceiver receiver = null;
- try {
- java.lang.ClassLoader cl = packageInfo.getClassLoader();
- data.intent.setExtrasClassLoader(cl);
- if (data.resultExtras != null) {
- data.resultExtras.setClassLoader(cl);
- }
- receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
- } catch (Exception e) {
- try {
- mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
- data.resultData, data.resultExtras, data.resultAbort);
- } catch (RemoteException ex) {
- }
- throw new RuntimeException(
- "Unable to instantiate receiver " + component
- + ": " + e.toString(), e);
- }
-
- try {
- Application app = packageInfo.makeApplication();
-
- if (localLOGV) Log.v(
- TAG, "Performing receive of " + data.intent
- + ": app=" + app
- + ", appName=" + app.getPackageName()
- + ", pkg=" + packageInfo.getPackageName()
- + ", comp=" + data.intent.getComponent().toShortString()
- + ", dir=" + packageInfo.getAppDir());
-
- ApplicationContext context = (ApplicationContext)app.getBaseContext();
- receiver.setOrderedHint(true);
- receiver.setResult(data.resultCode, data.resultData,
- data.resultExtras);
- receiver.setOrderedHint(data.sync);
- receiver.onReceive(context.getReceiverRestrictedContext(),
- data.intent);
- } catch (Exception e) {
- try {
- mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
- data.resultData, data.resultExtras, data.resultAbort);
- } catch (RemoteException ex) {
- }
- if (!mInstrumentation.onException(receiver, e)) {
- throw new RuntimeException(
- "Unable to start receiver " + component
- + ": " + e.toString(), e);
- }
- }
-
- try {
- if (data.sync) {
- mgr.finishReceiver(
- mAppThread.asBinder(), receiver.getResultCode(),
- receiver.getResultData(), receiver.getResultExtras(false),
- receiver.getAbortBroadcast());
- } else {
- mgr.finishReceiver(mAppThread.asBinder(), 0, null, null, false);
- }
- } catch (RemoteException ex) {
- }
- }
-
- private final void handleCreateService(CreateServiceData data) {
- // If we are getting ready to gc after going to the background, well
- // we are back active so skip it.
- unscheduleGcIdler();
-
- PackageInfo packageInfo = getPackageInfoNoCheck(
- data.info.applicationInfo);
- Service service = null;
- try {
- java.lang.ClassLoader cl = packageInfo.getClassLoader();
- service = (Service) cl.loadClass(data.info.name).newInstance();
- } catch (Exception e) {
- if (!mInstrumentation.onException(service, e)) {
- throw new RuntimeException(
- "Unable to instantiate service " + data.info.name
- + ": " + e.toString(), e);
- }
- }
-
- try {
- if (localLOGV) Log.v(TAG, "Creating service " + data.info.name);
-
- ApplicationContext context = new ApplicationContext();
- context.init(packageInfo, null, this);
-
- Application app = packageInfo.makeApplication();
- context.setOuterContext(service);
- service.attach(context, this, data.info.name, data.token, app,
- ActivityManagerNative.getDefault());
- service.onCreate();
- mServices.put(data.token, service);
- try {
- ActivityManagerNative.getDefault().serviceDoneExecuting(data.token);
- } catch (RemoteException e) {
- // nothing to do.
- }
- } catch (Exception e) {
- if (!mInstrumentation.onException(service, e)) {
- throw new RuntimeException(
- "Unable to create service " + data.info.name
- + ": " + e.toString(), e);
- }
- }
- }
-
- private final void handleBindService(BindServiceData data) {
- Service s = mServices.get(data.token);
- if (s != null) {
- try {
- data.intent.setExtrasClassLoader(s.getClassLoader());
- try {
- if (!data.rebind) {
- IBinder binder = s.onBind(data.intent);
- ActivityManagerNative.getDefault().publishService(
- data.token, data.intent, binder);
- } else {
- s.onRebind(data.intent);
- ActivityManagerNative.getDefault().serviceDoneExecuting(
- data.token);
- }
- } catch (RemoteException ex) {
- }
- } catch (Exception e) {
- if (!mInstrumentation.onException(s, e)) {
- throw new RuntimeException(
- "Unable to bind to service " + s
- + " with " + data.intent + ": " + e.toString(), e);
- }
- }
- }
- }
-
- private final void handleUnbindService(BindServiceData data) {
- Service s = mServices.get(data.token);
- if (s != null) {
- try {
- data.intent.setExtrasClassLoader(s.getClassLoader());
- boolean doRebind = s.onUnbind(data.intent);
- try {
- if (doRebind) {
- ActivityManagerNative.getDefault().unbindFinished(
- data.token, data.intent, doRebind);
- } else {
- ActivityManagerNative.getDefault().serviceDoneExecuting(
- data.token);
- }
- } catch (RemoteException ex) {
- }
- } catch (Exception e) {
- if (!mInstrumentation.onException(s, e)) {
- throw new RuntimeException(
- "Unable to unbind to service " + s
- + " with " + data.intent + ": " + e.toString(), e);
- }
- }
- }
- }
-
- private void handleDumpService(DumpServiceInfo info) {
- try {
- Service s = mServices.get(info.service);
- if (s != null) {
- PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
- s.dump(info.fd, pw, info.args);
- pw.close();
- }
- } finally {
- synchronized (info) {
- info.dumped = true;
- info.notifyAll();
- }
- }
- }
-
- private final void handleServiceArgs(ServiceArgsData data) {
- Service s = mServices.get(data.token);
- if (s != null) {
- try {
- if (data.args != null) {
- data.args.setExtrasClassLoader(s.getClassLoader());
- }
- s.onStart(data.args, data.startId);
- try {
- ActivityManagerNative.getDefault().serviceDoneExecuting(data.token);
- } catch (RemoteException e) {
- // nothing to do.
- }
- } catch (Exception e) {
- if (!mInstrumentation.onException(s, e)) {
- throw new RuntimeException(
- "Unable to start service " + s
- + " with " + data.args + ": " + e.toString(), e);
- }
- }
- }
- }
-
- private final void handleStopService(IBinder token) {
- Service s = mServices.remove(token);
- if (s != null) {
- try {
- if (localLOGV) Log.v(TAG, "Destroying service " + s);
- s.onDestroy();
- Context context = s.getBaseContext();
- if (context instanceof ApplicationContext) {
- final String who = s.getClassName();
- ((ApplicationContext) context).scheduleFinalCleanup(who, "Service");
- }
- try {
- ActivityManagerNative.getDefault().serviceDoneExecuting(token);
- } catch (RemoteException e) {
- // nothing to do.
- }
- } catch (Exception e) {
- if (!mInstrumentation.onException(s, e)) {
- throw new RuntimeException(
- "Unable to stop service " + s
- + ": " + e.toString(), e);
- }
- }
- }
- //Log.i(TAG, "Running services: " + mServices);
- }
-
- public final ActivityRecord performResumeActivity(IBinder token,
- boolean clearHide) {
- ActivityRecord r = mActivities.get(token);
- if (localLOGV) Log.v(TAG, "Performing resume of " + r
- + " finished=" + r.activity.mFinished);
- if (r != null && !r.activity.mFinished) {
- if (clearHide) {
- r.hideForNow = false;
- r.activity.mStartedActivity = false;
- }
- try {
- if (r.pendingIntents != null) {
- deliverNewIntents(r, r.pendingIntents);
- r.pendingIntents = null;
- }
- if (r.pendingResults != null) {
- deliverResults(r, r.pendingResults);
- r.pendingResults = null;
- }
- r.activity.performResume();
-
- EventLog.writeEvent(LOG_ON_RESUME_CALLED,
- r.activity.getComponentName().getClassName());
-
- r.paused = false;
- r.stopped = false;
- if (r.activity.mStartedActivity) {
- r.hideForNow = true;
- }
- r.state = null;
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to resume activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- }
- return r;
- }
-
- final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
- // If we are getting ready to gc after going to the background, well
- // we are back active so skip it.
- unscheduleGcIdler();
-
- ActivityRecord r = performResumeActivity(token, clearHide);
-
- if (r != null) {
- final Activity a = r.activity;
-
- if (localLOGV) Log.v(
- TAG, "Resume " + r + " started activity: " +
- a.mStartedActivity + ", hideForNow: " + r.hideForNow
- + ", finished: " + a.mFinished);
-
- final int forwardBit = isForward ?
- WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
-
- // If the window hasn't yet been added to the window manager,
- // and this guy didn't finish itself or start another activity,
- // then go ahead and add the window.
- if (r.window == null && !a.mFinished && !a.mStartedActivity) {
- r.window = r.activity.getWindow();
- View decor = r.window.getDecorView();
- decor.setVisibility(View.INVISIBLE);
- ViewManager wm = a.getWindowManager();
- WindowManager.LayoutParams l = r.window.getAttributes();
- a.mDecor = decor;
- l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
- l.softInputMode |= forwardBit;
- if (a.mVisibleFromClient) {
- a.mWindowAdded = true;
- wm.addView(decor, l);
- }
-
- // If the window has already been added, but during resume
- // we started another activity, then don't yet make the
- // window visisble.
- } else if (a.mStartedActivity) {
- if (localLOGV) Log.v(
- TAG, "Launch " + r + " mStartedActivity set");
- r.hideForNow = true;
- }
-
- // The window is now visible if it has been added, we are not
- // simply finishing, and we are not starting another activity.
- if (!r.activity.mFinished && r.activity.mDecor != null
- && !r.hideForNow) {
- if (r.newConfig != null) {
- performConfigurationChanged(r.activity, r.newConfig);
- r.newConfig = null;
- }
- if (localLOGV) Log.v(TAG, "Resuming " + r + " with isForward="
- + isForward);
- WindowManager.LayoutParams l = r.window.getAttributes();
- if ((l.softInputMode
- & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
- != forwardBit) {
- l.softInputMode = (l.softInputMode
- & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
- | forwardBit;
- ViewManager wm = a.getWindowManager();
- View decor = r.window.getDecorView();
- wm.updateViewLayout(decor, l);
- }
- r.activity.mVisibleFromServer = true;
- mNumVisibleActivities++;
- if (r.activity.mVisibleFromClient) {
- r.activity.makeVisible();
- }
- }
-
- r.nextIdle = mNewActivities;
- mNewActivities = r;
- if (localLOGV) Log.v(
- TAG, "Scheduling idle handler for " + r);
- Looper.myQueue().addIdleHandler(new Idler());
-
- } else {
- // If an exception was thrown when trying to resume, then
- // just end this activity.
- try {
- ActivityManagerNative.getDefault()
- .finishActivity(token, Activity.RESULT_CANCELED, null);
- } catch (RemoteException ex) {
- }
- }
- }
-
- private int mThumbnailWidth = -1;
- private int mThumbnailHeight = -1;
-
- private final Bitmap createThumbnailBitmap(ActivityRecord r) {
- Bitmap thumbnail = null;
- try {
- int w = mThumbnailWidth;
- int h;
- if (w < 0) {
- Resources res = r.activity.getResources();
- mThumbnailHeight = h =
- res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
-
- mThumbnailWidth = w =
- res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
- } else {
- h = mThumbnailHeight;
- }
-
- // XXX Only set hasAlpha if needed?
- thumbnail = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
- thumbnail.eraseColor(0);
- Canvas cv = new Canvas(thumbnail);
- if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
- thumbnail = null;
- }
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to create thumbnail of "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- thumbnail = null;
- }
-
- return thumbnail;
- }
-
- private final void handlePauseActivity(IBinder token, boolean finished,
- boolean userLeaving, int configChanges) {
- ActivityRecord r = mActivities.get(token);
- if (r != null) {
- //Log.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
- if (userLeaving) {
- performUserLeavingActivity(r);
- }
-
- r.activity.mConfigChangeFlags |= configChanges;
- Bundle state = performPauseActivity(token, finished, true);
-
- // Tell the activity manager we have paused.
- try {
- ActivityManagerNative.getDefault().activityPaused(token, state);
- } catch (RemoteException ex) {
- }
- }
- }
-
- final void performUserLeavingActivity(ActivityRecord r) {
- mInstrumentation.callActivityOnUserLeaving(r.activity);
- }
-
- final Bundle performPauseActivity(IBinder token, boolean finished,
- boolean saveState) {
- ActivityRecord r = mActivities.get(token);
- return r != null ? performPauseActivity(r, finished, saveState) : null;
- }
-
- final Bundle performPauseActivity(ActivityRecord r, boolean finished,
- boolean saveState) {
- if (r.paused) {
- if (r.activity.mFinished) {
- // If we are finishing, we won't call onResume() in certain cases.
- // So here we likewise don't want to call onPause() if the activity
- // isn't resumed.
- return null;
- }
- RuntimeException e = new RuntimeException(
- "Performing pause of activity that is not resumed: "
- + r.intent.getComponent().toShortString());
- Log.e(TAG, e.getMessage(), e);
- }
- Bundle state = null;
- if (finished) {
- r.activity.mFinished = true;
- }
- try {
- // Next have the activity save its current state and managed dialogs...
- if (!r.activity.mFinished && saveState) {
- state = new Bundle();
- mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
- r.state = state;
- }
- // Now we are idle.
- r.activity.mCalled = false;
- mInstrumentation.callActivityOnPause(r.activity);
- EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName());
- if (!r.activity.mCalled) {
- throw new SuperNotCalledException(
- "Activity " + r.intent.getComponent().toShortString() +
- " did not call through to super.onPause()");
- }
-
- } catch (SuperNotCalledException e) {
- throw e;
-
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to pause activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- r.paused = true;
- return state;
- }
-
- final void performStopActivity(IBinder token) {
- ActivityRecord r = mActivities.get(token);
- performStopActivityInner(r, null, false);
- }
-
- private static class StopInfo {
- Bitmap thumbnail;
- CharSequence description;
- }
-
- private final class ProviderRefCount {
- public int count;
- ProviderRefCount(int pCount) {
- count = pCount;
- }
- }
-
- private final void performStopActivityInner(ActivityRecord r,
- StopInfo info, boolean keepShown) {
- if (localLOGV) Log.v(TAG, "Performing stop of " + r);
- if (r != null) {
- if (!keepShown && r.stopped) {
- if (r.activity.mFinished) {
- // If we are finishing, we won't call onResume() in certain
- // cases. So here we likewise don't want to call onStop()
- // if the activity isn't resumed.
- return;
- }
- RuntimeException e = new RuntimeException(
- "Performing stop of activity that is not resumed: "
- + r.intent.getComponent().toShortString());
- Log.e(TAG, e.getMessage(), e);
- }
-
- if (info != null) {
- try {
- // First create a thumbnail for the activity...
- //info.thumbnail = createThumbnailBitmap(r);
- info.description = r.activity.onCreateDescription();
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to save state of activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- }
-
- if (!keepShown) {
- try {
- // Now we are idle.
- r.activity.performStop();
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to stop activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- r.stopped = true;
- }
-
- r.paused = true;
- }
- }
-
- private final void updateVisibility(ActivityRecord r, boolean show) {
- View v = r.activity.mDecor;
- if (v != null) {
- if (show) {
- if (!r.activity.mVisibleFromServer) {
- r.activity.mVisibleFromServer = true;
- mNumVisibleActivities++;
- if (r.activity.mVisibleFromClient) {
- r.activity.makeVisible();
- }
- }
- if (r.newConfig != null) {
- performConfigurationChanged(r.activity, r.newConfig);
- r.newConfig = null;
- }
- } else {
- if (r.activity.mVisibleFromServer) {
- r.activity.mVisibleFromServer = false;
- mNumVisibleActivities--;
- v.setVisibility(View.INVISIBLE);
- }
- }
- }
- }
-
- private final void handleStopActivity(IBinder token, boolean show, int configChanges) {
- ActivityRecord r = mActivities.get(token);
- r.activity.mConfigChangeFlags |= configChanges;
-
- StopInfo info = new StopInfo();
- performStopActivityInner(r, info, show);
-
- if (localLOGV) Log.v(
- TAG, "Finishing stop of " + r + ": show=" + show
- + " win=" + r.window);
-
- updateVisibility(r, show);
-
- // Tell activity manager we have been stopped.
- try {
- ActivityManagerNative.getDefault().activityStopped(
- r.token, info.thumbnail, info.description);
- } catch (RemoteException ex) {
- }
- }
-
- final void performRestartActivity(IBinder token) {
- ActivityRecord r = mActivities.get(token);
- if (r.stopped) {
- r.activity.performRestart();
- r.stopped = false;
- }
- }
-
- private final void handleWindowVisibility(IBinder token, boolean show) {
- ActivityRecord r = mActivities.get(token);
- if (!show && !r.stopped) {
- performStopActivityInner(r, null, show);
- } else if (show && r.stopped) {
- // If we are getting ready to gc after going to the background, well
- // we are back active so skip it.
- unscheduleGcIdler();
-
- r.activity.performRestart();
- r.stopped = false;
- }
- if (r.activity.mDecor != null) {
- if (Config.LOGV) Log.v(
- TAG, "Handle window " + r + " visibility: " + show);
- updateVisibility(r, show);
- }
- }
-
- private final void deliverResults(ActivityRecord r, List<ResultInfo> results) {
- final int N = results.size();
- for (int i=0; i<N; i++) {
- ResultInfo ri = results.get(i);
- try {
- if (ri.mData != null) {
- ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
- }
- r.activity.dispatchActivityResult(ri.mResultWho,
- ri.mRequestCode, ri.mResultCode, ri.mData);
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Failure delivering result " + ri + " to activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- }
- }
-
- private final void handleSendResult(ResultData res) {
- ActivityRecord r = mActivities.get(res.token);
- if (localLOGV) Log.v(TAG, "Handling send result to " + r);
- if (r != null) {
- final boolean resumed = !r.paused;
- if (!r.activity.mFinished && r.activity.mDecor != null
- && r.hideForNow && resumed) {
- // We had hidden the activity because it started another
- // one... we have gotten a result back and we are not
- // paused, so make sure our window is visible.
- updateVisibility(r, true);
- }
- if (resumed) {
- try {
- // Now we are idle.
- r.activity.mCalled = false;
- mInstrumentation.callActivityOnPause(r.activity);
- if (!r.activity.mCalled) {
- throw new SuperNotCalledException(
- "Activity " + r.intent.getComponent().toShortString()
- + " did not call through to super.onPause()");
- }
- } catch (SuperNotCalledException e) {
- throw e;
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to pause activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- }
- deliverResults(r, res.results);
- if (resumed) {
- mInstrumentation.callActivityOnResume(r.activity);
- }
- }
- }
-
- public final ActivityRecord performDestroyActivity(IBinder token, boolean finishing) {
- return performDestroyActivity(token, finishing, 0, false);
- }
-
- private final ActivityRecord performDestroyActivity(IBinder token, boolean finishing,
- int configChanges, boolean getNonConfigInstance) {
- ActivityRecord r = mActivities.get(token);
- if (localLOGV) Log.v(TAG, "Performing finish of " + r);
- if (r != null) {
- r.activity.mConfigChangeFlags |= configChanges;
- if (finishing) {
- r.activity.mFinished = true;
- }
- if (!r.paused) {
- try {
- r.activity.mCalled = false;
- mInstrumentation.callActivityOnPause(r.activity);
- EventLog.writeEvent(LOG_ON_PAUSE_CALLED,
- r.activity.getComponentName().getClassName());
- if (!r.activity.mCalled) {
- throw new SuperNotCalledException(
- "Activity " + r.intent.getComponent().toShortString()
- + " did not call through to super.onPause()");
- }
- } catch (SuperNotCalledException e) {
- throw e;
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to pause activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- r.paused = true;
- }
- if (!r.stopped) {
- try {
- r.activity.performStop();
- } catch (SuperNotCalledException e) {
- throw e;
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to stop activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- r.stopped = true;
- }
- if (getNonConfigInstance) {
- try {
- r.lastNonConfigurationInstance
- = r.activity.onRetainNonConfigurationInstance();
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to retain activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- try {
- r.lastNonConfigurationChildInstances
- = r.activity.onRetainNonConfigurationChildInstances();
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to retain child activities "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
-
- }
- try {
- r.activity.mCalled = false;
- r.activity.onDestroy();
- if (!r.activity.mCalled) {
- throw new SuperNotCalledException(
- "Activity " + r.intent.getComponent().toShortString() +
- " did not call through to super.onDestroy()");
- }
- if (r.window != null) {
- r.window.closeAllPanels();
- }
- } catch (SuperNotCalledException e) {
- throw e;
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to destroy activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- }
- mActivities.remove(token);
-
- return r;
- }
-
- private final void handleDestroyActivity(IBinder token, boolean finishing,
- int configChanges, boolean getNonConfigInstance) {
- ActivityRecord r = performDestroyActivity(token, finishing,
- configChanges, getNonConfigInstance);
- if (r != null) {
- WindowManager wm = r.activity.getWindowManager();
- View v = r.activity.mDecor;
- if (v != null) {
- if (r.activity.mVisibleFromServer) {
- mNumVisibleActivities--;
- }
- IBinder wtoken = v.getWindowToken();
- if (r.activity.mWindowAdded) {
- wm.removeViewImmediate(v);
- }
- if (wtoken != null) {
- WindowManagerImpl.getDefault().closeAll(wtoken,
- r.activity.getClass().getName(), "Activity");
- }
- r.activity.mDecor = null;
- }
- WindowManagerImpl.getDefault().closeAll(token,
- r.activity.getClass().getName(), "Activity");
-
- // Mocked out contexts won't be participating in the normal
- // process lifecycle, but if we're running with a proper
- // ApplicationContext we need to have it tear down things
- // cleanly.
- Context c = r.activity.getBaseContext();
- if (c instanceof ApplicationContext) {
- ((ApplicationContext) c).scheduleFinalCleanup(
- r.activity.getClass().getName(), "Activity");
- }
- }
- if (finishing) {
- try {
- ActivityManagerNative.getDefault().activityDestroyed(token);
- } catch (RemoteException ex) {
- // If the system process has died, it's game over for everyone.
- }
- }
- }
-
- private final void handleRelaunchActivity(ActivityRecord tmp, int configChanges) {
- // If we are getting ready to gc after going to the background, well
- // we are back active so skip it.
- unscheduleGcIdler();
-
- Configuration changedConfig = null;
-
- // First: make sure we have the most recent configuration and most
- // recent version of the activity, or skip it if some previous call
- // had taken a more recent version.
- synchronized (mRelaunchingActivities) {
- int N = mRelaunchingActivities.size();
- IBinder token = tmp.token;
- tmp = null;
- for (int i=0; i<N; i++) {
- ActivityRecord r = mRelaunchingActivities.get(i);
- if (r.token == token) {
- tmp = r;
- mRelaunchingActivities.remove(i);
- i--;
- N--;
- }
- }
-
- if (tmp == null) {
- return;
- }
-
- if (mPendingConfiguration != null) {
- changedConfig = mPendingConfiguration;
- mPendingConfiguration = null;
- }
- }
-
- // If there was a pending configuration change, execute it first.
- if (changedConfig != null) {
- handleConfigurationChanged(changedConfig);
- }
-
- ActivityRecord r = mActivities.get(tmp.token);
- if (localLOGV) Log.v(TAG, "Handling relaunch of " + r);
- if (r == null) {
- return;
- }
-
- r.activity.mConfigChangeFlags |= configChanges;
-
- Bundle savedState = null;
- if (!r.paused) {
- savedState = performPauseActivity(r.token, false, true);
- }
-
- handleDestroyActivity(r.token, false, configChanges, true);
-
- r.activity = null;
- r.window = null;
- r.hideForNow = false;
- r.nextIdle = null;
- r.pendingResults = tmp.pendingResults;
- r.pendingIntents = tmp.pendingIntents;
- r.startsNotResumed = tmp.startsNotResumed;
- if (savedState != null) {
- r.state = savedState;
- }
-
- handleLaunchActivity(r);
- }
-
- private final void handleRequestThumbnail(IBinder token) {
- ActivityRecord r = mActivities.get(token);
- Bitmap thumbnail = createThumbnailBitmap(r);
- CharSequence description = null;
- try {
- description = r.activity.onCreateDescription();
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to create description of activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- //System.out.println("Reporting top thumbnail " + thumbnail);
- try {
- ActivityManagerNative.getDefault().reportThumbnail(
- token, thumbnail, description);
- } catch (RemoteException ex) {
- }
- }
-
- ArrayList<ComponentCallbacks> collectComponentCallbacksLocked(
- boolean allActivities, Configuration newConfig) {
- ArrayList<ComponentCallbacks> callbacks
- = new ArrayList<ComponentCallbacks>();
-
- if (mActivities.size() > 0) {
- Iterator<ActivityRecord> it = mActivities.values().iterator();
- while (it.hasNext()) {
- ActivityRecord ar = it.next();
- Activity a = ar.activity;
- if (a != null) {
- if (!ar.activity.mFinished && (allActivities ||
- (a != null && !ar.paused))) {
- // If the activity is currently resumed, its configuration
- // needs to change right now.
- callbacks.add(a);
- } else if (newConfig != null) {
- // Otherwise, we will tell it about the change
- // the next time it is resumed or shown. Note that
- // the activity manager may, before then, decide the
- // activity needs to be destroyed to handle its new
- // configuration.
- ar.newConfig = newConfig;
- }
- }
- }
- }
- if (mServices.size() > 0) {
- Iterator<Service> it = mServices.values().iterator();
- while (it.hasNext()) {
- callbacks.add(it.next());
- }
- }
- synchronized (mProviderMap) {
- if (mLocalProviders.size() > 0) {
- Iterator<ProviderRecord> it = mLocalProviders.values().iterator();
- while (it.hasNext()) {
- callbacks.add(it.next().mLocalProvider);
- }
- }
- }
- final int N = mAllApplications.size();
- for (int i=0; i<N; i++) {
- callbacks.add(mAllApplications.get(i));
- }
-
- return callbacks;
- }
-
- private final void performConfigurationChanged(
- ComponentCallbacks cb, Configuration config) {
- // Only for Activity objects, check that they actually call up to their
- // superclass implementation. ComponentCallbacks is an interface, so
- // we check the runtime type and act accordingly.
- Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
- if (activity != null) {
- activity.mCalled = false;
- }
-
- boolean shouldChangeConfig = false;
- if ((activity == null) || (activity.mCurrentConfig == null)) {
- shouldChangeConfig = true;
- } else {
-
- // If the new config is the same as the config this Activity
- // is already running with then don't bother calling
- // onConfigurationChanged
- int diff = activity.mCurrentConfig.diff(config);
- if (diff != 0) {
-
- // If this activity doesn't handle any of the config changes
- // then don't bother calling onConfigurationChanged as we're
- // going to destroy it.
- if ((~activity.mActivityInfo.configChanges & diff) == 0) {
- shouldChangeConfig = true;
- }
- }
- }
-
- if (shouldChangeConfig) {
- cb.onConfigurationChanged(config);
-
- if (activity != null) {
- if (!activity.mCalled) {
- throw new SuperNotCalledException(
- "Activity " + activity.getLocalClassName() +
- " did not call through to super.onConfigurationChanged()");
- }
- activity.mConfigChangeFlags = 0;
- activity.mCurrentConfig = new Configuration(config);
- }
- }
- }
-
- final void handleConfigurationChanged(Configuration config) {
-
- synchronized (mRelaunchingActivities) {
- if (mPendingConfiguration != null) {
- config = mPendingConfiguration;
- mPendingConfiguration = null;
- }
- }
-
- ArrayList<ComponentCallbacks> callbacks
- = new ArrayList<ComponentCallbacks>();
-
- synchronized(mPackages) {
- if (mConfiguration == null) {
- mConfiguration = new Configuration();
- }
- mConfiguration.updateFrom(config);
- DisplayMetrics dm = getDisplayMetricsLocked(true);
-
- // set it for java, this also affects newly created Resources
- if (config.locale != null) {
- Locale.setDefault(config.locale);
- }
-
- Resources.updateSystemConfiguration(config, null);
-
- ApplicationContext.ApplicationPackageManager.configurationChanged();
- //Log.i(TAG, "Configuration changed in " + currentPackageName());
- {
- Iterator<WeakReference<Resources>> it =
- mActiveResources.values().iterator();
- //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
- // mActiveResources.entrySet().iterator();
- while (it.hasNext()) {
- WeakReference<Resources> v = it.next();
- Resources r = v.get();
- if (r != null) {
- r.updateConfiguration(config, dm);
- //Log.i(TAG, "Updated app resources " + v.getKey()
- // + " " + r + ": " + r.getConfiguration());
- } else {
- //Log.i(TAG, "Removing old resources " + v.getKey());
- it.remove();
- }
- }
- }
-
- callbacks = collectComponentCallbacksLocked(false, config);
- }
-
- final int N = callbacks.size();
- for (int i=0; i<N; i++) {
- performConfigurationChanged(callbacks.get(i), config);
- }
- }
-
- final void handleActivityConfigurationChanged(IBinder token) {
- ActivityRecord r = mActivities.get(token);
- if (r == null || r.activity == null) {
- return;
- }
-
- performConfigurationChanged(r.activity, mConfiguration);
- }
-
- final void handleLowMemory() {
- ArrayList<ComponentCallbacks> callbacks
- = new ArrayList<ComponentCallbacks>();
-
- synchronized(mPackages) {
- callbacks = collectComponentCallbacksLocked(true, null);
- }
-
- final int N = callbacks.size();
- for (int i=0; i<N; i++) {
- callbacks.get(i).onLowMemory();
- }
-
- // Ask SQLite to free up as much memory as it can, mostly from it's page caches
- int sqliteReleased = SQLiteDatabase.releaseMemory();
- EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
-
- BinderInternal.forceGc("mem");
- }
-
- private final void handleBindApplication(AppBindData data) {
- mBoundApplication = data;
- mConfiguration = new Configuration(data.config);
-
- // We now rely on this being set by zygote.
- //Process.setGid(data.appInfo.gid);
- //Process.setUid(data.appInfo.uid);
-
- // send up app name; do this *before* waiting for debugger
- android.ddm.DdmHandleAppName.setAppName(data.processName);
-
- /*
- * Before spawning a new process, reset the time zone to be the system time zone.
- * This needs to be done because the system time zone could have changed after the
- * the spawning of this process. Without doing this this process would have the incorrect
- * system time zone.
- */
- TimeZone.setDefault(null);
-
- /*
- * Initialize the default locale in this process for the reasons we set the time zone.
- */
- Locale.setDefault(data.config.locale);
-
- data.info = getPackageInfoNoCheck(data.appInfo);
-
- if (data.debugMode != IApplicationThread.DEBUG_OFF) {
- // XXX should have option to change the port.
- Debug.changeDebugPort(8100);
- if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
- Log.w(TAG, "Application " + data.info.getPackageName()
- + " is waiting for the debugger on port 8100...");
-
- IActivityManager mgr = ActivityManagerNative.getDefault();
- try {
- mgr.showWaitingForDebugger(mAppThread, true);
- } catch (RemoteException ex) {
- }
-
- Debug.waitForDebugger();
-
- try {
- mgr.showWaitingForDebugger(mAppThread, false);
- } catch (RemoteException ex) {
- }
-
- } else {
- Log.w(TAG, "Application " + data.info.getPackageName()
- + " can be debugged on port 8100...");
- }
- }
-
- if (data.instrumentationName != null) {
- ApplicationContext appContext = new ApplicationContext();
- appContext.init(data.info, null, this);
- InstrumentationInfo ii = null;
- try {
- ii = appContext.getPackageManager().
- getInstrumentationInfo(data.instrumentationName, 0);
- } catch (PackageManager.NameNotFoundException e) {
- }
- if (ii == null) {
- throw new RuntimeException(
- "Unable to find instrumentation info for: "
- + data.instrumentationName);
- }
-
- mInstrumentationAppDir = ii.sourceDir;
- mInstrumentationAppPackage = ii.packageName;
- mInstrumentedAppDir = data.info.getAppDir();
-
- ApplicationInfo instrApp = new ApplicationInfo();
- instrApp.packageName = ii.packageName;
- instrApp.sourceDir = ii.sourceDir;
- instrApp.publicSourceDir = ii.publicSourceDir;
- instrApp.dataDir = ii.dataDir;
- PackageInfo pi = getPackageInfo(instrApp,
- appContext.getClassLoader(), false, true);
- ApplicationContext instrContext = new ApplicationContext();
- instrContext.init(pi, null, this);
-
- try {
- java.lang.ClassLoader cl = instrContext.getClassLoader();
- mInstrumentation = (Instrumentation)
- cl.loadClass(data.instrumentationName.getClassName()).newInstance();
- } catch (Exception e) {
- throw new RuntimeException(
- "Unable to instantiate instrumentation "
- + data.instrumentationName + ": " + e.toString(), e);
- }
-
- mInstrumentation.init(this, instrContext, appContext,
- new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);
-
- if (data.profileFile != null && !ii.handleProfiling) {
- data.handlingProfiling = true;
- File file = new File(data.profileFile);
- file.getParentFile().mkdirs();
- Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
- }
-
- try {
- mInstrumentation.onCreate(data.instrumentationArgs);
- }
- catch (Exception e) {
- throw new RuntimeException(
- "Exception thrown in onCreate() of "
- + data.instrumentationName + ": " + e.toString(), e);
- }
-
- } else {
- mInstrumentation = new Instrumentation();
- }
-
- Application app = data.info.makeApplication();
- mInitialApplication = app;
-
- List<ProviderInfo> providers = data.providers;
- if (providers != null) {
- installContentProviders(app, providers);
- }
-
- try {
- mInstrumentation.callApplicationOnCreate(app);
- } catch (Exception e) {
- if (!mInstrumentation.onException(app, e)) {
- throw new RuntimeException(
- "Unable to create application " + app.getClass().getName()
- + ": " + e.toString(), e);
- }
- }
- }
-
- /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
- IActivityManager am = ActivityManagerNative.getDefault();
- if (mBoundApplication.profileFile != null && mBoundApplication.handlingProfiling) {
- Debug.stopMethodTracing();
- }
- //Log.i(TAG, "am: " + ActivityManagerNative.getDefault()
- // + ", app thr: " + mAppThread);
- try {
- am.finishInstrumentation(mAppThread, resultCode, results);
- } catch (RemoteException ex) {
- }
- }
-
- private final void installContentProviders(
- Context context, List<ProviderInfo> providers) {
- final ArrayList<IActivityManager.ContentProviderHolder> results =
- new ArrayList<IActivityManager.ContentProviderHolder>();
-
- Iterator<ProviderInfo> i = providers.iterator();
- while (i.hasNext()) {
- ProviderInfo cpi = i.next();
- StringBuilder buf = new StringBuilder(128);
- buf.append("Publishing provider ");
- buf.append(cpi.authority);
- buf.append(": ");
- buf.append(cpi.name);
- Log.i(TAG, buf.toString());
- IContentProvider cp = installProvider(context, null, cpi, false);
- if (cp != null) {
- IActivityManager.ContentProviderHolder cph =
- new IActivityManager.ContentProviderHolder(cpi);
- cph.provider = cp;
- results.add(cph);
- // Don't ever unload this provider from the process.
- synchronized(mProviderMap) {
- mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000));
- }
- }
- }
-
- try {
- ActivityManagerNative.getDefault().publishContentProviders(
- getApplicationThread(), results);
- } catch (RemoteException ex) {
- }
- }
-
- private final IContentProvider getProvider(Context context, String name) {
- synchronized(mProviderMap) {
- final ProviderRecord pr = mProviderMap.get(name);
- if (pr != null) {
- return pr.mProvider;
- }
- }
-
- IActivityManager.ContentProviderHolder holder = null;
- try {
- holder = ActivityManagerNative.getDefault().getContentProvider(
- getApplicationThread(), name);
- } catch (RemoteException ex) {
- }
- if (holder == null) {
- Log.e(TAG, "Failed to find provider info for " + name);
- return null;
- }
- if (holder.permissionFailure != null) {
- throw new SecurityException("Permission " + holder.permissionFailure
- + " required for provider " + name);
- }
-
- IContentProvider prov = installProvider(context, holder.provider,
- holder.info, true);
- //Log.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded);
- if (holder.noReleaseNeeded || holder.provider == null) {
- // We are not going to release the provider if it is an external
- // provider that doesn't care about being released, or if it is
- // a local provider running in this process.
- //Log.i(TAG, "*** NO RELEASE NEEDED");
- synchronized(mProviderMap) {
- mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000));
- }
- }
- return prov;
- }
-
- public final IContentProvider acquireProvider(Context c, String name) {
- IContentProvider provider = getProvider(c, name);
- if(provider == null)
- return null;
- IBinder jBinder = provider.asBinder();
- synchronized(mProviderMap) {
- ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
- if(prc == null) {
- mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
- } else {
- prc.count++;
- } //end else
- } //end synchronized
- return provider;
- }
-
- public final boolean releaseProvider(IContentProvider provider) {
- if(provider == null) {
- return false;
- }
- IBinder jBinder = provider.asBinder();
- synchronized(mProviderMap) {
- ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
- if(prc == null) {
- if(localLOGV) Log.v(TAG, "releaseProvider::Weird shouldnt be here");
- return false;
- } else {
- prc.count--;
- if(prc.count == 0) {
- mProviderRefCountMap.remove(jBinder);
- //invoke removeProvider to dereference provider
- removeProviderLocked(provider);
- } //end if
- } //end else
- } //end synchronized
- return true;
- }
-
- public final void removeProviderLocked(IContentProvider provider) {
- if (provider == null) {
- return;
- }
- IBinder providerBinder = provider.asBinder();
- boolean amRemoveFlag = false;
-
- // remove the provider from mProviderMap
- Iterator<ProviderRecord> iter = mProviderMap.values().iterator();
- while (iter.hasNext()) {
- ProviderRecord pr = iter.next();
- IBinder myBinder = pr.mProvider.asBinder();
- if (myBinder == providerBinder) {
- //find if its published by this process itself
- if(pr.mLocalProvider != null) {
- if(localLOGV) Log.i(TAG, "removeProvider::found local provider returning");
- return;
- }
- if(localLOGV) Log.v(TAG, "removeProvider::Not local provider Unlinking " +
- "death recipient");
- //content provider is in another process
- myBinder.unlinkToDeath(pr, 0);
- iter.remove();
- //invoke remove only once for the very first name seen
- if(!amRemoveFlag) {
- try {
- if(localLOGV) Log.v(TAG, "removeProvider::Invoking " +
- "ActivityManagerNative.removeContentProvider("+pr.mName);
- ActivityManagerNative.getDefault().removeContentProvider(getApplicationThread(), pr.mName);
- amRemoveFlag = true;
- } catch (RemoteException e) {
- //do nothing content provider object is dead any way
- } //end catch
- }
- } //end if myBinder
- } //end while iter
- }
-
- final void removeDeadProvider(String name, IContentProvider provider) {
- synchronized(mProviderMap) {
- ProviderRecord pr = mProviderMap.get(name);
- if (pr.mProvider.asBinder() == provider.asBinder()) {
- Log.i(TAG, "Removing dead content provider: " + name);
- mProviderMap.remove(name);
- }
- }
- }
-
- final void removeDeadProviderLocked(String name, IContentProvider provider) {
- ProviderRecord pr = mProviderMap.get(name);
- if (pr.mProvider.asBinder() == provider.asBinder()) {
- Log.i(TAG, "Removing dead content provider: " + name);
- mProviderMap.remove(name);
- }
- }
-
- private final IContentProvider installProvider(Context context,
- IContentProvider provider, ProviderInfo info, boolean noisy) {
- ContentProvider localProvider = null;
- if (provider == null) {
- if (noisy) {
- Log.d(TAG, "Loading provider " + info.authority + ": "
- + info.name);
- }
- Context c = null;
- ApplicationInfo ai = info.applicationInfo;
- if (context.getPackageName().equals(ai.packageName)) {
- c = context;
- } else if (mInitialApplication != null &&
- mInitialApplication.getPackageName().equals(ai.packageName)) {
- c = mInitialApplication;
- } else {
- try {
- c = context.createPackageContext(ai.packageName,
- Context.CONTEXT_INCLUDE_CODE);
- } catch (PackageManager.NameNotFoundException e) {
- }
- }
- if (c == null) {
- Log.w(TAG, "Unable to get context for package " +
- ai.packageName +
- " while loading content provider " +
- info.name);
- return null;
- }
- try {
- final java.lang.ClassLoader cl = c.getClassLoader();
- localProvider = (ContentProvider)cl.
- loadClass(info.name).newInstance();
- provider = localProvider.getIContentProvider();
- if (provider == null) {
- Log.e(TAG, "Failed to instantiate class " +
- info.name + " from sourceDir " +
- info.applicationInfo.sourceDir);
- return null;
- }
- if (Config.LOGV) Log.v(
- TAG, "Instantiating local provider " + info.name);
- // XXX Need to create the correct context for this provider.
- localProvider.attachInfo(c, info);
- } catch (java.lang.Exception e) {
- if (!mInstrumentation.onException(null, e)) {
- throw new RuntimeException(
- "Unable to get provider " + info.name
- + ": " + e.toString(), e);
- }
- return null;
- }
- } else if (localLOGV) {
- Log.v(TAG, "Installing external provider " + info.authority + ": "
- + info.name);
- }
-
- synchronized (mProviderMap) {
- // Cache the pointer for the remote provider.
- String names[] = PATTERN_SEMICOLON.split(info.authority);
- for (int i=0; i<names.length; i++) {
- ProviderRecord pr = new ProviderRecord(names[i], provider,
- localProvider);
- try {
- provider.asBinder().linkToDeath(pr, 0);
- mProviderMap.put(names[i], pr);
- } catch (RemoteException e) {
- return null;
- }
- }
- if (localProvider != null) {
- mLocalProviders.put(provider.asBinder(),
- new ProviderRecord(null, provider, localProvider));
- }
- }
-
- return provider;
- }
-
- private final void attach(boolean system) {
- sThreadLocal.set(this);
- mSystemThread = system;
- AndroidHttpClient.setThreadBlocked(true);
- if (!system) {
- android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
- RuntimeInit.setApplicationObject(mAppThread.asBinder());
- IActivityManager mgr = ActivityManagerNative.getDefault();
- try {
- mgr.attachApplication(mAppThread);
- } catch (RemoteException ex) {
- }
- } else {
- // Don't set application object here -- if the system crashes,
- // we can't display an alert, we just want to die die die.
- android.ddm.DdmHandleAppName.setAppName("system_process");
- try {
- mInstrumentation = new Instrumentation();
- ApplicationContext context = new ApplicationContext();
- context.init(getSystemContext().mPackageInfo, null, this);
- Application app = Instrumentation.newApplication(Application.class, context);
- mAllApplications.add(app);
- mInitialApplication = app;
- app.onCreate();
- } catch (Exception e) {
- throw new RuntimeException(
- "Unable to instantiate Application():" + e.toString(), e);
- }
- }
- }
-
- private final void detach()
- {
- AndroidHttpClient.setThreadBlocked(false);
- sThreadLocal.set(null);
- }
-
- public static final ActivityThread systemMain() {
- ActivityThread thread = new ActivityThread();
- thread.attach(true);
- return thread;
- }
-
- public final void installSystemProviders(List providers) {
- if (providers != null) {
- installContentProviders(mInitialApplication,
- (List<ProviderInfo>)providers);
- }
- }
-
- public static final void main(String[] args) {
- Process.setArgV0("<pre-initialized>");
-
- Looper.prepareMainLooper();
-
- ActivityThread thread = new ActivityThread();
- thread.attach(false);
-
- Looper.loop();
-
- if (Process.supportsProcesses()) {
- throw new RuntimeException("Main thread loop unexpectedly exited");
- }
-
- thread.detach();
- String name;
- if (thread.mInitialApplication != null) name = thread.mInitialApplication.getPackageName();
- else name = "<unknown>";
- Log.i(TAG, "Main thread of " + name + " is now exiting");
- }
-}
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
deleted file mode 100644
index b4c0e31..0000000
--- a/core/java/android/app/AlarmManager.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-
-/**
- * This class provides access to the system alarm services. These allow you
- * to schedule your application to be run at some point in the future. When
- * an alarm goes off, the {@link Intent} that had been registered for it
- * is broadcast by the system, automatically starting the target application
- * if it is not already running. Registered alarms are retained while the
- * device is asleep (and can optionally wake the device up if they go off
- * during that time), but will be cleared if it is turned off and rebooted.
- *
- * <p><b>Note: The Alarm Manager is intended for cases where you want to have
- * your application code run at a specific time, even if your application is
- * not currently running. For normal timing operations (ticks, timeouts,
- * etc) it is easier and much more efficient to use
- * {@link android.os.Handler}.</b>
- *
- * <p>You do not
- * instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.ALARM_SERVICE)}.
- */
-public class AlarmManager
-{
- /**
- * Alarm time in {@link System#currentTimeMillis System.currentTimeMillis()}
- * (wall clock time in UTC), which will wake up the device when
- * it goes off.
- */
- public static final int RTC_WAKEUP = 0;
- /**
- * Alarm time in {@link System#currentTimeMillis System.currentTimeMillis()}
- * (wall clock time in UTC). This alarm does not wake the
- * device up; if it goes off while the device is asleep, it will not be
- * delivered until the next time the device wakes up.
- */
- public static final int RTC = 1;
- /**
- * Alarm time in {@link android.os.SystemClock#elapsedRealtime
- * SystemClock.elapsedRealtime()} (time since boot, including sleep),
- * which will wake up the device when it goes off.
- */
- public static final int ELAPSED_REALTIME_WAKEUP = 2;
- /**
- * Alarm time in {@link android.os.SystemClock#elapsedRealtime
- * SystemClock.elapsedRealtime()} (time since boot, including sleep).
- * This alarm does not wake the device up; if it goes off while the device
- * is asleep, it will not be delivered until the next time the device
- * wakes up.
- */
- public static final int ELAPSED_REALTIME = 3;
-
- private final IAlarmManager mService;
-
- /**
- * package private on purpose
- */
- AlarmManager(IAlarmManager service) {
- mService = service;
- }
-
- /**
- * Schedule an alarm. <b>Note: for timing operations (ticks, timeouts,
- * etc) it is easier and much more efficient to use
- * {@link android.os.Handler}.</b> If there is already an alarm scheduled
- * for the same IntentSender, it will first be canceled.
- *
- * <p>If the time occurs in the past, the alarm will be triggered
- * immediately. If there is already an alarm for this Intent
- * scheduled (with the equality of two intents being defined by
- * {@link Intent#filterEquals}), then it will be removed and replaced by
- * this one.
- *
- * <p>
- * The alarm is an intent broadcast that goes to a broadcast receiver that
- * you registered with {@link android.content.Context#registerReceiver}
- * or through the &lt;receiver&gt; tag in an AndroidManifest.xml file.
- *
- * <p>
- * Alarm intents are delivered with a data extra of type int called
- * {@link Intent#EXTRA_ALARM_COUNT Intent.EXTRA_ALARM_COUNT} that indicates
- * how many past alarm events have been accumulated into this intent
- * broadcast. Recurring alarms that have gone undelivered because the
- * phone was asleep may have a count greater than one when delivered.
- *
- * @param type One of ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC or
- * RTC_WAKEUP.
- * @param triggerAtTime Time the alarm should go off, using the
- * appropriate clock (depending on the alarm type).
- * @param operation Action to perform when the alarm goes off;
- * typically comes from {@link PendingIntent#getBroadcast
- * IntentSender.getBroadcast()}.
- *
- * @see android.os.Handler
- * @see #setRepeating
- * @see #cancel
- * @see android.content.Context#sendBroadcast
- * @see android.content.Context#registerReceiver
- * @see android.content.Intent#filterEquals
- * @see #ELAPSED_REALTIME
- * @see #ELAPSED_REALTIME_WAKEUP
- * @see #RTC
- * @see #RTC_WAKEUP
- */
- public void set(int type, long triggerAtTime, PendingIntent operation) {
- try {
- mService.set(type, triggerAtTime, operation);
- } catch (RemoteException ex) {
- }
- }
-
- /**
- * Schedule a repeating alarm. <b>Note: for timing operations (ticks,
- * timeouts, etc) it is easier and much more efficient to use
- * {@link android.os.Handler}.</b> If there is already an alarm scheduled
- * for the same IntentSender, it will first be canceled.
- *
- * <p>Like {@link #set}, except you can also
- * supply a rate at which the alarm will repeat. This alarm continues
- * repeating until explicitly removed with {@link #cancel}. If the time
- * occurs in the past, the alarm will be triggered immediately, with an
- * alarm count depending on how far in the past the trigger time is relative
- * to the repeat interval.
- *
- * <p>If an alarm is delayed (by system sleep, for example, for non
- * _WAKEUP alarm types), a skipped repeat will be delivered as soon as
- * possible. After that, future alarms will be delivered according to the
- * original schedule; they do not drift over time. For example, if you have
- * set a recurring alarm for the top of every hour but the phone was asleep
- * from 7:45 until 8:45, an alarm will be sent as soon as the phone awakens,
- * then the next alarm will be sent at 9:00.
- *
- * <p>If your application wants to allow the delivery times to drift in
- * order to guarantee that at least a certain time interval always elapses
- * between alarms, then the approach to take is to use one-time alarms,
- * scheduling the next one yourself when handling each alarm delivery.
- *
- * @param type One of ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP}, RTC or
- * RTC_WAKEUP.
- * @param triggerAtTime Time the alarm should first go off, using the
- * appropriate clock (depending on the alarm type).
- * @param interval Interval between subsequent repeats of the alarm.
- * @param operation Action to perform when the alarm goes off;
- * typically comes from {@link PendingIntent#getBroadcast
- * IntentSender.getBroadcast()}.
- *
- * @see android.os.Handler
- * @see #set
- * @see #cancel
- * @see android.content.Context#sendBroadcast
- * @see android.content.Context#registerReceiver
- * @see android.content.Intent#filterEquals
- * @see #ELAPSED_REALTIME
- * @see #ELAPSED_REALTIME_WAKEUP
- * @see #RTC
- * @see #RTC_WAKEUP
- */
- public void setRepeating(int type, long triggerAtTime, long interval,
- PendingIntent operation) {
- try {
- mService.setRepeating(type, triggerAtTime, interval, operation);
- } catch (RemoteException ex) {
- }
- }
-
- /**
- * Available inexact recurrence intervals recognized by
- * {@link #setInexactRepeating(int, long, long, PendingIntent)}
- */
- public static final long INTERVAL_FIFTEEN_MINUTES = 15 * 60 * 1000;
- public static final long INTERVAL_HALF_HOUR = 2*INTERVAL_FIFTEEN_MINUTES;
- public static final long INTERVAL_HOUR = 2*INTERVAL_HALF_HOUR;
- public static final long INTERVAL_HALF_DAY = 12*INTERVAL_HOUR;
- public static final long INTERVAL_DAY = 2*INTERVAL_HALF_DAY;
-
- /**
- * Schedule a repeating alarm that has inexact trigger time requirements;
- * for example, an alarm that repeats every hour, but not necessarily at
- * the top of every hour. These alarms are more power-efficient than
- * the strict recurrences supplied by {@link #setRepeating}, since the
- * system can adjust alarms' phase to cause them to fire simultaneously,
- * avoiding waking the device from sleep more than necessary.
- *
- * <p>Your alarm's first trigger will not be before the requested time,
- * but it might not occur for almost a full interval after that time. In
- * addition, while the overall period of the repeating alarm will be as
- * requested, the time between any two successive firings of the alarm
- * may vary. If your application demands very low jitter, use
- * {@link #setRepeating} instead.
- *
- * @param type One of ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP}, RTC or
- * RTC_WAKEUP.
- * @param triggerAtTime Time the alarm should first go off, using the
- * appropriate clock (depending on the alarm type). This
- * is inexact: the alarm will not fire before this time,
- * but there may be a delay of almost an entire alarm
- * interval before the first invocation of the alarm.
- * @param interval Interval between subsequent repeats of the alarm. If
- * this is one of INTERVAL_FIFTEEN_MINUTES, INTERVAL_HALF_HOUR,
- * INTERVAL_HOUR, INTERVAL_HALF_DAY, or INTERVAL_DAY then the
- * alarm will be phase-aligned with other alarms to reduce
- * the number of wakeups. Otherwise, the alarm will be set
- * as though the application had called {@link #setRepeating}.
- * @param operation Action to perform when the alarm goes off;
- * typically comes from {@link PendingIntent#getBroadcast
- * IntentSender.getBroadcast()}.
- *
- * @see android.os.Handler
- * @see #set
- * @see #cancel
- * @see android.content.Context#sendBroadcast
- * @see android.content.Context#registerReceiver
- * @see android.content.Intent#filterEquals
- * @see #ELAPSED_REALTIME
- * @see #ELAPSED_REALTIME_WAKEUP
- * @see #RTC
- * @see #RTC_WAKEUP
- * @see #INTERVAL_FIFTEEN_MINUTES
- * @see #INTERVAL_HALF_HOUR
- * @see #INTERVAL_HOUR
- * @see #INTERVAL_HALF_DAY
- * @see #INTERVAL_DAY
- */
- public void setInexactRepeating(int type, long triggerAtTime, long interval,
- PendingIntent operation) {
- try {
- mService.setInexactRepeating(type, triggerAtTime, interval, operation);
- } catch (RemoteException ex) {
- }
- }
-
- /**
- * Remove any alarms with a matching {@link Intent}.
- * Any alarm, of any type, whose Intent matches this one (as defined by
- * {@link Intent#filterEquals}), will be canceled.
- *
- * @param operation IntentSender which matches a previously added
- * IntentSender.
- *
- * @see #set
- */
- public void cancel(PendingIntent operation) {
- try {
- mService.remove(operation);
- } catch (RemoteException ex) {
- }
- }
-
- public void setTimeZone(String timeZone) {
- try {
- mService.setTimeZone(timeZone);
- } catch (RemoteException ex) {
- }
- }
-}
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
deleted file mode 100644
index f2b89c3..0000000
--- a/core/java/android/app/AlertDialog.java
+++ /dev/null
@@ -1,795 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.Context;
-import android.content.DialogInterface;
-import android.database.Cursor;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Message;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.AdapterView;
-import android.widget.Button;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-
-import com.android.internal.app.AlertController;
-
-/**
- * A subclass of Dialog that can display one, two or three buttons. If you only want to
- * display a String in this dialog box, use the setMessage() method. If you
- * want to display a more complex view, look up the FrameLayout called "body"
- * and add your view to it:
- *
- * <pre>
- * FrameLayout fl = (FrameLayout) findViewById(R.id.body);
- * fl.add(myView, new LayoutParams(FILL_PARENT, WRAP_CONTENT));
- * </pre>
- *
- * <p>The AlertDialog class takes care of automatically setting
- * {@link WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM
- * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM} for you based on whether
- * any views in the dialog return true from {@link View#onCheckIsTextEditor()
- * View.onCheckIsTextEditor()}. Generally you want this set for a Dialog
- * without text editors, so that it will be placed on top of the current
- * input method UI. You can modify this behavior by forcing the flag to your
- * desired mode after calling {@link #onCreate}.
- */
-public class AlertDialog extends Dialog implements DialogInterface {
- private AlertController mAlert;
-
- protected AlertDialog(Context context) {
- this(context, com.android.internal.R.style.Theme_Dialog_Alert);
- }
-
- protected AlertDialog(Context context, int theme) {
- super(context, theme);
- mAlert = new AlertController(context, this, getWindow());
- }
-
- protected AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
- super(context, com.android.internal.R.style.Theme_Dialog_Alert);
- setCancelable(cancelable);
- setOnCancelListener(cancelListener);
- mAlert = new AlertController(context, this, getWindow());
- }
-
- /**
- * Gets one of the buttons used in the dialog.
- * <p>
- * If a button does not exist in the dialog, null will be returned.
- *
- * @param whichButton The identifier of the button that should be returned.
- * For example, this can be
- * {@link DialogInterface#BUTTON_POSITIVE}.
- * @return The button from the dialog, or null if a button does not exist.
- */
- public Button getButton(int whichButton) {
- return mAlert.getButton(whichButton);
- }
-
- /**
- * Gets the list view used in the dialog.
- *
- * @return The {@link ListView} from the dialog.
- */
- public ListView getListView() {
- return mAlert.getListView();
- }
-
- @Override
- public void setTitle(CharSequence title) {
- super.setTitle(title);
- mAlert.setTitle(title);
- }
-
- /**
- * @see Builder#setCustomTitle(View)
- */
- public void setCustomTitle(View customTitleView) {
- mAlert.setCustomTitle(customTitleView);
- }
-
- public void setMessage(CharSequence message) {
- mAlert.setMessage(message);
- }
-
- /**
- * Set the view to display in that dialog.
- */
- public void setView(View view) {
- mAlert.setView(view);
- }
-
- /**
- * Set the view to display in that dialog, specifying the spacing to appear around that
- * view.
- *
- * @param view The view to show in the content area of the dialog
- * @param viewSpacingLeft Extra space to appear to the left of {@code view}
- * @param viewSpacingTop Extra space to appear above {@code view}
- * @param viewSpacingRight Extra space to appear to the right of {@code view}
- * @param viewSpacingBottom Extra space to appear below {@code view}
- */
- public void setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight,
- int viewSpacingBottom) {
- mAlert.setView(view, viewSpacingLeft, viewSpacingTop, viewSpacingRight, viewSpacingBottom);
- }
-
- /**
- * Set a message to be sent when a button is pressed.
- *
- * @param whichButton Which button to set the message for, can be one of
- * {@link DialogInterface#BUTTON_POSITIVE},
- * {@link DialogInterface#BUTTON_NEGATIVE}, or
- * {@link DialogInterface#BUTTON_NEUTRAL}
- * @param text The text to display in positive button.
- * @param msg The {@link Message} to be sent when clicked.
- */
- public void setButton(int whichButton, CharSequence text, Message msg) {
- mAlert.setButton(whichButton, text, null, msg);
- }
-
- /**
- * Set a listener to be invoked when the positive button of the dialog is pressed.
- *
- * @param whichButton Which button to set the listener on, can be one of
- * {@link DialogInterface#BUTTON_POSITIVE},
- * {@link DialogInterface#BUTTON_NEGATIVE}, or
- * {@link DialogInterface#BUTTON_NEUTRAL}
- * @param text The text to display in positive button.
- * @param listener The {@link DialogInterface.OnClickListener} to use.
- */
- public void setButton(int whichButton, CharSequence text, OnClickListener listener) {
- mAlert.setButton(whichButton, text, listener, null);
- }
-
- /**
- * @deprecated Use {@link #setButton(int, CharSequence, Message)} with
- * {@link DialogInterface#BUTTON_POSITIVE}.
- */
- @Deprecated
- public void setButton(CharSequence text, Message msg) {
- setButton(BUTTON_POSITIVE, text, msg);
- }
-
- /**
- * @deprecated Use {@link #setButton(int, CharSequence, Message)} with
- * {@link DialogInterface#BUTTON_NEGATIVE}.
- */
- @Deprecated
- public void setButton2(CharSequence text, Message msg) {
- setButton(BUTTON_NEGATIVE, text, msg);
- }
-
- /**
- * @deprecated Use {@link #setButton(int, CharSequence, Message)} with
- * {@link DialogInterface#BUTTON_NEUTRAL}.
- */
- @Deprecated
- public void setButton3(CharSequence text, Message msg) {
- setButton(BUTTON_NEUTRAL, text, msg);
- }
-
- /**
- * Set a listener to be invoked when button 1 of the dialog is pressed.
- *
- * @param text The text to display in button 1.
- * @param listener The {@link DialogInterface.OnClickListener} to use.
- * @deprecated Use
- * {@link #setButton(int, CharSequence, android.content.DialogInterface.OnClickListener)}
- * with {@link DialogInterface#BUTTON_POSITIVE}
- */
- @Deprecated
- public void setButton(CharSequence text, final OnClickListener listener) {
- setButton(BUTTON_POSITIVE, text, listener);
- }
-
- /**
- * Set a listener to be invoked when button 2 of the dialog is pressed.
- * @param text The text to display in button 2.
- * @param listener The {@link DialogInterface.OnClickListener} to use.
- * @deprecated Use
- * {@link #setButton(int, CharSequence, android.content.DialogInterface.OnClickListener)}
- * with {@link DialogInterface#BUTTON_NEGATIVE}
- */
- @Deprecated
- public void setButton2(CharSequence text, final OnClickListener listener) {
- setButton(BUTTON_NEGATIVE, text, listener);
- }
-
- /**
- * Set a listener to be invoked when button 3 of the dialog is pressed.
- * @param text The text to display in button 3.
- * @param listener The {@link DialogInterface.OnClickListener} to use.
- * @deprecated Use
- * {@link #setButton(int, CharSequence, android.content.DialogInterface.OnClickListener)}
- * with {@link DialogInterface#BUTTON_POSITIVE}
- */
- @Deprecated
- public void setButton3(CharSequence text, final OnClickListener listener) {
- setButton(BUTTON_NEUTRAL, text, listener);
- }
-
- /**
- * Set resId to 0 if you don't want an icon.
- * @param resId the resourceId of the drawable to use as the icon or 0
- * if you don't want an icon.
- */
- public void setIcon(int resId) {
- mAlert.setIcon(resId);
- }
-
- public void setIcon(Drawable icon) {
- mAlert.setIcon(icon);
- }
-
- public void setInverseBackgroundForced(boolean forceInverseBackground) {
- mAlert.setInverseBackgroundForced(forceInverseBackground);
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mAlert.installContent();
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (mAlert.onKeyDown(keyCode, event)) return true;
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (mAlert.onKeyUp(keyCode, event)) return true;
- return super.onKeyUp(keyCode, event);
- }
-
- public static class Builder {
- private final AlertController.AlertParams P;
-
- /**
- * Constructor using a context for this builder and the {@link AlertDialog} it creates.
- */
- public Builder(Context context) {
- P = new AlertController.AlertParams(context);
- }
-
- /**
- * Set the title using the given resource id.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setTitle(int titleId) {
- P.mTitle = P.mContext.getText(titleId);
- return this;
- }
-
- /**
- * Set the title displayed in the {@link Dialog}.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setTitle(CharSequence title) {
- P.mTitle = title;
- return this;
- }
-
- /**
- * Set the title using the custom view {@code customTitleView}. The
- * methods {@link #setTitle(int)} and {@link #setIcon(int)} should be
- * sufficient for most titles, but this is provided if the title needs
- * more customization. Using this will replace the title and icon set
- * via the other methods.
- *
- * @param customTitleView The custom view to use as the title.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setCustomTitle(View customTitleView) {
- P.mCustomTitleView = customTitleView;
- return this;
- }
-
- /**
- * Set the message to display using the given resource id.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setMessage(int messageId) {
- P.mMessage = P.mContext.getText(messageId);
- return this;
- }
-
- /**
- * Set the message to display.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setMessage(CharSequence message) {
- P.mMessage = message;
- return this;
- }
-
- /**
- * Set the resource id of the {@link Drawable} to be used in the title.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setIcon(int iconId) {
- P.mIconId = iconId;
- return this;
- }
-
- /**
- * Set the {@link Drawable} to be used in the title.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setIcon(Drawable icon) {
- P.mIcon = icon;
- return this;
- }
-
- /**
- * Set a listener to be invoked when the positive button of the dialog is pressed.
- * @param textId The resource id of the text to display in the positive button
- * @param listener The {@link DialogInterface.OnClickListener} to use.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setPositiveButton(int textId, final OnClickListener listener) {
- P.mPositiveButtonText = P.mContext.getText(textId);
- P.mPositiveButtonListener = listener;
- return this;
- }
-
- /**
- * Set a listener to be invoked when the positive button of the dialog is pressed.
- * @param text The text to display in the positive button
- * @param listener The {@link DialogInterface.OnClickListener} to use.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setPositiveButton(CharSequence text, final OnClickListener listener) {
- P.mPositiveButtonText = text;
- P.mPositiveButtonListener = listener;
- return this;
- }
-
- /**
- * Set a listener to be invoked when the negative button of the dialog is pressed.
- * @param textId The resource id of the text to display in the negative button
- * @param listener The {@link DialogInterface.OnClickListener} to use.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setNegativeButton(int textId, final OnClickListener listener) {
- P.mNegativeButtonText = P.mContext.getText(textId);
- P.mNegativeButtonListener = listener;
- return this;
- }
-
- /**
- * Set a listener to be invoked when the negative button of the dialog is pressed.
- * @param text The text to display in the negative button
- * @param listener The {@link DialogInterface.OnClickListener} to use.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setNegativeButton(CharSequence text, final OnClickListener listener) {
- P.mNegativeButtonText = text;
- P.mNegativeButtonListener = listener;
- return this;
- }
-
- /**
- * Set a listener to be invoked when the neutral button of the dialog is pressed.
- * @param textId The resource id of the text to display in the neutral button
- * @param listener The {@link DialogInterface.OnClickListener} to use.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setNeutralButton(int textId, final OnClickListener listener) {
- P.mNeutralButtonText = P.mContext.getText(textId);
- P.mNeutralButtonListener = listener;
- return this;
- }
-
- /**
- * Set a listener to be invoked when the neutral button of the dialog is pressed.
- * @param text The text to display in the neutral button
- * @param listener The {@link DialogInterface.OnClickListener} to use.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setNeutralButton(CharSequence text, final OnClickListener listener) {
- P.mNeutralButtonText = text;
- P.mNeutralButtonListener = listener;
- return this;
- }
-
- /**
- * Sets whether the dialog is cancelable or not default is true.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setCancelable(boolean cancelable) {
- P.mCancelable = cancelable;
- return this;
- }
-
- /**
- * Sets the callback that will be called if the dialog is canceled.
- * @see #setCancelable(boolean)
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setOnCancelListener(OnCancelListener onCancelListener) {
- P.mOnCancelListener = onCancelListener;
- return this;
- }
-
- /**
- * Sets the callback that will be called if a key is dispatched to the dialog.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setOnKeyListener(OnKeyListener onKeyListener) {
- P.mOnKeyListener = onKeyListener;
- return this;
- }
-
- /**
- * Set a list of items to be displayed in the dialog as the content, you will be notified of the
- * selected item via the supplied listener. This should be an array type i.e. R.array.foo
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setItems(int itemsId, final OnClickListener listener) {
- P.mItems = P.mContext.getResources().getTextArray(itemsId);
- P.mOnClickListener = listener;
- return this;
- }
-
- /**
- * Set a list of items to be displayed in the dialog as the content, you will be notified of the
- * selected item via the supplied listener.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setItems(CharSequence[] items, final OnClickListener listener) {
- P.mItems = items;
- P.mOnClickListener = listener;
- return this;
- }
-
- /**
- * Set a list of items, which are supplied by the given {@link ListAdapter}, to be
- * displayed in the dialog as the content, you will be notified of the
- * selected item via the supplied listener.
- *
- * @param adapter The {@link ListAdapter} to supply the list of items
- * @param listener The listener that will be called when an item is clicked.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setAdapter(final ListAdapter adapter, final OnClickListener listener) {
- P.mAdapter = adapter;
- P.mOnClickListener = listener;
- return this;
- }
-
- /**
- * Set a list of items, which are supplied by the given {@link Cursor}, to be
- * displayed in the dialog as the content, you will be notified of the
- * selected item via the supplied listener.
- *
- * @param cursor The {@link Cursor} to supply the list of items
- * @param listener The listener that will be called when an item is clicked.
- * @param labelColumn The column name on the cursor containing the string to display
- * in the label.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setCursor(final Cursor cursor, final OnClickListener listener,
- String labelColumn) {
- P.mCursor = cursor;
- P.mLabelColumn = labelColumn;
- P.mOnClickListener = listener;
- return this;
- }
-
- /**
- * Set a list of items to be displayed in the dialog as the content,
- * you will be notified of the selected item via the supplied listener.
- * This should be an array type, e.g. R.array.foo. The list will have
- * a check mark displayed to the right of the text for each checked
- * item. Clicking on an item in the list will not dismiss the dialog.
- * Clicking on a button will dismiss the dialog.
- *
- * @param itemsId the resource id of an array i.e. R.array.foo
- * @param checkedItems specifies which items are checked. It should be null in which case no
- * items are checked. If non null it must be exactly the same length as the array of
- * items.
- * @param listener notified when an item on the list is clicked. The dialog will not be
- * dismissed when an item is clicked. It will only be dismissed if clicked on a
- * button, if no buttons are supplied it's up to the user to dismiss the dialog.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setMultiChoiceItems(int itemsId, boolean[] checkedItems,
- final OnMultiChoiceClickListener listener) {
- P.mItems = P.mContext.getResources().getTextArray(itemsId);
- P.mOnCheckboxClickListener = listener;
- P.mCheckedItems = checkedItems;
- P.mIsMultiChoice = true;
- return this;
- }
-
- /**
- * Set a list of items to be displayed in the dialog as the content,
- * you will be notified of the selected item via the supplied listener.
- * The list will have a check mark displayed to the right of the text
- * for each checked item. Clicking on an item in the list will not
- * dismiss the dialog. Clicking on a button will dismiss the dialog.
- *
- * @param items the text of the items to be displayed in the list.
- * @param checkedItems specifies which items are checked. It should be null in which case no
- * items are checked. If non null it must be exactly the same length as the array of
- * items.
- * @param listener notified when an item on the list is clicked. The dialog will not be
- * dismissed when an item is clicked. It will only be dismissed if clicked on a
- * button, if no buttons are supplied it's up to the user to dismiss the dialog.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems,
- final OnMultiChoiceClickListener listener) {
- P.mItems = items;
- P.mOnCheckboxClickListener = listener;
- P.mCheckedItems = checkedItems;
- P.mIsMultiChoice = true;
- return this;
- }
-
- /**
- * Set a list of items to be displayed in the dialog as the content,
- * you will be notified of the selected item via the supplied listener.
- * The list will have a check mark displayed to the right of the text
- * for each checked item. Clicking on an item in the list will not
- * dismiss the dialog. Clicking on a button will dismiss the dialog.
- *
- * @param cursor the cursor used to provide the items.
- * @param isCheckedColumn specifies the column name on the cursor to use to determine
- * whether a checkbox is checked or not. It must return an integer value where 1
- * means checked and 0 means unchecked.
- * @param labelColumn The column name on the cursor containing the string to display in the
- * label.
- * @param listener notified when an item on the list is clicked. The dialog will not be
- * dismissed when an item is clicked. It will only be dismissed if clicked on a
- * button, if no buttons are supplied it's up to the user to dismiss the dialog.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setMultiChoiceItems(Cursor cursor, String isCheckedColumn, String labelColumn,
- final OnMultiChoiceClickListener listener) {
- P.mCursor = cursor;
- P.mOnCheckboxClickListener = listener;
- P.mIsCheckedColumn = isCheckedColumn;
- P.mLabelColumn = labelColumn;
- P.mIsMultiChoice = true;
- return this;
- }
-
- /**
- * Set a list of items to be displayed in the dialog as the content, you will be notified of
- * the selected item via the supplied listener. This should be an array type i.e.
- * R.array.foo The list will have a check mark displayed to the right of the text for the
- * checked item. Clicking on an item in the list will not dismiss the dialog. Clicking on a
- * button will dismiss the dialog.
- *
- * @param itemsId the resource id of an array i.e. R.array.foo
- * @param checkedItem specifies which item is checked. If -1 no items are checked.
- * @param listener notified when an item on the list is clicked. The dialog will not be
- * dismissed when an item is clicked. It will only be dismissed if clicked on a
- * button, if no buttons are supplied it's up to the user to dismiss the dialog.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setSingleChoiceItems(int itemsId, int checkedItem,
- final OnClickListener listener) {
- P.mItems = P.mContext.getResources().getTextArray(itemsId);
- P.mOnClickListener = listener;
- P.mCheckedItem = checkedItem;
- P.mIsSingleChoice = true;
- return this;
- }
-
- /**
- * Set a list of items to be displayed in the dialog as the content, you will be notified of
- * the selected item via the supplied listener. The list will have a check mark displayed to
- * the right of the text for the checked item. Clicking on an item in the list will not
- * dismiss the dialog. Clicking on a button will dismiss the dialog.
- *
- * @param cursor the cursor to retrieve the items from.
- * @param checkedItem specifies which item is checked. If -1 no items are checked.
- * @param labelColumn The column name on the cursor containing the string to display in the
- * label.
- * @param listener notified when an item on the list is clicked. The dialog will not be
- * dismissed when an item is clicked. It will only be dismissed if clicked on a
- * button, if no buttons are supplied it's up to the user to dismiss the dialog.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setSingleChoiceItems(Cursor cursor, int checkedItem, String labelColumn,
- final OnClickListener listener) {
- P.mCursor = cursor;
- P.mOnClickListener = listener;
- P.mCheckedItem = checkedItem;
- P.mLabelColumn = labelColumn;
- P.mIsSingleChoice = true;
- return this;
- }
-
- /**
- * Set a list of items to be displayed in the dialog as the content, you will be notified of
- * the selected item via the supplied listener. The list will have a check mark displayed to
- * the right of the text for the checked item. Clicking on an item in the list will not
- * dismiss the dialog. Clicking on a button will dismiss the dialog.
- *
- * @param items the items to be displayed.
- * @param checkedItem specifies which item is checked. If -1 no items are checked.
- * @param listener notified when an item on the list is clicked. The dialog will not be
- * dismissed when an item is clicked. It will only be dismissed if clicked on a
- * button, if no buttons are supplied it's up to the user to dismiss the dialog.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setSingleChoiceItems(CharSequence[] items, int checkedItem, final OnClickListener listener) {
- P.mItems = items;
- P.mOnClickListener = listener;
- P.mCheckedItem = checkedItem;
- P.mIsSingleChoice = true;
- return this;
- }
-
- /**
- * Set a list of items to be displayed in the dialog as the content, you will be notified of
- * the selected item via the supplied listener. The list will have a check mark displayed to
- * the right of the text for the checked item. Clicking on an item in the list will not
- * dismiss the dialog. Clicking on a button will dismiss the dialog.
- *
- * @param adapter The {@link ListAdapter} to supply the list of items
- * @param checkedItem specifies which item is checked. If -1 no items are checked.
- * @param listener notified when an item on the list is clicked. The dialog will not be
- * dismissed when an item is clicked. It will only be dismissed if clicked on a
- * button, if no buttons are supplied it's up to the user to dismiss the dialog.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setSingleChoiceItems(ListAdapter adapter, int checkedItem, final OnClickListener listener) {
- P.mAdapter = adapter;
- P.mOnClickListener = listener;
- P.mCheckedItem = checkedItem;
- P.mIsSingleChoice = true;
- return this;
- }
-
- /**
- * Sets a listener to be invoked when an item in the list is selected.
- *
- * @param listener The listener to be invoked.
- * @see AdapterView#setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener)
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setOnItemSelectedListener(final AdapterView.OnItemSelectedListener listener) {
- P.mOnItemSelectedListener = listener;
- return this;
- }
-
- /**
- * Set a custom view to be the contents of the Dialog. If the supplied view is an instance
- * of a {@link ListView} the light background will be used.
- *
- * @param view The view to use as the contents of the Dialog.
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setView(View view) {
- P.mView = view;
- P.mViewSpacingSpecified = false;
- return this;
- }
-
- /**
- * Set a custom view to be the contents of the Dialog, specifying the
- * spacing to appear around that view. If the supplied view is an
- * instance of a {@link ListView} the light background will be used.
- *
- * @param view The view to use as the contents of the Dialog.
- * @param viewSpacingLeft Spacing between the left edge of the view and
- * the dialog frame
- * @param viewSpacingTop Spacing between the top edge of the view and
- * the dialog frame
- * @param viewSpacingRight Spacing between the right edge of the view
- * and the dialog frame
- * @param viewSpacingBottom Spacing between the bottom edge of the view
- * and the dialog frame
- * @return This Builder object to allow for chaining of calls to set
- * methods
- *
- * @hide pending API review
- */
- public Builder setView(View view, int viewSpacingLeft, int viewSpacingTop,
- int viewSpacingRight, int viewSpacingBottom) {
- P.mView = view;
- P.mViewSpacingSpecified = true;
- P.mViewSpacingLeft = viewSpacingLeft;
- P.mViewSpacingTop = viewSpacingTop;
- P.mViewSpacingRight = viewSpacingRight;
- P.mViewSpacingBottom = viewSpacingBottom;
- return this;
- }
-
- /**
- * Sets the Dialog to use the inverse background, regardless of what the
- * contents is.
- *
- * @param useInverseBackground Whether to use the inverse background
- *
- * @return This Builder object to allow for chaining of calls to set methods
- */
- public Builder setInverseBackgroundForced(boolean useInverseBackground) {
- P.mForceInverseBackground = useInverseBackground;
- return this;
- }
-
- /**
- * Creates a {@link AlertDialog} with the arguments supplied to this builder. It does not
- * {@link Dialog#show()} the dialog. This allows the user to do any extra processing
- * before displaying the dialog. Use {@link #show()} if you don't have any other processing
- * to do and want this to be created and displayed.
- */
- public AlertDialog create() {
- final AlertDialog dialog = new AlertDialog(P.mContext);
- P.apply(dialog.mAlert);
- dialog.setCancelable(P.mCancelable);
- dialog.setOnCancelListener(P.mOnCancelListener);
- if (P.mOnKeyListener != null) {
- dialog.setOnKeyListener(P.mOnKeyListener);
- }
- return dialog;
- }
-
- /**
- * Creates a {@link AlertDialog} with the arguments supplied to this builder and
- * {@link Dialog#show()}'s the dialog.
- */
- public AlertDialog show() {
- AlertDialog dialog = create();
- dialog.show();
- return dialog;
- }
- }
-
-}
diff --git a/core/java/android/app/AliasActivity.java b/core/java/android/app/AliasActivity.java
deleted file mode 100644
index 4f91e02..0000000
--- a/core/java/android/app/AliasActivity.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.res.XmlResourceParser;
-import android.os.Bundle;
-import android.util.AttributeSet;
-import android.util.Xml;
-import com.android.internal.util.XmlUtils;
-
-import java.io.IOException;
-
-/**
- * Stub activity that launches another activity (and then finishes itself)
- * based on information in its component's manifest meta-data. This is a
- * simple way to implement an alias-like mechanism.
- *
- * To use this activity, you should include in the manifest for the associated
- * component an entry named "android.app.alias". It is a reference to an XML
- * resource describing an intent that launches the real application.
- */
-public class AliasActivity extends Activity {
- /**
- * This is the name under which you should store in your component the
- * meta-data information about the alias. It is a reference to an XML
- * resource describing an intent that launches the real application.
- * {@hide}
- */
- public final String ALIAS_META_DATA = "android.app.alias";
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- XmlResourceParser parser = null;
- try {
- ActivityInfo ai = getPackageManager().getActivityInfo(
- getComponentName(), PackageManager.GET_META_DATA);
- parser = ai.loadXmlMetaData(getPackageManager(),
- ALIAS_META_DATA);
- if (parser == null) {
- throw new RuntimeException("Alias requires a meta-data field "
- + ALIAS_META_DATA);
- }
-
- Intent intent = parseAlias(parser);
- if (intent == null) {
- throw new RuntimeException(
- "No <intent> tag found in alias description");
- }
-
- startActivity(intent);
- finish();
-
- } catch (PackageManager.NameNotFoundException e) {
- throw new RuntimeException("Error parsing alias", e);
- } catch (XmlPullParserException e) {
- throw new RuntimeException("Error parsing alias", e);
- } catch (IOException e) {
- throw new RuntimeException("Error parsing alias", e);
- } finally {
- if (parser != null) parser.close();
- }
- }
-
- private Intent parseAlias(XmlPullParser parser)
- throws XmlPullParserException, IOException {
- AttributeSet attrs = Xml.asAttributeSet(parser);
-
- Intent intent = null;
-
- int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && type != XmlPullParser.START_TAG) {
- }
-
- String nodeName = parser.getName();
- if (!"alias".equals(nodeName)) {
- throw new RuntimeException(
- "Alias meta-data must start with <alias> tag; found"
- + nodeName + " at " + parser.getPositionDescription());
- }
-
- int outerDepth = parser.getDepth();
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
-
- nodeName = parser.getName();
- if ("intent".equals(nodeName)) {
- Intent gotIntent = Intent.parseIntent(getResources(), parser, attrs);
- if (intent == null) intent = gotIntent;
- } else {
- XmlUtils.skipCurrentTag(parser);
- }
- }
-
- return intent;
- }
-
-}
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
deleted file mode 100644
index 45ce860..0000000
--- a/core/java/android/app/Application.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.ComponentCallbacks;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.res.Configuration;
-
-/**
- * Base class for those who need to maintain global application state. You can
- * provide your own implementation by specifying its name in your
- * AndroidManifest.xml's &lt;application&gt; tag, which will cause that class
- * to be instantiated for you when the process for your application/package is
- * created.
- */
-public class Application extends ContextWrapper implements ComponentCallbacks {
-
- public Application() {
- super(null);
- }
-
- /**
- * Called when the application is starting, before any other application
- * objects have been created. Implementations should be as quick as
- * possible (for example using lazy initialization of state) since the time
- * spent in this function directly impacts the performance of starting the
- * first activity, service, or receiver in a process.
- * If you override this method, be sure to call super.onCreate().
- */
- public void onCreate() {
- }
-
- /**
- * Called when the application is stopping. There are no more application
- * objects running and the process will exit. <em>Note: never depend on
- * this method being called; in many cases an unneeded application process
- * will simply be killed by the kernel without executing any application
- * code.</em>
- * If you override this method, be sure to call super.onTerminate().
- */
- public void onTerminate() {
- }
-
- public void onConfigurationChanged(Configuration newConfig) {
- }
-
- public void onLowMemory() {
- }
-
- // ------------------ Internal API ------------------
-
- /**
- * @hide
- */
- /* package */ final void attach(Context context) {
- attachBaseContext(context);
- }
-
-}
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
deleted file mode 100644
index 394b8e3..0000000
--- a/core/java/android/app/ApplicationContext.java
+++ /dev/null
@@ -1,2728 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import com.google.android.collect.Maps;
-import com.android.internal.util.XmlUtils;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.IBluetoothDevice;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.IContentProvider;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.ReceiverCallNotAllowedException;
-import android.content.ServiceConnection;
-import android.content.SharedPreferences;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.ComponentInfo;
-import android.content.pm.IPackageDataObserver;
-import android.content.pm.IPackageDeleteObserver;
-import android.content.pm.IPackageStatsObserver;
-import android.content.pm.IPackageInstallObserver;
-import android.content.pm.IPackageManager;
-import android.content.pm.InstrumentationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PermissionGroupInfo;
-import android.content.pm.PermissionInfo;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.content.res.AssetManager;
-import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteDatabase.CursorFactory;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.hardware.SensorManager;
-import android.location.ILocationManager;
-import android.location.LocationManager;
-import android.media.AudioManager;
-import android.net.ConnectivityManager;
-import android.net.IConnectivityManager;
-import android.net.Uri;
-import android.net.wifi.IWifiManager;
-import android.net.wifi.WifiManager;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.FileUtils;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.IPowerManager;
-import android.os.ParcelFileDescriptor;
-import android.os.PowerManager;
-import android.os.Process;
-import android.os.ServiceManager;
-import android.os.Vibrator;
-import android.os.FileUtils.FileStatus;
-import android.telephony.TelephonyManager;
-import android.text.ClipboardManager;
-import android.util.AndroidRuntimeException;
-import android.util.Log;
-import android.view.ContextThemeWrapper;
-import android.view.LayoutInflater;
-import android.view.WindowManagerImpl;
-import android.view.inputmethod.InputMethodManager;
-
-import com.android.internal.policy.PolicyManager;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-class ReceiverRestrictedContext extends ContextWrapper {
- ReceiverRestrictedContext(Context base) {
- super(base);
- }
-
- @Override
- public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
- return registerReceiver(receiver, filter, null, null);
- }
-
- @Override
- public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
- String broadcastPermission, Handler scheduler) {
- throw new ReceiverCallNotAllowedException(
- "IntentReceiver components are not allowed to register to receive intents");
- //ex.fillInStackTrace();
- //Log.e("IntentReceiver", ex.getMessage(), ex);
- //return mContext.registerReceiver(receiver, filter, broadcastPermission,
- // scheduler);
- }
-
- @Override
- public boolean bindService(Intent service, ServiceConnection conn, int flags) {
- throw new ReceiverCallNotAllowedException(
- "IntentReceiver components are not allowed to bind to services");
- //ex.fillInStackTrace();
- //Log.e("IntentReceiver", ex.getMessage(), ex);
- //return mContext.bindService(service, interfaceName, conn, flags);
- }
-}
-
-/**
- * Common implementation of Context API, which Activity and other application
- * classes inherit.
- */
-class ApplicationContext extends Context {
- private final static String TAG = "ApplicationContext";
- private final static boolean DEBUG_ICONS = false;
-
- private static final Object sSync = new Object();
- private static AlarmManager sAlarmManager;
- private static PowerManager sPowerManager;
- private static ConnectivityManager sConnectivityManager;
- private static WifiManager sWifiManager;
- private static LocationManager sLocationManager;
- private static boolean sIsBluetoothDeviceCached = false;
- private static BluetoothDevice sBluetoothDevice;
- private static IWallpaperService sWallpaperService;
- private static final HashMap<File, SharedPreferencesImpl> sSharedPrefs =
- new HashMap<File, SharedPreferencesImpl>();
-
- private AudioManager mAudioManager;
- /*package*/ ActivityThread.PackageInfo mPackageInfo;
- private Resources mResources;
- /*package*/ ActivityThread mMainThread;
- private Context mOuterContext;
- private IBinder mActivityToken = null;
- private ApplicationContentResolver mContentResolver;
- private int mThemeResource = 0;
- private Resources.Theme mTheme = null;
- private PackageManager mPackageManager;
- private NotificationManager mNotificationManager = null;
- private ActivityManager mActivityManager = null;
- private Context mReceiverRestrictedContext = null;
- private SearchManager mSearchManager = null;
- private SensorManager mSensorManager = null;
- private Vibrator mVibrator = null;
- private LayoutInflater mLayoutInflater = null;
- private StatusBarManager mStatusBarManager = null;
- private TelephonyManager mTelephonyManager = null;
- private ClipboardManager mClipboardManager = null;
-
- private final Object mSync = new Object();
-
- private File mDatabasesDir;
- private File mPreferencesDir;
- private File mFilesDir;
-
-
- private File mCacheDir;
-
- private Drawable mWallpaper;
- private IWallpaperServiceCallback mWallpaperCallback = null;
-
- private static long sInstanceCount = 0;
-
- private static final String[] EMPTY_FILE_LIST = {};
-
- @Override
- protected void finalize() throws Throwable {
- super.finalize();
- --sInstanceCount;
- }
-
- public static long getInstanceCount() {
- return sInstanceCount;
- }
-
- @Override
- public AssetManager getAssets() {
- return mResources.getAssets();
- }
-
- @Override
- public Resources getResources() {
- return mResources;
- }
-
- @Override
- public PackageManager getPackageManager() {
- if (mPackageManager != null) {
- return mPackageManager;
- }
-
- IPackageManager pm = ActivityThread.getPackageManager();
- if (pm != null) {
- // Doesn't matter if we make more than one instance.
- return (mPackageManager = new ApplicationPackageManager(this, pm));
- }
-
- return null;
- }
-
- @Override
- public ContentResolver getContentResolver() {
- return mContentResolver;
- }
-
- @Override
- public Looper getMainLooper() {
- return mMainThread.getLooper();
- }
-
- @Override
- public Context getApplicationContext() {
- return mMainThread.getApplication();
- }
-
- @Override
- public void setTheme(int resid) {
- mThemeResource = resid;
- }
-
- @Override
- public Resources.Theme getTheme() {
- if (mTheme == null) {
- if (mThemeResource == 0) {
- mThemeResource = com.android.internal.R.style.Theme;
- }
- mTheme = mResources.newTheme();
- mTheme.applyStyle(mThemeResource, true);
- }
- return mTheme;
- }
-
- @Override
- public ClassLoader getClassLoader() {
- return mPackageInfo != null ?
- mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
- }
-
- @Override
- public String getPackageName() {
- if (mPackageInfo != null) {
- return mPackageInfo.getPackageName();
- }
- throw new RuntimeException("Not supported in system context");
- }
-
- @Override
- public String getPackageResourcePath() {
- if (mPackageInfo != null) {
- return mPackageInfo.getResDir();
- }
- throw new RuntimeException("Not supported in system context");
- }
-
- @Override
- public String getPackageCodePath() {
- if (mPackageInfo != null) {
- return mPackageInfo.getAppDir();
- }
- throw new RuntimeException("Not supported in system context");
- }
-
- private static File makeBackupFile(File prefsFile) {
- return new File(prefsFile.getPath() + ".bak");
- }
-
- @Override
- public SharedPreferences getSharedPreferences(String name, int mode) {
- SharedPreferencesImpl sp;
- File f = makeFilename(getPreferencesDir(), name + ".xml");
- synchronized (sSharedPrefs) {
- sp = sSharedPrefs.get(f);
- if (sp != null && !sp.hasFileChanged()) {
- //Log.i(TAG, "Returning existing prefs " + name + ": " + sp);
- return sp;
- }
- }
-
- FileInputStream str = null;
- File backup = makeBackupFile(f);
- if (backup.exists()) {
- f.delete();
- backup.renameTo(f);
- }
-
- // Debugging
- if (f.exists() && !f.canRead()) {
- Log.w(TAG, "Attempt to read preferences file " + f + " without permission");
- }
-
- Map map = null;
- if (f.exists() && f.canRead()) {
- try {
- str = new FileInputStream(f);
- map = XmlUtils.readMapXml(str);
- str.close();
- } catch (org.xmlpull.v1.XmlPullParserException e) {
- Log.w(TAG, "getSharedPreferences", e);
- } catch (FileNotFoundException e) {
- Log.w(TAG, "getSharedPreferences", e);
- } catch (IOException e) {
- Log.w(TAG, "getSharedPreferences", e);
- }
- }
-
- synchronized (sSharedPrefs) {
- if (sp != null) {
- //Log.i(TAG, "Updating existing prefs " + name + " " + sp + ": " + map);
- sp.replace(map);
- } else {
- sp = sSharedPrefs.get(f);
- if (sp == null) {
- sp = new SharedPreferencesImpl(f, mode, map);
- sSharedPrefs.put(f, sp);
- }
- }
- return sp;
- }
- }
-
- private File getPreferencesDir() {
- synchronized (mSync) {
- if (mPreferencesDir == null) {
- mPreferencesDir = new File(getDataDirFile(), "shared_prefs");
- }
- return mPreferencesDir;
- }
- }
-
- @Override
- public FileInputStream openFileInput(String name)
- throws FileNotFoundException {
- File f = makeFilename(getFilesDir(), name);
- return new FileInputStream(f);
- }
-
- @Override
- public FileOutputStream openFileOutput(String name, int mode)
- throws FileNotFoundException {
- final boolean append = (mode&MODE_APPEND) != 0;
- File f = makeFilename(getFilesDir(), name);
- try {
- FileOutputStream fos = new FileOutputStream(f, append);
- setFilePermissionsFromMode(f.getPath(), mode, 0);
- return fos;
- } catch (FileNotFoundException e) {
- }
-
- File parent = f.getParentFile();
- parent.mkdir();
- FileUtils.setPermissions(
- parent.getPath(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
- -1, -1);
- FileOutputStream fos = new FileOutputStream(f, append);
- setFilePermissionsFromMode(f.getPath(), mode, 0);
- return fos;
- }
-
- @Override
- public boolean deleteFile(String name) {
- File f = makeFilename(getFilesDir(), name);
- return f.delete();
- }
-
- @Override
- public File getFilesDir() {
- synchronized (mSync) {
- if (mFilesDir == null) {
- mFilesDir = new File(getDataDirFile(), "files");
- }
- if (!mFilesDir.exists()) {
- if(!mFilesDir.mkdirs()) {
- Log.w(TAG, "Unable to create files directory");
- return null;
- }
- FileUtils.setPermissions(
- mFilesDir.getPath(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
- -1, -1);
- }
- return mFilesDir;
- }
- }
-
- @Override
- public File getCacheDir() {
- synchronized (mSync) {
- if (mCacheDir == null) {
- mCacheDir = new File(getDataDirFile(), "cache");
- }
- if (!mCacheDir.exists()) {
- if(!mCacheDir.mkdirs()) {
- Log.w(TAG, "Unable to create cache directory");
- return null;
- }
- FileUtils.setPermissions(
- mCacheDir.getPath(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
- -1, -1);
- }
- }
- return mCacheDir;
- }
-
-
- @Override
- public File getFileStreamPath(String name) {
- return makeFilename(getFilesDir(), name);
- }
-
- @Override
- public String[] fileList() {
- final String[] list = getFilesDir().list();
- return (list != null) ? list : EMPTY_FILE_LIST;
- }
-
- @Override
- public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
- File dir = getDatabasesDir();
- if (!dir.isDirectory() && dir.mkdir()) {
- FileUtils.setPermissions(dir.getPath(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
- -1, -1);
- }
-
- File f = makeFilename(dir, name);
- SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
- setFilePermissionsFromMode(f.getPath(), mode, 0);
- return db;
- }
-
- @Override
- public boolean deleteDatabase(String name) {
- try {
- File f = makeFilename(getDatabasesDir(), name);
- return f.delete();
- } catch (Exception e) {
- }
- return false;
- }
-
- @Override
- public File getDatabasePath(String name) {
- return makeFilename(getDatabasesDir(), name);
- }
-
- @Override
- public String[] databaseList() {
- final String[] list = getDatabasesDir().list();
- return (list != null) ? list : EMPTY_FILE_LIST;
- }
-
-
- private File getDatabasesDir() {
- synchronized (mSync) {
- if (mDatabasesDir == null) {
- mDatabasesDir = new File(getDataDirFile(), "databases");
- }
- if (mDatabasesDir.getPath().equals("databases")) {
- mDatabasesDir = new File("/data/system");
- }
- return mDatabasesDir;
- }
- }
-
- @Override
- public Drawable getWallpaper() {
- Drawable dr = peekWallpaper();
- return dr != null ? dr : getResources().getDrawable(
- com.android.internal.R.drawable.default_wallpaper);
- }
-
- @Override
- public synchronized Drawable peekWallpaper() {
- if (mWallpaper != null) {
- return mWallpaper;
- }
- mWallpaperCallback = new WallpaperCallback(this);
- mWallpaper = getCurrentWallpaperLocked();
- return mWallpaper;
- }
-
- private Drawable getCurrentWallpaperLocked() {
- try {
- ParcelFileDescriptor fd = getWallpaperService().getWallpaper(mWallpaperCallback);
- if (fd != null) {
- Bitmap bm = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor());
- if (bm != null) {
- return new BitmapDrawable(bm);
- }
- }
- } catch (RemoteException e) {
- }
- return null;
- }
-
- @Override
- public int getWallpaperDesiredMinimumWidth() {
- try {
- return getWallpaperService().getWidthHint();
- } catch (RemoteException e) {
- // Shouldn't happen!
- return 0;
- }
- }
-
- @Override
- public int getWallpaperDesiredMinimumHeight() {
- try {
- return getWallpaperService().getHeightHint();
- } catch (RemoteException e) {
- // Shouldn't happen!
- return 0;
- }
- }
-
- @Override
- public void setWallpaper(Bitmap bitmap) throws IOException {
- try {
- ParcelFileDescriptor fd = getWallpaperService().setWallpaper();
- if (fd == null) {
- return;
- }
- FileOutputStream fos = null;
- try {
- fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
- bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
- } finally {
- if (fos != null) {
- fos.close();
- }
- }
- } catch (RemoteException e) {
- }
- }
-
- @Override
- public void setWallpaper(InputStream data) throws IOException {
- try {
- ParcelFileDescriptor fd = getWallpaperService().setWallpaper();
- if (fd == null) {
- return;
- }
- FileOutputStream fos = null;
- try {
- fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
- setWallpaper(data, fos);
- } finally {
- if (fos != null) {
- fos.close();
- }
- }
- } catch (RemoteException e) {
- }
- }
-
- private void setWallpaper(InputStream data, FileOutputStream fos)
- throws IOException {
- byte[] buffer = new byte[32768];
- int amt;
- while ((amt=data.read(buffer)) > 0) {
- fos.write(buffer, 0, amt);
- }
- }
-
- @Override
- public void clearWallpaper() throws IOException {
- try {
- /* Set the wallpaper to the default values */
- ParcelFileDescriptor fd = getWallpaperService().setWallpaper();
- if (fd != null) {
- FileOutputStream fos = null;
- try {
- fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
- setWallpaper(getResources().openRawResource(
- com.android.internal.R.drawable.default_wallpaper),
- fos);
- } finally {
- if (fos != null) {
- fos.close();
- }
- }
- }
- } catch (RemoteException e) {
- }
- }
-
- @Override
- public void startActivity(Intent intent) {
- if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
- throw new AndroidRuntimeException(
- "Calling startActivity() from outside of an Activity "
- + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
- + " Is this really what you want?");
- }
- mMainThread.getInstrumentation().execStartActivity(
- getOuterContext(), mMainThread.getApplicationThread(), null, null, intent, -1);
- }
-
- @Override
- public void sendBroadcast(Intent intent) {
- String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
- try {
- ActivityManagerNative.getDefault().broadcastIntent(
- mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, null, false, false);
- } catch (RemoteException e) {
- }
- }
-
- @Override
- public void sendBroadcast(Intent intent, String receiverPermission) {
- String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
- try {
- ActivityManagerNative.getDefault().broadcastIntent(
- mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermission, false, false);
- } catch (RemoteException e) {
- }
- }
-
- @Override
- public void sendOrderedBroadcast(Intent intent,
- String receiverPermission) {
- String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
- try {
- ActivityManagerNative.getDefault().broadcastIntent(
- mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermission, true, false);
- } catch (RemoteException e) {
- }
- }
-
- @Override
- public void sendOrderedBroadcast(Intent intent,
- String receiverPermission, BroadcastReceiver resultReceiver,
- Handler scheduler, int initialCode, String initialData,
- Bundle initialExtras) {
- IIntentReceiver rd = null;
- if (resultReceiver != null) {
- if (mPackageInfo != null) {
- if (scheduler == null) {
- scheduler = mMainThread.getHandler();
- }
- rd = mPackageInfo.getReceiverDispatcher(
- resultReceiver, getOuterContext(), scheduler,
- mMainThread.getInstrumentation(), false);
- } else {
- if (scheduler == null) {
- scheduler = mMainThread.getHandler();
- }
- rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
- resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
- }
- }
- String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
- try {
- ActivityManagerNative.getDefault().broadcastIntent(
- mMainThread.getApplicationThread(), intent, resolvedType, rd,
- initialCode, initialData, initialExtras, receiverPermission,
- true, false);
- } catch (RemoteException e) {
- }
- }
-
- @Override
- public void sendStickyBroadcast(Intent intent) {
- String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
- try {
- ActivityManagerNative.getDefault().broadcastIntent(
- mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, null, false, true);
- } catch (RemoteException e) {
- }
- }
-
- @Override
- public void removeStickyBroadcast(Intent intent) {
- String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
- if (resolvedType != null) {
- intent = new Intent(intent);
- intent.setDataAndType(intent.getData(), resolvedType);
- }
- try {
- ActivityManagerNative.getDefault().unbroadcastIntent(
- mMainThread.getApplicationThread(), intent);
- } catch (RemoteException e) {
- }
- }
-
- @Override
- public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
- return registerReceiver(receiver, filter, null, null);
- }
-
- @Override
- public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
- String broadcastPermission, Handler scheduler) {
- return registerReceiverInternal(receiver, filter, broadcastPermission,
- scheduler, getOuterContext());
- }
-
- private Intent registerReceiverInternal(BroadcastReceiver receiver,
- IntentFilter filter, String broadcastPermission,
- Handler scheduler, Context context) {
- IIntentReceiver rd = null;
- if (receiver != null) {
- if (mPackageInfo != null && context != null) {
- if (scheduler == null) {
- scheduler = mMainThread.getHandler();
- }
- rd = mPackageInfo.getReceiverDispatcher(
- receiver, context, scheduler,
- mMainThread.getInstrumentation(), true);
- } else {
- if (scheduler == null) {
- scheduler = mMainThread.getHandler();
- }
- rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
- receiver, context, scheduler, null, false).getIIntentReceiver();
- }
- }
- try {
- return ActivityManagerNative.getDefault().registerReceiver(
- mMainThread.getApplicationThread(),
- rd, filter, broadcastPermission);
- } catch (RemoteException e) {
- return null;
- }
- }
-
- @Override
- public void unregisterReceiver(BroadcastReceiver receiver) {
- if (mPackageInfo != null) {
- IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
- getOuterContext(), receiver);
- try {
- ActivityManagerNative.getDefault().unregisterReceiver(rd);
- } catch (RemoteException e) {
- }
- } else {
- throw new RuntimeException("Not supported in system context");
- }
- }
-
- @Override
- public ComponentName startService(Intent service) {
- try {
- ComponentName cn = ActivityManagerNative.getDefault().startService(
- mMainThread.getApplicationThread(), service,
- service.resolveTypeIfNeeded(getContentResolver()));
- if (cn != null && cn.getPackageName().equals("!")) {
- throw new SecurityException(
- "Not allowed to start service " + service
- + " without permission " + cn.getClassName());
- }
- return cn;
- } catch (RemoteException e) {
- return null;
- }
- }
-
- @Override
- public boolean stopService(Intent service) {
- try {
- int res = ActivityManagerNative.getDefault().stopService(
- mMainThread.getApplicationThread(), service,
- service.resolveTypeIfNeeded(getContentResolver()));
- if (res < 0) {
- throw new SecurityException(
- "Not allowed to stop service " + service);
- }
- return res != 0;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- @Override
- public boolean bindService(Intent service, ServiceConnection conn,
- int flags) {
- IServiceConnection sd;
- if (mPackageInfo != null) {
- sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
- mMainThread.getHandler(), flags);
- } else {
- throw new RuntimeException("Not supported in system context");
- }
- try {
- int res = ActivityManagerNative.getDefault().bindService(
- mMainThread.getApplicationThread(), getActivityToken(),
- service, service.resolveTypeIfNeeded(getContentResolver()),
- sd, flags);
- if (res < 0) {
- throw new SecurityException(
- "Not allowed to bind to service " + service);
- }
- return res != 0;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- @Override
- public void unbindService(ServiceConnection conn) {
- if (mPackageInfo != null) {
- IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
- getOuterContext(), conn);
- try {
- ActivityManagerNative.getDefault().unbindService(sd);
- } catch (RemoteException e) {
- }
- } else {
- throw new RuntimeException("Not supported in system context");
- }
- }
-
- @Override
- public boolean startInstrumentation(ComponentName className,
- String profileFile, Bundle arguments) {
- try {
- return ActivityManagerNative.getDefault().startInstrumentation(
- className, profileFile, 0, arguments, null);
- } catch (RemoteException e) {
- // System has crashed, nothing we can do.
- }
- return false;
- }
-
- @Override
- public Object getSystemService(String name) {
- if (WINDOW_SERVICE.equals(name)) {
- return WindowManagerImpl.getDefault();
- } else if (LAYOUT_INFLATER_SERVICE.equals(name)) {
- synchronized (mSync) {
- LayoutInflater inflater = mLayoutInflater;
- if (inflater != null) {
- return inflater;
- }
- mLayoutInflater = inflater =
- PolicyManager.makeNewLayoutInflater(getOuterContext());
- return inflater;
- }
- } else if (ACTIVITY_SERVICE.equals(name)) {
- return getActivityManager();
- } else if (ALARM_SERVICE.equals(name)) {
- return getAlarmManager();
- } else if (POWER_SERVICE.equals(name)) {
- return getPowerManager();
- } else if (CONNECTIVITY_SERVICE.equals(name)) {
- return getConnectivityManager();
- } else if (WIFI_SERVICE.equals(name)) {
- return getWifiManager();
- } else if (NOTIFICATION_SERVICE.equals(name)) {
- return getNotificationManager();
- } else if (KEYGUARD_SERVICE.equals(name)) {
- return new KeyguardManager();
- } else if (LOCATION_SERVICE.equals(name)) {
- return getLocationManager();
- } else if (SEARCH_SERVICE.equals(name)) {
- return getSearchManager();
- } else if ( SENSOR_SERVICE.equals(name)) {
- return getSensorManager();
- } else if (BLUETOOTH_SERVICE.equals(name)) {
- return getBluetoothDevice();
- } else if (VIBRATOR_SERVICE.equals(name)) {
- return getVibrator();
- } else if (STATUS_BAR_SERVICE.equals(name)) {
- synchronized (mSync) {
- if (mStatusBarManager == null) {
- mStatusBarManager = new StatusBarManager(getOuterContext());
- }
- return mStatusBarManager;
- }
- } else if (AUDIO_SERVICE.equals(name)) {
- return getAudioManager();
- } else if (TELEPHONY_SERVICE.equals(name)) {
- return getTelephonyManager();
- } else if (CLIPBOARD_SERVICE.equals(name)) {
- return getClipboardManager();
- } else if (INPUT_METHOD_SERVICE.equals(name)) {
- return InputMethodManager.getInstance(this);
- }
-
- return null;
- }
-
- private ActivityManager getActivityManager() {
- synchronized (mSync) {
- if (mActivityManager == null) {
- mActivityManager = new ActivityManager(getOuterContext(),
- mMainThread.getHandler());
- }
- }
- return mActivityManager;
- }
-
- private AlarmManager getAlarmManager() {
- synchronized (sSync) {
- if (sAlarmManager == null) {
- IBinder b = ServiceManager.getService(ALARM_SERVICE);
- IAlarmManager service = IAlarmManager.Stub.asInterface(b);
- sAlarmManager = new AlarmManager(service);
- }
- }
- return sAlarmManager;
- }
-
- private PowerManager getPowerManager() {
- synchronized (sSync) {
- if (sPowerManager == null) {
- IBinder b = ServiceManager.getService(POWER_SERVICE);
- IPowerManager service = IPowerManager.Stub.asInterface(b);
- sPowerManager = new PowerManager(service, mMainThread.getHandler());
- }
- }
- return sPowerManager;
- }
-
- private ConnectivityManager getConnectivityManager()
- {
- synchronized (sSync) {
- if (sConnectivityManager == null) {
- IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE);
- IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
- sConnectivityManager = new ConnectivityManager(service);
- }
- }
- return sConnectivityManager;
- }
-
- private WifiManager getWifiManager()
- {
- synchronized (sSync) {
- if (sWifiManager == null) {
- IBinder b = ServiceManager.getService(WIFI_SERVICE);
- IWifiManager service = IWifiManager.Stub.asInterface(b);
- sWifiManager = new WifiManager(service, mMainThread.getHandler());
- }
- }
- return sWifiManager;
- }
-
- private NotificationManager getNotificationManager()
- {
- synchronized (mSync) {
- if (mNotificationManager == null) {
- mNotificationManager = new NotificationManager(
- new ContextThemeWrapper(getOuterContext(), com.android.internal.R.style.Theme_Dialog),
- mMainThread.getHandler());
- }
- }
- return mNotificationManager;
- }
-
- private TelephonyManager getTelephonyManager() {
- synchronized (mSync) {
- if (mTelephonyManager == null) {
- mTelephonyManager = new TelephonyManager(getOuterContext());
- }
- }
- return mTelephonyManager;
- }
-
- private ClipboardManager getClipboardManager() {
- synchronized (mSync) {
- if (mClipboardManager == null) {
- mClipboardManager = new ClipboardManager(getOuterContext(),
- mMainThread.getHandler());
- }
- }
- return mClipboardManager;
- }
-
- private LocationManager getLocationManager() {
- synchronized (sSync) {
- if (sLocationManager == null) {
- IBinder b = ServiceManager.getService(LOCATION_SERVICE);
- ILocationManager service = ILocationManager.Stub.asInterface(b);
- sLocationManager = new LocationManager(service);
- }
- }
- return sLocationManager;
- }
-
- private SearchManager getSearchManager() {
- // This is only useable in Activity Contexts
- if (getActivityToken() == null) {
- throw new AndroidRuntimeException(
- "Acquiring SearchManager objects only valid in Activity Contexts.");
- }
- synchronized (mSync) {
- if (mSearchManager == null) {
- mSearchManager = new SearchManager(getOuterContext(), mMainThread.getHandler());
- }
- }
- return mSearchManager;
- }
-
- private BluetoothDevice getBluetoothDevice() {
- if (sIsBluetoothDeviceCached) {
- return sBluetoothDevice;
- }
- synchronized (sSync) {
- IBinder b = ServiceManager.getService(BLUETOOTH_SERVICE);
- if (b == null) {
- sBluetoothDevice = null;
- } else {
- IBluetoothDevice service = IBluetoothDevice.Stub.asInterface(b);
- sBluetoothDevice = new BluetoothDevice(service);
- }
- sIsBluetoothDeviceCached = true;
- }
- return sBluetoothDevice;
- }
-
- private SensorManager getSensorManager() {
- synchronized (mSync) {
- if (mSensorManager == null) {
- mSensorManager = new SensorManager(mMainThread.getHandler().getLooper());
- }
- }
- return mSensorManager;
- }
-
- private Vibrator getVibrator() {
- synchronized (mSync) {
- if (mVibrator == null) {
- mVibrator = new Vibrator();
- }
- }
- return mVibrator;
- }
-
- private IWallpaperService getWallpaperService() {
- synchronized (sSync) {
- if (sWallpaperService == null) {
- IBinder b = ServiceManager.getService(WALLPAPER_SERVICE);
- sWallpaperService = IWallpaperService.Stub.asInterface(b);
- }
- }
- return sWallpaperService;
- }
-
- private AudioManager getAudioManager()
- {
- if (mAudioManager == null) {
- mAudioManager = new AudioManager(this);
- }
- return mAudioManager;
- }
-
- @Override
- public int checkPermission(String permission, int pid, int uid) {
- if (permission == null) {
- throw new IllegalArgumentException("permission is null");
- }
-
- if (!Process.supportsProcesses()) {
- return PackageManager.PERMISSION_GRANTED;
- }
- try {
- return ActivityManagerNative.getDefault().checkPermission(
- permission, pid, uid);
- } catch (RemoteException e) {
- return PackageManager.PERMISSION_DENIED;
- }
- }
-
- @Override
- public int checkCallingPermission(String permission) {
- if (permission == null) {
- throw new IllegalArgumentException("permission is null");
- }
-
- if (!Process.supportsProcesses()) {
- return PackageManager.PERMISSION_GRANTED;
- }
- int pid = Binder.getCallingPid();
- if (pid != Process.myPid()) {
- return checkPermission(permission, pid,
- Binder.getCallingUid());
- }
- return PackageManager.PERMISSION_DENIED;
- }
-
- @Override
- public int checkCallingOrSelfPermission(String permission) {
- if (permission == null) {
- throw new IllegalArgumentException("permission is null");
- }
-
- return checkPermission(permission, Binder.getCallingPid(),
- Binder.getCallingUid());
- }
-
- private void enforce(
- String permission, int resultOfCheck,
- boolean selfToo, int uid, String message) {
- if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException(
- (message != null ? (message + ": ") : "") +
- (selfToo
- ? "Neither user " + uid + " nor current process has "
- : "User " + uid + " does not have ") +
- permission +
- ".");
- }
- }
-
- public void enforcePermission(
- String permission, int pid, int uid, String message) {
- enforce(permission,
- checkPermission(permission, pid, uid),
- false,
- uid,
- message);
- }
-
- public void enforceCallingPermission(String permission, String message) {
- enforce(permission,
- checkCallingPermission(permission),
- false,
- Binder.getCallingUid(),
- message);
- }
-
- public void enforceCallingOrSelfPermission(
- String permission, String message) {
- enforce(permission,
- checkCallingOrSelfPermission(permission),
- true,
- Binder.getCallingUid(),
- message);
- }
-
- @Override
- public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
- try {
- ActivityManagerNative.getDefault().grantUriPermission(
- mMainThread.getApplicationThread(), toPackage, uri,
- modeFlags);
- } catch (RemoteException e) {
- }
- }
-
- @Override
- public void revokeUriPermission(Uri uri, int modeFlags) {
- try {
- ActivityManagerNative.getDefault().revokeUriPermission(
- mMainThread.getApplicationThread(), uri,
- modeFlags);
- } catch (RemoteException e) {
- }
- }
-
- @Override
- public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
- if (!Process.supportsProcesses()) {
- return PackageManager.PERMISSION_GRANTED;
- }
- try {
- return ActivityManagerNative.getDefault().checkUriPermission(
- uri, pid, uid, modeFlags);
- } catch (RemoteException e) {
- return PackageManager.PERMISSION_DENIED;
- }
- }
-
- @Override
- public int checkCallingUriPermission(Uri uri, int modeFlags) {
- if (!Process.supportsProcesses()) {
- return PackageManager.PERMISSION_GRANTED;
- }
- int pid = Binder.getCallingPid();
- if (pid != Process.myPid()) {
- return checkUriPermission(uri, pid,
- Binder.getCallingUid(), modeFlags);
- }
- return PackageManager.PERMISSION_DENIED;
- }
-
- @Override
- public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
- return checkUriPermission(uri, Binder.getCallingPid(),
- Binder.getCallingUid(), modeFlags);
- }
-
- @Override
- public int checkUriPermission(Uri uri, String readPermission,
- String writePermission, int pid, int uid, int modeFlags) {
- if (false) {
- Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission="
- + readPermission + " writePermission=" + writePermission
- + " pid=" + pid + " uid=" + uid + " mode" + modeFlags);
- }
- if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
- if (readPermission == null
- || checkPermission(readPermission, pid, uid)
- == PackageManager.PERMISSION_GRANTED) {
- return PackageManager.PERMISSION_GRANTED;
- }
- }
- if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
- if (writePermission == null
- || checkPermission(writePermission, pid, uid)
- == PackageManager.PERMISSION_GRANTED) {
- return PackageManager.PERMISSION_GRANTED;
- }
- }
- return uri != null ? checkUriPermission(uri, pid, uid, modeFlags)
- : PackageManager.PERMISSION_DENIED;
- }
-
- private String uriModeFlagToString(int uriModeFlags) {
- switch (uriModeFlags) {
- case Intent.FLAG_GRANT_READ_URI_PERMISSION |
- Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
- return "read and write";
- case Intent.FLAG_GRANT_READ_URI_PERMISSION:
- return "read";
- case Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
- return "write";
- }
- throw new IllegalArgumentException(
- "Unknown permission mode flags: " + uriModeFlags);
- }
-
- private void enforceForUri(
- int modeFlags, int resultOfCheck, boolean selfToo,
- int uid, Uri uri, String message) {
- if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException(
- (message != null ? (message + ": ") : "") +
- (selfToo
- ? "Neither user " + uid + " nor current process has "
- : "User " + uid + " does not have ") +
- uriModeFlagToString(modeFlags) +
- " permission on " +
- uri +
- ".");
- }
- }
-
- public void enforceUriPermission(
- Uri uri, int pid, int uid, int modeFlags, String message) {
- enforceForUri(
- modeFlags, checkUriPermission(uri, pid, uid, modeFlags),
- false, uid, uri, message);
- }
-
- public void enforceCallingUriPermission(
- Uri uri, int modeFlags, String message) {
- enforceForUri(
- modeFlags, checkCallingUriPermission(uri, modeFlags),
- false, Binder.getCallingUid(), uri, message);
- }
-
- public void enforceCallingOrSelfUriPermission(
- Uri uri, int modeFlags, String message) {
- enforceForUri(
- modeFlags,
- checkCallingOrSelfUriPermission(uri, modeFlags), true,
- Binder.getCallingUid(), uri, message);
- }
-
- public void enforceUriPermission(
- Uri uri, String readPermission, String writePermission,
- int pid, int uid, int modeFlags, String message) {
- enforceForUri(modeFlags,
- checkUriPermission(
- uri, readPermission, writePermission, pid, uid,
- modeFlags),
- false,
- uid,
- uri,
- message);
- }
-
- @Override
- public Context createPackageContext(String packageName, int flags)
- throws PackageManager.NameNotFoundException {
- if (packageName.equals("system") || packageName.equals("android")) {
- return new ApplicationContext(mMainThread.getSystemContext());
- }
-
- ActivityThread.PackageInfo pi =
- mMainThread.getPackageInfo(packageName, flags);
- if (pi != null) {
- ApplicationContext c = new ApplicationContext();
- c.init(pi, null, mMainThread);
- if (c.mResources != null) {
- return c;
- }
- }
-
- // Should be a better exception.
- throw new PackageManager.NameNotFoundException(
- "Application package " + packageName + " not found");
- }
-
- private File getDataDirFile() {
- if (mPackageInfo != null) {
- return mPackageInfo.getDataDirFile();
- }
- throw new RuntimeException("Not supported in system context");
- }
-
- @Override
- public File getDir(String name, int mode) {
- name = "app_" + name;
- File file = makeFilename(getDataDirFile(), name);
- if (!file.exists()) {
- file.mkdir();
- setFilePermissionsFromMode(file.getPath(), mode,
- FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH);
- }
- return file;
- }
-
- static ApplicationContext createSystemContext(ActivityThread mainThread) {
- ApplicationContext context = new ApplicationContext();
- context.init(Resources.getSystem(), mainThread);
- return context;
- }
-
- ApplicationContext() {
- ++sInstanceCount;
- mOuterContext = this;
- }
-
- /**
- * Create a new ApplicationContext from an existing one. The new one
- * works and operates the same as the one it is copying.
- *
- * @param context Existing application context.
- */
- public ApplicationContext(ApplicationContext context) {
- ++sInstanceCount;
- mPackageInfo = context.mPackageInfo;
- mResources = context.mResources;
- mMainThread = context.mMainThread;
- mContentResolver = context.mContentResolver;
- mOuterContext = this;
- }
-
- final void init(ActivityThread.PackageInfo packageInfo,
- IBinder activityToken, ActivityThread mainThread) {
- mPackageInfo = packageInfo;
- mResources = mPackageInfo.getResources(mainThread);
- mMainThread = mainThread;
- mContentResolver = new ApplicationContentResolver(this, mainThread);
-
- setActivityToken(activityToken);
- }
-
- final void init(Resources resources, ActivityThread mainThread) {
- mPackageInfo = null;
- mResources = resources;
- mMainThread = mainThread;
- mContentResolver = new ApplicationContentResolver(this, mainThread);
- }
-
- final void scheduleFinalCleanup(String who, String what) {
- mMainThread.scheduleContextCleanup(this, who, what);
- }
-
- final void performFinalCleanup(String who, String what) {
- //Log.i(TAG, "Cleanup up context: " + this);
- mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
- }
-
- final Context getReceiverRestrictedContext() {
- if (mReceiverRestrictedContext != null) {
- return mReceiverRestrictedContext;
- }
- return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
- }
-
- final void setActivityToken(IBinder token) {
- mActivityToken = token;
- }
-
- final void setOuterContext(Context context) {
- mOuterContext = context;
- }
-
- final Context getOuterContext() {
- return mOuterContext;
- }
-
- final IBinder getActivityToken() {
- return mActivityToken;
- }
-
- private static void setFilePermissionsFromMode(String name, int mode,
- int extraPermissions) {
- int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR
- |FileUtils.S_IRGRP|FileUtils.S_IWGRP
- |extraPermissions;
- if ((mode&MODE_WORLD_READABLE) != 0) {
- perms |= FileUtils.S_IROTH;
- }
- if ((mode&MODE_WORLD_WRITEABLE) != 0) {
- perms |= FileUtils.S_IWOTH;
- }
- if (false) {
- Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode)
- + ", perms=0x" + Integer.toHexString(perms));
- }
- FileUtils.setPermissions(name, perms, -1, -1);
- }
-
- private File makeFilename(File base, String name) {
- if (name.indexOf(File.separatorChar) < 0) {
- return new File(base, name);
- }
- throw new IllegalArgumentException(
- "File " + name + " contains a path separator");
- }
-
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
-
- private static final class ApplicationContentResolver extends ContentResolver {
- public ApplicationContentResolver(Context context,
- ActivityThread mainThread)
- {
- super(context);
- mMainThread = mainThread;
- }
-
- @Override
- protected IContentProvider acquireProvider(Context context, String name)
- {
- return mMainThread.acquireProvider(context, name);
- }
-
- @Override
- public boolean releaseProvider(IContentProvider provider)
- {
- return mMainThread.releaseProvider(provider);
- }
-
- private final ActivityThread mMainThread;
- }
-
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
-
- /*package*/
- static final class ApplicationPackageManager extends PackageManager {
- @Override
- public PackageInfo getPackageInfo(String packageName, int flags)
- throws NameNotFoundException {
- try {
- PackageInfo pi = mPM.getPackageInfo(packageName, flags);
- if (pi != null) {
- return pi;
- }
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
-
- throw new NameNotFoundException(packageName);
- }
-
- @Override
- public int[] getPackageGids(String packageName)
- throws NameNotFoundException {
- try {
- int[] gids = mPM.getPackageGids(packageName);
- if (gids == null || gids.length > 0) {
- return gids;
- }
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
-
- throw new NameNotFoundException(packageName);
- }
-
- @Override
- public PermissionInfo getPermissionInfo(String name, int flags)
- throws NameNotFoundException {
- try {
- PermissionInfo pi = mPM.getPermissionInfo(name, flags);
- if (pi != null) {
- return pi;
- }
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
-
- throw new NameNotFoundException(name);
- }
-
- @Override
- public List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
- throws NameNotFoundException {
- try {
- List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags);
- if (pi != null) {
- return pi;
- }
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
-
- throw new NameNotFoundException(group);
- }
-
- @Override
- public PermissionGroupInfo getPermissionGroupInfo(String name,
- int flags) throws NameNotFoundException {
- try {
- PermissionGroupInfo pgi = mPM.getPermissionGroupInfo(name, flags);
- if (pgi != null) {
- return pgi;
- }
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
-
- throw new NameNotFoundException(name);
- }
-
- @Override
- public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
- try {
- return mPM.getAllPermissionGroups(flags);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public ApplicationInfo getApplicationInfo(String packageName, int flags)
- throws NameNotFoundException {
- try {
- ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags);
- if (ai != null) {
- return ai;
- }
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
-
- throw new NameNotFoundException(packageName);
- }
-
- @Override
- public ActivityInfo getActivityInfo(ComponentName className, int flags)
- throws NameNotFoundException {
- try {
- ActivityInfo ai = mPM.getActivityInfo(className, flags);
- if (ai != null) {
- return ai;
- }
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
-
- throw new NameNotFoundException(className.toString());
- }
-
- @Override
- public ActivityInfo getReceiverInfo(ComponentName className, int flags)
- throws NameNotFoundException {
- try {
- ActivityInfo ai = mPM.getReceiverInfo(className, flags);
- if (ai != null) {
- return ai;
- }
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
-
- throw new NameNotFoundException(className.toString());
- }
-
- @Override
- public ServiceInfo getServiceInfo(ComponentName className, int flags)
- throws NameNotFoundException {
- try {
- ServiceInfo si = mPM.getServiceInfo(className, flags);
- if (si != null) {
- return si;
- }
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
-
- throw new NameNotFoundException(className.toString());
- }
-
- @Override
- public String[] getSystemSharedLibraryNames() {
- try {
- return mPM.getSystemSharedLibraryNames();
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public int checkPermission(String permName, String pkgName) {
- try {
- return mPM.checkPermission(permName, pkgName);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public boolean addPermission(PermissionInfo info) {
- try {
- return mPM.addPermission(info);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public void removePermission(String name) {
- try {
- mPM.removePermission(name);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public int checkSignatures(String pkg1, String pkg2) {
- try {
- return mPM.checkSignatures(pkg1, pkg2);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public String[] getPackagesForUid(int uid) {
- try {
- return mPM.getPackagesForUid(uid);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public String getNameForUid(int uid) {
- try {
- return mPM.getNameForUid(uid);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public int getUidForSharedUser(String sharedUserName)
- throws NameNotFoundException {
- try {
- int uid = mPM.getUidForSharedUser(sharedUserName);
- if(uid != -1) {
- return uid;
- }
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
- }
-
- @Override
- public List<PackageInfo> getInstalledPackages(int flags) {
- try {
- return mPM.getInstalledPackages(flags);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public List<ApplicationInfo> getInstalledApplications(int flags) {
- try {
- return mPM.getInstalledApplications(flags);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public ResolveInfo resolveActivity(Intent intent, int flags) {
- try {
- return mPM.resolveIntent(
- intent,
- intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- flags);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public List<ResolveInfo> queryIntentActivities(Intent intent,
- int flags) {
- try {
- return mPM.queryIntentActivities(
- intent,
- intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- flags);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public List<ResolveInfo> queryIntentActivityOptions(
- ComponentName caller, Intent[] specifics, Intent intent,
- int flags) {
- final ContentResolver resolver = mContext.getContentResolver();
-
- String[] specificTypes = null;
- if (specifics != null) {
- final int N = specifics.length;
- for (int i=0; i<N; i++) {
- Intent sp = specifics[i];
- if (sp != null) {
- String t = sp.resolveTypeIfNeeded(resolver);
- if (t != null) {
- if (specificTypes == null) {
- specificTypes = new String[N];
- }
- specificTypes[i] = t;
- }
- }
- }
- }
-
- try {
- return mPM.queryIntentActivityOptions(caller, specifics,
- specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
- flags);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
- try {
- return mPM.queryIntentReceivers(
- intent,
- intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- flags);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public ResolveInfo resolveService(Intent intent, int flags) {
- try {
- return mPM.resolveService(
- intent,
- intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- flags);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
- try {
- return mPM.queryIntentServices(
- intent,
- intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- flags);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public ProviderInfo resolveContentProvider(String name,
- int flags) {
- try {
- return mPM.resolveContentProvider(name, flags);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public List<ProviderInfo> queryContentProviders(String processName,
- int uid, int flags) {
- try {
- return mPM.queryContentProviders(processName, uid, flags);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override
- public InstrumentationInfo getInstrumentationInfo(
- ComponentName className, int flags)
- throws NameNotFoundException {
- try {
- InstrumentationInfo ii = mPM.getInstrumentationInfo(
- className, flags);
- if (ii != null) {
- return ii;
- }
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
-
- throw new NameNotFoundException(className.toString());
- }
-
- @Override
- public List<InstrumentationInfo> queryInstrumentation(
- String targetPackage, int flags) {
- try {
- return mPM.queryInstrumentation(targetPackage, flags);
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- @Override public Drawable getDrawable(String packageName, int resid,
- ApplicationInfo appInfo) {
- ResourceName name = new ResourceName(packageName, resid);
- Drawable dr = getCachedIcon(name);
- if (dr != null) {
- return dr;
- }
- if (appInfo == null) {
- try {
- appInfo = getApplicationInfo(packageName, 0);
- } catch (NameNotFoundException e) {
- return null;
- }
- }
- try {
- Resources r = getResourcesForApplication(appInfo);
- dr = r.getDrawable(resid);
- if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
- + Integer.toHexString(resid) + " from " + r
- + ": " + dr);
- putCachedIcon(name, dr);
- return dr;
- } catch (NameNotFoundException e) {
- Log.w("PackageManager", "Failure retrieving resources for"
- + appInfo.packageName);
- } catch (RuntimeException e) {
- // If an exception was thrown, fall through to return
- // default icon.
- Log.w("PackageManager", "Failure retrieving icon 0x"
- + Integer.toHexString(resid) + " in package "
- + packageName, e);
- }
- return null;
- }
-
- @Override public Drawable getActivityIcon(ComponentName activityName)
- throws NameNotFoundException {
- return getActivityInfo(activityName, 0).loadIcon(this);
- }
-
- @Override public Drawable getActivityIcon(Intent intent)
- throws NameNotFoundException {
- if (intent.getComponent() != null) {
- return getActivityIcon(intent.getComponent());
- }
-
- ResolveInfo info = resolveActivity(
- intent, PackageManager.MATCH_DEFAULT_ONLY);
- if (info != null) {
- return info.activityInfo.loadIcon(this);
- }
-
- throw new NameNotFoundException(intent.toURI());
- }
-
- @Override public Drawable getDefaultActivityIcon() {
- return Resources.getSystem().getDrawable(
- com.android.internal.R.drawable.sym_def_app_icon);
- }
-
- @Override public Drawable getApplicationIcon(ApplicationInfo info) {
- final int icon = info.icon;
- if (icon != 0) {
- ResourceName name = new ResourceName(info, icon);
- Drawable dr = getCachedIcon(name);
- if (dr != null) {
- return dr;
- }
- try {
- Resources r = getResourcesForApplication(info);
- dr = r.getDrawable(icon);
- if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
- + Integer.toHexString(icon) + " from " + r
- + ": " + dr);
- putCachedIcon(name, dr);
- return dr;
- } catch (NameNotFoundException e) {
- Log.w("PackageManager", "Failure retrieving resources for"
- + info.packageName);
- } catch (RuntimeException e) {
- // If an exception was thrown, fall through to return
- // default icon.
- Log.w("PackageManager", "Failure retrieving app icon", e);
- }
- }
- return getDefaultActivityIcon();
- }
-
- @Override public Drawable getApplicationIcon(String packageName)
- throws NameNotFoundException {
- return getApplicationIcon(getApplicationInfo(packageName, 0));
- }
-
- @Override public Resources getResourcesForActivity(
- ComponentName activityName) throws NameNotFoundException {
- return getResourcesForApplication(
- getActivityInfo(activityName, 0).applicationInfo);
- }
-
- @Override public Resources getResourcesForApplication(
- ApplicationInfo app) throws NameNotFoundException {
- if (app.packageName.equals("system")) {
- return mContext.mMainThread.getSystemContext().getResources();
- }
- Resources r = mContext.mMainThread.getTopLevelResources(
- app.uid == Process.myUid() ? app.sourceDir
- : app.publicSourceDir);
- if (r != null) {
- return r;
- }
- throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
- }
-
- @Override public Resources getResourcesForApplication(
- String appPackageName) throws NameNotFoundException {
- return getResourcesForApplication(
- getApplicationInfo(appPackageName, 0));
- }
-
- int mCachedSafeMode = -1;
- @Override public boolean isSafeMode() {
- try {
- if (mCachedSafeMode < 0) {
- mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
- }
- return mCachedSafeMode != 0;
- } catch (RemoteException e) {
- throw new RuntimeException("Package manager has died", e);
- }
- }
-
- static void configurationChanged() {
- synchronized (sSync) {
- sIconCache.clear();
- sStringCache.clear();
- }
- }
-
- ApplicationPackageManager(ApplicationContext context,
- IPackageManager pm) {
- mContext = context;
- mPM = pm;
- }
-
- private Drawable getCachedIcon(ResourceName name) {
- synchronized (sSync) {
- WeakReference<Drawable> wr = sIconCache.get(name);
- if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
- + name + ": " + wr);
- if (wr != null) { // we have the activity
- Drawable dr = wr.get();
- if (dr != null) {
- if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
- + name + ": " + dr);
- return dr;
- }
- // our entry has been purged
- sIconCache.remove(name);
- }
- }
- return null;
- }
-
- private void establishPackageRemovedReceiver() {
- // mContext.registerReceiverInternal() winds up acquiring the
- // main ActivityManagerService.this lock. If we hold our usual
- // sSync global lock at the same time, we impose a required ordering
- // on those two locks, which is not good for deadlock prevention.
- // Use a dedicated lock around initialization of
- // sPackageRemovedReceiver to avoid this.
- synchronized (sPackageRemovedSync) {
- if (sPackageRemovedReceiver == null) {
- sPackageRemovedReceiver = new PackageRemovedReceiver();
- IntentFilter filter = new IntentFilter(
- Intent.ACTION_PACKAGE_REMOVED);
- filter.addDataScheme("package");
- mContext.registerReceiverInternal(sPackageRemovedReceiver,
- filter, null, null, null);
- }
- }
- }
-
- private void putCachedIcon(ResourceName name, Drawable dr) {
- establishPackageRemovedReceiver();
-
- synchronized (sSync) {
- sIconCache.put(name, new WeakReference<Drawable>(dr));
- if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
- + name + ": " + dr);
- }
- }
-
- private static final class PackageRemovedReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- Uri data = intent.getData();
- String ssp;
- if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
- boolean needCleanup = false;
- synchronized (sSync) {
- Iterator<ResourceName> it = sIconCache.keySet().iterator();
- while (it.hasNext()) {
- ResourceName nm = it.next();
- if (nm.packageName.equals(ssp)) {
- //Log.i(TAG, "Removing cached drawable for " + nm);
- it.remove();
- needCleanup = true;
- }
- }
- it = sStringCache.keySet().iterator();
- while (it.hasNext()) {
- ResourceName nm = it.next();
- if (nm.packageName.equals(ssp)) {
- //Log.i(TAG, "Removing cached string for " + nm);
- it.remove();
- needCleanup = true;
- }
- }
- }
- if (needCleanup || ActivityThread.currentActivityThread().hasPackageInfo(ssp)) {
- ActivityThread.currentActivityThread().scheduleGcIdler();
- }
- }
- }
- }
-
- private static final class ResourceName {
- final String packageName;
- final int iconId;
-
- ResourceName(String _packageName, int _iconId) {
- packageName = _packageName;
- iconId = _iconId;
- }
-
- ResourceName(ApplicationInfo aInfo, int _iconId) {
- this(aInfo.packageName, _iconId);
- }
-
- ResourceName(ComponentInfo cInfo, int _iconId) {
- this(cInfo.applicationInfo.packageName, _iconId);
- }
-
- ResourceName(ResolveInfo rInfo, int _iconId) {
- this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- ResourceName that = (ResourceName) o;
-
- if (iconId != that.iconId) return false;
- return !(packageName != null ?
- !packageName.equals(that.packageName) : that.packageName != null);
-
- }
-
- @Override
- public int hashCode() {
- int result;
- result = packageName.hashCode();
- result = 31 * result + iconId;
- return result;
- }
-
- @Override
- public String toString() {
- return "{ResourceName " + packageName + " / " + iconId + "}";
- }
- }
-
- private CharSequence getCachedString(ResourceName name) {
- synchronized (sSync) {
- WeakReference<CharSequence> wr = sStringCache.get(name);
- if (wr != null) { // we have the activity
- CharSequence cs = wr.get();
- if (cs != null) {
- return cs;
- }
- // our entry has been purged
- sStringCache.remove(name);
- }
- }
- return null;
- }
-
- private void putCachedString(ResourceName name, CharSequence cs) {
- establishPackageRemovedReceiver();
-
- synchronized (sSync) {
- sStringCache.put(name, new WeakReference<CharSequence>(cs));
- }
- }
-
- private CharSequence getLabel(ResourceName name, ApplicationInfo app, int id) {
- CharSequence cs = getCachedString(name);
- if (cs != null) {
- return cs;
- }
- try {
- Resources r = getResourcesForApplication(app);
- cs = r.getText(id);
- putCachedString(name, cs);
- } catch (NameNotFoundException e) {
- Log.w("PackageManager", "Failure retrieving resources for"
- + app.packageName);
- } catch (RuntimeException e) {
- // If an exception was thrown, fall through to return null
- Log.w("ApplicationInfo", "Failure retrieving activity name", e);
- }
- return cs;
- }
-
- @Override
- public CharSequence getText(String packageName, int resid,
- ApplicationInfo appInfo) {
- ResourceName name = new ResourceName(packageName, resid);
- CharSequence text = getCachedString(name);
- if (text != null) {
- return text;
- }
- if (appInfo == null) {
- try {
- appInfo = getApplicationInfo(packageName, 0);
- } catch (NameNotFoundException e) {
- return null;
- }
- }
- try {
- Resources r = getResourcesForApplication(appInfo);
- text = r.getText(resid);
- putCachedString(name, text);
- return text;
- } catch (NameNotFoundException e) {
- Log.w("PackageManager", "Failure retrieving resources for"
- + appInfo.packageName);
- } catch (RuntimeException e) {
- // If an exception was thrown, fall through to return
- // default icon.
- Log.w("PackageManager", "Failure retrieving text 0x"
- + Integer.toHexString(resid) + " in package "
- + packageName, e);
- }
- return null;
- }
-
- @Override
- public XmlResourceParser getXml(String packageName, int resid,
- ApplicationInfo appInfo) {
- if (appInfo == null) {
- try {
- appInfo = getApplicationInfo(packageName, 0);
- } catch (NameNotFoundException e) {
- return null;
- }
- }
- try {
- Resources r = getResourcesForApplication(appInfo);
- return r.getXml(resid);
- } catch (RuntimeException e) {
- // If an exception was thrown, fall through to return
- // default icon.
- Log.w("PackageManager", "Failure retrieving xml 0x"
- + Integer.toHexString(resid) + " in package "
- + packageName, e);
- } catch (NameNotFoundException e) {
- Log.w("PackageManager", "Failure retrieving resources for"
- + appInfo.packageName);
- }
- return null;
- }
-
- @Override
- public CharSequence getApplicationLabel(ApplicationInfo info) {
- if (info.nonLocalizedLabel != null) {
- return info.nonLocalizedLabel;
- }
- final int id = info.labelRes;
- if (id != 0) {
- CharSequence cs = getLabel(new ResourceName(info, id), info, id);
- if (cs != null) {
- return cs;
- }
- }
- return info.packageName;
- }
-
- @Override
- public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags) {
- try {
- mPM.installPackage(packageURI, observer, flags);
- } catch (RemoteException e) {
- // Should never happen!
- }
- }
-
- @Override
- public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
- try {
- mPM.deletePackage(packageName, observer, flags);
- } catch (RemoteException e) {
- // Should never happen!
- }
- }
- @Override
- public void clearApplicationUserData(String packageName,
- IPackageDataObserver observer) {
- try {
- mPM.clearApplicationUserData(packageName, observer);
- } catch (RemoteException e) {
- // Should never happen!
- }
- }
- @Override
- public void deleteApplicationCacheFiles(String packageName,
- IPackageDataObserver observer) {
- try {
- mPM.deleteApplicationCacheFiles(packageName, observer);
- } catch (RemoteException e) {
- // Should never happen!
- }
- }
- @Override
- public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) {
- try {
- mPM.freeStorageAndNotify(idealStorageSize, observer);
- } catch (RemoteException e) {
- // Should never happen!
- }
- }
-
- @Override
- public void freeStorage(long idealStorageSize, PendingIntent opFinishedIntent) {
- try {
- mPM.freeStorage(idealStorageSize, opFinishedIntent);
- } catch (RemoteException e) {
- // Should never happen!
- }
- }
-
- @Override
- public void getPackageSizeInfo(String packageName,
- IPackageStatsObserver observer) {
- try {
- mPM.getPackageSizeInfo(packageName, observer);
- } catch (RemoteException e) {
- // Should never happen!
- }
- }
- @Override
- public void addPackageToPreferred(String packageName) {
- try {
- mPM.addPackageToPreferred(packageName);
- } catch (RemoteException e) {
- // Should never happen!
- }
- }
-
- @Override
- public void removePackageFromPreferred(String packageName) {
- try {
- mPM.removePackageFromPreferred(packageName);
- } catch (RemoteException e) {
- // Should never happen!
- }
- }
-
- @Override
- public List<PackageInfo> getPreferredPackages(int flags) {
- try {
- return mPM.getPreferredPackages(flags);
- } catch (RemoteException e) {
- // Should never happen!
- }
- return new ArrayList<PackageInfo>();
- }
-
- @Override
- public void addPreferredActivity(IntentFilter filter,
- int match, ComponentName[] set, ComponentName activity) {
- try {
- mPM.addPreferredActivity(filter, match, set, activity);
- } catch (RemoteException e) {
- // Should never happen!
- }
- }
-
- @Override
- public void clearPackagePreferredActivities(String packageName) {
- try {
- mPM.clearPackagePreferredActivities(packageName);
- } catch (RemoteException e) {
- // Should never happen!
- }
- }
-
- @Override
- public int getPreferredActivities(List<IntentFilter> outFilters,
- List<ComponentName> outActivities, String packageName) {
- try {
- return mPM.getPreferredActivities(outFilters, outActivities, packageName);
- } catch (RemoteException e) {
- // Should never happen!
- }
- return 0;
- }
-
- @Override
- public void setComponentEnabledSetting(ComponentName componentName,
- int newState, int flags) {
- try {
- mPM.setComponentEnabledSetting(componentName, newState, flags);
- } catch (RemoteException e) {
- // Should never happen!
- }
- }
-
- @Override
- public int getComponentEnabledSetting(ComponentName componentName) {
- try {
- return mPM.getComponentEnabledSetting(componentName);
- } catch (RemoteException e) {
- // Should never happen!
- }
- return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
- }
-
- @Override
- public void setApplicationEnabledSetting(String packageName,
- int newState, int flags) {
- try {
- mPM.setApplicationEnabledSetting(packageName, newState, flags);
- } catch (RemoteException e) {
- // Should never happen!
- }
- }
-
- @Override
- public int getApplicationEnabledSetting(String packageName) {
- try {
- return mPM.getApplicationEnabledSetting(packageName);
- } catch (RemoteException e) {
- // Should never happen!
- }
- return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
- }
-
- private final ApplicationContext mContext;
- private final IPackageManager mPM;
-
- private static final Object sSync = new Object();
- private static final Object sPackageRemovedSync = new Object();
- private static BroadcastReceiver sPackageRemovedReceiver;
- private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
- = new HashMap<ResourceName, WeakReference<Drawable> >();
- private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
- = new HashMap<ResourceName, WeakReference<CharSequence> >();
- }
-
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
-
- private static final class SharedPreferencesImpl implements SharedPreferences {
-
- private final File mFile;
- private final File mBackupFile;
- private final int mMode;
- private Map mMap;
- private final FileStatus mFileStatus = new FileStatus();
- private long mTimestamp;
-
- private List<OnSharedPreferenceChangeListener> mListeners;
-
- SharedPreferencesImpl(
- File file, int mode, Map initialContents) {
- mFile = file;
- mBackupFile = makeBackupFile(file);
- mMode = mode;
- mMap = initialContents != null ? initialContents : new HashMap();
- if (FileUtils.getFileStatus(file.getPath(), mFileStatus)) {
- mTimestamp = mFileStatus.mtime;
- }
- mListeners = new ArrayList<OnSharedPreferenceChangeListener>();
- }
-
- public boolean hasFileChanged() {
- synchronized (this) {
- if (!FileUtils.getFileStatus(mFile.getPath(), mFileStatus)) {
- return true;
- }
- return mTimestamp != mFileStatus.mtime;
- }
- }
-
- public void replace(Map newContents) {
- if (newContents != null) {
- synchronized (this) {
- mMap = newContents;
- }
- }
- }
-
- public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
- synchronized(this) {
- if (!mListeners.contains(listener)) {
- mListeners.add(listener);
- }
- }
- }
-
- public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
- synchronized(this) {
- mListeners.remove(listener);
- }
- }
-
- public Map<String, ?> getAll() {
- synchronized(this) {
- //noinspection unchecked
- return new HashMap(mMap);
- }
- }
-
- public String getString(String key, String defValue) {
- synchronized (this) {
- String v = (String)mMap.get(key);
- return v != null ? v : defValue;
- }
- }
-
- public int getInt(String key, int defValue) {
- synchronized (this) {
- Integer v = (Integer)mMap.get(key);
- return v != null ? v : defValue;
- }
- }
- public long getLong(String key, long defValue) {
- synchronized (this) {
- Long v = (Long) mMap.get(key);
- return v != null ? v : defValue;
- }
- }
- public float getFloat(String key, float defValue) {
- synchronized (this) {
- Float v = (Float)mMap.get(key);
- return v != null ? v : defValue;
- }
- }
- public boolean getBoolean(String key, boolean defValue) {
- synchronized (this) {
- Boolean v = (Boolean)mMap.get(key);
- return v != null ? v : defValue;
- }
- }
-
- public boolean contains(String key) {
- synchronized (this) {
- return mMap.containsKey(key);
- }
- }
-
- public final class EditorImpl implements Editor {
- private final Map<String, Object> mModified = Maps.newHashMap();
- private boolean mClear = false;
-
- public Editor putString(String key, String value) {
- synchronized (this) {
- mModified.put(key, value);
- return this;
- }
- }
- public Editor putInt(String key, int value) {
- synchronized (this) {
- mModified.put(key, value);
- return this;
- }
- }
- public Editor putLong(String key, long value) {
- synchronized (this) {
- mModified.put(key, value);
- return this;
- }
- }
- public Editor putFloat(String key, float value) {
- synchronized (this) {
- mModified.put(key, value);
- return this;
- }
- }
- public Editor putBoolean(String key, boolean value) {
- synchronized (this) {
- mModified.put(key, value);
- return this;
- }
- }
-
- public Editor remove(String key) {
- synchronized (this) {
- mModified.put(key, this);
- return this;
- }
- }
-
- public Editor clear() {
- synchronized (this) {
- mClear = true;
- return this;
- }
- }
-
- public boolean commit() {
- boolean returnValue;
-
- boolean hasListeners;
- List<String> keysModified = null;
- List<OnSharedPreferenceChangeListener> listeners = null;
-
- synchronized (SharedPreferencesImpl.this) {
- hasListeners = mListeners.size() > 0;
- if (hasListeners) {
- keysModified = new ArrayList<String>();
- listeners = new ArrayList<OnSharedPreferenceChangeListener>(mListeners);
- }
-
- synchronized (this) {
- if (mClear) {
- mMap.clear();
- mClear = false;
- }
-
- Iterator<Entry<String, Object>> it = mModified.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry<String, Object> e = it.next();
- String k = e.getKey();
- Object v = e.getValue();
- if (v == this) {
- mMap.remove(k);
- } else {
- mMap.put(k, v);
- }
-
- if (hasListeners) {
- keysModified.add(k);
- }
- }
-
- mModified.clear();
- }
-
- returnValue = writeFileLocked();
- }
-
- if (hasListeners) {
- for (int i = keysModified.size() - 1; i >= 0; i--) {
- final String key = keysModified.get(i);
- // Call in the order they were registered
- final int listenersSize = listeners.size();
- for (int j = 0; j < listenersSize; j++) {
- listeners.get(j).onSharedPreferenceChanged(SharedPreferencesImpl.this, key);
- }
- }
- }
-
- return returnValue;
- }
- }
-
- public Editor edit() {
- return new EditorImpl();
- }
-
- private FileOutputStream createFileOutputStream(File file) {
- FileOutputStream str = null;
- try {
- str = new FileOutputStream(file);
- } catch (FileNotFoundException e) {
- File parent = file.getParentFile();
- if (!parent.mkdir()) {
- Log.e(TAG, "Couldn't create directory for SharedPreferences file " + file);
- return null;
- }
- FileUtils.setPermissions(
- parent.getPath(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
- -1, -1);
- try {
- str = new FileOutputStream(file);
- } catch (FileNotFoundException e2) {
- Log.e(TAG, "Couldn't create SharedPreferences file " + file, e2);
- }
- }
- return str;
- }
-
- private boolean writeFileLocked() {
- // Rename the current file so it may be used as a backup during the next read
- if (mFile.exists()) {
- if (!mFile.renameTo(mBackupFile)) {
- Log.e(TAG, "Couldn't rename file " + mFile + " to backup file " + mBackupFile);
- }
- }
-
- // Attempt to write the file, delete the backup and return true as atomically as
- // possible. If any exception occurs, delete the new file; next time we will restore
- // from the backup.
- try {
- FileOutputStream str = createFileOutputStream(mFile);
- if (str == null) {
- return false;
- }
- XmlUtils.writeMapXml(mMap, str);
- str.close();
- setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
- if (FileUtils.getFileStatus(mFile.getPath(), mFileStatus)) {
- mTimestamp = mFileStatus.mtime;
- }
-
- // Writing was successful, delete the backup file
- if (!mBackupFile.delete()) {
- Log.e(TAG, "Couldn't delete new backup file " + mBackupFile);
- }
- return true;
- } catch (XmlPullParserException e) {
- Log.w(TAG, "writeFileLocked: Got exception:", e);
- } catch (IOException e) {
- Log.w(TAG, "writeFileLocked: Got exception:", e);
- }
- // Clean up an unsuccessfully written file
- if (mFile.exists()) {
- if (!mFile.delete()) {
- Log.e(TAG, "Couldn't clean up partially-written file " + mFile);
- }
- }
- return false;
- }
- }
-
- private static class WallpaperCallback extends IWallpaperServiceCallback.Stub {
- private WeakReference<ApplicationContext> mContext;
-
- public WallpaperCallback(ApplicationContext context) {
- mContext = new WeakReference<ApplicationContext>(context);
- }
-
- public synchronized void onWallpaperChanged() {
-
- /* The wallpaper has changed but we shouldn't eagerly load the
- * wallpaper as that would be inefficient. Reset the cached wallpaper
- * to null so if the user requests the wallpaper again then we'll
- * fetch it.
- */
- final ApplicationContext applicationContext = mContext.get();
- if (applicationContext != null) {
- applicationContext.mWallpaper = null;
- }
- }
- }
-}
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
deleted file mode 100644
index 2e301c9..0000000
--- a/core/java/android/app/ApplicationLoaders.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import dalvik.system.PathClassLoader;
-
-import java.util.HashMap;
-
-class ApplicationLoaders
-{
- public static ApplicationLoaders getDefault()
- {
- return gApplicationLoaders;
- }
-
- public ClassLoader getClassLoader(String zip, String appDataDir,
- ClassLoader parent)
- {
- /*
- * This is the parent we use if they pass "null" in. In theory
- * this should be the "system" class loader; in practice we
- * don't use that and can happily (and more efficiently) use the
- * bootstrap class loader.
- */
- ClassLoader baseParent = ClassLoader.getSystemClassLoader().getParent();
-
- synchronized (mLoaders) {
- if (parent == null) {
- parent = baseParent;
- }
-
- /*
- * If we're one step up from the base class loader, find
- * something in our cache. Otherwise, we create a whole
- * new ClassLoader for the zip archive.
- */
- if (parent == baseParent) {
- ClassLoader loader = (ClassLoader)mLoaders.get(zip);
- if (loader != null) {
- return loader;
- }
-
- PathClassLoader pathClassloader =
- new PathClassLoader(zip, appDataDir + "/lib", parent);
-
- mLoaders.put(zip, pathClassloader);
- return pathClassloader;
- }
-
- return new PathClassLoader(zip, parent);
- }
- }
-
- private final HashMap mLoaders = new HashMap();
-
- private static final ApplicationLoaders gApplicationLoaders
- = new ApplicationLoaders();
-}
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
deleted file mode 100644
index d2cf55a..0000000
--- a/core/java/android/app/ApplicationThreadNative.java
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ServiceInfo;
-import android.content.res.Configuration;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/** {@hide} */
-public abstract class ApplicationThreadNative extends Binder
- implements IApplicationThread {
- /**
- * Cast a Binder object into an application thread interface, generating
- * a proxy if needed.
- */
- static public IApplicationThread asInterface(IBinder obj) {
- if (obj == null) {
- return null;
- }
- IApplicationThread in =
- (IApplicationThread)obj.queryLocalInterface(descriptor);
- if (in != null) {
- return in;
- }
-
- return new ApplicationThreadProxy(obj);
- }
-
- public ApplicationThreadNative() {
- attachInterface(this, descriptor);
- }
-
- @Override
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
- throws RemoteException {
- switch (code) {
- case SCHEDULE_PAUSE_ACTIVITY_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder b = data.readStrongBinder();
- boolean finished = data.readInt() != 0;
- boolean userLeaving = data.readInt() != 0;
- int configChanges = data.readInt();
- schedulePauseActivity(b, finished, userLeaving, configChanges);
- return true;
- }
-
- case SCHEDULE_STOP_ACTIVITY_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder b = data.readStrongBinder();
- boolean show = data.readInt() != 0;
- int configChanges = data.readInt();
- scheduleStopActivity(b, show, configChanges);
- return true;
- }
-
- case SCHEDULE_WINDOW_VISIBILITY_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder b = data.readStrongBinder();
- boolean show = data.readInt() != 0;
- scheduleWindowVisibility(b, show);
- return true;
- }
-
- case SCHEDULE_RESUME_ACTIVITY_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder b = data.readStrongBinder();
- boolean isForward = data.readInt() != 0;
- scheduleResumeActivity(b, isForward);
- return true;
- }
-
- case SCHEDULE_SEND_RESULT_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder b = data.readStrongBinder();
- List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR);
- scheduleSendResult(b, ri);
- return true;
- }
-
- case SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- Intent intent = Intent.CREATOR.createFromParcel(data);
- IBinder b = data.readStrongBinder();
- ActivityInfo info = ActivityInfo.CREATOR.createFromParcel(data);
- Bundle state = data.readBundle();
- List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR);
- List<Intent> pi = data.createTypedArrayList(Intent.CREATOR);
- boolean notResumed = data.readInt() != 0;
- boolean isForward = data.readInt() != 0;
- scheduleLaunchActivity(intent, b, info, state, ri, pi, notResumed, isForward);
- return true;
- }
-
- case SCHEDULE_RELAUNCH_ACTIVITY_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder b = data.readStrongBinder();
- List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR);
- List<Intent> pi = data.createTypedArrayList(Intent.CREATOR);
- int configChanges = data.readInt();
- boolean notResumed = data.readInt() != 0;
- scheduleRelaunchActivity(b, ri, pi, configChanges, notResumed);
- return true;
- }
-
- case SCHEDULE_NEW_INTENT_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- List<Intent> pi = data.createTypedArrayList(Intent.CREATOR);
- IBinder b = data.readStrongBinder();
- scheduleNewIntent(pi, b);
- return true;
- }
-
- case SCHEDULE_FINISH_ACTIVITY_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder b = data.readStrongBinder();
- boolean finishing = data.readInt() != 0;
- int configChanges = data.readInt();
- scheduleDestroyActivity(b, finishing, configChanges);
- return true;
- }
-
- case SCHEDULE_RECEIVER_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- Intent intent = Intent.CREATOR.createFromParcel(data);
- ActivityInfo info = ActivityInfo.CREATOR.createFromParcel(data);
- int resultCode = data.readInt();
- String resultData = data.readString();
- Bundle resultExtras = data.readBundle();
- boolean sync = data.readInt() != 0;
- scheduleReceiver(intent, info, resultCode, resultData,
- resultExtras, sync);
- return true;
- }
-
- case SCHEDULE_CREATE_SERVICE_TRANSACTION: {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder token = data.readStrongBinder();
- ServiceInfo info = ServiceInfo.CREATOR.createFromParcel(data);
- scheduleCreateService(token, info);
- return true;
- }
-
- case SCHEDULE_BIND_SERVICE_TRANSACTION: {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder token = data.readStrongBinder();
- Intent intent = Intent.CREATOR.createFromParcel(data);
- boolean rebind = data.readInt() != 0;
- scheduleBindService(token, intent, rebind);
- return true;
- }
-
- case SCHEDULE_UNBIND_SERVICE_TRANSACTION: {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder token = data.readStrongBinder();
- Intent intent = Intent.CREATOR.createFromParcel(data);
- scheduleUnbindService(token, intent);
- return true;
- }
-
- case SCHEDULE_SERVICE_ARGS_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder token = data.readStrongBinder();
- int startId = data.readInt();
- Intent args = Intent.CREATOR.createFromParcel(data);
- scheduleServiceArgs(token, startId, args);
- return true;
- }
-
- case SCHEDULE_STOP_SERVICE_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder token = data.readStrongBinder();
- scheduleStopService(token);
- return true;
- }
-
- case BIND_APPLICATION_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- String packageName = data.readString();
- ApplicationInfo info =
- ApplicationInfo.CREATOR.createFromParcel(data);
- List<ProviderInfo> providers =
- data.createTypedArrayList(ProviderInfo.CREATOR);
- ComponentName testName = (data.readInt() != 0)
- ? new ComponentName(data) : null;
- String profileName = data.readString();
- Bundle testArgs = data.readBundle();
- IBinder binder = data.readStrongBinder();
- IInstrumentationWatcher testWatcher = IInstrumentationWatcher.Stub.asInterface(binder);
- int testMode = data.readInt();
- Configuration config = Configuration.CREATOR.createFromParcel(data);
- HashMap<String, IBinder> services = data.readHashMap(null);
- bindApplication(packageName, info,
- providers, testName, profileName,
- testArgs, testWatcher, testMode, config, services);
- return true;
- }
-
- case SCHEDULE_EXIT_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- scheduleExit();
- return true;
- }
-
- case REQUEST_THUMBNAIL_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder b = data.readStrongBinder();
- requestThumbnail(b);
- return true;
- }
-
- case SCHEDULE_CONFIGURATION_CHANGED_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- Configuration config = Configuration.CREATOR.createFromParcel(data);
- scheduleConfigurationChanged(config);
- return true;
- }
-
- case UPDATE_TIME_ZONE_TRANSACTION: {
- data.enforceInterface(IApplicationThread.descriptor);
- updateTimeZone();
- return true;
- }
-
- case PROCESS_IN_BACKGROUND_TRANSACTION: {
- data.enforceInterface(IApplicationThread.descriptor);
- processInBackground();
- return true;
- }
-
- case DUMP_SERVICE_TRANSACTION: {
- data.enforceInterface(IApplicationThread.descriptor);
- ParcelFileDescriptor fd = data.readFileDescriptor();
- final IBinder service = data.readStrongBinder();
- final String[] args = data.readStringArray();
- if (fd != null) {
- dumpService(fd.getFileDescriptor(), service, args);
- try {
- fd.close();
- } catch (IOException e) {
- }
- }
- return true;
- }
-
- case SCHEDULE_REGISTERED_RECEIVER_TRANSACTION: {
- data.enforceInterface(IApplicationThread.descriptor);
- IIntentReceiver receiver = IIntentReceiver.Stub.asInterface(
- data.readStrongBinder());
- Intent intent = Intent.CREATOR.createFromParcel(data);
- int resultCode = data.readInt();
- String dataStr = data.readString();
- Bundle extras = data.readBundle();
- boolean ordered = data.readInt() != 0;
- scheduleRegisteredReceiver(receiver, intent,
- resultCode, dataStr, extras, ordered);
- return true;
- }
-
- case SCHEDULE_LOW_MEMORY_TRANSACTION:
- {
- scheduleLowMemory();
- return true;
- }
-
- case SCHEDULE_ACTIVITY_CONFIGURATION_CHANGED_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder b = data.readStrongBinder();
- scheduleActivityConfigurationChanged(b);
- return true;
- }
-
- case REQUEST_PSS_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- requestPss();
- return true;
- }
- }
-
- return super.onTransact(code, data, reply, flags);
- }
-
- public IBinder asBinder()
- {
- return this;
- }
-}
-
-class ApplicationThreadProxy implements IApplicationThread {
- private final IBinder mRemote;
-
- public ApplicationThreadProxy(IBinder remote) {
- mRemote = remote;
- }
-
- public final IBinder asBinder() {
- return mRemote;
- }
-
- public final void schedulePauseActivity(IBinder token, boolean finished,
- boolean userLeaving, int configChanges) throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- data.writeInt(finished ? 1 : 0);
- data.writeInt(userLeaving ? 1 :0);
- data.writeInt(configChanges);
- mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleStopActivity(IBinder token, boolean showWindow,
- int configChanges) throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- data.writeInt(showWindow ? 1 : 0);
- data.writeInt(configChanges);
- mRemote.transact(SCHEDULE_STOP_ACTIVITY_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleWindowVisibility(IBinder token,
- boolean showWindow) throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- data.writeInt(showWindow ? 1 : 0);
- mRemote.transact(SCHEDULE_WINDOW_VISIBILITY_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleResumeActivity(IBinder token, boolean isForward)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- data.writeInt(isForward ? 1 : 0);
- mRemote.transact(SCHEDULE_RESUME_ACTIVITY_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleSendResult(IBinder token, List<ResultInfo> results)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- data.writeTypedList(results);
- mRemote.transact(SCHEDULE_SEND_RESULT_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleLaunchActivity(Intent intent, IBinder token,
- ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
- List<Intent> pendingNewIntents, boolean notResumed, boolean isForward)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- intent.writeToParcel(data, 0);
- data.writeStrongBinder(token);
- info.writeToParcel(data, 0);
- data.writeBundle(state);
- data.writeTypedList(pendingResults);
- data.writeTypedList(pendingNewIntents);
- data.writeInt(notResumed ? 1 : 0);
- data.writeInt(isForward ? 1 : 0);
- mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleRelaunchActivity(IBinder token,
- List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
- int configChanges, boolean notResumed) throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- data.writeTypedList(pendingResults);
- data.writeTypedList(pendingNewIntents);
- data.writeInt(configChanges);
- data.writeInt(notResumed ? 1 : 0);
- mRemote.transact(SCHEDULE_RELAUNCH_ACTIVITY_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public void scheduleNewIntent(List<Intent> intents, IBinder token)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeTypedList(intents);
- data.writeStrongBinder(token);
- mRemote.transact(SCHEDULE_NEW_INTENT_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleDestroyActivity(IBinder token, boolean finishing,
- int configChanges) throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- data.writeInt(finishing ? 1 : 0);
- data.writeInt(configChanges);
- mRemote.transact(SCHEDULE_FINISH_ACTIVITY_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleReceiver(Intent intent, ActivityInfo info,
- int resultCode, String resultData,
- Bundle map, boolean sync) throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- intent.writeToParcel(data, 0);
- info.writeToParcel(data, 0);
- data.writeInt(resultCode);
- data.writeString(resultData);
- data.writeBundle(map);
- data.writeInt(sync ? 1 : 0);
- mRemote.transact(SCHEDULE_RECEIVER_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleCreateService(IBinder token, ServiceInfo info)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- info.writeToParcel(data, 0);
- mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleBindService(IBinder token, Intent intent, boolean rebind)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- intent.writeToParcel(data, 0);
- data.writeInt(rebind ? 1 : 0);
- mRemote.transact(SCHEDULE_BIND_SERVICE_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleUnbindService(IBinder token, Intent intent)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- intent.writeToParcel(data, 0);
- mRemote.transact(SCHEDULE_UNBIND_SERVICE_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleServiceArgs(IBinder token, int startId,
- Intent args) throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- data.writeInt(startId);
- args.writeToParcel(data, 0);
- mRemote.transact(SCHEDULE_SERVICE_ARGS_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleStopService(IBinder token)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- mRemote.transact(SCHEDULE_STOP_SERVICE_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void bindApplication(String packageName, ApplicationInfo info,
- List<ProviderInfo> providers, ComponentName testName,
- String profileName, Bundle testArgs, IInstrumentationWatcher testWatcher, int debugMode,
- Configuration config, Map<String, IBinder> services) throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeString(packageName);
- info.writeToParcel(data, 0);
- data.writeTypedList(providers);
- if (testName == null) {
- data.writeInt(0);
- } else {
- data.writeInt(1);
- testName.writeToParcel(data, 0);
- }
- data.writeString(profileName);
- data.writeBundle(testArgs);
- data.writeStrongInterface(testWatcher);
- data.writeInt(debugMode);
- config.writeToParcel(data, 0);
- data.writeMap(services);
- mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleExit() throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- mRemote.transact(SCHEDULE_EXIT_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void requestThumbnail(IBinder token)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- mRemote.transact(REQUEST_THUMBNAIL_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleConfigurationChanged(Configuration config)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- config.writeToParcel(data, 0);
- mRemote.transact(SCHEDULE_CONFIGURATION_CHANGED_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public void updateTimeZone() throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- mRemote.transact(UPDATE_TIME_ZONE_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public void processInBackground() throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- mRemote.transact(PROCESS_IN_BACKGROUND_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public void dumpService(FileDescriptor fd, IBinder token, String[] args)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeFileDescriptor(fd);
- data.writeStrongBinder(token);
- data.writeStringArray(args);
- mRemote.transact(DUMP_SERVICE_TRANSACTION, data, null, 0);
- data.recycle();
- }
-
- public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
- int resultCode, String dataStr, Bundle extras, boolean ordered)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(receiver.asBinder());
- intent.writeToParcel(data, 0);
- data.writeInt(resultCode);
- data.writeString(dataStr);
- data.writeBundle(extras);
- data.writeInt(ordered ? 1 : 0);
- mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleLowMemory() throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- mRemote.transact(SCHEDULE_LOW_MEMORY_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void scheduleActivityConfigurationChanged(
- IBinder token) throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- mRemote.transact(SCHEDULE_ACTIVITY_CONFIGURATION_CHANGED_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public final void requestPss() throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- mRemote.transact(REQUEST_PSS_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
-}
-
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
deleted file mode 100644
index ee5e0d5..0000000
--- a/core/java/android/app/DatePickerDialog.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.os.Bundle;
-import android.text.TextUtils.TruncateAt;
-import android.text.format.DateFormat;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.DatePicker;
-import android.widget.TextView;
-import android.widget.DatePicker.OnDateChangedListener;
-
-import com.android.internal.R;
-
-import java.text.DateFormatSymbols;
-import java.util.Calendar;
-
-/**
- * A simple dialog containing an {@link android.widget.DatePicker}.
- */
-public class DatePickerDialog extends AlertDialog implements OnClickListener,
- OnDateChangedListener {
-
- private static final String YEAR = "year";
- private static final String MONTH = "month";
- private static final String DAY = "day";
-
- private final DatePicker mDatePicker;
- private final OnDateSetListener mCallBack;
- private final Calendar mCalendar;
- private final java.text.DateFormat mDateFormat;
- private final String[] mWeekDays;
-
- private int mInitialYear;
- private int mInitialMonth;
- private int mInitialDay;
-
- /**
- * The callback used to indicate the user is done filling in the date.
- */
- public interface OnDateSetListener {
-
- /**
- * @param view The view associated with this listener.
- * @param year The year that was set.
- * @param monthOfYear The month that was set (0-11) for compatibility
- * with {@link java.util.Calendar}.
- * @param dayOfMonth The day of the month that was set.
- */
- void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth);
- }
-
- /**
- * @param context The context the dialog is to run in.
- * @param callBack How the parent is notified that the date is set.
- * @param year The initial year of the dialog.
- * @param monthOfYear The initial month of the dialog.
- * @param dayOfMonth The initial day of the dialog.
- */
- public DatePickerDialog(Context context,
- OnDateSetListener callBack,
- int year,
- int monthOfYear,
- int dayOfMonth) {
- this(context, com.android.internal.R.style.Theme_Dialog_Alert,
- callBack, year, monthOfYear, dayOfMonth);
- }
-
- /**
- * @param context The context the dialog is to run in.
- * @param theme the theme to apply to this dialog
- * @param callBack How the parent is notified that the date is set.
- * @param year The initial year of the dialog.
- * @param monthOfYear The initial month of the dialog.
- * @param dayOfMonth The initial day of the dialog.
- */
- public DatePickerDialog(Context context,
- int theme,
- OnDateSetListener callBack,
- int year,
- int monthOfYear,
- int dayOfMonth) {
- super(context, theme);
-
- mCallBack = callBack;
- mInitialYear = year;
- mInitialMonth = monthOfYear;
- mInitialDay = dayOfMonth;
- DateFormatSymbols symbols = new DateFormatSymbols();
- mWeekDays = symbols.getShortWeekdays();
-
- mDateFormat = DateFormat.getMediumDateFormat(context);
- mCalendar = Calendar.getInstance();
- updateTitle(mInitialYear, mInitialMonth, mInitialDay);
-
- setButton(context.getText(R.string.date_time_set), this);
- setButton2(context.getText(R.string.cancel), (OnClickListener) null);
- setIcon(R.drawable.ic_dialog_time);
-
- LayoutInflater inflater =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(R.layout.date_picker_dialog, null);
- setView(view);
- mDatePicker = (DatePicker) view.findViewById(R.id.datePicker);
- mDatePicker.init(mInitialYear, mInitialMonth, mInitialDay, this);
- }
-
- @Override
- public void show() {
- super.show();
-
- /* Sometimes the full month is displayed causing the title
- * to be very long, in those cases ensure it doesn't wrap to
- * 2 lines (as that looks jumpy) and ensure we ellipsize the end.
- */
- TextView title = (TextView) findViewById(R.id.alertTitle);
- title.setSingleLine();
- title.setEllipsize(TruncateAt.END);
- }
-
- public void onClick(DialogInterface dialog, int which) {
- if (mCallBack != null) {
- mDatePicker.clearFocus();
- mCallBack.onDateSet(mDatePicker, mDatePicker.getYear(),
- mDatePicker.getMonth(), mDatePicker.getDayOfMonth());
- }
- }
-
- public void onDateChanged(DatePicker view, int year,
- int month, int day) {
- updateTitle(year, month, day);
- }
-
- public void updateDate(int year, int monthOfYear, int dayOfMonth) {
- mInitialYear = year;
- mInitialMonth = monthOfYear;
- mInitialDay = dayOfMonth;
- mDatePicker.updateDate(year, monthOfYear, dayOfMonth);
- }
-
- private void updateTitle(int year, int month, int day) {
- mCalendar.set(Calendar.YEAR, year);
- mCalendar.set(Calendar.MONTH, month);
- mCalendar.set(Calendar.DAY_OF_MONTH, day);
- String weekday = mWeekDays[mCalendar.get(Calendar.DAY_OF_WEEK)];
- setTitle(weekday + ", " + mDateFormat.format(mCalendar.getTime()));
- }
-
- @Override
- public Bundle onSaveInstanceState() {
- Bundle state = super.onSaveInstanceState();
- state.putInt(YEAR, mDatePicker.getYear());
- state.putInt(MONTH, mDatePicker.getMonth());
- state.putInt(DAY, mDatePicker.getDayOfMonth());
- return state;
- }
-
- @Override
- public void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- int year = savedInstanceState.getInt(YEAR);
- int month = savedInstanceState.getInt(MONTH);
- int day = savedInstanceState.getInt(DAY);
- mDatePicker.init(year, month, day, this);
- updateTitle(year, month, day);
- }
-}
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
deleted file mode 100644
index b09a57f..0000000
--- a/core/java/android/app/Dialog.java
+++ /dev/null
@@ -1,954 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.Context;
-import android.content.DialogInterface;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Bundle;
-import android.util.Config;
-import android.util.Log;
-import android.view.ContextMenu;
-import android.view.ContextThemeWrapper;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.LayoutInflater;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.View.OnCreateContextMenuListener;
-
-import com.android.internal.policy.PolicyManager;
-
-import java.lang.ref.WeakReference;
-
-/**
- * Base class for Dialogs.
- *
- * <p>Note: Activities provide a facility to manage the creation, saving and
- * restoring of dialogs. See {@link Activity#onCreateDialog(int)},
- * {@link Activity#onPrepareDialog(int, Dialog)},
- * {@link Activity#showDialog(int)}, and {@link Activity#dismissDialog(int)}. If
- * these methods are used, {@link #getOwnerActivity()} will return the Activity
- * that managed this dialog.
- *
- * <p>Often you will want to have a Dialog display on top of the current
- * input method, because there is no reason for it to accept text. You can
- * do this by setting the {@link WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM
- * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM} window flag (assuming
- * your Dialog takes input focus, as it the default) with the following code:
- *
- * <pre>
- * getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
- * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
- * </pre>
- */
-public class Dialog implements DialogInterface, Window.Callback,
- KeyEvent.Callback, OnCreateContextMenuListener {
- private static final String LOG_TAG = "Dialog";
-
- private Activity mOwnerActivity;
-
- final Context mContext;
- final WindowManager mWindowManager;
- Window mWindow;
- View mDecor;
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected boolean mCancelable = true;
- private Message mCancelMessage;
- private Message mDismissMessage;
-
- /**
- * Whether to cancel the dialog when a touch is received outside of the
- * window's bounds.
- */
- private boolean mCanceledOnTouchOutside = false;
-
- private OnKeyListener mOnKeyListener;
-
- private boolean mCreated = false;
- private boolean mShowing = false;
-
- private final Thread mUiThread;
- private final Handler mHandler = new Handler();
-
- private final Runnable mDismissAction = new Runnable() {
- public void run() {
- dismissDialog();
- }
- };
-
- /**
- * Create a Dialog window that uses the default dialog frame style.
- *
- * @param context The Context the Dialog is to run it. In particular, it
- * uses the window manager and theme in this context to
- * present its UI.
- */
- public Dialog(Context context) {
- this(context, 0);
- }
-
- /**
- * Create a Dialog window that uses a custom dialog style.
- *
- * @param context The Context in which the Dialog should run. In particular, it
- * uses the window manager and theme from this context to
- * present its UI.
- * @param theme A style resource describing the theme to use for the
- * window. See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">Style
- * and Theme Resources</a> for more information about defining and using
- * styles. This theme is applied on top of the current theme in
- * <var>context</var>. If 0, the default dialog theme will be used.
- */
- public Dialog(Context context, int theme) {
- mContext = new ContextThemeWrapper(
- context, theme == 0 ? com.android.internal.R.style.Theme_Dialog : theme);
- mWindowManager = (WindowManager)context.getSystemService("window");
- Window w = PolicyManager.makeNewWindow(mContext);
- mWindow = w;
- w.setCallback(this);
- w.setWindowManager(mWindowManager, null, null);
- w.setGravity(Gravity.CENTER);
- mUiThread = Thread.currentThread();
- mDismissCancelHandler = new DismissCancelHandler(this);
- }
-
- /**
- * @deprecated
- * @hide
- */
- @Deprecated
- protected Dialog(Context context, boolean cancelable,
- Message cancelCallback) {
- this(context);
- mCancelable = cancelable;
- mCancelMessage = cancelCallback;
- }
-
- protected Dialog(Context context, boolean cancelable,
- OnCancelListener cancelListener) {
- this(context);
- mCancelable = cancelable;
- setOnCancelListener(cancelListener);
- }
-
- /**
- * Retrieve the Context this Dialog is running in.
- *
- * @return Context The Context that was supplied to the constructor.
- */
- public final Context getContext() {
- return mContext;
- }
-
- /**
- * Sets the Activity that owns this dialog. An example use: This Dialog will
- * use the suggested volume control stream of the Activity.
- *
- * @param activity The Activity that owns this dialog.
- */
- public final void setOwnerActivity(Activity activity) {
- mOwnerActivity = activity;
-
- getWindow().setVolumeControlStream(mOwnerActivity.getVolumeControlStream());
- }
-
- /**
- * Returns the Activity that owns this Dialog. For example, if
- * {@link Activity#showDialog(int)} is used to show this Dialog, that
- * Activity will be the owner (by default). Depending on how this dialog was
- * created, this may return null.
- *
- * @return The Activity that owns this Dialog.
- */
- public final Activity getOwnerActivity() {
- return mOwnerActivity;
- }
-
- /**
- * @return Whether the dialog is currently showing.
- */
- public boolean isShowing() {
- return mShowing;
- }
-
- /**
- * Start the dialog and display it on screen. The window is placed in the
- * application layer and opaque. Note that you should not override this
- * method to do initialization when the dialog is shown, instead implement
- * that in {@link #onStart}.
- */
- public void show() {
- if (mShowing) {
- if (Config.LOGV) Log.v(LOG_TAG,
- "[Dialog] start: already showing, ignore");
- if (mDecor != null) mDecor.setVisibility(View.VISIBLE);
- return;
- }
-
- if (!mCreated) {
- dispatchOnCreate(null);
- }
-
- onStart();
- mDecor = mWindow.getDecorView();
- WindowManager.LayoutParams l = mWindow.getAttributes();
- if ((l.softInputMode
- & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {
- WindowManager.LayoutParams nl = new WindowManager.LayoutParams();
- nl.copyFrom(l);
- nl.softInputMode |=
- WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
- l = nl;
- }
- mWindowManager.addView(mDecor, l);
- mShowing = true;
- }
-
- /**
- * Hide the dialog, but do not dismiss it.
- */
- public void hide() {
- if (mDecor != null) mDecor.setVisibility(View.GONE);
- }
-
- /**
- * Dismiss this dialog, removing it from the screen. This method can be
- * invoked safely from any thread. Note that you should not override this
- * method to do cleanup when the dialog is dismissed, instead implement
- * that in {@link #onStop}.
- */
- public void dismiss() {
- if (Thread.currentThread() != mUiThread) {
- mHandler.post(mDismissAction);
- } else {
- mDismissAction.run();
- }
- }
-
- private void dismissDialog() {
- if (mDecor == null) {
- if (Config.LOGV) Log.v(LOG_TAG,
- "[Dialog] dismiss: already dismissed, ignore");
- return;
- }
- if (!mShowing) {
- if (Config.LOGV) Log.v(LOG_TAG,
- "[Dialog] dismiss: not showing, ignore");
- return;
- }
-
- mWindowManager.removeView(mDecor);
- mDecor = null;
- mWindow.closeAllPanels();
- onStop();
- mShowing = false;
-
- sendDismissMessage();
- }
-
- private void sendDismissMessage() {
- if (mDismissMessage != null) {
- // Obtain a new message so this dialog can be re-used
- Message.obtain(mDismissMessage).sendToTarget();
- }
- }
-
- // internal method to make sure mcreated is set properly without requiring
- // users to call through to super in onCreate
- void dispatchOnCreate(Bundle savedInstanceState) {
- onCreate(savedInstanceState);
- mCreated = true;
- }
-
- /**
- * Similar to {@link Activity#onCreate}, you should initialized your dialog
- * in this method, including calling {@link #setContentView}.
- * @param savedInstanceState If this dialog is being reinitalized after a
- * the hosting activity was previously shut down, holds the result from
- * the most recent call to {@link #onSaveInstanceState}, or null if this
- * is the first time.
- */
- protected void onCreate(Bundle savedInstanceState) {
- }
-
- /**
- * Called when the dialog is starting.
- */
- protected void onStart() {
- }
-
- /**
- * Called to tell you that you're stopping.
- */
- protected void onStop() {
- }
-
- private static final String DIALOG_SHOWING_TAG = "android:dialogShowing";
- private static final String DIALOG_HIERARCHY_TAG = "android:dialogHierarchy";
-
- /**
- * Saves the state of the dialog into a bundle.
- *
- * The default implementation saves the state of its view hierarchy, so you'll
- * likely want to call through to super if you override this to save additional
- * state.
- * @return A bundle with the state of the dialog.
- */
- public Bundle onSaveInstanceState() {
- Bundle bundle = new Bundle();
- bundle.putBoolean(DIALOG_SHOWING_TAG, mShowing);
- if (mCreated) {
- bundle.putBundle(DIALOG_HIERARCHY_TAG, mWindow.saveHierarchyState());
- }
- return bundle;
- }
-
- /**
- * Restore the state of the dialog from a previously saved bundle.
- *
- * The default implementation restores the state of the dialog's view
- * hierarchy that was saved in the default implementation of {@link #onSaveInstanceState()},
- * so be sure to call through to super when overriding unless you want to
- * do all restoring of state yourself.
- * @param savedInstanceState The state of the dialog previously saved by
- * {@link #onSaveInstanceState()}.
- */
- public void onRestoreInstanceState(Bundle savedInstanceState) {
- final Bundle dialogHierarchyState = savedInstanceState.getBundle(DIALOG_HIERARCHY_TAG);
- if (dialogHierarchyState == null) {
- // dialog has never been shown, or onCreated, nothing to restore.
- return;
- }
- dispatchOnCreate(savedInstanceState);
- mWindow.restoreHierarchyState(dialogHierarchyState);
- if (savedInstanceState.getBoolean(DIALOG_SHOWING_TAG)) {
- show();
- }
- }
-
- /**
- * Retrieve the current Window for the activity. This can be used to
- * directly access parts of the Window API that are not available
- * through Activity/Screen.
- *
- * @return Window The current window, or null if the activity is not
- * visual.
- */
- public Window getWindow() {
- return mWindow;
- }
-
- /**
- * Call {@link android.view.Window#getCurrentFocus} on the
- * Window if this Activity to return the currently focused view.
- *
- * @return View The current View with focus or null.
- *
- * @see #getWindow
- * @see android.view.Window#getCurrentFocus
- */
- public View getCurrentFocus() {
- return mWindow != null ? mWindow.getCurrentFocus() : null;
- }
-
- /**
- * Finds a view that was identified by the id attribute from the XML that
- * was processed in {@link #onStart}.
- *
- * @param id the identifier of the view to find
- * @return The view if found or null otherwise.
- */
- public View findViewById(int id) {
- return mWindow.findViewById(id);
- }
-
- /**
- * Set the screen content from a layout resource. The resource will be
- * inflated, adding all top-level views to the screen.
- *
- * @param layoutResID Resource ID to be inflated.
- */
- public void setContentView(int layoutResID) {
- mWindow.setContentView(layoutResID);
- }
-
- /**
- * Set the screen content to an explicit view. This view is placed
- * directly into the screen's view hierarchy. It can itself be a complex
- * view hierarhcy.
- *
- * @param view The desired content to display.
- */
- public void setContentView(View view) {
- mWindow.setContentView(view);
- }
-
- /**
- * Set the screen content to an explicit view. This view is placed
- * directly into the screen's view hierarchy. It can itself be a complex
- * view hierarhcy.
- *
- * @param view The desired content to display.
- * @param params Layout parameters for the view.
- */
- public void setContentView(View view, ViewGroup.LayoutParams params) {
- mWindow.setContentView(view, params);
- }
-
- /**
- * Add an additional content view to the screen. Added after any existing
- * ones in the screen -- existing views are NOT removed.
- *
- * @param view The desired content to display.
- * @param params Layout parameters for the view.
- */
- public void addContentView(View view, ViewGroup.LayoutParams params) {
- mWindow.addContentView(view, params);
- }
-
- /**
- * Set the title text for this dialog's window.
- *
- * @param title The new text to display in the title.
- */
- public void setTitle(CharSequence title) {
- mWindow.setTitle(title);
- mWindow.getAttributes().setTitle(title);
- }
-
- /**
- * Set the title text for this dialog's window. The text is retrieved
- * from the resources with the supplied identifier.
- *
- * @param titleId the title's text resource identifier
- */
- public void setTitle(int titleId) {
- setTitle(mContext.getText(titleId));
- }
-
- /**
- * A key was pressed down.
- *
- * <p>If the focused view didn't want this event, this method is called.
- *
- * <p>The default implementation handles KEYCODE_BACK to close the
- * dialog.
- *
- * @see #onKeyUp
- * @see android.view.KeyEvent
- */
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- if (mCancelable) {
- cancel();
- }
- return true;
- }
-
- return false;
- }
-
- /**
- * A key was released.
- *
- * @see #onKeyDown
- * @see KeyEvent
- */
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- return false;
- }
-
- /**
- * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
- * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
- * the event).
- */
- public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
- return false;
- }
-
- /**
- * Called when a touch screen event was not handled by any of the views
- * under it. This is most useful to process touch events that happen outside
- * of your window bounds, where there is no view to receive it.
- *
- * @param event The touch screen event being processed.
- * @return Return true if you have consumed the event, false if you haven't.
- * The default implementation will cancel the dialog when a touch
- * happens outside of the window bounds.
- */
- public boolean onTouchEvent(MotionEvent event) {
- if (mCancelable && mCanceledOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN
- && isOutOfBounds(event)) {
- cancel();
- return true;
- }
-
- return false;
- }
-
- private boolean isOutOfBounds(MotionEvent event) {
- final int x = (int) event.getX();
- final int y = (int) event.getY();
- final int slop = ViewConfiguration.get(mContext).getScaledWindowTouchSlop();
- final View decorView = getWindow().getDecorView();
- return (x < -slop) || (y < -slop)
- || (x > (decorView.getWidth()+slop))
- || (y > (decorView.getHeight()+slop));
- }
-
- /**
- * Called when the trackball was moved and not handled by any of the
- * views inside of the activity. So, for example, if the trackball moves
- * while focus is on a button, you will receive a call here because
- * buttons do not normally do anything with trackball events. The call
- * here happens <em>before</em> trackball movements are converted to
- * DPAD key events, which then get sent back to the view hierarchy, and
- * will be processed at the point for things like focus navigation.
- *
- * @param event The trackball event being processed.
- *
- * @return Return true if you have consumed the event, false if you haven't.
- * The default implementation always returns false.
- */
- public boolean onTrackballEvent(MotionEvent event) {
- return false;
- }
-
- public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
- if (mDecor != null) {
- mWindowManager.updateViewLayout(mDecor, params);
- }
- }
-
- public void onContentChanged() {
- }
-
- public void onWindowFocusChanged(boolean hasFocus) {
- }
-
- /**
- * Called to process key events. You can override this to intercept all
- * key events before they are dispatched to the window. Be sure to call
- * this implementation for key events that should be handled normally.
- *
- * @param event The key event.
- *
- * @return boolean Return true if this event was consumed.
- */
- public boolean dispatchKeyEvent(KeyEvent event) {
- if ((mOnKeyListener != null) && (mOnKeyListener.onKey(this, event.getKeyCode(), event))) {
- return true;
- }
- if (mWindow.superDispatchKeyEvent(event)) {
- return true;
- }
- return event.dispatch(this);
- }
-
- /**
- * Called to process touch screen events. You can override this to
- * intercept all touch screen events before they are dispatched to the
- * window. Be sure to call this implementation for touch screen events
- * that should be handled normally.
- *
- * @param ev The touch screen event.
- *
- * @return boolean Return true if this event was consumed.
- */
- public boolean dispatchTouchEvent(MotionEvent ev) {
- if (mWindow.superDispatchTouchEvent(ev)) {
- return true;
- }
- return onTouchEvent(ev);
- }
-
- /**
- * Called to process trackball events. You can override this to
- * intercept all trackball events before they are dispatched to the
- * window. Be sure to call this implementation for trackball events
- * that should be handled normally.
- *
- * @param ev The trackball event.
- *
- * @return boolean Return true if this event was consumed.
- */
- public boolean dispatchTrackballEvent(MotionEvent ev) {
- if (mWindow.superDispatchTrackballEvent(ev)) {
- return true;
- }
- return onTrackballEvent(ev);
- }
-
- /**
- * @see Activity#onCreatePanelView(int)
- */
- public View onCreatePanelView(int featureId) {
- return null;
- }
-
- /**
- * @see Activity#onCreatePanelMenu(int, Menu)
- */
- public boolean onCreatePanelMenu(int featureId, Menu menu) {
- if (featureId == Window.FEATURE_OPTIONS_PANEL) {
- return onCreateOptionsMenu(menu);
- }
-
- return false;
- }
-
- /**
- * @see Activity#onPreparePanel(int, View, Menu)
- */
- public boolean onPreparePanel(int featureId, View view, Menu menu) {
- if (featureId == Window.FEATURE_OPTIONS_PANEL && menu != null) {
- boolean goforit = onPrepareOptionsMenu(menu);
- return goforit && menu.hasVisibleItems();
- }
- return true;
- }
-
- /**
- * @see Activity#onMenuOpened(int, Menu)
- */
- public boolean onMenuOpened(int featureId, Menu menu) {
- return true;
- }
-
- /**
- * @see Activity#onMenuItemSelected(int, MenuItem)
- */
- public boolean onMenuItemSelected(int featureId, MenuItem item) {
- return false;
- }
-
- /**
- * @see Activity#onPanelClosed(int, Menu)
- */
- public void onPanelClosed(int featureId, Menu menu) {
- }
-
- /**
- * It is usually safe to proxy this call to the owner activity's
- * {@link Activity#onCreateOptionsMenu(Menu)} if the client desires the same
- * menu for this Dialog.
- *
- * @see Activity#onCreateOptionsMenu(Menu)
- * @see #getOwnerActivity()
- */
- public boolean onCreateOptionsMenu(Menu menu) {
- return true;
- }
-
- /**
- * It is usually safe to proxy this call to the owner activity's
- * {@link Activity#onPrepareOptionsMenu(Menu)} if the client desires the
- * same menu for this Dialog.
- *
- * @see Activity#onPrepareOptionsMenu(Menu)
- * @see #getOwnerActivity()
- */
- public boolean onPrepareOptionsMenu(Menu menu) {
- return true;
- }
-
- /**
- * @see Activity#onOptionsItemSelected(MenuItem)
- */
- public boolean onOptionsItemSelected(MenuItem item) {
- return false;
- }
-
- /**
- * @see Activity#onOptionsMenuClosed(Menu)
- */
- public void onOptionsMenuClosed(Menu menu) {
- }
-
- /**
- * @see Activity#openOptionsMenu()
- */
- public void openOptionsMenu() {
- mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null);
- }
-
- /**
- * @see Activity#closeOptionsMenu()
- */
- public void closeOptionsMenu() {
- mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
- }
-
- /**
- * @see Activity#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)
- */
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- }
-
- /**
- * @see Activity#registerForContextMenu(View)
- */
- public void registerForContextMenu(View view) {
- view.setOnCreateContextMenuListener(this);
- }
-
- /**
- * @see Activity#unregisterForContextMenu(View)
- */
- public void unregisterForContextMenu(View view) {
- view.setOnCreateContextMenuListener(null);
- }
-
- /**
- * @see Activity#openContextMenu(View)
- */
- public void openContextMenu(View view) {
- view.showContextMenu();
- }
-
- /**
- * @see Activity#onContextItemSelected(MenuItem)
- */
- public boolean onContextItemSelected(MenuItem item) {
- return false;
- }
-
- /**
- * @see Activity#onContextMenuClosed(Menu)
- */
- public void onContextMenuClosed(Menu menu) {
- }
-
- /**
- * This hook is called when the user signals the desire to start a search.
- */
- public boolean onSearchRequested() {
- // not during dialogs, no.
- return false;
- }
-
-
- /**
- * Request that key events come to this dialog. Use this if your
- * dialog has no views with focus, but the dialog still wants
- * a chance to process key events.
- *
- * @param get true if the dialog should receive key events, false otherwise
- * @see android.view.Window#takeKeyEvents
- */
- public void takeKeyEvents(boolean get) {
- mWindow.takeKeyEvents(get);
- }
-
- /**
- * Enable extended window features. This is a convenience for calling
- * {@link android.view.Window#requestFeature getWindow().requestFeature()}.
- *
- * @param featureId The desired feature as defined in
- * {@link android.view.Window}.
- * @return Returns true if the requested feature is supported and now
- * enabled.
- *
- * @see android.view.Window#requestFeature
- */
- public final boolean requestWindowFeature(int featureId) {
- return getWindow().requestFeature(featureId);
- }
-
- /**
- * Convenience for calling
- * {@link android.view.Window#setFeatureDrawableResource}.
- */
- public final void setFeatureDrawableResource(int featureId, int resId) {
- getWindow().setFeatureDrawableResource(featureId, resId);
- }
-
- /**
- * Convenience for calling
- * {@link android.view.Window#setFeatureDrawableUri}.
- */
- public final void setFeatureDrawableUri(int featureId, Uri uri) {
- getWindow().setFeatureDrawableUri(featureId, uri);
- }
-
- /**
- * Convenience for calling
- * {@link android.view.Window#setFeatureDrawable(int, Drawable)}.
- */
- public final void setFeatureDrawable(int featureId, Drawable drawable) {
- getWindow().setFeatureDrawable(featureId, drawable);
- }
-
- /**
- * Convenience for calling
- * {@link android.view.Window#setFeatureDrawableAlpha}.
- */
- public final void setFeatureDrawableAlpha(int featureId, int alpha) {
- getWindow().setFeatureDrawableAlpha(featureId, alpha);
- }
-
- public LayoutInflater getLayoutInflater() {
- return getWindow().getLayoutInflater();
- }
-
- /**
- * Sets whether this dialog is cancelable with the
- * {@link KeyEvent#KEYCODE_BACK BACK} key.
- */
- public void setCancelable(boolean flag) {
- mCancelable = flag;
- }
-
- /**
- * Sets whether this dialog is canceled when touched outside the window's
- * bounds. If setting to true, the dialog is set to be cancelable if not
- * already set.
- *
- * @param cancel Whether the dialog should be canceled when touched outside
- * the window.
- */
- public void setCanceledOnTouchOutside(boolean cancel) {
- if (cancel && !mCancelable) {
- mCancelable = true;
- }
-
- mCanceledOnTouchOutside = cancel;
- }
-
- /**
- * Cancel the dialog. This is essentially the same as calling {@link #dismiss()}, but it will
- * also call your {@link DialogInterface.OnCancelListener} (if registered).
- */
- public void cancel() {
- if (mCancelMessage != null) {
-
- // Obtain a new message so this dialog can be re-used
- Message.obtain(mCancelMessage).sendToTarget();
- }
- dismiss();
- }
-
- /**
- * Set a listener to be invoked when the dialog is canceled.
- * <p>
- * This will only be invoked when the dialog is canceled, if the creator
- * needs to know when it is dismissed in general, use
- * {@link #setOnDismissListener}.
- *
- * @param listener The {@link DialogInterface.OnCancelListener} to use.
- */
- public void setOnCancelListener(final OnCancelListener listener) {
- if (listener != null) {
- mCancelMessage = mDismissCancelHandler.obtainMessage(CANCEL, listener);
- } else {
- mCancelMessage = null;
- }
- }
-
- /**
- * Set a message to be sent when the dialog is canceled.
- * @param msg The msg to send when the dialog is canceled.
- * @see #setOnCancelListener(android.content.DialogInterface.OnCancelListener)
- */
- public void setCancelMessage(final Message msg) {
- mCancelMessage = msg;
- }
-
- /**
- * Set a listener to be invoked when the dialog is dismissed.
- * @param listener The {@link DialogInterface.OnDismissListener} to use.
- */
- public void setOnDismissListener(final OnDismissListener listener) {
- if (listener != null) {
- mDismissMessage = mDismissCancelHandler.obtainMessage(DISMISS, listener);
- } else {
- mDismissMessage = null;
- }
- }
-
- /**
- * Set a message to be sent when the dialog is dismissed.
- * @param msg The msg to send when the dialog is dismissed.
- */
- public void setDismissMessage(final Message msg) {
- mDismissMessage = msg;
- }
-
- /**
- * By default, this will use the owner Activity's suggested stream type.
- *
- * @see Activity#setVolumeControlStream(int)
- * @see #setOwnerActivity(Activity)
- */
- public final void setVolumeControlStream(int streamType) {
- getWindow().setVolumeControlStream(streamType);
- }
-
- /**
- * @see Activity#getVolumeControlStream()
- */
- public final int getVolumeControlStream() {
- return getWindow().getVolumeControlStream();
- }
-
- /**
- * Sets the callback that will be called if a key is dispatched to the dialog.
- */
- public void setOnKeyListener(final OnKeyListener onKeyListener) {
- mOnKeyListener = onKeyListener;
- }
-
- private static final int DISMISS = 0x43;
- private static final int CANCEL = 0x44;
-
- private Handler mDismissCancelHandler;
-
- private static final class DismissCancelHandler extends Handler {
- private WeakReference<DialogInterface> mDialog;
-
- public DismissCancelHandler(Dialog dialog) {
- mDialog = new WeakReference<DialogInterface>(dialog);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case DISMISS:
- ((OnDismissListener) msg.obj).onDismiss(mDialog.get());
- break;
- case CANCEL:
- ((OnCancelListener) msg.obj).onCancel(mDialog.get());
- break;
- }
- }
- }
-}
diff --git a/core/java/android/app/ExpandableListActivity.java b/core/java/android/app/ExpandableListActivity.java
deleted file mode 100644
index 75dfcae..0000000
--- a/core/java/android/app/ExpandableListActivity.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.database.Cursor;
-import android.os.Bundle;
-import java.util.List;
-import android.view.ContextMenu;
-import android.view.View;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.View.OnCreateContextMenuListener;
-import android.widget.ExpandableListAdapter;
-import android.widget.ExpandableListView;
-import android.widget.SimpleCursorTreeAdapter;
-import android.widget.SimpleExpandableListAdapter;
-import android.widget.AdapterView.AdapterContextMenuInfo;
-
-import java.util.Map;
-
-/**
- * An activity that displays an expandable list of items by binding to a data
- * source implementing the ExpandableListAdapter, and exposes event handlers
- * when the user selects an item.
- * <p>
- * ExpandableListActivity hosts a
- * {@link android.widget.ExpandableListView ExpandableListView} object that can
- * be bound to different data sources that provide a two-levels of data (the
- * top-level is group, and below each group are children). Binding, screen
- * layout, and row layout are discussed in the following sections.
- * <p>
- * <strong>Screen Layout</strong>
- * </p>
- * <p>
- * ExpandableListActivity has a default layout that consists of a single,
- * full-screen, centered expandable list. However, if you desire, you can
- * customize the screen layout by setting your own view layout with
- * setContentView() in onCreate(). To do this, your own view MUST contain an
- * ExpandableListView object with the id "@android:id/list" (or
- * {@link android.R.id#list} if it's in code)
- * <p>
- * Optionally, your custom view can contain another view object of any type to
- * display when the list view is empty. This "empty list" notifier must have an
- * id "android:empty". Note that when an empty view is present, the expandable
- * list view will be hidden when there is no data to display.
- * <p>
- * The following code demonstrates an (ugly) custom screen layout. It has a list
- * with a green background, and an alternate red "no data" message.
- * </p>
- *
- * <pre>
- * &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
- * &lt;LinearLayout
- * android:orientation=&quot;vertical&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;fill_parent&quot;
- * android:paddingLeft=&quot;8&quot;
- * android:paddingRight=&quot;8&quot;&gt;
- *
- * &lt;ExpandableListView id=&quot;android:list&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;fill_parent&quot;
- * android:background=&quot;#00FF00&quot;
- * android:layout_weight=&quot;1&quot;
- * android:drawSelectorOnTop=&quot;false&quot;/&gt;
- *
- * &lt;TextView id=&quot;android:empty&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;fill_parent&quot;
- * android:background=&quot;#FF0000&quot;
- * android:text=&quot;No data&quot;/&gt;
- * &lt;/LinearLayout&gt;
- * </pre>
- *
- * <p>
- * <strong>Row Layout</strong>
- * </p>
- * The {@link ExpandableListAdapter} set in the {@link ExpandableListActivity}
- * via {@link #setListAdapter(ExpandableListAdapter)} provides the {@link View}s
- * for each row. This adapter has separate methods for providing the group
- * {@link View}s and child {@link View}s. There are a couple provided
- * {@link ExpandableListAdapter}s that simplify use of adapters:
- * {@link SimpleCursorTreeAdapter} and {@link SimpleExpandableListAdapter}.
- * <p>
- * With these, you can specify the layout of individual rows for groups and
- * children in the list. These constructor takes a few parameters that specify
- * layout resources for groups and children. It also has additional parameters
- * that let you specify which data field to associate with which object in the
- * row layout resource. The {@link SimpleCursorTreeAdapter} fetches data from
- * {@link Cursor}s and the {@link SimpleExpandableListAdapter} fetches data
- * from {@link List}s of {@link Map}s.
- * </p>
- * <p>
- * Android provides some standard row layout resources. These are in the
- * {@link android.R.layout} class, and have names such as simple_list_item_1,
- * simple_list_item_2, and two_line_list_item. The following layout XML is the
- * source for the resource two_line_list_item, which displays two data
- * fields,one above the other, for each list row.
- * </p>
- *
- * <pre>
- * &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
- * &lt;LinearLayout
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;wrap_content&quot;
- * android:orientation=&quot;vertical&quot;&gt;
- *
- * &lt;TextView id=&quot;text1&quot;
- * android:textSize=&quot;16&quot;
- * android:textStyle=&quot;bold&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;wrap_content&quot;/&gt;
- *
- * &lt;TextView id=&quot;text2&quot;
- * android:textSize=&quot;16&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;wrap_content&quot;/&gt;
- * &lt;/LinearLayout&gt;
- * </pre>
- *
- * <p>
- * You must identify the data bound to each TextView object in this layout. The
- * syntax for this is discussed in the next section.
- * </p>
- * <p>
- * <strong>Binding to Data</strong>
- * </p>
- * <p>
- * You bind the ExpandableListActivity's ExpandableListView object to data using
- * a class that implements the
- * {@link android.widget.ExpandableListAdapter ExpandableListAdapter} interface.
- * Android provides two standard list adapters:
- * {@link android.widget.SimpleExpandableListAdapter SimpleExpandableListAdapter}
- * for static data (Maps), and
- * {@link android.widget.SimpleCursorTreeAdapter SimpleCursorTreeAdapter} for
- * Cursor query results.
- * </p>
- *
- * @see #setListAdapter
- * @see android.widget.ExpandableListView
- */
-public class ExpandableListActivity extends Activity implements
- OnCreateContextMenuListener,
- ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener,
- ExpandableListView.OnGroupExpandListener {
- ExpandableListAdapter mAdapter;
- ExpandableListView mList;
- boolean mFinishedStart = false;
-
- /**
- * Override this to populate the context menu when an item is long pressed. menuInfo
- * will contain a {@link AdapterContextMenuInfo} whose position is a packed position
- * that should be used with {@link ExpandableListView#getPackedPositionType(long)} and
- * the other similar methods.
- * <p>
- * {@inheritDoc}
- */
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- }
-
- /**
- * Override this for receiving callbacks when a child has been clicked.
- * <p>
- * {@inheritDoc}
- */
- public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
- int childPosition, long id) {
- return false;
- }
-
- /**
- * Override this for receiving callbacks when a group has been collapsed.
- */
- public void onGroupCollapse(int groupPosition) {
- }
-
- /**
- * Override this for receiving callbacks when a group has been expanded.
- */
- public void onGroupExpand(int groupPosition) {
- }
-
- /**
- * Ensures the expandable list view has been created before Activity restores all
- * of the view states.
- *
- *@see Activity#onRestoreInstanceState(Bundle)
- */
- @Override
- protected void onRestoreInstanceState(Bundle state) {
- ensureList();
- super.onRestoreInstanceState(state);
- }
-
- /**
- * Updates the screen state (current list and other views) when the
- * content changes.
- *
- * @see Activity#onContentChanged()
- */
- @Override
- public void onContentChanged() {
- super.onContentChanged();
- View emptyView = findViewById(com.android.internal.R.id.empty);
- mList = (ExpandableListView)findViewById(com.android.internal.R.id.list);
- if (mList == null) {
- throw new RuntimeException(
- "Your content must have a ExpandableListView whose id attribute is " +
- "'android.R.id.list'");
- }
- if (emptyView != null) {
- mList.setEmptyView(emptyView);
- }
- mList.setOnChildClickListener(this);
- mList.setOnGroupExpandListener(this);
- mList.setOnGroupCollapseListener(this);
-
- if (mFinishedStart) {
- setListAdapter(mAdapter);
- }
- mFinishedStart = true;
- }
-
- /**
- * Provide the adapter for the expandable list.
- */
- public void setListAdapter(ExpandableListAdapter adapter) {
- synchronized (this) {
- ensureList();
- mAdapter = adapter;
- mList.setAdapter(adapter);
- }
- }
-
- /**
- * Get the activity's expandable list view widget. This can be used to get the selection,
- * set the selection, and many other useful functions.
- *
- * @see ExpandableListView
- */
- public ExpandableListView getExpandableListView() {
- ensureList();
- return mList;
- }
-
- /**
- * Get the ExpandableListAdapter associated with this activity's
- * ExpandableListView.
- */
- public ExpandableListAdapter getExpandableListAdapter() {
- return mAdapter;
- }
-
- private void ensureList() {
- if (mList != null) {
- return;
- }
- setContentView(com.android.internal.R.layout.expandable_list_content);
- }
-
- /**
- * Gets the ID of the currently selected group or child.
- *
- * @return The ID of the currently selected group or child.
- */
- public long getSelectedId() {
- return mList.getSelectedId();
- }
-
- /**
- * Gets the position (in packed position representation) of the currently
- * selected group or child. Use
- * {@link ExpandableListView#getPackedPositionType},
- * {@link ExpandableListView#getPackedPositionGroup}, and
- * {@link ExpandableListView#getPackedPositionChild} to unpack the returned
- * packed position.
- *
- * @return A packed position representation containing the currently
- * selected group or child's position and type.
- */
- public long getSelectedPosition() {
- return mList.getSelectedPosition();
- }
-
- /**
- * Sets the selection to the specified child. If the child is in a collapsed
- * group, the group will only be expanded and child subsequently selected if
- * shouldExpandGroup is set to true, otherwise the method will return false.
- *
- * @param groupPosition The position of the group that contains the child.
- * @param childPosition The position of the child within the group.
- * @param shouldExpandGroup Whether the child's group should be expanded if
- * it is collapsed.
- * @return Whether the selection was successfully set on the child.
- */
- public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) {
- return mList.setSelectedChild(groupPosition, childPosition, shouldExpandGroup);
- }
-
- /**
- * Sets the selection to the specified group.
- * @param groupPosition The position of the group that should be selected.
- */
- public void setSelectedGroup(int groupPosition) {
- mList.setSelectedGroup(groupPosition);
- }
-
-}
-
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
deleted file mode 100644
index cd3701f..0000000
--- a/core/java/android/app/IActivityManager.java
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.app.ActivityManager.MemoryInfo;
-import android.content.ComponentName;
-import android.content.ContentProviderNative;
-import android.content.IContentProvider;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ConfigurationInfo;
-import android.content.pm.IPackageDataObserver;
-import android.content.pm.ProviderInfo;
-import android.content.res.Configuration;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.ParcelFileDescriptor;
-import android.text.TextUtils;
-import android.os.Bundle;
-
-import java.util.List;
-
-/**
- * System private API for talking with the activity manager service. This
- * provides calls from the application back to the activity manager.
- *
- * {@hide}
- */
-public interface IActivityManager extends IInterface {
- public static final int START_DELIVERED_TO_TOP = 3;
- public static final int START_TASK_TO_FRONT = 2;
- public static final int START_RETURN_INTENT_TO_CALLER = 1;
- public static final int START_SUCCESS = 0;
- public static final int START_INTENT_NOT_RESOLVED = -1;
- public static final int START_CLASS_NOT_FOUND = -2;
- public static final int START_FORWARD_AND_REQUEST_CONFLICT = -3;
- public static final int START_PERMISSION_DENIED = -4;
- public int startActivity(IApplicationThread caller,
- Intent intent, String resolvedType, Uri[] grantedUriPermissions,
- int grantedMode, IBinder resultTo, String resultWho, int requestCode,
- boolean onlyIfNeeded, boolean debug) throws RemoteException;
- public boolean startNextMatchingActivity(IBinder callingActivity,
- Intent intent) throws RemoteException;
- public boolean finishActivity(IBinder token, int code, Intent data)
- throws RemoteException;
- public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException;
- public Intent registerReceiver(IApplicationThread caller,
- IIntentReceiver receiver, IntentFilter filter,
- String requiredPermission) throws RemoteException;
- public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException;
- public static final int BROADCAST_SUCCESS = 0;
- public static final int BROADCAST_STICKY_CANT_HAVE_PERMISSION = -1;
- public int broadcastIntent(IApplicationThread caller, Intent intent,
- String resolvedType, IIntentReceiver resultTo, int resultCode,
- String resultData, Bundle map, String requiredPermission,
- boolean serialized, boolean sticky) throws RemoteException;
- public void unbroadcastIntent(IApplicationThread caller, Intent intent) throws RemoteException;
- /* oneway */
- public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle map, boolean abortBroadcast) throws RemoteException;
- public void setPersistent(IBinder token, boolean isPersistent) throws RemoteException;
- public void attachApplication(IApplicationThread app) throws RemoteException;
- /* oneway */
- public void activityIdle(IBinder token) throws RemoteException;
- public void activityPaused(IBinder token, Bundle state) throws RemoteException;
- /* oneway */
- public void activityStopped(IBinder token,
- Bitmap thumbnail, CharSequence description) throws RemoteException;
- /* oneway */
- public void activityDestroyed(IBinder token) throws RemoteException;
- public String getCallingPackage(IBinder token) throws RemoteException;
- public ComponentName getCallingActivity(IBinder token) throws RemoteException;
- public List getTasks(int maxNum, int flags,
- IThumbnailReceiver receiver) throws RemoteException;
- public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
- int flags) throws RemoteException;
- public List getServices(int maxNum, int flags) throws RemoteException;
- public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState()
- throws RemoteException;
- public void moveTaskToFront(int task) throws RemoteException;
- public void moveTaskToBack(int task) throws RemoteException;
- public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) throws RemoteException;
- public void moveTaskBackwards(int task) throws RemoteException;
- public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException;
- public void finishOtherInstances(IBinder token, ComponentName className) throws RemoteException;
- /* oneway */
- public void reportThumbnail(IBinder token,
- Bitmap thumbnail, CharSequence description) throws RemoteException;
- public ContentProviderHolder getContentProvider(IApplicationThread caller,
- String name) throws RemoteException;
- public void removeContentProvider(IApplicationThread caller,
- String name) throws RemoteException;
- public void publishContentProviders(IApplicationThread caller,
- List<ContentProviderHolder> providers) throws RemoteException;
- public ComponentName startService(IApplicationThread caller, Intent service,
- String resolvedType) throws RemoteException;
- public int stopService(IApplicationThread caller, Intent service,
- String resolvedType) throws RemoteException;
- public boolean stopServiceToken(ComponentName className, IBinder token,
- int startId) throws RemoteException;
- public void setServiceForeground(ComponentName className, IBinder token,
- boolean isForeground) throws RemoteException;
- public int bindService(IApplicationThread caller, IBinder token,
- Intent service, String resolvedType,
- IServiceConnection connection, int flags) throws RemoteException;
- public boolean unbindService(IServiceConnection connection) throws RemoteException;
- public void publishService(IBinder token,
- Intent intent, IBinder service) throws RemoteException;
- public void unbindFinished(IBinder token, Intent service,
- boolean doRebind) throws RemoteException;
- /* oneway */
- public void serviceDoneExecuting(IBinder token) throws RemoteException;
- public IBinder peekService(Intent service, String resolvedType) throws RemoteException;
-
- public boolean startInstrumentation(ComponentName className, String profileFile,
- int flags, Bundle arguments, IInstrumentationWatcher watcher)
- throws RemoteException;
- public void finishInstrumentation(IApplicationThread target,
- int resultCode, Bundle results) throws RemoteException;
-
- public Configuration getConfiguration() throws RemoteException;
- public void updateConfiguration(Configuration values) throws RemoteException;
- public void setRequestedOrientation(IBinder token,
- int requestedOrientation) throws RemoteException;
- public int getRequestedOrientation(IBinder token) throws RemoteException;
-
- public ComponentName getActivityClassForToken(IBinder token) throws RemoteException;
- public String getPackageForToken(IBinder token) throws RemoteException;
-
- public static final int INTENT_SENDER_BROADCAST = 1;
- public static final int INTENT_SENDER_ACTIVITY = 2;
- public static final int INTENT_SENDER_ACTIVITY_RESULT = 3;
- public static final int INTENT_SENDER_SERVICE = 4;
- public IIntentSender getIntentSender(int type,
- String packageName, IBinder token, String resultWho,
- int requestCode, Intent intent, String resolvedType, int flags) throws RemoteException;
- public void cancelIntentSender(IIntentSender sender) throws RemoteException;
- public boolean clearApplicationUserData(final String packageName,
- final IPackageDataObserver observer) throws RemoteException;
- public String getPackageForIntentSender(IIntentSender sender) throws RemoteException;
-
- public void setProcessLimit(int max) throws RemoteException;
- public int getProcessLimit() throws RemoteException;
-
- public void setProcessForeground(IBinder token, int pid, boolean isForeground) throws RemoteException;
-
- public int checkPermission(String permission, int pid, int uid)
- throws RemoteException;
-
- public int checkUriPermission(Uri uri, int pid, int uid, int mode)
- throws RemoteException;
- public void grantUriPermission(IApplicationThread caller, String targetPkg,
- Uri uri, int mode) throws RemoteException;
- public void revokeUriPermission(IApplicationThread caller, Uri uri,
- int mode) throws RemoteException;
-
- public void showWaitingForDebugger(IApplicationThread who, boolean waiting)
- throws RemoteException;
-
- public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) throws RemoteException;
-
- public void restartPackage(final String packageName) throws RemoteException;
-
- // Note: probably don't want to allow applications access to these.
- public void goingToSleep() throws RemoteException;
- public void wakingUp() throws RemoteException;
-
- public void unhandledBack() throws RemoteException;
- public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException;
- public void setDebugApp(
- String packageName, boolean waitForDebugger, boolean persistent)
- throws RemoteException;
- public void setAlwaysFinish(boolean enabled) throws RemoteException;
- public void setActivityWatcher(IActivityWatcher watcher)
- throws RemoteException;
-
- public void enterSafeMode() throws RemoteException;
-
- public void noteWakeupAlarm(IIntentSender sender) throws RemoteException;
-
- public boolean killPidsForMemory(int[] pids) throws RemoteException;
-
- public void reportPss(IApplicationThread caller, int pss) throws RemoteException;
-
- // Special low-level communication with activity manager.
- public void startRunning(String pkg, String cls, String action,
- String data) throws RemoteException;
- public void systemReady() throws RemoteException;
- // Returns 1 if the user wants to debug.
- public int handleApplicationError(IBinder app,
- int flags, /* 1 == can debug */
- String tag, String shortMsg, String longMsg,
- byte[] crashData) throws RemoteException;
-
- /*
- * This will deliver the specified signal to all the persistent processes. Currently only
- * SIGUSR1 is delivered. All others are ignored.
- */
- public void signalPersistentProcesses(int signal) throws RemoteException;
- // Retrieve running application processes in the system
- public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses()
- throws RemoteException;
- // Get device configuration
- public ConfigurationInfo getDeviceConfigurationInfo() throws RemoteException;
-
- /*
- * Private non-Binder interfaces
- */
- /* package */ boolean testIsSystemReady();
-
- /** Information you can retrieve about a particular application. */
- public static class ContentProviderHolder implements Parcelable {
- public final ProviderInfo info;
- public final String permissionFailure;
- public IContentProvider provider;
- public boolean noReleaseNeeded;
-
- public ContentProviderHolder(ProviderInfo _info) {
- info = _info;
- permissionFailure = null;
- }
-
- public ContentProviderHolder(ProviderInfo _info,
- String _permissionFailure) {
- info = _info;
- permissionFailure = _permissionFailure;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- info.writeToParcel(dest, 0);
- dest.writeString(permissionFailure);
- if (provider != null) {
- dest.writeStrongBinder(provider.asBinder());
- } else {
- dest.writeStrongBinder(null);
- }
- dest.writeInt(noReleaseNeeded ? 1:0);
- }
-
- public static final Parcelable.Creator<ContentProviderHolder> CREATOR
- = new Parcelable.Creator<ContentProviderHolder>() {
- public ContentProviderHolder createFromParcel(Parcel source) {
- return new ContentProviderHolder(source);
- }
-
- public ContentProviderHolder[] newArray(int size) {
- return new ContentProviderHolder[size];
- }
- };
-
- private ContentProviderHolder(Parcel source) {
- info = ProviderInfo.CREATOR.createFromParcel(source);
- permissionFailure = source.readString();
- provider = ContentProviderNative.asInterface(
- source.readStrongBinder());
- noReleaseNeeded = source.readInt() != 0;
- }
- };
-
- String descriptor = "android.app.IActivityManager";
-
- // Please keep these transaction codes the same -- they are also
- // sent by C++ code.
- int START_RUNNING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
- int HANDLE_APPLICATION_ERROR_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+1;
- int START_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+2;
- int UNHANDLED_BACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+3;
- int OPEN_CONTENT_URI_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+4;
-
- // Remaining non-native transaction codes.
- int FINISH_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+10;
- int REGISTER_RECEIVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+11;
- int UNREGISTER_RECEIVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+12;
- int BROADCAST_INTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+13;
- int UNBROADCAST_INTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+14;
- int FINISH_RECEIVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+15;
- int ATTACH_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+16;
- int ACTIVITY_IDLE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+17;
- int ACTIVITY_PAUSED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+18;
- int ACTIVITY_STOPPED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+19;
- int GET_CALLING_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+20;
- int GET_CALLING_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+21;
- int GET_TASKS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+22;
- int MOVE_TASK_TO_FRONT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+23;
- int MOVE_TASK_TO_BACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+24;
- int MOVE_TASK_BACKWARDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+25;
- int GET_TASK_FOR_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+26;
- int REPORT_THUMBNAIL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+27;
- int GET_CONTENT_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+28;
- int PUBLISH_CONTENT_PROVIDERS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+29;
- int SET_PERSISTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+30;
- int FINISH_SUB_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+31;
- int SYSTEM_READY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+32;
- int START_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+33;
- int STOP_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+34;
- int BIND_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+35;
- int UNBIND_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+36;
- int PUBLISH_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+37;
- int FINISH_OTHER_INSTANCES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+38;
- int GOING_TO_SLEEP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+39;
- int WAKING_UP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+40;
- int SET_DEBUG_APP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+41;
- int SET_ALWAYS_FINISH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+42;
- int START_INSTRUMENTATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+43;
- int FINISH_INSTRUMENTATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+44;
- int GET_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+45;
- int UPDATE_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+46;
- int STOP_SERVICE_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+47;
- int GET_ACTIVITY_CLASS_FOR_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+48;
- int GET_PACKAGE_FOR_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+49;
- int SET_PROCESS_LIMIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+50;
- int GET_PROCESS_LIMIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+51;
- int CHECK_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+52;
- int CHECK_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+53;
- int GRANT_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+54;
- int REVOKE_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+55;
- int SET_ACTIVITY_WATCHER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+56;
- int SHOW_WAITING_FOR_DEBUGGER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+57;
- int SIGNAL_PERSISTENT_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+58;
- int GET_RECENT_TASKS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+59;
- int SERVICE_DONE_EXECUTING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+60;
- int ACTIVITY_DESTROYED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+61;
- int GET_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+62;
- int CANCEL_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+63;
- int GET_PACKAGE_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+64;
- int ENTER_SAFE_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+65;
- int START_NEXT_MATCHING_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+66;
- int NOTE_WAKEUP_ALARM_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+67;
- int REMOVE_CONTENT_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+68;
- int SET_REQUESTED_ORIENTATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+69;
- int GET_REQUESTED_ORIENTATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+70;
- int UNBIND_FINISHED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+71;
- int SET_PROCESS_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+72;
- int SET_SERVICE_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+73;
- int MOVE_ACTIVITY_TASK_TO_BACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+74;
- int GET_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+75;
- int GET_PROCESSES_IN_ERROR_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+76;
- int CLEAR_APP_DATA_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+77;
- int RESTART_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+78;
- int KILL_PIDS_FOR_MEMORY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+79;
- int GET_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+80;
- int REPORT_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+81;
- int GET_RUNNING_APP_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+82;
- int GET_DEVICE_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+83;
- int PEEK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+84;
-}
diff --git a/core/java/android/app/IActivityPendingResult.aidl b/core/java/android/app/IActivityPendingResult.aidl
deleted file mode 100644
index e8eebf1..0000000
--- a/core/java/android/app/IActivityPendingResult.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/* //device/java/android/android/app/IActivityPendingResult.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.app;
-
-import android.os.Bundle;
-
-/** @hide */
-interface IActivityPendingResult
-{
- boolean sendResult(int code, String data, in Bundle ex);
-}
-
diff --git a/core/java/android/app/IActivityWatcher.aidl b/core/java/android/app/IActivityWatcher.aidl
deleted file mode 100644
index f13a385..0000000
--- a/core/java/android/app/IActivityWatcher.aidl
+++ /dev/null
@@ -1,55 +0,0 @@
-/* //device/java/android/android/app/IInstrumentationWatcher.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.app;
-
-import android.content.Intent;
-
-/**
- * Testing interface to monitor what is happening in the activity manager
- * while tests are running. Not for normal application development.
- * {@hide}
- */
-interface IActivityWatcher
-{
- /**
- * The system is trying to start an activity. Return true to allow
- * it to be started as normal, or false to cancel/reject this activity.
- */
- boolean activityStarting(in Intent intent, String pkg);
-
- /**
- * The system is trying to return to an activity. Return true to allow
- * it to be resumed as normal, or false to cancel/reject this activity.
- */
- boolean activityResuming(String pkg);
-
- /**
- * An application process has crashed (in Java). Return true for the
- * normal error recovery (app crash dialog) to occur, false to kill
- * it immediately.
- */
- boolean appCrashed(String processName, int pid, String shortMsg,
- String longMsg, in byte[] crashData);
-
- /**
- * An application process is not responding. Return 0 to show the "app
- * not responding" dialog, 1 to continue waiting, or -1 to kill it
- * immediately.
- */
- int appNotResponding(String processName, int pid, String processStats);
-}
diff --git a/core/java/android/app/IAlarmManager.aidl b/core/java/android/app/IAlarmManager.aidl
deleted file mode 100755
index cb42236..0000000
--- a/core/java/android/app/IAlarmManager.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/* //device/java/android/android/app/IAlarmManager.aidl
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-package android.app;
-
-import android.app.PendingIntent;
-
-/**
- * System private API for talking with the alarm manager service.
- *
- * {@hide}
- */
-interface IAlarmManager {
- void set(int type, long triggerAtTime, in PendingIntent operation);
- void setRepeating(int type, long triggerAtTime, long interval, in PendingIntent operation);
- void setInexactRepeating(int type, long triggerAtTime, long interval, in PendingIntent operation);
- void setTimeZone(String zone);
- void remove(in PendingIntent operation);
-}
-
-
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
deleted file mode 100644
index 47476b5..0000000
--- a/core/java/android/app/IApplicationThread.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ServiceInfo;
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.os.IInterface;
-
-import java.io.FileDescriptor;
-import java.util.List;
-import java.util.Map;
-
-/**
- * System private API for communicating with the application. This is given to
- * the activity manager by an application when it starts up, for the activity
- * manager to tell the application about things it needs to do.
- *
- * {@hide}
- */
-public interface IApplicationThread extends IInterface {
- void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,
- int configChanges) throws RemoteException;
- void scheduleStopActivity(IBinder token, boolean showWindow,
- int configChanges) throws RemoteException;
- void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;
- void scheduleResumeActivity(IBinder token, boolean isForward) throws RemoteException;
- void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
- void scheduleLaunchActivity(Intent intent, IBinder token,
- ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
- List<Intent> pendingNewIntents, boolean notResumed, boolean isForward)
- throws RemoteException;
- void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,
- List<Intent> pendingNewIntents, int configChanges,
- boolean notResumed) throws RemoteException;
- void scheduleNewIntent(List<Intent> intent, IBinder token) throws RemoteException;
- void scheduleDestroyActivity(IBinder token, boolean finished,
- int configChanges) throws RemoteException;
- void scheduleReceiver(Intent intent, ActivityInfo info, int resultCode,
- String data, Bundle extras, boolean sync) throws RemoteException;
- void scheduleCreateService(IBinder token, ServiceInfo info) throws RemoteException;
- void scheduleBindService(IBinder token,
- Intent intent, boolean rebind) throws RemoteException;
- void scheduleUnbindService(IBinder token,
- Intent intent) throws RemoteException;
- void scheduleServiceArgs(IBinder token, int startId, Intent args) throws RemoteException;
- void scheduleStopService(IBinder token) throws RemoteException;
- static final int DEBUG_OFF = 0;
- static final int DEBUG_ON = 1;
- static final int DEBUG_WAIT = 2;
- void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers,
- ComponentName testName, String profileName, Bundle testArguments,
- IInstrumentationWatcher testWatcher, int debugMode, Configuration config, Map<String,
- IBinder> services) throws RemoteException;
- void scheduleExit() throws RemoteException;
- void requestThumbnail(IBinder token) throws RemoteException;
- void scheduleConfigurationChanged(Configuration config) throws RemoteException;
- void updateTimeZone() throws RemoteException;
- void processInBackground() throws RemoteException;
- void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args)
- throws RemoteException;
- void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
- int resultCode, String data, Bundle extras, boolean ordered)
- throws RemoteException;
- void scheduleLowMemory() throws RemoteException;
- void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException;
- void requestPss() throws RemoteException;
-
- String descriptor = "android.app.IApplicationThread";
-
- int SCHEDULE_PAUSE_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
- int SCHEDULE_STOP_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+2;
- int SCHEDULE_WINDOW_VISIBILITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+3;
- int SCHEDULE_RESUME_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+4;
- int SCHEDULE_SEND_RESULT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+5;
- int SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+6;
- int SCHEDULE_NEW_INTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+7;
- int SCHEDULE_FINISH_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+8;
- int SCHEDULE_RECEIVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+9;
- int SCHEDULE_CREATE_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+10;
- int SCHEDULE_STOP_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+11;
- int BIND_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+12;
- int SCHEDULE_EXIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+13;
- int REQUEST_THUMBNAIL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+14;
- int SCHEDULE_CONFIGURATION_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+15;
- int SCHEDULE_SERVICE_ARGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+16;
- int UPDATE_TIME_ZONE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+17;
- int PROCESS_IN_BACKGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+18;
- int SCHEDULE_BIND_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+19;
- int SCHEDULE_UNBIND_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+20;
- int DUMP_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+21;
- int SCHEDULE_REGISTERED_RECEIVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+22;
- int SCHEDULE_LOW_MEMORY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+23;
- int SCHEDULE_ACTIVITY_CONFIGURATION_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+24;
- int SCHEDULE_RELAUNCH_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+25;
- int REQUEST_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+26;
-}
diff --git a/core/java/android/app/IInstrumentationWatcher.aidl b/core/java/android/app/IInstrumentationWatcher.aidl
deleted file mode 100644
index 405a3d8..0000000
--- a/core/java/android/app/IInstrumentationWatcher.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/* //device/java/android/android/app/IInstrumentationWatcher.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.app;
-
-import android.content.ComponentName;
-import android.os.Bundle;
-
-/** @hide */
-oneway interface IInstrumentationWatcher
-{
- void instrumentationStatus(in ComponentName name, int resultCode,
- in Bundle results);
- void instrumentationFinished(in ComponentName name, int resultCode,
- in Bundle results);
-}
-
diff --git a/core/java/android/app/IIntentReceiver.aidl b/core/java/android/app/IIntentReceiver.aidl
deleted file mode 100755
index 5f5d0eb..0000000
--- a/core/java/android/app/IIntentReceiver.aidl
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-package android.app;
-
-import android.content.Intent;
-import android.os.Bundle;
-
-/**
- * System private API for dispatching intent broadcasts. This is given to the
- * activity manager as part of registering for an intent broadcasts, and is
- * called when it receives intents.
- *
- * {@hide}
- */
-oneway interface IIntentReceiver {
- void performReceive(in Intent intent, int resultCode,
- String data, in Bundle extras, boolean ordered);
-}
-
diff --git a/core/java/android/app/IIntentSender.aidl b/core/java/android/app/IIntentSender.aidl
deleted file mode 100644
index 53e135a..0000000
--- a/core/java/android/app/IIntentSender.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/* //device/java/android/android/app/IActivityPendingResult.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.app;
-
-import android.app.IIntentReceiver;
-import android.content.Intent;
-
-/** @hide */
-interface IIntentSender {
- int send(int code, in Intent intent, String resolvedType,
- IIntentReceiver finishedReceiver);
-}
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
deleted file mode 100644
index c1035b6..0000000
--- a/core/java/android/app/INotificationManager.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/* //device/java/android/android/app/INotificationManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.app;
-
-import android.app.ITransientNotification;
-import android.app.Notification;
-import android.content.Intent;
-
-/** {@hide} */
-interface INotificationManager
-{
- void enqueueNotification(String pkg, int id, in Notification notification, inout int[] idReceived);
- void cancelNotification(String pkg, int id);
- void cancelAllNotifications(String pkg);
-
- void enqueueToast(String pkg, ITransientNotification callback, int duration);
- void cancelToast(String pkg, ITransientNotification callback);
-}
-
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
deleted file mode 100644
index 6c3617a..0000000
--- a/core/java/android/app/ISearchManager.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Copyright (c) 2007, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.ComponentName;
-import android.server.search.SearchableInfo;
-
-/** @hide */
-interface ISearchManager {
- SearchableInfo getSearchableInfo(in ComponentName launchActivity, boolean globalSearch);
-}
diff --git a/core/java/android/app/IServiceConnection.aidl b/core/java/android/app/IServiceConnection.aidl
deleted file mode 100644
index 6804071..0000000
--- a/core/java/android/app/IServiceConnection.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/* //device/java/android/android/app/IServiceConnection.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.app;
-
-import android.content.ComponentName;
-
-/** @hide */
-oneway interface IServiceConnection {
- void connected(in ComponentName name, IBinder service);
-}
-
diff --git a/core/java/android/app/IStatusBar.aidl b/core/java/android/app/IStatusBar.aidl
deleted file mode 100644
index c64fa50..0000000
--- a/core/java/android/app/IStatusBar.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Copyright (c) 2007, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-/** @hide */
-interface IStatusBar
-{
- void activate();
- void deactivate();
- void toggle();
- void disable(int what, IBinder token, String pkg);
- IBinder addIcon(String slot, String iconPackage, int iconId, int iconLevel);
- void updateIcon(IBinder key, String slot, String iconPackage, int iconId, int iconLevel);
- void removeIcon(IBinder key);
-}
diff --git a/core/java/android/app/IThumbnailReceiver.aidl b/core/java/android/app/IThumbnailReceiver.aidl
deleted file mode 100755
index 7943f2c..0000000
--- a/core/java/android/app/IThumbnailReceiver.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/* //device/java/android/android/app/IThumbnailReceiver.aidl
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-package android.app;
-
-import android.graphics.Bitmap;
-
-/**
- * System private API for receiving updated thumbnails from a checkpoint.
- *
- * {@hide}
- */
-oneway interface IThumbnailReceiver {
- void newThumbnail(int id, in Bitmap thumbnail, CharSequence description);
- void finished();
-}
-
diff --git a/core/java/android/app/ITransientNotification.aidl b/core/java/android/app/ITransientNotification.aidl
deleted file mode 100644
index 35b53a4..0000000
--- a/core/java/android/app/ITransientNotification.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/* //device/java/android/android/app/ITransientNotification.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.app;
-
-/** @hide */
-oneway interface ITransientNotification {
- void show();
- void hide();
-}
-
diff --git a/core/java/android/app/IWallpaperService.aidl b/core/java/android/app/IWallpaperService.aidl
deleted file mode 100644
index a332b1a..0000000
--- a/core/java/android/app/IWallpaperService.aidl
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Copyright (c) 2008, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.os.ParcelFileDescriptor;
-import android.app.IWallpaperServiceCallback;
-
-/** @hide */
-interface IWallpaperService {
-
- /**
- * Set the wallpaper.
- */
- ParcelFileDescriptor setWallpaper();
-
- /**
- * Get the wallpaper.
- */
- ParcelFileDescriptor getWallpaper(IWallpaperServiceCallback cb);
-
- /**
- * Clear the wallpaper.
- */
- void clearWallpaper();
-
- /**
- * Sets the dimension hint for the wallpaper. These hints indicate the desired
- * minimum width and height for the wallpaper.
- */
- void setDimensionHints(in int width, in int height);
-
- /**
- * Returns the desired minimum width for the wallpaper.
- */
- int getWidthHint();
-
- /**
- * Returns the desired minimum height for the wallpaper.
- */
- int getHeightHint();
-}
diff --git a/core/java/android/app/IWallpaperServiceCallback.aidl b/core/java/android/app/IWallpaperServiceCallback.aidl
deleted file mode 100644
index 6086f40..0000000
--- a/core/java/android/app/IWallpaperServiceCallback.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-/**
- * Callback interface used by IWallpaperService to send asynchronous
- * notifications back to its clients. Note that this is a
- * one-way interface so the server does not block waiting for the client.
- *
- * @hide
- */
-oneway interface IWallpaperServiceCallback {
- /**
- * Called when the wallpaper has changed
- */
- void onWallpaperChanged();
-}
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
deleted file mode 100644
index f6a28b2..0000000
--- a/core/java/android/app/Instrumentation.java
+++ /dev/null
@@ -1,1613 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.ActivityNotFoundException;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.Debug;
-import android.os.IBinder;
-import android.os.MessageQueue;
-import android.os.Process;
-import android.os.SystemClock;
-import android.os.ServiceManager;
-import android.util.AndroidRuntimeException;
-import android.util.Config;
-import android.util.Log;
-import android.view.IWindowManager;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.ViewConfiguration;
-import android.view.Window;
-import android.view.inputmethod.InputMethodManager;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-
-/**
- * Base class for implementing application instrumentation code. When running
- * with instrumentation turned on, this class will be instantiated for you
- * before any of the application code, allowing you to monitor all of the
- * interaction the system has with the application. An Instrumentation
- * implementation is described to the system through an AndroidManifest.xml's
- * &lt;instrumentation&gt; tag.
- */
-public class Instrumentation {
- /**
- * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
- * identifies the class that is writing the report. This can be used to provide more structured
- * logging or reporting capabilities in the IInstrumentationWatcher.
- */
- public static final String REPORT_KEY_IDENTIFIER = "id";
- /**
- * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
- * identifies a string which can simply be printed to the output stream. Using these streams
- * provides a "pretty printer" version of the status & final packets. Any bundles including
- * this key should also include the complete set of raw key/value pairs, so that the
- * instrumentation can also be launched, and results collected, by an automated system.
- */
- public static final String REPORT_KEY_STREAMRESULT = "stream";
-
- private static final String TAG = "Instrumentation";
-
- private final Object mSync = new Object();
- private ActivityThread mThread = null;
- private MessageQueue mMessageQueue = null;
- private Context mInstrContext;
- private Context mAppContext;
- private ComponentName mComponent;
- private Thread mRunner;
- private List<ActivityWaiter> mWaitingActivities;
- private List<ActivityMonitor> mActivityMonitors;
- private IInstrumentationWatcher mWatcher;
- private long mPreCpuTime;
- private long mStart;
- private boolean mAutomaticPerformanceSnapshots = false;
- private Bundle mPrePerfMetrics = new Bundle();
- private Bundle mPerfMetrics = new Bundle();
-
- public Instrumentation() {
- }
-
- /**
- * Called when the instrumentation is starting, before any application code
- * has been loaded. Usually this will be implemented to simply call
- * {@link #start} to begin the instrumentation thread, which will then
- * continue execution in {@link #onStart}.
- *
- * <p>If you do not need your own thread -- that is you are writing your
- * instrumentation to be completely asynchronous (returning to the event
- * loop so that the application can run), you can simply begin your
- * instrumentation here, for example call {@link Context#startActivity} to
- * begin the appropriate first activity of the application.
- *
- * @param arguments Any additional arguments that were supplied when the
- * instrumentation was started.
- */
- public void onCreate(Bundle arguments) {
- }
-
- /**
- * Create and start a new thread in which to run instrumentation. This new
- * thread will call to {@link #onStart} where you can implement the
- * instrumentation.
- */
- public void start() {
- if (mRunner != null) {
- throw new RuntimeException("Instrumentation already started");
- }
- mRunner = new InstrumentationThread("Instr: " + getClass().getName());
- mRunner.start();
- }
-
- /**
- * Method where the instrumentation thread enters execution. This allows
- * you to run your instrumentation code in a separate thread than the
- * application, so that it can perform blocking operation such as
- * {@link #sendKeySync} or {@link #startActivitySync}.
- *
- * <p>You will typically want to call finish() when this function is done,
- * to end your instrumentation.
- */
- public void onStart() {
- }
-
- /**
- * This is called whenever the system captures an unhandled exception that
- * was thrown by the application. The default implementation simply
- * returns false, allowing normal system handling of the exception to take
- * place.
- *
- * @param obj The client object that generated the exception. May be an
- * Application, Activity, BroadcastReceiver, Service, or null.
- * @param e The exception that was thrown.
- *
- * @return To allow normal system exception process to occur, return false.
- * If true is returned, the system will proceed as if the exception
- * didn't happen.
- */
- public boolean onException(Object obj, Throwable e) {
- return false;
- }
-
- /**
- * Provide a status report about the application.
- *
- * @param resultCode Current success/failure of instrumentation.
- * @param results Any results to send back to the code that started the instrumentation.
- */
- public void sendStatus(int resultCode, Bundle results) {
- if (mWatcher != null) {
- try {
- mWatcher.instrumentationStatus(mComponent, resultCode, results);
- }
- catch (RemoteException e) {
- mWatcher = null;
- }
- }
- }
-
- /**
- * Terminate instrumentation of the application. This will cause the
- * application process to exit, removing this instrumentation from the next
- * time the application is started.
- *
- * @param resultCode Overall success/failure of instrumentation.
- * @param results Any results to send back to the code that started the
- * instrumentation.
- */
- public void finish(int resultCode, Bundle results) {
- if (mAutomaticPerformanceSnapshots) {
- endPerformanceSnapshot();
- }
- if (mPerfMetrics != null) {
- results.putAll(mPerfMetrics);
- }
- mThread.finishInstrumentation(resultCode, results);
- }
-
- public void setAutomaticPerformanceSnapshots() {
- mAutomaticPerformanceSnapshots = true;
- }
-
- public void startPerformanceSnapshot() {
- mStart = 0;
- if (!isProfiling()) {
- // Add initial binder counts
- Bundle binderCounts = getBinderCounts();
- for (String key: binderCounts.keySet()) {
- addPerfMetricLong("pre_" + key, binderCounts.getLong(key));
- }
-
- // Force a GC and zero out the performance counters. Do this
- // before reading initial CPU/wall-clock times so we don't include
- // the cost of this setup in our final metrics.
- startAllocCounting();
-
- // Record CPU time up to this point, and start timing. Note: this
- // must happen at the end of this method, otherwise the timing will
- // include noise.
- mStart = SystemClock.uptimeMillis();
- mPreCpuTime = Process.getElapsedCpuTime();
- }
- }
-
- public void endPerformanceSnapshot() {
- if (!isProfiling()) {
- // Stop the timing. This must be done first before any other counting is stopped.
- long cpuTime = Process.getElapsedCpuTime();
- long duration = SystemClock.uptimeMillis();
-
- stopAllocCounting();
-
- long nativeMax = Debug.getNativeHeapSize() / 1024;
- long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
- long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
-
- Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
- Debug.getMemoryInfo(memInfo);
-
- Runtime runtime = Runtime.getRuntime();
-
- long dalvikMax = runtime.totalMemory() / 1024;
- long dalvikFree = runtime.freeMemory() / 1024;
- long dalvikAllocated = dalvikMax - dalvikFree;
-
- // Add final binder counts
- Bundle binderCounts = getBinderCounts();
- for (String key: binderCounts.keySet()) {
- addPerfMetricLong(key, binderCounts.getLong(key));
- }
-
- // Add alloc counts
- Bundle allocCounts = getAllocCounts();
- for (String key: allocCounts.keySet()) {
- addPerfMetricLong(key, allocCounts.getLong(key));
- }
-
- addPerfMetricLong("execution_time", duration - mStart);
- addPerfMetricLong("pre_cpu_time", mPreCpuTime);
- addPerfMetricLong("cpu_time", cpuTime - mPreCpuTime);
-
- addPerfMetricLong("native_size", nativeMax);
- addPerfMetricLong("native_allocated", nativeAllocated);
- addPerfMetricLong("native_free", nativeFree);
- addPerfMetricInt("native_pss", memInfo.nativePss);
- addPerfMetricInt("native_private_dirty", memInfo.nativePrivateDirty);
- addPerfMetricInt("native_shared_dirty", memInfo.nativeSharedDirty);
-
- addPerfMetricLong("java_size", dalvikMax);
- addPerfMetricLong("java_allocated", dalvikAllocated);
- addPerfMetricLong("java_free", dalvikFree);
- addPerfMetricInt("java_pss", memInfo.dalvikPss);
- addPerfMetricInt("java_private_dirty", memInfo.dalvikPrivateDirty);
- addPerfMetricInt("java_shared_dirty", memInfo.dalvikSharedDirty);
-
- addPerfMetricInt("other_pss", memInfo.otherPss);
- addPerfMetricInt("other_private_dirty", memInfo.otherPrivateDirty);
- addPerfMetricInt("other_shared_dirty", memInfo.otherSharedDirty);
-
- }
- }
-
- private void addPerfMetricLong(String key, long value) {
- mPerfMetrics.putLong("performance." + key, value);
- }
-
- private void addPerfMetricInt(String key, int value) {
- mPerfMetrics.putInt("performance." + key, value);
- }
-
- /**
- * Called when the instrumented application is stopping, after all of the
- * normal application cleanup has occurred.
- */
- public void onDestroy() {
- }
-
- /**
- * Return the Context of this instrumentation's package. Note that this is
- * often different than the Context of the application being
- * instrumentated, since the instrumentation code often lives is a
- * different package than that of the application it is running against.
- * See {@link #getTargetContext} to retrieve a Context for the target
- * application.
- *
- * @return The instrumentation's package context.
- *
- * @see #getTargetContext
- */
- public Context getContext() {
- return mInstrContext;
- }
-
- /**
- * Returns complete component name of this instrumentation.
- *
- * @return Returns the complete component name for this instrumentation.
- */
- public ComponentName getComponentName() {
- return mComponent;
- }
-
- /**
- * Return a Context for the target application being instrumented. Note
- * that this is often different than the Context of the instrumentation
- * code, since the instrumentation code often lives is a different package
- * than that of the application it is running against. See
- * {@link #getContext} to retrieve a Context for the instrumentation code.
- *
- * @return A Context in the target application.
- *
- * @see #getContext
- */
- public Context getTargetContext() {
- return mAppContext;
- }
-
- /**
- * Check whether this instrumentation was started with profiling enabled.
- *
- * @return Returns true if profiling was enabled when starting, else false.
- */
- public boolean isProfiling() {
- return mThread.isProfiling();
- }
-
- /**
- * This method will start profiling if isProfiling() returns true. You should
- * only call this method if you set the handleProfiling attribute in the
- * manifest file for this Instrumentation to true.
- */
- public void startProfiling() {
- if (mThread.isProfiling()) {
- File file = new File(mThread.getProfileFilePath());
- file.getParentFile().mkdirs();
- Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
- }
- }
-
- /**
- * Stops profiling if isProfiling() returns true.
- */
- public void stopProfiling() {
- if (mThread.isProfiling()) {
- Debug.stopMethodTracing();
- }
- }
-
- /**
- * Force the global system in or out of touch mode. This can be used if
- * your instrumentation relies on the UI being in one more or the other
- * when it starts.
- *
- * @param inTouch Set to true to be in touch mode, false to be in
- * focus mode.
- */
- public void setInTouchMode(boolean inTouch) {
- try {
- IWindowManager.Stub.asInterface(
- ServiceManager.getService("window")).setInTouchMode(inTouch);
- } catch (RemoteException e) {
- // Shouldn't happen!
- }
- }
-
- /**
- * Schedule a callback for when the application's main thread goes idle
- * (has no more events to process).
- *
- * @param recipient Called the next time the thread's message queue is
- * idle.
- */
- public void waitForIdle(Runnable recipient) {
- mMessageQueue.addIdleHandler(new Idler(recipient));
- mThread.getHandler().post(new EmptyRunnable());
- }
-
- /**
- * Synchronously wait for the application to be idle. Can not be called
- * from the main application thread -- use {@link #start} to execute
- * instrumentation in its own thread.
- */
- public void waitForIdleSync() {
- validateNotAppThread();
- Idler idler = new Idler(null);
- mMessageQueue.addIdleHandler(idler);
- mThread.getHandler().post(new EmptyRunnable());
- idler.waitForIdle();
- }
-
- /**
- * Execute a call on the application's main thread, blocking until it is
- * complete. Useful for doing things that are not thread-safe, such as
- * looking at or modifying the view hierarchy.
- *
- * @param runner The code to run on the main thread.
- */
- public void runOnMainSync(Runnable runner) {
- validateNotAppThread();
- SyncRunnable sr = new SyncRunnable(runner);
- mThread.getHandler().post(sr);
- sr.waitForComplete();
- }
-
- /**
- * Start a new activity and wait for it to begin running before returning.
- * In addition to being synchronous, this method as some semantic
- * differences from the standard {@link Context#startActivity} call: the
- * activity component is resolved before talking with the activity manager
- * (its class name is specified in the Intent that this method ultimately
- * starts), and it does not allow you to start activities that run in a
- * different process. In addition, if the given Intent resolves to
- * multiple activities, instead of displaying a dialog for the user to
- * select an activity, an exception will be thrown.
- *
- * <p>The function returns as soon as the activity goes idle following the
- * call to its {@link Activity#onCreate}. Generally this means it has gone
- * through the full initialization including {@link Activity#onResume} and
- * drawn and displayed its initial window.
- *
- * @param intent Description of the activity to start.
- *
- * @see Context#startActivity
- */
- public Activity startActivitySync(Intent intent) {
- validateNotAppThread();
-
- synchronized (mSync) {
- intent = new Intent(intent);
-
- ActivityInfo ai = intent.resolveActivityInfo(
- getTargetContext().getPackageManager(), 0);
- if (ai == null) {
- throw new RuntimeException("Unable to resolve activity for: " + intent);
- }
- if (!ai.applicationInfo.processName.equals(
- getTargetContext().getPackageName())) {
- // todo: if this intent is ambiguous, look here to see if
- // there is a single match that is in our package.
- throw new RuntimeException("Intent resolved to different package "
- + ai.applicationInfo.packageName + ": "
- + intent);
- }
-
- intent.setComponent(new ComponentName(
- ai.applicationInfo.packageName, ai.name));
- final ActivityWaiter aw = new ActivityWaiter(intent);
-
- if (mWaitingActivities == null) {
- mWaitingActivities = new ArrayList();
- }
- mWaitingActivities.add(aw);
-
- getTargetContext().startActivity(intent);
-
- do {
- try {
- mSync.wait();
- } catch (InterruptedException e) {
- }
- } while (mWaitingActivities.contains(aw));
-
- return aw.activity;
- }
- }
-
- /**
- * Information about a particular kind of Intent that is being monitored.
- * An instance of this class is added to the
- * current instrumentation through {@link #addMonitor}; after being added,
- * when a new activity is being started the monitor will be checked and, if
- * matching, its hit count updated and (optionally) the call stopped and a
- * canned result returned.
- *
- * <p>An ActivityMonitor can also be used to look for the creation of an
- * activity, through the {@link #waitForActivity} method. This will return
- * after a matching activity has been created with that activity object.
- */
- public static class ActivityMonitor {
- private final IntentFilter mWhich;
- private final String mClass;
- private final ActivityResult mResult;
- private final boolean mBlock;
-
-
- // This is protected by 'Instrumentation.this.mSync'.
- /*package*/ int mHits = 0;
-
- // This is protected by 'this'.
- /*package*/ Activity mLastActivity = null;
-
- /**
- * Create a new ActivityMonitor that looks for a particular kind of
- * intent to be started.
- *
- * @param which The set of intents this monitor is responsible for.
- * @param result A canned result to return if the monitor is hit; can
- * be null.
- * @param block Controls whether the monitor should block the activity
- * start (returning its canned result) or let the call
- * proceed.
- *
- * @see Instrumentation#addMonitor
- */
- public ActivityMonitor(
- IntentFilter which, ActivityResult result, boolean block) {
- mWhich = which;
- mClass = null;
- mResult = result;
- mBlock = block;
- }
-
- /**
- * Create a new ActivityMonitor that looks for a specific activity
- * class to be started.
- *
- * @param cls The activity class this monitor is responsible for.
- * @param result A canned result to return if the monitor is hit; can
- * be null.
- * @param block Controls whether the monitor should block the activity
- * start (returning its canned result) or let the call
- * proceed.
- *
- * @see Instrumentation#addMonitor
- */
- public ActivityMonitor(
- String cls, ActivityResult result, boolean block) {
- mWhich = null;
- mClass = cls;
- mResult = result;
- mBlock = block;
- }
-
- /**
- * Retrieve the filter associated with this ActivityMonitor.
- */
- public final IntentFilter getFilter() {
- return mWhich;
- }
-
- /**
- * Retrieve the result associated with this ActivityMonitor, or null if
- * none.
- */
- public final ActivityResult getResult() {
- return mResult;
- }
-
- /**
- * Check whether this monitor blocks activity starts (not allowing the
- * actual activity to run) or allows them to execute normally.
- */
- public final boolean isBlocking() {
- return mBlock;
- }
-
- /**
- * Retrieve the number of times the monitor has been hit so far.
- */
- public final int getHits() {
- return mHits;
- }
-
- /**
- * Retrieve the most recent activity class that was seen by this
- * monitor.
- */
- public final Activity getLastActivity() {
- return mLastActivity;
- }
-
- /**
- * Block until an Activity is created that matches this monitor,
- * returning the resulting activity.
- *
- * @return Activity
- */
- public final Activity waitForActivity() {
- synchronized (this) {
- while (mLastActivity == null) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
- Activity res = mLastActivity;
- mLastActivity = null;
- return res;
- }
- }
-
- /**
- * Block until an Activity is created that matches this monitor,
- * returning the resulting activity or till the timeOut period expires.
- * If the timeOut expires before the activity is started, return null.
- *
- * @param timeOut Time to wait before the activity is created.
- *
- * @return Activity
- */
- public final Activity waitForActivityWithTimeout(long timeOut) {
- synchronized (this) {
- try {
- wait(timeOut);
- } catch (InterruptedException e) {
- }
- if (mLastActivity == null) {
- return null;
- } else {
- Activity res = mLastActivity;
- mLastActivity = null;
- return res;
- }
- }
- }
-
- final boolean match(Context who,
- Activity activity,
- Intent intent) {
- synchronized (this) {
- if (mWhich != null
- && mWhich.match(who.getContentResolver(), intent,
- true, "Instrumentation") < 0) {
- return false;
- }
- if (mClass != null) {
- String cls = null;
- if (activity != null) {
- cls = activity.getClass().getName();
- } else if (intent.getComponent() != null) {
- cls = intent.getComponent().getClassName();
- }
- if (cls == null || !mClass.equals(cls)) {
- return false;
- }
- }
- if (activity != null) {
- mLastActivity = activity;
- notifyAll();
- }
- return true;
- }
- }
- }
-
- /**
- * Add a new {@link ActivityMonitor} that will be checked whenever an
- * activity is started. The monitor is added
- * after any existing ones; the monitor will be hit only if none of the
- * existing monitors can themselves handle the Intent.
- *
- * @param monitor The new ActivityMonitor to see.
- *
- * @see #addMonitor(IntentFilter, ActivityResult, boolean)
- * @see #checkMonitorHit
- */
- public void addMonitor(ActivityMonitor monitor) {
- synchronized (mSync) {
- if (mActivityMonitors == null) {
- mActivityMonitors = new ArrayList();
- }
- mActivityMonitors.add(monitor);
- }
- }
-
- /**
- * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
- * creates an intent filter matching {@link ActivityMonitor} for you and
- * returns it.
- *
- * @param filter The set of intents this monitor is responsible for.
- * @param result A canned result to return if the monitor is hit; can
- * be null.
- * @param block Controls whether the monitor should block the activity
- * start (returning its canned result) or let the call
- * proceed.
- *
- * @return The newly created and added activity monitor.
- *
- * @see #addMonitor(ActivityMonitor)
- * @see #checkMonitorHit
- */
- public ActivityMonitor addMonitor(
- IntentFilter filter, ActivityResult result, boolean block) {
- ActivityMonitor am = new ActivityMonitor(filter, result, block);
- addMonitor(am);
- return am;
- }
-
- /**
- * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
- * creates a class matching {@link ActivityMonitor} for you and returns it.
- *
- * @param cls The activity class this monitor is responsible for.
- * @param result A canned result to return if the monitor is hit; can
- * be null.
- * @param block Controls whether the monitor should block the activity
- * start (returning its canned result) or let the call
- * proceed.
- *
- * @return The newly created and added activity monitor.
- *
- * @see #addMonitor(ActivityMonitor)
- * @see #checkMonitorHit
- */
- public ActivityMonitor addMonitor(
- String cls, ActivityResult result, boolean block) {
- ActivityMonitor am = new ActivityMonitor(cls, result, block);
- addMonitor(am);
- return am;
- }
-
- /**
- * Test whether an existing {@link ActivityMonitor} has been hit. If the
- * monitor has been hit at least <var>minHits</var> times, then it will be
- * removed from the activity monitor list and true returned. Otherwise it
- * is left as-is and false is returned.
- *
- * @param monitor The ActivityMonitor to check.
- * @param minHits The minimum number of hits required.
- *
- * @return True if the hit count has been reached, else false.
- *
- * @see #addMonitor
- */
- public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) {
- waitForIdleSync();
- synchronized (mSync) {
- if (monitor.getHits() < minHits) {
- return false;
- }
- mActivityMonitors.remove(monitor);
- }
- return true;
- }
-
- /**
- * Wait for an existing {@link ActivityMonitor} to be hit. Once the
- * monitor has been hit, it is removed from the activity monitor list and
- * the first created Activity object that matched it is returned.
- *
- * @param monitor The ActivityMonitor to wait for.
- *
- * @return The Activity object that matched the monitor.
- */
- public Activity waitForMonitor(ActivityMonitor monitor) {
- Activity activity = monitor.waitForActivity();
- synchronized (mSync) {
- mActivityMonitors.remove(monitor);
- }
- return activity;
- }
-
- /**
- * Wait for an existing {@link ActivityMonitor} to be hit till the timeout
- * expires. Once the monitor has been hit, it is removed from the activity
- * monitor list and the first created Activity object that matched it is
- * returned. If the timeout expires, a null object is returned.
- *
- * @param monitor The ActivityMonitor to wait for.
- * @param timeOut The timeout value in secs.
- *
- * @return The Activity object that matched the monitor.
- */
- public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) {
- Activity activity = monitor.waitForActivityWithTimeout(timeOut);
- synchronized (mSync) {
- mActivityMonitors.remove(monitor);
- }
- return activity;
- }
-
- /**
- * Remove an {@link ActivityMonitor} that was previously added with
- * {@link #addMonitor}.
- *
- * @param monitor The monitor to remove.
- *
- * @see #addMonitor
- */
- public void removeMonitor(ActivityMonitor monitor) {
- synchronized (mSync) {
- mActivityMonitors.remove(monitor);
- }
- }
-
- /**
- * Execute a particular menu item.
- *
- * @param targetActivity The activity in question.
- * @param id The identifier associated with the menu item.
- * @param flag Additional flags, if any.
- * @return Whether the invocation was successful (for example, it could be
- * false if item is disabled).
- */
- public boolean invokeMenuActionSync(Activity targetActivity,
- int id, int flag) {
- class MenuRunnable implements Runnable {
- private final Activity activity;
- private final int identifier;
- private final int flags;
- boolean returnValue;
-
- public MenuRunnable(Activity _activity, int _identifier,
- int _flags) {
- activity = _activity;
- identifier = _identifier;
- flags = _flags;
- }
-
- public void run() {
- Window win = activity.getWindow();
-
- returnValue = win.performPanelIdentifierAction(
- Window.FEATURE_OPTIONS_PANEL,
- identifier,
- flags);
- }
-
- }
- MenuRunnable mr = new MenuRunnable(targetActivity, id, flag);
- runOnMainSync(mr);
- return mr.returnValue;
- }
-
- /**
- * Show the context menu for the currently focused view and executes a
- * particular context menu item.
- *
- * @param targetActivity The activity in question.
- * @param id The identifier associated with the context menu item.
- * @param flag Additional flags, if any.
- * @return Whether the invocation was successful (for example, it could be
- * false if item is disabled).
- */
- public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) {
- validateNotAppThread();
-
- // Bring up context menu for current focus.
- // It'd be nice to do this through code, but currently ListView depends on
- // long press to set metadata for its selected child
-
- final KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
- sendKeySync(downEvent);
-
- // Need to wait for long press
- waitForIdleSync();
- try {
- Thread.sleep(ViewConfiguration.getLongPressTimeout());
- } catch (InterruptedException e) {
- Log.e(TAG, "Could not sleep for long press timeout", e);
- return false;
- }
-
- final KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
- sendKeySync(upEvent);
-
- // Wait for context menu to appear
- waitForIdleSync();
-
- class ContextMenuRunnable implements Runnable {
- private final Activity activity;
- private final int identifier;
- private final int flags;
- boolean returnValue;
-
- public ContextMenuRunnable(Activity _activity, int _identifier,
- int _flags) {
- activity = _activity;
- identifier = _identifier;
- flags = _flags;
- }
-
- public void run() {
- Window win = activity.getWindow();
- returnValue = win.performContextMenuIdentifierAction(
- identifier,
- flags);
- }
-
- }
-
- ContextMenuRunnable cmr = new ContextMenuRunnable(targetActivity, id, flag);
- runOnMainSync(cmr);
- return cmr.returnValue;
- }
-
- /**
- * Sends the key events corresponding to the text to the app being
- * instrumented.
- *
- * @param text The text to be sent.
- */
- public void sendStringSync(String text) {
- if (text == null) {
- return;
- }
- KeyCharacterMap keyCharacterMap =
- KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD);
-
- KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray());
-
- if (events != null) {
- for (int i = 0; i < events.length; i++) {
- sendKeySync(events[i]);
- }
- }
- }
-
- /**
- * Send a key event to the currently focused window/view and wait for it to
- * be processed. Finished at some point after the recipient has returned
- * from its event processing, though it may <em>not</em> have completely
- * finished reacting from the event -- for example, if it needs to update
- * its display as a result, it may still be in the process of doing that.
- *
- * @param event The event to send to the current focus.
- */
- public void sendKeySync(KeyEvent event) {
- validateNotAppThread();
- try {
- (IWindowManager.Stub.asInterface(ServiceManager.getService("window")))
- .injectKeyEvent(event, true);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Sends an up and down key event sync to the currently focused window.
- *
- * @param key The integer keycode for the event.
- */
- public void sendKeyDownUpSync(int key) {
- sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key));
- sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key));
- }
-
- /**
- * Higher-level method for sending both the down and up key events for a
- * particular character key code. Equivalent to creating both KeyEvent
- * objects by hand and calling {@link #sendKeySync}. The event appears
- * as if it came from keyboard 0, the built in one.
- *
- * @param keyCode The key code of the character to send.
- */
- public void sendCharacterSync(int keyCode) {
- sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
- sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
- }
-
- /**
- * Dispatch a pointer event. Finished at some point after the recipient has
- * returned from its event processing, though it may <em>not</em> have
- * completely finished reacting from the event -- for example, if it needs
- * to update its display as a result, it may still be in the process of
- * doing that.
- *
- * @param event A motion event describing the pointer action. (As noted in
- * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
- * {@link SystemClock#uptimeMillis()} as the timebase.
- */
- public void sendPointerSync(MotionEvent event) {
- validateNotAppThread();
- try {
- (IWindowManager.Stub.asInterface(ServiceManager.getService("window")))
- .injectPointerEvent(event, true);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Dispatch a trackball event. Finished at some point after the recipient has
- * returned from its event processing, though it may <em>not</em> have
- * completely finished reacting from the event -- for example, if it needs
- * to update its display as a result, it may still be in the process of
- * doing that.
- *
- * @param event A motion event describing the trackball action. (As noted in
- * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
- * {@link SystemClock#uptimeMillis()} as the timebase.
- */
- public void sendTrackballEventSync(MotionEvent event) {
- validateNotAppThread();
- try {
- (IWindowManager.Stub.asInterface(ServiceManager.getService("window")))
- .injectTrackballEvent(event, true);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Perform instantiation of the process's {@link Application} object. The
- * default implementation provides the normal system behavior.
- *
- * @param cl The ClassLoader with which to instantiate the object.
- * @param className The name of the class implementing the Application
- * object.
- * @param context The context to initialize the application with
- *
- * @return The newly instantiated Application object.
- */
- public Application newApplication(ClassLoader cl, String className, Context context)
- throws InstantiationException, IllegalAccessException,
- ClassNotFoundException {
- return newApplication(cl.loadClass(className), context);
- }
-
- /**
- * Perform instantiation of the process's {@link Application} object. The
- * default implementation provides the normal system behavior.
- *
- * @param clazz The class used to create an Application object from.
- * @param context The context to initialize the application with
- *
- * @return The newly instantiated Application object.
- */
- static public Application newApplication(Class<?> clazz, Context context)
- throws InstantiationException, IllegalAccessException,
- ClassNotFoundException {
- Application app = (Application)clazz.newInstance();
- app.attach(context);
- return app;
- }
-
- /**
- * Perform calling of the application's {@link Application#onCreate}
- * method. The default implementation simply calls through to that method.
- *
- * @param app The application being created.
- */
- public void callApplicationOnCreate(Application app) {
- app.onCreate();
- }
-
- /**
- * Perform instantiation of an {@link Activity} object. This method is intended for use with
- * unit tests, such as android.test.ActivityUnitTestCase. The activity will be useable
- * locally but will be missing some of the linkages necessary for use within the sytem.
- *
- * @param clazz The Class of the desired Activity
- * @param context The base context for the activity to use
- * @param token The token for this activity to communicate with
- * @param application The application object (if any)
- * @param intent The intent that started this Activity
- * @param info ActivityInfo from the manifest
- * @param title The title, typically retrieved from the ActivityInfo record
- * @param parent The parent Activity (if any)
- * @param id The embedded Id (if any)
- * @param lastNonConfigurationInstance Arbitrary object that will be
- * available via {@link Activity#getLastNonConfigurationInstance()
- * Activity.getLastNonConfigurationInstance()}.
- * @return Returns the instantiated activity
- * @throws InstantiationException
- * @throws IllegalAccessException
- */
- public Activity newActivity(Class<?> clazz, Context context,
- IBinder token, Application application, Intent intent, ActivityInfo info,
- CharSequence title, Activity parent, String id,
- Object lastNonConfigurationInstance) throws InstantiationException,
- IllegalAccessException {
- Activity activity = (Activity)clazz.newInstance();
- ActivityThread aThread = null;
- activity.attach(context, aThread, this, token, application, intent, info, title,
- parent, id, lastNonConfigurationInstance, new Configuration());
- return activity;
- }
-
- /**
- * Perform instantiation of the process's {@link Activity} object. The
- * default implementation provides the normal system behavior.
- *
- * @param cl The ClassLoader with which to instantiate the object.
- * @param className The name of the class implementing the Activity
- * object.
- * @param intent The Intent object that specified the activity class being
- * instantiated.
- *
- * @return The newly instantiated Activity object.
- */
- public Activity newActivity(ClassLoader cl, String className,
- Intent intent)
- throws InstantiationException, IllegalAccessException,
- ClassNotFoundException {
- return (Activity)cl.loadClass(className).newInstance();
- }
-
- /**
- * Perform calling of an activity's {@link Activity#onCreate}
- * method. The default implementation simply calls through to that method.
- *
- * @param activity The activity being created.
- * @param icicle The previously frozen state (or null) to pass through to
- * onCreate().
- */
- public void callActivityOnCreate(Activity activity, Bundle icicle) {
- if (mWaitingActivities != null) {
- synchronized (mSync) {
- final int N = mWaitingActivities.size();
- for (int i=0; i<N; i++) {
- final ActivityWaiter aw = mWaitingActivities.get(i);
- final Intent intent = aw.intent;
- if (intent.filterEquals(activity.getIntent())) {
- aw.activity = activity;
- mMessageQueue.addIdleHandler(new ActivityGoing(aw));
- }
- }
- }
- }
-
- activity.onCreate(icicle);
-
- if (mActivityMonitors != null) {
- synchronized (mSync) {
- final int N = mActivityMonitors.size();
- for (int i=0; i<N; i++) {
- final ActivityMonitor am = mActivityMonitors.get(i);
- am.match(activity, activity, activity.getIntent());
- }
- }
- }
- }
-
- public void callActivityOnDestroy(Activity activity) {
- if (mWaitingActivities != null) {
- synchronized (mSync) {
- final int N = mWaitingActivities.size();
- for (int i=0; i<N; i++) {
- final ActivityWaiter aw = mWaitingActivities.get(i);
- final Intent intent = aw.intent;
- if (intent.filterEquals(activity.getIntent())) {
- aw.activity = activity;
- mMessageQueue.addIdleHandler(new ActivityGoing(aw));
- }
- }
- }
- }
-
- activity.onDestroy();
-
- if (mActivityMonitors != null) {
- synchronized (mSync) {
- final int N = mActivityMonitors.size();
- for (int i=0; i<N; i++) {
- final ActivityMonitor am = mActivityMonitors.get(i);
- am.match(activity, activity, activity.getIntent());
- }
- }
- }
- }
-
- /**
- * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
- * method. The default implementation simply calls through to that method.
- *
- * @param activity The activity being restored.
- * @param savedInstanceState The previously saved state being restored.
- */
- public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState) {
- activity.performRestoreInstanceState(savedInstanceState);
- }
-
- /**
- * Perform calling of an activity's {@link Activity#onPostCreate} method.
- * The default implementation simply calls through to that method.
- *
- * @param activity The activity being created.
- * @param icicle The previously frozen state (or null) to pass through to
- * onPostCreate().
- */
- public void callActivityOnPostCreate(Activity activity, Bundle icicle) {
- activity.onPostCreate(icicle);
- }
-
- /**
- * Perform calling of an activity's {@link Activity#onNewIntent}
- * method. The default implementation simply calls through to that method.
- *
- * @param activity The activity receiving a new Intent.
- * @param intent The new intent being received.
- */
- public void callActivityOnNewIntent(Activity activity, Intent intent) {
- activity.onNewIntent(intent);
- }
-
- /**
- * Perform calling of an activity's {@link Activity#onStart}
- * method. The default implementation simply calls through to that method.
- *
- * @param activity The activity being started.
- */
- public void callActivityOnStart(Activity activity) {
- activity.onStart();
- }
-
- /**
- * Perform calling of an activity's {@link Activity#onRestart}
- * method. The default implementation simply calls through to that method.
- *
- * @param activity The activity being restarted.
- */
- public void callActivityOnRestart(Activity activity) {
- activity.onRestart();
- }
-
- /**
- * Perform calling of an activity's {@link Activity#onResume} method. The
- * default implementation simply calls through to that method.
- *
- * @param activity The activity being resumed.
- */
- public void callActivityOnResume(Activity activity) {
- activity.onResume();
-
- if (mActivityMonitors != null) {
- synchronized (mSync) {
- final int N = mActivityMonitors.size();
- for (int i=0; i<N; i++) {
- final ActivityMonitor am = mActivityMonitors.get(i);
- am.match(activity, activity, activity.getIntent());
- }
- }
- }
- }
-
- /**
- * Perform calling of an activity's {@link Activity#onStop}
- * method. The default implementation simply calls through to that method.
- *
- * @param activity The activity being stopped.
- */
- public void callActivityOnStop(Activity activity) {
- activity.onStop();
- }
-
- /**
- * Perform calling of an activity's {@link Activity#onPause} method. The
- * default implementation simply calls through to that method.
- *
- * @param activity The activity being saved.
- * @param outState The bundle to pass to the call.
- */
- public void callActivityOnSaveInstanceState(Activity activity, Bundle outState) {
- activity.performSaveInstanceState(outState);
- }
-
- /**
- * Perform calling of an activity's {@link Activity#onPause} method. The
- * default implementation simply calls through to that method.
- *
- * @param activity The activity being paused.
- */
- public void callActivityOnPause(Activity activity) {
- activity.performPause();
- }
-
- /**
- * Perform calling of an activity's {@link Activity#onUserLeaveHint} method.
- * The default implementation simply calls through to that method.
- *
- * @param activity The activity being notified that the user has navigated away
- */
- public void callActivityOnUserLeaving(Activity activity) {
- activity.performUserLeaving();
- }
-
- /*
- * Starts allocation counting. This triggers a gc and resets the counts.
- */
- public void startAllocCounting() {
- // Before we start trigger a GC and reset the debug counts. Run the
- // finalizers and another GC before starting and stopping the alloc
- // counts. This will free up any objects that were just sitting around
- // waiting for their finalizers to be run.
- Runtime.getRuntime().gc();
- Runtime.getRuntime().runFinalization();
- Runtime.getRuntime().gc();
-
- Debug.resetAllCounts();
-
- // start the counts
- Debug.startAllocCounting();
- }
-
- /*
- * Stops allocation counting.
- */
- public void stopAllocCounting() {
- Runtime.getRuntime().gc();
- Runtime.getRuntime().runFinalization();
- Runtime.getRuntime().gc();
- Debug.stopAllocCounting();
- }
-
- /**
- * If Results already contains Key, it appends Value to the key's ArrayList
- * associated with the key. If the key doesn't already exist in results, it
- * adds the key/value pair to results.
- */
- private void addValue(String key, int value, Bundle results) {
- if (results.containsKey(key)) {
- List<Integer> list = results.getIntegerArrayList(key);
- if (list != null) {
- list.add(value);
- }
- } else {
- ArrayList<Integer> list = new ArrayList<Integer>();
- list.add(value);
- results.putIntegerArrayList(key, list);
- }
- }
-
- /**
- * Returns a bundle with the current results from the allocation counting.
- */
- public Bundle getAllocCounts() {
- Bundle results = new Bundle();
- results.putLong("global_alloc_count", Debug.getGlobalAllocCount());
- results.putLong("global_alloc_size", Debug.getGlobalAllocSize());
- results.putLong("global_freed_count", Debug.getGlobalFreedCount());
- results.putLong("global_freed_size", Debug.getGlobalFreedSize());
- results.putLong("gc_invocation_count", Debug.getGlobalGcInvocationCount());
- return results;
- }
-
- /**
- * Returns a bundle with the counts for various binder counts for this process. Currently the only two that are
- * reported are the number of send and the number of received transactions.
- */
- public Bundle getBinderCounts() {
- Bundle results = new Bundle();
- results.putLong("sent_transactions", Debug.getBinderSentTransactions());
- results.putLong("received_transactions", Debug.getBinderReceivedTransactions());
- return results;
- }
-
- /**
- * Description of a Activity execution result to return to the original
- * activity.
- */
- public static final class ActivityResult {
- /**
- * Create a new activity result. See {@link Activity#setResult} for
- * more information.
- *
- * @param resultCode The result code to propagate back to the
- * originating activity, often RESULT_CANCELED or RESULT_OK
- * @param resultData The data to propagate back to the originating
- * activity.
- */
- public ActivityResult(int resultCode, Intent resultData) {
- mResultCode = resultCode;
- mResultData = resultData;
- }
-
- /**
- * Retrieve the result code contained in this result.
- */
- public int getResultCode() {
- return mResultCode;
- }
-
- /**
- * Retrieve the data contained in this result.
- */
- public Intent getResultData() {
- return mResultData;
- }
-
- private final int mResultCode;
- private final Intent mResultData;
- }
-
- /**
- * Execute a startActivity call made by the application. The default
- * implementation takes care of updating any active {@link ActivityMonitor}
- * objects and dispatches this call to the system activity manager; you can
- * override this to watch for the application to start an activity, and
- * modify what happens when it does.
- *
- * <p>This method returns an {@link ActivityResult} object, which you can
- * use when intercepting application calls to avoid performing the start
- * activity action but still return the result the application is
- * expecting. To do this, override this method to catch the call to start
- * activity so that it returns a new ActivityResult containing the results
- * you would like the application to see, and don't call up to the super
- * class. Note that an application is only expecting a result if
- * <var>requestCode</var> is &gt;= 0.
- *
- * <p>This method throws {@link android.content.ActivityNotFoundException}
- * if there was no Activity found to run the given Intent.
- *
- * @param who The Context from which the activity is being started.
- * @param contextThread The main thread of the Context from which the activity
- * is being started.
- * @param token Internal token identifying to the system who is starting
- * the activity; may be null.
- * @param target Which activity is perform the start (and thus receiving
- * any result); may be null if this call is not being made
- * from an activity.
- * @param intent The actual Intent to start.
- * @param requestCode Identifier for this request's result; less than zero
- * if the caller is not expecting a result.
- *
- * @return To force the return of a particular result, return an
- * ActivityResult object containing the desired data; otherwise
- * return null. The default implementation always returns null.
- *
- * @throws android.content.ActivityNotFoundException
- *
- * @see Activity#startActivity(Intent)
- * @see Activity#startActivityForResult(Intent, int)
- * @see Activity#startActivityFromChild
- *
- * {@hide}
- */
- public ActivityResult execStartActivity(
- Context who, IBinder contextThread, IBinder token, Activity target,
- Intent intent, int requestCode) {
- IApplicationThread whoThread = (IApplicationThread) contextThread;
- if (mActivityMonitors != null) {
- synchronized (mSync) {
- final int N = mActivityMonitors.size();
- for (int i=0; i<N; i++) {
- final ActivityMonitor am = mActivityMonitors.get(i);
- if (am.match(who, null, intent)) {
- am.mHits++;
- if (am.isBlocking()) {
- return requestCode >= 0 ? am.getResult() : null;
- }
- break;
- }
- }
- }
- }
- try {
- int result = ActivityManagerNative.getDefault()
- .startActivity(whoThread, intent,
- intent.resolveTypeIfNeeded(who.getContentResolver()),
- null, 0, token, target != null ? target.mEmbeddedID : null,
- requestCode, false, false);
- checkStartActivityResult(result, intent);
- } catch (RemoteException e) {
- }
- return null;
- }
-
- /*package*/ final void init(ActivityThread thread,
- Context instrContext, Context appContext, ComponentName component,
- IInstrumentationWatcher watcher) {
- mThread = thread;
- mMessageQueue = mThread.getLooper().myQueue();
- mInstrContext = instrContext;
- mAppContext = appContext;
- mComponent = component;
- mWatcher = watcher;
- }
-
- /*package*/ static void checkStartActivityResult(int res, Intent intent) {
- if (res >= IActivityManager.START_SUCCESS) {
- return;
- }
-
- switch (res) {
- case IActivityManager.START_INTENT_NOT_RESOLVED:
- case IActivityManager.START_CLASS_NOT_FOUND:
- if (intent.getComponent() != null)
- throw new ActivityNotFoundException(
- "Unable to find explicit activity class "
- + intent.getComponent().toShortString()
- + "; have you declared this activity in your AndroidManifest.xml?");
- throw new ActivityNotFoundException(
- "No Activity found to handle " + intent);
- case IActivityManager.START_PERMISSION_DENIED:
- throw new SecurityException("Not allowed to start activity "
- + intent);
- case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
- throw new AndroidRuntimeException(
- "FORWARD_RESULT_FLAG used while also requesting a result");
- default:
- throw new AndroidRuntimeException("Unknown error code "
- + res + " when starting " + intent);
- }
- }
-
- private final void validateNotAppThread() {
- if (ActivityThread.currentActivityThread() != null) {
- throw new RuntimeException(
- "This method can not be called from the main application thread");
- }
- }
-
- private final class InstrumentationThread extends Thread {
- public InstrumentationThread(String name) {
- super(name);
- }
- public void run() {
- IActivityManager am = ActivityManagerNative.getDefault();
- try {
- Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
- } catch (RuntimeException e) {
- Log.w(TAG, "Exception setting priority of instrumentation thread "
- + Process.myTid(), e);
- }
- if (mAutomaticPerformanceSnapshots) {
- startPerformanceSnapshot();
- }
- onStart();
- }
- }
-
- private static final class EmptyRunnable implements Runnable {
- public void run() {
- }
- }
-
- private static final class SyncRunnable implements Runnable {
- private final Runnable mTarget;
- private boolean mComplete;
-
- public SyncRunnable(Runnable target) {
- mTarget = target;
- }
-
- public void run() {
- mTarget.run();
- synchronized (this) {
- mComplete = true;
- notifyAll();
- }
- }
-
- public void waitForComplete() {
- synchronized (this) {
- while (!mComplete) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
- }
- }
- }
-
- private static final class ActivityWaiter {
- public final Intent intent;
- public Activity activity;
-
- public ActivityWaiter(Intent _intent) {
- intent = _intent;
- }
- }
-
- private final class ActivityGoing implements MessageQueue.IdleHandler {
- private final ActivityWaiter mWaiter;
-
- public ActivityGoing(ActivityWaiter waiter) {
- mWaiter = waiter;
- }
-
- public final boolean queueIdle() {
- synchronized (mSync) {
- mWaitingActivities.remove(mWaiter);
- mSync.notifyAll();
- }
- return false;
- }
- }
-
- private static final class Idler implements MessageQueue.IdleHandler {
- private final Runnable mCallback;
- private boolean mIdle;
-
- public Idler(Runnable callback) {
- mCallback = callback;
- mIdle = false;
- }
-
- public final boolean queueIdle() {
- if (mCallback != null) {
- mCallback.run();
- }
- synchronized (this) {
- mIdle = true;
- notifyAll();
- }
- return false;
- }
-
- public void waitForIdle() {
- synchronized (this) {
- while (!mIdle) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
- }
- }
- }
-}
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
deleted file mode 100644
index 0c07553..0000000
--- a/core/java/android/app/KeyguardManager.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.Context;
-import android.os.Binder;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.os.ServiceManager;
-import android.view.IWindowManager;
-import android.view.IOnKeyguardExitResult;
-
-/**
- * Class that can be used to lock and unlock the keyboard. Get an instance of this
- * class by calling {@link android.content.Context#getSystemService(java.lang.String)}
- * with argument {@link android.content.Context#KEYGUARD_SERVICE}. The
- * Actual class to control the keyboard locking is
- * {@link android.app.KeyguardManager.KeyguardLock}.
- */
-public class KeyguardManager {
- private IWindowManager mWM;
-
- /**
- * Handle returned by {@link KeyguardManager#newKeyguardLock} that allows
- * you to disable / reenable the keyguard.
- */
- public class KeyguardLock {
- private IBinder mToken = new Binder();
- private String mTag;
-
- KeyguardLock(String tag) {
- mTag = tag;
- }
-
- /**
- * Disable the keyguard from showing. If the keyguard is currently
- * showing, hide it. The keyguard will be prevented from showing again
- * until {@link #reenableKeyguard()} is called.
- *
- * A good place to call this is from {@link android.app.Activity#onResume()}
- *
- * @see #reenableKeyguard()
- */
- public void disableKeyguard() {
- try {
- mWM.disableKeyguard(mToken, mTag);
- } catch (RemoteException ex) {
- }
- }
-
- /**
- * Reenable the keyguard. The keyguard will reappear if the previous
- * call to {@link #disableKeyguard()} caused it it to be hidden.
- *
- * A good place to call this is from {@link android.app.Activity#onPause()}
- *
- * @see #disableKeyguard()
- */
- public void reenableKeyguard() {
- try {
- mWM.reenableKeyguard(mToken);
- } catch (RemoteException ex) {
- }
- }
- }
-
- /**
- * Callback passed to {@link KeyguardManager#exitKeyguardSecurely} to notify
- * caller of result.
- */
- public interface OnKeyguardExitResult {
-
- /**
- * @param success True if the user was able to authenticate, false if
- * not.
- */
- void onKeyguardExitResult(boolean success);
- }
-
-
- KeyguardManager() {
- mWM = IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
- }
-
- /**
- * Enables you to lock or unlock the keyboard. Get an instance of this class by
- * calling {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- * This class is wrapped by {@link android.app.KeyguardManager KeyguardManager}.
- * @param tag A tag that informally identifies who you are (for debugging who
- * is disabling he keyguard).
- *
- * @return A {@link KeyguardLock} handle to use to disable and reenable the
- * keyguard.
- */
- public KeyguardLock newKeyguardLock(String tag) {
- return new KeyguardLock(tag);
- }
-
- /**
- * If keyguard screen is showing or in restricted key input mode (i.e. in
- * keyguard password emergency screen). When in such mode, certain keys,
- * such as the Home key and the right soft keys, don't work.
- *
- * @return true if in keyguard restricted input mode.
- *
- * @see android.view.WindowManagerPolicy#inKeyguardRestrictedKeyInputMode
- */
- public boolean inKeyguardRestrictedInputMode() {
- try {
- return mWM.inKeyguardRestrictedInputMode();
- } catch (RemoteException ex) {
- return false;
- }
- }
-
- /**
- * Exit the keyguard securely. The use case for this api is that, after
- * disabling the keyguard, your app, which was granted permission to
- * disable the keyguard and show a limited amount of information deemed
- * safe without the user getting past the keyguard, needs to navigate to
- * something that is not safe to view without getting past the keyguard.
- *
- * This will, if the keyguard is secure, bring up the unlock screen of
- * the keyguard.
- *
- * @param callback Let's you know whether the operation was succesful and
- * it is safe to launch anything that would normally be considered safe
- * once the user has gotten past the keyguard.
- */
- public void exitKeyguardSecurely(final OnKeyguardExitResult callback) {
- try {
- mWM.exitKeyguardSecurely(new IOnKeyguardExitResult.Stub() {
- public void onKeyguardExitResult(boolean success) throws RemoteException {
- callback.onKeyguardExitResult(success);
- }
- });
- } catch (RemoteException e) {
-
- }
- }
-}
diff --git a/core/java/android/app/LauncherActivity.java b/core/java/android/app/LauncherActivity.java
deleted file mode 100644
index d6fcbb1..0000000
--- a/core/java/android/app/LauncherActivity.java
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.PaintFlagsDrawFilter;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.PaintDrawable;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.widget.BaseAdapter;
-import android.widget.Filter;
-import android.widget.Filterable;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-
-/**
- * Displays a list of all activities which can be performed
- * for a given intent. Launches when clicked.
- *
- */
-public abstract class LauncherActivity extends ListActivity {
-
- Intent mIntent;
- PackageManager mPackageManager;
-
- /**
- * An item in the list
- */
- public static class ListItem {
- public CharSequence label;
- //public CharSequence description;
- public Drawable icon;
- public String packageName;
- public String className;
-
- ListItem(PackageManager pm, ResolveInfo resolveInfo, IconResizer resizer) {
- label = resolveInfo.loadLabel(pm);
- if (label == null && resolveInfo.activityInfo != null) {
- label = resolveInfo.activityInfo.name;
- }
-
- /*
- if (resolveInfo.activityInfo != null &&
- resolveInfo.activityInfo.applicationInfo != null) {
- description = resolveInfo.activityInfo.applicationInfo.loadDescription(pm);
- }
- */
-
- icon = resizer.createIconThumbnail(resolveInfo.loadIcon(pm));
- packageName = resolveInfo.activityInfo.applicationInfo.packageName;
- className = resolveInfo.activityInfo.name;
- }
-
- public ListItem() {
- }
- }
-
- /**
- * Adapter which shows the set of activities that can be performed for a given intent.
- */
- private class ActivityAdapter extends BaseAdapter implements Filterable {
- private final Object lock = new Object();
- private ArrayList<ListItem> mOriginalValues;
-
- protected final LayoutInflater mInflater;
-
- protected List<ListItem> mActivitiesList;
-
- private Filter mFilter;
-
- public ActivityAdapter() {
- mInflater = (LayoutInflater) LauncherActivity.this.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- mActivitiesList = makeListItems();
- }
-
- public Intent intentForPosition(int position) {
- if (mActivitiesList == null) {
- return null;
- }
-
- Intent intent = new Intent(mIntent);
- ListItem item = mActivitiesList.get(position);
- intent.setClassName(item.packageName, item.className);
- return intent;
- }
-
- public int getCount() {
- return mActivitiesList != null ? mActivitiesList.size() : 0;
- }
-
- public Object getItem(int position) {
- return position;
- }
-
- public long getItemId(int position) {
- return position;
- }
-
- public View getView(int position, View convertView, ViewGroup parent) {
- View view;
- if (convertView == null) {
- view = mInflater.inflate(
- com.android.internal.R.layout.activity_list_item_2, parent, false);
- } else {
- view = convertView;
- }
- bindView(view, mActivitiesList.get(position));
- return view;
- }
-
- private void bindView(View view, ListItem item) {
- TextView text = (TextView) view;
- text.setText(item.label);
- text.setCompoundDrawablesWithIntrinsicBounds(item.icon, null, null, null);
- }
-
- public Filter getFilter() {
- if (mFilter == null) {
- mFilter = new ArrayFilter();
- }
- return mFilter;
- }
-
- /**
- * An array filters constrains the content of the array adapter with a prefix. Each
- * item that does not start with the supplied prefix is removed from the list.
- */
- private class ArrayFilter extends Filter {
- @Override
- protected FilterResults performFiltering(CharSequence prefix) {
- FilterResults results = new FilterResults();
-
- if (mOriginalValues == null) {
- synchronized (lock) {
- mOriginalValues = new ArrayList<ListItem>(mActivitiesList);
- }
- }
-
- if (prefix == null || prefix.length() == 0) {
- synchronized (lock) {
- ArrayList<ListItem> list = new ArrayList<ListItem>(mOriginalValues);
- results.values = list;
- results.count = list.size();
- }
- } else {
- final String prefixString = prefix.toString().toLowerCase();
-
- ArrayList<ListItem> values = mOriginalValues;
- int count = values.size();
-
- ArrayList<ListItem> newValues = new ArrayList<ListItem>(count);
-
- for (int i = 0; i < count; i++) {
- ListItem item = values.get(i);
-
- String[] words = item.label.toString().toLowerCase().split(" ");
- int wordCount = words.length;
-
- for (int k = 0; k < wordCount; k++) {
- final String word = words[k];
-
- if (word.startsWith(prefixString)) {
- newValues.add(item);
- break;
- }
- }
- }
-
- results.values = newValues;
- results.count = newValues.size();
- }
-
- return results;
- }
-
- @Override
- protected void publishResults(CharSequence constraint, FilterResults results) {
- //noinspection unchecked
- mActivitiesList = (List<ListItem>) results.values;
- if (results.count > 0) {
- notifyDataSetChanged();
- } else {
- notifyDataSetInvalidated();
- }
- }
- }
- }
-
- /**
- * Utility class to resize icons to match default icon size.
- */
- public class IconResizer {
- // Code is borrowed from com.android.launcher.Utilities.
- private int mIconWidth = -1;
- private int mIconHeight = -1;
-
- private final Rect mOldBounds = new Rect();
- private Canvas mCanvas = new Canvas();
-
- public IconResizer() {
- mCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
- Paint.FILTER_BITMAP_FLAG));
-
- final Resources resources = LauncherActivity.this.getResources();
- mIconWidth = mIconHeight = (int) resources.getDimension(
- android.R.dimen.app_icon_size);
- }
-
- /**
- * Returns a Drawable representing the thumbnail of the specified Drawable.
- * The size of the thumbnail is defined by the dimension
- * android.R.dimen.launcher_application_icon_size.
- *
- * This method is not thread-safe and should be invoked on the UI thread only.
- *
- * @param icon The icon to get a thumbnail of.
- *
- * @return A thumbnail for the specified icon or the icon itself if the
- * thumbnail could not be created.
- */
- public Drawable createIconThumbnail(Drawable icon) {
- int width = mIconWidth;
- int height = mIconHeight;
-
- final int iconWidth = icon.getIntrinsicWidth();
- final int iconHeight = icon.getIntrinsicHeight();
-
- if (icon instanceof PaintDrawable) {
- PaintDrawable painter = (PaintDrawable) icon;
- painter.setIntrinsicWidth(width);
- painter.setIntrinsicHeight(height);
- }
-
- if (width > 0 && height > 0) {
- if (width < iconWidth || height < iconHeight) {
- final float ratio = (float) iconWidth / iconHeight;
-
- if (iconWidth > iconHeight) {
- height = (int) (width / ratio);
- } else if (iconHeight > iconWidth) {
- width = (int) (height * ratio);
- }
-
- final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ?
- Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
- final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
- final Canvas canvas = mCanvas;
- canvas.setBitmap(thumb);
- // Copy the old bounds to restore them later
- // If we were to do oldBounds = icon.getBounds(),
- // the call to setBounds() that follows would
- // change the same instance and we would lose the
- // old bounds
- mOldBounds.set(icon.getBounds());
- final int x = (mIconWidth - width) / 2;
- final int y = (mIconHeight - height) / 2;
- icon.setBounds(x, y, x + width, y + height);
- icon.draw(canvas);
- icon.setBounds(mOldBounds);
- icon = new BitmapDrawable(thumb);
- } else if (iconWidth < width && iconHeight < height) {
- final Bitmap.Config c = Bitmap.Config.ARGB_8888;
- final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
- final Canvas canvas = mCanvas;
- canvas.setBitmap(thumb);
- mOldBounds.set(icon.getBounds());
- final int x = (width - iconWidth) / 2;
- final int y = (height - iconHeight) / 2;
- icon.setBounds(x, y, x + iconWidth, y + iconHeight);
- icon.draw(canvas);
- icon.setBounds(mOldBounds);
- icon = new BitmapDrawable(thumb);
- }
- }
-
- return icon;
- }
- }
-
- @Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- mPackageManager = getPackageManager();
-
- requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
- setProgressBarIndeterminateVisibility(true);
- setContentView(com.android.internal.R.layout.activity_list);
-
-
- mIntent = new Intent(getTargetIntent());
- mIntent.setComponent(null);
- mAdapter = new ActivityAdapter();
-
- setListAdapter(mAdapter);
- getListView().setTextFilterEnabled(true);
-
- setProgressBarIndeterminateVisibility(false);
- }
-
- @Override
- protected void onListItemClick(ListView l, View v, int position, long id) {
- Intent intent = ((ActivityAdapter)mAdapter).intentForPosition(position);
-
- startActivity(intent);
- }
-
- /**
- * Return the actual Intent for a specific position in our
- * {@link android.widget.ListView}.
- * @param position The item whose Intent to return
- */
- protected Intent intentForPosition(int position) {
- ActivityAdapter adapter = (ActivityAdapter) mAdapter;
- return adapter.intentForPosition(position);
- }
-
- /**
- * Get the base intent to use when running
- * {@link PackageManager#queryIntentActivities(Intent, int)}.
- */
- protected Intent getTargetIntent() {
- return new Intent();
- }
-
- /**
- * Perform the query to determine which results to show and return a list of them.
- */
- public List<ListItem> makeListItems() {
- // Load all matching activities and sort correctly
- List<ResolveInfo> list = mPackageManager.queryIntentActivities(mIntent,
- /* no flags */ 0);
- Collections.sort(list, new ResolveInfo.DisplayNameComparator(mPackageManager));
-
- IconResizer resizer = new IconResizer();
-
- ArrayList<ListItem> result = new ArrayList<ListItem>(list.size());
- int listSize = list.size();
- for (int i = 0; i < listSize; i++) {
- ResolveInfo resolveInfo = list.get(i);
- result.add(new ListItem(mPackageManager, resolveInfo, resizer));
- }
-
- return result;
- }
-}
diff --git a/core/java/android/app/ListActivity.java b/core/java/android/app/ListActivity.java
deleted file mode 100644
index 2818937..0000000
--- a/core/java/android/app/ListActivity.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.view.KeyEvent;
-import android.view.View;
-import android.widget.Adapter;
-import android.widget.AdapterView;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-
-/**
- * An activity that displays a list of items by binding to a data source such as
- * an array or Cursor, and exposes event handlers when the user selects an item.
- * <p>
- * ListActivity hosts a {@link android.widget.ListView ListView} object that can
- * be bound to different data sources, typically either an array or a Cursor
- * holding query results. Binding, screen layout, and row layout are discussed
- * in the following sections.
- * <p>
- * <strong>Screen Layout</strong>
- * </p>
- * <p>
- * ListActivity has a default layout that consists of a single, full-screen list
- * in the center of the screen. However, if you desire, you can customize the
- * screen layout by setting your own view layout with setContentView() in
- * onCreate(). To do this, your own view MUST contain a ListView object with the
- * id "@android:id/list" (or {@link android.R.id#list} if it's in code)
- * <p>
- * Optionally, your custom view can contain another view object of any type to
- * display when the list view is empty. This "empty list" notifier must have an
- * id "android:empty". Note that when an empty view is present, the list view
- * will be hidden when there is no data to display.
- * <p>
- * The following code demonstrates an (ugly) custom screen layout. It has a list
- * with a green background, and an alternate red "no data" message.
- * </p>
- *
- * <pre>
- * &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
- * &lt;LinearLayout
- * android:orientation=&quot;vertical&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;fill_parent&quot;
- * android:paddingLeft=&quot;8&quot;
- * android:paddingRight=&quot;8&quot;&gt;
- *
- * &lt;ListView id=&quot;android:list&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;fill_parent&quot;
- * android:background=&quot;#00FF00&quot;
- * android:layout_weight=&quot;1&quot;
- * android:drawSelectorOnTop=&quot;false&quot;/&gt;
- *
- * &lt;TextView id=&quot;android:empty&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;fill_parent&quot;
- * android:background=&quot;#FF0000&quot;
- * android:text=&quot;No data&quot;/&gt;
- * &lt;/LinearLayout&gt;
- * </pre>
- *
- * <p>
- * <strong>Row Layout</strong>
- * </p>
- * <p>
- * You can specify the layout of individual rows in the list. You do this by
- * specifying a layout resource in the ListAdapter object hosted by the activity
- * (the ListAdapter binds the ListView to the data; more on this later).
- * <p>
- * A ListAdapter constructor takes a parameter that specifies a layout resource
- * for each row. It also has two additional parameters that let you specify
- * which data field to associate with which object in the row layout resource.
- * These two parameters are typically parallel arrays.
- * </p>
- * <p>
- * Android provides some standard row layout resources. These are in the
- * {@link android.R.layout} class, and have names such as simple_list_item_1,
- * simple_list_item_2, and two_line_list_item. The following layout XML is the
- * source for the resource two_line_list_item, which displays two data
- * fields,one above the other, for each list row.
- * </p>
- *
- * <pre>
- * &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
- * &lt;LinearLayout
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;wrap_content&quot;
- * android:orientation=&quot;vertical&quot;&gt;
- *
- * &lt;TextView id=&quot;text1&quot;
- * android:textSize=&quot;16&quot;
- * android:textStyle=&quot;bold&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;wrap_content&quot;/&gt;
- *
- * &lt;TextView id=&quot;text2&quot;
- * android:textSize=&quot;16&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;wrap_content&quot;/&gt;
- * &lt;/LinearLayout&gt;
- * </pre>
- *
- * <p>
- * You must identify the data bound to each TextView object in this layout. The
- * syntax for this is discussed in the next section.
- * </p>
- * <p>
- * <strong>Binding to Data</strong>
- * </p>
- * <p>
- * You bind the ListActivity's ListView object to data using a class that
- * implements the {@link android.widget.ListAdapter ListAdapter} interface.
- * Android provides two standard list adapters:
- * {@link android.widget.SimpleAdapter SimpleAdapter} for static data (Maps),
- * and {@link android.widget.SimpleCursorAdapter SimpleCursorAdapter} for Cursor
- * query results.
- * </p>
- * <p>
- * The following code from a custom ListActivity demonstrates querying the
- * Contacts provider for all contacts, then binding the Name and Company fields
- * to a two line row layout in the activity's ListView.
- * </p>
- *
- * <pre>
- * public class MyListAdapter extends ListActivity {
- *
- * &#064;Override
- * protected void onCreate(Bundle icicle){
- * super.onCreate(icicle);
- *
- * // We'll define a custom screen layout here (the one shown above), but
- * // typically, you could just use the standard ListActivity layout.
- * setContentView(R.layout.custom_list_activity_view);
- *
- * // Query for all people contacts using the {@link android.provider.Contacts.People} convenience class.
- * // Put a managed wrapper around the retrieved cursor so we don't have to worry about
- * // requerying or closing it as the activity changes state.
- * mCursor = People.query(this.getContentResolver(), null);
- * startManagingCursor(mCursor);
- *
- * // Now create a new list adapter bound to the cursor.
- * // SimpleListAdapter is designed for binding to a Cursor.
- * ListAdapter adapter = new SimpleCursorAdapter(
- * this, // Context.
- * android.R.layout.two_line_list_item, // Specify the row template to use (here, two columns bound to the two retrieved cursor
- * rows).
- * mCursor, // Pass in the cursor to bind to.
- * new String[] {People.NAME, People.COMPANY}, // Array of cursor columns to bind to.
- * new int[]); // Parallel array of which template objects to bind to those columns.
- *
- * // Bind to our new adapter.
- * setListAdapter(adapter);
- * }
- * }
- * </pre>
- *
- * @see #setListAdapter
- * @see android.widget.ListView
- */
-public class ListActivity extends Activity {
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected ListAdapter mAdapter;
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected ListView mList;
-
- private Handler mHandler = new Handler();
- private boolean mFinishedStart = false;
-
- private Runnable mRequestFocus = new Runnable() {
- public void run() {
- mList.focusableViewAvailable(mList);
- }
- };
-
- /**
- * This method will be called when an item in the list is selected.
- * Subclasses should override. Subclasses can call
- * getListView().getItemAtPosition(position) if they need to access the
- * data associated with the selected item.
- *
- * @param l The ListView where the click happened
- * @param v The view that was clicked within the ListView
- * @param position The position of the view in the list
- * @param id The row id of the item that was clicked
- */
- protected void onListItemClick(ListView l, View v, int position, long id) {
- }
-
- /**
- * Ensures the list view has been created before Activity restores all
- * of the view states.
- *
- *@see Activity#onRestoreInstanceState(Bundle)
- */
- @Override
- protected void onRestoreInstanceState(Bundle state) {
- ensureList();
- super.onRestoreInstanceState(state);
- }
-
- /**
- * Updates the screen state (current list and other views) when the
- * content changes.
- *
- * @see Activity#onContentChanged()
- */
- @Override
- public void onContentChanged() {
- super.onContentChanged();
- View emptyView = findViewById(com.android.internal.R.id.empty);
- mList = (ListView)findViewById(com.android.internal.R.id.list);
- if (mList == null) {
- throw new RuntimeException(
- "Your content must have a ListView whose id attribute is " +
- "'android.R.id.list'");
- }
- if (emptyView != null) {
- mList.setEmptyView(emptyView);
- }
- mList.setOnItemClickListener(mOnClickListener);
- if (mFinishedStart) {
- setListAdapter(mAdapter);
- }
- mHandler.post(mRequestFocus);
- mFinishedStart = true;
- }
-
- /**
- * Provide the cursor for the list view.
- */
- public void setListAdapter(ListAdapter adapter) {
- synchronized (this) {
- ensureList();
- mAdapter = adapter;
- mList.setAdapter(adapter);
- }
- }
-
- /**
- * Set the currently selected list item to the specified
- * position with the adapter's data
- *
- * @param position
- */
- public void setSelection(int position) {
- mList.setSelection(position);
- }
-
- /**
- * Get the position of the currently selected list item.
- */
- public int getSelectedItemPosition() {
- return mList.getSelectedItemPosition();
- }
-
- /**
- * Get the cursor row ID of the currently selected list item.
- */
- public long getSelectedItemId() {
- return mList.getSelectedItemId();
- }
-
- /**
- * Get the activity's list view widget.
- */
- public ListView getListView() {
- ensureList();
- return mList;
- }
-
- /**
- * Get the ListAdapter associated with this activity's ListView.
- */
- public ListAdapter getListAdapter() {
- return mAdapter;
- }
-
- private void ensureList() {
- if (mList != null) {
- return;
- }
- setContentView(com.android.internal.R.layout.list_content);
-
- }
-
- private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() {
- public void onItemClick(AdapterView parent, View v, int position, long id)
- {
- onListItemClick((ListView)parent, v, position, id);
- }
- };
-}
-
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
deleted file mode 100644
index a24fcae..0000000
--- a/core/java/android/app/LocalActivityManager.java
+++ /dev/null
@@ -1,627 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.os.Binder;
-import android.os.Bundle;
-import android.util.Config;
-import android.util.Log;
-import android.view.Window;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * Helper class for managing multiple running embedded activities in the same
- * process. This class is not normally used directly, but rather created for
- * you as part of the {@link android.app.ActivityGroup} implementation.
- *
- * @see ActivityGroup
- */
-public class LocalActivityManager {
- private static final String TAG = "LocalActivityManager";
- private static final boolean localLOGV = false || Config.LOGV;
-
- // Internal token for an Activity being managed by LocalActivityManager.
- private static class LocalActivityRecord extends Binder {
- LocalActivityRecord(String _id, Intent _intent) {
- id = _id;
- intent = _intent;
- }
-
- final String id; // Unique name of this record.
- Intent intent; // Which activity to run here.
- ActivityInfo activityInfo; // Package manager info about activity.
- Activity activity; // Currently instantiated activity.
- Window window; // Activity's top-level window.
- Bundle instanceState; // Last retrieved freeze state.
- int curState = RESTORED; // Current state the activity is in.
- }
-
- static final int RESTORED = 0; // State restored, but no startActivity().
- static final int INITIALIZING = 1; // Ready to launch (after startActivity()).
- static final int CREATED = 2; // Created, not started or resumed.
- static final int STARTED = 3; // Created and started, not resumed.
- static final int RESUMED = 4; // Created started and resumed.
- static final int DESTROYED = 5; // No longer with us.
-
- /** Thread our activities are running in. */
- private final ActivityThread mActivityThread;
- /** The containing activity that owns the activities we create. */
- private final Activity mParent;
-
- /** The activity that is currently resumed. */
- private LocalActivityRecord mResumed;
- /** id -> record of all known activities. */
- private final Map<String, LocalActivityRecord> mActivities
- = new HashMap<String, LocalActivityRecord>();
- /** array of all known activities for easy iterating. */
- private final ArrayList<LocalActivityRecord> mActivityArray
- = new ArrayList<LocalActivityRecord>();
-
- /** True if only one activity can be resumed at a time */
- private boolean mSingleMode;
-
- /** Set to true once we find out the container is finishing. */
- private boolean mFinishing;
-
- /** Current state the owner (ActivityGroup) is in */
- private int mCurState = INITIALIZING;
-
- /** String ids of running activities starting with least recently used. */
- // TODO: put back in stopping of activities.
- //private List<LocalActivityRecord> mLRU = new ArrayList();
-
- /**
- * Create a new LocalActivityManager for holding activities running within
- * the given <var>parent</var>.
- *
- * @param parent the host of the embedded activities
- * @param singleMode True if the LocalActivityManger should keep a maximum
- * of one activity resumed
- */
- public LocalActivityManager(Activity parent, boolean singleMode) {
- mActivityThread = ActivityThread.currentActivityThread();
- mParent = parent;
- mSingleMode = singleMode;
- }
-
- private void moveToState(LocalActivityRecord r, int desiredState) {
- if (r.curState == RESTORED || r.curState == DESTROYED) {
- // startActivity() has not yet been called, so nothing to do.
- return;
- }
-
- if (r.curState == INITIALIZING) {
- // Get the lastNonConfigurationInstance for the activity
- HashMap<String,Object> lastNonConfigurationInstances =
- mParent.getLastNonConfigurationChildInstances();
- Object instance = null;
- if (lastNonConfigurationInstances != null) {
- instance = lastNonConfigurationInstances.get(r.id);
- }
-
- // We need to have always created the activity.
- if (localLOGV) Log.v(TAG, r.id + ": starting " + r.intent);
- if (r.activityInfo == null) {
- r.activityInfo = mActivityThread.resolveActivityInfo(r.intent);
- }
- r.activity = mActivityThread.startActivityNow(
- mParent, r.id, r.intent, r.activityInfo, r, r.instanceState, instance);
- if (r.activity == null) {
- return;
- }
- r.window = r.activity.getWindow();
- r.instanceState = null;
- r.curState = STARTED;
-
- if (desiredState == RESUMED) {
- if (localLOGV) Log.v(TAG, r.id + ": resuming");
- mActivityThread.performResumeActivity(r, true);
- r.curState = RESUMED;
- }
-
- // Don't do anything more here. There is an important case:
- // if this is being done as part of onCreate() of the group, then
- // the launching of the activity gets its state a little ahead
- // of our own (it is now STARTED, while we are only CREATED).
- // If we just leave things as-is, we'll deal with it as the
- // group's state catches up.
- return;
- }
-
- switch (r.curState) {
- case CREATED:
- if (desiredState == STARTED) {
- if (localLOGV) Log.v(TAG, r.id + ": restarting");
- mActivityThread.performRestartActivity(r);
- r.curState = STARTED;
- }
- if (desiredState == RESUMED) {
- if (localLOGV) Log.v(TAG, r.id + ": restarting and resuming");
- mActivityThread.performRestartActivity(r);
- mActivityThread.performResumeActivity(r, true);
- r.curState = RESUMED;
- }
- return;
-
- case STARTED:
- if (desiredState == RESUMED) {
- // Need to resume it...
- if (localLOGV) Log.v(TAG, r.id + ": resuming");
- mActivityThread.performResumeActivity(r, true);
- r.instanceState = null;
- r.curState = RESUMED;
- }
- if (desiredState == CREATED) {
- if (localLOGV) Log.v(TAG, r.id + ": stopping");
- mActivityThread.performStopActivity(r);
- r.curState = CREATED;
- }
- return;
-
- case RESUMED:
- if (desiredState == STARTED) {
- if (localLOGV) Log.v(TAG, r.id + ": pausing");
- performPause(r, mFinishing);
- r.curState = STARTED;
- }
- if (desiredState == CREATED) {
- if (localLOGV) Log.v(TAG, r.id + ": pausing");
- performPause(r, mFinishing);
- if (localLOGV) Log.v(TAG, r.id + ": stopping");
- mActivityThread.performStopActivity(r);
- r.curState = CREATED;
- }
- return;
- }
- }
-
- private void performPause(LocalActivityRecord r, boolean finishing) {
- boolean needState = r.instanceState == null;
- Bundle instanceState = mActivityThread.performPauseActivity(r,
- finishing, needState);
- if (needState) {
- r.instanceState = instanceState;
- }
- }
-
- /**
- * Start a new activity running in the group. Every activity you start
- * must have a unique string ID associated with it -- this is used to keep
- * track of the activity, so that if you later call startActivity() again
- * on it the same activity object will be retained.
- *
- * <p>When there had previously been an activity started under this id,
- * it may either be destroyed and a new one started, or the current
- * one re-used, based on these conditions, in order:</p>
- *
- * <ul>
- * <li> If the Intent maps to a different activity component than is
- * currently running, the current activity is finished and a new one
- * started.
- * <li> If the current activity uses a non-multiple launch mode (such
- * as singleTop), or the Intent has the
- * {@link Intent#FLAG_ACTIVITY_SINGLE_TOP} flag set, then the current
- * activity will remain running and its
- * {@link Activity#onNewIntent(Intent) Activity.onNewIntent()} method
- * called.
- * <li> If the new Intent is the same (excluding extras) as the previous
- * one, and the new Intent does not have the
- * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP} set, then the current activity
- * will remain running as-is.
- * <li> Otherwise, the current activity will be finished and a new
- * one started.
- * </ul>
- *
- * <p>If the given Intent can not be resolved to an available Activity,
- * this method throws {@link android.content.ActivityNotFoundException}.
- *
- * <p>Warning: There is an issue where, if the Intent does not
- * include an explicit component, we can restore the state for a different
- * activity class than was previously running when the state was saved (if
- * the set of available activities changes between those points).
- *
- * @param id Unique identifier of the activity to be started
- * @param intent The Intent describing the activity to be started
- *
- * @return Returns the window of the activity. The caller needs to take
- * care of adding this window to a view hierarchy, and likewise dealing
- * with removing the old window if the activity has changed.
- *
- * @throws android.content.ActivityNotFoundException
- */
- public Window startActivity(String id, Intent intent) {
- if (mCurState == INITIALIZING) {
- throw new IllegalStateException(
- "Activities can't be added until the containing group has been created.");
- }
-
- boolean adding = false;
- boolean sameIntent = false;
-
- ActivityInfo aInfo = null;
-
- // Already have information about the new activity id?
- LocalActivityRecord r = mActivities.get(id);
- if (r == null) {
- // Need to create it...
- r = new LocalActivityRecord(id, intent);
- adding = true;
- } else if (r.intent != null) {
- sameIntent = r.intent.filterEquals(intent);
- if (sameIntent) {
- // We are starting the same activity.
- aInfo = r.activityInfo;
- }
- }
- if (aInfo == null) {
- aInfo = mActivityThread.resolveActivityInfo(intent);
- }
-
- // Pause the currently running activity if there is one and only a single
- // activity is allowed to be running at a time.
- if (mSingleMode) {
- LocalActivityRecord old = mResumed;
-
- // If there was a previous activity, and it is not the current
- // activity, we need to stop it.
- if (old != null && old != r && mCurState == RESUMED) {
- moveToState(old, STARTED);
- }
- }
-
- if (adding) {
- // It's a brand new world.
- mActivities.put(id, r);
- mActivityArray.add(r);
- } else if (r.activityInfo != null) {
- // If the new activity is the same as the current one, then
- // we may be able to reuse it.
- if (aInfo == r.activityInfo ||
- (aInfo.name.equals(r.activityInfo.name) &&
- aInfo.packageName.equals(r.activityInfo.packageName))) {
- if (aInfo.launchMode != ActivityInfo.LAUNCH_MULTIPLE ||
- (intent.getFlags()&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0) {
- // The activity wants onNewIntent() called.
- ArrayList<Intent> intents = new ArrayList<Intent>(1);
- intents.add(intent);
- if (localLOGV) Log.v(TAG, r.id + ": new intent");
- mActivityThread.performNewIntents(r, intents);
- r.intent = intent;
- moveToState(r, mCurState);
- if (mSingleMode) {
- mResumed = r;
- }
- return r.window;
- }
- if (sameIntent &&
- (intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_TOP) == 0) {
- // We are showing the same thing, so this activity is
- // just resumed and stays as-is.
- r.intent = intent;
- moveToState(r, mCurState);
- if (mSingleMode) {
- mResumed = r;
- }
- return r.window;
- }
- }
-
- // The new activity is different than the current one, or it
- // is a multiple launch activity, so we need to destroy what
- // is currently there.
- performDestroy(r, true);
- }
-
- r.intent = intent;
- r.curState = INITIALIZING;
- r.activityInfo = aInfo;
-
- moveToState(r, mCurState);
-
- // When in single mode keep track of the current activity
- if (mSingleMode) {
- mResumed = r;
- }
- return r.window;
- }
-
- private Window performDestroy(LocalActivityRecord r, boolean finish) {
- Window win = null;
- win = r.window;
- if (r.curState == RESUMED && !finish) {
- performPause(r, finish);
- }
- if (localLOGV) Log.v(TAG, r.id + ": destroying");
- mActivityThread.performDestroyActivity(r, finish);
- r.activity = null;
- r.window = null;
- if (finish) {
- r.instanceState = null;
- }
- r.curState = DESTROYED;
- return win;
- }
-
- /**
- * Destroy the activity associated with a particular id. This activity
- * will go through the normal lifecycle events and fine onDestroy(), and
- * then the id removed from the group.
- *
- * @param id Unique identifier of the activity to be destroyed
- * @param finish If true, this activity will be finished, so its id and
- * all state are removed from the group.
- *
- * @return Returns the window that was used to display the activity, or
- * null if there was none.
- */
- public Window destroyActivity(String id, boolean finish) {
- LocalActivityRecord r = mActivities.get(id);
- Window win = null;
- if (r != null) {
- win = performDestroy(r, finish);
- if (finish) {
- mActivities.remove(r);
- }
- }
- return win;
- }
-
- /**
- * Retrieve the Activity that is currently running.
- *
- * @return the currently running (resumed) Activity, or null if there is
- * not one
- *
- * @see #startActivity
- * @see #getCurrentId
- */
- public Activity getCurrentActivity() {
- return mResumed != null ? mResumed.activity : null;
- }
-
- /**
- * Retrieve the ID of the activity that is currently running.
- *
- * @return the ID of the currently running (resumed) Activity, or null if
- * there is not one
- *
- * @see #startActivity
- * @see #getCurrentActivity
- */
- public String getCurrentId() {
- return mResumed != null ? mResumed.id : null;
- }
-
- /**
- * Return the Activity object associated with a string ID.
- *
- * @see #startActivity
- *
- * @return the associated Activity object, or null if the id is unknown or
- * its activity is not currently instantiated
- */
- public Activity getActivity(String id) {
- LocalActivityRecord r = mActivities.get(id);
- return r != null ? r.activity : null;
- }
-
- /**
- * Restore a state that was previously returned by {@link #saveInstanceState}. This
- * adds to the activity group information about all activity IDs that had
- * previously been saved, even if they have not been started yet, so if the
- * user later navigates to them the correct state will be restored.
- *
- * <p>Note: This does <b>not</b> change the current running activity, or
- * start whatever activity was previously running when the state was saved.
- * That is up to the client to do, in whatever way it thinks is best.
- *
- * @param state a previously saved state; does nothing if this is null
- *
- * @see #saveInstanceState
- */
- public void dispatchCreate(Bundle state) {
- if (state != null) {
- final Iterator<String> i = state.keySet().iterator();
- while (i.hasNext()) {
- try {
- final String id = i.next();
- final Bundle astate = state.getBundle(id);
- LocalActivityRecord r = mActivities.get(id);
- if (r != null) {
- r.instanceState = astate;
- } else {
- r = new LocalActivityRecord(id, null);
- r.instanceState = astate;
- mActivities.put(id, r);
- mActivityArray.add(r);
- }
- } catch (Exception e) {
- // Recover from -all- app errors.
- Log.e(TAG,
- "Exception thrown when restoring LocalActivityManager state",
- e);
- }
- }
- }
-
- mCurState = CREATED;
- }
-
- /**
- * Retrieve the state of all activities known by the group. For
- * activities that have previously run and are now stopped or finished, the
- * last saved state is used. For the current running activity, its
- * {@link Activity#onSaveInstanceState} is called to retrieve its current state.
- *
- * @return a Bundle holding the newly created state of all known activities
- *
- * @see #dispatchCreate
- */
- public Bundle saveInstanceState() {
- Bundle state = null;
-
- // FIXME: child activities will freeze as part of onPaused. Do we
- // need to do this here?
- final int N = mActivityArray.size();
- for (int i=0; i<N; i++) {
- final LocalActivityRecord r = mActivityArray.get(i);
- if (state == null) {
- state = new Bundle();
- }
- if ((r.instanceState != null || r.curState == RESUMED)
- && r.activity != null) {
- // We need to save the state now, if we don't currently
- // already have it or the activity is currently resumed.
- final Bundle childState = new Bundle();
- r.activity.onSaveInstanceState(childState);
- r.instanceState = childState;
- }
- if (r.instanceState != null) {
- state.putBundle(r.id, r.instanceState);
- }
- }
-
- return state;
- }
-
- /**
- * Called by the container activity in its {@link Activity#onResume} so
- * that LocalActivityManager can perform the corresponding action on the
- * activities it holds.
- *
- * @see Activity#onResume
- */
- public void dispatchResume() {
- mCurState = RESUMED;
- if (mSingleMode) {
- if (mResumed != null) {
- moveToState(mResumed, RESUMED);
- }
- } else {
- final int N = mActivityArray.size();
- for (int i=0; i<N; i++) {
- moveToState(mActivityArray.get(i), RESUMED);
- }
- }
- }
-
- /**
- * Called by the container activity in its {@link Activity#onPause} so
- * that LocalActivityManager can perform the corresponding action on the
- * activities it holds.
- *
- * @param finishing set to true if the parent activity has been finished;
- * this can be determined by calling
- * Activity.isFinishing()
- *
- * @see Activity#onPause
- * @see Activity#isFinishing
- */
- public void dispatchPause(boolean finishing) {
- if (finishing) {
- mFinishing = true;
- }
- mCurState = STARTED;
- if (mSingleMode) {
- if (mResumed != null) {
- moveToState(mResumed, STARTED);
- }
- } else {
- final int N = mActivityArray.size();
- for (int i=0; i<N; i++) {
- LocalActivityRecord r = mActivityArray.get(i);
- if (r.curState == RESUMED) {
- moveToState(r, STARTED);
- }
- }
- }
- }
-
- /**
- * Called by the container activity in its {@link Activity#onStop} so
- * that LocalActivityManager can perform the corresponding action on the
- * activities it holds.
- *
- * @see Activity#onStop
- */
- public void dispatchStop() {
- mCurState = CREATED;
- final int N = mActivityArray.size();
- for (int i=0; i<N; i++) {
- LocalActivityRecord r = mActivityArray.get(i);
- moveToState(r, CREATED);
- }
- }
-
- /**
- * Call onRetainNonConfigurationInstance on each child activity and store the
- * results in a HashMap by id. Only construct the HashMap if there is a non-null
- * object to store. Note that this does not support nested ActivityGroups.
- *
- * {@hide}
- */
- public HashMap<String,Object> dispatchRetainNonConfigurationInstance() {
- HashMap<String,Object> instanceMap = null;
-
- final int N = mActivityArray.size();
- for (int i=0; i<N; i++) {
- LocalActivityRecord r = mActivityArray.get(i);
- if ((r != null) && (r.activity != null)) {
- Object instance = r.activity.onRetainNonConfigurationInstance();
- if (instance != null) {
- if (instanceMap == null) {
- instanceMap = new HashMap<String,Object>();
- }
- instanceMap.put(r.id, instance);
- }
- }
- }
- return instanceMap;
- }
-
- /**
- * Remove all activities from this LocalActivityManager, performing an
- * {@link Activity#onDestroy} on any that are currently instantiated.
- */
- public void removeAllActivities() {
- dispatchDestroy(true);
- }
-
- /**
- * Called by the container activity in its {@link Activity#onDestroy} so
- * that LocalActivityManager can perform the corresponding action on the
- * activities it holds.
- *
- * @see Activity#onDestroy
- */
- public void dispatchDestroy(boolean finishing) {
- final int N = mActivityArray.size();
- for (int i=0; i<N; i++) {
- LocalActivityRecord r = mActivityArray.get(i);
- if (localLOGV) Log.v(TAG, r.id + ": destroying");
- mActivityThread.performDestroyActivity(r, finishing);
- }
- mActivities.clear();
- mActivityArray.clear();
- }
-}
diff --git a/core/java/android/app/Notification.aidl b/core/java/android/app/Notification.aidl
deleted file mode 100644
index 9d8129c..0000000
--- a/core/java/android/app/Notification.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2007, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-parcelable Notification;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
deleted file mode 100644
index 51fddb1..0000000
--- a/core/java/android/app/Notification.java
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import java.util.Date;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.media.AudioManager;
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.text.format.DateFormat;
-import android.text.format.DateUtils;
-import android.widget.RemoteViews;
-
-/**
- * A class that represents how a persistent notification is to be presented to
- * the user using the {@link android.app.NotificationManager}.
- *
- */
-public class Notification implements Parcelable
-{
- /**
- * Use all default values (where applicable).
- */
- public static final int DEFAULT_ALL = ~0;
-
- /**
- * Use the default notification sound. This will ignore any given
- * {@link #sound}.
- *
- * @see #defaults
- */
- public static final int DEFAULT_SOUND = 1;
-
- /**
- * Use the default notification vibrate. This will ignore any given
- * {@link #vibrate}.
- *
- * @see #defaults
- */
- public static final int DEFAULT_VIBRATE = 2;
-
- /**
- * Use the default notification lights. This will ignore the
- * {@link #FLAG_SHOW_LIGHTS} bit, and {@link #ledARGB}, {@link #ledOffMS}, or
- * {@link #ledOnMS}.
- *
- * @see #defaults
- */
- public static final int DEFAULT_LIGHTS = 4;
-
- /**
- * The timestamp for the notification. The icons and expanded views
- * are sorted by this key.
- */
- public long when;
-
- /**
- * The resource id of a drawable to use as the icon in the status bar.
- */
- public int icon;
-
- /**
- * The number of events that this notification represents. For example, if this is the
- * new mail notification, this would be the number of unread messages. This number is
- * be superimposed over the icon in the status bar. If the number is 0 or negative, it
- * is not shown in the status bar.
- */
- public int number;
-
- /**
- * The intent to execute when the expanded status entry is clicked. If
- * this is an activity, it must include the
- * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires
- * that you take care of task management as described in the <em>Activities and Tasks</em>
- * section of the <a href="{@docRoot}guide/topics/fundamentals.html#acttask">Application
- * Fundamentals</a> document.
- */
- public PendingIntent contentIntent;
-
- /**
- * The intent to execute when the status entry is deleted by the user
- * with the "Clear All Notifications" button. This probably shouldn't
- * be launching an activity since several of those will be sent at the
- * same time.
- */
- public PendingIntent deleteIntent;
-
- /**
- * Text to scroll across the screen when this item is added to
- * the status bar.
- */
- public CharSequence tickerText;
-
- /**
- * The view that shows when this notification is shown in the expanded status bar.
- */
- public RemoteViews contentView;
-
- /**
- * If the icon in the status bar is to have more than one level, you can set this. Otherwise,
- * leave it at its default value of 0.
- *
- * @see android.widget.ImageView#setImageLevel
- * @see android.graphics.drawable#setLevel
- */
- public int iconLevel;
-
- /**
- * The sound to play.
- *
- * <p>
- * To play the default notification sound, see {@link #defaults}.
- * </p>
- */
- public Uri sound;
-
- /**
- * Use this constant as the value for audioStreamType to request that
- * the default stream type for notifications be used. Currently the
- * default stream type is STREAM_RING.
- */
- public static final int STREAM_DEFAULT = -1;
-
- /**
- * The audio stream type to use when playing the sound.
- * Should be one of the STREAM_ constants from
- * {@link android.media.AudioManager}.
- */
- public int audioStreamType = STREAM_DEFAULT;
-
-
- /**
- * The pattern with which to vibrate. This pattern will repeat if {@link
- * #FLAG_INSISTENT} bit is set in the {@link #flags} field.
- *
- * <p>
- * To vibrate the default pattern, see {@link #defaults}.
- * </p>
- *
- * @see android.os.Vibrator#vibrate(long[],int)
- */
- public long[] vibrate;
-
- /**
- * The color of the led. The hardware will do its best approximation.
- *
- * @see #FLAG_SHOW_LIGHTS
- * @see #flags
- */
- public int ledARGB;
-
- /**
- * The number of milliseconds for the LED to be on while it's flashing.
- * The hardware will do its best approximation.
- *
- * @see #FLAG_SHOW_LIGHTS
- * @see #flags
- */
- public int ledOnMS;
-
- /**
- * The number of milliseconds for the LED to be off while it's flashing.
- * The hardware will do its best approximation.
- *
- * @see #FLAG_SHOW_LIGHTS
- * @see #flags
- */
- public int ledOffMS;
-
- /**
- * Specifies which values should be taken from the defaults.
- * <p>
- * To set, OR the desired from {@link #DEFAULT_SOUND},
- * {@link #DEFAULT_VIBRATE}, {@link #DEFAULT_LIGHTS}. For all default
- * values, use {@link #DEFAULT_ALL}.
- * </p>
- */
- public int defaults;
-
-
- /**
- * Bit to be bitwise-ored into the {@link #flags} field that should be
- * set if you want the LED on for this notification.
- * <ul>
- * <li>To turn the LED off, pass 0 in the alpha channel for colorARGB
- * or 0 for both ledOnMS and ledOffMS.</li>
- * <li>To turn the LED on, pass 1 for ledOnMS and 0 for ledOffMS.</li>
- * <li>To flash the LED, pass the number of milliseconds that it should
- * be on and off to ledOnMS and ledOffMS.</li>
- * </ul>
- * <p>
- * Since hardware varies, you are not guaranteed that any of the values
- * you pass are honored exactly. Use the system defaults (TODO) if possible
- * because they will be set to values that work on any given hardware.
- * <p>
- * The alpha channel must be set for forward compatibility.
- *
- */
- public static final int FLAG_SHOW_LIGHTS = 0x00000001;
-
- /**
- * Bit to be bitwise-ored into the {@link #flags} field that should be
- * set if this notification is in reference to something that is ongoing,
- * like a phone call. It should not be set if this notification is in
- * reference to something that happened at a particular point in time,
- * like a missed phone call.
- */
- public static final int FLAG_ONGOING_EVENT = 0x00000002;
-
- /**
- * Bit to be bitwise-ored into the {@link #flags} field that if set,
- * the audio and vibration will be repeated until the notification is
- * cancelled.
- *
- * <p>
- * NOTE: This notion will change when we have decided exactly
- * what the UI will be.
- * </p>
- */
- public static final int FLAG_INSISTENT = 0x00000004;
-
- /**
- * Bit to be bitwise-ored into the {@link #flags} field that should be
- * set if you want the sound and/or vibration play each time the
- * notification is sent, even if it has not been canceled before that.
- */
- public static final int FLAG_ONLY_ALERT_ONCE = 0x00000008;
-
- /**
- * Bit to be bitwise-ored into the {@link #flags} field that should be
- * set if the notification should be canceled when it is clicked by the
- * user.
- */
- public static final int FLAG_AUTO_CANCEL = 0x00000010;
-
- /**
- * Bit to be bitwise-ored into the {@link #flags} field that should be
- * set if the notification should not be canceled when the user clicks
- * the Clear all button.
- */
- public static final int FLAG_NO_CLEAR = 0x00000020;
-
- public int flags;
-
- /**
- * Constructs a Notification object with everything set to 0.
- */
- public Notification()
- {
- this.when = System.currentTimeMillis();
- }
-
- /**
- * @deprecated use {@link #Notification(int,CharSequence,long)} and {@link #setLatestEventInfo}.
- * @hide
- */
- public Notification(Context context, int icon, CharSequence tickerText, long when,
- CharSequence contentTitle, CharSequence contentText, Intent contentIntent)
- {
- this.when = when;
- this.icon = icon;
- this.tickerText = tickerText;
- setLatestEventInfo(context, contentTitle, contentText,
- PendingIntent.getActivity(context, 0, contentIntent, 0));
- }
-
- /**
- * Constructs a Notification object with the information needed to
- * have a status bar icon without the standard expanded view.
- *
- * @param icon The resource id of the icon to put in the status bar.
- * @param tickerText The text that flows by in the status bar when the notification first
- * activates.
- * @param when The time to show in the time field. In the System.currentTimeMillis
- * timebase.
- */
- public Notification(int icon, CharSequence tickerText, long when)
- {
- this.icon = icon;
- this.tickerText = tickerText;
- this.when = when;
- }
-
- /**
- * Unflatten the notification from a parcel.
- */
- public Notification(Parcel parcel)
- {
- int version = parcel.readInt();
-
- when = parcel.readLong();
- icon = parcel.readInt();
- number = parcel.readInt();
- if (parcel.readInt() != 0) {
- contentIntent = PendingIntent.CREATOR.createFromParcel(parcel);
- }
- if (parcel.readInt() != 0) {
- deleteIntent = PendingIntent.CREATOR.createFromParcel(parcel);
- }
- if (parcel.readInt() != 0) {
- tickerText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
- }
- if (parcel.readInt() != 0) {
- contentView = RemoteViews.CREATOR.createFromParcel(parcel);
- }
- defaults = parcel.readInt();
- flags = parcel.readInt();
- if (parcel.readInt() != 0) {
- sound = Uri.CREATOR.createFromParcel(parcel);
- }
-
- audioStreamType = parcel.readInt();
- vibrate = parcel.createLongArray();
- ledARGB = parcel.readInt();
- ledOnMS = parcel.readInt();
- ledOffMS = parcel.readInt();
- iconLevel = parcel.readInt();
- }
-
- public int describeContents() {
- return 0;
- }
-
- /**
- * Flatten this notification from a parcel.
- */
- public void writeToParcel(Parcel parcel, int flags)
- {
- parcel.writeInt(1);
-
- parcel.writeLong(when);
- parcel.writeInt(icon);
- parcel.writeInt(number);
- if (contentIntent != null) {
- parcel.writeInt(1);
- contentIntent.writeToParcel(parcel, 0);
- } else {
- parcel.writeInt(0);
- }
- if (deleteIntent != null) {
- parcel.writeInt(1);
- deleteIntent.writeToParcel(parcel, 0);
- } else {
- parcel.writeInt(0);
- }
- if (tickerText != null) {
- parcel.writeInt(1);
- TextUtils.writeToParcel(tickerText, parcel, flags);
- } else {
- parcel.writeInt(0);
- }
- if (contentView != null) {
- parcel.writeInt(1);
- contentView.writeToParcel(parcel, 0);
- } else {
- parcel.writeInt(0);
- }
-
- parcel.writeInt(defaults);
- parcel.writeInt(this.flags);
-
- if (sound != null) {
- parcel.writeInt(1);
- sound.writeToParcel(parcel, 0);
- } else {
- parcel.writeInt(0);
- }
- parcel.writeInt(audioStreamType);
- parcel.writeLongArray(vibrate);
- parcel.writeInt(ledARGB);
- parcel.writeInt(ledOnMS);
- parcel.writeInt(ledOffMS);
- parcel.writeInt(iconLevel);
- }
-
- /**
- * Parcelable.Creator that instantiates Notification objects
- */
- public static final Parcelable.Creator<Notification> CREATOR
- = new Parcelable.Creator<Notification>()
- {
- public Notification createFromParcel(Parcel parcel)
- {
- return new Notification(parcel);
- }
-
- public Notification[] newArray(int size)
- {
- return new Notification[size];
- }
- };
-
- /**
- * Sets the {@link #contentView} field to be a view with the standard "Latest Event"
- * layout.
- *
- * <p>Uses the {@link #icon} and {@link #when} fields to set the icon and time fields
- * in the view.</p>
- * @param context The context for your application / activity.
- * @param contentTitle The title that goes in the expanded entry.
- * @param contentText The text that goes in the expanded entry.
- * @param contentIntent The intent to launch when the user clicks the expanded notification.
- * If this is an activity, it must include the
- * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires
- * that you take care of task management as described in
- * <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">Application Fundamentals: Activities and Tasks</a>.
- */
- public void setLatestEventInfo(Context context,
- CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) {
- RemoteViews contentView = new RemoteViews(context.getPackageName(),
- com.android.internal.R.layout.status_bar_latest_event_content);
- if (this.icon != 0) {
- contentView.setImageViewResource(com.android.internal.R.id.icon, this.icon);
- }
- if (contentTitle != null) {
- contentView.setTextViewText(com.android.internal.R.id.title, contentTitle);
- }
- if (contentText != null) {
- contentView.setTextViewText(com.android.internal.R.id.text, contentText);
- }
- if (this.when != 0) {
- Date date = new Date(when);
- CharSequence str =
- DateUtils.isToday(when) ? DateFormat.getTimeFormat(context).format(date)
- : DateFormat.getDateFormat(context).format(date);
- contentView.setTextViewText(com.android.internal.R.id.time, str);
- }
-
- this.contentView = contentView;
- this.contentIntent = contentIntent;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("Notification(vibrate=");
- if (this.vibrate != null) {
- int N = this.vibrate.length-1;
- sb.append("[");
- for (int i=0; i<N; i++) {
- sb.append(this.vibrate[i]);
- sb.append(',');
- }
- sb.append(this.vibrate[N]);
- sb.append("]");
- } else if ((this.defaults & DEFAULT_VIBRATE) != 0) {
- sb.append("default");
- } else {
- sb.append("null");
- }
- sb.append(",sound=");
- if (this.sound != null) {
- sb.append(this.sound.toString());
- } else if ((this.defaults & DEFAULT_SOUND) != 0) {
- sb.append("default");
- } else {
- sb.append("null");
- }
- sb.append(",defaults=0x");
- sb.append(Integer.toHexString(this.defaults));
- sb.append(")");
- return sb.toString();
- }
-}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
deleted file mode 100644
index afb3827..0000000
--- a/core/java/android/app/NotificationManager.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.Context;
-import android.os.RemoteException;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.ServiceManager;
-import android.util.Log;
-
-/**
- * Class to notify the user of events that happen. This is how you tell
- * the user that something has happened in the background. {@more}
- *
- * Notifications can take different forms:
- * <ul>
- * <li>A persistent icon that goes in the status bar and is accessible
- * through the launcher, (when the user selects it, a designated Intent
- * can be launched),</li>
- * <li>Turning on or flashing LEDs on the device, or</li>
- * <li>Alerting the user by flashing the backlight, playing a sound,
- * or vibrating.</li>
- * </ul>
- *
- * <p>
- * Each of the notify methods takes an int id parameter. This id identifies
- * this notification from your app to the system, so that id should be unique
- * within your app. If you call one of the notify methods with an id that is
- * currently active and a new set of notification parameters, it will be
- * updated. For example, if you pass a new status bar icon, the old icon in
- * the status bar will be replaced with the new one. This is also the same
- * id you pass to the {@link #cancel} method to clear this notification.
- *
- * <p>
- * You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService}.
- *
- * @see android.app.Notification
- * @see android.content.Context#getSystemService
- */
-public class NotificationManager
-{
- private static String TAG = "NotificationManager";
- private static boolean DEBUG = false;
- private static boolean localLOGV = DEBUG || android.util.Config.LOGV;
-
- private static INotificationManager sService;
-
- static private INotificationManager getService()
- {
- if (sService != null) {
- return sService;
- }
- IBinder b = ServiceManager.getService("notification");
- sService = INotificationManager.Stub.asInterface(b);
- return sService;
- }
-
- /*package*/ NotificationManager(Context context, Handler handler)
- {
- mContext = context;
- }
-
- /**
- * Persistent notification on the status bar,
- *
- * @param id An identifier for this notification unique within your
- * application.
- * @param notification A {@link Notification} object describing how to
- * notify the user, other than the view you're providing. If you
- * pass null, there will be no persistent notification and no
- * flashing, vibration, etc.
- */
- public void notify(int id, Notification notification)
- {
- int[] idOut = new int[1];
- INotificationManager service = getService();
- String pkg = mContext.getPackageName();
- if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
- try {
- service.enqueueNotification(pkg, id, notification, idOut);
- if (id != idOut[0]) {
- Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
- }
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Cancel a previously shown notification. If it's transient, the view
- * will be hidden. If it's persistent, it will be removed from the status
- * bar.
- */
- public void cancel(int id)
- {
- INotificationManager service = getService();
- String pkg = mContext.getPackageName();
- if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")");
- try {
- service.cancelNotification(pkg, id);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Cancel all previously shown notifications. See {@link #cancel} for the
- * detailed behavior.
- */
- public void cancelAll()
- {
- INotificationManager service = getService();
- String pkg = mContext.getPackageName();
- if (localLOGV) Log.v(TAG, pkg + ": cancelAll()");
- try {
- service.cancelAllNotifications(pkg);
- } catch (RemoteException e) {
- }
- }
-
- private Context mContext;
-}
diff --git a/core/java/android/app/PendingIntent.aidl b/core/java/android/app/PendingIntent.aidl
deleted file mode 100644
index f0d530c..0000000
--- a/core/java/android/app/PendingIntent.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/content/Intent.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.app;
-
-parcelable PendingIntent;
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
deleted file mode 100644
index 1bed706..0000000
--- a/core/java/android/app/PendingIntent.java
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.AndroidException;
-
-/**
- * A description of an Intent and target action to perform with it. Instances
- * of this class are created with {@link #getActivity},
- * {@link #getBroadcast}, {@link #getService}; the returned object can be
- * handed to other applications so that they can perform the action you
- * described on your behalf at a later time.
- *
- * <p>By giving a PendingIntent to another application,
- * you are granting it the right to perform the operation you have specified
- * as if the other application was yourself (with the same permissions and
- * identity). As such, you should be careful about how you build the PendingIntent:
- * often, for example, the base Intent you supply will have the component
- * name explicitly set to one of your own components, to ensure it is ultimately
- * sent there and nowhere else.
- *
- * <p>A PendingIntent itself is simply a reference to a token maintained by
- * the system describing the original data used to retrieve it. This means
- * that, even if its owning application's process is killed, the
- * PendingIntent itself will remain usable from other processes that
- * have been given it. If the creating application later re-retrieves the
- * same kind of PendingIntent (same operation, same Intent action, data,
- * categories, and components, and same flags), it will receive a PendingIntent
- * representing the same token if that is still valid, and can thus call
- * {@link #cancel} to remove it.
- */
-public final class PendingIntent implements Parcelable {
- private final IIntentSender mTarget;
-
- /**
- * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
- * {@link #getService}: this
- * PendingIntent can only be used once. If set, after
- * {@link #send()} is called on it, it will be automatically
- * canceled for you and any future attempt to send through it will fail.
- */
- public static final int FLAG_ONE_SHOT = 1<<30;
- /**
- * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
- * {@link #getService}: if the described PendingIntent does not already
- * exist, then simply return null instead of creating it.
- */
- public static final int FLAG_NO_CREATE = 1<<29;
- /**
- * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
- * {@link #getService}: if the described PendingIntent already exists,
- * the current one is canceled before generating a new one. You can use
- * this to retrieve a new PendingIntent when you are only changing the
- * extra data in the Intent; by canceling the previous pending intent,
- * this ensures that only entities given the new data will be able to
- * launch it. If this assurance is not an issue, consider
- * {@link #FLAG_UPDATE_CURRENT}.
- */
- public static final int FLAG_CANCEL_CURRENT = 1<<28;
- /**
- * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
- * {@link #getService}: if the described PendingIntent already exists,
- * then keep it but its replace its extra data with what is in this new
- * Intent. This can be used if you are creating intents where only the
- * extras change, and don't care that any entities that received your
- * previous PendingIntent will be able to launch it with your new
- * extras even if they are not explicitly given to it.
- */
- public static final int FLAG_UPDATE_CURRENT = 1<<27;
-
- /**
- * Exception thrown when trying to send through a PendingIntent that
- * has been canceled or is otherwise no longer able to execute the request.
- */
- public static class CanceledException extends AndroidException {
- public CanceledException() {
- }
-
- public CanceledException(String name) {
- super(name);
- }
-
- public CanceledException(Exception cause) {
- super(cause);
- }
- };
-
- /**
- * Callback interface for discovering when a send operation has
- * completed. Primarily for use with a PendingIntent that is
- * performing a broadcast, this provides the same information as
- * calling {@link Context#sendOrderedBroadcast(Intent, String,
- * android.content.BroadcastReceiver, Handler, int, String, Bundle)
- * Context.sendBroadcast()} with a final BroadcastReceiver.
- */
- public interface OnFinished {
- /**
- * Called when a send operation as completed.
- *
- * @param pendingIntent The PendingIntent this operation was sent through.
- * @param intent The original Intent that was sent.
- * @param resultCode The final result code determined by the send.
- * @param resultData The final data collected by a broadcast.
- * @param resultExtras The final extras collected by a broadcast.
- */
- void onSendFinished(PendingIntent pendingIntent, Intent intent,
- int resultCode, String resultData, Bundle resultExtras);
- }
-
- private static class FinishedDispatcher extends IIntentReceiver.Stub
- implements Runnable {
- private final PendingIntent mPendingIntent;
- private final OnFinished mWho;
- private final Handler mHandler;
- private Intent mIntent;
- private int mResultCode;
- private String mResultData;
- private Bundle mResultExtras;
- FinishedDispatcher(PendingIntent pi, OnFinished who, Handler handler) {
- mPendingIntent = pi;
- mWho = who;
- mHandler = handler;
- }
- public void performReceive(Intent intent, int resultCode,
- String data, Bundle extras, boolean serialized) {
- mIntent = intent;
- mResultCode = resultCode;
- mResultData = data;
- mResultExtras = extras;
- if (mHandler == null) {
- run();
- } else {
- mHandler.post(this);
- }
- }
- public void run() {
- mWho.onSendFinished(mPendingIntent, mIntent, mResultCode,
- mResultData, mResultExtras);
- }
- }
-
- /**
- * Retrieve a PendingIntent that will start a new activity, like calling
- * {@link Context#startActivity(Intent) Context.startActivity(Intent)}.
- * Note that the activity will be started outside of the context of an
- * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
- * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.
- *
- * @param context The Context in which this PendingIntent should start
- * the activity.
- * @param requestCode Private request code for the sender (currently
- * not used).
- * @param intent Intent of the activity to be launched.
- * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
- * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
- * or any of the flags as supported by
- * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
- * of the intent that can be supplied when the actual send happens.
- *
- * @return Returns an existing or new PendingIntent matching the given
- * parameters. May return null only if {@link #FLAG_NO_CREATE} has been
- * supplied.
- */
- public static PendingIntent getActivity(Context context, int requestCode,
- Intent intent, int flags) {
- String packageName = context.getPackageName();
- String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
- context.getContentResolver()) : null;
- try {
- IIntentSender target =
- ActivityManagerNative.getDefault().getIntentSender(
- IActivityManager.INTENT_SENDER_ACTIVITY, packageName,
- null, null, requestCode, intent, resolvedType, flags);
- return target != null ? new PendingIntent(target) : null;
- } catch (RemoteException e) {
- }
- return null;
- }
-
- /**
- * Retrieve a PendingIntent that will perform a broadcast, like calling
- * {@link Context#sendBroadcast(Intent) Context.sendBroadcast()}.
- *
- * @param context The Context in which this PendingIntent should perform
- * the broadcast.
- * @param requestCode Private request code for the sender (currently
- * not used).
- * @param intent The Intent to be broadcast.
- * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
- * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
- * or any of the flags as supported by
- * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
- * of the intent that can be supplied when the actual send happens.
- *
- * @return Returns an existing or new PendingIntent matching the given
- * parameters. May return null only if {@link #FLAG_NO_CREATE} has been
- * supplied.
- */
- public static PendingIntent getBroadcast(Context context, int requestCode,
- Intent intent, int flags) {
- String packageName = context.getPackageName();
- String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
- context.getContentResolver()) : null;
- try {
- IIntentSender target =
- ActivityManagerNative.getDefault().getIntentSender(
- IActivityManager.INTENT_SENDER_BROADCAST, packageName,
- null, null, requestCode, intent, resolvedType, flags);
- return target != null ? new PendingIntent(target) : null;
- } catch (RemoteException e) {
- }
- return null;
- }
-
- /**
- * Retrieve a PendingIntent that will start a service, like calling
- * {@link Context#startService Context.startService()}. The start
- * arguments given to the service will come from the extras of the Intent.
- *
- * @param context The Context in which this PendingIntent should start
- * the service.
- * @param requestCode Private request code for the sender (currently
- * not used).
- * @param intent An Intent describing the service to be started.
- * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
- * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
- * or any of the flags as supported by
- * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
- * of the intent that can be supplied when the actual send happens.
- *
- * @return Returns an existing or new PendingIntent matching the given
- * parameters. May return null only if {@link #FLAG_NO_CREATE} has been
- * supplied.
- */
- public static PendingIntent getService(Context context, int requestCode,
- Intent intent, int flags) {
- String packageName = context.getPackageName();
- String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
- context.getContentResolver()) : null;
- try {
- IIntentSender target =
- ActivityManagerNative.getDefault().getIntentSender(
- IActivityManager.INTENT_SENDER_SERVICE, packageName,
- null, null, requestCode, intent, resolvedType, flags);
- return target != null ? new PendingIntent(target) : null;
- } catch (RemoteException e) {
- }
- return null;
- }
-
- /**
- * Cancel a currently active PendingIntent. Only the original application
- * owning an PendingIntent can cancel it.
- */
- public void cancel() {
- try {
- ActivityManagerNative.getDefault().cancelIntentSender(mTarget);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Perform the operation associated with this PendingIntent.
- *
- * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
- *
- * @throws CanceledException Throws CanceledException if the PendingIntent
- * is no longer allowing more intents to be sent through it.
- */
- public void send() throws CanceledException {
- send(null, 0, null, null, null);
- }
-
- /**
- * Perform the operation associated with this PendingIntent.
- *
- * @param code Result code to supply back to the PendingIntent's target.
- *
- * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
- *
- * @throws CanceledException Throws CanceledException if the PendingIntent
- * is no longer allowing more intents to be sent through it.
- */
- public void send(int code) throws CanceledException {
- send(null, code, null, null, null);
- }
-
- /**
- * Perform the operation associated with this PendingIntent, allowing the
- * caller to specify information about the Intent to use.
- *
- * @param context The Context of the caller.
- * @param code Result code to supply back to the PendingIntent's target.
- * @param intent Additional Intent data. See {@link Intent#fillIn
- * Intent.fillIn()} for information on how this is applied to the
- * original Intent.
- *
- * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
- *
- * @throws CanceledException Throws CanceledException if the PendingIntent
- * is no longer allowing more intents to be sent through it.
- */
- public void send(Context context, int code, Intent intent)
- throws CanceledException {
- send(context, code, intent, null, null);
- }
-
- /**
- * Perform the operation associated with this PendingIntent, allowing the
- * caller to be notified when the send has completed.
- *
- * @param code Result code to supply back to the PendingIntent's target.
- * @param onFinished The object to call back on when the send has
- * completed, or null for no callback.
- * @param handler Handler identifying the thread on which the callback
- * should happen. If null, the callback will happen from the thread
- * pool of the process.
- *
- * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
- *
- * @throws CanceledException Throws CanceledException if the PendingIntent
- * is no longer allowing more intents to be sent through it.
- */
- public void send(int code, OnFinished onFinished, Handler handler)
- throws CanceledException {
- send(null, code, null, onFinished, handler);
- }
-
- /**
- * Perform the operation associated with this PendingIntent, allowing the
- * caller to specify information about the Intent to use and be notified
- * when the send has completed.
- *
- * <p>For the intent parameter, a PendingIntent
- * often has restrictions on which fields can be supplied here, based on
- * how the PendingIntent was retrieved in {@link #getActivity},
- * {@link #getBroadcast}, or {@link #getService}.
- *
- * @param context The Context of the caller. This may be null if
- * <var>intent</var> is also null.
- * @param code Result code to supply back to the PendingIntent's target.
- * @param intent Additional Intent data. See {@link Intent#fillIn
- * Intent.fillIn()} for information on how this is applied to the
- * original Intent. Use null to not modify the original Intent.
- * @param onFinished The object to call back on when the send has
- * completed, or null for no callback.
- * @param handler Handler identifying the thread on which the callback
- * should happen. If null, the callback will happen from the thread
- * pool of the process.
- *
- * @see #send()
- * @see #send(int)
- * @see #send(Context, int, Intent)
- * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
- *
- * @throws CanceledException Throws CanceledException if the PendingIntent
- * is no longer allowing more intents to be sent through it.
- */
- public void send(Context context, int code, Intent intent,
- OnFinished onFinished, Handler handler) throws CanceledException {
- try {
- String resolvedType = intent != null ?
- intent.resolveTypeIfNeeded(context.getContentResolver())
- : null;
- int res = mTarget.send(code, intent, resolvedType,
- onFinished != null
- ? new FinishedDispatcher(this, onFinished, handler)
- : null);
- if (res < 0) {
- throw new CanceledException();
- }
- } catch (RemoteException e) {
- throw new CanceledException(e);
- }
- }
-
- /**
- * Return the package name of the application that created this
- * PendingIntent, that is the identity under which you will actually be
- * sending the Intent. The returned string is supplied by the system, so
- * that an application can not spoof its package.
- *
- * @return The package name of the PendingIntent, or null if there is
- * none associated with it.
- */
- public String getTargetPackage() {
- try {
- return ActivityManagerNative.getDefault()
- .getPackageForIntentSender(mTarget);
- } catch (RemoteException e) {
- // Should never happen.
- return null;
- }
- }
-
- /**
- * Comparison operator on two PendingIntent objects, such that true
- * is returned then they both represent the same operation from the
- * same package. This allows you to use {@link #getActivity},
- * {@link #getBroadcast}, or {@link #getService} multiple times (even
- * across a process being killed), resulting in different PendingIntent
- * objects but whose equals() method identifies them as being the same
- * operation.
- */
- @Override
- public boolean equals(Object otherObj) {
- if (otherObj instanceof PendingIntent) {
- return mTarget.asBinder().equals(((PendingIntent)otherObj)
- .mTarget.asBinder());
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return mTarget.asBinder().hashCode();
- }
-
- @Override
- public String toString() {
- return "PendingIntent{"
- + Integer.toHexString(System.identityHashCode(this))
- + " target " + (mTarget != null ? mTarget.asBinder() : null) + "}";
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeStrongBinder(mTarget.asBinder());
- }
-
- public static final Parcelable.Creator<PendingIntent> CREATOR
- = new Parcelable.Creator<PendingIntent>() {
- public PendingIntent createFromParcel(Parcel in) {
- IBinder target = in.readStrongBinder();
- return target != null ? new PendingIntent(target) : null;
- }
-
- public PendingIntent[] newArray(int size) {
- return new PendingIntent[size];
- }
- };
-
- /**
- * Convenience function for writing either a PendingIntent or null pointer to
- * a Parcel. You must use this with {@link #readPendingIntentOrNullFromParcel}
- * for later reading it.
- *
- * @param sender The PendingIntent to write, or null.
- * @param out Where to write the PendingIntent.
- */
- public static void writePendingIntentOrNullToParcel(PendingIntent sender,
- Parcel out) {
- out.writeStrongBinder(sender != null ? sender.mTarget.asBinder()
- : null);
- }
-
- /**
- * Convenience function for reading either a Messenger or null pointer from
- * a Parcel. You must have previously written the Messenger with
- * {@link #writePendingIntentOrNullToParcel}.
- *
- * @param in The Parcel containing the written Messenger.
- *
- * @return Returns the Messenger read from the Parcel, or null if null had
- * been written.
- */
- public static PendingIntent readPendingIntentOrNullFromParcel(Parcel in) {
- IBinder b = in.readStrongBinder();
- return b != null ? new PendingIntent(b) : null;
- }
-
- /*package*/ PendingIntent(IIntentSender target) {
- mTarget = target;
- }
-
- /*package*/ PendingIntent(IBinder target) {
- mTarget = IIntentSender.Stub.asInterface(target);
- }
-
- /*package*/ IIntentSender getTarget() {
- return mTarget;
- }
-}
diff --git a/core/java/android/app/ProgressDialog.java b/core/java/android/app/ProgressDialog.java
deleted file mode 100644
index c87e398..0000000
--- a/core/java/android/app/ProgressDialog.java
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import com.android.internal.R;
-
-import java.text.NumberFormat;
-
-/**
- * <p>A dialog showing a progress indicator and an optional text message or view.
- * Only a text message or a view can be used at the same time.</p>
- * <p>The dialog can be made cancelable on back key press.</p>
- * <p>The progress range is 0..10000.</p>
- */
-public class ProgressDialog extends AlertDialog {
-
- /** Creates a ProgressDialog with a ciruclar, spinning progress
- * bar. This is the default.
- */
- public static final int STYLE_SPINNER = 0;
-
- /** Creates a ProgressDialog with a horizontal progress bar.
- */
- public static final int STYLE_HORIZONTAL = 1;
-
- private ProgressBar mProgress;
- private TextView mMessageView;
-
- private int mProgressStyle = STYLE_SPINNER;
- private TextView mProgressNumber;
- private TextView mProgressPercent;
- private NumberFormat mProgressPercentFormat;
-
- private int mMax;
- private int mProgressVal;
- private int mSecondaryProgressVal;
- private int mIncrementBy;
- private int mIncrementSecondaryBy;
- private Drawable mProgressDrawable;
- private Drawable mIndeterminateDrawable;
- private CharSequence mMessage;
- private boolean mIndeterminate;
-
- private boolean mHasStarted;
- private Handler mViewUpdateHandler;
-
- public ProgressDialog(Context context) {
- this(context, com.android.internal.R.style.Theme_Dialog_Alert);
- }
-
- public ProgressDialog(Context context, int theme) {
- super(context, theme);
- }
-
- public static ProgressDialog show(Context context, CharSequence title,
- CharSequence message) {
- return show(context, title, message, false);
- }
-
- public static ProgressDialog show(Context context, CharSequence title,
- CharSequence message, boolean indeterminate) {
- return show(context, title, message, indeterminate, false, null);
- }
-
- public static ProgressDialog show(Context context, CharSequence title,
- CharSequence message, boolean indeterminate, boolean cancelable) {
- return show(context, title, message, indeterminate, cancelable, null);
- }
-
- public static ProgressDialog show(Context context, CharSequence title,
- CharSequence message, boolean indeterminate,
- boolean cancelable, OnCancelListener cancelListener) {
- ProgressDialog dialog = new ProgressDialog(context);
- dialog.setTitle(title);
- dialog.setMessage(message);
- dialog.setIndeterminate(indeterminate);
- dialog.setCancelable(cancelable);
- dialog.setOnCancelListener(cancelListener);
- dialog.show();
- return dialog;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- LayoutInflater inflater = LayoutInflater.from(mContext);
- if (mProgressStyle == STYLE_HORIZONTAL) {
-
- /* Use a separate handler to update the text views as they
- * must be updated on the same thread that created them.
- */
- mViewUpdateHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
-
- /* Update the number and percent */
- int progress = mProgress.getProgress();
- int max = mProgress.getMax();
- double percent = (double) progress / (double) max;
- mProgressNumber.setText(progress + "/" + max);
- mProgressPercent.setText(mProgressPercentFormat.format(percent));
- }
- };
- View view = inflater.inflate(R.layout.alert_dialog_progress, null);
- mProgress = (ProgressBar) view.findViewById(R.id.progress);
- mProgressNumber = (TextView) view.findViewById(R.id.progress_number);
- mProgressPercent = (TextView) view.findViewById(R.id.progress_percent);
- mProgressPercentFormat = NumberFormat.getPercentInstance();
- mProgressPercentFormat.setMaximumFractionDigits(0);
- setView(view);
- } else {
- View view = inflater.inflate(R.layout.progress_dialog, null);
- mProgress = (ProgressBar) view.findViewById(R.id.progress);
- mMessageView = (TextView) view.findViewById(R.id.message);
- setView(view);
- }
- if (mMax > 0) {
- setMax(mMax);
- }
- if (mProgressVal > 0) {
- setProgress(mProgressVal);
- }
- if (mSecondaryProgressVal > 0) {
- setSecondaryProgress(mSecondaryProgressVal);
- }
- if (mIncrementBy > 0) {
- incrementProgressBy(mIncrementBy);
- }
- if (mIncrementSecondaryBy > 0) {
- incrementSecondaryProgressBy(mIncrementSecondaryBy);
- }
- if (mProgressDrawable != null) {
- setProgressDrawable(mProgressDrawable);
- }
- if (mIndeterminateDrawable != null) {
- setIndeterminateDrawable(mIndeterminateDrawable);
- }
- if (mMessage != null) {
- setMessage(mMessage);
- }
- setIndeterminate(mIndeterminate);
- onProgressChanged();
- super.onCreate(savedInstanceState);
- }
-
- @Override
- public void onStart() {
- super.onStart();
- mHasStarted = true;
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- mHasStarted = false;
- }
-
- public void setProgress(int value) {
- if (mHasStarted) {
- mProgress.setProgress(value);
- onProgressChanged();
- } else {
- mProgressVal = value;
- }
- }
-
- public void setSecondaryProgress(int secondaryProgress) {
- if (mProgress != null) {
- mProgress.setSecondaryProgress(secondaryProgress);
- onProgressChanged();
- } else {
- mSecondaryProgressVal = secondaryProgress;
- }
- }
-
- public int getProgress() {
- if (mProgress != null) {
- return mProgress.getProgress();
- }
- return mProgressVal;
- }
-
- public int getSecondaryProgress() {
- if (mProgress != null) {
- return mProgress.getSecondaryProgress();
- }
- return mSecondaryProgressVal;
- }
-
- public int getMax() {
- if (mProgress != null) {
- return mProgress.getMax();
- }
- return mMax;
- }
-
- public void setMax(int max) {
- if (mProgress != null) {
- mProgress.setMax(max);
- onProgressChanged();
- } else {
- mMax = max;
- }
- }
-
- public void incrementProgressBy(int diff) {
- if (mProgress != null) {
- mProgress.incrementProgressBy(diff);
- onProgressChanged();
- } else {
- mIncrementBy += diff;
- }
- }
-
- public void incrementSecondaryProgressBy(int diff) {
- if (mProgress != null) {
- mProgress.incrementSecondaryProgressBy(diff);
- onProgressChanged();
- } else {
- mIncrementSecondaryBy += diff;
- }
- }
-
- public void setProgressDrawable(Drawable d) {
- if (mProgress != null) {
- mProgress.setProgressDrawable(d);
- } else {
- mProgressDrawable = d;
- }
- }
-
- public void setIndeterminateDrawable(Drawable d) {
- if (mProgress != null) {
- mProgress.setIndeterminateDrawable(d);
- } else {
- mIndeterminateDrawable = d;
- }
- }
-
- public void setIndeterminate(boolean indeterminate) {
- if (mProgress != null) {
- mProgress.setIndeterminate(indeterminate);
- } else {
- mIndeterminate = indeterminate;
- }
- }
-
- public boolean isIndeterminate() {
- if (mProgress != null) {
- return mProgress.isIndeterminate();
- }
- return mIndeterminate;
- }
-
- @Override
- public void setMessage(CharSequence message) {
- if (mProgress != null) {
- if (mProgressStyle == STYLE_HORIZONTAL) {
- super.setMessage(message);
- } else {
- mMessageView.setText(message);
- }
- } else {
- mMessage = message;
- }
- }
-
- public void setProgressStyle(int style) {
- mProgressStyle = style;
- }
-
- private void onProgressChanged() {
- if (mProgressStyle == STYLE_HORIZONTAL) {
- mViewUpdateHandler.sendEmptyMessage(0);
- }
- }
-}
diff --git a/core/java/android/app/ResultInfo.java b/core/java/android/app/ResultInfo.java
deleted file mode 100644
index 48a0fc2..0000000
--- a/core/java/android/app/ResultInfo.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.Intent;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.Bundle;
-
-import java.util.Map;
-
-/**
- * {@hide}
- */
-public class ResultInfo implements Parcelable {
- public final String mResultWho;
- public final int mRequestCode;
- public final int mResultCode;
- public final Intent mData;
-
- public ResultInfo(String resultWho, int requestCode, int resultCode,
- Intent data) {
- mResultWho = resultWho;
- mRequestCode = requestCode;
- mResultCode = resultCode;
- mData = data;
- }
-
- public String toString() {
- return "ResultInfo{who=" + mResultWho + ", request=" + mRequestCode
- + ", result=" + mResultCode + ", data=" + mData + "}";
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(mResultWho);
- out.writeInt(mRequestCode);
- out.writeInt(mResultCode);
- if (mData != null) {
- out.writeInt(1);
- mData.writeToParcel(out, 0);
- } else {
- out.writeInt(0);
- }
- }
-
- public static final Parcelable.Creator<ResultInfo> CREATOR
- = new Parcelable.Creator<ResultInfo>() {
- public ResultInfo createFromParcel(Parcel in) {
- return new ResultInfo(in);
- }
-
- public ResultInfo[] newArray(int size) {
- return new ResultInfo[size];
- }
- };
-
- public ResultInfo(Parcel in) {
- mResultWho = in.readString();
- mRequestCode = in.readInt();
- mResultCode = in.readInt();
- if (in.readInt() != 0) {
- mData = Intent.CREATOR.createFromParcel(in);
- } else {
- mData = null;
- }
- }
-}
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
deleted file mode 100644
index 7b8256c..0000000
--- a/core/java/android/app/SearchDialog.java
+++ /dev/null
@@ -1,1593 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.ActivityNotFoundException;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
-import android.database.Cursor;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.server.search.SearchableInfo;
-import android.speech.RecognizerIntent;
-import android.text.Editable;
-import android.text.InputType;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
-import android.widget.AdapterView;
-import android.widget.AutoCompleteTextView;
-import android.widget.Button;
-import android.widget.CursorAdapter;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.SimpleCursorAdapter;
-import android.widget.TextView;
-import android.widget.WrapperListAdapter;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.AdapterView.OnItemSelectedListener;
-
-import java.lang.ref.WeakReference;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * In-application-process implementation of Search Bar. This is still controlled by the
- * SearchManager, but it runs in the current activity's process to keep things lighter weight.
- *
- * @hide
- */
-public class SearchDialog extends Dialog implements OnItemClickListener, OnItemSelectedListener {
-
- // Debugging support
- final static String LOG_TAG = "SearchDialog";
- private static final int DBG_LOG_TIMING = 0;
- final static int DBG_JAM_THREADING = 0;
-
- // interaction with runtime
- IntentFilter mCloseDialogsFilter;
- IntentFilter mPackageFilter;
-
- private static final String INSTANCE_KEY_COMPONENT = "comp";
- private static final String INSTANCE_KEY_APPDATA = "data";
- private static final String INSTANCE_KEY_GLOBALSEARCH = "glob";
- private static final String INSTANCE_KEY_DISPLAY_QUERY = "dQry";
- private static final String INSTANCE_KEY_DISPLAY_SEL_START = "sel1";
- private static final String INSTANCE_KEY_DISPLAY_SEL_END = "sel2";
- private static final String INSTANCE_KEY_USER_QUERY = "uQry";
- private static final String INSTANCE_KEY_SUGGESTION_QUERY = "sQry";
- private static final String INSTANCE_KEY_SELECTED_ELEMENT = "slEl";
- private static final int INSTANCE_SELECTED_BUTTON = -2;
- private static final int INSTANCE_SELECTED_QUERY = -1;
-
- // views & widgets
- private TextView mBadgeLabel;
- private AutoCompleteTextView mSearchTextField;
- private Button mGoButton;
- private ImageButton mVoiceButton;
-
- // interaction with searchable application
- private ComponentName mLaunchComponent;
- private Bundle mAppSearchData;
- private boolean mGlobalSearchMode;
- private Context mActivityContext;
-
- // interaction with the search manager service
- private SearchableInfo mSearchable;
-
- // support for suggestions
- private String mUserQuery = null;
- private int mUserQuerySelStart;
- private int mUserQuerySelEnd;
- private boolean mLeaveJammedQueryOnRefocus = false;
- private String mPreviousSuggestionQuery = null;
- private int mPresetSelection = -1;
- private String mSuggestionAction = null;
- private Uri mSuggestionData = null;
- private String mSuggestionQuery = null;
-
- // For voice searching
- private Intent mVoiceWebSearchIntent;
- private Intent mVoiceAppSearchIntent;
-
- // support for AutoCompleteTextView suggestions display
- private SuggestionsAdapter mSuggestionsAdapter;
-
-
- /**
- * Constructor - fires it up and makes it look like the search UI.
- *
- * @param context Application Context we can use for system acess
- */
- public SearchDialog(Context context) {
- super(context, com.android.internal.R.style.Theme_SearchBar);
- }
-
- /**
- * We create the search dialog just once, and it stays around (hidden)
- * until activated by the user.
- */
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- Window theWindow = getWindow();
- theWindow.setGravity(Gravity.TOP|Gravity.FILL_HORIZONTAL);
-
- setContentView(com.android.internal.R.layout.search_bar);
-
- theWindow.setLayout(ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- WindowManager.LayoutParams lp = theWindow.getAttributes();
- lp.setTitle("Search Dialog");
- lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE;
- theWindow.setAttributes(lp);
-
- // get the view elements for local access
- mBadgeLabel = (TextView) findViewById(com.android.internal.R.id.search_badge);
- mSearchTextField = (AutoCompleteTextView)
- findViewById(com.android.internal.R.id.search_src_text);
- mGoButton = (Button) findViewById(com.android.internal.R.id.search_go_btn);
- mVoiceButton = (ImageButton) findViewById(com.android.internal.R.id.search_voice_btn);
-
- // attach listeners
- mSearchTextField.addTextChangedListener(mTextWatcher);
- mSearchTextField.setOnKeyListener(mTextKeyListener);
- mGoButton.setOnClickListener(mGoButtonClickListener);
- mGoButton.setOnKeyListener(mButtonsKeyListener);
- mVoiceButton.setOnClickListener(mVoiceButtonClickListener);
- mVoiceButton.setOnKeyListener(mButtonsKeyListener);
-
- // pre-hide all the extraneous elements
- mBadgeLabel.setVisibility(View.GONE);
-
- // Additional adjustments to make Dialog work for Search
-
- // Touching outside of the search dialog will dismiss it
- setCanceledOnTouchOutside(true);
-
- // Set up broadcast filters
- mCloseDialogsFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- mPackageFilter = new IntentFilter();
- mPackageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
- mPackageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- mPackageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- mPackageFilter.addDataScheme("package");
-
- // Save voice intent for later queries/launching
- mVoiceWebSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
- mVoiceWebSearchIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
- RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
-
- mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
- }
-
- /**
- * Set up the search dialog
- *
- * @param Returns true if search dialog launched, false if not
- */
- public boolean show(String initialQuery, boolean selectInitialQuery,
- ComponentName componentName, Bundle appSearchData, boolean globalSearch) {
- if (isShowing()) {
- // race condition - already showing but not handling events yet.
- // in this case, just discard the "show" request
- return true;
- }
-
- // Get searchable info from search manager and use to set up other elements of UI
- // Do this first so we can get out quickly if there's nothing to search
- ISearchManager sms;
- sms = ISearchManager.Stub.asInterface(ServiceManager.getService(Context.SEARCH_SERVICE));
- try {
- mSearchable = sms.getSearchableInfo(componentName, globalSearch);
- } catch (RemoteException e) {
- mSearchable = null;
- }
- if (mSearchable == null) {
- // unfortunately, we can't log here. it would be logspam every time the user
- // clicks the "search" key on a non-search app
- return false;
- }
-
- // OK, we're going to show ourselves
- super.show();
-
- setupSearchableInfo();
-
- mLaunchComponent = componentName;
- mAppSearchData = appSearchData;
- mGlobalSearchMode = globalSearch;
-
- // receive broadcasts
- getContext().registerReceiver(mBroadcastReceiver, mCloseDialogsFilter);
- getContext().registerReceiver(mBroadcastReceiver, mPackageFilter);
-
- // configure the autocomplete aspects of the input box
- mSearchTextField.setOnItemClickListener(this);
- mSearchTextField.setOnItemSelectedListener(this);
-
- // This conversion is necessary to force a preload of the EditText and thus force
- // suggestions to be presented (even for an empty query)
- if (initialQuery == null) {
- initialQuery = ""; // This forces the preload to happen, triggering suggestions
- }
-
- // attach the suggestions adapter, if suggestions are available
- // The existence of a suggestions authority is the proxy for "suggestions available here"
- if (mSearchable.getSuggestAuthority() == null) {
- mSuggestionsAdapter = null;
- mSearchTextField.setAdapter(mSuggestionsAdapter);
- mSearchTextField.setText(initialQuery);
- } else {
- mSuggestionsAdapter = new SuggestionsAdapter(getContext(), mSearchable);
- mSearchTextField.setAdapter(mSuggestionsAdapter);
-
- // finally, load the user's initial text (which may trigger suggestions)
- mSuggestionsAdapter.setNonUserQuery(false);
- mSearchTextField.setText(initialQuery);
- }
-
- if (selectInitialQuery) {
- mSearchTextField.selectAll();
- } else {
- mSearchTextField.setSelection(initialQuery.length());
- }
- return true;
- }
-
- /**
- * The default show() for this Dialog is not supported.
- */
- @Override
- public void show() {
- return;
- }
-
- /**
- * The search dialog is being dismissed, so handle all of the local shutdown operations.
- *
- * This function is designed to be idempotent so that dismiss() can be safely called at any time
- * (even if already closed) and more likely to really dump any memory. No leaks!
- */
- @Override
- public void onStop() {
- super.onStop();
-
- setOnCancelListener(null);
- setOnDismissListener(null);
-
- // stop receiving broadcasts (throws exception if none registered)
- try {
- getContext().unregisterReceiver(mBroadcastReceiver);
- } catch (RuntimeException e) {
- // This is OK - it just means we didn't have any registered
- }
-
- // close any leftover cursor
- if (mSuggestionsAdapter != null) {
- mSuggestionsAdapter.changeCursor(null);
- }
-
- // dump extra memory we're hanging on to
- mLaunchComponent = null;
- mAppSearchData = null;
- mSearchable = null;
- mSuggestionAction = null;
- mSuggestionData = null;
- mSuggestionQuery = null;
- mActivityContext = null;
- mPreviousSuggestionQuery = null;
- mUserQuery = null;
- }
-
- /**
- * Save the minimal set of data necessary to recreate the search
- *
- * @return A bundle with the state of the dialog.
- */
- @Override
- public Bundle onSaveInstanceState() {
- Bundle bundle = new Bundle();
-
- // setup info so I can recreate this particular search
- bundle.putParcelable(INSTANCE_KEY_COMPONENT, mLaunchComponent);
- bundle.putBundle(INSTANCE_KEY_APPDATA, mAppSearchData);
- bundle.putBoolean(INSTANCE_KEY_GLOBALSEARCH, mGlobalSearchMode);
-
- // UI state
- bundle.putString(INSTANCE_KEY_DISPLAY_QUERY, mSearchTextField.getText().toString());
- bundle.putInt(INSTANCE_KEY_DISPLAY_SEL_START, mSearchTextField.getSelectionStart());
- bundle.putInt(INSTANCE_KEY_DISPLAY_SEL_END, mSearchTextField.getSelectionEnd());
- bundle.putString(INSTANCE_KEY_USER_QUERY, mUserQuery);
- bundle.putString(INSTANCE_KEY_SUGGESTION_QUERY, mPreviousSuggestionQuery);
-
- int selectedElement = INSTANCE_SELECTED_QUERY;
- if (mGoButton.isFocused()) {
- selectedElement = INSTANCE_SELECTED_BUTTON;
- } else if (mSearchTextField.isPopupShowing()) {
- selectedElement = 0; // TODO mSearchTextField.getListSelection() // 0..n
- }
- bundle.putInt(INSTANCE_KEY_SELECTED_ELEMENT, selectedElement);
-
- return bundle;
- }
-
- /**
- * Restore the state of the dialog from a previously saved bundle.
- *
- * @param savedInstanceState The state of the dialog previously saved by
- * {@link #onSaveInstanceState()}.
- */
- @Override
- public void onRestoreInstanceState(Bundle savedInstanceState) {
- // Get the launch info
- ComponentName launchComponent = savedInstanceState.getParcelable(INSTANCE_KEY_COMPONENT);
- Bundle appSearchData = savedInstanceState.getBundle(INSTANCE_KEY_APPDATA);
- boolean globalSearch = savedInstanceState.getBoolean(INSTANCE_KEY_GLOBALSEARCH);
-
- // get the UI state
- String displayQuery = savedInstanceState.getString(INSTANCE_KEY_DISPLAY_QUERY);
- int querySelStart = savedInstanceState.getInt(INSTANCE_KEY_DISPLAY_SEL_START, -1);
- int querySelEnd = savedInstanceState.getInt(INSTANCE_KEY_DISPLAY_SEL_END, -1);
- String userQuery = savedInstanceState.getString(INSTANCE_KEY_USER_QUERY);
- int selectedElement = savedInstanceState.getInt(INSTANCE_KEY_SELECTED_ELEMENT);
- String suggestionQuery = savedInstanceState.getString(INSTANCE_KEY_SUGGESTION_QUERY);
-
- // show the dialog. skip any show/hide animation, we want to go fast.
- // send the text that actually generates the suggestions here; we'll replace the display
- // text as necessary in a moment.
- if (!show(suggestionQuery, false, launchComponent, appSearchData, globalSearch)) {
- // for some reason, we couldn't re-instantiate
- return;
- }
-
- if (mSuggestionsAdapter != null) {
- mSuggestionsAdapter.setNonUserQuery(true);
- }
- mSearchTextField.setText(displayQuery);
- // TODO because the new query is (not) processed in another thread, we can't just
- // take away this flag (yet). The better solution here is going to require a new API
- // in AutoCompleteTextView which allows us to change the text w/o changing the suggestions.
-// mSuggestionsAdapter.setNonUserQuery(false);
-
- // clean up the selection state
- switch (selectedElement) {
- case INSTANCE_SELECTED_BUTTON:
- mGoButton.setEnabled(true);
- mGoButton.setFocusable(true);
- mGoButton.requestFocus();
- break;
- case INSTANCE_SELECTED_QUERY:
- if (querySelStart >= 0 && querySelEnd >= 0) {
- mSearchTextField.requestFocus();
- mSearchTextField.setSelection(querySelStart, querySelEnd);
- }
- break;
- default:
- // defer selecting a list element until suggestion list appears
- mPresetSelection = selectedElement;
- // TODO mSearchTextField.setListSelection(selectedElement)
- break;
- }
- }
-
- /**
- * Hook for updating layout on a rotation
- *
- */
- public void onConfigurationChanged(Configuration newConfig) {
- if (isShowing()) {
- // Redraw (resources may have changed)
- updateSearchButton();
- updateSearchBadge();
- updateQueryHint();
- }
- }
-
- /**
- * Use SearchableInfo record (from search manager service) to preconfigure the UI in various
- * ways.
- */
- private void setupSearchableInfo() {
- if (mSearchable != null) {
- mActivityContext = mSearchable.getActivityContext(getContext());
-
- updateSearchButton();
- updateSearchBadge();
- updateQueryHint();
- updateVoiceButton();
-
- // In order to properly configure the input method (if one is being used), we
- // need to let it know if we'll be providing suggestions. Although it would be
- // difficult/expensive to know if every last detail has been configured properly, we
- // can at least see if a suggestions provider has been configured, and use that
- // as our trigger.
- int inputType = mSearchable.getInputType();
- // We only touch this if the input type is set up for text (which it almost certainly
- // should be, in the case of search!)
- if ((inputType & InputType.TYPE_MASK_CLASS) == InputType.TYPE_CLASS_TEXT) {
- // The existence of a suggestions authority is the proxy for "suggestions
- // are available here"
- inputType &= ~InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE;
- if (mSearchable.getSuggestAuthority() != null) {
- inputType |= InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE;
- }
- }
- mSearchTextField.setInputType(inputType);
- }
- }
-
- /**
- * The list of installed packages has just changed. This means that our current context
- * may no longer be valid. This would only happen if a package is installed/removed exactly
- * when the search bar is open. So for now we're just going to close the search
- * bar.
- *
- * Anything fancier would require some checks to see if the user's context was still valid.
- * Which would be messier.
- */
- public void onPackageListChange() {
- cancel();
- }
-
- /**
- * Update the text in the search button. Note: This is deprecated functionality, for
- * 1.0 compatibility only.
- */
- private void updateSearchButton() {
- String textLabel = null;
- Drawable iconLabel = null;
- int textId = mSearchable.getSearchButtonText();
- if (textId != 0) {
- textLabel = mActivityContext.getResources().getString(textId);
- } else {
- iconLabel = getContext().getResources().
- getDrawable(com.android.internal.R.drawable.ic_btn_search);
- }
- mGoButton.setText(textLabel);
- mGoButton.setCompoundDrawablesWithIntrinsicBounds(iconLabel, null, null, null);
- }
-
- /**
- * Setup the search "Badge" if request by mode flags.
- */
- private void updateSearchBadge() {
- // assume both hidden
- int visibility = View.GONE;
- Drawable icon = null;
- String text = null;
-
- // optionally show one or the other.
- if (mSearchable.mBadgeIcon) {
- icon = mActivityContext.getResources().getDrawable(mSearchable.getIconId());
- visibility = View.VISIBLE;
- } else if (mSearchable.mBadgeLabel) {
- text = mActivityContext.getResources().getText(mSearchable.getLabelId()).toString();
- visibility = View.VISIBLE;
- }
-
- mBadgeLabel.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
- mBadgeLabel.setText(text);
- mBadgeLabel.setVisibility(visibility);
- }
-
- /**
- * Update the hint in the query text field.
- */
- private void updateQueryHint() {
- if (isShowing()) {
- String hint = null;
- if (mSearchable != null) {
- int hintId = mSearchable.getHintId();
- if (hintId != 0) {
- hint = mActivityContext.getString(hintId);
- }
- }
- mSearchTextField.setHint(hint);
- }
- }
-
- /**
- * Update the visibility of the voice button. There are actually two voice search modes,
- * either of which will activate the button.
- */
- private void updateVoiceButton() {
- int visibility = View.GONE;
- if (mSearchable.getVoiceSearchEnabled()) {
- Intent testIntent = null;
- if (mSearchable.getVoiceSearchLaunchWebSearch()) {
- testIntent = mVoiceWebSearchIntent;
- } else if (mSearchable.getVoiceSearchLaunchRecognizer()) {
- testIntent = mVoiceAppSearchIntent;
- }
- if (testIntent != null) {
- ResolveInfo ri = getContext().getPackageManager().
- resolveActivity(testIntent, PackageManager.MATCH_DEFAULT_ONLY);
- if (ri != null) {
- visibility = View.VISIBLE;
- }
- }
- }
- mVoiceButton.setVisibility(visibility);
- }
-
- /**
- * Listeners of various types
- */
-
- /**
- * Dialog's OnKeyListener implements various search-specific functionality
- *
- * @param keyCode This is the keycode of the typed key, and is the same value as
- * found in the KeyEvent parameter.
- * @param event The complete event record for the typed key
- *
- * @return Return true if the event was handled here, or false if not.
- */
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_BACK:
- cancel();
- return true;
- case KeyEvent.KEYCODE_SEARCH:
- if (TextUtils.getTrimmedLength(mSearchTextField.getText()) != 0) {
- launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null);
- } else {
- cancel();
- }
- return true;
- default:
- SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
- if ((actionKey != null) && (actionKey.mQueryActionMsg != null)) {
- launchQuerySearch(keyCode, actionKey.mQueryActionMsg);
- return true;
- }
- break;
- }
- return false;
- }
-
- /**
- * Callback to watch the textedit field for empty/non-empty
- */
- private TextWatcher mTextWatcher = new TextWatcher() {
-
- public void beforeTextChanged(CharSequence s, int start, int
- before, int after) { }
-
- public void onTextChanged(CharSequence s, int start,
- int before, int after) {
- if (DBG_LOG_TIMING == 1) {
- dbgLogTiming("onTextChanged()");
- }
- updateWidgetState();
- // Only do suggestions if actually typed by user
- if ((mSuggestionsAdapter != null) && !mSuggestionsAdapter.getNonUserQuery()) {
- mPreviousSuggestionQuery = s.toString();
- mUserQuery = mSearchTextField.getText().toString();
- mUserQuerySelStart = mSearchTextField.getSelectionStart();
- mUserQuerySelEnd = mSearchTextField.getSelectionEnd();
- }
- }
-
- public void afterTextChanged(Editable s) { }
- };
-
- /**
- * Enable/Disable the cancel button based on edit text state (any text?)
- */
- private void updateWidgetState() {
- // enable the button if we have one or more non-space characters
- boolean enabled =
- TextUtils.getTrimmedLength(mSearchTextField.getText()) != 0;
-
- mGoButton.setEnabled(enabled);
- mGoButton.setFocusable(enabled);
- }
-
- private final static String[] ONE_LINE_FROM = {SearchManager.SUGGEST_COLUMN_TEXT_1 };
- private final static String[] ONE_LINE_ICONS_FROM = {SearchManager.SUGGEST_COLUMN_TEXT_1,
- SearchManager.SUGGEST_COLUMN_ICON_1,
- SearchManager.SUGGEST_COLUMN_ICON_2};
- private final static String[] TWO_LINE_FROM = {SearchManager.SUGGEST_COLUMN_TEXT_1,
- SearchManager.SUGGEST_COLUMN_TEXT_2 };
- private final static String[] TWO_LINE_ICONS_FROM = {SearchManager.SUGGEST_COLUMN_TEXT_1,
- SearchManager.SUGGEST_COLUMN_TEXT_2,
- SearchManager.SUGGEST_COLUMN_ICON_1,
- SearchManager.SUGGEST_COLUMN_ICON_2 };
-
- private final static int[] ONE_LINE_TO = {com.android.internal.R.id.text1};
- private final static int[] ONE_LINE_ICONS_TO = {com.android.internal.R.id.text1,
- com.android.internal.R.id.icon1,
- com.android.internal.R.id.icon2};
- private final static int[] TWO_LINE_TO = {com.android.internal.R.id.text1,
- com.android.internal.R.id.text2};
- private final static int[] TWO_LINE_ICONS_TO = {com.android.internal.R.id.text1,
- com.android.internal.R.id.text2,
- com.android.internal.R.id.icon1,
- com.android.internal.R.id.icon2};
-
- /**
- * Safely retrieve the suggestions cursor adapter from the ListView
- *
- * @param adapterView The ListView containing our adapter
- * @result The CursorAdapter that we installed, or null if not set
- */
- private static CursorAdapter getSuggestionsAdapter(AdapterView<?> adapterView) {
- CursorAdapter result = null;
- if (adapterView != null) {
- Object ad = adapterView.getAdapter();
- if (ad instanceof CursorAdapter) {
- result = (CursorAdapter) ad;
- } else if (ad instanceof WrapperListAdapter) {
- result = (CursorAdapter) ((WrapperListAdapter)ad).getWrappedAdapter();
- }
- }
- return result;
- }
-
- /**
- * React to typing in the GO search button by refocusing to EditText.
- * Continue typing the query.
- */
- View.OnKeyListener mButtonsKeyListener = new View.OnKeyListener() {
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- // also guard against possible race conditions (late arrival after dismiss)
- if (mSearchable != null) {
- return refocusingKeyListener(v, keyCode, event);
- }
- return false;
- }
- };
-
- /**
- * React to a click in the GO button by launching a search.
- */
- View.OnClickListener mGoButtonClickListener = new View.OnClickListener() {
- public void onClick(View v) {
- // also guard against possible race conditions (late arrival after dismiss)
- if (mSearchable != null) {
- launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null);
- }
- }
- };
-
- /**
- * React to a click in the voice search button.
- */
- View.OnClickListener mVoiceButtonClickListener = new View.OnClickListener() {
- public void onClick(View v) {
- try {
- if (mSearchable.getVoiceSearchLaunchWebSearch()) {
- getContext().startActivity(mVoiceWebSearchIntent);
- dismiss();
- } else if (mSearchable.getVoiceSearchLaunchRecognizer()) {
- Intent appSearchIntent = createVoiceAppSearchIntent(mVoiceAppSearchIntent);
- getContext().startActivity(appSearchIntent);
- dismiss();
- }
- } catch (ActivityNotFoundException e) {
- // Should not happen, since we check the availability of
- // voice search before showing the button. But just in case...
- Log.w(LOG_TAG, "Could not find voice search activity");
- }
- }
- };
-
- /**
- * Create and return an Intent that can launch the voice search activity, perform a specific
- * voice transcription, and forward the results to the searchable activity.
- *
- * @param baseIntent The voice app search intent to start from
- * @return A completely-configured intent ready to send to the voice search activity
- */
- private Intent createVoiceAppSearchIntent(Intent baseIntent) {
- // create the necessary intent to set up a search-and-forward operation
- // in the voice search system. We have to keep the bundle separate,
- // because it becomes immutable once it enters the PendingIntent
- Intent queryIntent = new Intent(Intent.ACTION_SEARCH);
- queryIntent.setComponent(mSearchable.mSearchActivity);
- PendingIntent pending = PendingIntent.getActivity(
- getContext(), 0, queryIntent, PendingIntent.FLAG_ONE_SHOT);
-
- // Now set up the bundle that will be inserted into the pending intent
- // when it's time to do the search. We always build it here (even if empty)
- // because the voice search activity will always need to insert "QUERY" into
- // it anyway.
- Bundle queryExtras = new Bundle();
- if (mAppSearchData != null) {
- queryExtras.putBundle(SearchManager.APP_DATA, mAppSearchData);
- }
-
- // Now build the intent to launch the voice search. Add all necessary
- // extras to launch the voice recognizer, and then all the necessary extras
- // to forward the results to the searchable activity
- Intent voiceIntent = new Intent(baseIntent);
-
- // Add all of the configuration options supplied by the searchable's metadata
- String languageModel = RecognizerIntent.LANGUAGE_MODEL_FREE_FORM;
- String prompt = null;
- String language = null;
- int maxResults = 1;
- Resources resources = mActivityContext.getResources();
- if (mSearchable.getVoiceLanguageModeId() != 0) {
- languageModel = resources.getString(mSearchable.getVoiceLanguageModeId());
- }
- if (mSearchable.getVoicePromptTextId() != 0) {
- prompt = resources.getString(mSearchable.getVoicePromptTextId());
- }
- if (mSearchable.getVoiceLanguageId() != 0) {
- language = resources.getString(mSearchable.getVoiceLanguageId());
- }
- if (mSearchable.getVoiceMaxResults() != 0) {
- maxResults = mSearchable.getVoiceMaxResults();
- }
- voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, languageModel);
- voiceIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt);
- voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
- voiceIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, maxResults);
-
- // Add the values that configure forwarding the results
- voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT, pending);
- voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT_BUNDLE, queryExtras);
-
- return voiceIntent;
- }
-
- /**
- * React to the user typing "enter" or other hardwired keys while typing in the search box.
- * This handles these special keys while the edit box has focus.
- */
- View.OnKeyListener mTextKeyListener = new View.OnKeyListener() {
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- cancel();
- return true;
- }
- // also guard against possible race conditions (late arrival after dismiss)
- if (mSearchable != null &&
- TextUtils.getTrimmedLength(mSearchTextField.getText()) > 0) {
- if (DBG_LOG_TIMING == 1) {
- dbgLogTiming("doTextKey()");
- }
- // dispatch "typing in the list" first
- if (mSearchTextField.isPopupShowing() &&
- mSearchTextField.getListSelection() != ListView.INVALID_POSITION) {
- return onSuggestionsKey(v, keyCode, event);
- }
- // otherwise, dispatch an "edit view" key
- switch (keyCode) {
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- if (event.getAction() == KeyEvent.ACTION_UP) {
- v.cancelLongPress();
- launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null);
- return true;
- }
- break;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- // capture the EditText state, so we can restore the user entry later
- mUserQuery = mSearchTextField.getText().toString();
- mUserQuerySelStart = mSearchTextField.getSelectionStart();
- mUserQuerySelEnd = mSearchTextField.getSelectionEnd();
- // pass through - we're just watching here
- break;
- default:
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
- if ((actionKey != null) && (actionKey.mQueryActionMsg != null)) {
- launchQuerySearch(keyCode, actionKey.mQueryActionMsg);
- return true;
- }
- }
- break;
- }
- }
- return false;
- }
- };
-
- /**
- * React to the user typing while the suggestions are focused. First, check for action
- * keys. If not handled, try refocusing regular characters into the EditText. In this case,
- * replace the query text (start typing fresh text).
- */
- private boolean onSuggestionsKey(View v, int keyCode, KeyEvent event) {
- boolean handled = false;
- // also guard against possible race conditions (late arrival after dismiss)
- if (mSearchable != null) {
- handled = doSuggestionsKey(v, keyCode, event);
- }
- return handled;
- }
-
- /**
- * Per UI design, we're going to "steer" any typed keystrokes back into the EditText
- * box, even if the user has navigated the focus to the dropdown or to the GO button.
- *
- * @param v The view into which the keystroke was typed
- * @param keyCode keyCode of entered key
- * @param event Full KeyEvent record of entered key
- */
- private boolean refocusingKeyListener(View v, int keyCode, KeyEvent event) {
- boolean handled = false;
-
- if (!event.isSystem() &&
- (keyCode != KeyEvent.KEYCODE_DPAD_UP) &&
- (keyCode != KeyEvent.KEYCODE_DPAD_DOWN) &&
- (keyCode != KeyEvent.KEYCODE_DPAD_LEFT) &&
- (keyCode != KeyEvent.KEYCODE_DPAD_RIGHT) &&
- (keyCode != KeyEvent.KEYCODE_DPAD_CENTER)) {
- // restore focus and give key to EditText ...
- // but don't replace the user's query
- mLeaveJammedQueryOnRefocus = true;
- if (mSearchTextField.requestFocus()) {
- handled = mSearchTextField.dispatchKeyEvent(event);
- }
- mLeaveJammedQueryOnRefocus = false;
- }
- return handled;
- }
-
- /**
- * Update query text based on transitions in and out of suggestions list.
- */
- /*
- * TODO - figure out if this logic is required for the autocomplete text view version
-
- OnFocusChangeListener mSuggestFocusListener = new OnFocusChangeListener() {
- public void onFocusChange(View v, boolean hasFocus) {
- // also guard against possible race conditions (late arrival after dismiss)
- if (mSearchable == null) {
- return;
- }
- // Update query text based on navigation in to/out of the suggestions list
- if (hasFocus) {
- // Entering the list view - record selection point from user's query
- mUserQuery = mSearchTextField.getText().toString();
- mUserQuerySelStart = mSearchTextField.getSelectionStart();
- mUserQuerySelEnd = mSearchTextField.getSelectionEnd();
- // then update the query to match the entered selection
- jamSuggestionQuery(true, mSuggestionsList,
- mSuggestionsList.getSelectedItemPosition());
- } else {
- // Exiting the list view
-
- if (mSuggestionsList.getSelectedItemPosition() < 0) {
- // Direct exit - Leave new suggestion in place (do nothing)
- } else {
- // Navigation exit - restore user's query text
- if (!mLeaveJammedQueryOnRefocus) {
- jamSuggestionQuery(false, null, -1);
- }
- }
- }
-
- }
- };
- */
-
- /**
- * This is the listener for the ACTION_CLOSE_SYSTEM_DIALOGS intent. It's an indication that
- * we should close ourselves immediately, in order to allow a higher-priority UI to take over
- * (e.g. phone call received).
- */
- private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
- cancel();
- } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)
- || Intent.ACTION_PACKAGE_REMOVED.equals(action)
- || Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
- onPackageListChange();
- }
- }
- };
-
- /**
- * Various ways to launch searches
- */
-
- /**
- * React to the user clicking the "GO" button. Hide the UI and launch a search.
- *
- * @param actionKey Pass a keycode if the launch was triggered by an action key. Pass
- * KeyEvent.KEYCODE_UNKNOWN for no actionKey code.
- * @param actionMsg Pass the suggestion-provided message if the launch was triggered by an
- * action key. Pass null for no actionKey message.
- */
- private void launchQuerySearch(int actionKey, final String actionMsg) {
- final String query = mSearchTextField.getText().toString();
- final Bundle appData = mAppSearchData;
- final SearchableInfo si = mSearchable; // cache briefly (dismiss() nulls it)
- dismiss();
- sendLaunchIntent(Intent.ACTION_SEARCH, null, query, appData, actionKey, actionMsg, si);
- }
-
- /**
- * React to the user typing an action key while in the suggestions list
- */
- private boolean doSuggestionsKey(View v, int keyCode, KeyEvent event) {
- // Exit early in case of race condition
- if (mSuggestionsAdapter == null) {
- return false;
- }
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- if (DBG_LOG_TIMING == 1) {
- dbgLogTiming("doSuggestionsKey()");
- }
-
- // First, check for enter or search (both of which we'll treat as a "click")
- if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_SEARCH) {
- int position = mSearchTextField.getListSelection();
- return launchSuggestion(mSuggestionsAdapter, position);
- }
-
- // Next, check for left/right moves, which we use to "return" the user to the edit view
- if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
- // give "focus" to text editor, but don't restore the user's original query
- int selPoint = (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) ?
- 0 : mSearchTextField.length();
- mSearchTextField.setSelection(selPoint);
- mSearchTextField.setListSelection(0);
- mSearchTextField.clearListSelection();
- return true;
- }
-
- // Next, check for an "up and out" move
- if (keyCode == KeyEvent.KEYCODE_DPAD_UP && 0 == mSearchTextField.getListSelection()) {
- jamSuggestionQuery(false, null, -1);
- // let ACTV complete the move
- return false;
- }
-
- // Next, check for an "action key"
- SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
- if ((actionKey != null) &&
- ((actionKey.mSuggestActionMsg != null) ||
- (actionKey.mSuggestActionMsgColumn != null))) {
- // launch suggestion using action key column
- int position = mSearchTextField.getListSelection();
- if (position >= 0) {
- Cursor c = mSuggestionsAdapter.getCursor();
- if (c.moveToPosition(position)) {
- final String actionMsg = getActionKeyMessage(c, actionKey);
- if (actionMsg != null && (actionMsg.length() > 0)) {
- // shut down search bar and launch the activity
- // cache everything we need because dismiss releases mems
- setupSuggestionIntent(c, mSearchable);
- final String query = mSearchTextField.getText().toString();
- final Bundle appData = mAppSearchData;
- SearchableInfo si = mSearchable;
- String suggestionAction = mSuggestionAction;
- Uri suggestionData = mSuggestionData;
- String suggestionQuery = mSuggestionQuery;
- dismiss();
- sendLaunchIntent(suggestionAction, suggestionData,
- suggestionQuery, appData,
- keyCode, actionMsg, si);
- return true;
- }
- }
- }
- }
- }
- return false;
- }
-
- /**
- * Set or reset the user query to follow the selections in the suggestions
- *
- * @param jamQuery True means to set the query, false means to reset it to the user's choice
- */
- private void jamSuggestionQuery(boolean jamQuery, AdapterView<?> parent, int position) {
- // quick check against race conditions
- if (mSearchable == null) {
- return;
- }
-
- mSuggestionsAdapter.setNonUserQuery(true); // disables any suggestions processing
- if (jamQuery) {
- CursorAdapter ca = getSuggestionsAdapter(parent);
- Cursor c = ca.getCursor();
- if (c.moveToPosition(position)) {
- setupSuggestionIntent(c, mSearchable);
- String jamText = null;
-
- // Simple heuristic for selecting text with which to rewrite the query.
- if (mSuggestionQuery != null) {
- jamText = mSuggestionQuery;
- } else if (mSearchable.mQueryRewriteFromData && (mSuggestionData != null)) {
- jamText = mSuggestionData.toString();
- } else if (mSearchable.mQueryRewriteFromText) {
- try {
- int column = c.getColumnIndexOrThrow(SearchManager.SUGGEST_COLUMN_TEXT_1);
- jamText = c.getString(column);
- } catch (RuntimeException e) {
- // no work here, jamText is null
- }
- }
- if (jamText != null) {
- mSearchTextField.setText(jamText);
- /* mSearchTextField.selectAll(); */ // this didn't work anyway in the old UI
- // TODO this is only needed in the model where we have a selection in the ACTV
- // and in the dropdown at the same time.
- mSearchTextField.setSelection(jamText.length());
- }
- }
- } else {
- // reset user query
- mSearchTextField.setText(mUserQuery);
- try {
- mSearchTextField.setSelection(mUserQuerySelStart, mUserQuerySelEnd);
- } catch (IndexOutOfBoundsException e) {
- // In case of error, just select all
- Log.e(LOG_TAG, "Caught IndexOutOfBoundsException while setting selection. " +
- "start=" + mUserQuerySelStart + " end=" + mUserQuerySelEnd +
- " text=\"" + mUserQuery + "\"");
- mSearchTextField.selectAll();
- }
- }
- // TODO because the new query is (not) processed in another thread, we can't just
- // take away this flag (yet). The better solution here is going to require a new API
- // in AutoCompleteTextView which allows us to change the text w/o changing the suggestions.
-// mSuggestionsAdapter.setNonUserQuery(false);
- }
-
- /**
- * Assemble a search intent and send it.
- *
- * @param action The intent to send, typically Intent.ACTION_SEARCH
- * @param data The data for the intent
- * @param query The user text entered (so far)
- * @param appData The app data bundle (if supplied)
- * @param actionKey If the intent was triggered by an action key, e.g. KEYCODE_CALL, it will
- * be sent here. Pass KeyEvent.KEYCODE_UNKNOWN for no actionKey code.
- * @param actionMsg If the intent was triggered by an action key, e.g. KEYCODE_CALL, the
- * corresponding tag message will be sent here. Pass null for no actionKey message.
- * @param si Reference to the current SearchableInfo. Passed here so it can be used even after
- * we've called dismiss(), which attempts to null mSearchable.
- */
- private void sendLaunchIntent(final String action, final Uri data, final String query,
- final Bundle appData, int actionKey, final String actionMsg, final SearchableInfo si) {
- Intent launcher = new Intent(action);
-
- if (query != null) {
- launcher.putExtra(SearchManager.QUERY, query);
- }
-
- if (data != null) {
- launcher.setData(data);
- }
-
- if (appData != null) {
- launcher.putExtra(SearchManager.APP_DATA, appData);
- }
-
- // add launch info (action key, etc.)
- if (actionKey != KeyEvent.KEYCODE_UNKNOWN) {
- launcher.putExtra(SearchManager.ACTION_KEY, actionKey);
- launcher.putExtra(SearchManager.ACTION_MSG, actionMsg);
- }
-
- // attempt to enforce security requirement (no 3rd-party intents)
- launcher.setComponent(si.mSearchActivity);
-
- getContext().startActivity(launcher);
- }
-
- /**
- * Shared code for launching a query from a suggestion.
- * @param ca The cursor adapter containing the suggestions
- * @param position The suggestion we'll be launching from
- * @return true if a successful launch, false if could not (e.g. bad position)
- */
- private boolean launchSuggestion(CursorAdapter ca, int position) {
- Cursor c = ca.getCursor();
- if ((c != null) && c.moveToPosition(position)) {
- setupSuggestionIntent(c, mSearchable);
-
- final Bundle appData = mAppSearchData;
- SearchableInfo si = mSearchable;
- String suggestionAction = mSuggestionAction;
- Uri suggestionData = mSuggestionData;
- String suggestionQuery = mSuggestionQuery;
- dismiss();
- sendLaunchIntent(suggestionAction, suggestionData, suggestionQuery, appData,
- KeyEvent.KEYCODE_UNKNOWN, null, si);
- return true;
- }
- return false;
- }
-
- /**
- * When a particular suggestion has been selected, perform the various lookups required
- * to use the suggestion. This includes checking the cursor for suggestion-specific data,
- * and/or falling back to the XML for defaults; It also creates REST style Uri data when
- * the suggestion includes a data id.
- *
- * NOTE: Return values are in member variables mSuggestionAction & mSuggestionData.
- *
- * @param c The suggestions cursor, moved to the row of the user's selection
- * @param si The searchable activity's info record
- */
- void setupSuggestionIntent(Cursor c, SearchableInfo si) {
- try {
- // use specific action if supplied, or default action if supplied, or fixed default
- mSuggestionAction = null;
- int mColumn = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_ACTION);
- if (mColumn >= 0) {
- final String action = c.getString(mColumn);
- if (action != null) {
- mSuggestionAction = action;
- }
- }
- if (mSuggestionAction == null) {
- mSuggestionAction = si.getSuggestIntentAction();
- }
- if (mSuggestionAction == null) {
- mSuggestionAction = Intent.ACTION_SEARCH;
- }
-
- // use specific data if supplied, or default data if supplied
- String data = null;
- mColumn = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_DATA);
- if (mColumn >= 0) {
- final String rowData = c.getString(mColumn);
- if (rowData != null) {
- data = rowData;
- }
- }
- if (data == null) {
- data = si.getSuggestIntentData();
- }
-
- // then, if an ID was provided, append it.
- if (data != null) {
- mColumn = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
- if (mColumn >= 0) {
- final String id = c.getString(mColumn);
- if (id != null) {
- data = data + "/" + Uri.encode(id);
- }
- }
- }
- mSuggestionData = (data == null) ? null : Uri.parse(data);
-
- mSuggestionQuery = null;
- mColumn = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_QUERY);
- if (mColumn >= 0) {
- final String query = c.getString(mColumn);
- if (query != null) {
- mSuggestionQuery = query;
- }
- }
- } catch (RuntimeException e ) {
- int rowNum;
- try { // be really paranoid now
- rowNum = c.getPosition();
- } catch (RuntimeException e2 ) {
- rowNum = -1;
- }
- Log.w(LOG_TAG, "Search Suggestions cursor at row " + rowNum +
- " returned exception" + e.toString());
- }
- }
-
- /**
- * For a given suggestion and a given cursor row, get the action message. If not provided
- * by the specific row/column, also check for a single definition (for the action key).
- *
- * @param c The cursor providing suggestions
- * @param actionKey The actionkey record being examined
- *
- * @return Returns a string, or null if no action key message for this suggestion
- */
- private String getActionKeyMessage(Cursor c, final SearchableInfo.ActionKeyInfo actionKey) {
- String result = null;
- // check first in the cursor data, for a suggestion-specific message
- final String column = actionKey.mSuggestActionMsgColumn;
- if (column != null) {
- try {
- int colId = c.getColumnIndexOrThrow(column);
- result = c.getString(colId);
- } catch (RuntimeException e) {
- // OK - result is already null
- }
- }
- // If the cursor didn't give us a message, see if there's a single message defined
- // for the actionkey (for all suggestions)
- if (result == null) {
- result = actionKey.mSuggestActionMsg;
- }
- return result;
- }
-
- /**
- * Local subclass for AutoCompleteTextView
- *
- * This exists entirely to override the threshold method. Otherwise we just use the class
- * as-is.
- */
- public static class SearchAutoComplete extends AutoCompleteTextView {
-
- public SearchAutoComplete(Context context) {
- super(null);
- }
-
- public SearchAutoComplete(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public SearchAutoComplete(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- /**
- * We never allow ACTV to automatically replace the text, since we use "jamSuggestionQuery"
- * to do that. There's no point in letting ACTV do this here, because in the search UI,
- * as soon as we click a suggestion, we're going to start shutting things down.
- */
- @Override
- public void replaceText(CharSequence text) {
- }
-
- /**
- * We always return true, so that the effective threshold is "zero". This allows us
- * to provide "null" suggestions such as "just show me some recent entries".
- */
- @Override
- public boolean enoughToFilter() {
- return true;
- }
- }
-
- /**
- * Support for AutoCompleteTextView-based suggestions
- */
- /**
- * This class provides the filtering-based interface to suggestions providers.
- * It is hardwired in a couple of places to support GoogleSearch - for example, it supports
- * two-line suggestions, but it does not support icons.
- */
- private static class SuggestionsAdapter extends SimpleCursorAdapter {
- private final String TAG = "SuggestionsAdapter";
-
- SearchableInfo mSearchable;
- private Resources mProviderResources;
-
- // These private variables are shared by the filter thread and must be protected
- private WeakReference<Cursor> mRecentCursor = new WeakReference<Cursor>(null);
- private boolean mNonUserQuery = false;
-
- public SuggestionsAdapter(Context context, SearchableInfo searchable) {
- super(context, -1, null, null, null);
- mSearchable = searchable;
-
- // set up provider resources (gives us icons, etc.)
- Context activityContext = mSearchable.getActivityContext(mContext);
- Context providerContext = mSearchable.getProviderContext(mContext, activityContext);
- mProviderResources = providerContext.getResources();
- }
-
- /**
- * Set this field (temporarily!) to disable suggestions updating. This allows us
- * to change the string in the text view without changing the suggestions list.
- */
- public void setNonUserQuery(boolean nonUserQuery) {
- synchronized (this) {
- mNonUserQuery = nonUserQuery;
- }
- }
-
- public boolean getNonUserQuery() {
- synchronized (this) {
- return mNonUserQuery;
- }
- }
-
- /**
- * Use the search suggestions provider to obtain a live cursor. This will be called
- * in a worker thread, so it's OK if the query is slow (e.g. round trip for suggestions).
- * The results will be processed in the UI thread and changeCursor() will be called.
- *
- * In order to provide the Search Mgr functionality of seeing your query change as you
- * scroll through the list, we have to be able to jam new text into the string without
- * retriggering the suggestions. We do that here via the "nonUserQuery" flag. In that
- * case we simply return the existing cursor.
- *
- * TODO: Dianne suggests that this should simply be promoted into an AutoCompleteTextView
- * behavior (perhaps optionally).
- *
- * TODO: The "nonuserquery" logic has a race condition because it happens in another thread.
- * This also needs to be fixed.
- */
- @Override
- public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
- String query = (constraint == null) ? "" : constraint.toString();
- Cursor c = null;
- synchronized (this) {
- if (mNonUserQuery) {
- c = mRecentCursor.get();
- mNonUserQuery = false;
- }
- }
- if (c == null) {
- c = getSuggestions(mSearchable, query);
- synchronized (this) {
- mRecentCursor = new WeakReference<Cursor>(c);
- }
- }
- return c;
- }
-
- /**
- * Overriding changeCursor() allows us to change not only the cursor, but by sampling
- * the cursor's columns, the actual display characteristics of the list.
- */
- @Override
- public void changeCursor(Cursor c) {
-
- // first, check for various conditions that disqualify this cursor
- if ((c == null) || (c.getCount() == 0)) {
- // no cursor, or cursor with no data
- changeCursorAndColumns(null, null, null);
- if (c != null) {
- c.close();
- }
- return;
- }
-
- // check cursor before trying to create list views from it
- int colId = c.getColumnIndex("_id");
- int col1 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1);
- int col2 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2);
- int colIc1 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1);
- int colIc2 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2);
-
- boolean minimal = (colId >= 0) && (col1 >= 0);
- boolean hasIcons = (colIc1 >= 0) && (colIc2 >= 0);
- boolean has2Lines = col2 >= 0;
-
- if (minimal) {
- int layout;
- String[] from;
- int[] to;
-
- if (hasIcons) {
- if (has2Lines) {
- layout = com.android.internal.R.layout.search_dropdown_item_icons_2line;
- from = TWO_LINE_ICONS_FROM;
- to = TWO_LINE_ICONS_TO;
- } else {
- layout = com.android.internal.R.layout.search_dropdown_item_icons_1line;
- from = ONE_LINE_ICONS_FROM;
- to = ONE_LINE_ICONS_TO;
- }
- } else {
- if (has2Lines) {
- layout = com.android.internal.R.layout.search_dropdown_item_2line;
- from = TWO_LINE_FROM;
- to = TWO_LINE_TO;
- } else {
- layout = com.android.internal.R.layout.search_dropdown_item_1line;
- from = ONE_LINE_FROM;
- to = ONE_LINE_TO;
- }
- }
- // Now actually set up the cursor, columns, and the list view
- changeCursorAndColumns(c, from, to);
- setViewResource(layout);
- } else {
- // Provide some help for developers instead of just silently discarding
- Log.w(LOG_TAG, "Suggestions cursor discarded due to missing required columns.");
- changeCursorAndColumns(null, null, null);
- c.close();
- }
- if ((colIc1 >= 0) != (colIc2 >= 0)) {
- Log.w(LOG_TAG, "Suggestion icon column(s) discarded, must be 0 or 2 columns.");
- }
- }
-
- /**
- * Overriding this allows us to write the selected query back into the box.
- * NOTE: This is a vastly simplified version of SearchDialog.jamQuery() and does
- * not universally support the search API. But it is sufficient for Google Search.
- */
- @Override
- public CharSequence convertToString(Cursor cursor) {
- CharSequence result = null;
- if (cursor != null) {
- int column = cursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_QUERY);
- if (column >= 0) {
- final String query = cursor.getString(column);
- if (query != null) {
- result = query;
- }
- }
- }
- return result;
- }
-
- /**
- * Get the query cursor for the search suggestions.
- *
- * TODO this is functionally identical to the version in SearchDialog.java. Perhaps it
- * could be hoisted into SearchableInfo or some other shared spot.
- *
- * @param query The search text entered (so far)
- * @return Returns a cursor with suggestions, or null if no suggestions
- */
- private Cursor getSuggestions(final SearchableInfo searchable, final String query) {
- Cursor cursor = null;
- if (searchable.getSuggestAuthority() != null) {
- try {
- StringBuilder uriStr = new StringBuilder("content://");
- uriStr.append(searchable.getSuggestAuthority());
-
- // if content path provided, insert it now
- final String contentPath = searchable.getSuggestPath();
- if (contentPath != null) {
- uriStr.append('/');
- uriStr.append(contentPath);
- }
-
- // append standard suggestion query path
- uriStr.append('/' + SearchManager.SUGGEST_URI_PATH_QUERY);
-
- // inject query, either as selection args or inline
- String[] selArgs = null;
- if (searchable.getSuggestSelection() != null) { // use selection if provided
- selArgs = new String[] {query};
- } else {
- uriStr.append('/'); // no sel, use REST pattern
- uriStr.append(Uri.encode(query));
- }
-
- // finally, make the query
- cursor = mContext.getContentResolver().query(
- Uri.parse(uriStr.toString()), null,
- searchable.getSuggestSelection(), selArgs,
- null);
- } catch (RuntimeException e) {
- Log.w(TAG, "Search Suggestions query returned exception " + e.toString());
- cursor = null;
- }
- }
-
- return cursor;
- }
-
- /**
- * Overriding this allows us to affect the way that an icon is loaded. Specifically,
- * we can be more controlling about the resource path (and allow icons to come from other
- * packages).
- *
- * TODO: This is 100% identical to the version in SearchDialog.java
- *
- * @param v ImageView to receive an image
- * @param value the value retrieved from the cursor
- */
- @Override
- public void setViewImage(ImageView v, String value) {
- int resID;
- Drawable img = null;
-
- try {
- resID = Integer.parseInt(value);
- if (resID != 0) {
- img = mProviderResources.getDrawable(resID);
- }
- } catch (NumberFormatException nfe) {
- // img = null;
- } catch (NotFoundException e2) {
- // img = null;
- }
-
- // finally, set the image to whatever we've gotten
- v.setImageDrawable(img);
- }
-
- /**
- * This method is overridden purely to provide a bit of protection against
- * flaky content providers.
- *
- * TODO: This is 100% identical to the version in SearchDialog.java
- *
- * @see android.widget.ListAdapter#getView(int, View, ViewGroup)
- */
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- try {
- return super.getView(position, convertView, parent);
- } catch (RuntimeException e) {
- Log.w(TAG, "Search Suggestions cursor returned exception " + e.toString());
- // what can I return here?
- View v = newView(mContext, mCursor, parent);
- if (v != null) {
- TextView tv = (TextView) v.findViewById(com.android.internal.R.id.text1);
- tv.setText(e.toString());
- }
- return v;
- }
- }
-
- }
-
- /**
- * Implements OnItemClickListener
- */
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- // Log.d(LOG_TAG, "onItemClick() position " + position);
- launchSuggestion(mSuggestionsAdapter, position);
- }
-
- /**
- * Implements OnItemSelectedListener
- */
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- // Log.d(LOG_TAG, "onItemSelected() position " + position);
- jamSuggestionQuery(true, parent, position);
- }
-
- /**
- * Implements OnItemSelectedListener
- */
- public void onNothingSelected(AdapterView<?> parent) {
- // Log.d(LOG_TAG, "onNothingSelected()");
- }
-
- /**
- * Debugging Support
- */
-
- /**
- * For debugging only, sample the millisecond clock and log it.
- * Uses AtomicLong so we can use in multiple threads
- */
- private AtomicLong mLastLogTime = new AtomicLong(SystemClock.uptimeMillis());
- private void dbgLogTiming(final String caller) {
- long millis = SystemClock.uptimeMillis();
- long oldTime = mLastLogTime.getAndSet(millis);
- long delta = millis - oldTime;
- final String report = millis + " (+" + delta + ") ticks for Search keystroke in " + caller;
- Log.d(LOG_TAG,report);
- }
-}
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
deleted file mode 100644
index 2cc6de9..0000000
--- a/core/java/android/app/SearchManager.java
+++ /dev/null
@@ -1,1377 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ServiceManager;
-import android.view.KeyEvent;
-
-/**
- * This class provides access to the system search services.
- *
- * <p>In practice, you won't interact with this class directly, as search
- * services are provided through methods in {@link android.app.Activity Activity}
- * methods and the the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
- * {@link android.content.Intent Intent}. This class does provide a basic
- * overview of search services and how to integrate them with your activities.
- * If you do require direct access to the Search Manager, do not instantiate
- * this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * context.getSystemService(Context.SEARCH_SERVICE)}.
- *
- * <p>Topics covered here:
- * <ol>
- * <li><a href="#DeveloperGuide">Developer Guide</a>
- * <li><a href="#HowSearchIsInvoked">How Search Is Invoked</a>
- * <li><a href="#QuerySearchApplications">Query-Search Applications</a>
- * <li><a href="#FilterSearchApplications">Filter-Search Applications</a>
- * <li><a href="#Suggestions">Search Suggestions</a>
- * <li><a href="#ActionKeys">Action Keys</a>
- * <li><a href="#SearchabilityMetadata">Searchability Metadata</a>
- * <li><a href="#PassingSearchContext">Passing Search Context</a>
- * <li><a href="#ProtectingUserPrivacy">Protecting User Privacy</a>
- * </ol>
- *
- * <a name="DeveloperGuide"></a>
- * <h3>Developer Guide</h3>
- *
- * <p>The ability to search for user, system, or network based data is considered to be
- * a core user-level feature of the android platform. At any time, the user should be
- * able to use a familiar command, button, or keystroke to invoke search, and the user
- * should be able to search any data which is available to them. The goal is to make search
- * appear to the user as a seamless, system-wide feature.
- *
- * <p>In terms of implementation, there are three broad classes of Applications:
- * <ol>
- * <li>Applications that are not inherently searchable</li>
- * <li>Query-Search Applications</li>
- * <li>Filter-Search Applications</li>
- * </ol>
- * <p>These categories, as well as related topics, are discussed in
- * the sections below.
- *
- * <p>Even if your application is not <i>searchable</i>, it can still support the invocation of
- * search. Please review the section <a href="#HowSearchIsInvoked">How Search Is Invoked</a>
- * for more information on how to support this.
- *
- * <p>Many applications are <i>searchable</i>. These are
- * the applications which can convert a query string into a list of results.
- * Within this subset, applications can be grouped loosely into two families:
- * <ul><li><i>Query Search</i> applications perform batch-mode searches - each query string is
- * converted to a list of results.</li>
- * <li><i>Filter Search</i> applications provide live filter-as-you-type searches.</li></ul>
- * <p>Generally speaking, you would use query search for network-based data, and filter
- * search for local data, but this is not a hard requirement and applications
- * are free to use the model that fits them best (or invent a new model).
- * <p>It should be clear that the search implementation decouples "search
- * invocation" from "searchable". This satisfies the goal of making search appear
- * to be "universal". The user should be able to launch any search from
- * almost any context.
- *
- * <a name="HowSearchIsInvoked"></a>
- * <h3>How Search Is Invoked</h3>
- *
- * <p>Unless impossible or inapplicable, all applications should support
- * invoking the search UI. This means that when the user invokes the search command,
- * a search UI will be presented to them. The search command is currently defined as a menu
- * item called "Search" (with an alphabetic shortcut key of "S"), or on some devices, a dedicated
- * search button key.
- * <p>If your application is not inherently searchable, you can also allow the search UI
- * to be invoked in a "web search" mode. If the user enters a search term and clicks the
- * "Search" button, this will bring the browser to the front and will launch a web-based
- * search. The user will be able to click the "Back" button and return to your application.
- * <p>In general this is implemented by your activity, or the {@link android.app.Activity Activity}
- * base class, which captures the search command and invokes the Search Manager to
- * display and operate the search UI. You can also cause the search UI to be presented in response
- * to user keystrokes in your activity (for example, to instantly start filter searching while
- * viewing a list and typing any key).
- * <p>The search UI is presented as a floating
- * window and does not cause any change in the activity stack. If the user
- * cancels search, the previous activity re-emerges. If the user launches a
- * search, this will be done by sending a search {@link android.content.Intent Intent} (see below),
- * and the normal intent-handling sequence will take place (your activity will pause,
- * etc.)
- * <p><b>What you need to do:</b> First, you should consider the way in which you want to
- * handle invoking search. There are four broad (and partially overlapping) categories for
- * you to choose from.
- * <ul><li>You can capture the search command yourself, by including a <i>search</i>
- * button or menu item - and invoking the search UI directly.</li>
- * <li>You can provide a <i>type-to-search</i> feature, in which search is invoked automatically
- * when the user enters any characters.</li>
- * <li>Even if your application is not inherently searchable, you can allow web search,
- * via the search key (or even via a search menu item).
- * <li>You can disable search entirely. This should only be used in very rare circumstances,
- * as search is a system-wide feature and users will expect it to be available in all contexts.</li>
- * </ul>
- *
- * <p><b>How to define a search menu.</b> The system provides the following resources which may
- * be useful when adding a search item to your menu:
- * <ul><li>android.R.drawable.ic_search_category_default is an icon you can use in your menu.</li>
- * <li>{@link #MENU_KEY SearchManager.MENU_KEY} is the recommended alphabetic shortcut.</li>
- * </ul>
- *
- * <p><b>How to invoke search directly.</b> In order to invoke search directly, from a button
- * or menu item, you can launch a generic search by calling
- * {@link android.app.Activity#onSearchRequested onSearchRequested} as shown:
- * <pre class="prettyprint">
- * onSearchRequested();</pre>
- *
- * <p><b>How to implement type-to-search.</b> While setting up your activity, call
- * {@link android.app.Activity#setDefaultKeyMode setDefaultKeyMode}:
- * <pre class="prettyprint">
- * setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); // search within your activity
- * setDefaultKeyMode(DEFAULT_KEYS_SEARCH_GLOBAL); // search using platform global search</pre>
- *
- * <p><b>How to enable web-based search.</b> In addition to searching within your activity or
- * application, you can also use the Search Manager to invoke a platform-global search, typically
- * a web search. There are two ways to do this:
- * <ul><li>You can simply define "search" within your application or activity to mean global search.
- * This is described in more detail in the
- * <a href="#SearchabilityMetadata">Searchability Metadata</a> section. Briefly, you will
- * add a single meta-data entry to your manifest, declaring that the default search
- * for your application is "*". This indicates to the system that no application-specific
- * search activity is provided, and that it should launch web-based search instead.</li>
- * <li>You can specify this at invocation time via default keys (see above), overriding
- * {@link android.app.Activity#onSearchRequested}, or via a direct call to
- * {@link android.app.Activity#startSearch}. This is most useful if you wish to provide local
- * searchability <i>and</i> access to global search.</li></ul>
- *
- * <p><b>How to disable search from your activity.</b> search is a system-wide feature and users
- * will expect it to be available in all contexts. If your UI design absolutely precludes
- * launching search, override {@link android.app.Activity#onSearchRequested onSearchRequested}
- * as shown:
- * <pre class="prettyprint">
- * &#64;Override
- * public boolean onSearchRequested() {
- * return false;
- * }</pre>
- *
- * <p><b>Managing focus and knowing if Search is active.</b> The search UI is not a separate
- * activity, and when the UI is invoked or dismissed, your activity will not typically be paused,
- * resumed, or otherwise notified by the methods defined in
- * <a href="{@docRoot}guide/topics/fundamentals.html#actlife">Application Fundamentals:
- * Activity Lifecycle</a>. The search UI is
- * handled in the same way as other system UI elements which may appear from time to time, such as
- * notifications, screen locks, or other system alerts:
- * <p>When the search UI appears, your activity will lose input focus.
- * <p>When the search activity is dismissed, there are three possible outcomes:
- * <ul><li>If the user simply canceled the search UI, your activity will regain input focus and
- * proceed as before. See {@link #setOnDismissListener} and {@link #setOnCancelListener} if you
- * required direct notification of search dialog dismissals.</li>
- * <li>If the user launched a search, and this required switching to another activity to receive
- * and process the search {@link android.content.Intent Intent}, your activity will receive the
- * normal sequence of activity pause or stop notifications.</li>
- * <li>If the user launched a search, and the current activity is the recipient of the search
- * {@link android.content.Intent Intent}, you will receive notification via the
- * {@link android.app.Activity#onNewIntent onNewIntent()} method.</li></ul>
- * <p>This list is provided in order to clarify the ways in which your activities will interact with
- * the search UI. More details on searchable activities and search intents are provided in the
- * sections below.
- *
- * <a name="QuerySearchApplications"></a>
- * <h3>Query-Search Applications</h3>
- *
- * <p>Query-search applications are those that take a single query (e.g. a search
- * string) and present a set of results that may fit. Primary examples include
- * web queries, map lookups, or email searches (with the common thread being
- * network query dispatch). It may also be the case that certain local searches
- * are treated this way. It's up to the application to decide.
- *
- * <p><b>What you need to do:</b> The following steps are necessary in order to
- * implement query search.
- * <ul>
- * <li>Implement search invocation as described above. (Strictly speaking,
- * these are decoupled, but it would make little sense to be "searchable" but not
- * "search-invoking".)</li>
- * <li>Your application should have an activity that takes a search string and
- * converts it to a list of results. This could be your primary display activity
- * or it could be a dedicated search results activity. This is your <i>searchable</i>
- * activity and every query-search application must have one.</li>
- * <li>In the searchable activity, in onCreate(), you must receive and handle the
- * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
- * {@link android.content.Intent Intent}. The text to search (query string) for is provided by
- * calling
- * {@link #QUERY getStringExtra(SearchManager.QUERY)}.</li>
- * <li>To identify and support your searchable activity, you'll need to
- * provide an XML file providing searchability configuration parameters, a reference to that
- * in your searchable activity's <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a>
- * entry, and an intent-filter declaring that you can
- * receive ACTION_SEARCH intents. This is described in more detail in the
- * <a href="#SearchabilityMetadata">Searchability Metadata</a> section.</li>
- * <li>Your <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> also needs a metadata entry
- * providing a global reference to the searchable activity. This is the "glue" directing the search
- * UI, when invoked from any of your <i>other</i> activities, to use your application as the
- * default search context. This is also described in more detail in the
- * <a href="#SearchabilityMetadata">Searchability Metadata</a> section.</li>
- * <li>Finally, you may want to define your search results activity as with the
- * {@link android.R.attr#launchMode singleTop} launchMode flag. This allows the system
- * to launch searches from/to the same activity without creating a pile of them on the
- * activity stack. If you do this, be sure to also override
- * {@link android.app.Activity#onNewIntent onNewIntent} to handle the
- * updated intents (with new queries) as they arrive.</li>
- * </ul>
- *
- * <p>Code snippet showing handling of intents in your search activity:
- * <pre class="prettyprint">
- * &#64;Override
- * protected void onCreate(Bundle icicle) {
- * super.onCreate(icicle);
- *
- * final Intent queryIntent = getIntent();
- * final String queryAction = queryIntent.getAction();
- * if (Intent.ACTION_SEARCH.equals(queryAction)) {
- * doSearchWithIntent(queryIntent);
- * }
- * }
- *
- * private void doSearchWithIntent(final Intent queryIntent) {
- * final String queryString = queryIntent.getStringExtra(SearchManager.QUERY);
- * doSearchWithQuery(queryString);
- * }</pre>
- *
- * <a name="FilterSearchApplications"></a>
- * <h3>Filter-Search Applications</h3>
- *
- * <p>Filter-search applications are those that use live text entry (e.g. keystrokes)) to
- * display and continuously update a list of results. Primary examples include applications
- * that use locally-stored data.
- *
- * <p>Filter search is not directly supported by the Search Manager. Most filter search
- * implementations will use variants of {@link android.widget.Filterable}, such as a
- * {@link android.widget.ListView} bound to a {@link android.widget.SimpleCursorAdapter}. However,
- * you may find it useful to mix them together, by declaring your filtered view searchable. With
- * this configuration, you can still present the standard search dialog in all activities
- * within your application, but transition to a filtered search when you enter the activity
- * and display the results.
- *
- * <a name="Suggestions"></a>
- * <h3>Search Suggestions</h3>
- *
- * <p>A powerful feature of the Search Manager is the ability of any application to easily provide
- * live "suggestions" in order to prompt the user. Each application implements suggestions in a
- * different, unique, and appropriate way. Suggestions be drawn from many sources, including but
- * not limited to:
- * <ul>
- * <li>Actual searchable results (e.g. names in the address book)</li>
- * <li>Recently entered queries</li>
- * <li>Recently viewed data or results</li>
- * <li>Contextually appropriate queries or results</li>
- * <li>Summaries of possible results</li>
- * </ul>
- *
- * <p>Another feature of suggestions is that they can expose queries or results before the user
- * ever visits the application. This reduces the amount of context switching required, and helps
- * the user access their data quickly and with less context shifting. In order to provide this
- * capability, suggestions are accessed via a
- * {@link android.content.ContentProvider Content Provider}.
- *
- * <p>The primary form of suggestions is known as <i>queried suggestions</i> and is based on query
- * text that the user has already typed. This would generally be based on partial matches in
- * the available data. In certain situations - for example, when no query text has been typed yet -
- * an application may also opt to provide <i>zero-query suggestions</i>.
- * These would typically be drawn from the same data source, but because no partial query text is
- * available, they should be weighted based on other factors - for example, most recent queries
- * or most recent results.
- *
- * <p><b>Overview of how suggestions are provided.</b> When the search manager identifies a
- * particular activity as searchable, it will check for certain metadata which indicates that
- * there is also a source of suggestions. If suggestions are provided, the following steps are
- * taken.
- * <ul><li>Using formatting information found in the metadata, the user's query text (whatever
- * has been typed so far) will be formatted into a query and sent to the suggestions
- * {@link android.content.ContentProvider Content Provider}.</li>
- * <li>The suggestions {@link android.content.ContentProvider Content Provider} will create a
- * {@link android.database.Cursor Cursor} which can iterate over the possible suggestions.</li>
- * <li>The search manager will populate a list using display data found in each row of the cursor,
- * and display these suggestions to the user.</li>
- * <li>If the user types another key, or changes the query in any way, the above steps are repeated
- * and the suggestions list is updated or repopulated.</li>
- * <li>If the user clicks or touches the "GO" button, the suggestions are ignored and the search is
- * launched using the normal {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} type of
- * {@link android.content.Intent Intent}.</li>
- * <li>If the user uses the directional controls to navigate the focus into the suggestions list,
- * the query text will be updated while the user navigates from suggestion to suggestion. The user
- * can then click or touch the updated query and edit it further. If the user navigates back to
- * the edit field, the original typed query is restored.</li>
- * <li>If the user clicks or touches a particular suggestion, then a combination of data from the
- * cursor and
- * values found in the metadata are used to synthesize an Intent and send it to the application.
- * Depending on the design of the activity and the way it implements search, this might be a
- * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} (in order to launch a query), or it
- * might be a {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}, in order to proceed directly
- * to display of specific data.</li>
- * </ul>
- *
- * <p><b>Simple Recent-Query-Based Suggestions.</b> The Android framework provides a simple Search
- * Suggestions provider, which simply records and replays recent queries. For many applications,
- * this will be sufficient. The basic steps you will need to
- * do, in order to use the built-in recent queries suggestions provider, are as follows:
- * <ul>
- * <li>Implement and test query search, as described in the previous sections.</li>
- * <li>Create a Provider within your application by extending
- * {@link android.content.SearchRecentSuggestionsProvider}.</li>
- * <li>Create a manifest entry describing your provider.</li>
- * <li>Update your searchable activity's XML configuration file with information about your
- * provider.</li>
- * <li>In your searchable activities, capture any user-generated queries and record them
- * for future searches by calling {@link android.provider.SearchRecentSuggestions#saveRecentQuery}.
- * </li>
- * </ul>
- * <p>For complete implementation details, please refer to
- * {@link android.content.SearchRecentSuggestionsProvider}. The rest of the information in this
- * section should not be necessary, as it refers to custom suggestions providers.
- *
- * <p><b>Creating a Customized Suggestions Provider:</b> In order to create more sophisticated
- * suggestion providers, you'll need to take the following steps:
- * <ul>
- * <li>Implement and test query search, as described in the previous sections.</li>
- * <li>Decide how you wish to <i>receive</i> suggestions. Just like queries that the user enters,
- * suggestions will be delivered to your searchable activity as
- * {@link android.content.Intent Intent} messages; Unlike simple queries, you have quite a bit of
- * flexibility in forming those intents. A query search application will probably
- * wish to continue receiving the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
- * {@link android.content.Intent Intent}, which will launch a query search using query text as
- * provided by the suggestion. A filter search application will probably wish to
- * receive the {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}
- * {@link android.content.Intent Intent}, which will take the user directly to a selected entry.
- * Other interesting suggestions, including hybrids, are possible, and the suggestion provider
- * can easily mix-and-match results to provide a richer set of suggestions for the user. Finally,
- * you'll need to update your searchable activity (or other activities) to receive the intents
- * as you've defined them.</li>
- * <li>Implement a Content Provider that provides suggestions. If you already have one, and it
- * has access to your suggestions data. If not, you'll have to create one.
- * You'll also provide information about your Content Provider in your
- * package's <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a>.</li>
- * <li>Update your searchable activity's XML configuration file. There are two categories of
- * information used for suggestions:
- * <ul><li>The first is (required) data that the search manager will
- * use to format the queries which are sent to the Content Provider.</li>
- * <li>The second is (optional) parameters to configure structure
- * if intents generated by suggestions.</li></li>
- * </ul>
- * </ul>
- *
- * <p><b>Configuring your Content Provider to Receive Suggestion Queries.</b> The basic job of
- * a search suggestions {@link android.content.ContentProvider Content Provider} is to provide
- * "live" (while-you-type) conversion of the user's query text into a set of zero or more
- * suggestions. Each application is free to define the conversion, and as described above there are
- * many possible solutions. This section simply defines how to communicate with the suggestion
- * provider.
- *
- * <p>The Search Manager must first determine if your package provides suggestions. This is done
- * by examination of your searchable meta-data XML file. The android:searchSuggestAuthority
- * attribute, if provided, is the signal to obtain & display suggestions.
- *
- * <p>Every query includes a Uri, and the Search Manager will format the Uri as shown:
- * <p><pre class="prettyprint">
- * content:// your.suggest.authority / your.suggest.path / SearchManager.SUGGEST_URI_PATH_QUERY</pre>
- *
- * <p>Your Content Provider can receive the query text in one of two ways.
- * <ul>
- * <li><b>Query provided as a selection argument.</b> If you define the attribute value
- * android:searchSuggestSelection and include a string, this string will be passed as the
- * <i>selection</i> parameter to your Content Provider's query function. You must define a single
- * selection argument, using the '?' character. The user's query text will be passed to you
- * as the first element of the selection arguments array.</li>
- * <li><b>Query provided with Data Uri.</b> If you <i>do not</i> define the attribute value
- * android:searchSuggestSelection, then the Search Manager will append another "/" followed by
- * the user's query to the query Uri. The query will be encoding using Uri encoding rules - don't
- * forget to decode it. (See {@link android.net.Uri#getPathSegments} and
- * {@link android.net.Uri#getLastPathSegment} for helpful utilities you can use here.)</li>
- * </ul>
- *
- * <p><b>Handling empty queries.</b> Your application should handle the "empty query"
- * (no user text entered) case properly, and generate useful suggestions in this case. There are a
- * number of ways to do this; Two are outlined here:
- * <ul><li>For a simple filter search of local data, you could simply present the entire dataset,
- * unfiltered. (example: People)</li>
- * <li>For a query search, you could simply present the most recent queries. This allows the user
- * to quickly repeat a recent search.</li></ul>
- *
- * <p><b>The Format of Individual Suggestions.</b> Your suggestions are communicated back to the
- * Search Manager by way of a {@link android.database.Cursor Cursor}. The Search Manager will
- * usually pass a null Projection, which means that your provider can simply return all appropriate
- * columns for each suggestion. The columns currently defined are:
- *
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
- *
- * <thead>
- * <tr><th>Column Name</th> <th>Description</th> <th>Required?</th></tr>
- * </thead>
- *
- * <tbody>
- * <tr><th>{@link #SUGGEST_COLUMN_FORMAT}</th>
- * <td><i>Unused - can be null.</i></td>
- * <td align="center">No</td>
- * </tr>
- *
- * <tr><th>{@link #SUGGEST_COLUMN_TEXT_1}</th>
- * <td>This is the line of text that will be presented to the user as the suggestion.</td>
- * <td align="center">Yes</td>
- * </tr>
- *
- * <tr><th>{@link #SUGGEST_COLUMN_TEXT_2}</th>
- * <td>If your cursor includes this column, then all suggestions will be provided in a
- * two-line format. The data in this column will be displayed as a second, smaller
- * line of text below the primary suggestion, or it can be null or empty to indicate no
- * text in this row's suggestion.</td>
- * <td align="center">No</td>
- * </tr>
- *
- * <tr><th>{@link #SUGGEST_COLUMN_ICON_1}</th>
- * <td>If your cursor includes this column, then all suggestions will be provided in an
- * icons+text format. This value should be a reference (resource ID) of the icon to
- * draw on the left side, or it can be null or zero to indicate no icon in this row.
- * You must provide both cursor columns, or neither.
- * </td>
- * <td align="center">No, but required if you also have {@link #SUGGEST_COLUMN_ICON_2}</td>
- * </tr>
- *
- * <tr><th>{@link #SUGGEST_COLUMN_ICON_2}</th>
- * <td>If your cursor includes this column, then all suggestions will be provided in an
- * icons+text format. This value should be a reference (resource ID) of the icon to
- * draw on the right side, or it can be null or zero to indicate no icon in this row.
- * You must provide both cursor columns, or neither.
- * </td>
- * <td align="center">No, but required if you also have {@link #SUGGEST_COLUMN_ICON_1}</td>
- * </tr>
- *
- * <tr><th>{@link #SUGGEST_COLUMN_INTENT_ACTION}</th>
- * <td>If this column exists <i>and</i> this element exists at the given row, this is the
- * action that will be used when forming the suggestion's intent. If the element is
- * not provided, the action will be taken from the android:searchSuggestIntentAction
- * field in your XML metadata. <i>At least one of these must be present for the
- * suggestion to generate an intent.</i> Note: If your action is the same for all
- * suggestions, it is more efficient to specify it using XML metadata and omit it from
- * the cursor.</td>
- * <td align="center">No</td>
- * </tr>
- *
- * <tr><th>{@link #SUGGEST_COLUMN_INTENT_DATA}</th>
- * <td>If this column exists <i>and</i> this element exists at the given row, this is the
- * data that will be used when forming the suggestion's intent. If the element is not
- * provided, the data will be taken from the android:searchSuggestIntentData field in
- * your XML metadata. If neither source is provided, the Intent's data field will be
- * null. Note: If your data is the same for all suggestions, or can be described
- * using a constant part and a specific ID, it is more efficient to specify it using
- * XML metadata and omit it from the cursor.</td>
- * <td align="center">No</td>
- * </tr>
- *
- * <tr><th>{@link #SUGGEST_COLUMN_INTENT_DATA_ID}</th>
- * <td>If this column exists <i>and</i> this element exists at the given row, then "/" and
- * this value will be appended to the data field in the Intent. This should only be
- * used if the data field has already been set to an appropriate base string.</td>
- * <td align="center">No</td>
- * </tr>
- *
- * <tr><th>{@link #SUGGEST_COLUMN_QUERY}</th>
- * <td>If this column exists <i>and</i> this element exists at the given row, this is the
- * data that will be used when forming the suggestion's query.</td>
- * <td align="center">Required if suggestion's action is
- * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}, optional otherwise.</td>
- * </tr>
- *
- * <tr><th><i>Other Columns</i></th>
- * <td>Finally, if you have defined any <a href="#ActionKeys">Action Keys</a> and you wish
- * for them to have suggestion-specific definitions, you'll need to define one
- * additional column per action key. The action key will only trigger if the
- * currently-selection suggestion has a non-empty string in the corresponding column.
- * See the section on <a href="#ActionKeys">Action Keys</a> for additional details and
- * implementation steps.</td>
- * <td align="center">No</td>
- * </tr>
- *
- * </tbody>
- * </table>
- *
- * <p>Clearly there are quite a few permutations of your suggestion data, but in the next section
- * we'll look at a few simple combinations that you'll select from.
- *
- * <p><b>The Format Of Intents Sent By Search Suggestions.</b> Although there are many ways to
- * configure these intents, this document will provide specific information on just a few of them.
- * <ul><li><b>Launch a query.</b> In this model, each suggestion represents a query that your
- * searchable activity can perform, and the {@link android.content.Intent Intent} will be formatted
- * exactly like those sent when the user enters query text and clicks the "GO" button:
- * <ul>
- * <li><b>Action:</b> {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} provided
- * using your XML metadata (android:searchSuggestIntentAction).</li>
- * <li><b>Data:</b> empty (not used).</li>
- * <li><b>Query:</b> query text supplied by the cursor.</li>
- * </ul>
- * </li>
- * <li><b>Go directly to a result, using a complete Data Uri.</b> In this model, the user will be
- * taken directly to a specific result.
- * <ul>
- * <li><b>Action:</b> {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}</li>
- * <li><b>Data:</b> a complete Uri, supplied by the cursor, that identifies the desired data.</li>
- * <li><b>Query:</b> query text supplied with the suggestion (probably ignored)</li>
- * </ul>
- * </li>
- * <li><b>Go directly to a result, using a synthesized Data Uri.</b> This has the same result
- * as the previous suggestion, but provides the Data Uri in a different way.
- * <ul>
- * <li><b>Action:</b> {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}</li>
- * <li><b>Data:</b> The search manager will assemble a Data Uri using the following elements:
- * a Uri fragment provided in your XML metadata (android:searchSuggestIntentData), followed by
- * a single "/", followed by the value found in the {@link #SUGGEST_COLUMN_INTENT_DATA_ID}
- * entry in your cursor.</li>
- * <li><b>Query:</b> query text supplied with the suggestion (probably ignored)</li>
- * </ul>
- * </li>
- * </ul>
- * <p>This list is not meant to be exhaustive. Applications should feel free to define other types
- * of suggestions. For example, you could reduce long lists of results to summaries, and use one
- * of the above intents (or one of your own) with specially formatted Data Uri's to display more
- * detailed results. Or you could display textual shortcuts as suggestions, but launch a display
- * in a more data-appropriate format such as media artwork.
- *
- * <p><b>Suggestion Rewriting.</b> If the user navigates through the suggestions list, the UI
- * may temporarily rewrite the user's query with a query that matches the currently selected
- * suggestion. This enables the user to see what query is being suggested, and also allows the user
- * to click or touch in the entry EditText element and make further edits to the query before
- * dispatching it. In order to perform this correctly, the Search UI needs to know exactly what
- * text to rewrite the query with.
- *
- * <p>For each suggestion, the following logic is used to select a new query string:
- * <ul><li>If the suggestion provides an explicit value in the {@link #SUGGEST_COLUMN_QUERY}
- * column, this value will be used.</li>
- * <li>If the metadata includes the queryRewriteFromData flag, and the suggestion provides an
- * explicit value for the intent Data field, this Uri will be used. Note that this should only be
- * used with Uri's that are intended to be user-visible, such as HTTP. Internal Uri schemes should
- * not be used in this way.</li>
- * <li>If the metadata includes the queryRewriteFromText flag, the text in
- * {@link #SUGGEST_COLUMN_TEXT_1} will be used. This should be used for suggestions in which no
- * query text is provided and the SUGGEST_COLUMN_INTENT_DATA values are not suitable for user
- * inspection and editing.</li></ul>
- *
- * <a name="ActionKeys"></a>
- * <h3>Action Keys</h3>
- *
- * <p>Searchable activities may also wish to provide shortcuts based on the various action keys
- * available on the device. The most basic example of this is the contacts app, which enables the
- * green "dial" key for quick access during searching. Not all action keys are available on
- * every device, and not all are allowed to be overriden in this way. (For example, the "Home"
- * key must always return to the home screen, with no exceptions.)
- *
- * <p>In order to define action keys for your searchable application, you must do two things.
- *
- * <ul>
- * <li>You'll add one or more <i>actionkey</i> elements to your searchable metadata configuration
- * file. Each element defines one of the keycodes you are interested in,
- * defines the conditions under which they are sent, and provides details
- * on how to communicate the action key event back to your searchable activity.</li>
- * <li>In your broadcast receiver, if you wish, you can check for action keys by checking the
- * extras field of the {@link android.content.Intent Intent}.</li>
- * </ul>
- *
- * <p><b>Updating metadata.</b> For each keycode of interest, you must add an &lt;actionkey&gt;
- * element. Within this element you must define two or three attributes. The first attribute,
- * &lt;android:keycode&gt;, is required; It is the key code of the action key event, as defined in
- * {@link android.view.KeyEvent}. The remaining two attributes define the value of the actionkey's
- * <i>message</i>, which will be passed to your searchable activity in the
- * {@link android.content.Intent Intent} (see below for more details). Although each of these
- * attributes is optional, you must define one or both for the action key to have any effect.
- * &lt;android:queryActionMsg&gt; provides the message that will be sent if the action key is
- * pressed while the user is simply entering query text. &lt;android:suggestActionMsgColumn&gt;
- * is used when action keys are tied to specific suggestions. This attribute provides the name
- * of a <i>column</i> in your suggestion cursor; The individual suggestion, in that column,
- * provides the message. (If the cell is empty or null, that suggestion will not work with that
- * action key.)
- * <p>See the <a href="#SearchabilityMetadata">Searchability Metadata</a> section for more details
- * and examples.
- *
- * <p><b>Receiving Action Keys</b> Intents launched by action keys will be specially marked
- * using a combination of values. This enables your searchable application to examine the intent,
- * if necessary, and perform special processing. For example, clicking a suggested contact might
- * simply display them; Selecting a suggested contact and clicking the dial button might
- * immediately call them.
- *
- * <p>When a search {@link android.content.Intent Intent} is launched by an action key, two values
- * will be added to the extras field.
- * <ul>
- * <li>To examine the key code, use {@link android.content.Intent#getIntExtra
- * getIntExtra(SearchManager.ACTION_KEY)}.</li>
- * <li>To examine the message string, use {@link android.content.Intent#getStringExtra
- * getStringExtra(SearchManager.ACTION_MSG)}</li>
- * </ul>
- *
- * <a name="SearchabilityMetadata"></a>
- * <h3>Searchability Metadata</h3>
- *
- * <p>Every activity that is searchable must provide a small amount of additional information
- * in order to properly configure the search system. This controls the way that your search
- * is presented to the user, and controls for the various modalities described previously.
- *
- * <p>If your application is not searchable,
- * then you do not need to provide any search metadata, and you can skip the rest of this section.
- * When this search metadata cannot be found, the search manager will assume that the activity
- * does not implement search. (Note: to implement web-based search, you will need to add
- * the android.app.default_searchable metadata to your manifest, as shown below.)
- *
- * <p>Values you supply in metadata apply only to each local searchable activity. Each
- * searchable activity can define a completely unique search experience relevant to its own
- * capabilities and user experience requirements, and a single application can even define multiple
- * searchable activities.
- *
- * <p><b>Metadata for searchable activity.</b> As with your search implementations described
- * above, you must first identify which of your activities is searchable. In the
- * <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> entry for this activity, you must
- * provide two elements:
- * <ul><li>An intent-filter specifying that you can receive and process the
- * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} {@link android.content.Intent Intent}.
- * </li>
- * <li>A reference to a small XML file (typically called "searchable.xml") which contains the
- * remaining configuration information for how your application implements search.</li></ul>
- *
- * <p>Here is a snippet showing the necessary elements in the
- * <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> entry for your searchable activity.
- * <pre class="prettyprint">
- * &lt;!-- Search Activity - searchable --&gt;
- * &lt;activity android:name="MySearchActivity"
- * android:label="Search"
- * android:launchMode="singleTop"&gt;
- * &lt;intent-filter&gt;
- * &lt;action android:name="android.intent.action.SEARCH" /&gt;
- * &lt;category android:name="android.intent.category.DEFAULT" /&gt;
- * &lt;/intent-filter&gt;
- * &lt;meta-data android:name="android.app.searchable"
- * android:resource="@xml/searchable" /&gt;
- * &lt;/activity&gt;</pre>
- *
- * <p>Next, you must provide the rest of the searchability configuration in
- * the small XML file, stored in the ../xml/ folder in your build. The XML file is a
- * simple enumeration of the search configuration parameters for searching within this activity,
- * application, or package. Here is a sample XML file (named searchable.xml, for use with
- * the above manifest) for a query-search activity.
- *
- * <pre class="prettyprint">
- * &lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
- * android:label="@string/search_label"
- * android:hint="@string/search_hint" &gt;
- * &lt;/searchable&gt;</pre>
- *
- * <p>Note that all user-visible strings <i>must</i> be provided in the form of "@string"
- * references. Hard-coded strings, which cannot be localized, will not work properly in search
- * metadata.
- *
- * <p>Attributes you can set in search metadata:
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
- *
- * <thead>
- * <tr><th>Attribute</th> <th>Description</th> <th>Required?</th></tr>
- * </thead>
- *
- * <tbody>
- * <tr><th>android:label</th>
- * <td>This is the name for your application that will be presented to the user in a
- * list of search targets, or in the search box as a label.</td>
- * <td align="center">Yes</td>
- * </tr>
- *
- * <tr><th>android:icon</th>
- * <td>If provided, this icon will be used <i>in place</i> of the label string. This
- * is provided in order to present logos or other non-textual banners.</td>
- * <td align="center">No</td>
- * </tr>
- *
- * <tr><th>android:hint</th>
- * <td>This is the text to display in the search text field when no user text has been
- * entered.</td>
- * <td align="center">No</td>
- * </tr>
- *
- * <tr><th>android:searchButtonText</th>
- * <td>If provided, this text will replace the default text in the "Search" button.</td>
- * <td align="center">No</td>
- * </tr>
- *
- * <tr><th>android:searchMode</th>
- * <td>If provided and non-zero, sets additional modes for control of the search
- * presentation. The following mode bits are defined:
- * <table border="2" align="center" frame="hsides" rules="rows">
- * <tbody>
- * <tr><th>showSearchLabelAsBadge</th>
- * <td>If set, this flag enables the display of the search target (label)
- * within the search bar. If this flag and showSearchIconAsBadge
- * (see below) are both not set, no badge will be shown.</td>
- * </tr>
- * <tr><th>showSearchIconAsBadge</th>
- * <td>If set, this flag enables the display of the search target (icon) within
- * the search bar. If this flag and showSearchLabelAsBadge
- * (see above) are both not set, no badge will be shown. If both flags
- * are set, showSearchIconAsBadge has precedence and the icon will be
- * shown.</td>
- * </tr>
- * <tr><th>queryRewriteFromData</th>
- * <td>If set, this flag causes the suggestion column SUGGEST_COLUMN_INTENT_DATA
- * to be considered as the text for suggestion query rewriting. This should
- * only be used when the values in SUGGEST_COLUMN_INTENT_DATA are suitable
- * for user inspection and editing - typically, HTTP/HTTPS Uri's.</td>
- * </tr>
- * <tr><th>queryRewriteFromText</th>
- * <td>If set, this flag causes the suggestion column SUGGEST_COLUMN_TEXT_1 to
- * be considered as the text for suggestion query rewriting. This should
- * be used for suggestions in which no query text is provided and the
- * SUGGEST_COLUMN_INTENT_DATA values are not suitable for user inspection
- * and editing.</td>
- * </tr>
- * </tbody>
- * </table></td>
- * <td align="center">No</td>
- * </tr>
- *
- * <tr><th>android:inputType</th>
- * <td>If provided, supplies a hint about the type of search text the user will be
- * entering. For most searches, in which free form text is expected, this attribute
- * need not be provided. Suitable values for this attribute are described in the
- * <a href="../R.attr.html#inputType">inputType</a> attribute.</td>
- * <td align="center">No</td>
- * </tr>
- *
- * </tbody>
- * </table>
- *
- * <p><b>Styleable Resources in your Metadata.</b> It's possible to provide alternate strings
- * for your searchable application, in order to provide localization and/or to better visual
- * presentation on different device configurations. Each searchable activity has a single XML
- * metadata file, but any resource references can be replaced at runtime based on device
- * configuration, language setting, and other system inputs.
- *
- * <p>A concrete example is the "hint" text you supply using the android:searchHint attribute.
- * In portrait mode you'll have less screen space and may need to provide a shorter string, but
- * in landscape mode you can provide a longer, more descriptive hint. To do this, you'll need to
- * define two or more strings.xml files, in the following directories:
- * <ul><li>.../res/values-land/strings.xml</li>
- * <li>.../res/values-port/strings.xml</li>
- * <li>.../res/values/strings.xml</li></ul>
- *
- * <p>For more complete documentation on this capability, see
- * <a href="{@docRoot}guide/topics/resources/resources-i18n.html#AlternateResources">Resources and
- * Internationalization: Alternate Resources</a>.
- *
- * <p><b>Metadata for non-searchable activities.</b> Activities which are part of a searchable
- * application, but don't implement search itself, require a bit of "glue" in order to cause
- * them to invoke search using your searchable activity as their primary context. If this is not
- * provided, then searches from these activities will use the system default search context.
- *
- * <p>The simplest way to specify this is to add a <i>search reference</i> element to the
- * application entry in the <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a> file.
- * The value of this reference can be either of:
- * <ul><li>The name of your searchable activity.
- * It is typically prefixed by '.' to indicate that it's in the same package.</li>
- * <li>A "*" indicates that the system may select a default searchable activity, in which
- * case it will typically select web-based search.</li>
- * </ul>
- *
- * <p>Here is a snippet showing the necessary addition to the manifest entry for your
- * non-searchable activities.
- * <pre class="prettyprint">
- * &lt;application&gt;
- * &lt;meta-data android:name="android.app.default_searchable"
- * android:value=".MySearchActivity" /&gt;
- *
- * &lt;!-- followed by activities, providers, etc... --&gt;
- * &lt;/application&gt;</pre>
- *
- * <p>You can also specify android.app.default_searchable on a per-activity basis, by including
- * the meta-data element (as shown above) in one or more activity sections. If found, these will
- * override the reference in the application section. The only reason to configure your application
- * this way would be if you wish to partition it into separate sections with different search
- * behaviors; Otherwise this configuration is not recommended.
- *
- * <p><b>Additional Metadata for search suggestions.</b> If you have defined a content provider
- * to generate search suggestions, you'll need to publish it to the system, and you'll need to
- * provide a bit of additional XML metadata in order to configure communications with it.
- *
- * <p>First, in your <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a>, you'll add the
- * following lines.
- * <pre class="prettyprint">
- * &lt;!-- Content provider for search suggestions --&gt;
- * &lt;provider android:name="YourSuggestionProviderClass"
- * android:authorities="your.suggestion.authority" /&gt;</pre>
- *
- * <p>Next, you'll add a few lines to your XML metadata file, as shown:
- * <pre class="prettyprint">
- * &lt;!-- Required attribute for any suggestions provider --&gt;
- * android:searchSuggestAuthority="your.suggestion.authority"
- *
- * &lt;!-- Optional attribute for configuring queries --&gt;
- * android:searchSuggestSelection="field =?"
- *
- * &lt;!-- Optional attributes for configuring intent construction --&gt;
- * android:searchSuggestIntentAction="intent action string"
- * android:searchSuggestIntentData="intent data Uri" /&gt;</pre>
- *
- * <p>Elements of search metadata that support suggestions:
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
- *
- * <thead>
- * <tr><th>Attribute</th> <th>Description</th> <th>Required?</th></tr>
- * </thead>
- *
- * <tbody>
- * <tr><th>android:searchSuggestAuthority</th>
- * <td>This value must match the authority string provided in the <i>provider</i> section
- * of your <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a>.</td>
- * <td align="center">Yes</td>
- * </tr>
- *
- * <tr><th>android:searchSuggestPath</th>
- * <td>If provided, this will be inserted in the suggestions query Uri, after the authority
- * you have provide but before the standard suggestions path. This is only required if
- * you have a single content provider issuing different types of suggestions (e.g. for
- * different data types) and you need a way to disambiguate the suggestions queries
- * when they are received.</td>
- * <td align="center">No</td>
- * </tr>
- *
- * <tr><th>android:searchSuggestSelection</th>
- * <td>If provided, this value will be passed into your query function as the
- * <i>selection</i> parameter. Typically this will be a WHERE clause for your database,
- * and will contain a single question mark, which represents the actual query string
- * that has been typed by the user. However, you can also use any non-null value
- * to simply trigger the delivery of the query text (via selection arguments), and then
- * use the query text in any way appropriate for your provider (ignoring the actual
- * text of the selection parameter.)</td>
- * <td align="center">No</td>
- * </tr>
- *
- * <tr><th>android:searchSuggestIntentAction</th>
- * <td>If provided, and not overridden by the selected suggestion, this value will be
- * placed in the action field of the {@link android.content.Intent Intent} when the
- * user clicks a suggestion.</td>
- * <td align="center">No</td>
- *
- * <tr><th>android:searchSuggestIntentData</th>
- * <td>If provided, and not overridden by the selected suggestion, this value will be
- * placed in the data field of the {@link android.content.Intent Intent} when the user
- * clicks a suggestion.</td>
- * <td align="center">No</td>
- * </tr>
- *
- * </tbody>
- * </table>
- *
- * <p><b>Additional Metadata for search action keys.</b> For each action key that you would like to
- * define, you'll need to add an additional element defining that key, and using the attributes
- * discussed in <a href="#ActionKeys">Action Keys</a>. A simple example is shown here:
- *
- * <pre class="prettyprint">&lt;actionkey
- * android:keycode="KEYCODE_CALL"
- * android:queryActionMsg="call"
- * android:suggestActionMsg="call"
- * android:suggestActionMsgColumn="call_column" /&gt;</pre>
- *
- * <p>Elements of search metadata that support search action keys. Note that although each of the
- * action message elements are marked as <i>optional</i>, at least one must be present for the
- * action key to have any effect.
- *
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
- *
- * <thead>
- * <tr><th>Attribute</th> <th>Description</th> <th>Required?</th></tr>
- * </thead>
- *
- * <tbody>
- * <tr><th>android:keycode</th>
- * <td>This attribute denotes the action key you wish to respond to. Note that not
- * all action keys are actually supported using this mechanism, as many of them are
- * used for typing, navigation, or system functions. This will be added to the
- * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to
- * your searchable activity. To examine the key code, use
- * {@link android.content.Intent#getIntExtra getIntExtra(SearchManager.ACTION_KEY)}.
- * <p>Note, in addition to the keycode, you must also provide one or more of the action
- * specifier attributes.</td>
- * <td align="center">Yes</td>
- * </tr>
- *
- * <tr><th>android:queryActionMsg</th>
- * <td>If you wish to handle an action key during normal search query entry, you
- * must define an action string here. This will be added to the
- * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to your
- * searchable activity. To examine the string, use
- * {@link android.content.Intent#getStringExtra
- * getStringExtra(SearchManager.ACTION_MSG)}.</td>
- * <td align="center">No</td>
- * </tr>
- *
- * <tr><th>android:suggestActionMsg</th>
- * <td>If you wish to handle an action key while a suggestion is being displayed <i>and
- * selected</i>, there are two ways to handle this. If <i>all</i> of your suggestions
- * can handle the action key, you can simply define the action message using this
- * attribute. This will be added to the
- * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to
- * your searchable activity. To examine the string, use
- * {@link android.content.Intent#getStringExtra
- * getStringExtra(SearchManager.ACTION_MSG)}.</td>
- * <td align="center">No</td>
- * </tr>
- *
- * <tr><th>android:suggestActionMsgColumn</th>
- * <td>If you wish to handle an action key while a suggestion is being displayed <i>and
- * selected</i>, but you do not wish to enable this action key for every suggestion,
- * then you can use this attribute to control it on a suggestion-by-suggestion basis.
- * First, you must define a column (and name it here) where your suggestions will
- * include the action string. Then, in your content provider, you must provide this
- * column, and when desired, provide data in this column.
- * The search manager will look at your suggestion cursor, using the string
- * provided here in order to select a column, and will use that to select a string from
- * the cursor. That string will be added to the
- * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} intent that is passed to
- * your searchable activity. To examine the string, use
- * {@link android.content.Intent#getStringExtra
- * getStringExtra(SearchManager.ACTION_MSG)}. <i>If the data does not exist for the
- * selection suggestion, the action key will be ignored.</i></td>
- * <td align="center">No</td>
- * </tr>
- *
- * </tbody>
- * </table>
- *
- * <a name="PassingSearchContext"></a>
- * <h3>Passing Search Context</h3>
- *
- * <p>In order to improve search experience, an application may wish to specify
- * additional data along with the search, such as local history or context. For
- * example, a maps search would be improved by including the current location.
- * In order to simplify the structure of your activities, this can be done using
- * the search manager.
- *
- * <p>Any data can be provided at the time the search is launched, as long as it
- * can be stored in a {@link android.os.Bundle Bundle} object.
- *
- * <p>To pass application data into the Search Manager, you'll need to override
- * {@link android.app.Activity#onSearchRequested onSearchRequested} as follows:
- *
- * <pre class="prettyprint">
- * &#64;Override
- * public boolean onSearchRequested() {
- * Bundle appData = new Bundle();
- * appData.put...();
- * appData.put...();
- * startSearch(null, false, appData);
- * return true;
- * }</pre>
- *
- * <p>To receive application data from the Search Manager, you'll extract it from
- * the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
- * {@link android.content.Intent Intent} as follows:
- *
- * <pre class="prettyprint">
- * final Bundle appData = queryIntent.getBundleExtra(SearchManager.APP_DATA);
- * if (appData != null) {
- * appData.get...();
- * appData.get...();
- * }</pre>
- *
- * <a name="ProtectingUserPrivacy"></a>
- * <h3>Protecting User Privacy</h3>
- *
- * <p>Many users consider their activities on the phone, including searches, to be private
- * information. Applications that implement search should take steps to protect users' privacy
- * wherever possible. This section covers two areas of concern, but you should consider your search
- * design carefully and take any additional steps necessary.
- *
- * <p><b>Don't send personal information to servers, and if you do, don't log it.</b>
- * "Personal information" is information that can personally identify your users, such as name,
- * email address or billing information, or other data which can be reasonably linked to such
- * information. If your application implements search with the assistance of a server, try to
- * avoid sending personal information with your searches. For example, if you are searching for
- * businesses near a zip code, you don't need to send the user ID as well - just send the zip code
- * to the server. If you do need to send personal information, you should take steps to avoid
- * logging it. If you must log it, you should protect that data very carefully, and erase it as
- * soon as possible.
- *
- * <p><b>Provide the user with a way to clear their search history.</b> The Search Manager helps
- * your application provide context-specific suggestions. Sometimes these suggestions are based
- * on previous searches, or other actions taken by the user in an earlier session. A user may not
- * wish for previous searches to be revealed to other users, for instance if they share their phone
- * with a friend. If your application provides suggestions that can reveal previous activities,
- * you should implement a "Clear History" menu, preference, or button. If you are using
- * {@link android.provider.SearchRecentSuggestions}, you can simply call its
- * {@link android.provider.SearchRecentSuggestions#clearHistory() clearHistory()} method from
- * your "Clear History" UI. If you are implementing your own form of recent suggestions, you'll
- * need to provide a similar a "clear history" API in your provider, and call it from your
- * "Clear History" UI.
- */
-public class SearchManager
- implements DialogInterface.OnDismissListener, DialogInterface.OnCancelListener
-{
- /**
- * This is a shortcut definition for the default menu key to use for invoking search.
- *
- * See Menu.Item.setAlphabeticShortcut() for more information.
- */
- public final static char MENU_KEY = 's';
-
- /**
- * This is a shortcut definition for the default menu key to use for invoking search.
- *
- * See Menu.Item.setAlphabeticShortcut() for more information.
- */
- public final static int MENU_KEYCODE = KeyEvent.KEYCODE_S;
-
- /**
- * Intent extra data key: Use this key with
- * {@link android.content.Intent#getStringExtra
- * content.Intent.getStringExtra()}
- * to obtain the query string from Intent.ACTION_SEARCH.
- */
- public final static String QUERY = "query";
-
- /**
- * Intent extra data key: Use this key with Intent.ACTION_SEARCH and
- * {@link android.content.Intent#getBundleExtra
- * content.Intent.getBundleExtra()}
- * to obtain any additional app-specific data that was inserted by the
- * activity that launched the search.
- */
- public final static String APP_DATA = "app_data";
-
- /**
- * Intent app_data bundle key: Use this key with the bundle from
- * {@link android.content.Intent#getBundleExtra
- * content.Intent.getBundleExtra(APP_DATA)} to obtain the source identifier
- * set by the activity that launched the search.
- *
- * @hide
- */
- public final static String SOURCE = "source";
-
- /**
- * Intent extra data key: Use this key with Intent.ACTION_SEARCH and
- * {@link android.content.Intent#getIntExtra content.Intent.getIntExtra()}
- * to obtain the keycode that the user used to trigger this query. It will be zero if the
- * user simply pressed the "GO" button on the search UI. This is primarily used in conjunction
- * with the keycode attribute in the actionkey element of your searchable.xml configuration
- * file.
- */
- public final static String ACTION_KEY = "action_key";
-
- /**
- * Intent extra data key: Use this key with Intent.ACTION_SEARCH and
- * {@link android.content.Intent#getStringExtra content.Intent.getStringExtra()}
- * to obtain the action message that was defined for a particular search action key and/or
- * suggestion. It will be null if the search was launched by typing "enter", touched the the
- * "GO" button, or other means not involving any action key.
- */
- public final static String ACTION_MSG = "action_msg";
-
- /**
- * Uri path for queried suggestions data. This is the path that the search manager
- * will use when querying your content provider for suggestions data based on user input
- * (e.g. looking for partial matches).
- * Typically you'll use this with a URI matcher.
- */
- public final static String SUGGEST_URI_PATH_QUERY = "search_suggest_query";
-
- /**
- * MIME type for suggestions data. You'll use this in your suggestions content provider
- * in the getType() function.
- */
- public final static String SUGGEST_MIME_TYPE =
- "vnd.android.cursor.dir/vnd.android.search.suggest";
-
- /**
- * Column name for suggestions cursor. <i>Unused - can be null or column can be omitted.</i>
- */
- public final static String SUGGEST_COLUMN_FORMAT = "suggest_format";
- /**
- * Column name for suggestions cursor. <i>Required.</i> This is the primary line of text that
- * will be presented to the user as the suggestion.
- */
- public final static String SUGGEST_COLUMN_TEXT_1 = "suggest_text_1";
- /**
- * Column name for suggestions cursor. <i>Optional.</i> If your cursor includes this column,
- * then all suggestions will be provided in a two-line format. The second line of text is in
- * a much smaller appearance.
- */
- public final static String SUGGEST_COLUMN_TEXT_2 = "suggest_text_2";
- /**
- * Column name for suggestions cursor. <i>Optional.</i> If your cursor includes this column,
- * then all suggestions will be provided in format that includes space for two small icons,
- * one at the left and one at the right of each suggestion. The data in the column must
- * be a a resource ID for the icon you wish to have displayed. If you include this column,
- * you must also include {@link #SUGGEST_COLUMN_ICON_2}.
- */
- public final static String SUGGEST_COLUMN_ICON_1 = "suggest_icon_1";
- /**
- * Column name for suggestions cursor. <i>Optional.</i> If your cursor includes this column,
- * then all suggestions will be provided in format that includes space for two small icons,
- * one at the left and one at the right of each suggestion. The data in the column must
- * be a a resource ID for the icon you wish to have displayed. If you include this column,
- * you must also include {@link #SUGGEST_COLUMN_ICON_1}.
- */
- public final static String SUGGEST_COLUMN_ICON_2 = "suggest_icon_2";
- /**
- * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i>
- * this element exists at the given row, this is the action that will be used when
- * forming the suggestion's intent. If the element is not provided, the action will be taken
- * from the android:searchSuggestIntentAction field in your XML metadata. <i>At least one of
- * these must be present for the suggestion to generate an intent.</i> Note: If your action is
- * the same for all suggestions, it is more efficient to specify it using XML metadata and omit
- * it from the cursor.
- */
- public final static String SUGGEST_COLUMN_INTENT_ACTION = "suggest_intent_action";
- /**
- * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i>
- * this element exists at the given row, this is the data that will be used when
- * forming the suggestion's intent. If the element is not provided, the data will be taken
- * from the android:searchSuggestIntentData field in your XML metadata. If neither source
- * is provided, the Intent's data field will be null. Note: If your data is
- * the same for all suggestions, or can be described using a constant part and a specific ID,
- * it is more efficient to specify it using XML metadata and omit it from the cursor.
- */
- public final static String SUGGEST_COLUMN_INTENT_DATA = "suggest_intent_data";
- /**
- * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i>
- * this element exists at the given row, then "/" and this value will be appended to the data
- * field in the Intent. This should only be used if the data field has already been set to an
- * appropriate base string.
- */
- public final static String SUGGEST_COLUMN_INTENT_DATA_ID = "suggest_intent_data_id";
- /**
- * Column name for suggestions cursor. <i>Required if action is
- * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}, optional otherwise.</i> If this
- * column exists <i>and</i> this element exists at the given row, this is the data that will be
- * used when forming the suggestion's query.
- */
- public final static String SUGGEST_COLUMN_QUERY = "suggest_intent_query";
-
-
- private final Context mContext;
- private final Handler mHandler;
-
- private SearchDialog mSearchDialog;
-
- private OnDismissListener mDismissListener = null;
- private OnCancelListener mCancelListener = null;
-
- /*package*/ SearchManager(Context context, Handler handler) {
- mContext = context;
- mHandler = handler;
- }
- private static ISearchManager mService;
-
- static {
- mService = ISearchManager.Stub.asInterface(
- ServiceManager.getService(Context.SEARCH_SERVICE));
- }
-
- /**
- * Launch search UI.
- *
- * <p>The search manager will open a search widget in an overlapping
- * window, and the underlying activity may be obscured. The search
- * entry state will remain in effect until one of the following events:
- * <ul>
- * <li>The user completes the search. In most cases this will launch
- * a search intent.</li>
- * <li>The user uses the back, home, or other keys to exit the search.</li>
- * <li>The application calls the {@link #stopSearch}
- * method, which will hide the search window and return focus to the
- * activity from which it was launched.</li>
- *
- * <p>Most applications will <i>not</i> use this interface to invoke search.
- * The primary method for invoking search is to call
- * {@link android.app.Activity#onSearchRequested Activity.onSearchRequested()} or
- * {@link android.app.Activity#startSearch Activity.startSearch()}.
- *
- * @param initialQuery A search string can be pre-entered here, but this
- * is typically null or empty.
- * @param selectInitialQuery If true, the intial query will be preselected, which means that
- * any further typing will replace it. This is useful for cases where an entire pre-formed
- * query is being inserted. If false, the selection point will be placed at the end of the
- * inserted query. This is useful when the inserted query is text that the user entered,
- * and the user would expect to be able to keep typing. <i>This parameter is only meaningful
- * if initialQuery is a non-empty string.</i>
- * @param launchActivity The ComponentName of the activity that has launched this search.
- * @param appSearchData An application can insert application-specific
- * context here, in order to improve quality or specificity of its own
- * searches. This data will be returned with SEARCH intent(s). Null if
- * no extra data is required.
- * @param globalSearch If false, this will only launch the search that has been specifically
- * defined by the application (which is usually defined as a local search). If no default
- * search is defined in the current application or activity, no search will be launched.
- * If true, this will always launch a platform-global (e.g. web-based) search instead.
- *
- * @see android.app.Activity#onSearchRequested
- * @see #stopSearch
- */
- public void startSearch(String initialQuery,
- boolean selectInitialQuery,
- ComponentName launchActivity,
- Bundle appSearchData,
- boolean globalSearch) {
-
- if (mSearchDialog == null) {
- mSearchDialog = new SearchDialog(mContext);
- }
-
- // activate the search manager and start it up!
- mSearchDialog.show(initialQuery, selectInitialQuery, launchActivity, appSearchData,
- globalSearch);
-
- mSearchDialog.setOnCancelListener(this);
- mSearchDialog.setOnDismissListener(this);
- }
-
- /**
- * Terminate search UI.
- *
- * <p>Typically the user will terminate the search UI by launching a
- * search or by canceling. This function allows the underlying application
- * or activity to cancel the search prematurely (for any reason).
- *
- * <p>This function can be safely called at any time (even if no search is active.)
- *
- * @see #startSearch
- */
- public void stopSearch() {
- if (mSearchDialog != null) {
- mSearchDialog.cancel();
- }
- }
-
- /**
- * Determine if the Search UI is currently displayed.
- *
- * This is provided primarily for application test purposes.
- *
- * @return Returns true if the search UI is currently displayed.
- *
- * @hide
- */
- public boolean isVisible() {
- if (mSearchDialog != null) {
- return mSearchDialog.isShowing();
- }
- return false;
- }
-
- /**
- * See {@link #setOnDismissListener} for configuring your activity to monitor search UI state.
- */
- public interface OnDismissListener {
- /**
- * This method will be called when the search UI is dismissed. To make use if it, you must
- * implement this method in your activity, and call {@link #setOnDismissListener} to
- * register it.
- */
- public void onDismiss();
- }
-
- /**
- * See {@link #setOnCancelListener} for configuring your activity to monitor search UI state.
- */
- public interface OnCancelListener {
- /**
- * This method will be called when the search UI is canceled. To make use if it, you must
- * implement this method in your activity, and call {@link #setOnCancelListener} to
- * register it.
- */
- public void onCancel();
- }
-
- /**
- * Set or clear the callback that will be invoked whenever the search UI is dismissed.
- *
- * @param listener The {@link OnDismissListener} to use, or null.
- */
- public void setOnDismissListener(final OnDismissListener listener) {
- mDismissListener = listener;
- }
-
- /**
- * The callback from the search dialog when dismissed
- * @hide
- */
- public void onDismiss(DialogInterface dialog) {
- if (dialog == mSearchDialog) {
- if (mDismissListener != null) {
- mDismissListener.onDismiss();
- }
- }
- }
-
- /**
- * Set or clear the callback that will be invoked whenever the search UI is canceled.
- *
- * @param listener The {@link OnCancelListener} to use, or null.
- */
- public void setOnCancelListener(final OnCancelListener listener) {
- mCancelListener = listener;
- }
-
-
- /**
- * The callback from the search dialog when canceled
- * @hide
- */
- public void onCancel(DialogInterface dialog) {
- if (dialog == mSearchDialog) {
- if (mCancelListener != null) {
- mCancelListener.onCancel();
- }
- }
- }
-
- /**
- * Save instance state so we can recreate after a rotation.
- *
- * @hide
- */
- void saveSearchDialog(Bundle outState, String key) {
- if (mSearchDialog != null && mSearchDialog.isShowing()) {
- Bundle searchDialogState = mSearchDialog.onSaveInstanceState();
- outState.putBundle(key, searchDialogState);
- }
- }
-
- /**
- * Restore instance state after a rotation.
- *
- * @hide
- */
- void restoreSearchDialog(Bundle inState, String key) {
- Bundle searchDialogState = inState.getBundle(key);
- if (searchDialogState != null) {
- if (mSearchDialog == null) {
- mSearchDialog = new SearchDialog(mContext);
- }
- mSearchDialog.onRestoreInstanceState(searchDialogState);
- }
- }
-
- /**
- * Hook for updating layout on a rotation
- *
- * @hide
- */
- void onConfigurationChanged(Configuration newConfig) {
- if (mSearchDialog != null && mSearchDialog.isShowing()) {
- mSearchDialog.onConfigurationChanged(newConfig);
- }
- }
-
-}
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
deleted file mode 100644
index a6a436f..0000000
--- a/core/java/android/app/Service.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.ComponentCallbacks;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.ContextWrapper;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.os.RemoteException;
-import android.os.IBinder;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * A Service is an application component that runs in the background, not
- * interacting with the user, for an indefinite period of time. Each service
- * class must have a corresponding
- * {@link android.R.styleable#AndroidManifestService &lt;service&gt;}
- * declaration in its package's <code>AndroidManifest.xml</code>. Services
- * can be started with
- * {@link android.content.Context#startService Context.startService()} and
- * {@link android.content.Context#bindService Context.bindService()}.
- *
- * <p>Note that services, like other application objects, run in the main
- * thread of their hosting process. This means that, if your service is going
- * to do any CPU intensive (such as MP3 playback) or blocking (such as
- * networking) operations, it should spawn its own thread in which to do that
- * work. More information on this can be found in
- * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
- * Processes and Threads</a>.</p>
- *
- * <p>The Service class is an important part of an
- * <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">application's overall lifecycle</a>.</p>
- *
- * <p>Topics covered here:
- * <ol>
- * <li><a href="#ServiceLifecycle">Service Lifecycle</a>
- * <li><a href="#Permissions">Permissions</a>
- * <li><a href="#ProcessLifecycle">Process Lifecycle</a>
- * </ol>
- *
- * <a name="ServiceLifecycle"></a>
- * <h3>Service Lifecycle</h3>
- *
- * <p>There are two reasons that a service can be run by the system. If someone
- * calls {@link android.content.Context#startService Context.startService()} then the system will
- * retrieve the service (creating it and calling its {@link #onCreate} method
- * if needed) and then call its {@link #onStart} method with the
- * arguments supplied by the client. The service will at this point continue
- * running until {@link android.content.Context#stopService Context.stopService()} or
- * {@link #stopSelf()} is called. Note that multiple calls to
- * Context.startService() do not nest (though they do result in multiple corresponding
- * calls to onStart()), so no matter how many times it is started a service
- * will be stopped once Context.stopService() or stopSelf() is called.
- *
- * <p>Clients can also use {@link android.content.Context#bindService Context.bindService()} to
- * obtain a persistent connection to a service. This likewise creates the
- * service if it is not already running (calling {@link #onCreate} while
- * doing so), but does not call onStart(). The client will receive the
- * {@link android.os.IBinder} object that the service returns from its
- * {@link #onBind} method, allowing the client to then make calls back
- * to the service. The service will remain running as long as the connection
- * is established (whether or not the client retains a reference on the
- * service's IBinder). Usually the IBinder returned is for a complex
- * interface that has been <a href="{@docRoot}guide/developing/tools/aidl.html">written
- * in aidl</a>.
- *
- * <p>A service can be both started and have connections bound to it. In such
- * a case, the system will keep the service running as long as either it is
- * started <em>or</em> there are one or more connections to it with the
- * {@link android.content.Context#BIND_AUTO_CREATE Context.BIND_AUTO_CREATE}
- * flag. Once neither
- * of these situations hold, the service's {@link #onDestroy} method is called
- * and the service is effectively terminated. All cleanup (stopping threads,
- * unregistering receivers) should be complete upon returning from onDestroy().
- *
- * <a name="Permissions"></a>
- * <h3>Permissions</h3>
- *
- * <p>Global access to a service can be enforced when it is declared in its
- * manifest's {@link android.R.styleable#AndroidManifestService &lt;service&gt;}
- * tag. By doing so, other applications will need to declare a corresponding
- * {@link android.R.styleable#AndroidManifestUsesPermission &lt;uses-permission&gt;}
- * element in their own manifest to be able to start, stop, or bind to
- * the service.
- *
- * <p>In addition, a service can protect individual IPC calls into it with
- * permissions, by calling the
- * {@link #checkCallingPermission}
- * method before executing the implementation of that call.
- *
- * <p>See the <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a>
- * document for more information on permissions and security in general.
- *
- * <a name="ProcessLifecycle"></a>
- * <h3>Process Lifecycle</h3>
- *
- * <p>The Android system will attempt to keep the process hosting a service
- * around as long as the service has been started or has clients bound to it.
- * When running low on memory and needing to kill existing processes, the
- * priority of a process hosting the service will be the higher of the
- * following possibilities:
- *
- * <ul>
- * <li><p>If the service is currently executing code in its
- * {@link #onCreate onCreate()}, {@link #onStart onStart()},
- * or {@link #onDestroy onDestroy()} methods, then the hosting process will
- * be a foreground process to ensure this code can execute without
- * being killed.
- * <li><p>If the service has been started, then its hosting process is considered
- * to be less important than any processes that are currently visible to the
- * user on-screen, but more important than any process not visible. Because
- * only a few processes are generally visible to the user, this means that
- * the service should not be killed except in extreme low memory conditions.
- * <li><p>If there are clients bound to the service, then the service's hosting
- * process is never less important than the most important client. That is,
- * if one of its clients is visible to the user, then the service itself is
- * considered to be visible.
- * </ul>
- *
- * <p>Note this means that most of the time your service is running, it may
- * be killed by the system if it is under heavy memory pressure. If this
- * happens, the system will later try to restart the service. An important
- * consequence of this is that if you implement {@link #onStart onStart()}
- * to schedule work to be done asynchronously or in another thread, then you
- * may want to write information about that work into persistent storage
- * during the onStart() call so that it does not get lost if the service later
- * gets killed.
- *
- * <p>Other application components running in the same process as the service
- * (such as an {@link android.app.Activity}) can, of course, increase the
- * importance of the overall
- * process beyond just the importance of the service itself.
- */
-public abstract class Service extends ContextWrapper implements ComponentCallbacks {
- private static final String TAG = "Service";
-
- public Service() {
- super(null);
- }
-
- /** Return the application that owns this service. */
- public final Application getApplication() {
- return mApplication;
- }
-
- /**
- * Called by the system when the service is first created. Do not call this method directly.
- */
- public void onCreate() {
- }
-
- /**
- * Called by the system every time a client explicitly starts the service by calling
- * {@link android.content.Context#startService}, providing the arguments it supplied and a
- * unique integer token representing the start request. Do not call this method directly.
- *
- * @param intent The Intent supplied to {@link android.content.Context#startService},
- * as given.
- * @param startId A unique integer representing this specific request to
- * start. Use with {@link #stopSelfResult(int)}.
- *
- * @see #stopSelfResult(int)
- */
- public void onStart(Intent intent, int startId) {
- }
-
- /**
- * Called by the system to notify a Service that it is no longer used and is being removed. The
- * service should clean up an resources it holds (threads, registered
- * receivers, etc) at this point. Upon return, there will be no more calls
- * in to this Service object and it is effectively dead. Do not call this method directly.
- */
- public void onDestroy() {
- }
-
- public void onConfigurationChanged(Configuration newConfig) {
- }
-
- public void onLowMemory() {
- }
-
- /**
- * Return the communication channel to the service. May return null if
- * clients can not bind to the service. The returned
- * {@link android.os.IBinder} is usually for a complex interface
- * that has been <a href="{@docRoot}guide/developing/tools/aidl.html">described using
- * aidl</a>.
- *
- * <p><em>Note that unlike other application components, calls on to the
- * IBinder interface returned here may not happen on the main thread
- * of the process</em>. More information about this can be found
- * in <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
- * Processes and Threads</a>.</p>
- *
- * @param intent The Intent that was used to bind to this service,
- * as given to {@link android.content.Context#bindService
- * Context.bindService}. Note that any extras that were included with
- * the Intent at that point will <em>not</em> be seen here.
- *
- * @return Return an IBinder through which clients can call on to the
- * service.
- */
- public abstract IBinder onBind(Intent intent);
-
- /**
- * Called when all clients have disconnected from a particular interface
- * published by the service. The default implementation does nothing and
- * returns false.
- *
- * @param intent The Intent that was used to bind to this service,
- * as given to {@link android.content.Context#bindService
- * Context.bindService}. Note that any extras that were included with
- * the Intent at that point will <em>not</em> be seen here.
- *
- * @return Return true if you would like to have the service's
- * {@link #onRebind} method later called when new clients bind to it.
- */
- public boolean onUnbind(Intent intent) {
- return false;
- }
-
- /**
- * Called when new clients have connected to the service, after it had
- * previously been notified that all had disconnected in its
- * {@link #onUnbind}. This will only be called if the implementation
- * of {@link #onUnbind} was overridden to return true.
- *
- * @param intent The Intent that was used to bind to this service,
- * as given to {@link android.content.Context#bindService
- * Context.bindService}. Note that any extras that were included with
- * the Intent at that point will <em>not</em> be seen here.
- */
- public void onRebind(Intent intent) {
- }
-
- /**
- * Stop the service, if it was previously started. This is the same as
- * calling {@link android.content.Context#stopService} for this particular service.
- *
- * @see #stopSelfResult(int)
- */
- public final void stopSelf() {
- stopSelf(-1);
- }
-
- /**
- * Old version of {@link #stopSelfResult} that doesn't return a result.
- *
- * @see #stopSelfResult
- */
- public final void stopSelf(int startId) {
- if (mActivityManager == null) {
- return;
- }
- try {
- mActivityManager.stopServiceToken(
- new ComponentName(this, mClassName), mToken, startId);
- } catch (RemoteException ex) {
- }
- }
-
- /**
- * Stop the service, if the most recent time it was started was
- * <var>startId</var>. This is the same as calling {@link
- * android.content.Context#stopService} for this particular service but allows you to
- * safely avoid stopping if there is a start request from a client that you
- * haven't yet see in {@link #onStart}.
- *
- * @param startId The most recent start identifier received in {@link
- * #onStart}.
- * @return Returns true if the startId matches the last start request
- * and the service will be stopped, else false.
- *
- * @see #stopSelf()
- */
- public final boolean stopSelfResult(int startId) {
- if (mActivityManager == null) {
- return false;
- }
- try {
- return mActivityManager.stopServiceToken(
- new ComponentName(this, mClassName), mToken, startId);
- } catch (RemoteException ex) {
- }
- return false;
- }
-
- /**
- * Control whether this service is considered to be a foreground service.
- * By default services are background, meaning that if the system needs to
- * kill them to reclaim more memory (such as to display a large page in a
- * web browser), they can be killed without too much harm. You can set this
- * flag if killing your service would be disruptive to the user: such as
- * if your service is performing background music playback, so the user
- * would notice if their music stopped playing.
- *
- * @param isForeground Determines whether this service is considered to
- * be foreground (true) or background (false).
- */
- public final void setForeground(boolean isForeground) {
- if (mActivityManager == null) {
- return;
- }
- try {
- mActivityManager.setServiceForeground(
- new ComponentName(this, mClassName), mToken, isForeground);
- } catch (RemoteException ex) {
- }
- }
-
- /**
- * Print the Service's state into the given stream. This gets invoked if
- * you run "adb shell dumpsys activity service <yourservicename>".
- * This is distinct from "dumpsys <servicename>", which only works for
- * named system services and which invokes the {@link IBinder#dump} method
- * on the {@link IBinder} interface registered with ServiceManager.
- *
- * @param fd The raw file descriptor that the dump is being sent to.
- * @param writer The PrintWriter to which you should dump your state. This will be
- * closed for you after you return.
- * @param args additional arguments to the dump request.
- */
- protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- writer.println("nothing to dump");
- }
-
- @Override
- protected void finalize() throws Throwable {
- super.finalize();
- //Log.i("Service", "Finalizing Service: " + this);
- }
-
- // ------------------ Internal API ------------------
-
- /**
- * @hide
- */
- public final void attach(
- Context context,
- ActivityThread thread, String className, IBinder token,
- Application application, Object activityManager) {
- attachBaseContext(context);
- mThread = thread; // NOTE: unused - remove?
- mClassName = className;
- mToken = token;
- mApplication = application;
- mActivityManager = (IActivityManager)activityManager;
- }
-
- final String getClassName() {
- return mClassName;
- }
-
- // set by the thread after the constructor and before onCreate(Bundle icicle) is called.
- private ActivityThread mThread = null;
- private String mClassName = null;
- private IBinder mToken = null;
- private Application mApplication = null;
- private IActivityManager mActivityManager = null;
-}
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
deleted file mode 100644
index 51d7393..0000000
--- a/core/java/android/app/StatusBarManager.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package android.app;
-
-import android.content.Context;
-import android.os.Binder;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.os.ServiceManager;
-
-/**
- * Allows an app to control the status bar.
- *
- * @hide
- */
-public class StatusBarManager {
- /**
- * Flag for {@link #disable} to make the status bar not expandable. Unless you also
- * set {@link #DISABLE_NOTIFICATIONS}, new notifications will continue to show.
- */
- public static final int DISABLE_EXPAND = 0x00000001;
-
- /**
- * Flag for {@link #disable} to hide notification icons and ticker text.
- */
- public static final int DISABLE_NOTIFICATION_ICONS = 0x00000002;
-
- /**
- * Flag for {@link #disable} to disable incoming notification alerts. This will not block
- * icons, but it will block sound, vibrating and other visual or aural notifications.
- */
- public static final int DISABLE_NOTIFICATION_ALERTS = 0x00000004;
-
- /**
- * Re-enable all of the status bar features that you've disabled.
- */
- public static final int DISABLE_NONE = 0x00000000;
-
- private Context mContext;
- private IStatusBar mService;
- private IBinder mToken = new Binder();
-
- StatusBarManager(Context context) {
- mContext = context;
- mService = IStatusBar.Stub.asInterface(
- ServiceManager.getService(Context.STATUS_BAR_SERVICE));
- }
-
- /**
- * Disable some features in the status bar. Pass the bitwise-or of the DISABLE_* flags.
- * To re-enable everything, pass {@link #DISABLE_NONE}.
- */
- public void disable(int what) {
- try {
- mService.disable(what, mToken, mContext.getPackageName());
- } catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
- }
- }
-
- /**
- * Expand the status bar.
- */
- public void expand() {
- try {
- mService.activate();
- } catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
- }
- }
-
- /**
- * Collapse the status bar.
- */
- public void collapse() {
- try {
- mService.deactivate();
- } catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
- }
- }
-
- /**
- * Toggle the status bar.
- */
- public void toggle() {
- try {
- mService.toggle();
- } catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
- }
- }
-
- public IBinder addIcon(String slot, int iconId, int iconLevel) {
- try {
- return mService.addIcon(slot, mContext.getPackageName(), iconId, iconLevel);
- } catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
- }
- }
-
- public void updateIcon(IBinder key, String slot, int iconId, int iconLevel) {
- try {
- mService.updateIcon(key, slot, mContext.getPackageName(), iconId, iconLevel);
- } catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
- }
- }
-
- public void removeIcon(IBinder key) {
- try {
- mService.removeIcon(key);
- } catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
- }
- }
-}
diff --git a/core/java/android/app/TabActivity.java b/core/java/android/app/TabActivity.java
deleted file mode 100644
index 033fa0c..0000000
--- a/core/java/android/app/TabActivity.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.os.Bundle;
-import android.view.View;
-import android.widget.TabHost;
-import android.widget.TabWidget;
-import android.widget.TextView;
-
-/**
- * An activity that contains and runs multiple embedded activities or views.
- */
-public class TabActivity extends ActivityGroup {
- private TabHost mTabHost;
- private String mDefaultTab = null;
- private int mDefaultTabIndex = -1;
-
- public TabActivity() {
- }
-
- /**
- * Sets the default tab that is the first tab highlighted.
- *
- * @param tag the name of the default tab
- */
- public void setDefaultTab(String tag) {
- mDefaultTab = tag;
- mDefaultTabIndex = -1;
- }
-
- /**
- * Sets the default tab that is the first tab highlighted.
- *
- * @param index the index of the default tab
- */
- public void setDefaultTab(int index) {
- mDefaultTab = null;
- mDefaultTabIndex = index;
- }
-
- @Override
- protected void onRestoreInstanceState(Bundle state) {
- super.onRestoreInstanceState(state);
- ensureTabHost();
- String cur = state.getString("currentTab");
- if (cur != null) {
- mTabHost.setCurrentTabByTag(cur);
- }
- if (mTabHost.getCurrentTab() < 0) {
- if (mDefaultTab != null) {
- mTabHost.setCurrentTabByTag(mDefaultTab);
- } else if (mDefaultTabIndex >= 0) {
- mTabHost.setCurrentTab(mDefaultTabIndex);
- }
- }
- }
-
- @Override
- protected void onPostCreate(Bundle icicle) {
- super.onPostCreate(icicle);
-
- ensureTabHost();
-
- if (mTabHost.getCurrentTab() == -1) {
- mTabHost.setCurrentTab(0);
- }
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- String currentTabTag = mTabHost.getCurrentTabTag();
- if (currentTabTag != null) {
- outState.putString("currentTab", currentTabTag);
- }
- }
-
- /**
- * Updates the screen state (current list and other views) when the
- * content changes.
- *
- *@see Activity#onContentChanged()
- */
- @Override
- public void onContentChanged() {
- super.onContentChanged();
- mTabHost = (TabHost) findViewById(com.android.internal.R.id.tabhost);
-
- if (mTabHost == null) {
- throw new RuntimeException(
- "Your content must have a TabHost whose id attribute is " +
- "'android.R.id.tabhost'");
- }
- mTabHost.setup(getLocalActivityManager());
- }
-
- private void ensureTabHost() {
- if (mTabHost == null) {
- this.setContentView(com.android.internal.R.layout.tab_content);
- }
- }
-
- @Override
- protected void
- onChildTitleChanged(Activity childActivity, CharSequence title) {
- // Dorky implementation until we can have multiple activities running.
- if (getLocalActivityManager().getCurrentActivity() == childActivity) {
- View tabView = mTabHost.getCurrentTabView();
- if (tabView != null && tabView instanceof TextView) {
- ((TextView) tabView).setText(title);
- }
- }
- }
-
- /**
- * Returns the {@link TabHost} the activity is using to host its tabs.
- *
- * @return the {@link TabHost} the activity is using to host its tabs.
- */
- public TabHost getTabHost() {
- ensureTabHost();
- return mTabHost;
- }
-
- /**
- * Returns the {@link TabWidget} the activity is using to draw the actual tabs.
- *
- * @return the {@link TabWidget} the activity is using to draw the actual tabs.
- */
- public TabWidget getTabWidget() {
- return mTabHost.getTabWidget();
- }
-}
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java
deleted file mode 100644
index 002b01f..0000000
--- a/core/java/android/app/TimePickerDialog.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.os.Bundle;
-import android.text.format.DateFormat;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.TimePicker;
-import android.widget.TimePicker.OnTimeChangedListener;
-
-import com.android.internal.R;
-
-import java.util.Calendar;
-
-/**
- * A dialog that prompts the user for the time of day using a {@link TimePicker}.
- */
-public class TimePickerDialog extends AlertDialog implements OnClickListener,
- OnTimeChangedListener {
-
- /**
- * The callback interface used to indicate the user is done filling in
- * the time (they clicked on the 'Set' button).
- */
- public interface OnTimeSetListener {
-
- /**
- * @param view The view associated with this listener.
- * @param hourOfDay The hour that was set.
- * @param minute The minute that was set.
- */
- void onTimeSet(TimePicker view, int hourOfDay, int minute);
- }
-
- private static final String HOUR = "hour";
- private static final String MINUTE = "minute";
- private static final String IS_24_HOUR = "is24hour";
-
- private final TimePicker mTimePicker;
- private final OnTimeSetListener mCallback;
- private final Calendar mCalendar;
- private final java.text.DateFormat mDateFormat;
-
- int mInitialHourOfDay;
- int mInitialMinute;
- boolean mIs24HourView;
-
- /**
- * @param context Parent.
- * @param callBack How parent is notified.
- * @param hourOfDay The initial hour.
- * @param minute The initial minute.
- * @param is24HourView Whether this is a 24 hour view, or AM/PM.
- */
- public TimePickerDialog(Context context,
- OnTimeSetListener callBack,
- int hourOfDay, int minute, boolean is24HourView) {
- this(context, com.android.internal.R.style.Theme_Dialog_Alert,
- callBack, hourOfDay, minute, is24HourView);
- }
-
- /**
- * @param context Parent.
- * @param theme the theme to apply to this dialog
- * @param callBack How parent is notified.
- * @param hourOfDay The initial hour.
- * @param minute The initial minute.
- * @param is24HourView Whether this is a 24 hour view, or AM/PM.
- */
- public TimePickerDialog(Context context,
- int theme,
- OnTimeSetListener callBack,
- int hourOfDay, int minute, boolean is24HourView) {
- super(context, theme);
- mCallback = callBack;
- mInitialHourOfDay = hourOfDay;
- mInitialMinute = minute;
- mIs24HourView = is24HourView;
-
- mDateFormat = DateFormat.getTimeFormat(context);
- mCalendar = Calendar.getInstance();
- updateTitle(mInitialHourOfDay, mInitialMinute);
-
- setButton(context.getText(R.string.date_time_set), this);
- setButton2(context.getText(R.string.cancel), (OnClickListener) null);
- setIcon(R.drawable.ic_dialog_time);
-
- LayoutInflater inflater =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(R.layout.time_picker_dialog, null);
- setView(view);
- mTimePicker = (TimePicker) view.findViewById(R.id.timePicker);
-
- // initialize state
- mTimePicker.setCurrentHour(mInitialHourOfDay);
- mTimePicker.setCurrentMinute(mInitialMinute);
- mTimePicker.setIs24HourView(mIs24HourView);
- mTimePicker.setOnTimeChangedListener(this);
- }
-
- public void onClick(DialogInterface dialog, int which) {
- if (mCallback != null) {
- mTimePicker.clearFocus();
- mCallback.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
- mTimePicker.getCurrentMinute());
- }
- }
-
- public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
- updateTitle(hourOfDay, minute);
- }
-
- public void updateTime(int hourOfDay, int minutOfHour) {
- mTimePicker.setCurrentHour(hourOfDay);
- mTimePicker.setCurrentMinute(minutOfHour);
- }
-
- private void updateTitle(int hour, int minute) {
- mCalendar.set(Calendar.HOUR_OF_DAY, hour);
- mCalendar.set(Calendar.MINUTE, minute);
- setTitle(mDateFormat.format(mCalendar.getTime()));
- }
-
- @Override
- public Bundle onSaveInstanceState() {
- Bundle state = super.onSaveInstanceState();
- state.putInt(HOUR, mTimePicker.getCurrentHour());
- state.putInt(MINUTE, mTimePicker.getCurrentMinute());
- state.putBoolean(IS_24_HOUR, mTimePicker.is24HourView());
- return state;
- }
-
- @Override
- public void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- int hour = savedInstanceState.getInt(HOUR);
- int minute = savedInstanceState.getInt(MINUTE);
- mTimePicker.setCurrentHour(hour);
- mTimePicker.setCurrentMinute(minute);
- mTimePicker.setIs24HourView(savedInstanceState.getBoolean(IS_24_HOUR));
- mTimePicker.setOnTimeChangedListener(this);
- updateTitle(hour, minute);
- }
-}
diff --git a/core/java/android/app/package.html b/core/java/android/app/package.html
deleted file mode 100644
index 048ee93..0000000
--- a/core/java/android/app/package.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<html>
-<head>
-<script type="text/javascript" src="http://www.corp.google.com/style/prettify.js"></script>
-<script src="http://www.corp.google.com/eng/techpubs/include/navbar.js" type="text/javascript"></script>
-</head>
-
-<body>
-
-<p>High-level classes encapsulating the overall Android application model.
-The central class is {@link android.app.Activity}, with other top-level
-application components being defined by {@link android.app.Service} and,
-from the {@link android.content} package, {@link android.content.BroadcastReceiver}
-and {@link android.content.ContentProvider}. It also includes application
-tools, such as dialogs and notifications.</p>
-
-<p>This package builds on top of the lower-level Android packages
-{@link android.widget}, {@link android.view}, {@link android.content},
-{@link android.text}, {@link android.graphics}, {@link android.os}, and
-{@link android.util}.</p>
-
-<p>An {@link android.app.Activity Activity} is a specific operation the
-user can perform, generally corresponding
-to one screen in the user interface.
-It is the basic building block of an Android application.
-Examples of activities are "view the
-list of people," "view the details of a person," "edit information about
-a person," "view an image," etc. Switching from one activity to another
-generally implies adding a new entry on the navigation history; that is,
-going "back" means moving to the previous activity you were doing.</p>
-
-<p>A set of related activities can be grouped together as a "task". Until
-a new task is explicitly specified, all activites you start are considered
-to be part of the current task. While the only way to navigate between
-individual activities is by going "back" in the history stack, the group
-of activities in a task can be moved in relation to other tasks: for example
-to the front or the back of the history stack. This mechanism can be used
-to present to the user a list of things they have been doing, moving
-between them without disrupting previous work.
-</p>
-
-<p>A complete "application" is a set of activities that allow the user to do a
-cohesive group of operations -- such as working with contacts, working with a
-calendar, messaging, etc. Though there can be a custom application object
-associated with a set of activities, in many cases this is not needed --
-each activity provides a particular path into one of the various kinds of
-functionality inside of the application, serving as its on self-contained
-"mini application".
-</p>
-
-<p>This approach allows an application to be broken into pieces, which
-can be reused and replaced in a variety of ways. Consider, for example,
-a "camera application." There are a number of things this application
-must do, each of which is provided by a separate activity: take a picture
-(creating a new image), browse through the existing images, display a
-specific image, etc. If the "contacts application" then wants to let the
-user associate an image with a person, it can simply launch the existing
-"take a picture" or "select an image" activity that is part of the camera
-application and attach the picture it gets back.
-</p>
-
-<p>Note that there is no hard relationship between tasks the user sees and
-applications the developer writes. A task can be composed of activities from
-multiple applications (such as the contact application using an activity in
-the camera application to get a picture for a person), and multiple active
-tasks may be running for the same application (such as editing e-mail messages
-to two different people). The way tasks are organized is purely a UI policy
-decided by the system; for example, typically a new task is started when the
-user goes to the application launcher and selects an application.
-</p>
-
-</body>
-</html>
diff --git a/core/java/android/bluetooth/AtCommandHandler.java b/core/java/android/bluetooth/AtCommandHandler.java
deleted file mode 100644
index 8de2133..0000000
--- a/core/java/android/bluetooth/AtCommandHandler.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.bluetooth.AtCommandResult;
-
-/**
- * Handler Interface for {@link AtParser}.<p>
- * @hide
- */
-public abstract class AtCommandHandler {
-
- /**
- * Handle Basic commands "ATA".<p>
- * These are single letter commands such as ATA and ATD. Anything following
- * the single letter command ('A' and 'D' respectively) will be passed as
- * 'arg'.<p>
- * For example, "ATDT1234" would result in the call
- * handleBasicCommand("T1234").<p>
- * @param arg Everything following the basic command character.
- * @return The result of this command.
- */
- public AtCommandResult handleBasicCommand(String arg) {
- return new AtCommandResult(AtCommandResult.ERROR);
- }
-
- /**
- * Handle Actions command "AT+FOO".<p>
- * Action commands are part of the Extended command syntax, and are
- * typically used to signal an action on "FOO".<p>
- * @return The result of this command.
- */
- public AtCommandResult handleActionCommand() {
- return new AtCommandResult(AtCommandResult.ERROR);
- }
-
- /**
- * Handle Read command "AT+FOO?".<p>
- * Read commands are part of the Extended command syntax, and are
- * typically used to read the value of "FOO".<p>
- * @return The result of this command.
- */
- public AtCommandResult handleReadCommand() {
- return new AtCommandResult(AtCommandResult.ERROR);
- }
-
- /**
- * Handle Set command "AT+FOO=...".<p>
- * Set commands are part of the Extended command syntax, and are
- * typically used to set the value of "FOO". Multiple arguments can be
- * sent.<p>
- * AT+FOO=[<arg1>[,<arg2>[,...]]]<p>
- * Each argument will be either numeric (Integer) or String.
- * handleSetCommand is passed a generic Object[] array in which each
- * element will be an Integer (if it can be parsed with parseInt()) or
- * String.<p>
- * Missing arguments ",," are set to empty Strings.<p>
- * @param args Array of String and/or Integer's. There will always be at
- * least one element in this array.
- * @return The result of this command.
- */
- // Typically used to set this paramter
- public AtCommandResult handleSetCommand(Object[] args) {
- return new AtCommandResult(AtCommandResult.ERROR);
- }
-
- /**
- * Handle Test command "AT+FOO=?".<p>
- * Test commands are part of the Extended command syntax, and are typically
- * used to request an indication of the range of legal values that "FOO"
- * can take.<p>
- * By defualt we return an OK result, to indicate that this command is at
- * least recognized.<p>
- * @return The result of this command.
- */
- public AtCommandResult handleTestCommand() {
- return new AtCommandResult(AtCommandResult.OK);
- }
-}
diff --git a/core/java/android/bluetooth/AtCommandResult.java b/core/java/android/bluetooth/AtCommandResult.java
deleted file mode 100644
index 638be2d..0000000
--- a/core/java/android/bluetooth/AtCommandResult.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import java.util.*;
-
-/**
- * The result of execution of an single AT command.<p>
- *
- *
- * This class can represent the final response to an AT command line, and also
- * intermediate responses to a single command within a chained AT command
- * line.<p>
- *
- * The actual responses that are intended to be send in reply to the AT command
- * line are stored in a string array. The final response is stored as an
- * int enum, converted to a string when toString() is called. Only a single
- * final response is sent from multiple commands chained into a single command
- * line.<p>
- * @hide
- */
-public class AtCommandResult {
- // Result code enumerations
- public static final int OK = 0;
- public static final int ERROR = 1;
- public static final int UNSOLICITED = 2;
-
- private static final String OK_STRING = "OK";
- private static final String ERROR_STRING = "ERROR";
-
- private int mResultCode; // Result code
- private StringBuilder mResponse; // Response with CRLF line breaks
-
- /**
- * Construct a new AtCommandResult with given result code, and an empty
- * response array.
- * @param resultCode One of OK, ERROR or UNSOLICITED.
- */
- public AtCommandResult(int resultCode) {
- mResultCode = resultCode;
- mResponse = new StringBuilder();
- }
-
- /**
- * Construct a new AtCommandResult with result code OK, and the specified
- * single line response.
- * @param response The single line response.
- */
- public AtCommandResult(String response) {
- this(OK);
- addResponse(response);
- }
-
- public int getResultCode() {
- return mResultCode;
- }
-
- /**
- * Add another line to the response.
- */
- public void addResponse(String response) {
- appendWithCrlf(mResponse, response);
- }
-
- /**
- * Add the given result into this AtCommandResult object.<p>
- * Used to combine results from multiple commands in a single command line
- * (command chaining).
- * @param result The AtCommandResult to add to this result.
- */
- public void addResult(AtCommandResult result) {
- if (result != null) {
- appendWithCrlf(mResponse, result.mResponse.toString());
- mResultCode = result.mResultCode;
- }
- }
-
- /**
- * Generate the string response ready to send
- */
- public String toString() {
- StringBuilder result = new StringBuilder(mResponse.toString());
- switch (mResultCode) {
- case OK:
- appendWithCrlf(result, OK_STRING);
- break;
- case ERROR:
- appendWithCrlf(result, ERROR_STRING);
- break;
- }
- return result.toString();
- }
-
- /** Append a string to a string builder, joining with a double
- * CRLF. Used to create multi-line AT command replies
- */
- public static void appendWithCrlf(StringBuilder str1, String str2) {
- if (str1.length() > 0 && str2.length() > 0) {
- str1.append("\r\n\r\n");
- }
- str1.append(str2);
- }
-};
diff --git a/core/java/android/bluetooth/AtParser.java b/core/java/android/bluetooth/AtParser.java
deleted file mode 100644
index 1ea3150..0000000
--- a/core/java/android/bluetooth/AtParser.java
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.bluetooth.AtCommandHandler;
-import android.bluetooth.AtCommandResult;
-
-import java.util.*;
-
-/**
- * An AT (Hayes command) Parser based on (a subset of) the ITU-T V.250 standard.
- * <p>
- *
- * Conforment with the subset of V.250 required for implementation of the
- * Bluetooth Headset and Handsfree Profiles, as per Bluetooth SIP
- * specifications. Also implements some V.250 features not required by
- * Bluetooth - such as chained commands.<p>
- *
- * Command handlers are registered with an AtParser object. These handlers are
- * invoked when command lines are processed by AtParser's process() method.<p>
- *
- * The AtParser object accepts a new command line to parse via its process()
- * method. It breaks each command line into one or more commands. Each command
- * is parsed for name, type, and (optional) arguments, and an appropriate
- * external handler method is called through the AtCommandHandler interface.
- *
- * The command types are<ul>
- * <li>Basic Command. For example "ATDT1234567890". Basic command names are a
- * single character (e.g. "D"), and everything following this character is
- * passed to the handler as a string argument (e.g. "T1234567890").
- * <li>Action Command. For example "AT+CIMI". The command name is "CIMI", and
- * there are no arguments for action commands.
- * <li>Read Command. For example "AT+VGM?". The command name is "VGM", and there
- * are no arguments for get commands.
- * <li>Set Command. For example "AT+VGM=14". The command name is "VGM", and
- * there is a single integer argument in this case. In the general case then
- * can be zero or more arguments (comma deliminated) each of integer or string
- * form.
- * <li>Test Command. For example "AT+VGM=?. No arguments.
- * </ul>
- *
- * In V.250 the last four command types are known as Extended Commands, and
- * they are used heavily in Bluetooth.<p>
- *
- * Basic commands cannot be chained in this implementation. For Bluetooth
- * headset/handsfree use this is acceptable, because they only use the basic
- * commands ATA and ATD, which are not allowed to be chained. For general V.250
- * use we would need to improve this class to allow Basic command chaining -
- * however its tricky to get right becuase there is no deliminator for Basic
- * command chaining.<p>
- *
- * Extended commands can be chained. For example:<p>
- * AT+VGM?;+VGM=14;+CIMI<p>
- * This is equivalent to:<p>
- * AT+VGM?
- * AT+VGM=14
- * AT+CIMI
- * Except that only one final result code is return (although several
- * intermediate responses may be returned), and as soon as one command in the
- * chain fails the rest are abandonded.<p>
- *
- * Handlers are registered by there command name via register(Char c, ...) or
- * register(String s, ...). Handlers for Basic command should be registered by
- * the basic command character, and handlers for Extended commands should be
- * registered by String.<p>
- *
- * Refer to:<ul>
- * <li>ITU-T Recommendation V.250
- * <li>ETSI TS 127.007 (AT Comannd set for User Equipment, 3GPP TS 27.007)
- * <li>Bluetooth Headset Profile Spec (K6)
- * <li>Bluetooth Handsfree Profile Spec (HFP 1.5)
- * </ul>
- * @hide
- */
-public class AtParser {
-
- // Extended command type enumeration, only used internally
- private static final int TYPE_ACTION = 0; // AT+FOO
- private static final int TYPE_READ = 1; // AT+FOO?
- private static final int TYPE_SET = 2; // AT+FOO=
- private static final int TYPE_TEST = 3; // AT+FOO=?
-
- private HashMap<String, AtCommandHandler> mExtHandlers;
- private HashMap<Character, AtCommandHandler> mBasicHandlers;
-
- private String mLastInput; // for "A/" (repeat last command) support
-
- /**
- * Create a new AtParser.<p>
- * No handlers are registered.
- */
- public AtParser() {
- mBasicHandlers = new HashMap<Character, AtCommandHandler>();
- mExtHandlers = new HashMap<String, AtCommandHandler>();
- mLastInput = "";
- }
-
- /**
- * Register a Basic command handler.<p>
- * Basic command handlers are later called via their
- * <code>handleBasicCommand(String args)</code> method.
- * @param command Command name - a single character
- * @param handler Handler to register
- */
- public void register(Character command, AtCommandHandler handler) {
- mBasicHandlers.put(command, handler);
- }
-
- /**
- * Register an Extended command handler.<p>
- * Extended command handlers are later called via:<ul>
- * <li><code>handleActionCommand()</code>
- * <li><code>handleGetCommand()</code>
- * <li><code>handleSetCommand()</code>
- * <li><code>handleTestCommand()</code>
- * </ul>
- * Only one method will be called for each command processed.
- * @param command Command name - can be multiple characters
- * @param handler Handler to register
- */
- public void register(String command, AtCommandHandler handler) {
- mExtHandlers.put(command, handler);
- }
-
-
- /**
- * Strip input of whitespace and force Uppercase - except sections inside
- * quotes. Also fixes unmatched quotes (by appending a quote). Double
- * quotes " are the only quotes allowed by V.250
- */
- static private String clean(String input) {
- StringBuilder out = new StringBuilder(input.length());
-
- for (int i = 0; i < input.length(); i++) {
- char c = input.charAt(i);
- if (c == '"') {
- int j = input.indexOf('"', i + 1 ); // search for closing "
- if (j == -1) { // unmatched ", insert one.
- out.append(input.substring(i, input.length()));
- out.append('"');
- break;
- }
- out.append(input.substring(i, j + 1));
- i = j;
- } else if (c != ' ') {
- out.append(Character.toUpperCase(c));
- }
- }
-
- return out.toString();
- }
-
- static private boolean isAtoZ(char c) {
- return (c >= 'A' && c <= 'Z');
- }
-
- /**
- * Find a character ch, ignoring quoted sections.
- * Return input.length() if not found.
- */
- static private int findChar(char ch, String input, int fromIndex) {
- for (int i = fromIndex; i < input.length(); i++) {
- char c = input.charAt(i);
- if (c == '"') {
- i = input.indexOf('"', i + 1);
- if (i == -1) {
- return input.length();
- }
- } else if (c == ch) {
- return i;
- }
- }
- return input.length();
- }
-
- /**
- * Break an argument string into individual arguments (comma deliminated).
- * Integer arguments are turned into Integer objects. Otherwise a String
- * object is used.
- */
- static private Object[] generateArgs(String input) {
- int i = 0;
- int j;
- ArrayList<Object> out = new ArrayList<Object>();
- while (i <= input.length()) {
- j = findChar(',', input, i);
-
- String arg = input.substring(i, j);
- try {
- out.add(new Integer(arg));
- } catch (NumberFormatException e) {
- out.add(arg);
- }
-
- i = j + 1; // move past comma
- }
- return out.toArray();
- }
-
- /**
- * Return the index of the end of character after the last characeter in
- * the extended command name. Uses the V.250 spec for allowed command
- * names.
- */
- static private int findEndExtendedName(String input, int index) {
- for (int i = index; i < input.length(); i++) {
- char c = input.charAt(i);
-
- // V.250 defines the following chars as legal extended command
- // names
- if (isAtoZ(c)) continue;
- if (c >= '0' && c <= '9') continue;
- switch (c) {
- case '!':
- case '%':
- case '-':
- case '.':
- case '/':
- case ':':
- case '_':
- continue;
- default:
- return i;
- }
- }
- return input.length();
- }
-
- /**
- * Processes an incoming AT command line.<p>
- * This method will invoke zero or one command handler methods for each
- * command in the command line.<p>
- * @param raw_input The AT input, without EOL deliminator (e.g. <CR>).
- * @return Result object for this command line. This can be
- * converted to a String[] response with toStrings().
- */
- public AtCommandResult process(String raw_input) {
- String input = clean(raw_input);
-
- // Handle "A/" (repeat previous line)
- if (input.regionMatches(0, "A/", 0, 2)) {
- input = new String(mLastInput);
- } else {
- mLastInput = new String(input);
- }
-
- // Handle empty line - no response necessary
- if (input.equals("")) {
- // Return []
- return new AtCommandResult(AtCommandResult.UNSOLICITED);
- }
-
- // Anything else deserves an error
- if (!input.regionMatches(0, "AT", 0, 2)) {
- // Return ["ERROR"]
- return new AtCommandResult(AtCommandResult.ERROR);
- }
-
- // Ok we have a command that starts with AT. Process it
- int index = 2;
- AtCommandResult result =
- new AtCommandResult(AtCommandResult.UNSOLICITED);
- while (index < input.length()) {
- char c = input.charAt(index);
-
- if (isAtoZ(c)) {
- // Option 1: Basic Command
- // Pass the rest of the line as is to the handler. Do not
- // look for any more commands on this line.
- String args = input.substring(index + 1);
- if (mBasicHandlers.containsKey((Character)c)) {
- result.addResult(mBasicHandlers.get(
- (Character)c).handleBasicCommand(args));
- return result;
- } else {
- // no handler
- result.addResult(
- new AtCommandResult(AtCommandResult.ERROR));
- return result;
- }
- // control never reaches here
- }
-
- if (c == '+') {
- // Option 2: Extended Command
- // Search for first non-name character. Shortcircuit if we dont
- // handle this command name.
- int i = findEndExtendedName(input, index + 1);
- String commandName = input.substring(index, i);
- if (!mExtHandlers.containsKey(commandName)) {
- // no handler
- result.addResult(
- new AtCommandResult(AtCommandResult.ERROR));
- return result;
- }
- AtCommandHandler handler = mExtHandlers.get(commandName);
-
- // Search for end of this command - this is usually the end of
- // line
- int endIndex = findChar(';', input, index);
-
- // Determine what type of command this is.
- // Default to TYPE_ACTION if we can't find anything else
- // obvious.
- int type;
-
- if (i >= endIndex) {
- type = TYPE_ACTION;
- } else if (input.charAt(i) == '?') {
- type = TYPE_READ;
- } else if (input.charAt(i) == '=') {
- if (i + 1 < endIndex) {
- if (input.charAt(i + 1) == '?') {
- type = TYPE_TEST;
- } else {
- type = TYPE_SET;
- }
- } else {
- type = TYPE_SET;
- }
- } else {
- type = TYPE_ACTION;
- }
-
- // Call this command. Short-circuit as soon as a command fails
- switch (type) {
- case TYPE_ACTION:
- result.addResult(handler.handleActionCommand());
- break;
- case TYPE_READ:
- result.addResult(handler.handleReadCommand());
- break;
- case TYPE_TEST:
- result.addResult(handler.handleTestCommand());
- break;
- case TYPE_SET:
- Object[] args =
- generateArgs(input.substring(i + 1, endIndex));
- result.addResult(handler.handleSetCommand(args));
- break;
- }
- if (result.getResultCode() != AtCommandResult.OK) {
- return result; // short-circuit
- }
-
- index = endIndex;
- } else {
- // Can't tell if this is a basic or extended command.
- // Push forwards and hope we hit something.
- index++;
- }
- }
- // Finished processing (and all results were ok)
- return result;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
deleted file mode 100644
index b0b0154..0000000
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.server.BluetoothA2dpService;
-import android.content.Context;
-import android.os.ServiceManager;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.util.Log;
-
-import java.util.List;
-
-/**
- * Public API for controlling the Bluetooth A2DP Profile Service.
- *
- * BluetoothA2dp is a proxy object for controlling the Bluetooth A2DP
- * Service via IPC.
- *
- * Creating a BluetoothA2dp object will initiate a binding with the
- * BluetoothHeadset service. Users of this object should call close() when they
- * are finished, so that this proxy object can unbind from the service.
- *
- * Currently the BluetoothA2dp service runs in the system server and this
- * proxy object will be immediately bound to the service on construction.
- * However this may change in future releases, and error codes such as
- * BluetoothError.ERROR_IPC_NOT_READY will be returned from this API when the
- * proxy object is not yet attached.
- *
- * Currently this class provides methods to connect to A2DP audio sinks.
- *
- * @hide
- */
-public class BluetoothA2dp {
- private static final String TAG = "BluetoothA2dp";
-
- /** int extra for SINK_STATE_CHANGED_ACTION */
- public static final String SINK_STATE =
- "android.bluetooth.a2dp.intent.SINK_STATE";
- /** int extra for SINK_STATE_CHANGED_ACTION */
- public static final String SINK_PREVIOUS_STATE =
- "android.bluetooth.a2dp.intent.SINK_PREVIOUS_STATE";
-
- /** Indicates the state of an A2DP audio sink has changed.
- * This intent will always contain SINK_STATE, SINK_PREVIOUS_STATE and
- * BluetoothIntent.ADDRESS extras.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String SINK_STATE_CHANGED_ACTION =
- "android.bluetooth.a2dp.intent.action.SINK_STATE_CHANGED";
-
- public static final int STATE_DISCONNECTED = 0;
- public static final int STATE_CONNECTING = 1;
- public static final int STATE_CONNECTED = 2;
- public static final int STATE_DISCONNECTING = 3;
- /** Playing implies connected */
- public static final int STATE_PLAYING = 4;
-
- /** Default priority for a2dp devices that should allow incoming
- * connections */
- public static final int PRIORITY_AUTO = 100;
- /** Default priority for a2dp devices that should not allow incoming
- * connections */
- public static final int PRIORITY_OFF = 0;
- private final IBluetoothA2dp mService;
- private final Context mContext;
-
- /**
- * Create a BluetoothA2dp proxy object for interacting with the local
- * Bluetooth A2DP service.
- * @param c Context
- */
- public BluetoothA2dp(Context c) {
- mContext = c;
- IBinder b = ServiceManager.getService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE);
- if (b == null) {
- throw new RuntimeException("Bluetooth A2DP service not available!");
- }
- mService = IBluetoothA2dp.Stub.asInterface(b);
- }
-
- /** Initiate a connection to an A2DP sink.
- * Listen for SINK_STATE_CHANGED_ACTION to find out when the
- * connection is completed.
- * @param address Remote BT address.
- * @return Result code, negative indicates an immediate error.
- * @hide
- */
- public int connectSink(String address) {
- try {
- return mService.connectSink(address);
- } catch (RemoteException e) {
- Log.w(TAG, "", e);
- return BluetoothError.ERROR_IPC;
- }
- }
-
- /** Initiate disconnect from an A2DP sink.
- * Listen for SINK_STATE_CHANGED_ACTION to find out when
- * disconnect is completed.
- * @param address Remote BT address.
- * @return Result code, negative indicates an immediate error.
- * @hide
- */
- public int disconnectSink(String address) {
- try {
- return mService.disconnectSink(address);
- } catch (RemoteException e) {
- Log.w(TAG, "", e);
- return BluetoothError.ERROR_IPC;
- }
- }
-
- /** Check if a specified A2DP sink is connected.
- * @param address Remote BT address.
- * @return True if connected (or playing), false otherwise and on error.
- * @hide
- */
- public boolean isSinkConnected(String address) {
- int state = getSinkState(address);
- return state == STATE_CONNECTED || state == STATE_PLAYING;
- }
-
- /** Check if any A2DP sink is connected.
- * @return a List of connected A2DP sinks, or null on error.
- * @hide
- */
- public List<String> listConnectedSinks() {
- try {
- return mService.listConnectedSinks();
- } catch (RemoteException e) {
- Log.w(TAG, "", e);
- return null;
- }
- }
-
- /** Get the state of an A2DP sink
- * @param address Remote BT address.
- * @return State code, or negative on error
- * @hide
- */
- public int getSinkState(String address) {
- try {
- return mService.getSinkState(address);
- } catch (RemoteException e) {
- Log.w(TAG, "", e);
- return BluetoothError.ERROR_IPC;
- }
- }
-
- /**
- * Set priority of a2dp sink.
- * Priority is a non-negative integer. By default paired sinks will have
- * a priority of PRIORITY_AUTO, and unpaired headset PRIORITY_NONE (0).
- * Sinks with priority greater than zero will accept incoming connections
- * (if no sink is currently connected).
- * Priority for unpaired sink must be PRIORITY_NONE.
- * @param address Paired sink
- * @param priority Integer priority, for example PRIORITY_AUTO or
- * PRIORITY_NONE
- * @return Result code, negative indicates an error
- */
- public int setSinkPriority(String address, int priority) {
- try {
- return mService.setSinkPriority(address, priority);
- } catch (RemoteException e) {
- Log.w(TAG, "", e);
- return BluetoothError.ERROR_IPC;
- }
- }
-
- /**
- * Get priority of a2dp sink.
- * @param address Sink
- * @return non-negative priority, or negative error code on error.
- */
- public int getSinkPriority(String address) {
- try {
- return mService.getSinkPriority(address);
- } catch (RemoteException e) {
- Log.w(TAG, "", e);
- return BluetoothError.ERROR_IPC;
- }
- }
-
- /**
- * Check class bits for possible A2DP Sink support.
- * This is a simple heuristic that tries to guess if a device with the
- * given class bits might be a A2DP Sink. It is not accurate for all
- * devices. It tries to err on the side of false positives.
- * @return True if this device might be a A2DP sink
- */
- public static boolean doesClassMatchSink(int btClass) {
- if (BluetoothClass.Service.hasService(btClass, BluetoothClass.Service.RENDER)) {
- return true;
- }
- // By the A2DP spec, sinks must indicate the RENDER service.
- // However we found some that do not (Chordette). So lets also
- // match on some other class bits.
- switch (BluetoothClass.Device.getDevice(btClass)) {
- case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO:
- case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES:
- case BluetoothClass.Device.AUDIO_VIDEO_LOUDSPEAKER:
- case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
- return true;
- default:
- return false;
- }
- }
-
- /** Helper for converting a state to a string.
- * For debug use only - strings are not internationalized.
- * @hide
- */
- public static String stateToString(int state) {
- switch (state) {
- case STATE_DISCONNECTED:
- return "disconnected";
- case STATE_CONNECTING:
- return "connecting";
- case STATE_CONNECTED:
- return "connected";
- case STATE_DISCONNECTING:
- return "disconnecting";
- case STATE_PLAYING:
- return "playing";
- default:
- return "<unknown state " + state + ">";
- }
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothAudioGateway.java b/core/java/android/bluetooth/BluetoothAudioGateway.java
deleted file mode 100644
index f3afd2a..0000000
--- a/core/java/android/bluetooth/BluetoothAudioGateway.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package android.bluetooth;
-
-import java.lang.Thread;
-
-import android.os.Message;
-import android.os.Handler;
-import android.util.Log;
-
-/**
- * Listen's for incoming RFCOMM connection for the headset / handsfree service.
- *
- * This class is planned for deletion, in favor of a generic Rfcomm class.
- *
- * @hide
- */
-public class BluetoothAudioGateway {
- private static final String TAG = "BT Audio Gateway";
- private static final boolean DBG = false;
-
- private int mNativeData;
- static { classInitNative(); }
-
- private BluetoothDevice mBluetooth;
-
- /* in */
- private int mHandsfreeAgRfcommChannel = -1;
- private int mHeadsetAgRfcommChannel = -1;
-
- /* out */
- private String mConnectingHeadsetAddress;
- private int mConnectingHeadsetRfcommChannel; /* -1 when not connected */
- private int mConnectingHeadsetSocketFd;
- private String mConnectingHandsfreeAddress;
- private int mConnectingHandsfreeRfcommChannel; /* -1 when not connected */
- private int mConnectingHandsfreeSocketFd;
- private int mTimeoutRemainingMs; /* in/out */
-
- public static final int DEFAULT_HF_AG_CHANNEL = 10;
- public static final int DEFAULT_HS_AG_CHANNEL = 11;
-
- public BluetoothAudioGateway(BluetoothDevice bluetooth) {
- this(bluetooth, DEFAULT_HF_AG_CHANNEL, DEFAULT_HS_AG_CHANNEL);
- }
-
- public BluetoothAudioGateway(BluetoothDevice bluetooth,
- int handsfreeAgRfcommChannel,
- int headsetAgRfcommChannel) {
- mBluetooth = bluetooth;
- mHandsfreeAgRfcommChannel = handsfreeAgRfcommChannel;
- mHeadsetAgRfcommChannel = headsetAgRfcommChannel;
- initializeNativeDataNative();
- }
-
- private Thread mConnectThead;
- private volatile boolean mInterrupted;
- private static final int SELECT_WAIT_TIMEOUT = 1000;
-
- private Handler mCallback;
-
- public class IncomingConnectionInfo {
- IncomingConnectionInfo(BluetoothDevice bluetooth, String address, int socketFd,
- int rfcommChan) {
- mBluetooth = bluetooth;
- mAddress = address;
- mSocketFd = socketFd;
- mRfcommChan = rfcommChan;
- }
-
- public BluetoothDevice mBluetooth;
- public String mAddress;
- public int mSocketFd;
- public int mRfcommChan;
- }
-
- public static final int MSG_INCOMING_HEADSET_CONNECTION = 100;
- public static final int MSG_INCOMING_HANDSFREE_CONNECTION = 101;
-
- public synchronized boolean start(Handler callback) {
-
- if (mConnectThead == null) {
- mCallback = callback;
- mConnectThead = new Thread(TAG) {
- public void run() {
- if (DBG) log("Connect Thread starting");
- while (!mInterrupted) {
- //Log.i(TAG, "waiting for connect");
- mConnectingHeadsetRfcommChannel = -1;
- mConnectingHandsfreeRfcommChannel = -1;
- if (waitForHandsfreeConnectNative(SELECT_WAIT_TIMEOUT) == false) {
- if (mTimeoutRemainingMs > 0) {
- try {
- Log.i(TAG, "select thread timed out, but " +
- mTimeoutRemainingMs + "ms of waiting remain.");
- Thread.sleep(mTimeoutRemainingMs);
- } catch (InterruptedException e) {
- Log.i(TAG, "select thread was interrupted (2), exiting");
- mInterrupted = true;
- }
- }
- }
- else {
- Log.i(TAG, "connect notification!");
- /* A device connected (most likely just one, but
- it is possible for two separate devices, one
- a headset and one a handsfree, to connect
- simultaneously.
- */
- if (mConnectingHeadsetRfcommChannel >= 0) {
- Log.i(TAG, "Incoming connection from headset " +
- mConnectingHeadsetAddress + " on channel " +
- mConnectingHeadsetRfcommChannel);
- Message msg = Message.obtain(mCallback);
- msg.what = MSG_INCOMING_HEADSET_CONNECTION;
- msg.obj =
- new IncomingConnectionInfo(
- mBluetooth,
- mConnectingHeadsetAddress,
- mConnectingHeadsetSocketFd,
- mConnectingHeadsetRfcommChannel);
- msg.sendToTarget();
- }
- if (mConnectingHandsfreeRfcommChannel >= 0) {
- Log.i(TAG, "Incoming connection from handsfree " +
- mConnectingHandsfreeAddress + " on channel " +
- mConnectingHandsfreeRfcommChannel);
- Message msg = Message.obtain();
- msg.setTarget(mCallback);
- msg.what = MSG_INCOMING_HANDSFREE_CONNECTION;
- msg.obj =
- new IncomingConnectionInfo(
- mBluetooth,
- mConnectingHandsfreeAddress,
- mConnectingHandsfreeSocketFd,
- mConnectingHandsfreeRfcommChannel);
- msg.sendToTarget();
- }
- }
- }
- if (DBG) log("Connect Thread finished");
- }
- };
-
- if (setUpListeningSocketsNative() == false) {
- Log.e(TAG, "Could not set up listening socket, exiting");
- return false;
- }
-
- mInterrupted = false;
- mConnectThead.start();
- }
-
- return true;
- }
-
- public synchronized void stop() {
- if (mConnectThead != null) {
- if (DBG) log("stopping Connect Thread");
- mInterrupted = true;
- try {
- mConnectThead.interrupt();
- if (DBG) log("waiting for thread to terminate");
- mConnectThead.join();
- mConnectThead = null;
- mCallback = null;
- tearDownListeningSocketsNative();
- } catch (InterruptedException e) {
- Log.w(TAG, "Interrupted waiting for Connect Thread to join");
- }
- }
- }
-
- protected void finalize() throws Throwable {
- try {
- cleanupNativeDataNative();
- } finally {
- super.finalize();
- }
- }
-
- private static native void classInitNative();
- private native void initializeNativeDataNative();
- private native void cleanupNativeDataNative();
- private native boolean waitForHandsfreeConnectNative(int timeoutMs);
- private native boolean setUpListeningSocketsNative();
- private native void tearDownListeningSocketsNative();
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java
deleted file mode 100644
index 88ce18b..0000000
--- a/core/java/android/bluetooth/BluetoothClass.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-/**
- * The Android Bluetooth API is not finalized, and *will* change. Use at your
- * own risk.
- *
- * Static helper methods and constants to decode the device class bit vector
- * returned by the Bluetooth API.
- *
- * The Android Bluetooth API returns a 32-bit integer to represent the class.
- * The format of these bits is defined at
- * http://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm
- * (login required). This class provides static helper methods and constants to
- * determine what Service Class(es) and Device Class are encoded in the 32-bit
- * class.
- *
- * Devices typically have zero or more service classes, and exactly one device
- * class. The device class is encoded as a major and minor device class, the
- * minor being a subset of the major.
- *
- * Class is useful to describe a device (for example to show an icon),
- * but does not reliably describe what profiles a device supports. To determine
- * profile support you usually need to perform SDP queries.
- *
- * Each of these helper methods takes the 32-bit integer class as an argument.
- *
- * @hide
- */
-public class BluetoothClass {
- /** Indicates the Bluetooth API could not retrieve the class */
- public static final int ERROR = 0xFF000000;
-
- /** Every Bluetooth device has zero or more service classes */
- public static class Service {
- public static final int BITMASK = 0xFFE000;
-
- public static final int LIMITED_DISCOVERABILITY = 0x002000;
- public static final int POSITIONING = 0x010000;
- public static final int NETWORKING = 0x020000;
- public static final int RENDER = 0x040000;
- public static final int CAPTURE = 0x080000;
- public static final int OBJECT_TRANSFER = 0x100000;
- public static final int AUDIO = 0x200000;
- public static final int TELEPHONY = 0x400000;
- public static final int INFORMATION = 0x800000;
-
- /** Returns true if the given class supports the given Service Class.
- * A bluetooth device can claim to support zero or more service classes.
- * @param btClass The bluetooth class.
- * @param serviceClass The service class constant to test for. For
- * example, Service.AUDIO. Must be one of the
- * Service.FOO constants.
- * @return True if the service class is supported.
- */
- public static boolean hasService(int btClass, int serviceClass) {
- if (btClass == ERROR) {
- return false;
- }
- return ((btClass & Service.BITMASK & serviceClass) != 0);
- }
- }
-
- /** Every Bluetooth device has exactly one device class, comprimised of
- * major and minor components. We have not included the minor classes for
- * major classes: NETWORKING, PERIPHERAL and IMAGING yet because they work
- * a little differently. */
- public static class Device {
- public static final int BITMASK = 0x1FFC;
-
- public static class Major {
- public static final int BITMASK = 0x1F00;
-
- public static final int MISC = 0x0000;
- public static final int COMPUTER = 0x0100;
- public static final int PHONE = 0x0200;
- public static final int NETWORKING = 0x0300;
- public static final int AUDIO_VIDEO = 0x0400;
- public static final int PERIPHERAL = 0x0500;
- public static final int IMAGING = 0x0600;
- public static final int WEARABLE = 0x0700;
- public static final int TOY = 0x0800;
- public static final int HEALTH = 0x0900;
- public static final int UNCATEGORIZED = 0x1F00;
-
- /** Returns the Major Device Class component of a bluetooth class.
- * Values returned from this function can be compared with the constants
- * Device.Major.FOO. A bluetooth device can only be associated
- * with one major class.
- */
- public static int getDeviceMajor(int btClass) {
- if (btClass == ERROR) {
- return ERROR;
- }
- return (btClass & Device.Major.BITMASK);
- }
- }
-
- // Devices in the COMPUTER major class
- public static final int COMPUTER_UNCATEGORIZED = 0x0100;
- public static final int COMPUTER_DESKTOP = 0x0104;
- public static final int COMPUTER_SERVER = 0x0108;
- public static final int COMPUTER_LAPTOP = 0x010C;
- public static final int COMPUTER_HANDHELD_PC_PDA = 0x0110;
- public static final int COMPUTER_PALM_SIZE_PC_PDA = 0x0114;
- public static final int COMPUTER_WEARABLE = 0x0118;
-
- // Devices in the PHONE major class
- public static final int PHONE_UNCATEGORIZED = 0x0200;
- public static final int PHONE_CELLULAR = 0x0204;
- public static final int PHONE_CORDLESS = 0x0208;
- public static final int PHONE_SMART = 0x020C;
- public static final int PHONE_MODEM_OR_GATEWAY = 0x0210;
- public static final int PHONE_ISDN = 0x0214;
-
- // Minor classes for the AUDIO_VIDEO major class
- public static final int AUDIO_VIDEO_UNCATEGORIZED = 0x0400;
- public static final int AUDIO_VIDEO_WEARABLE_HEADSET = 0x0404;
- public static final int AUDIO_VIDEO_HANDSFREE = 0x0408;
- //public static final int AUDIO_VIDEO_RESERVED = 0x040C;
- public static final int AUDIO_VIDEO_MICROPHONE = 0x0410;
- public static final int AUDIO_VIDEO_LOUDSPEAKER = 0x0414;
- public static final int AUDIO_VIDEO_HEADPHONES = 0x0418;
- public static final int AUDIO_VIDEO_PORTABLE_AUDIO = 0x041C;
- public static final int AUDIO_VIDEO_CAR_AUDIO = 0x0420;
- public static final int AUDIO_VIDEO_SET_TOP_BOX = 0x0424;
- public static final int AUDIO_VIDEO_HIFI_AUDIO = 0x0428;
- public static final int AUDIO_VIDEO_VCR = 0x042C;
- public static final int AUDIO_VIDEO_VIDEO_CAMERA = 0x0430;
- public static final int AUDIO_VIDEO_CAMCORDER = 0x0434;
- public static final int AUDIO_VIDEO_VIDEO_MONITOR = 0x0438;
- public static final int AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER = 0x043C;
- public static final int AUDIO_VIDEO_VIDEO_CONFERENCING = 0x0440;
- //public static final int AUDIO_VIDEO_RESERVED = 0x0444;
- public static final int AUDIO_VIDEO_VIDEO_GAMING_TOY = 0x0448;
-
- // Devices in the WEARABLE major class
- public static final int WEARABLE_UNCATEGORIZED = 0x0700;
- public static final int WEARABLE_WRIST_WATCH = 0x0704;
- public static final int WEARABLE_PAGER = 0x0708;
- public static final int WEARABLE_JACKET = 0x070C;
- public static final int WEARABLE_HELMET = 0x0710;
- public static final int WEARABLE_GLASSES = 0x0714;
-
- // Devices in the TOY major class
- public static final int TOY_UNCATEGORIZED = 0x0800;
- public static final int TOY_ROBOT = 0x0804;
- public static final int TOY_VEHICLE = 0x0808;
- public static final int TOY_DOLL_ACTION_FIGURE = 0x080C;
- public static final int TOY_CONTROLLER = 0x0810;
- public static final int TOY_GAME = 0x0814;
-
- // Devices in the HEALTH major class
- public static final int HEALTH_UNCATEGORIZED = 0x0900;
- public static final int HEALTH_BLOOD_PRESSURE = 0x0904;
- public static final int HEALTH_THERMOMETER = 0x0908;
- public static final int HEALTH_WEIGHING = 0x090C;
- public static final int HEALTH_GLUCOSE = 0x0910;
- public static final int HEALTH_PULSE_OXIMETER = 0x0914;
- public static final int HEALTH_PULSE_RATE = 0x0918;
- public static final int HEALTH_DATA_DISPLAY = 0x091C;
-
- /** Returns the Device Class component of a bluetooth class. This includes
- * both the major and minor device components. Values returned from this
- * function can be compared with the constants Device.FOO. A bluetooth
- * device can only be associated with one device class.
- */
- public static int getDevice(int btClass) {
- if (btClass == ERROR) {
- return ERROR;
- }
- return (btClass & Device.BITMASK);
- }
- }
-}
-
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
deleted file mode 100644
index 56b231f..0000000
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ /dev/null
@@ -1,578 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.UnsupportedEncodingException;
-
-/**
- * The Android Bluetooth API is not finalized, and *will* change. Use at your
- * own risk.
- *
- * Manages the local Bluetooth device. Scan for devices, create bondings,
- * power up and down the adapter.
- *
- * @hide
- */
-public class BluetoothDevice {
- /** Inquiry scan and page scan are both off.
- * Device is neither discoverable nor connectable */
- public static final int SCAN_MODE_NONE = 0;
- /** Page scan is on, inquiry scan is off.
- * Device is connectable, but not discoverable */
- public static final int SCAN_MODE_CONNECTABLE = 1;
- /** Page scan and inquiry scan are on.
- * Device is connectable and discoverable */
- public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 3;
-
- public static final int RESULT_FAILURE = -1;
- public static final int RESULT_SUCCESS = 0;
-
- /** We do not have a link key for the remote device, and are therefore not
- * bonded */
- public static final int BOND_NOT_BONDED = 0;
- /** We have a link key for the remote device, and are probably bonded. */
- public static final int BOND_BONDED = 1;
- /** We are currently attempting bonding */
- public static final int BOND_BONDING = 2;
-
- //TODO: Unify these result codes in BluetoothResult or BluetoothError
- /** A bond attempt failed because pins did not match, or remote device did
- * not respond to pin request in time */
- public static final int UNBOND_REASON_AUTH_FAILED = 1;
- /** A bond attempt failed because the other side explicilty rejected
- * bonding */
- public static final int UNBOND_REASON_AUTH_REJECTED = 2;
- /** A bond attempt failed because we canceled the bonding process */
- public static final int UNBOND_REASON_AUTH_CANCELED = 3;
- /** A bond attempt failed because we could not contact the remote device */
- public static final int UNBOND_REASON_REMOTE_DEVICE_DOWN = 4;
- /** An existing bond was explicitly revoked */
- public static final int UNBOND_REASON_REMOVED = 5;
-
- private static final String TAG = "BluetoothDevice";
-
- private final IBluetoothDevice mService;
- /**
- * @hide - hide this because it takes a parameter of type
- * IBluetoothDevice, which is a System private class.
- * Also note that Context.getSystemService is a factory that
- * returns a BlueToothDevice. That is the right way to get
- * a BluetoothDevice.
- */
- public BluetoothDevice(IBluetoothDevice service) {
- mService = service;
- }
-
- /**
- * Get the current status of Bluetooth hardware.
- *
- * @return true if Bluetooth enabled, false otherwise.
- */
- public boolean isEnabled() {
- try {
- return mService.isEnabled();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- /**
- * Enable the Bluetooth device.
- * Turn on the underlying hardware.
- * This is an asynchronous call, BluetoothIntent.ENABLED_ACTION will be
- * sent if and when the device is successfully enabled.
- * @return false if we cannot enable the Bluetooth device. True does not
- * imply the device was enabled, it only implies that so far there were no
- * problems.
- */
- public boolean enable() {
- return enable(null);
- }
-
- /**
- * Enable the Bluetooth device.
- * Turns on the underlying hardware.
- * This is an asynchronous call. onEnableResult() of your callback will be
- * called when the call is complete, with either RESULT_SUCCESS or
- * RESULT_FAILURE.
- *
- * Your callback will be called from a binder thread, not the main thread.
- *
- * In addition to the callback, BluetoothIntent.ENABLED_ACTION will be
- * broadcast if the device is successfully enabled.
- *
- * @param callback Your callback, null is ok.
- * @return true if your callback was successfully registered, or false if
- * there was an error, implying your callback will never be called.
- */
- public boolean enable(IBluetoothDeviceCallback callback) {
- try {
- return mService.enable(callback);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- /**
- * Disable the Bluetooth device.
- * This turns off the underlying hardware.
- *
- * @return true if successful, false otherwise.
- */
- public boolean disable() {
- try {
- return mService.disable();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- public String getAddress() {
- try {
- return mService.getAddress();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
-
- /**
- * Get the friendly Bluetooth name of this device.
- *
- * This name is visible to remote Bluetooth devices. Currently it is only
- * possible to retrieve the Bluetooth name when Bluetooth is enabled.
- *
- * @return the Bluetooth name, or null if there was a problem.
- */
- public String getName() {
- try {
- return mService.getName();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
-
- /**
- * Set the friendly Bluetooth name of this device.
- *
- * This name is visible to remote Bluetooth devices. The Bluetooth Service
- * is responsible for persisting this name.
- *
- * @param name the name to set
- * @return true, if the name was successfully set. False otherwise.
- */
- public boolean setName(String name) {
- try {
- return mService.setName(name);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- public String getVersion() {
- try {
- return mService.getVersion();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
- public String getRevision() {
- try {
- return mService.getRevision();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
- public String getManufacturer() {
- try {
- return mService.getManufacturer();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
- public String getCompany() {
- try {
- return mService.getCompany();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
-
- /**
- * Get the current scan mode.
- * Used to determine if the local device is connectable and/or discoverable
- * @return Scan mode, one of SCAN_MODE_* or an error code
- */
- public int getScanMode() {
- try {
- return mService.getScanMode();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return BluetoothError.ERROR_IPC;
- }
-
- /**
- * Set the current scan mode.
- * Used to make the local device connectable and/or discoverable
- * @param scanMode One of SCAN_MODE_*
- */
- public void setScanMode(int scanMode) {
- try {
- mService.setScanMode(scanMode);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- }
-
- public int getDiscoverableTimeout() {
- try {
- return mService.getDiscoverableTimeout();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return -1;
- }
- public void setDiscoverableTimeout(int timeout) {
- try {
- mService.setDiscoverableTimeout(timeout);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- }
-
- public boolean startDiscovery() {
- return startDiscovery(true);
- }
- public boolean startDiscovery(boolean resolveNames) {
- try {
- return mService.startDiscovery(resolveNames);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- public void cancelDiscovery() {
- try {
- mService.cancelDiscovery();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- }
-
- public boolean isDiscovering() {
- try {
- return mService.isDiscovering();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- public boolean startPeriodicDiscovery() {
- try {
- return mService.startPeriodicDiscovery();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
- public boolean stopPeriodicDiscovery() {
- try {
- return mService.stopPeriodicDiscovery();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
- public boolean isPeriodicDiscovery() {
- try {
- return mService.isPeriodicDiscovery();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- public String[] listRemoteDevices() {
- try {
- return mService.listRemoteDevices();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
-
- /**
- * List remote devices that have a low level (ACL) connection.
- *
- * RFCOMM, SDP and L2CAP are all built on ACL connections. Devices can have
- * an ACL connection even when not paired - this is common for SDP queries
- * or for in-progress pairing requests.
- *
- * In most cases you probably want to test if a higher level protocol is
- * connected, rather than testing ACL connections.
- *
- * @return bluetooth hardware addresses of remote devices with a current
- * ACL connection. Array size is 0 if no devices have a
- * connection. Null on error.
- */
- public String[] listAclConnections() {
- try {
- return mService.listAclConnections();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
-
- /**
- * Check if a specified remote device has a low level (ACL) connection.
- *
- * RFCOMM, SDP and L2CAP are all built on ACL connections. Devices can have
- * an ACL connection even when not paired - this is common for SDP queries
- * or for in-progress pairing requests.
- *
- * In most cases you probably want to test if a higher level protocol is
- * connected, rather than testing ACL connections.
- *
- * @param address the Bluetooth hardware address you want to check.
- * @return true if there is an ACL connection, false otherwise and on
- * error.
- */
- public boolean isAclConnected(String address) {
- try {
- return mService.isAclConnected(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- /**
- * Perform a low level (ACL) disconnection of a remote device.
- *
- * This forcably disconnects the ACL layer connection to a remote device,
- * which will cause all RFCOMM, SDP and L2CAP connections to this remote
- * device to close.
- *
- * @param address the Bluetooth hardware address you want to disconnect.
- * @return true if the device was disconnected, false otherwise and on
- * error.
- */
- public boolean disconnectRemoteDeviceAcl(String address) {
- try {
- return mService.disconnectRemoteDeviceAcl(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- /**
- * Create a bonding with a remote bluetooth device.
- *
- * This is an asynchronous call. The result of this bonding attempt can be
- * observed through BluetoothIntent.BOND_STATE_CHANGED_ACTION intents.
- *
- * @param address the remote device Bluetooth address.
- * @return false If there was an immediate problem creating the bonding,
- * true otherwise.
- */
- public boolean createBond(String address) {
- try {
- return mService.createBond(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- /**
- * Cancel an in-progress bonding request started with createBond.
- */
- public boolean cancelBondProcess(String address) {
- try {
- return mService.cancelBondProcess(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- /**
- * Remove an already exisiting bonding (delete the link key).
- */
- public boolean removeBond(String address) {
- try {
- return mService.removeBond(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- /**
- * List remote devices that are bonded (paired) to the local device.
- *
- * Bonding (pairing) is the process by which the user enters a pin code for
- * the device, which generates a shared link key, allowing for
- * authentication and encryption of future connections. In Android we
- * require bonding before RFCOMM or SCO connections can be made to a remote
- * device.
- *
- * This function lists which remote devices we have a link key for. It does
- * not cause any RF transmission, and does not check if the remote device
- * still has it's link key with us. If the other side no longer has its
- * link key then the RFCOMM or SCO connection attempt will result in an
- * error.
- *
- * This function does not check if the remote device is in range.
- *
- * Remote devices that have an in-progress bonding attempt are not
- * returned.
- *
- * @return bluetooth hardware addresses of remote devices that are
- * bonded. Array size is 0 if no devices are bonded. Null on error.
- */
- public String[] listBonds() {
- try {
- return mService.listBonds();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
-
- /**
- * Get the bonding state of a remote device.
- *
- * Result is one of:
- * BluetoothError.*
- * BOND_*
- *
- * @param address Bluetooth hardware address of the remote device to check.
- * @return Result code
- */
- public int getBondState(String address) {
- try {
- return mService.getBondState(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return BluetoothError.ERROR_IPC;
- }
-
- public String getRemoteName(String address) {
- try {
- return mService.getRemoteName(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
-
- public String getRemoteVersion(String address) {
- try {
- return mService.getRemoteVersion(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
- public String getRemoteRevision(String address) {
- try {
- return mService.getRemoteRevision(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
- public String getRemoteManufacturer(String address) {
- try {
- return mService.getRemoteManufacturer(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
- public String getRemoteCompany(String address) {
- try {
- return mService.getRemoteCompany(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
-
- /**
- * Returns the RFCOMM channel associated with the 16-byte UUID on
- * the remote Bluetooth address.
- *
- * Performs a SDP ServiceSearchAttributeRequest transaction. The provided
- * uuid is verified in the returned record. If there was a problem, or the
- * specified uuid does not exist, -1 is returned.
- */
- public boolean getRemoteServiceChannel(String address, short uuid16,
- IBluetoothDeviceCallback callback) {
- try {
- return mService.getRemoteServiceChannel(address, uuid16, callback);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- /**
- * Get the major, minor and servics classes of a remote device.
- * These classes are encoded as a 32-bit integer. See BluetoothClass.
- * @param address remote device
- * @return 32-bit class suitable for use with BluetoothClass.
- */
- public int getRemoteClass(String address) {
- try {
- return mService.getRemoteClass(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return BluetoothClass.ERROR;
- }
-
- public byte[] getRemoteFeatures(String address) {
- try {
- return mService.getRemoteFeatures(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
- public String lastSeen(String address) {
- try {
- return mService.lastSeen(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
- public String lastUsed(String address) {
- try {
- return mService.lastUsed(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
-
- public boolean setPin(String address, byte[] pin) {
- try {
- return mService.setPin(address, pin);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
- public boolean cancelPin(String address) {
- try {
- return mService.cancelPin(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- /**
- * Check that a pin is valid and convert to byte array.
- *
- * Bluetooth pin's are 1 to 16 bytes of UTF8 characters.
- * @param pin pin as java String
- * @return the pin code as a UTF8 byte array, or null if it is an invalid
- * Bluetooth pin.
- */
- public static byte[] convertPinToBytes(String pin) {
- if (pin == null) {
- return null;
- }
- byte[] pinBytes;
- try {
- pinBytes = pin.getBytes("UTF8");
- } catch (UnsupportedEncodingException uee) {
- Log.e(TAG, "UTF8 not supported?!?"); // this should not happen
- return null;
- }
- if (pinBytes.length <= 0 || pinBytes.length > 16) {
- return null;
- }
- return pinBytes;
- }
-
-
- private static final int ADDRESS_LENGTH = 17;
- /** Sanity check a bluetooth address, such as "00:43:A8:23:10:F0" */
- public static boolean checkBluetoothAddress(String address) {
- if (address == null || address.length() != ADDRESS_LENGTH) {
- return false;
- }
- for (int i = 0; i < ADDRESS_LENGTH; i++) {
- char c = address.charAt(i);
- switch (i % 3) {
- case 0:
- case 1:
- if (Character.digit(c, 16) != -1) {
- break; // hex character, OK
- }
- return false;
- case 2:
- if (c == ':') {
- break; // OK
- }
- return false;
- }
- }
- return true;
- }
-}
diff --git a/core/java/android/bluetooth/BluetoothError.java b/core/java/android/bluetooth/BluetoothError.java
deleted file mode 100644
index 2554bea..0000000
--- a/core/java/android/bluetooth/BluetoothError.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-/**
- * Bluetooth API error codes.
- *
- * Errors are always negative.
- *
- * @hide
- */
-public class BluetoothError {
- /** No error */
- public static final int SUCCESS = 0;
-
- /** Generic error */
- public static final int ERROR = -1000;
-
- /** Bluetooth currently disabled */
- public static final int ERROR_DISABLED = -1001;
-
- /** IPC is not ready, for example service is not yet bound */
- public static final int ERROR_IPC_NOT_READY = -1011;
-
- /** Some other IPC error, for example a RemoteException */
- public static final int ERROR_IPC = -1012;
-
-}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
deleted file mode 100644
index 34196bf..0000000
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.util.Log;
-
-/**
- * The Android Bluetooth API is not finalized, and *will* change. Use at your
- * own risk.
- *
- * Public API for controlling the Bluetooth Headset Service. This includes both
- * Bluetooth Headset and Handsfree (v1.5) profiles. The Headset service will
- * attempt a handsfree connection first, and fall back to headset.
- *
- * BluetoothHeadset is a proxy object for controlling the Bluetooth Headset
- * Service via IPC.
- *
- * Creating a BluetoothHeadset object will create a binding with the
- * BluetoothHeadset service. Users of this object should call close() when they
- * are finished with the BluetoothHeadset, so that this proxy object can unbind
- * from the service.
- *
- * This BluetoothHeadset object is not immediately bound to the
- * BluetoothHeadset service. Use the ServiceListener interface to obtain a
- * notification when it is bound, this is especially important if you wish to
- * immediately call methods on BluetootHeadset after construction.
- *
- * Android only supports one connected Bluetooth Headset at a time.
- *
- * @hide
- */
-public class BluetoothHeadset {
-
- private static final String TAG = "BluetoothHeadset";
- private static final boolean DBG = false;
-
- private IBluetoothHeadset mService;
- private final Context mContext;
- private final ServiceListener mServiceListener;
-
- /** There was an error trying to obtain the state */
- public static final int STATE_ERROR = -1;
- /** No headset currently connected */
- public static final int STATE_DISCONNECTED = 0;
- /** Connection attempt in progress */
- public static final int STATE_CONNECTING = 1;
- /** A headset is currently connected */
- public static final int STATE_CONNECTED = 2;
-
- public static final int RESULT_FAILURE = 0;
- public static final int RESULT_SUCCESS = 1;
- /** Connection canceled before completetion. */
- public static final int RESULT_CANCELED = 2;
-
- /** Default priority for headsets that should be auto-connected */
- public static final int PRIORITY_AUTO = 100;
- /** Default priority for headsets that should not be auto-connected */
- public static final int PRIORITY_OFF = 0;
-
- /**
- * An interface for notifying BluetoothHeadset IPC clients when they have
- * been connected to the BluetoothHeadset service.
- */
- public interface ServiceListener {
- /**
- * Called to notify the client when this proxy object has been
- * connected to the BluetoothHeadset service. Clients must wait for
- * this callback before making IPC calls on the BluetoothHeadset
- * service.
- */
- public void onServiceConnected();
-
- /**
- * Called to notify the client that this proxy object has been
- * disconnected from the BluetoothHeadset service. Clients must not
- * make IPC calls on the BluetoothHeadset service after this callback.
- * This callback will currently only occur if the application hosting
- * the BluetoothHeadset service, but may be called more often in future.
- */
- public void onServiceDisconnected();
- }
-
- /**
- * Create a BluetoothHeadset proxy object.
- */
- public BluetoothHeadset(Context context, ServiceListener l) {
- mContext = context;
- mServiceListener = l;
- if (!context.bindService(new Intent(IBluetoothHeadset.class.getName()), mConnection, 0)) {
- Log.e(TAG, "Could not bind to Bluetooth Headset Service");
- }
- }
-
- protected void finalize() throws Throwable {
- try {
- close();
- } finally {
- super.finalize();
- }
- }
-
- /**
- * Close the connection to the backing service.
- * Other public functions of BluetoothHeadset will return default error
- * results once close() has been called. Multiple invocations of close()
- * are ok.
- */
- public synchronized void close() {
- if (mConnection != null) {
- mContext.unbindService(mConnection);
- mConnection = null;
- }
- }
-
- /**
- * Get the current state of the Bluetooth Headset service.
- * @return One of the STATE_ return codes, or STATE_ERROR if this proxy
- * object is currently not connected to the Headset service.
- */
- public int getState() {
- if (mService != null) {
- try {
- return mService.getState();
- } catch (RemoteException e) {Log.e(TAG, e.toString());}
- } else {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- }
- return BluetoothHeadset.STATE_ERROR;
- }
-
- /**
- * Get the Bluetooth address of the current headset.
- * @return The Bluetooth address, or null if not in connected or connecting
- * state, or if this proxy object is not connected to the Headset
- * service.
- */
- public String getHeadsetAddress() {
- if (mService != null) {
- try {
- return mService.getHeadsetAddress();
- } catch (RemoteException e) {Log.e(TAG, e.toString());}
- } else {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- }
- return null;
- }
-
- /**
- * Request to initiate a connection to a headset.
- * This call does not block. Fails if a headset is already connecting
- * or connected.
- * Initiates auto-connection if address is null. Tries to connect to all
- * devices with priority greater than PRIORITY_AUTO in descending order.
- * @param address The Bluetooth Address to connect to, or null to
- * auto-connect to the last connected headset.
- * @return False if there was a problem initiating the connection
- * procedure, and no further HEADSET_STATE_CHANGED intents
- * will be expected.
- */
- public boolean connectHeadset(String address) {
- if (mService != null) {
- try {
- if (mService.connectHeadset(address)) {
- return true;
- }
- } catch (RemoteException e) {Log.e(TAG, e.toString());}
- } else {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- }
- return false;
- }
-
- /**
- * Returns true if the specified headset is connected (does not include
- * connecting). Returns false if not connected, or if this proxy object
- * if not currently connected to the headset service.
- */
- public boolean isConnected(String address) {
- if (mService != null) {
- try {
- return mService.isConnected(address);
- } catch (RemoteException e) {Log.e(TAG, e.toString());}
- } else {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- }
- return false;
- }
-
- /**
- * Disconnects the current headset. Currently this call blocks, it may soon
- * be made asynchornous. Returns false if this proxy object is
- * not currently connected to the Headset service.
- */
- public boolean disconnectHeadset() {
- if (mService != null) {
- try {
- mService.disconnectHeadset();
- return true;
- } catch (RemoteException e) {Log.e(TAG, e.toString());}
- } else {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- }
- return false;
- }
-
- /**
- * Start BT Voice Recognition mode, and set up Bluetooth audio path.
- * Returns false if there is no headset connected, or if the
- * connected headset does not support voice recognition, or on
- * error.
- */
- public boolean startVoiceRecognition() {
- if (mService != null) {
- try {
- return mService.startVoiceRecognition();
- } catch (RemoteException e) {Log.e(TAG, e.toString());}
- } else {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- }
- return false;
- }
-
- /**
- * Stop BT Voice Recognition mode, and shut down Bluetooth audio path.
- * Returns false if there is no headset connected, or the connected
- * headset is not in voice recognition mode, or on error.
- */
- public boolean stopVoiceRecognition() {
- if (mService != null) {
- try {
- return mService.stopVoiceRecognition();
- } catch (RemoteException e) {Log.e(TAG, e.toString());}
- } else {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- }
- return false;
- }
-
- /**
- * Set priority of headset.
- * Priority is a non-negative integer. By default paired headsets will have
- * a priority of PRIORITY_AUTO, and unpaired headset PRIORITY_NONE (0).
- * Headsets with priority greater than zero will be auto-connected, and
- * incoming connections will be accepted (if no other headset is
- * connected).
- * Auto-connection occurs at the following events: boot, incoming phone
- * call, outgoing phone call.
- * Headsets with priority equal to zero, or that are unpaired, are not
- * auto-connected.
- * Incoming connections are ignored regardless of priority if there is
- * already a headset connected.
- * @param address Paired headset
- * @param priority Integer priority, for example PRIORITY_AUTO or
- * PRIORITY_NONE
- * @return True if successful, false if there was some error.
- */
- public boolean setPriority(String address, int priority) {
- if (mService != null) {
- try {
- return mService.setPriority(address, priority);
- } catch (RemoteException e) {Log.e(TAG, e.toString());}
- } else {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- }
- return false;
- }
-
- /**
- * Get priority of headset.
- * @param address Headset
- * @return non-negative priority, or negative error code on error.
- */
- public int getPriority(String address) {
- if (mService != null) {
- try {
- return mService.getPriority(address);
- } catch (RemoteException e) {Log.e(TAG, e.toString());}
- } else {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
- }
- return -1;
- }
-
- /**
- * Check class bits for possible HSP or HFP support.
- * This is a simple heuristic that tries to guess if a device with the
- * given class bits might support HSP or HFP. It is not accurate for all
- * devices. It tries to err on the side of false positives.
- * @return True if this device might support HSP or HFP.
- */
- public static boolean doesClassMatch(int btClass) {
- // The render service class is required by the spec for HFP, so is a
- // pretty good signal
- if (BluetoothClass.Service.hasService(btClass, BluetoothClass.Service.RENDER)) {
- return true;
- }
- // Just in case they forgot the render service class
- switch (BluetoothClass.Device.getDevice(btClass)) {
- case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
- case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
- case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
- return true;
- default:
- return false;
- }
- }
-
- private ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- mService = IBluetoothHeadset.Stub.asInterface(service);
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected();
- }
- }
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected();
- }
- }
- };
-}
diff --git a/core/java/android/bluetooth/BluetoothIntent.java b/core/java/android/bluetooth/BluetoothIntent.java
deleted file mode 100644
index b66b06e..0000000
--- a/core/java/android/bluetooth/BluetoothIntent.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-
-/**
- * The Android Bluetooth API is not finalized, and *will* change. Use at your
- * own risk.
- *
- * Manages the local Bluetooth device. Scan for devices, create bondings,
- * power up and down the adapter.
- *
- * @hide
- */
-public interface BluetoothIntent {
- public static final String SCAN_MODE =
- "android.bluetooth.intent.SCAN_MODE";
- public static final String ADDRESS =
- "android.bluetooth.intent.ADDRESS";
- public static final String NAME =
- "android.bluetooth.intent.NAME";
- public static final String ALIAS =
- "android.bluetooth.intent.ALIAS";
- public static final String RSSI =
- "android.bluetooth.intent.RSSI";
- public static final String CLASS =
- "android.bluetooth.intent.CLASS";
- public static final String HEADSET_STATE =
- "android.bluetooth.intent.HEADSET_STATE";
- public static final String HEADSET_PREVIOUS_STATE =
- "android.bluetooth.intent.HEADSET_PREVIOUS_STATE";
- public static final String BOND_STATE =
- "android.bluetooth.intent.BOND_STATE";
- public static final String BOND_PREVIOUS_STATE =
- "android.bluetooth.intent.BOND_PREVIOUS_STATE";
- public static final String REASON =
- "android.bluetooth.intent.REASON";
-
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ENABLED_ACTION =
- "android.bluetooth.intent.action.ENABLED";
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String DISABLED_ACTION =
- "android.bluetooth.intent.action.DISABLED";
-
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String NAME_CHANGED_ACTION =
- "android.bluetooth.intent.action.NAME_CHANGED";
-
- /**
- * Broadcast when the scan mode changes. Always contains an int extra
- * named SCAN_MODE that contains the new scan mode.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String SCAN_MODE_CHANGED_ACTION =
- "android.bluetooth.intent.action.SCAN_MODE_CHANGED";
-
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String DISCOVERY_STARTED_ACTION =
- "android.bluetooth.intent.action.DISCOVERY_STARTED";
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String DISCOVERY_COMPLETED_ACTION =
- "android.bluetooth.intent.action.DISCOVERY_COMPLETED";
-
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String PAIRING_REQUEST_ACTION =
- "android.bluetooth.intent.action.PAIRING_REQUEST";
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String PAIRING_CANCEL_ACTION =
- "android.bluetooth.intent.action.PAIRING_CANCEL";
-
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String REMOTE_DEVICE_FOUND_ACTION =
- "android.bluetooth.intent.action.REMOTE_DEVICE_FOUND";
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String REMOTE_DEVICE_DISAPPEARED_ACTION =
- "android.bluetooth.intent.action.REMOTE_DEVICE_DISAPPEARED";
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String REMOTE_DEVICE_CLASS_UPDATED_ACTION =
- "android.bluetooth.intent.action.REMOTE_DEVICE_DISAPPEARED";
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String REMOTE_DEVICE_CONNECTED_ACTION =
- "android.bluetooth.intent.action.REMOTE_DEVICE_CONNECTED";
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String REMOTE_DEVICE_DISCONNECT_REQUESTED_ACTION =
- "android.bluetooth.intent.action.REMOTE_DEVICE_DISCONNECT_REQUESTED";
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String REMOTE_DEVICE_DISCONNECTED_ACTION =
- "android.bluetooth.intent.action.REMOTE_DEVICE_DISCONNECTED";
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String REMOTE_NAME_UPDATED_ACTION =
- "android.bluetooth.intent.action.REMOTE_NAME_UPDATED";
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String REMOTE_NAME_FAILED_ACTION =
- "android.bluetooth.intent.action.REMOTE_NAME_FAILED";
-
- /**
- * Broadcast when the bond state of a remote device changes.
- * Has string extra ADDRESS and int extras BOND_STATE and
- * BOND_PREVIOUS_STATE.
- * If BOND_STATE is BluetoothDevice.BOND_NOT_BONDED then will
- * also have an int extra REASON with a value of:
- * BluetoothDevice.BOND_RESULT_*
- * */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String BOND_STATE_CHANGED_ACTION =
- "android.bluetooth.intent.action.BOND_STATE_CHANGED_ACTION";
-
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String HEADSET_STATE_CHANGED_ACTION =
- "android.bluetooth.intent.action.HEADSET_STATE_CHANGED";
-}
diff --git a/core/java/android/bluetooth/Database.java b/core/java/android/bluetooth/Database.java
deleted file mode 100644
index fef641a..0000000
--- a/core/java/android/bluetooth/Database.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.bluetooth.RfcommSocket;
-
-import android.util.Log;
-
-import java.io.*;
-import java.util.*;
-
-/**
- * The Android Bluetooth API is not finalized, and *will* change. Use at your
- * own risk.
- *
- * A low-level API to the Service Discovery Protocol (SDP) Database.
- *
- * Allows service records to be added to the local SDP database. Once added,
- * these services will be advertised to remote devices when they make SDP
- * queries on this device.
- *
- * Currently this API is a thin wrapper to the bluez SDP Database API. See:
- * http://wiki.bluez.org/wiki/Database
- * http://wiki.bluez.org/wiki/HOWTO/ManagingServiceRecords
- * @hide
- */
-public final class Database {
- private static Database mInstance;
-
- private static final String sLogName = "android.bluetooth.Database";
-
- /**
- * Class load time initialization
- */
- static {
- classInitNative();
- }
- private native static void classInitNative();
-
- /**
- * Private to enforce singleton property
- */
- private Database() {
- initializeNativeDataNative();
- }
- private native void initializeNativeDataNative();
-
- protected void finalize() throws Throwable {
- try {
- cleanupNativeDataNative();
- } finally {
- super.finalize();
- }
- }
- private native void cleanupNativeDataNative();
-
- /**
- * Singelton accessor
- * @return The singleton instance of Database
- */
- public static synchronized Database getInstance() {
- if (mInstance == null) {
- mInstance = new Database();
- }
- return mInstance;
- }
-
- /**
- * Advertise a service with an RfcommSocket.
- *
- * This adds the service the SDP Database with the following attributes
- * set: Service Name, Protocol Descriptor List, Service Class ID List
- * TODO: Construct a byte[] record directly, rather than via XML.
- * @param socket The rfcomm socket to advertise (by channel).
- * @param serviceName A short name for this service
- * @param uuid
- * Unique identifier for this service, by which clients
- * can search for your service
- * @return Handle to the new service record
- */
- public int advertiseRfcommService(RfcommSocket socket,
- String serviceName,
- UUID uuid) throws IOException {
- String xmlRecord =
- "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
- "<record>\n" +
- " <attribute id=\"0x0001\">\n" + // ServiceClassIDList
- " <sequence>\n" +
- " <uuid value=\""
- + uuid.toString() + // UUID for this service
- "\"/>\n" +
- " </sequence>\n" +
- " </attribute>\n" +
- " <attribute id=\"0x0004\">\n" + // ProtocolDescriptorList
- " <sequence>\n" +
- " <sequence>\n" +
- " <uuid value=\"0x0100\"/>\n" + // L2CAP
- " </sequence>\n" +
- " <sequence>\n" +
- " <uuid value=\"0x0003\"/>\n" + // RFCOMM
- " <uint8 value=\"" +
- socket.getPort() + // RFCOMM port
- "\" name=\"channel\"/>\n" +
- " </sequence>\n" +
- " </sequence>\n" +
- " </attribute>\n" +
- " <attribute id=\"0x0100\">\n" + // ServiceName
- " <text value=\"" + serviceName + "\"/>\n" +
- " </attribute>\n" +
- "</record>\n";
- Log.i(sLogName, xmlRecord);
- return addServiceRecordFromXml(xmlRecord);
- }
-
-
- /**
- * Add a new service record.
- * @param record The byte[] record
- * @return A handle to the new record
- */
- public synchronized int addServiceRecord(byte[] record) throws IOException {
- int handle = addServiceRecordNative(record);
- Log.i(sLogName, "Added SDP record: " + Integer.toHexString(handle));
- return handle;
- }
- private native int addServiceRecordNative(byte[] record)
- throws IOException;
-
- /**
- * Add a new service record, using XML.
- * @param record The record as an XML string
- * @return A handle to the new record
- */
- public synchronized int addServiceRecordFromXml(String record) throws IOException {
- int handle = addServiceRecordFromXmlNative(record);
- Log.i(sLogName, "Added SDP record: " + Integer.toHexString(handle));
- return handle;
- }
- private native int addServiceRecordFromXmlNative(String record)
- throws IOException;
-
- /**
- * Update an exisiting service record.
- * @param handle Handle to exisiting record
- * @param record The updated byte[] record
- */
- public synchronized void updateServiceRecord(int handle, byte[] record) {
- try {
- updateServiceRecordNative(handle, record);
- } catch (IOException e) {
- Log.e(getClass().toString(), e.getMessage());
- }
- }
- private native void updateServiceRecordNative(int handle, byte[] record)
- throws IOException;
-
- /**
- * Update an exisiting record, using XML.
- * @param handle Handle to exisiting record
- * @param record The record as an XML string.
- */
- public synchronized void updateServiceRecordFromXml(int handle, String record) {
- try {
- updateServiceRecordFromXmlNative(handle, record);
- } catch (IOException e) {
- Log.e(getClass().toString(), e.getMessage());
- }
- }
- private native void updateServiceRecordFromXmlNative(int handle, String record)
- throws IOException;
-
- /**
- * Remove a service record.
- * It is only possible to remove service records that were added by the
- * current connection.
- * @param handle Handle to exisiting record to be removed
- */
- public synchronized void removeServiceRecord(int handle) {
- try {
- removeServiceRecordNative(handle);
- } catch (IOException e) {
- Log.e(getClass().toString(), e.getMessage());
- }
- }
- private native void removeServiceRecordNative(int handle) throws IOException;
-}
diff --git a/core/java/android/bluetooth/HeadsetBase.java b/core/java/android/bluetooth/HeadsetBase.java
deleted file mode 100644
index fd2d2ab..0000000
--- a/core/java/android/bluetooth/HeadsetBase.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.os.Handler;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
-import android.util.Log;
-
-/**
- * The Android Bluetooth API is not finalized, and *will* change. Use at your
- * own risk.
- *
- * The base RFCOMM (service) connection for a headset or handsfree device.
- *
- * In the future this class will be removed.
- *
- * @hide
- */
-public class HeadsetBase {
- private static final String TAG = "Bluetooth HeadsetBase";
- private static final boolean DBG = false;
-
- public static final int RFCOMM_DISCONNECTED = 1;
-
- public static final int DIRECTION_INCOMING = 1;
- public static final int DIRECTION_OUTGOING = 2;
-
- private final BluetoothDevice mBluetooth;
- private final String mAddress;
- private final int mRfcommChannel;
- private int mNativeData;
- private Thread mEventThread;
- private volatile boolean mEventThreadInterrupted;
- private Handler mEventThreadHandler;
- private int mTimeoutRemainingMs;
- private final int mDirection;
- private final long mConnectTimestamp;
-
- protected AtParser mAtParser;
-
- private WakeLock mWakeLock; // held while processing an AT command
-
- private native static void classInitNative();
- static {
- classInitNative();
- }
-
- protected void finalize() throws Throwable {
- try {
- cleanupNativeDataNative();
- releaseWakeLock();
- } finally {
- super.finalize();
- }
- }
-
- private native void cleanupNativeDataNative();
-
- public HeadsetBase(PowerManager pm, BluetoothDevice bluetooth, String address,
- int rfcommChannel) {
- mDirection = DIRECTION_OUTGOING;
- mConnectTimestamp = System.currentTimeMillis();
- mBluetooth = bluetooth;
- mAddress = address;
- mRfcommChannel = rfcommChannel;
- mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "HeadsetBase");
- mWakeLock.setReferenceCounted(false);
- initializeAtParser();
- // Must be called after this.mAddress is set.
- initializeNativeDataNative(-1);
- }
-
- /* Create from an already exisiting rfcomm connection */
- public HeadsetBase(PowerManager pm, BluetoothDevice bluetooth, String address, int socketFd,
- int rfcommChannel, Handler handler) {
- mDirection = DIRECTION_INCOMING;
- mConnectTimestamp = System.currentTimeMillis();
- mBluetooth = bluetooth;
- mAddress = address;
- mRfcommChannel = rfcommChannel;
- mEventThreadHandler = handler;
- mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "HeadsetBase");
- mWakeLock.setReferenceCounted(false);
- initializeAtParser();
- // Must be called after this.mAddress is set.
- initializeNativeDataNative(socketFd);
- }
-
- private native void initializeNativeDataNative(int socketFd);
-
- /* Process an incoming AT command line
- */
- protected synchronized void handleInput(String input) {
- acquireWakeLock();
- long timestamp;
-
- if (DBG) timestamp = System.currentTimeMillis();
- AtCommandResult result = mAtParser.process(input);
- if (DBG) Log.d(TAG, "Processing " + input + " took " +
- (System.currentTimeMillis() - timestamp) + " ms");
-
- if (result.getResultCode() == AtCommandResult.ERROR) {
- Log.i(TAG, "Error pocessing <" + input + ">");
- }
-
- sendURC(result.toString());
-
- releaseWakeLock();
- }
-
- /**
- * Register AT commands that are common to all Headset / Handsets. This
- * function is called by the HeadsetBase constructor.
- */
- protected void initializeAtParser() {
- mAtParser = new AtParser();
- //TODO(): Get rid of this as there are no parsers registered. But because of dependencies,
- //it needs to be done as part of refactoring HeadsetBase and BluetoothHandsfree
- }
-
- public AtParser getAtParser() {
- return mAtParser;
- }
-
- public void startEventThread() {
- mEventThread =
- new Thread("HeadsetBase Event Thread") {
- public void run() {
- int last_read_error;
- while (!mEventThreadInterrupted) {
- String input = readNative(500);
- if (input != null) {
- handleInput(input);
- }
- else {
- last_read_error = getLastReadStatusNative();
- if (last_read_error != 0) {
- Log.i(TAG, "headset read error " + last_read_error);
- if (mEventThreadHandler != null) {
- mEventThreadHandler.obtainMessage(RFCOMM_DISCONNECTED)
- .sendToTarget();
- }
- disconnectNative();
- break;
- }
- }
- }
- }
- };
- mEventThreadInterrupted = false;
- mEventThread.start();
- }
-
-
-
- private native String readNative(int timeout_ms);
- private native int getLastReadStatusNative();
-
- private void stopEventThread() {
- mEventThreadInterrupted = true;
- mEventThread.interrupt();
- try {
- mEventThread.join();
- } catch (java.lang.InterruptedException e) {
- // FIXME: handle this,
- }
- mEventThread = null;
- }
-
- public boolean connect(Handler handler) {
- if (mEventThread == null) {
- if (!connectNative()) return false;
- mEventThreadHandler = handler;
- }
- return true;
- }
- private native boolean connectNative();
-
- /*
- * Returns true when either the asynchronous connect is in progress, or
- * the connect is complete. Call waitForAsyncConnect() to find out whether
- * the connect is actually complete, or disconnect() to cancel.
- */
-
- public boolean connectAsync() {
- return connectAsyncNative();
- }
- private native boolean connectAsyncNative();
-
- public int getRemainingAsyncConnectWaitingTimeMs() {
- return mTimeoutRemainingMs;
- }
-
- /*
- * Returns 1 when an async connect is complete, 0 on timeout, and -1 on
- * error. On error, handler will be called, and you need to re-initiate
- * the async connect.
- */
- public int waitForAsyncConnect(int timeout_ms, Handler handler) {
- int res = waitForAsyncConnectNative(timeout_ms);
- if (res > 0) {
- mEventThreadHandler = handler;
- }
- return res;
- }
- private native int waitForAsyncConnectNative(int timeout_ms);
-
- public void disconnect() {
- if (mEventThread != null) {
- stopEventThread();
- }
- disconnectNative();
- }
- private native void disconnectNative();
-
-
- /*
- * Note that if a remote side disconnects, this method will still return
- * true until disconnect() is called. You know when a remote side
- * disconnects because you will receive the intent
- * IBluetoothService.REMOTE_DEVICE_DISCONNECTED_ACTION. If, when you get
- * this intent, method isConnected() returns true, you know that the
- * disconnect was initiated by the remote device.
- */
-
- public boolean isConnected() {
- return mEventThread != null;
- }
-
- public String getAddress() {
- return mAddress;
- }
-
- public String getName() {
- return mBluetooth.getRemoteName(mAddress);
- }
-
- public int getDirection() {
- return mDirection;
- }
-
- public long getConnectTimestamp() {
- return mConnectTimestamp;
- }
-
- public synchronized boolean sendURC(String urc) {
- if (urc.length() > 0) {
- boolean ret = sendURCNative(urc);
- return ret;
- }
- return true;
- }
- private native boolean sendURCNative(String urc);
-
- private void acquireWakeLock() {
- if (!mWakeLock.isHeld()) {
- mWakeLock.acquire();
- }
- }
-
- private void releaseWakeLock() {
- if (mWakeLock.isHeld()) {
- mWakeLock.release();
- }
- }
-
- private void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
deleted file mode 100644
index 55ff27f..0000000
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-/**
- * System private API for Bluetooth A2DP service
- *
- * {@hide}
- */
-interface IBluetoothA2dp {
- int connectSink(in String address);
- int disconnectSink(in String address);
- List<String> listConnectedSinks();
- int getSinkState(in String address);
- int setSinkPriority(in String address, int priority);
- int getSinkPriority(in String address);
-}
diff --git a/core/java/android/bluetooth/IBluetoothDevice.aidl b/core/java/android/bluetooth/IBluetoothDevice.aidl
deleted file mode 100644
index 4351d2e..0000000
--- a/core/java/android/bluetooth/IBluetoothDevice.aidl
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2008, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.bluetooth.IBluetoothDeviceCallback;
-
-/**
- * System private API for talking with the Bluetooth service.
- *
- * {@hide}
- */
-interface IBluetoothDevice
-{
- boolean isEnabled();
- boolean enable(in IBluetoothDeviceCallback callback); // async
- boolean disable();
-
- String getAddress();
- String getName();
- boolean setName(in String name);
- String getVersion();
- String getRevision();
- String getManufacturer();
- String getCompany();
-
- int getScanMode();
- boolean setScanMode(int mode);
-
- int getDiscoverableTimeout();
- boolean setDiscoverableTimeout(int timeout);
-
- boolean startDiscovery(boolean resolveNames);
- boolean cancelDiscovery();
- boolean isDiscovering();
- boolean startPeriodicDiscovery();
- boolean stopPeriodicDiscovery();
- boolean isPeriodicDiscovery();
- String[] listRemoteDevices();
-
- String[] listAclConnections();
- boolean isAclConnected(in String address);
- boolean disconnectRemoteDeviceAcl(in String address);
-
- boolean createBond(in String address);
- boolean cancelBondProcess(in String address);
- boolean removeBond(in String address);
- String[] listBonds();
- int getBondState(in String address);
-
- String getRemoteName(in String address);
- String getRemoteVersion(in String address);
- String getRemoteRevision(in String address);
- int getRemoteClass(in String address);
- String getRemoteManufacturer(in String address);
- String getRemoteCompany(in String address);
- boolean getRemoteServiceChannel(in String address, int uuid16, in IBluetoothDeviceCallback callback);
- byte[] getRemoteFeatures(in String adddress);
- String lastSeen(in String address);
- String lastUsed(in String address);
-
- boolean setPin(in String address, in byte[] pin);
- boolean cancelPin(in String address);
-}
diff --git a/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl b/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl
deleted file mode 100644
index d25bd56..0000000
--- a/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2008, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-/**
- * {@hide}
- */
-oneway interface IBluetoothDeviceCallback
-{
- void onGetRemoteServiceChannelResult(in String address, int channel);
-
- void onEnableResult(int result);
-}
diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl
deleted file mode 100644
index 582d4e3..0000000
--- a/core/java/android/bluetooth/IBluetoothHeadset.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-/**
- * System private API for Bluetooth Headset service
- *
- * {@hide}
- */
-interface IBluetoothHeadset {
- int getState();
- String getHeadsetAddress();
- boolean connectHeadset(in String address);
- void disconnectHeadset();
- boolean isConnected(in String address);
- boolean startVoiceRecognition();
- boolean stopVoiceRecognition();
- boolean setPriority(in String address, int priority);
- int getPriority(in String address);
-}
diff --git a/core/java/android/bluetooth/RfcommSocket.java b/core/java/android/bluetooth/RfcommSocket.java
deleted file mode 100644
index a33263f..0000000
--- a/core/java/android/bluetooth/RfcommSocket.java
+++ /dev/null
@@ -1,674 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import java.io.IOException;
-import java.io.FileOutputStream;
-import java.io.FileInputStream;
-import java.io.OutputStream;
-import java.io.InputStream;
-import java.io.FileDescriptor;
-
-/**
- * The Android Bluetooth API is not finalized, and *will* change. Use at your
- * own risk.
- *
- * This class implements an API to the Bluetooth RFCOMM layer. An RFCOMM socket
- * is similar to a normal socket in that it takes an address and a port number.
- * The difference is of course that the address is a Bluetooth-device address,
- * and the port number is an RFCOMM channel. The API allows for the
- * establishment of listening sockets via methods
- * {@link #bind(String, int) bind}, {@link #listen(int) listen}, and
- * {@link #accept(RfcommSocket, int) accept}, as well as for the making of
- * outgoing connections with {@link #connect(String, int) connect},
- * {@link #connectAsync(String, int) connectAsync}, and
- * {@link #waitForAsyncConnect(int) waitForAsyncConnect}.
- *
- * After constructing a socket, you need to {@link #create() create} it and then
- * {@link #destroy() destroy} it when you are done using it. Both
- * {@link #create() create} and {@link #accept(RfcommSocket, int) accept} return
- * a {@link java.io.FileDescriptor FileDescriptor} for the actual data.
- * Alternatively, you may call {@link #getInputStream() getInputStream} and
- * {@link #getOutputStream() getOutputStream} to retrieve the respective streams
- * without going through the FileDescriptor.
- *
- * @hide
- */
-public class RfcommSocket {
-
- /**
- * Used by the native implementation of the class.
- */
- private int mNativeData;
-
- /**
- * Used by the native implementation of the class.
- */
- private int mPort;
-
- /**
- * Used by the native implementation of the class.
- */
- private String mAddress;
-
- /**
- * We save the return value of {@link #create() create} and
- * {@link #accept(RfcommSocket,int) accept} in this variable, and use it to
- * retrieve the I/O streams.
- */
- private FileDescriptor mFd;
-
- /**
- * After a call to {@link #waitForAsyncConnect(int) waitForAsyncConnect},
- * if the return value is zero, then, the the remaining time left to wait is
- * written into this variable (by the native implementation). It is possible
- * that {@link #waitForAsyncConnect(int) waitForAsyncConnect} returns before
- * the user-specified timeout expires, which is why we save the remaining
- * time in this member variable for the user to retrieve by calling method
- * {@link #getRemainingAsyncConnectWaitingTimeMs() getRemainingAsyncConnectWaitingTimeMs}.
- */
- private int mTimeoutRemainingMs;
-
- /**
- * Set to true when an asynchronous (nonblocking) connect is in progress.
- * {@see #connectAsync(String,int)}.
- */
- private boolean mIsConnecting;
-
- /**
- * Set to true after a successful call to {@link #bind(String,int) bind} and
- * used for error checking in {@link #listen(int) listen}. Reset to false
- * on {@link #destroy() destroy}.
- */
- private boolean mIsBound = false;
-
- /**
- * Set to true after a successful call to {@link #listen(int) listen} and
- * used for error checking in {@link #accept(RfcommSocket,int) accept}.
- * Reset to false on {@link #destroy() destroy}.
- */
- private boolean mIsListening = false;
-
- /**
- * Used to store the remaining time after an accept with a non-negative
- * timeout returns unsuccessfully. It is possible that a blocking
- * {@link #accept(int) accept} may wait for less than the time specified by
- * the user, which is why we store the remainder in this member variable for
- * it to be retrieved with method
- * {@link #getRemainingAcceptWaitingTimeMs() getRemainingAcceptWaitingTimeMs}.
- */
- private int mAcceptTimeoutRemainingMs;
-
- /**
- * Maintained by {@link #getInputStream() getInputStream}.
- */
- protected FileInputStream mInputStream;
-
- /**
- * Maintained by {@link #getOutputStream() getOutputStream}.
- */
- protected FileOutputStream mOutputStream;
-
- private native void initializeNativeDataNative();
-
- /**
- * Constructor.
- */
- public RfcommSocket() {
- initializeNativeDataNative();
- }
-
- private native void cleanupNativeDataNative();
-
- /**
- * Called by the GC to clean up the native data that we set up when we
- * construct the object.
- */
- protected void finalize() throws Throwable {
- try {
- cleanupNativeDataNative();
- } finally {
- super.finalize();
- }
- }
-
- private native static void classInitNative();
-
- static {
- classInitNative();
- }
-
- /**
- * Creates a socket. You need to call this method before performing any
- * other operation on a socket.
- *
- * @return FileDescriptor for the data stream.
- * @throws IOException
- * @see #destroy()
- */
- public FileDescriptor create() throws IOException {
- if (mFd == null) {
- mFd = createNative();
- }
- if (mFd == null) {
- throw new IOException("socket not created");
- }
- return mFd;
- }
-
- private native FileDescriptor createNative();
-
- /**
- * Destroys a socket created by {@link #create() create}. Call this
- * function when you no longer use the socket in order to release the
- * underlying OS resources.
- *
- * @see #create()
- */
- public void destroy() {
- synchronized (this) {
- destroyNative();
- mFd = null;
- mIsBound = false;
- mIsListening = false;
- }
- }
-
- private native void destroyNative();
-
- /**
- * Returns the {@link java.io.FileDescriptor FileDescriptor} of the socket.
- *
- * @return the FileDescriptor
- * @throws IOException
- * when the socket has not been {@link #create() created}.
- */
- public FileDescriptor getFileDescriptor() throws IOException {
- if (mFd == null) {
- throw new IOException("socket not created");
- }
- return mFd;
- }
-
- /**
- * Retrieves the input stream from the socket. Alternatively, you can do
- * that from the FileDescriptor returned by {@link #create() create} or
- * {@link #accept(RfcommSocket, int) accept}.
- *
- * @return InputStream
- * @throws IOException
- * if you have not called {@link #create() create} on the
- * socket.
- */
- public InputStream getInputStream() throws IOException {
- if (mFd == null) {
- throw new IOException("socket not created");
- }
-
- synchronized (this) {
- if (mInputStream == null) {
- mInputStream = new FileInputStream(mFd);
- }
-
- return mInputStream;
- }
- }
-
- /**
- * Retrieves the output stream from the socket. Alternatively, you can do
- * that from the FileDescriptor returned by {@link #create() create} or
- * {@link #accept(RfcommSocket, int) accept}.
- *
- * @return OutputStream
- * @throws IOException
- * if you have not called {@link #create() create} on the
- * socket.
- */
- public OutputStream getOutputStream() throws IOException {
- if (mFd == null) {
- throw new IOException("socket not created");
- }
-
- synchronized (this) {
- if (mOutputStream == null) {
- mOutputStream = new FileOutputStream(mFd);
- }
-
- return mOutputStream;
- }
- }
-
- /**
- * Starts a blocking connect to a remote RFCOMM socket. It takes the address
- * of a device and the RFCOMM channel (port) to which to connect.
- *
- * @param address
- * is the Bluetooth address of the remote device.
- * @param port
- * is the RFCOMM channel
- * @return true on success, false on failure
- * @throws IOException
- * if {@link #create() create} has not been called.
- * @see #connectAsync(String, int)
- */
- public boolean connect(String address, int port) throws IOException {
- synchronized (this) {
- if (mFd == null) {
- throw new IOException("socket not created");
- }
- return connectNative(address, port);
- }
- }
-
- private native boolean connectNative(String address, int port);
-
- /**
- * Starts an asynchronous (nonblocking) connect to a remote RFCOMM socket.
- * It takes the address of the device to connect to, as well as the RFCOMM
- * channel (port). On successful return (return value is true), you need to
- * call method {@link #waitForAsyncConnect(int) waitForAsyncConnect} to
- * block for up to a specified number of milliseconds while waiting for the
- * asyncronous connect to complete.
- *
- * @param address
- * of remote device
- * @param port
- * the RFCOMM channel
- * @return true when the asynchronous connect has successfully started,
- * false if there was an error.
- * @throws IOException
- * is you have not called {@link #create() create}
- * @see #waitForAsyncConnect(int)
- * @see #getRemainingAsyncConnectWaitingTimeMs()
- * @see #connect(String, int)
- */
- public boolean connectAsync(String address, int port) throws IOException {
- synchronized (this) {
- if (mFd == null) {
- throw new IOException("socket not created");
- }
- mIsConnecting = connectAsyncNative(address, port);
- return mIsConnecting;
- }
- }
-
- private native boolean connectAsyncNative(String address, int port);
-
- /**
- * Interrupts an asynchronous connect in progress. This method does nothing
- * when there is no asynchronous connect in progress.
- *
- * @throws IOException
- * if you have not called {@link #create() create}.
- * @see #connectAsync(String, int)
- */
- public void interruptAsyncConnect() throws IOException {
- synchronized (this) {
- if (mFd == null) {
- throw new IOException("socket not created");
- }
- if (mIsConnecting) {
- mIsConnecting = !interruptAsyncConnectNative();
- }
- }
- }
-
- private native boolean interruptAsyncConnectNative();
-
- /**
- * Tells you whether there is an asynchronous connect in progress. This
- * method returns an undefined value when there is a synchronous connect in
- * progress.
- *
- * @return true if there is an asyc connect in progress, false otherwise
- * @see #connectAsync(String, int)
- */
- public boolean isConnecting() {
- return mIsConnecting;
- }
-
- /**
- * Blocks for a specified amount of milliseconds while waiting for an
- * asynchronous connect to complete. Returns an integer value to indicate
- * one of the following: the connect succeeded, the connect is still in
- * progress, or the connect failed. It is possible for this method to block
- * for less than the time specified by the user, and still return zero
- * (i.e., async connect is still in progress.) For this reason, if the
- * return value is zero, you need to call method
- * {@link #getRemainingAsyncConnectWaitingTimeMs() getRemainingAsyncConnectWaitingTimeMs}
- * to retrieve the remaining time.
- *
- * @param timeoutMs
- * the time to block while waiting for the async connect to
- * complete.
- * @return a positive value if the connect succeeds; zero, if the connect is
- * still in progress, and a negative value if the connect failed.
- *
- * @throws IOException
- * @see #getRemainingAsyncConnectWaitingTimeMs()
- * @see #connectAsync(String, int)
- */
- public int waitForAsyncConnect(int timeoutMs) throws IOException {
- synchronized (this) {
- if (mFd == null) {
- throw new IOException("socket not created");
- }
- int ret = waitForAsyncConnectNative(timeoutMs);
- if (ret != 0) {
- mIsConnecting = false;
- }
- return ret;
- }
- }
-
- private native int waitForAsyncConnectNative(int timeoutMs);
-
- /**
- * Returns the number of milliseconds left to wait after the last call to
- * {@link #waitForAsyncConnect(int) waitForAsyncConnect}.
- *
- * It is possible that waitForAsyncConnect() waits for less than the time
- * specified by the user, and still returns zero (i.e., async connect is
- * still in progress.) For this reason, if the return value is zero, you
- * need to call this method to retrieve the remaining time before you call
- * waitForAsyncConnect again.
- *
- * @return the remaining timeout in milliseconds.
- * @see #waitForAsyncConnect(int)
- * @see #connectAsync(String, int)
- */
- public int getRemainingAsyncConnectWaitingTimeMs() {
- return mTimeoutRemainingMs;
- }
-
- /**
- * Shuts down both directions on a socket.
- *
- * @return true on success, false on failure; if the return value is false,
- * the socket might be left in a patially shut-down state (i.e. one
- * direction is shut down, but the other is still open.) In this
- * case, you should {@link #destroy() destroy} and then
- * {@link #create() create} the socket again.
- * @throws IOException
- * is you have not caled {@link #create() create}.
- * @see #shutdownInput()
- * @see #shutdownOutput()
- */
- public boolean shutdown() throws IOException {
- synchronized (this) {
- if (mFd == null) {
- throw new IOException("socket not created");
- }
- if (shutdownNative(true)) {
- return shutdownNative(false);
- }
-
- return false;
- }
- }
-
- /**
- * Shuts down the input stream of the socket, but leaves the output stream
- * in its current state.
- *
- * @return true on success, false on failure
- * @throws IOException
- * is you have not called {@link #create() create}
- * @see #shutdown()
- * @see #shutdownOutput()
- */
- public boolean shutdownInput() throws IOException {
- synchronized (this) {
- if (mFd == null) {
- throw new IOException("socket not created");
- }
- return shutdownNative(true);
- }
- }
-
- /**
- * Shut down the output stream of the socket, but leaves the input stream in
- * its current state.
- *
- * @return true on success, false on failure
- * @throws IOException
- * is you have not called {@link #create() create}
- * @see #shutdown()
- * @see #shutdownInput()
- */
- public boolean shutdownOutput() throws IOException {
- synchronized (this) {
- if (mFd == null) {
- throw new IOException("socket not created");
- }
- return shutdownNative(false);
- }
- }
-
- private native boolean shutdownNative(boolean shutdownInput);
-
- /**
- * Tells you whether a socket is connected to another socket. This could be
- * for input or output or both.
- *
- * @return true if connected, false otherwise.
- * @see #isInputConnected()
- * @see #isOutputConnected()
- */
- public boolean isConnected() {
- return isConnectedNative() > 0;
- }
-
- /**
- * Determines whether input is connected (i.e., whether you can receive data
- * on this socket.)
- *
- * @return true if input is connected, false otherwise.
- * @see #isConnected()
- * @see #isOutputConnected()
- */
- public boolean isInputConnected() {
- return (isConnectedNative() & 1) != 0;
- }
-
- /**
- * Determines whether output is connected (i.e., whether you can send data
- * on this socket.)
- *
- * @return true if output is connected, false otherwise.
- * @see #isConnected()
- * @see #isInputConnected()
- */
- public boolean isOutputConnected() {
- return (isConnectedNative() & 2) != 0;
- }
-
- private native int isConnectedNative();
-
- /**
- * Binds a listening socket to the local device, or a non-listening socket
- * to a remote device. The port is automatically selected as the first
- * available port in the range 12 to 30.
- *
- * NOTE: Currently we ignore the device parameter and always bind the socket
- * to the local device, assuming that it is a listening socket.
- *
- * TODO: Use bind(0) in native code to have the kernel select an unused
- * port.
- *
- * @param device
- * Bluetooth address of device to bind to (currently ignored).
- * @return true on success, false on failure
- * @throws IOException
- * if you have not called {@link #create() create}
- * @see #listen(int)
- * @see #accept(RfcommSocket,int)
- */
- public boolean bind(String device) throws IOException {
- if (mFd == null) {
- throw new IOException("socket not created");
- }
- for (int port = 12; port <= 30; port++) {
- if (bindNative(device, port)) {
- mIsBound = true;
- return true;
- }
- }
- mIsBound = false;
- return false;
- }
-
- /**
- * Binds a listening socket to the local device, or a non-listening socket
- * to a remote device.
- *
- * NOTE: Currently we ignore the device parameter and always bind the socket
- * to the local device, assuming that it is a listening socket.
- *
- * @param device
- * Bluetooth address of device to bind to (currently ignored).
- * @param port
- * RFCOMM channel to bind socket to.
- * @return true on success, false on failure
- * @throws IOException
- * if you have not called {@link #create() create}
- * @see #listen(int)
- * @see #accept(RfcommSocket,int)
- */
- public boolean bind(String device, int port) throws IOException {
- if (mFd == null) {
- throw new IOException("socket not created");
- }
- mIsBound = bindNative(device, port);
- return mIsBound;
- }
-
- private native boolean bindNative(String device, int port);
-
- /**
- * Starts listening for incoming connections on this socket, after it has
- * been bound to an address and RFCOMM channel with
- * {@link #bind(String,int) bind}.
- *
- * @param backlog
- * the number of pending incoming connections to queue for
- * {@link #accept(RfcommSocket, int) accept}.
- * @return true on success, false on failure
- * @throws IOException
- * if you have not called {@link #create() create} or if the
- * socket has not been bound to a device and RFCOMM channel.
- */
- public boolean listen(int backlog) throws IOException {
- if (mFd == null) {
- throw new IOException("socket not created");
- }
- if (!mIsBound) {
- throw new IOException("socket not bound");
- }
- mIsListening = listenNative(backlog);
- return mIsListening;
- }
-
- private native boolean listenNative(int backlog);
-
- /**
- * Accepts incoming-connection requests for a listening socket bound to an
- * RFCOMM channel. The user may provide a time to wait for an incoming
- * connection.
- *
- * Note that this method may return null (i.e., no incoming connection)
- * before the user-specified timeout expires. For this reason, on a null
- * return value, you need to call
- * {@link #getRemainingAcceptWaitingTimeMs() getRemainingAcceptWaitingTimeMs}
- * in order to see how much time is left to wait, before you call this
- * method again.
- *
- * @param newSock
- * is set to the new socket that is created as a result of a
- * successful accept.
- * @param timeoutMs
- * time (in milliseconds) to block while waiting to an
- * incoming-connection request. A negative value is an infinite
- * wait.
- * @return FileDescriptor of newSock on success, null on failure. Failure
- * occurs if the timeout expires without a successful connect.
- * @throws IOException
- * if the socket has not been {@link #create() create}ed, is
- * not bound, or is not a listening socket.
- * @see #bind(String, int)
- * @see #listen(int)
- * @see #getRemainingAcceptWaitingTimeMs()
- */
- public FileDescriptor accept(RfcommSocket newSock, int timeoutMs)
- throws IOException {
- synchronized (newSock) {
- if (mFd == null) {
- throw new IOException("socket not created");
- }
- if (mIsListening == false) {
- throw new IOException("not listening on socket");
- }
- newSock.mFd = acceptNative(newSock, timeoutMs);
- return newSock.mFd;
- }
- }
-
- /**
- * Returns the number of milliseconds left to wait after the last call to
- * {@link #accept(RfcommSocket, int) accept}.
- *
- * Since accept() may return null (i.e., no incoming connection) before the
- * user-specified timeout expires, you need to call this method in order to
- * see how much time is left to wait, and wait for that amount of time
- * before you call accept again.
- *
- * @return the remaining time, in milliseconds.
- */
- public int getRemainingAcceptWaitingTimeMs() {
- return mAcceptTimeoutRemainingMs;
- }
-
- private native FileDescriptor acceptNative(RfcommSocket newSock,
- int timeoutMs);
-
- /**
- * Get the port (rfcomm channel) associated with this socket.
- *
- * This is only valid if the port has been set via a successful call to
- * {@link #bind(String, int)}, {@link #connect(String, int)}
- * or {@link #connectAsync(String, int)}. This can be checked
- * with {@link #isListening()} and {@link #isConnected()}.
- * @return Port (rfcomm channel)
- */
- public int getPort() throws IOException {
- if (mFd == null) {
- throw new IOException("socket not created");
- }
- if (!mIsListening && !isConnected()) {
- throw new IOException("not listening or connected on socket");
- }
- return mPort;
- }
-
- /**
- * Return true if this socket is listening ({@link #listen(int)}
- * has been called successfully).
- */
- public boolean isListening() {
- return mIsListening;
- }
-}
diff --git a/core/java/android/bluetooth/ScoSocket.java b/core/java/android/bluetooth/ScoSocket.java
deleted file mode 100644
index a43a08b..0000000
--- a/core/java/android/bluetooth/ScoSocket.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.os.Handler;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
-import android.util.Log;
-
-/**
- * The Android Bluetooth API is not finalized, and *will* change. Use at your
- * own risk.
- *
- * Simple SCO Socket.
- * Currently in Android, there is no support for sending data over a SCO
- * socket - this is managed by the hardware link to the Bluetooth Chip. This
- * class is instead intended for management of the SCO socket lifetime,
- * and is tailored for use with the headset / handsfree profiles.
- * @hide
- */
-public class ScoSocket {
- private static final String TAG = "ScoSocket";
- private static final boolean DBG = true;
- private static final boolean VDBG = false; // even more logging
-
- public static final int STATE_READY = 1; // Ready for use. No threads or sockets
- public static final int STATE_ACCEPT = 2; // accept() thread running
- public static final int STATE_CONNECTING = 3; // connect() thread running
- public static final int STATE_CONNECTED = 4; // connected, waiting for close()
- public static final int STATE_CLOSED = 5; // was connected, now closed.
-
- private int mState;
- private int mNativeData;
- private Handler mHandler;
- private int mAcceptedCode;
- private int mConnectedCode;
- private int mClosedCode;
-
- private WakeLock mWakeLock; // held while in STATE_CONNECTING
-
- static {
- classInitNative();
- }
- private native static void classInitNative();
-
- public ScoSocket(PowerManager pm, Handler handler, int acceptedCode, int connectedCode,
- int closedCode) {
- initNative();
- mState = STATE_READY;
- mHandler = handler;
- mAcceptedCode = acceptedCode;
- mConnectedCode = connectedCode;
- mClosedCode = closedCode;
- mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ScoSocket");
- mWakeLock.setReferenceCounted(false);
- if (VDBG) log(this + " SCO OBJECT CTOR");
- }
- private native void initNative();
-
- protected void finalize() throws Throwable {
- try {
- if (VDBG) log(this + " SCO OBJECT DTOR");
- destroyNative();
- releaseWakeLock();
- } finally {
- super.finalize();
- }
- }
- private native void destroyNative();
-
- /** Connect this SCO socket to the given BT address.
- * Does not block.
- */
- public synchronized boolean connect(String address) {
- if (VDBG) log("connect() " + this);
- if (mState != STATE_READY) {
- if (DBG) log("connect(): Bad state");
- return false;
- }
- acquireWakeLock();
- if (connectNative(address)) {
- mState = STATE_CONNECTING;
- return true;
- } else {
- mState = STATE_CLOSED;
- releaseWakeLock();
- return false;
- }
- }
- private native boolean connectNative(String address);
-
- /** Accept incoming SCO connections.
- * Does not block.
- */
- public synchronized boolean accept() {
- if (VDBG) log("accept() " + this);
- if (mState != STATE_READY) {
- if (DBG) log("Bad state");
- return false;
- }
- if (acceptNative()) {
- mState = STATE_ACCEPT;
- return true;
- } else {
- mState = STATE_CLOSED;
- return false;
- }
- }
- private native boolean acceptNative();
-
- public synchronized void close() {
- if (DBG) log(this + " SCO OBJECT close() mState = " + mState);
- acquireWakeLock();
- mState = STATE_CLOSED;
- closeNative();
- releaseWakeLock();
- }
- private native void closeNative();
-
- public synchronized int getState() {
- return mState;
- }
-
- private synchronized void onConnected(int result) {
- if (VDBG) log(this + " onConnected() mState = " + mState + " " + this);
- if (mState != STATE_CONNECTING) {
- if (DBG) log("Strange state, closing " + mState + " " + this);
- return;
- }
- if (result >= 0) {
- mState = STATE_CONNECTED;
- } else {
- mState = STATE_CLOSED;
- }
- mHandler.obtainMessage(mConnectedCode, mState, -1, this).sendToTarget();
- releaseWakeLock();
- }
-
- private synchronized void onAccepted(int result) {
- if (VDBG) log("onAccepted() " + this);
- if (mState != STATE_ACCEPT) {
- if (DBG) log("Strange state " + this);
- return;
- }
- if (result >= 0) {
- mState = STATE_CONNECTED;
- } else {
- mState = STATE_CLOSED;
- }
- mHandler.obtainMessage(mAcceptedCode, mState, -1, this).sendToTarget();
- }
-
- private synchronized void onClosed() {
- if (DBG) log("onClosed() " + this);
- if (mState != STATE_CLOSED) {
- mState = STATE_CLOSED;
- mHandler.obtainMessage(mClosedCode, mState, -1, this).sendToTarget();
- releaseWakeLock();
- }
- }
-
- private void acquireWakeLock() {
- if (!mWakeLock.isHeld()) {
- mWakeLock.acquire();
- if (VDBG) log("mWakeLock.acquire() " + this);
- }
- }
-
- private void releaseWakeLock() {
- if (mWakeLock.isHeld()) {
- if (VDBG) log("mWakeLock.release() " + this);
- mWakeLock.release();
- }
- }
-
- private void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/bluetooth/package.html b/core/java/android/bluetooth/package.html
deleted file mode 100644
index 79abf0c..0000000
--- a/core/java/android/bluetooth/package.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<HTML>
-<BODY>
-Provides classes that manage Bluetooth functionality on the device.
-<p>
-The Bluetooth APIs allow applications can connect and disconnect headsets, or scan
-for other kinds of Bluetooth devices and pair them. Further control includes the
-ability to write and modify the local Service Discovery Protocol (SDP) database,
-query the SDP database of other Bluetooth devices, establish RFCOMM
-channels/sockets on Android, and connect to specified sockets on other devices.
-</p>
-<p>Remember, not all Android devices are guaranteed to have Bluetooth functionality.</p>
-</BODY>
-</HTML>
diff --git a/core/java/android/content/AbstractSyncableContentProvider.java b/core/java/android/content/AbstractSyncableContentProvider.java
deleted file mode 100644
index ce6501c..0000000
--- a/core/java/android/content/AbstractSyncableContentProvider.java
+++ /dev/null
@@ -1,601 +0,0 @@
-package android.content;
-
-import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.Cursor;
-import android.net.Uri;
-import android.accounts.AccountMonitor;
-import android.accounts.AccountMonitorListener;
-import android.provider.SyncConstValue;
-import android.util.Config;
-import android.util.Log;
-import android.os.Bundle;
-import android.text.TextUtils;
-
-import java.util.Collections;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Vector;
-import java.util.ArrayList;
-
-/**
- * A specialization of the ContentProvider that centralizes functionality
- * used by ContentProviders that are syncable. It also wraps calls to the ContentProvider
- * inside of database transactions.
- *
- * @hide
- */
-public abstract class AbstractSyncableContentProvider extends SyncableContentProvider {
- private static final String TAG = "SyncableContentProvider";
- protected SQLiteOpenHelper mOpenHelper;
- protected SQLiteDatabase mDb;
- private final String mDatabaseName;
- private final int mDatabaseVersion;
- private final Uri mContentUri;
- private AccountMonitor mAccountMonitor;
-
- /** the account set in the last call to onSyncStart() */
- private String mSyncingAccount;
-
- private SyncStateContentProviderHelper mSyncState = null;
-
- private static final String[] sAccountProjection = new String[] {SyncConstValue._SYNC_ACCOUNT};
-
- private boolean mIsTemporary;
-
- private AbstractTableMerger mCurrentMerger = null;
- private boolean mIsMergeCancelled = false;
-
- private static final String SYNC_ACCOUNT_WHERE_CLAUSE = SyncConstValue._SYNC_ACCOUNT + "=?";
-
- protected boolean isTemporary() {
- return mIsTemporary;
- }
-
- /**
- * Indicates whether or not this ContentProvider contains a full
- * set of data or just diffs. This knowledge comes in handy when
- * determining how to incorporate the contents of a temporary
- * provider into a real provider.
- */
- private boolean mContainsDiffs;
-
- /**
- * Initializes the AbstractSyncableContentProvider
- * @param dbName the filename of the database
- * @param dbVersion the current version of the database schema
- * @param contentUri The base Uri of the syncable content in this provider
- */
- public AbstractSyncableContentProvider(String dbName, int dbVersion, Uri contentUri) {
- super();
-
- mDatabaseName = dbName;
- mDatabaseVersion = dbVersion;
- mContentUri = contentUri;
- mIsTemporary = false;
- setContainsDiffs(false);
- if (Config.LOGV) {
- Log.v(TAG, "created SyncableContentProvider " + this);
- }
- }
-
- /**
- * Close resources that must be closed. You must call this to properly release
- * the resources used by the AbstractSyncableContentProvider.
- */
- public void close() {
- if (mOpenHelper != null) {
- mOpenHelper.close(); // OK to call .close() repeatedly.
- }
- }
-
- /**
- * Override to create your schema and do anything else you need to do with a new database.
- * This is run inside a transaction (so you don't need to use one).
- * This method may not use getDatabase(), or call content provider methods, it must only
- * use the database handle passed to it.
- */
- protected void bootstrapDatabase(SQLiteDatabase db) {}
-
- /**
- * Override to upgrade your database from an old version to the version you specified.
- * Don't set the DB version; this will automatically be done after the method returns.
- * This method may not use getDatabase(), or call content provider methods, it must only
- * use the database handle passed to it.
- *
- * @param oldVersion version of the existing database
- * @param newVersion current version to upgrade to
- * @return true if the upgrade was lossless, false if it was lossy
- */
- protected abstract boolean upgradeDatabase(SQLiteDatabase db, int oldVersion, int newVersion);
-
- /**
- * Override to do anything (like cleanups or checks) you need to do after opening a database.
- * Does nothing by default. This is run inside a transaction (so you don't need to use one).
- * This method may not use getDatabase(), or call content provider methods, it must only
- * use the database handle passed to it.
- */
- protected void onDatabaseOpened(SQLiteDatabase db) {}
-
- private class DatabaseHelper extends SQLiteOpenHelper {
- DatabaseHelper(Context context, String name) {
- // Note: context and name may be null for temp providers
- super(context, name, null, mDatabaseVersion);
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- bootstrapDatabase(db);
- mSyncState.createDatabase(db);
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- if (!upgradeDatabase(db, oldVersion, newVersion)) {
- mSyncState.discardSyncData(db, null /* all accounts */);
- getContext().getContentResolver().startSync(mContentUri, new Bundle());
- }
- }
-
- @Override
- public void onOpen(SQLiteDatabase db) {
- onDatabaseOpened(db);
- mSyncState.onDatabaseOpened(db);
- }
- }
-
- @Override
- public boolean onCreate() {
- if (isTemporary()) throw new IllegalStateException("onCreate() called for temp provider");
- mOpenHelper = new AbstractSyncableContentProvider.DatabaseHelper(getContext(), mDatabaseName);
- mSyncState = new SyncStateContentProviderHelper(mOpenHelper);
-
- AccountMonitorListener listener = new AccountMonitorListener() {
- public void onAccountsUpdated(String[] accounts) {
- // Some providers override onAccountsChanged(); give them a database to work with.
- mDb = mOpenHelper.getWritableDatabase();
- onAccountsChanged(accounts);
- TempProviderSyncAdapter syncAdapter = (TempProviderSyncAdapter)getSyncAdapter();
- if (syncAdapter != null) {
- syncAdapter.onAccountsChanged(accounts);
- }
- }
- };
- mAccountMonitor = new AccountMonitor(getContext(), listener);
-
- return true;
- }
-
- /**
- * Get a non-persistent instance of this content provider.
- * You must call {@link #close} on the returned
- * SyncableContentProvider when you are done with it.
- *
- * @return a non-persistent content provider with the same layout as this
- * provider.
- */
- public AbstractSyncableContentProvider getTemporaryInstance() {
- AbstractSyncableContentProvider temp;
- try {
- temp = getClass().newInstance();
- } catch (InstantiationException e) {
- throw new RuntimeException("unable to instantiate class, "
- + "this should never happen", e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(
- "IllegalAccess while instantiating class, "
- + "this should never happen", e);
- }
-
- // Note: onCreate() isn't run for the temp provider, and it has no Context.
- temp.mIsTemporary = true;
- temp.setContainsDiffs(true);
- temp.mOpenHelper = temp.new DatabaseHelper(null, null);
- temp.mSyncState = new SyncStateContentProviderHelper(temp.mOpenHelper);
- if (!isTemporary()) {
- mSyncState.copySyncState(
- mOpenHelper.getReadableDatabase(),
- temp.mOpenHelper.getWritableDatabase(),
- getSyncingAccount());
- }
- return temp;
- }
-
- public SQLiteDatabase getDatabase() {
- if (mDb == null) mDb = mOpenHelper.getWritableDatabase();
- return mDb;
- }
-
- public boolean getContainsDiffs() {
- return mContainsDiffs;
- }
-
- public void setContainsDiffs(boolean containsDiffs) {
- if (containsDiffs && !isTemporary()) {
- throw new IllegalStateException(
- "only a temporary provider can contain diffs");
- }
- mContainsDiffs = containsDiffs;
- }
-
- /**
- * Each subclass of this class should define a subclass of {@link
- * android.content.AbstractTableMerger} for each table they wish to merge. It
- * should then override this method and return one instance of
- * each merger, in sequence. Their {@link
- * android.content.AbstractTableMerger#merge merge} methods will be called, one at a
- * time, in the order supplied.
- *
- * <p>The default implementation returns an empty list, so that no
- * merging will occur.
- * @return A sequence of subclasses of {@link
- * android.content.AbstractTableMerger}, one for each table that should be merged.
- */
- protected Iterable<? extends AbstractTableMerger> getMergers() {
- return Collections.emptyList();
- }
-
- @Override
- public final int update(final Uri url, final ContentValues values,
- final String selection, final String[] selectionArgs) {
- mDb = mOpenHelper.getWritableDatabase();
- mDb.beginTransaction();
- try {
- if (isTemporary() && mSyncState.matches(url)) {
- int numRows = mSyncState.asContentProvider().update(
- url, values, selection, selectionArgs);
- mDb.setTransactionSuccessful();
- return numRows;
- }
-
- int result = updateInternal(url, values, selection, selectionArgs);
- mDb.setTransactionSuccessful();
-
- if (!isTemporary() && result > 0) {
- getContext().getContentResolver().notifyChange(url, null /* observer */,
- changeRequiresLocalSync(url));
- }
-
- return result;
- } finally {
- mDb.endTransaction();
- }
- }
-
- @Override
- public final int delete(final Uri url, final String selection,
- final String[] selectionArgs) {
- mDb = mOpenHelper.getWritableDatabase();
- mDb.beginTransaction();
- try {
- if (isTemporary() && mSyncState.matches(url)) {
- int numRows = mSyncState.asContentProvider().delete(url, selection, selectionArgs);
- mDb.setTransactionSuccessful();
- return numRows;
- }
- int result = deleteInternal(url, selection, selectionArgs);
- mDb.setTransactionSuccessful();
- if (!isTemporary() && result > 0) {
- getContext().getContentResolver().notifyChange(url, null /* observer */,
- changeRequiresLocalSync(url));
- }
- return result;
- } finally {
- mDb.endTransaction();
- }
- }
-
- @Override
- public final Uri insert(final Uri url, final ContentValues values) {
- mDb = mOpenHelper.getWritableDatabase();
- mDb.beginTransaction();
- try {
- if (isTemporary() && mSyncState.matches(url)) {
- Uri result = mSyncState.asContentProvider().insert(url, values);
- mDb.setTransactionSuccessful();
- return result;
- }
- Uri result = insertInternal(url, values);
- mDb.setTransactionSuccessful();
- if (!isTemporary() && result != null) {
- getContext().getContentResolver().notifyChange(url, null /* observer */,
- changeRequiresLocalSync(url));
- }
- return result;
- } finally {
- mDb.endTransaction();
- }
- }
-
- @Override
- public final int bulkInsert(final Uri uri, final ContentValues[] values) {
- int size = values.length;
- int completed = 0;
- final boolean isSyncStateUri = mSyncState.matches(uri);
- mDb = mOpenHelper.getWritableDatabase();
- mDb.beginTransaction();
- try {
- for (int i = 0; i < size; i++) {
- Uri result;
- if (isTemporary() && isSyncStateUri) {
- result = mSyncState.asContentProvider().insert(uri, values[i]);
- } else {
- result = insertInternal(uri, values[i]);
- mDb.yieldIfContended();
- }
- if (result != null) {
- completed++;
- }
- }
- mDb.setTransactionSuccessful();
- } finally {
- mDb.endTransaction();
- }
- if (!isTemporary() && completed == size) {
- getContext().getContentResolver().notifyChange(uri, null /* observer */,
- changeRequiresLocalSync(uri));
- }
- return completed;
- }
-
- /**
- * Check if changes to this URI can be syncable changes.
- * @param uri the URI of the resource that was changed
- * @return true if changes to this URI can be syncable changes, false otherwise
- */
- public boolean changeRequiresLocalSync(Uri uri) {
- return true;
- }
-
- @Override
- public final Cursor query(final Uri url, final String[] projection,
- final String selection, final String[] selectionArgs,
- final String sortOrder) {
- mDb = mOpenHelper.getReadableDatabase();
- if (isTemporary() && mSyncState.matches(url)) {
- return mSyncState.asContentProvider().query(
- url, projection, selection, selectionArgs, sortOrder);
- }
- return queryInternal(url, projection, selection, selectionArgs, sortOrder);
- }
-
- /**
- * Called right before a sync is started.
- *
- * @param context the sync context for the operation
- * @param account
- */
- public void onSyncStart(SyncContext context, String account) {
- if (TextUtils.isEmpty(account)) {
- throw new IllegalArgumentException("you passed in an empty account");
- }
- mSyncingAccount = account;
- }
-
- /**
- * Called right after a sync is completed
- *
- * @param context the sync context for the operation
- * @param success true if the sync succeeded, false if an error occurred
- */
- public void onSyncStop(SyncContext context, boolean success) {
- }
-
- /**
- * The account of the most recent call to onSyncStart()
- * @return the account
- */
- public String getSyncingAccount() {
- return mSyncingAccount;
- }
-
- /**
- * Merge diffs from a sync source with this content provider.
- *
- * @param context the SyncContext within which this merge is taking place
- * @param diffs A temporary content provider containing diffs from a sync
- * source.
- * @param result a MergeResult that contains information about the merge, including
- * a temporary content provider with the same layout as this provider containing
- * @param syncResult
- */
- public void merge(SyncContext context, SyncableContentProvider diffs,
- TempProviderSyncResult result, SyncResult syncResult) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- db.beginTransaction();
- try {
- synchronized(this) {
- mIsMergeCancelled = false;
- }
- Iterable<? extends AbstractTableMerger> mergers = getMergers();
- try {
- for (AbstractTableMerger merger : mergers) {
- synchronized(this) {
- if (mIsMergeCancelled) break;
- mCurrentMerger = merger;
- }
- merger.merge(context, getSyncingAccount(), diffs, result, syncResult, this);
- }
- if (mIsMergeCancelled) return;
- if (diffs != null) {
- mSyncState.copySyncState(
- ((AbstractSyncableContentProvider)diffs).mOpenHelper.getReadableDatabase(),
- mOpenHelper.getWritableDatabase(),
- getSyncingAccount());
- }
- } finally {
- synchronized (this) {
- mCurrentMerger = null;
- }
- }
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- }
- }
-
-
- /**
- * Invoked when the active sync has been canceled. Sets the sync state of this provider and
- * its merger to canceled.
- */
- public void onSyncCanceled() {
- synchronized (this) {
- mIsMergeCancelled = true;
- if (mCurrentMerger != null) {
- mCurrentMerger.onMergeCancelled();
- }
- }
- }
-
-
- public boolean isMergeCancelled() {
- return mIsMergeCancelled;
- }
-
- /**
- * Subclasses should override this instead of update(). See update()
- * for details.
- *
- * <p> This method is called within a acquireDbLock()/releaseDbLock() block,
- * which means a database transaction will be active during the call;
- */
- protected abstract int updateInternal(Uri url, ContentValues values,
- String selection, String[] selectionArgs);
-
- /**
- * Subclasses should override this instead of delete(). See delete()
- * for details.
- *
- * <p> This method is called within a acquireDbLock()/releaseDbLock() block,
- * which means a database transaction will be active during the call;
- */
- protected abstract int deleteInternal(Uri url, String selection, String[] selectionArgs);
-
- /**
- * Subclasses should override this instead of insert(). See insert()
- * for details.
- *
- * <p> This method is called within a acquireDbLock()/releaseDbLock() block,
- * which means a database transaction will be active during the call;
- */
- protected abstract Uri insertInternal(Uri url, ContentValues values);
-
- /**
- * Subclasses should override this instead of query(). See query()
- * for details.
- *
- * <p> This method is *not* called within a acquireDbLock()/releaseDbLock()
- * block for performance reasons. If an implementation needs atomic access
- * to the database the lock can be acquired then.
- */
- protected abstract Cursor queryInternal(Uri url, String[] projection,
- String selection, String[] selectionArgs, String sortOrder);
-
- /**
- * Make sure that there are no entries for accounts that no longer exist
- * @param accountsArray the array of currently-existing accounts
- */
- protected void onAccountsChanged(String[] accountsArray) {
- Map<String, Boolean> accounts = new HashMap<String, Boolean>();
- for (String account : accountsArray) {
- accounts.put(account, false);
- }
- accounts.put(SyncConstValue.NON_SYNCABLE_ACCOUNT, false);
-
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- Map<String, String> tableMap = db.getSyncedTables();
- Vector<String> tables = new Vector<String>();
- tables.addAll(tableMap.keySet());
- tables.addAll(tableMap.values());
-
- db.beginTransaction();
- try {
- mSyncState.onAccountsChanged(accountsArray);
- for (String table : tables) {
- deleteRowsForRemovedAccounts(accounts, table,
- SyncConstValue._SYNC_ACCOUNT);
- }
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- }
- }
-
- /**
- * A helper method to delete all rows whose account is not in the accounts
- * map. The accountColumnName is the name of the column that is expected
- * to hold the account. If a row has an empty account it is never deleted.
- *
- * @param accounts a map of existing accounts
- * @param table the table to delete from
- * @param accountColumnName the name of the column that is expected
- * to hold the account.
- */
- protected void deleteRowsForRemovedAccounts(Map<String, Boolean> accounts,
- String table, String accountColumnName) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- Cursor c = db.query(table, sAccountProjection, null, null,
- accountColumnName, null, null);
- try {
- while (c.moveToNext()) {
- String account = c.getString(0);
- if (TextUtils.isEmpty(account)) {
- continue;
- }
- if (!accounts.containsKey(account)) {
- int numDeleted;
- numDeleted = db.delete(table, accountColumnName + "=?", new String[]{account});
- if (Config.LOGV) {
- Log.v(TAG, "deleted " + numDeleted
- + " records from table " + table
- + " for account " + account);
- }
- }
- }
- } finally {
- c.close();
- }
- }
-
- /**
- * Called when the sync system determines that this provider should no longer
- * contain records for the specified account.
- */
- public void wipeAccount(String account) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- Map<String, String> tableMap = db.getSyncedTables();
- ArrayList<String> tables = new ArrayList<String>();
- tables.addAll(tableMap.keySet());
- tables.addAll(tableMap.values());
-
- db.beginTransaction();
-
- try {
- // remove the SyncState data
- mSyncState.discardSyncData(db, account);
-
- // remove the data in the synced tables
- for (String table : tables) {
- db.delete(table, SYNC_ACCOUNT_WHERE_CLAUSE, new String[]{account});
- }
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- }
- }
-
- /**
- * Retrieves the SyncData bytes for the given account. The byte array returned may be null.
- */
- public byte[] readSyncDataBytes(String account) {
- return mSyncState.readSyncDataBytes(mOpenHelper.getReadableDatabase(), account);
- }
-
- /**
- * Sets the SyncData bytes for the given account. The byte array may be null.
- */
- public void writeSyncDataBytes(String account, byte[] data) {
- mSyncState.writeSyncDataBytes(mOpenHelper.getWritableDatabase(), account, data);
- }
-}
diff --git a/core/java/android/content/AbstractTableMerger.java b/core/java/android/content/AbstractTableMerger.java
deleted file mode 100644
index 700f1d8..0000000
--- a/core/java/android/content/AbstractTableMerger.java
+++ /dev/null
@@ -1,582 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.sqlite.SQLiteDatabase;
-import android.net.Uri;
-import android.os.Debug;
-import android.provider.BaseColumns;
-import static android.provider.SyncConstValue.*;
-import android.text.TextUtils;
-import android.util.Log;
-
-/**
- * @hide
- */
-public abstract class AbstractTableMerger
-{
- private ContentValues mValues;
-
- protected SQLiteDatabase mDb;
- protected String mTable;
- protected Uri mTableURL;
- protected String mDeletedTable;
- protected Uri mDeletedTableURL;
- static protected ContentValues mSyncMarkValues;
- static private boolean TRACE;
-
- static {
- mSyncMarkValues = new ContentValues();
- mSyncMarkValues.put(_SYNC_MARK, 1);
- TRACE = false;
- }
-
- private static final String TAG = "AbstractTableMerger";
- private static final String[] syncDirtyProjection =
- new String[] {_SYNC_DIRTY, BaseColumns._ID, _SYNC_ID, _SYNC_VERSION};
- private static final String[] syncIdAndVersionProjection =
- new String[] {_SYNC_ID, _SYNC_VERSION};
-
- private volatile boolean mIsMergeCancelled;
-
- private static final String SELECT_MARKED = _SYNC_MARK + "> 0 and " + _SYNC_ACCOUNT + "=?";
-
- private static final String SELECT_BY_SYNC_ID_AND_ACCOUNT =
- _SYNC_ID +"=? and " + _SYNC_ACCOUNT + "=?";
- private static final String SELECT_BY_ID = BaseColumns._ID +"=?";
-
- private static final String SELECT_UNSYNCED = ""
- + _SYNC_DIRTY + " > 0 and (" + _SYNC_ACCOUNT + "=? or " + _SYNC_ACCOUNT + " is null)";
-
- public AbstractTableMerger(SQLiteDatabase database,
- String table, Uri tableURL, String deletedTable,
- Uri deletedTableURL)
- {
- mDb = database;
- mTable = table;
- mTableURL = tableURL;
- mDeletedTable = deletedTable;
- mDeletedTableURL = deletedTableURL;
- mValues = new ContentValues();
- }
-
- public abstract void insertRow(ContentProvider diffs,
- Cursor diffsCursor);
- public abstract void updateRow(long localPersonID,
- ContentProvider diffs, Cursor diffsCursor);
- public abstract void resolveRow(long localPersonID,
- String syncID, ContentProvider diffs, Cursor diffsCursor);
-
- /**
- * This is called when it is determined that a row should be deleted from the
- * ContentProvider. The localCursor is on a table from the local ContentProvider
- * and its current position is of the row that should be deleted. The localCursor
- * is only guaranteed to contain the BaseColumns.ID column so the implementation
- * of deleteRow() must query the database directly if other columns are needed.
- * <p>
- * It is the responsibility of the implementation of this method to ensure that the cursor
- * points to the next row when this method returns, either by calling Cursor.deleteRow() or
- * Cursor.next().
- *
- * @param localCursor The Cursor into the local table, which points to the row that
- * is to be deleted.
- */
- public void deleteRow(Cursor localCursor) {
- localCursor.deleteRow();
- }
-
- /**
- * After {@link #merge} has completed, this method is called to send
- * notifications to {@link android.database.ContentObserver}s of changes
- * to the containing {@link ContentProvider}. These notifications likely
- * do not want to request a sync back to the network.
- */
- protected abstract void notifyChanges();
-
- private static boolean findInCursor(Cursor cursor, int column, String id) {
- while (!cursor.isAfterLast() && !cursor.isNull(column)) {
- int comp = id.compareTo(cursor.getString(column));
- if (comp > 0) {
- cursor.moveToNext();
- continue;
- }
- return comp == 0;
- }
- return false;
- }
-
- public void onMergeCancelled() {
- mIsMergeCancelled = true;
- }
-
- /**
- * Carry out a merge of the given diffs, and add the results to
- * the given MergeResult. If we are the first merge to find
- * client-side diffs, we'll use the given ContentProvider to
- * construct a temporary instance to hold them.
- */
- public void merge(final SyncContext context,
- final String account,
- final SyncableContentProvider serverDiffs,
- TempProviderSyncResult result,
- SyncResult syncResult, SyncableContentProvider temporaryInstanceFactory) {
- mIsMergeCancelled = false;
- if (serverDiffs != null) {
- if (!mDb.isDbLockedByCurrentThread()) {
- throw new IllegalStateException("this must be called from within a DB transaction");
- }
- mergeServerDiffs(context, account, serverDiffs, syncResult);
- notifyChanges();
- }
-
- if (result != null) {
- findLocalChanges(result, temporaryInstanceFactory, account, syncResult);
- }
- if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "merge complete");
- }
-
- /**
- * @hide this is public for testing purposes only
- */
- public void mergeServerDiffs(SyncContext context,
- String account, SyncableContentProvider serverDiffs, SyncResult syncResult) {
- boolean diffsArePartial = serverDiffs.getContainsDiffs();
- // mark the current rows so that we can distinguish these from new
- // inserts that occur during the merge
- mDb.update(mTable, mSyncMarkValues, null, null);
- if (mDeletedTable != null) {
- mDb.update(mDeletedTable, mSyncMarkValues, null, null);
- }
-
- // load the local database entries, so we can merge them with the server
- final String[] accountSelectionArgs = new String[]{account};
- Cursor localCursor = mDb.query(mTable, syncDirtyProjection,
- SELECT_MARKED, accountSelectionArgs, null, null,
- mTable + "." + _SYNC_ID);
- Cursor deletedCursor;
- if (mDeletedTable != null) {
- deletedCursor = mDb.query(mDeletedTable, syncIdAndVersionProjection,
- SELECT_MARKED, accountSelectionArgs, null, null,
- mDeletedTable + "." + _SYNC_ID);
- } else {
- deletedCursor =
- mDb.rawQuery("select 'a' as _sync_id, 'b' as _sync_version limit 0", null);
- }
-
- // Apply updates and insertions from the server
- Cursor diffsCursor = serverDiffs.query(mTableURL,
- null, null, null, mTable + "." + _SYNC_ID);
- int deletedSyncIDColumn = deletedCursor.getColumnIndexOrThrow(_SYNC_ID);
- int deletedSyncVersionColumn = deletedCursor.getColumnIndexOrThrow(_SYNC_VERSION);
- int serverSyncIDColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_ID);
- int serverSyncVersionColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_VERSION);
- int serverSyncLocalIdColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_LOCAL_ID);
-
- String lastSyncId = null;
- int diffsCount = 0;
- int localCount = 0;
- localCursor.moveToFirst();
- deletedCursor.moveToFirst();
- while (diffsCursor.moveToNext()) {
- if (mIsMergeCancelled) {
- localCursor.close();
- deletedCursor.close();
- diffsCursor.close();
- return;
- }
- mDb.yieldIfContended();
- String serverSyncId = diffsCursor.getString(serverSyncIDColumn);
- String serverSyncVersion = diffsCursor.getString(serverSyncVersionColumn);
- long localRowId = 0;
- String localSyncVersion = null;
-
- diffsCount++;
- context.setStatusText("Processing " + diffsCount + "/"
- + diffsCursor.getCount());
- if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "processing server entry " +
- diffsCount + ", " + serverSyncId);
-
- if (TRACE) {
- if (diffsCount == 10) {
- Debug.startMethodTracing("atmtrace");
- }
- if (diffsCount == 20) {
- Debug.stopMethodTracing();
- }
- }
-
- boolean conflict = false;
- boolean update = false;
- boolean insert = false;
-
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "found event with serverSyncID " + serverSyncId);
- }
- if (TextUtils.isEmpty(serverSyncId)) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.e(TAG, "server entry doesn't have a serverSyncID");
- }
- continue;
- }
-
- // It is possible that the sync adapter wrote the same record multiple times,
- // e.g. if the same record came via multiple feeds. If this happens just ignore
- // the duplicate records.
- if (serverSyncId.equals(lastSyncId)) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "skipping record with duplicate remote server id " + lastSyncId);
- }
- continue;
- }
- lastSyncId = serverSyncId;
-
- String localSyncID = null;
- boolean localSyncDirty = false;
-
- while (!localCursor.isAfterLast()) {
- if (mIsMergeCancelled) {
- localCursor.deactivate();
- deletedCursor.deactivate();
- diffsCursor.deactivate();
- return;
- }
- localCount++;
- localSyncID = localCursor.getString(2);
-
- // If the local record doesn't have a _sync_id then
- // it is new. Ignore it for now, we will send an insert
- // the the server later.
- if (TextUtils.isEmpty(localSyncID)) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "local record " +
- localCursor.getLong(1) +
- " has no _sync_id, ignoring");
- }
- localCursor.moveToNext();
- localSyncID = null;
- continue;
- }
-
- int comp = serverSyncId.compareTo(localSyncID);
-
- // the local DB has a record that the server doesn't have
- if (comp > 0) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "local record " +
- localCursor.getLong(1) +
- " has _sync_id " + localSyncID +
- " that is < server _sync_id " + serverSyncId);
- }
- if (diffsArePartial) {
- localCursor.moveToNext();
- } else {
- deleteRow(localCursor);
- if (mDeletedTable != null) {
- mDb.delete(mDeletedTable, _SYNC_ID +"=?", new String[] {localSyncID});
- }
- syncResult.stats.numDeletes++;
- mDb.yieldIfContended();
- }
- localSyncID = null;
- continue;
- }
-
- // the server has a record that the local DB doesn't have
- if (comp < 0) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "local record " +
- localCursor.getLong(1) +
- " has _sync_id " + localSyncID +
- " that is > server _sync_id " + serverSyncId);
- }
- localSyncID = null;
- }
-
- // the server and the local DB both have this record
- if (comp == 0) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "local record " +
- localCursor.getLong(1) +
- " has _sync_id " + localSyncID +
- " that matches the server _sync_id");
- }
- localSyncDirty = localCursor.getInt(0) != 0;
- localRowId = localCursor.getLong(1);
- localSyncVersion = localCursor.getString(3);
- localCursor.moveToNext();
- }
-
- break;
- }
-
- // If this record is in the deleted table then update the server version
- // in the deleted table, if necessary, and then ignore it here.
- // We will send a deletion indication to the server down a
- // little further.
- if (findInCursor(deletedCursor, deletedSyncIDColumn, serverSyncId)) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "remote record " + serverSyncId + " is in the deleted table");
- }
- final String deletedSyncVersion = deletedCursor.getString(deletedSyncVersionColumn);
- if (!TextUtils.equals(deletedSyncVersion, serverSyncVersion)) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "setting version of deleted record " + serverSyncId + " to "
- + serverSyncVersion);
- }
- ContentValues values = new ContentValues();
- values.put(_SYNC_VERSION, serverSyncVersion);
- mDb.update(mDeletedTable, values, "_sync_id=?", new String[]{serverSyncId});
- }
- continue;
- }
-
- // If the _sync_local_id is present in the diffsCursor
- // then this record corresponds to a local record that was just
- // inserted into the server and the _sync_local_id is the row id
- // of the local record. Set these fields so that the next check
- // treats this record as an update, which will allow the
- // merger to update the record with the server's sync id
- if (!diffsCursor.isNull(serverSyncLocalIdColumn)) {
- localRowId = diffsCursor.getLong(serverSyncLocalIdColumn);
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "the remote record with sync id " + serverSyncId
- + " has a local sync id, " + localRowId);
- }
- localSyncID = serverSyncId;
- localSyncDirty = false;
- localSyncVersion = null;
- }
-
- if (!TextUtils.isEmpty(localSyncID)) {
- // An existing server item has changed
- boolean recordChanged = (localSyncVersion == null) ||
- !serverSyncVersion.equals(localSyncVersion);
- if (recordChanged) {
- if (localSyncDirty) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "remote record " + serverSyncId
- + " conflicts with local _sync_id " + localSyncID
- + ", local _id " + localRowId);
- }
- conflict = true;
- } else {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG,
- "remote record " +
- serverSyncId +
- " updates local _sync_id " +
- localSyncID + ", local _id " +
- localRowId);
- }
- update = true;
- }
- }
- } else {
- // the local db doesn't know about this record so add it
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "remote record " + serverSyncId + " is new, inserting");
- }
- insert = true;
- }
-
- if (update) {
- updateRow(localRowId, serverDiffs, diffsCursor);
- syncResult.stats.numUpdates++;
- } else if (conflict) {
- resolveRow(localRowId, serverSyncId, serverDiffs, diffsCursor);
- syncResult.stats.numUpdates++;
- } else if (insert) {
- insertRow(serverDiffs, diffsCursor);
- syncResult.stats.numInserts++;
- }
- }
-
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "processed " + diffsCount + " server entries");
- }
-
- // If tombstones aren't in use delete any remaining local rows that
- // don't have corresponding server rows. Keep the rows that don't
- // have a sync id since those were created locally and haven't been
- // synced to the server yet.
- if (!diffsArePartial) {
- while (!localCursor.isAfterLast() && !TextUtils.isEmpty(localCursor.getString(2))) {
- if (mIsMergeCancelled) {
- localCursor.deactivate();
- deletedCursor.deactivate();
- diffsCursor.deactivate();
- return;
- }
- localCount++;
- final String localSyncId = localCursor.getString(2);
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG,
- "deleting local record " +
- localCursor.getLong(1) +
- " _sync_id " + localSyncId);
- }
- deleteRow(localCursor);
- if (mDeletedTable != null) {
- mDb.delete(mDeletedTable, _SYNC_ID + "=?", new String[] {localSyncId});
- }
- syncResult.stats.numDeletes++;
- mDb.yieldIfContended();
- }
- }
-
- if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "checked " + localCount +
- " local entries");
- diffsCursor.deactivate();
- localCursor.deactivate();
- deletedCursor.deactivate();
-
- if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "applying deletions from the server");
-
- // Apply deletions from the server
- if (mDeletedTableURL != null) {
- diffsCursor = serverDiffs.query(mDeletedTableURL, null, null, null, null);
-
- while (diffsCursor.moveToNext()) {
- if (mIsMergeCancelled) {
- diffsCursor.deactivate();
- return;
- }
- // delete all rows that match each element in the diffsCursor
- fullyDeleteMatchingRows(diffsCursor, account, syncResult);
- mDb.yieldIfContended();
- }
- diffsCursor.deactivate();
- }
- }
-
- private void fullyDeleteMatchingRows(Cursor diffsCursor, String account,
- SyncResult syncResult) {
- int serverSyncIdColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_ID);
- final boolean deleteBySyncId = !diffsCursor.isNull(serverSyncIdColumn);
-
- // delete the rows explicitly so that the delete operation can be overridden
- final Cursor c;
- final String[] selectionArgs;
- if (deleteBySyncId) {
- selectionArgs = new String[]{diffsCursor.getString(serverSyncIdColumn), account};
- c = mDb.query(mTable, new String[]{BaseColumns._ID}, SELECT_BY_SYNC_ID_AND_ACCOUNT,
- selectionArgs, null, null, null);
- } else {
- int serverSyncLocalIdColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_LOCAL_ID);
- selectionArgs = new String[]{diffsCursor.getString(serverSyncLocalIdColumn)};
- c = mDb.query(mTable, new String[]{BaseColumns._ID}, SELECT_BY_ID, selectionArgs,
- null, null, null);
- }
- try {
- c.moveToFirst();
- while (!c.isAfterLast()) {
- deleteRow(c); // advances the cursor
- syncResult.stats.numDeletes++;
- }
- } finally {
- c.deactivate();
- }
- if (deleteBySyncId && mDeletedTable != null) {
- mDb.delete(mDeletedTable, SELECT_BY_SYNC_ID_AND_ACCOUNT, selectionArgs);
- }
- }
-
- /**
- * Converts cursor into a Map, using the correct types for the values.
- */
- protected void cursorRowToContentValues(Cursor cursor, ContentValues map) {
- DatabaseUtils.cursorRowToContentValues(cursor, map);
- }
-
- /**
- * Finds local changes, placing the results in the given result object.
- * @param temporaryInstanceFactory As an optimization for the case
- * where there are no client-side diffs, mergeResult may initially
- * have no {@link android.content.TempProviderSyncResult#tempContentProvider}. If this is
- * the first in the sequence of AbstractTableMergers to find
- * client-side diffs, it will use the given ContentProvider to
- * create a temporary instance and store its {@link
- * ContentProvider} in the mergeResult.
- * @param account
- * @param syncResult
- */
- private void findLocalChanges(TempProviderSyncResult mergeResult,
- SyncableContentProvider temporaryInstanceFactory, String account,
- SyncResult syncResult) {
- SyncableContentProvider clientDiffs = mergeResult.tempContentProvider;
- if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "generating client updates");
-
- final String[] accountSelectionArgs = new String[]{account};
-
- // Generate the client updates and insertions
- // Create a cursor for dirty records
- Cursor localChangesCursor = mDb.query(mTable, null, SELECT_UNSYNCED, accountSelectionArgs,
- null, null, null);
- long numInsertsOrUpdates = localChangesCursor.getCount();
- while (localChangesCursor.moveToNext()) {
- if (mIsMergeCancelled) {
- localChangesCursor.close();
- return;
- }
- if (clientDiffs == null) {
- clientDiffs = temporaryInstanceFactory.getTemporaryInstance();
- }
- mValues.clear();
- cursorRowToContentValues(localChangesCursor, mValues);
- mValues.remove("_id");
- DatabaseUtils.cursorLongToContentValues(localChangesCursor, "_id", mValues,
- _SYNC_LOCAL_ID);
- clientDiffs.insert(mTableURL, mValues);
- }
- localChangesCursor.close();
-
- // Generate the client deletions
- if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "generating client deletions");
- long numEntries = DatabaseUtils.queryNumEntries(mDb, mTable);
- long numDeletedEntries = 0;
- if (mDeletedTable != null) {
- Cursor deletedCursor = mDb.query(mDeletedTable,
- syncIdAndVersionProjection,
- _SYNC_ACCOUNT + "=? AND " + _SYNC_ID + " IS NOT NULL", accountSelectionArgs,
- null, null, mDeletedTable + "." + _SYNC_ID);
-
- numDeletedEntries = deletedCursor.getCount();
- while (deletedCursor.moveToNext()) {
- if (mIsMergeCancelled) {
- deletedCursor.close();
- return;
- }
- if (clientDiffs == null) {
- clientDiffs = temporaryInstanceFactory.getTemporaryInstance();
- }
- mValues.clear();
- DatabaseUtils.cursorRowToContentValues(deletedCursor, mValues);
- clientDiffs.insert(mDeletedTableURL, mValues);
- }
- deletedCursor.close();
- }
-
- if (clientDiffs != null) {
- mergeResult.tempContentProvider = clientDiffs;
- }
- syncResult.stats.numDeletes += numDeletedEntries;
- syncResult.stats.numUpdates += numInsertsOrUpdates;
- syncResult.stats.numEntries += numEntries;
- }
-}
diff --git a/core/java/android/content/ActivityNotFoundException.java b/core/java/android/content/ActivityNotFoundException.java
deleted file mode 100644
index 16149bb..0000000
--- a/core/java/android/content/ActivityNotFoundException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-/**
- * This exception is thrown when a call to {@link Context#startActivity} or
- * one of its variants fails because an Activity can not be found to execute
- * the given Intent.
- */
-public class ActivityNotFoundException extends RuntimeException
-{
- public ActivityNotFoundException()
- {
- }
-
- public ActivityNotFoundException(String name)
- {
- super(name);
- }
-};
-
diff --git a/core/java/android/content/AsyncQueryHandler.java b/core/java/android/content/AsyncQueryHandler.java
deleted file mode 100644
index ac851cc..0000000
--- a/core/java/android/content/AsyncQueryHandler.java
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.util.Log;
-
-import java.lang.ref.WeakReference;
-
-/**
- * A helper class to help make handling asynchronous {@link ContentResolver}
- * queries easier.
- */
-public abstract class AsyncQueryHandler extends Handler {
- private static final String TAG = "AsyncQuery";
- private static final boolean localLOGV = false;
-
- private static final int EVENT_ARG_QUERY = 1;
- private static final int EVENT_ARG_INSERT = 2;
- private static final int EVENT_ARG_UPDATE = 3;
- private static final int EVENT_ARG_DELETE = 4;
-
- /* package */ final WeakReference<ContentResolver> mResolver;
-
- private static Looper sLooper = null;
-
- private Handler mWorkerThreadHandler;
-
- protected static final class WorkerArgs {
- public Uri uri;
- public Handler handler;
- public String[] projection;
- public String selection;
- public String[] selectionArgs;
- public String orderBy;
- public Object result;
- public Object cookie;
- public ContentValues values;
- }
-
- protected class WorkerHandler extends Handler {
- public WorkerHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- final ContentResolver resolver = mResolver.get();
- if (resolver == null) return;
-
- WorkerArgs args = (WorkerArgs) msg.obj;
-
- int token = msg.what;
- int event = msg.arg1;
-
- switch (event) {
- case EVENT_ARG_QUERY:
- Cursor cursor;
- try {
- cursor = resolver.query(args.uri, args.projection,
- args.selection, args.selectionArgs,
- args.orderBy);
- // Calling getCount() causes the cursor window to be filled,
- // which will make the first access on the main thread a lot faster.
- if (cursor != null) {
- cursor.getCount();
- }
- } catch (Exception e) {
- cursor = null;
- }
-
- args.result = cursor;
- break;
-
- case EVENT_ARG_INSERT:
- args.result = resolver.insert(args.uri, args.values);
- break;
-
- case EVENT_ARG_UPDATE:
- args.result = resolver.update(args.uri, args.values, args.selection,
- args.selectionArgs);
- break;
-
- case EVENT_ARG_DELETE:
- args.result = resolver.delete(args.uri, args.selection, args.selectionArgs);
- break;
-
- }
-
- // passing the original token value back to the caller
- // on top of the event values in arg1.
- Message reply = args.handler.obtainMessage(token);
- reply.obj = args;
- reply.arg1 = msg.arg1;
-
- if (localLOGV) {
- Log.d(TAG, "WorkerHandler.handleMsg: msg.arg1=" + msg.arg1
- + ", reply.what=" + reply.what);
- }
-
- reply.sendToTarget();
- }
- }
-
- public AsyncQueryHandler(ContentResolver cr) {
- super();
- mResolver = new WeakReference<ContentResolver>(cr);
- synchronized (AsyncQueryHandler.class) {
- if (sLooper == null) {
- HandlerThread thread = new HandlerThread("AsyncQueryWorker");
- thread.start();
-
- sLooper = thread.getLooper();
- }
- }
- mWorkerThreadHandler = createHandler(sLooper);
- }
-
- protected Handler createHandler(Looper looper) {
- return new WorkerHandler(looper);
- }
-
- /**
- * This method begins an asynchronous query. When the query is done
- * {@link #onQueryComplete} is called.
- *
- * @param token A token passed into {@link #onQueryComplete} to identify
- * the query.
- * @param cookie An object that gets passed into {@link #onQueryComplete}
- * @param uri The URI, using the content:// scheme, for the content to
- * retrieve.
- * @param projection A list of which columns to return. Passing null will
- * return all columns, which is discouraged to prevent reading data
- * from storage that isn't going to be used.
- * @param selection A filter declaring which rows to return, formatted as an
- * SQL WHERE clause (excluding the WHERE itself). Passing null will
- * return all rows for the given URI.
- * @param selectionArgs You may include ?s in selection, which will be
- * replaced by the values from selectionArgs, in the order that they
- * appear in the selection. The values will be bound as Strings.
- * @param orderBy How to order the rows, formatted as an SQL ORDER BY
- * clause (excluding the ORDER BY itself). Passing null will use the
- * default sort order, which may be unordered.
- */
- public void startQuery(int token, Object cookie, Uri uri,
- String[] projection, String selection, String[] selectionArgs,
- String orderBy) {
- // Use the token as what so cancelOperations works properly
- Message msg = mWorkerThreadHandler.obtainMessage(token);
- msg.arg1 = EVENT_ARG_QUERY;
-
- WorkerArgs args = new WorkerArgs();
- args.handler = this;
- args.uri = uri;
- args.projection = projection;
- args.selection = selection;
- args.selectionArgs = selectionArgs;
- args.orderBy = orderBy;
- args.cookie = cookie;
- msg.obj = args;
-
- mWorkerThreadHandler.sendMessage(msg);
- }
-
- /**
- * Attempts to cancel operation that has not already started. Note that
- * there is no guarantee that the operation will be canceled. They still may
- * result in a call to on[Query/Insert/Update/Delete]Complete after this
- * call has completed.
- *
- * @param token The token representing the operation to be canceled.
- * If multiple operations have the same token they will all be canceled.
- */
- public final void cancelOperation(int token) {
- mWorkerThreadHandler.removeMessages(token);
- }
-
- /**
- * This method begins an asynchronous insert. When the insert operation is
- * done {@link #onInsertComplete} is called.
- *
- * @param token A token passed into {@link #onInsertComplete} to identify
- * the insert operation.
- * @param cookie An object that gets passed into {@link #onInsertComplete}
- * @param uri the Uri passed to the insert operation.
- * @param initialValues the ContentValues parameter passed to the insert operation.
- */
- public final void startInsert(int token, Object cookie, Uri uri,
- ContentValues initialValues) {
- // Use the token as what so cancelOperations works properly
- Message msg = mWorkerThreadHandler.obtainMessage(token);
- msg.arg1 = EVENT_ARG_INSERT;
-
- WorkerArgs args = new WorkerArgs();
- args.handler = this;
- args.uri = uri;
- args.cookie = cookie;
- args.values = initialValues;
- msg.obj = args;
-
- mWorkerThreadHandler.sendMessage(msg);
- }
-
- /**
- * This method begins an asynchronous update. When the update operation is
- * done {@link #onUpdateComplete} is called.
- *
- * @param token A token passed into {@link #onUpdateComplete} to identify
- * the update operation.
- * @param cookie An object that gets passed into {@link #onUpdateComplete}
- * @param uri the Uri passed to the update operation.
- * @param values the ContentValues parameter passed to the update operation.
- */
- public final void startUpdate(int token, Object cookie, Uri uri,
- ContentValues values, String selection, String[] selectionArgs) {
- // Use the token as what so cancelOperations works properly
- Message msg = mWorkerThreadHandler.obtainMessage(token);
- msg.arg1 = EVENT_ARG_UPDATE;
-
- WorkerArgs args = new WorkerArgs();
- args.handler = this;
- args.uri = uri;
- args.cookie = cookie;
- args.values = values;
- args.selection = selection;
- args.selectionArgs = selectionArgs;
- msg.obj = args;
-
- mWorkerThreadHandler.sendMessage(msg);
- }
-
- /**
- * This method begins an asynchronous delete. When the delete operation is
- * done {@link #onDeleteComplete} is called.
- *
- * @param token A token passed into {@link #onDeleteComplete} to identify
- * the delete operation.
- * @param cookie An object that gets passed into {@link #onDeleteComplete}
- * @param uri the Uri passed to the delete operation.
- * @param selection the where clause.
- */
- public final void startDelete(int token, Object cookie, Uri uri,
- String selection, String[] selectionArgs) {
- // Use the token as what so cancelOperations works properly
- Message msg = mWorkerThreadHandler.obtainMessage(token);
- msg.arg1 = EVENT_ARG_DELETE;
-
- WorkerArgs args = new WorkerArgs();
- args.handler = this;
- args.uri = uri;
- args.cookie = cookie;
- args.selection = selection;
- args.selectionArgs = selectionArgs;
- msg.obj = args;
-
- mWorkerThreadHandler.sendMessage(msg);
- }
-
- /**
- * Called when an asynchronous query is completed.
- *
- * @param token the token to identify the query, passed in from
- * {@link #startQuery}.
- * @param cookie the cookie object that's passed in from {@link #startQuery}.
- * @param cursor The cursor holding the results from the query.
- */
- protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
- // Empty
- }
-
- /**
- * Called when an asynchronous insert is completed.
- *
- * @param token the token to identify the query, passed in from
- * {@link #startInsert}.
- * @param cookie the cookie object that's passed in from
- * {@link #startInsert}.
- * @param uri the uri returned from the insert operation.
- */
- protected void onInsertComplete(int token, Object cookie, Uri uri) {
- // Empty
- }
-
- /**
- * Called when an asynchronous update is completed.
- *
- * @param token the token to identify the query, passed in from
- * {@link #startUpdate}.
- * @param cookie the cookie object that's passed in from
- * {@link #startUpdate}.
- * @param result the result returned from the update operation
- */
- protected void onUpdateComplete(int token, Object cookie, int result) {
- // Empty
- }
-
- /**
- * Called when an asynchronous delete is completed.
- *
- * @param token the token to identify the query, passed in from
- * {@link #startDelete}.
- * @param cookie the cookie object that's passed in from
- * {@link #startDelete}.
- * @param result the result returned from the delete operation
- */
- protected void onDeleteComplete(int token, Object cookie, int result) {
- // Empty
- }
-
- @Override
- public void handleMessage(Message msg) {
- WorkerArgs args = (WorkerArgs) msg.obj;
-
- if (localLOGV) {
- Log.d(TAG, "AsyncQueryHandler.handleMessage: msg.what=" + msg.what
- + ", msg.arg1=" + msg.arg1);
- }
-
- int token = msg.what;
- int event = msg.arg1;
-
- // pass token back to caller on each callback.
- switch (event) {
- case EVENT_ARG_QUERY:
- onQueryComplete(token, args.cookie, (Cursor) args.result);
- break;
-
- case EVENT_ARG_INSERT:
- onInsertComplete(token, args.cookie, (Uri) args.result);
- break;
-
- case EVENT_ARG_UPDATE:
- onUpdateComplete(token, args.cookie, (Integer) args.result);
- break;
-
- case EVENT_ARG_DELETE:
- onDeleteComplete(token, args.cookie, (Integer) args.result);
- break;
- }
- }
-}
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
deleted file mode 100644
index 08f6191..0000000
--- a/core/java/android/content/BroadcastReceiver.java
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.app.ActivityManagerNative;
-import android.app.IActivityManager;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-/**
- * Base class for code that will receive intents sent by sendBroadcast().
- * You can either dynamically register an instance of this class with
- * {@link Context#registerReceiver Context.registerReceiver()}
- * or statically publish an implementation through the
- * {@link android.R.styleable#AndroidManifestReceiver &lt;receiver&gt;}
- * tag in your <code>AndroidManifest.xml</code>. <em><strong>Note:</strong></em>
- * &nbsp;&nbsp;&nbsp;If registering a receiver in your
- * {@link android.app.Activity#onResume() Activity.onResume()}
- * implementation, you should unregister it in
- * {@link android.app.Activity#onPause() Activity.onPause()}.
- * (You won't receive intents when paused,
- * and this will cut down on unnecessary system overhead). Do not unregister in
- * {@link android.app.Activity#onSaveInstanceState(android.os.Bundle) Activity.onSaveInstanceState()},
- * because this won't be called if the user moves back in the history
- * stack.
- *
- * <p>There are two major classes of broadcasts that can be received:</p>
- * <ul>
- * <li> <b>Normal broadcasts</b> (sent with {@link Context#sendBroadcast(Intent)
- * Context.sendBroadcast}) are completely asynchronous. All receivers of the
- * broadcast are run, in an undefined order, often at the same time. This is
- * more efficient, but means that receivers can not use the result or abort
- * APIs included here.
- * <li> <b>Ordered broadcasts</b> (sent with {@link Context#sendOrderedBroadcast(Intent, String)
- * Context.sendOrderedBroadcast}) are delivered to one receiver at a time.
- * As each receiver executes in turn, it can propagate a result to the next
- * receiver, or it can completely abort the broadcast so that it won't be passed
- * to other receivers. The order receivers runs in can be controlled with the
- * {@link android.R.styleable#AndroidManifestIntentFilter_priority
- * android:priority} attribute of the matching intent-filter; receivers with
- * the same priority will be run in an arbitrary order.
- * </ul>
- *
- * <p>Even in the case of normal broadcasts, the system may in some
- * situations revert to delivering the broadcast one receiver at a time. In
- * particular, for receivers that may require the creation of a process, only
- * one will be run at a time to avoid overloading the system with new processes.
- * In this situation, however, the non-ordered semantics hold: these receivers
- * can not return results or abort their broadcast.</p>
- *
- * <p>Note that, although the Intent class is used for sending and receiving
- * these broadcasts, the Intent broadcast mechanism here is completely separate
- * from Intents that are used to start Activities with
- * {@link Context#startActivity Context.startActivity()}.
- * There is no way for an BroadcastReceiver
- * to see or capture Intents used with startActivity(); likewise, when
- * you broadcast an Intent, you will never find or start an Activity.
- * These two operations are semantically very different: starting an
- * Activity with an Intent is a foreground operation that modifies what the
- * user is currently interacting with; broadcasting an Intent is a background
- * operation that the user is not normally aware of.
- *
- * <p>The BroadcastReceiver class (when launched as a component through
- * a manifest's {@link android.R.styleable#AndroidManifestReceiver &lt;receiver&gt;}
- * tag) is an important part of an
- * <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">application's overall lifecycle</a>.</p>
- *
- * <p>Topics covered here:
- * <ol>
- * <li><a href="#ReceiverLifecycle">Receiver Lifecycle</a>
- * <li><a href="#Permissions">Permissions</a>
- * <li><a href="#ProcessLifecycle">Process Lifecycle</a>
- * </ol>
- *
- * <a name="ReceiverLifecycle"></a>
- * <h3>Receiver Lifecycle</h3>
- *
- * <p>A BroadcastReceiver object is only valid for the duration of the call
- * to {@link #onReceive}. Once your code returns from this function,
- * the system considers the object to be finished and no longer active.
- *
- * <p>This has important repercussions to what you can do in an
- * {@link #onReceive} implementation: anything that requires asynchronous
- * operation is not available, because you will need to return from the
- * function to handle the asynchronous operation, but at that point the
- * BroadcastReceiver is no longer active and thus the system is free to kill
- * its process before the asynchronous operation completes.
- *
- * <p>In particular, you may <i>not</i> show a dialog or bind to a service from
- * within an BroadcastReceiver. For the former, you should instead use the
- * {@link android.app.NotificationManager} API. For the latter, you can
- * use {@link android.content.Context#startService Context.startService()} to
- * send a command to the service.
- *
- * <a name="Permissions"></a>
- * <h3>Permissions</h3>
- *
- * <p>Access permissions can be enforced by either the sender or receiver
- * of an Intent.
- *
- * <p>To enforce a permission when sending, you supply a non-null
- * <var>permission</var> argument to
- * {@link Context#sendBroadcast(Intent, String)} or
- * {@link Context#sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)}.
- * Only receivers who have been granted this permission
- * (by requesting it with the
- * {@link android.R.styleable#AndroidManifestUsesPermission &lt;uses-permission&gt;}
- * tag in their <code>AndroidManifest.xml</code>) will be able to receive
- * the broadcast.
- *
- * <p>To enforce a permission when receiving, you supply a non-null
- * <var>permission</var> when registering your receiver -- either when calling
- * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)}
- * or in the static
- * {@link android.R.styleable#AndroidManifestReceiver &lt;receiver&gt;}
- * tag in your <code>AndroidManifest.xml</code>. Only broadcasters who have
- * been granted this permission (by requesting it with the
- * {@link android.R.styleable#AndroidManifestUsesPermission &lt;uses-permission&gt;}
- * tag in their <code>AndroidManifest.xml</code>) will be able to send an
- * Intent to the receiver.
- *
- * <p>See the <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a>
- * document for more information on permissions and security in general.
- *
- * <a name="ProcessLifecycle"></a>
- * <h3>Process Lifecycle</h3>
- *
- * <p>A process that is currently executing an BroadcastReceiver (that is,
- * currently running the code in its {@link #onReceive} method) is
- * considered to be a foreground process and will be kept running by the
- * system except under cases of extreme memory pressure.
- *
- * <p>Once you return from onReceive(), the BroadcastReceiver is no longer
- * active, and its hosting process is only as important as any other application
- * components that are running in it. This is especially important because if
- * that process was only hosting the BroadcastReceiver (a common case for
- * applications that the user has never or not recently interacted with), then
- * upon returning from onReceive() the system will consider its process
- * to be empty and aggressively kill it so that resources are available for other
- * more important processes.
- *
- * <p>This means that for longer-running operations you will often use
- * a {@link android.app.Service} in conjunction with an BroadcastReceiver to keep
- * the containing process active for the entire time of your operation.
- */
-public abstract class BroadcastReceiver {
- public BroadcastReceiver() {
- }
-
- /**
- * This method is called when the BroadcastReceiver is receiving an Intent
- * broadcast. During this time you can use the other methods on
- * BroadcastReceiver to view/modify the current result values. The function
- * is normally called from the main thread of its process, so you should
- * never perform long-running operations in it (there is a timeout of
- * 10 seconds that the system allows before considering the receiver to
- * be blocked and a candidate to be killed). You cannot launch a popup dialog
- * in your implementation of onReceive().
- *
- * <p><b>If this BroadcastReceiver was launched through a &lt;receiver&gt; tag,
- * then the object is no longer alive after returning from this
- * function.</b> This means you should not perform any operations that
- * return a result to you asynchronously -- in particular, for interacting
- * with services, you should use
- * {@link Context#startService(Intent)} instead of
- * {@link Context#bindService(Intent, ServiceConnection, int)}. If you wish
- * to interact with a service that is already running, you can use
- * {@link #peekService}.
- *
- * @param context The Context in which the receiver is running.
- * @param intent The Intent being received.
- */
- public abstract void onReceive(Context context, Intent intent);
-
- /**
- * Provide a binder to an already-running service. This method is synchronous
- * and will not start the target service if it is not present, so it is safe
- * to call from {@link #onReceive}.
- *
- * @param myContext The Context that had been passed to {@link #onReceive(Context, Intent)}
- * @param service The Intent indicating the service you wish to use. See {@link
- * Context#startService(Intent)} for more information.
- */
- public IBinder peekService(Context myContext, Intent service) {
- IActivityManager am = ActivityManagerNative.getDefault();
- IBinder binder = null;
- try {
- binder = am.peekService(service, service.resolveTypeIfNeeded(
- myContext.getContentResolver()));
- } catch (RemoteException e) {
- }
- return binder;
- }
-
- /**
- * Change the current result code of this broadcast; only works with
- * broadcasts sent through
- * {@link Context#sendOrderedBroadcast(Intent, String)
- * Context.sendOrderedBroadcast}. Often uses the
- * Activity {@link android.app.Activity#RESULT_CANCELED} and
- * {@link android.app.Activity#RESULT_OK} constants, though the
- * actual meaning of this value is ultimately up to the broadcaster.
- *
- * <p><strong>This method does not work with non-ordered broadcasts such
- * as those sent with {@link Context#sendBroadcast(Intent)
- * Context.sendBroadcast}</strong></p>
- *
- * @param code The new result code.
- *
- * @see #setResult(int, String, Bundle)
- */
- public final void setResultCode(int code) {
- checkSynchronousHint();
- mResultCode = code;
- }
-
- /**
- * Retrieve the current result code, as set by the previous receiver.
- *
- * @return int The current result code.
- */
- public final int getResultCode() {
- return mResultCode;
- }
-
- /**
- * Change the current result data of this broadcast; only works with
- * broadcasts sent through
- * {@link Context#sendOrderedBroadcast(Intent, String)
- * Context.sendOrderedBroadcast}. This is an arbitrary
- * string whose interpretation is up to the broadcaster.
- *
- * <p><strong>This method does not work with non-ordered broadcasts such
- * as those sent with {@link Context#sendBroadcast(Intent)
- * Context.sendBroadcast}</strong></p>
- *
- * @param data The new result data; may be null.
- *
- * @see #setResult(int, String, Bundle)
- */
- public final void setResultData(String data) {
- checkSynchronousHint();
- mResultData = data;
- }
-
- /**
- * Retrieve the current result data, as set by the previous receiver.
- * Often this is null.
- *
- * @return String The current result data; may be null.
- */
- public final String getResultData() {
- return mResultData;
- }
-
- /**
- * Change the current result extras of this broadcast; only works with
- * broadcasts sent through
- * {@link Context#sendOrderedBroadcast(Intent, String)
- * Context.sendOrderedBroadcast}. This is a Bundle
- * holding arbitrary data, whose interpretation is up to the
- * broadcaster. Can be set to null. Calling this method completely
- * replaces the current map (if any).
- *
- * <p><strong>This method does not work with non-ordered broadcasts such
- * as those sent with {@link Context#sendBroadcast(Intent)
- * Context.sendBroadcast}</strong></p>
- *
- * @param extras The new extra data map; may be null.
- *
- * @see #setResult(int, String, Bundle)
- */
- public final void setResultExtras(Bundle extras) {
- checkSynchronousHint();
- mResultExtras = extras;
- }
-
- /**
- * Retrieve the current result extra data, as set by the previous receiver.
- * Any changes you make to the returned Map will be propagated to the next
- * receiver.
- *
- * @param makeMap If true then a new empty Map will be made for you if the
- * current Map is null; if false you should be prepared to
- * receive a null Map.
- *
- * @return Map The current extras map.
- */
- public final Bundle getResultExtras(boolean makeMap) {
- Bundle e = mResultExtras;
- if (!makeMap) return e;
- if (e == null) mResultExtras = e = new Bundle();
- return e;
- }
-
- /**
- * Change all of the result data returned from this broadcasts; only works
- * with broadcasts sent through
- * {@link Context#sendOrderedBroadcast(Intent, String)
- * Context.sendOrderedBroadcast}. All current result data is replaced
- * by the value given to this method.
- *
- * <p><strong>This method does not work with non-ordered broadcasts such
- * as those sent with {@link Context#sendBroadcast(Intent)
- * Context.sendBroadcast}</strong></p>
- *
- * @param code The new result code. Often uses the
- * Activity {@link android.app.Activity#RESULT_CANCELED} and
- * {@link android.app.Activity#RESULT_OK} constants, though the
- * actual meaning of this value is ultimately up to the broadcaster.
- * @param data The new result data. This is an arbitrary
- * string whose interpretation is up to the broadcaster; may be null.
- * @param extras The new extra data map. This is a Bundle
- * holding arbitrary data, whose interpretation is up to the
- * broadcaster. Can be set to null. This completely
- * replaces the current map (if any).
- */
- public final void setResult(int code, String data, Bundle extras) {
- checkSynchronousHint();
- mResultCode = code;
- mResultData = data;
- mResultExtras = extras;
- }
-
- /**
- * Returns the flag indicating whether or not this receiver should
- * abort the current broadcast.
- *
- * @return True if the broadcast should be aborted.
- */
- public final boolean getAbortBroadcast() {
- return mAbortBroadcast;
- }
-
- /**
- * Sets the flag indicating that this receiver should abort the
- * current broadcast; only works with broadcasts sent through
- * {@link Context#sendOrderedBroadcast(Intent, String)
- * Context.sendOrderedBroadcast}. This will prevent
- * any other broadcast receivers from receiving the broadcast. It will still
- * call {@link #onReceive} of the BroadcastReceiver that the caller of
- * {@link Context#sendOrderedBroadcast(Intent, String)
- * Context.sendOrderedBroadcast} passed in.
- *
- * <p><strong>This method does not work with non-ordered broadcasts such
- * as those sent with {@link Context#sendBroadcast(Intent)
- * Context.sendBroadcast}</strong></p>
- */
- public final void abortBroadcast() {
- checkSynchronousHint();
- mAbortBroadcast = true;
- }
-
- /**
- * Clears the flag indicating that this receiver should abort the current
- * broadcast.
- */
- public final void clearAbortBroadcast() {
- mAbortBroadcast = false;
- }
-
- /**
- * For internal use, sets the hint about whether this BroadcastReceiver is
- * running in ordered mode.
- */
- public final void setOrderedHint(boolean isOrdered) {
- mOrderedHint = isOrdered;
- }
-
- /**
- * Control inclusion of debugging help for mismatched
- * calls to {@ Context#registerReceiver(BroadcastReceiver, IntentFilter)
- * Context.registerReceiver()}.
- * If called with true, before given to registerReceiver(), then the
- * callstack of the following {@link Context#unregisterReceiver(BroadcastReceiver)
- * Context.unregisterReceiver()} call is retained, to be printed if a later
- * incorrect unregister call is made. Note that doing this requires retaining
- * information about the BroadcastReceiver for the lifetime of the app,
- * resulting in a leak -- this should only be used for debugging.
- */
- public final void setDebugUnregister(boolean debug) {
- mDebugUnregister = debug;
- }
-
- /**
- * Return the last value given to {@link #setDebugUnregister}.
- */
- public final boolean getDebugUnregister() {
- return mDebugUnregister;
- }
-
- void checkSynchronousHint() {
- if (mOrderedHint) {
- return;
- }
- RuntimeException e = new RuntimeException(
- "BroadcastReceiver trying to return result during a non-ordered broadcast");
- e.fillInStackTrace();
- Log.e("BroadcastReceiver", e.getMessage(), e);
- }
-
- private int mResultCode;
- private String mResultData;
- private Bundle mResultExtras;
- private boolean mAbortBroadcast;
- private boolean mDebugUnregister;
- private boolean mOrderedHint;
-}
-
diff --git a/core/java/android/content/ComponentCallbacks.java b/core/java/android/content/ComponentCallbacks.java
deleted file mode 100644
index dad60b0..0000000
--- a/core/java/android/content/ComponentCallbacks.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.content.res.Configuration;
-
-/**
- * The set of callback APIs that are common to all application components
- * ({@link android.app.Activity}, {@link android.app.Service},
- * {@link ContentProvider}, and {@link android.app.Application}).
- */
-public interface ComponentCallbacks {
- /**
- * Called by the system when the device configuration changes while your
- * component is running. Note that, unlike activities, other components
- * are never restarted when a configuration changes: they must always deal
- * with the results of the change, such as by re-retrieving resources.
- *
- * <p>At the time that this function has been called, your Resources
- * object will have been updated to return resource values matching the
- * new configuration.
- *
- * @param newConfig The new device configuration.
- */
- void onConfigurationChanged(Configuration newConfig);
-
- /**
- * This is called when the overall system is running low on memory, and
- * would like actively running process to try to tighten their belt. While
- * the exact point at which this will be called is not defined, generally
- * it will happen around the time all background process have been killed,
- * that is before reaching the point of killing processes hosting
- * service and foreground UI that we would like to avoid killing.
- *
- * <p>Applications that want to be nice can implement this method to release
- * any caches or other unnecessary resources they may be holding on to.
- * The system will perform a gc for you after returning from this method.
- */
- void onLowMemory();
-}
diff --git a/core/java/android/content/ComponentName.aidl b/core/java/android/content/ComponentName.aidl
deleted file mode 100644
index 40dc8de..0000000
--- a/core/java/android/content/ComponentName.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2007, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-parcelable ComponentName;
diff --git a/core/java/android/content/ComponentName.java b/core/java/android/content/ComponentName.java
deleted file mode 100644
index 32c6864..0000000
--- a/core/java/android/content/ComponentName.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Identifier for a specific application component
- * ({@link android.app.Activity}, {@link android.app.Service},
- * {@link android.content.BroadcastReceiver}, or
- * {@link android.content.ContentProvider}) that is available. Two
- * pieces of information, encapsulated here, are required to identify
- * a component: the package (a String) it exists in, and the class (a String)
- * name inside of that package.
- *
- */
-public final class ComponentName implements Parcelable {
- private final String mPackage;
- private final String mClass;
-
- /**
- * Create a new component identifier.
- *
- * @param pkg The name of the package that the component exists in. Can
- * not be null.
- * @param cls The name of the class inside of <var>pkg</var> that
- * implements the component. Can not be null.
- */
- public ComponentName(String pkg, String cls) {
- if (pkg == null) throw new NullPointerException("package name is null");
- if (cls == null) throw new NullPointerException("class name is null");
- mPackage = pkg;
- mClass = cls;
- }
-
- /**
- * Create a new component identifier from a Context and class name.
- *
- * @param pkg A Context for the package implementing the component,
- * from which the actual package name will be retrieved.
- * @param cls The name of the class inside of <var>pkg</var> that
- * implements the component.
- */
- public ComponentName(Context pkg, String cls) {
- if (cls == null) throw new NullPointerException("class name is null");
- mPackage = pkg.getPackageName();
- mClass = cls;
- }
-
- /**
- * Create a new component identifier from a Context and Class object.
- *
- * @param pkg A Context for the package implementing the component, from
- * which the actual package name will be retrieved.
- * @param cls The Class object of the desired component, from which the
- * actual class name will be retrieved.
- */
- public ComponentName(Context pkg, Class<?> cls) {
- mPackage = pkg.getPackageName();
- mClass = cls.getName();
- }
-
- /**
- * Return the package name of this component.
- */
- public String getPackageName() {
- return mPackage;
- }
-
- /**
- * Return the class name of this component.
- */
- public String getClassName() {
- return mClass;
- }
-
- /**
- * Return the class name, either fully qualified or in a shortened form
- * (with a leading '.') if it is a suffix of the package.
- */
- public String getShortClassName() {
- if (mClass.startsWith(mPackage)) {
- int PN = mPackage.length();
- int CN = mClass.length();
- if (CN > PN && mClass.charAt(PN) == '.') {
- return mClass.substring(PN, CN);
- }
- }
- return mClass;
- }
-
- /**
- * Return a String that unambiguously describes both the package and
- * class names contained in the ComponentName. You can later recover
- * the ComponentName from this string through
- * {@link #unflattenFromString(String)}.
- *
- * @return Returns a new String holding the package and class names. This
- * is represented as the package name, concatenated with a '/' and then the
- * class name.
- *
- * @see #unflattenFromString(String)
- */
- public String flattenToString() {
- return mPackage + "/" + mClass;
- }
-
- /**
- * The samee as {@link #flattenToString()}, but abbreviates the class
- * name if it is a suffix of the package. The result can still be used
- * with {@link #unflattenFromString(String)}.
- *
- * @return Returns a new String holding the package and class names. This
- * is represented as the package name, concatenated with a '/' and then the
- * class name.
- *
- * @see #unflattenFromString(String)
- */
- public String flattenToShortString() {
- return mPackage + "/" + getShortClassName();
- }
-
- /**
- * Recover a ComponentName from a String that was previously created with
- * {@link #flattenToString()}. It splits the string at the first '/',
- * taking the part before as the package name and the part after as the
- * class name. As a special convenience (to use, for example, when
- * parsing component names on the command line), if the '/' is immediately
- * followed by a '.' then the final class name will be the concatenation
- * of the package name with the string following the '/'. Thus
- * "com.foo/.Blah" becomes package="com.foo" class="com.foo.Blah".
- *
- * @param str The String that was returned by flattenToString().
- * @return Returns a new ComponentName containing the package and class
- * names that were encoded in <var>str</var>
- *
- * @see #flattenToString()
- */
- public static ComponentName unflattenFromString(String str) {
- int sep = str.indexOf('/');
- if (sep < 0 || (sep+1) >= str.length()) {
- return null;
- }
- String pkg = str.substring(0, sep);
- String cls = str.substring(sep+1);
- if (cls.length() > 0 && cls.charAt(0) == '.') {
- cls = pkg + cls;
- }
- return new ComponentName(pkg, cls);
- }
-
- /**
- * Return string representation of this class without the class's name
- * as a prefix.
- */
- public String toShortString() {
- return "{" + mPackage + "/" + mClass + "}";
- }
-
- @Override
- public String toString() {
- return "ComponentInfo{" + mPackage + "/" + mClass + "}";
- }
-
- @Override
- public boolean equals(Object obj) {
- try {
- if (obj != null) {
- ComponentName other = (ComponentName)obj;
- // Note: no null checks, because mPackage and mClass can
- // never be null.
- return mPackage.equals(other.mPackage)
- && mClass.equals(other.mClass);
- }
- } catch (ClassCastException e) {
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return mPackage.hashCode() + mClass.hashCode();
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(mPackage);
- out.writeString(mClass);
- }
-
- /**
- * Write a ComponentName to a Parcel, handling null pointers. Must be
- * read with {@link #readFromParcel(Parcel)}.
- *
- * @param c The ComponentName to be written.
- * @param out The Parcel in which the ComponentName will be placed.
- *
- * @see #readFromParcel(Parcel)
- */
- public static void writeToParcel(ComponentName c, Parcel out) {
- if (c != null) {
- c.writeToParcel(out, 0);
- } else {
- out.writeString(null);
- }
- }
-
- /**
- * Read a ComponentName from a Parcel that was previously written
- * with {@link #writeToParcel(ComponentName, Parcel)}, returning either
- * a null or new object as appropriate.
- *
- * @param in The Parcel from which to read the ComponentName
- * @return Returns a new ComponentName matching the previously written
- * object, or null if a null had been written.
- *
- * @see #writeToParcel(ComponentName, Parcel)
- */
- public static ComponentName readFromParcel(Parcel in) {
- String pkg = in.readString();
- return pkg != null ? new ComponentName(pkg, in) : null;
- }
-
- public static final Parcelable.Creator<ComponentName> CREATOR
- = new Parcelable.Creator<ComponentName>() {
- public ComponentName createFromParcel(Parcel in) {
- return new ComponentName(in);
- }
-
- public ComponentName[] newArray(int size) {
- return new ComponentName[size];
- }
- };
-
- /**
- * Instantiate a new ComponentName from the data in a Parcel that was
- * previously written with {@link #writeToParcel(Parcel, int)}. Note that you
- * must not use this with data written by
- * {@link #writeToParcel(ComponentName, Parcel)} since it is not possible
- * to handle a null ComponentObject here.
- *
- * @param in The Parcel containing the previously written ComponentName,
- * positioned at the location in the buffer where it was written.
- */
- public ComponentName(Parcel in) {
- mPackage = in.readString();
- if (mPackage == null) throw new NullPointerException(
- "package name is null");
- mClass = in.readString();
- if (mClass == null) throw new NullPointerException(
- "class name is null");
- }
-
- private ComponentName(String pkg, Parcel in) {
- mPackage = pkg;
- mClass = in.readString();
- }
-}
diff --git a/core/java/android/content/ContentInsertHandler.java b/core/java/android/content/ContentInsertHandler.java
deleted file mode 100644
index fbf726e..0000000
--- a/core/java/android/content/ContentInsertHandler.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Interface to insert data to ContentResolver
- * @hide
- */
-public interface ContentInsertHandler extends ContentHandler {
- /**
- * insert data from InputStream to ContentResolver
- * @param contentResolver
- * @param in InputStream
- * @throws IOException
- * @throws SAXException
- */
- public void insert(ContentResolver contentResolver, InputStream in)
- throws IOException, SAXException;
-
- /**
- * insert data from String to ContentResolver
- * @param contentResolver
- * @param in input string
- * @throws SAXException
- */
- public void insert(ContentResolver contentResolver, String in)
- throws SAXException;
-
-}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
deleted file mode 100644
index 3a64cee..0000000
--- a/core/java/android/content/ContentProvider.java
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
-import android.content.res.Configuration;
-import android.database.Cursor;
-import android.database.CursorToBulkCursorAdaptor;
-import android.database.CursorWindow;
-import android.database.IBulkCursor;
-import android.database.IContentObserver;
-import android.database.SQLException;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.ParcelFileDescriptor;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-
-/**
- * Content providers are one of the primary building blocks of Android applications, providing
- * content to applications. They encapsulate data and provide it to applications through the single
- * {@link ContentResolver} interface. A content provider is only required if you need to share
- * data between multiple applications. For example, the contacts data is used by multiple
- * applications and must be stored in a content provider. If you don't need to share data amongst
- * multiple applications you can use a database directly via
- * {@link android.database.sqlite.SQLiteDatabase}.
- *
- * <p>For more information, read <a href="{@docRoot}guide/topics/providers/content-providers.html">Content
- * Providers</a>.</p>
- *
- * <p>When a request is made via
- * a {@link ContentResolver} the system inspects the authority of the given URI and passes the
- * request to the content provider registered with the authority. The content provider can interpret
- * the rest of the URI however it wants. The {@link UriMatcher} class is helpful for parsing
- * URIs.</p>
- *
- * <p>The primary methods that need to be implemented are:
- * <ul>
- * <li>{@link #query} which returns data to the caller</li>
- * <li>{@link #insert} which inserts new data into the content provider</li>
- * <li>{@link #update} which updates existing data in the content provider</li>
- * <li>{@link #delete} which deletes data from the content provider</li>
- * <li>{@link #getType} which returns the MIME type of data in the content provider</li>
- * </ul></p>
- *
- * <p>This class takes care of cross process calls so subclasses don't have to worry about which
- * process a request is coming from.</p>
- */
-public abstract class ContentProvider implements ComponentCallbacks {
- private Context mContext = null;
- private String mReadPermission;
- private String mWritePermission;
-
- private Transport mTransport = new Transport();
-
- /**
- * Given an IContentProvider, try to coerce it back to the real
- * ContentProvider object if it is running in the local process. This can
- * be used if you know you are running in the same process as a provider,
- * and want to get direct access to its implementation details. Most
- * clients should not nor have a reason to use it.
- *
- * @param abstractInterface The ContentProvider interface that is to be
- * coerced.
- * @return If the IContentProvider is non-null and local, returns its actual
- * ContentProvider instance. Otherwise returns null.
- * @hide
- */
- public static ContentProvider coerceToLocalContentProvider(
- IContentProvider abstractInterface) {
- if (abstractInterface instanceof Transport) {
- return ((Transport)abstractInterface).getContentProvider();
- }
- return null;
- }
-
- /**
- * Binder object that deals with remoting.
- *
- * @hide
- */
- class Transport extends ContentProviderNative {
- ContentProvider getContentProvider() {
- return ContentProvider.this;
- }
-
- /**
- * Remote version of a query, which returns an IBulkCursor. The bulk
- * cursor should be wrapped with BulkCursorToCursorAdaptor before use.
- */
- public IBulkCursor bulkQuery(Uri uri, String[] projection,
- String selection, String[] selectionArgs, String sortOrder,
- IContentObserver observer, CursorWindow window) {
- checkReadPermission(uri);
- Cursor cursor = ContentProvider.this.query(uri, projection,
- selection, selectionArgs, sortOrder);
- if (cursor == null) {
- return null;
- }
- String wperm = getWritePermission();
- return new CursorToBulkCursorAdaptor(cursor, observer,
- ContentProvider.this.getClass().getName(),
- wperm == null ||
- getContext().checkCallingOrSelfPermission(getWritePermission())
- == PackageManager.PERMISSION_GRANTED,
- window);
- }
-
- public Cursor query(Uri uri, String[] projection,
- String selection, String[] selectionArgs, String sortOrder) {
- checkReadPermission(uri);
- return ContentProvider.this.query(uri, projection, selection,
- selectionArgs, sortOrder);
- }
-
- public String getType(Uri uri) {
- return ContentProvider.this.getType(uri);
- }
-
-
- public Uri insert(Uri uri, ContentValues initialValues) {
- checkWritePermission(uri);
- return ContentProvider.this.insert(uri, initialValues);
- }
-
- public int bulkInsert(Uri uri, ContentValues[] initialValues) {
- checkWritePermission(uri);
- return ContentProvider.this.bulkInsert(uri, initialValues);
- }
-
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- checkWritePermission(uri);
- return ContentProvider.this.delete(uri, selection, selectionArgs);
- }
-
- public int update(Uri uri, ContentValues values, String selection,
- String[] selectionArgs) {
- checkWritePermission(uri);
- return ContentProvider.this.update(uri, values, selection, selectionArgs);
- }
-
- public ParcelFileDescriptor openFile(Uri uri, String mode)
- throws FileNotFoundException {
- if (mode != null && mode.startsWith("rw")) checkWritePermission(uri);
- else checkReadPermission(uri);
- return ContentProvider.this.openFile(uri, mode);
- }
-
- public ISyncAdapter getSyncAdapter() {
- checkWritePermission(null);
- return ContentProvider.this.getSyncAdapter().getISyncAdapter();
- }
-
- private void checkReadPermission(Uri uri) {
- final String rperm = getReadPermission();
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- if (getContext().checkUriPermission(uri, rperm, null, pid, uid,
- Intent.FLAG_GRANT_READ_URI_PERMISSION)
- == PackageManager.PERMISSION_GRANTED) {
- return;
- }
- String msg = "Permission Denial: reading "
- + ContentProvider.this.getClass().getName()
- + " uri " + uri + " from pid=" + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid()
- + " requires " + rperm;
- throw new SecurityException(msg);
- }
-
- private void checkWritePermission(Uri uri) {
- final String wperm = getWritePermission();
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- if (getContext().checkUriPermission(uri, null, wperm, pid, uid,
- Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
- == PackageManager.PERMISSION_GRANTED) {
- return;
- }
- String msg = "Permission Denial: writing "
- + ContentProvider.this.getClass().getName()
- + " uri " + uri + " from pid=" + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid()
- + " requires " + wperm;
- throw new SecurityException(msg);
- }
- }
-
-
- /**
- * Retrieve the Context this provider is running in. Only available once
- * onCreate(Map icicle) has been called -- this will be null in the
- * constructor.
- */
- public final Context getContext() {
- return mContext;
- }
-
- /**
- * Change the permission required to read data from the content
- * provider. This is normally set for you from its manifest information
- * when the provider is first created.
- *
- * @param permission Name of the permission required for read-only access.
- */
- protected final void setReadPermission(String permission) {
- mReadPermission = permission;
- }
-
- /**
- * Return the name of the permission required for read-only access to
- * this content provider. This method can be called from multiple
- * threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
- * Processes and Threads</a>.
- */
- public final String getReadPermission() {
- return mReadPermission;
- }
-
- /**
- * Change the permission required to read and write data in the content
- * provider. This is normally set for you from its manifest information
- * when the provider is first created.
- *
- * @param permission Name of the permission required for read/write access.
- */
- protected final void setWritePermission(String permission) {
- mWritePermission = permission;
- }
-
- /**
- * Return the name of the permission required for read/write access to
- * this content provider. This method can be called from multiple
- * threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
- * Processes and Threads</a>.
- */
- public final String getWritePermission() {
- return mWritePermission;
- }
-
- /**
- * Called when the provider is being started.
- *
- * @return true if the provider was successfully loaded, false otherwise
- */
- public abstract boolean onCreate();
-
- public void onConfigurationChanged(Configuration newConfig) {
- }
-
- public void onLowMemory() {
- }
-
- /**
- * Receives a query request from a client in a local process, and
- * returns a Cursor. This is called internally by the {@link ContentResolver}.
- * This method can be called from multiple
- * threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
- * Processes and Threads</a>.
- * <p>
- * Example client call:<p>
- * <pre>// Request a specific record.
- * Cursor managedCursor = managedQuery(
- Contacts.People.CONTENT_URI.addId(2),
- projection, // Which columns to return.
- null, // WHERE clause.
- People.NAME + " ASC"); // Sort order.</pre>
- * Example implementation:<p>
- * <pre>// SQLiteQueryBuilder is a helper class that creates the
- // proper SQL syntax for us.
- SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
-
- // Set the table we're querying.
- qBuilder.setTables(DATABASE_TABLE_NAME);
-
- // If the query ends in a specific record number, we're
- // being asked for a specific record, so set the
- // WHERE clause in our query.
- if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){
- qBuilder.appendWhere("_id=" + uri.getPathLeafId());
- }
-
- // Make the query.
- Cursor c = qBuilder.query(mDb,
- projection,
- selection,
- selectionArgs,
- groupBy,
- having,
- sortOrder);
- c.setNotificationUri(getContext().getContentResolver(), uri);
- return c;</pre>
- *
- * @param uri The URI to query. This will be the full URI sent by the client;
- * if the client is requesting a specific record, the URI will end in a record number
- * that the implementation should parse and add to a WHERE or HAVING clause, specifying
- * that _id value.
- * @param projection The list of columns to put into the cursor. If
- * null all columns are included.
- * @param selection A selection criteria to apply when filtering rows.
- * If null then all rows are included.
- * @param sortOrder How the rows in the cursor should be sorted.
- * If null then the provider is free to define the sort order.
- * @return a Cursor or null.
- */
- public abstract Cursor query(Uri uri, String[] projection,
- String selection, String[] selectionArgs, String sortOrder);
-
- /**
- * Return the MIME type of the data at the given URI. This should start with
- * <code>vnd.android.cursor.item</code> for a single record,
- * or <code>vnd.android.cursor.dir/</code> for multiple items.
- * This method can be called from multiple
- * threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
- * Processes and Threads</a>.
- *
- * @param uri the URI to query.
- * @return a MIME type string, or null if there is no type.
- */
- public abstract String getType(Uri uri);
-
- /**
- * Implement this to insert a new row.
- * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
- * after inserting.
- * This method can be called from multiple
- * threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
- * Processes and Threads</a>.
- * @param uri The content:// URI of the insertion request.
- * @param values A set of column_name/value pairs to add to the database.
- * @return The URI for the newly inserted item.
- */
- public abstract Uri insert(Uri uri, ContentValues values);
-
- /**
- * Implement this to insert a set of new rows, or the default implementation will
- * iterate over the values and call {@link #insert} on each of them.
- * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
- * after inserting.
- * This method can be called from multiple
- * threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
- * Processes and Threads</a>.
- *
- * @param uri The content:// URI of the insertion request.
- * @param values An array of sets of column_name/value pairs to add to the database.
- * @return The number of values that were inserted.
- */
- public int bulkInsert(Uri uri, ContentValues[] values) {
- int numValues = values.length;
- for (int i = 0; i < numValues; i++) {
- insert(uri, values[i]);
- }
- return numValues;
- }
-
- /**
- * A request to delete one or more rows. The selection clause is applied when performing
- * the deletion, allowing the operation to affect multiple rows in a
- * directory.
- * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyDelete()}
- * after deleting.
- * This method can be called from multiple
- * threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
- * Processes and Threads</a>.
- *
- * <p>The implementation is responsible for parsing out a row ID at the end
- * of the URI, if a specific row is being deleted. That is, the client would
- * pass in <code>content://contacts/people/22</code> and the implementation is
- * responsible for parsing the record number (22) when creating a SQL statement.
- *
- * @param uri The full URI to query, including a row ID (if a specific record is requested).
- * @param selection An optional restriction to apply to rows when deleting.
- * @return The number of rows affected.
- * @throws SQLException
- */
- public abstract int delete(Uri uri, String selection, String[] selectionArgs);
-
- /**
- * Update a content URI. All rows matching the optionally provided selection
- * will have their columns listed as the keys in the values map with the
- * values of those keys.
- * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
- * after updating.
- * This method can be called from multiple
- * threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
- * Processes and Threads</a>.
- *
- * @param uri The URI to query. This can potentially have a record ID if this
- * is an update request for a specific record.
- * @param values A Bundle mapping from column names to new column values (NULL is a
- * valid value).
- * @param selection An optional filter to match rows to update.
- * @return the number of rows affected.
- */
- public abstract int update(Uri uri, ContentValues values, String selection,
- String[] selectionArgs);
-
- /**
- * Open a file blob associated with a content URI.
- * This method can be called from multiple
- * threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
- * Processes and Threads</a>.
- *
- * <p>Returns a
- * ParcelFileDescriptor, from which you can obtain a
- * {@link java.io.FileDescriptor} for use with
- * {@link java.io.FileInputStream}, {@link java.io.FileOutputStream}, etc.
- * This can be used to store large data (such as an image) associated with
- * a particular piece of content.
- *
- * <p>The returned ParcelFileDescriptor is owned by the caller, so it is
- * their responsibility to close it when done. That is, the implementation
- * of this method should create a new ParcelFileDescriptor for each call.
- *
- * @param uri The URI whose file is to be opened.
- * @param mode Access mode for the file. May be "r" for read-only access
- * or "rw" for read and write access.
- *
- * @return Returns a new ParcelFileDescriptor which you can use to access
- * the file.
- *
- * @throws FileNotFoundException Throws FileNotFoundException if there is
- * no file associated with the given URI or the mode is invalid.
- * @throws SecurityException Throws SecurityException if the caller does
- * not have permission to access the file.
- */
- public ParcelFileDescriptor openFile(Uri uri, String mode)
- throws FileNotFoundException {
- throw new FileNotFoundException("No files supported by provider at "
- + uri);
- }
-
- /**
- * Convenience for subclasses that wish to implement {@link #openFile}
- * by looking up a column named "_data" at the given URI.
- *
- * @param uri The URI to be opened.
- * @param mode The file mode.
- *
- * @return Returns a new ParcelFileDescriptor that can be used by the
- * client to access the file.
- */
- protected final ParcelFileDescriptor openFileHelper(Uri uri,
- String mode) throws FileNotFoundException {
- Cursor c = query(uri, new String[]{"_data"}, null, null, null);
- int count = (c != null) ? c.getCount() : 0;
- if (count != 1) {
- // If there is not exactly one result, throw an appropriate
- // exception.
- if (c != null) {
- c.close();
- }
- if (count == 0) {
- throw new FileNotFoundException("No entry for " + uri);
- }
- throw new FileNotFoundException("Multiple items at " + uri);
- }
-
- c.moveToFirst();
- int i = c.getColumnIndex("_data");
- String path = (i >= 0 ? c.getString(i) : null);
- c.close();
- if (path == null) {
- throw new FileNotFoundException("Column _data not found.");
- }
-
- int modeBits;
- if ("r".equals(mode)) {
- modeBits = ParcelFileDescriptor.MODE_READ_ONLY;
- } else if ("rw".equals(mode)) {
- modeBits = ParcelFileDescriptor.MODE_READ_WRITE
- | ParcelFileDescriptor.MODE_CREATE;
- } else {
- throw new FileNotFoundException("Bad mode for " + uri + ": "
- + mode);
- }
- return ParcelFileDescriptor.open(new File(path), modeBits);
- }
-
- /**
- * Get the sync adapter that is to be used by this content provider.
- * This is intended for use by the sync system. If null then this
- * content provider is considered not syncable.
- * This method can be called from multiple
- * threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
- * Processes and Threads</a>.
- *
- * @return the SyncAdapter that is to be used by this ContentProvider, or null
- * if this ContentProvider is not syncable
- * @hide
- */
- public SyncAdapter getSyncAdapter() {
- return null;
- }
-
- /**
- * Returns true if this instance is a temporary content provider.
- * @return true if this instance is a temporary content provider
- */
- protected boolean isTemporary() {
- return false;
- }
-
- /**
- * Returns the Binder object for this provider.
- *
- * @return the Binder object for this provider
- * @hide
- */
- public IContentProvider getIContentProvider() {
- return mTransport;
- }
-
- /**
- * After being instantiated, this is called to tell the content provider
- * about itself.
- *
- * @param context The context this provider is running in
- * @param info Registered information about this content provider
- */
- public void attachInfo(Context context, ProviderInfo info) {
-
- /*
- * Only allow it to be set once, so after the content service gives
- * this to us clients can't change it.
- */
- if (mContext == null) {
- mContext = context;
- if (info != null) {
- setReadPermission(info.readPermission);
- setWritePermission(info.writePermission);
- }
- ContentProvider.this.onCreate();
- }
- }
-}
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
deleted file mode 100644
index ede2c9b..0000000
--- a/core/java/android/content/ContentProviderNative.java
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.database.BulkCursorNative;
-import android.database.BulkCursorToCursorAdaptor;
-import android.database.Cursor;
-import android.database.CursorWindow;
-import android.database.DatabaseUtils;
-import android.database.IBulkCursor;
-import android.database.IContentObserver;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
-import android.os.Parcelable;
-
-import java.io.FileNotFoundException;
-
-/**
- * {@hide}
- */
-abstract public class ContentProviderNative extends Binder implements IContentProvider {
- private static final String TAG = "ContentProvider";
-
- public ContentProviderNative()
- {
- attachInterface(this, descriptor);
- }
-
- /**
- * Cast a Binder object into a content resolver interface, generating
- * a proxy if needed.
- */
- static public IContentProvider asInterface(IBinder obj)
- {
- if (obj == null) {
- return null;
- }
- IContentProvider in =
- (IContentProvider)obj.queryLocalInterface(descriptor);
- if (in != null) {
- return in;
- }
-
- return new ContentProviderProxy(obj);
- }
-
- @Override
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
- throws RemoteException {
- try {
- switch (code) {
- case QUERY_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- Uri url = Uri.CREATOR.createFromParcel(data);
- int num = data.readInt();
- String[] projection = null;
- if (num > 0) {
- projection = new String[num];
- for (int i = 0; i < num; i++) {
- projection[i] = data.readString();
- }
- }
- String selection = data.readString();
- num = data.readInt();
- String[] selectionArgs = null;
- if (num > 0) {
- selectionArgs = new String[num];
- for (int i = 0; i < num; i++) {
- selectionArgs[i] = data.readString();
- }
- }
- String sortOrder = data.readString();
- IContentObserver observer = IContentObserver.Stub.
- asInterface(data.readStrongBinder());
- CursorWindow window = CursorWindow.CREATOR.createFromParcel(data);
-
- IBulkCursor bulkCursor = bulkQuery(url, projection, selection,
- selectionArgs, sortOrder, observer, window);
- reply.writeNoException();
- if (bulkCursor != null) {
- reply.writeStrongBinder(bulkCursor.asBinder());
- } else {
- reply.writeStrongBinder(null);
- }
- return true;
- }
-
- case GET_TYPE_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- Uri url = Uri.CREATOR.createFromParcel(data);
- String type = getType(url);
- reply.writeNoException();
- reply.writeString(type);
-
- return true;
- }
-
- case INSERT_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- Uri url = Uri.CREATOR.createFromParcel(data);
- ContentValues values = ContentValues.CREATOR.createFromParcel(data);
-
- Uri out = insert(url, values);
- reply.writeNoException();
- Uri.writeToParcel(reply, out);
- return true;
- }
-
- case BULK_INSERT_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- Uri url = Uri.CREATOR.createFromParcel(data);
- ContentValues[] values = data.createTypedArray(ContentValues.CREATOR);
-
- int count = bulkInsert(url, values);
- reply.writeNoException();
- reply.writeInt(count);
- return true;
- }
-
- case DELETE_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- Uri url = Uri.CREATOR.createFromParcel(data);
- String selection = data.readString();
- String[] selectionArgs = data.readStringArray();
-
- int count = delete(url, selection, selectionArgs);
-
- reply.writeNoException();
- reply.writeInt(count);
- return true;
- }
-
- case UPDATE_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- Uri url = Uri.CREATOR.createFromParcel(data);
- ContentValues values = ContentValues.CREATOR.createFromParcel(data);
- String selection = data.readString();
- String[] selectionArgs = data.readStringArray();
-
- int count = update(url, values, selection, selectionArgs);
-
- reply.writeNoException();
- reply.writeInt(count);
- return true;
- }
-
- case OPEN_FILE_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- Uri url = Uri.CREATOR.createFromParcel(data);
- String mode = data.readString();
-
- ParcelFileDescriptor fd;
- fd = openFile(url, mode);
- reply.writeNoException();
- if (fd != null) {
- reply.writeInt(1);
- fd.writeToParcel(reply,
- Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- } else {
- reply.writeInt(0);
- }
- return true;
- }
-
- case GET_SYNC_ADAPTER_TRANSACTION:
- {
- data.enforceInterface(IContentProvider.descriptor);
- ISyncAdapter sa = getSyncAdapter();
- reply.writeNoException();
- reply.writeStrongBinder(sa != null ? sa.asBinder() : null);
- return true;
- }
- }
- } catch (Exception e) {
- DatabaseUtils.writeExceptionToParcel(reply, e);
- return true;
- }
-
- return super.onTransact(code, data, reply, flags);
- }
-
- public IBinder asBinder()
- {
- return this;
- }
-}
-
-
-final class ContentProviderProxy implements IContentProvider
-{
- public ContentProviderProxy(IBinder remote)
- {
- mRemote = remote;
- }
-
- public IBinder asBinder()
- {
- return mRemote;
- }
-
- public IBulkCursor bulkQuery(Uri url, String[] projection,
- String selection, String[] selectionArgs, String sortOrder, IContentObserver observer,
- CursorWindow window) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IContentProvider.descriptor);
-
- url.writeToParcel(data, 0);
- int length = 0;
- if (projection != null) {
- length = projection.length;
- }
- data.writeInt(length);
- for (int i = 0; i < length; i++) {
- data.writeString(projection[i]);
- }
- data.writeString(selection);
- if (selectionArgs != null) {
- length = selectionArgs.length;
- } else {
- length = 0;
- }
- data.writeInt(length);
- for (int i = 0; i < length; i++) {
- data.writeString(selectionArgs[i]);
- }
- data.writeString(sortOrder);
- data.writeStrongBinder(observer.asBinder());
- window.writeToParcel(data, 0);
-
- mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
-
- IBulkCursor bulkCursor = null;
- IBinder bulkCursorBinder = reply.readStrongBinder();
- if (bulkCursorBinder != null) {
- bulkCursor = BulkCursorNative.asInterface(bulkCursorBinder);
- }
-
- data.recycle();
- reply.recycle();
-
- return bulkCursor;
- }
-
- public Cursor query(Uri url, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) throws RemoteException {
- //TODO make a pool of windows so we can reuse memory dealers
- CursorWindow window = new CursorWindow(false /* window will be used remotely */);
- BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
- IBulkCursor bulkCursor = bulkQuery(url, projection, selection, selectionArgs, sortOrder,
- adaptor.getObserver(), window);
-
- if (bulkCursor == null) {
- return null;
- }
- adaptor.set(bulkCursor);
- return adaptor;
- }
-
- public String getType(Uri url) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IContentProvider.descriptor);
-
- url.writeToParcel(data, 0);
-
- mRemote.transact(IContentProvider.GET_TYPE_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
- String out = reply.readString();
-
- data.recycle();
- reply.recycle();
-
- return out;
- }
-
- public Uri insert(Uri url, ContentValues values) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IContentProvider.descriptor);
-
- url.writeToParcel(data, 0);
- values.writeToParcel(data, 0);
-
- mRemote.transact(IContentProvider.INSERT_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
- Uri out = Uri.CREATOR.createFromParcel(reply);
-
- data.recycle();
- reply.recycle();
-
- return out;
- }
-
- public int bulkInsert(Uri url, ContentValues[] values) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IContentProvider.descriptor);
-
- url.writeToParcel(data, 0);
- data.writeTypedArray(values, 0);
-
- mRemote.transact(IContentProvider.BULK_INSERT_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
- int count = reply.readInt();
-
- data.recycle();
- reply.recycle();
-
- return count;
- }
-
- public int delete(Uri url, String selection, String[] selectionArgs)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IContentProvider.descriptor);
-
- url.writeToParcel(data, 0);
- data.writeString(selection);
- data.writeStringArray(selectionArgs);
-
- mRemote.transact(IContentProvider.DELETE_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
- int count = reply.readInt();
-
- data.recycle();
- reply.recycle();
-
- return count;
- }
-
- public int update(Uri url, ContentValues values, String selection,
- String[] selectionArgs) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IContentProvider.descriptor);
-
- url.writeToParcel(data, 0);
- values.writeToParcel(data, 0);
- data.writeString(selection);
- data.writeStringArray(selectionArgs);
-
- mRemote.transact(IContentProvider.UPDATE_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
- int count = reply.readInt();
-
- data.recycle();
- reply.recycle();
-
- return count;
- }
-
- public ParcelFileDescriptor openFile(Uri url, String mode)
- throws RemoteException, FileNotFoundException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IContentProvider.descriptor);
-
- url.writeToParcel(data, 0);
- data.writeString(mode);
-
- mRemote.transact(IContentProvider.OPEN_FILE_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
- int has = reply.readInt();
- ParcelFileDescriptor fd = has != 0 ? reply.readFileDescriptor() : null;
-
- data.recycle();
- reply.recycle();
-
- return fd;
- }
-
- public ISyncAdapter getSyncAdapter() throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IContentProvider.descriptor);
-
- mRemote.transact(IContentProvider.GET_SYNC_ADAPTER_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
- ISyncAdapter syncAdapter = ISyncAdapter.Stub.asInterface(reply.readStrongBinder());
-
- data.recycle();
- reply.recycle();
-
- return syncAdapter;
- }
-
- private IBinder mRemote;
-}
-
diff --git a/core/java/android/content/ContentQueryMap.java b/core/java/android/content/ContentQueryMap.java
deleted file mode 100644
index dbcb4a7..0000000
--- a/core/java/android/content/ContentQueryMap.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.os.Handler;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Observable;
-
-/**
- * Caches the contents of a cursor into a Map of String->ContentValues and optionally
- * keeps the cache fresh by registering for updates on the content backing the cursor. The column of
- * the database that is to be used as the key of the map is user-configurable, and the
- * ContentValues contains all columns other than the one that is designated the key.
- * <p>
- * The cursor data is accessed by row key and column name via getValue().
- */
-public class ContentQueryMap extends Observable {
- private Cursor mCursor;
- private String[] mColumnNames;
- private int mKeyColumn;
-
- private Handler mHandlerForUpdateNotifications = null;
- private boolean mKeepUpdated = false;
-
- private Map<String, ContentValues> mValues = null;
-
- private ContentObserver mContentObserver;
-
- /** Set when a cursor change notification is received and is cleared on a call to requery(). */
- private boolean mDirty = false;
-
- /**
- * Creates a ContentQueryMap that caches the content backing the cursor
- *
- * @param cursor the cursor whose contents should be cached
- * @param columnNameOfKey the column that is to be used as the key of the values map
- * @param keepUpdated true if the cursor's ContentProvider should be monitored for changes and
- * the map updated when changes do occur
- * @param handlerForUpdateNotifications the Handler that should be used to receive
- * notifications of changes (if requested). Normally you pass null here, but if
- * you know that the thread that is creating this isn't a thread that can receive
- * messages then you can create your own handler and use that here.
- */
- public ContentQueryMap(Cursor cursor, String columnNameOfKey, boolean keepUpdated,
- Handler handlerForUpdateNotifications) {
- mCursor = cursor;
- mColumnNames = mCursor.getColumnNames();
- mKeyColumn = mCursor.getColumnIndexOrThrow(columnNameOfKey);
- mHandlerForUpdateNotifications = handlerForUpdateNotifications;
- setKeepUpdated(keepUpdated);
-
- // If we aren't keeping the cache updated with the current state of the cursor's
- // ContentProvider then read it once into the cache. Otherwise the cache will be filled
- // automatically.
- if (!keepUpdated) {
- readCursorIntoCache();
- }
- }
-
- /**
- * Change whether or not the ContentQueryMap will register with the cursor's ContentProvider
- * for change notifications. If you use a ContentQueryMap in an activity you should call this
- * with false in onPause(), which means you need to call it with true in onResume()
- * if want it to be kept updated.
- * @param keepUpdated if true the ContentQueryMap should be registered with the cursor's
- * ContentProvider, false otherwise
- */
- public void setKeepUpdated(boolean keepUpdated) {
- if (keepUpdated == mKeepUpdated) return;
- mKeepUpdated = keepUpdated;
-
- if (!mKeepUpdated) {
- mCursor.unregisterContentObserver(mContentObserver);
- mContentObserver = null;
- } else {
- if (mHandlerForUpdateNotifications == null) {
- mHandlerForUpdateNotifications = new Handler();
- }
- if (mContentObserver == null) {
- mContentObserver = new ContentObserver(mHandlerForUpdateNotifications) {
- @Override
- public void onChange(boolean selfChange) {
- // If anyone is listening, we need to do this now to broadcast
- // to the observers. Otherwise, we'll just set mDirty and
- // let it query lazily when they ask for the values.
- if (countObservers() != 0) {
- requery();
- } else {
- mDirty = true;
- }
- }
- };
- }
- mCursor.registerContentObserver(mContentObserver);
- // mark dirty, since it is possible the cursor's backing data had changed before we
- // registered for changes
- mDirty = true;
- }
- }
-
- /**
- * Access the ContentValues for the row specified by rowName
- * @param rowName which row to read
- * @return the ContentValues for the row, or null if the row wasn't present in the cursor
- */
- public synchronized ContentValues getValues(String rowName) {
- if (mDirty) requery();
- return mValues.get(rowName);
- }
-
- /** Requeries the cursor and reads the contents into the cache */
- public void requery() {
- mDirty = false;
- mCursor.requery();
- readCursorIntoCache();
- setChanged();
- notifyObservers();
- }
-
- private synchronized void readCursorIntoCache() {
- // Make a new map so old values returned by getRows() are undisturbed.
- int capacity = mValues != null ? mValues.size() : 0;
- mValues = new HashMap<String, ContentValues>(capacity);
- while (mCursor.moveToNext()) {
- ContentValues values = new ContentValues();
- for (int i = 0; i < mColumnNames.length; i++) {
- if (i != mKeyColumn) {
- values.put(mColumnNames[i], mCursor.getString(i));
- }
- }
- mValues.put(mCursor.getString(mKeyColumn), values);
- }
- }
-
- public synchronized Map<String, ContentValues> getRows() {
- if (mDirty) requery();
- return mValues;
- }
-
- public synchronized void close() {
- if (mContentObserver != null) {
- mCursor.unregisterContentObserver(mContentObserver);
- mContentObserver = null;
- }
- mCursor.close();
- mCursor = null;
- }
-
- @Override
- protected void finalize() throws Throwable {
- if (mCursor != null) close();
- super.finalize();
- }
-}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
deleted file mode 100644
index 52f55b6..0000000
--- a/core/java/android/content/ContentResolver.java
+++ /dev/null
@@ -1,644 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.database.CursorWrapper;
-import android.database.IContentObserver;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.text.TextUtils;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.List;
-
-
-/**
- * This class provides applications access to the content model.
- */
-public abstract class ContentResolver {
- public final static String SYNC_EXTRAS_ACCOUNT = "account";
- public static final String SYNC_EXTRAS_EXPEDITED = "expedited";
- public static final String SYNC_EXTRAS_FORCE = "force";
- public static final String SYNC_EXTRAS_UPLOAD = "upload";
- public static final String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override";
- public static final String SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS = "discard_deletions";
-
- public static final String SCHEME_CONTENT = "content";
- public static final String SCHEME_ANDROID_RESOURCE = "android.resource";
- public static final String SCHEME_FILE = "file";
-
- /**
- * This is the Android platform's base MIME type for a content: URI
- * containing a Cursor of a single item. Applications should use this
- * as the base type along with their own sub-type of their content: URIs
- * that represent a particular item. For example, hypothetical IMAP email
- * client may have a URI
- * <code>content://com.company.provider.imap/inbox/1</code> for a particular
- * message in the inbox, whose MIME type would be reported as
- * <code>CURSOR_ITEM_BASE_TYPE + "/vnd.company.imap-msg"</code>
- *
- * <p>Compare with {@link #CURSOR_DIR_BASE_TYPE}.
- */
- public static final String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
-
- /**
- * This is the Android platform's base MIME type for a content: URI
- * containing a Cursor of zero or more items. Applications should use this
- * as the base type along with their own sub-type of their content: URIs
- * that represent a directory of items. For example, hypothetical IMAP email
- * client may have a URI
- * <code>content://com.company.provider.imap/inbox</code> for all of the
- * messages in its inbox, whose MIME type would be reported as
- * <code>CURSOR_DIR_BASE_TYPE + "/vnd.company.imap-msg"</code>
- *
- * <p>Note how the base MIME type varies between this and
- * {@link #CURSOR_ITEM_BASE_TYPE} depending on whether there is
- * one single item or multiple items in the data set, while the sub-type
- * remains the same because in either case the data structure contained
- * in the cursor is the same.
- */
- public static final String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
-
- public ContentResolver(Context context)
- {
- mContext = context;
- }
-
- /** @hide */
- protected abstract IContentProvider acquireProvider(Context c, String name);
- /** @hide */
- public abstract boolean releaseProvider(IContentProvider icp);
-
- /**
- * Return the MIME type of the given content URL.
- *
- * @param url A Uri identifying content (either a list or specific type),
- * using the content:// scheme.
- * @return A MIME type for the content, or null if the URL is invalid or the type is unknown
- */
- public final String getType(Uri url)
- {
- IContentProvider provider = acquireProvider(url);
- if (provider == null) {
- return null;
- }
- try {
- return provider.getType(url);
- } catch (RemoteException e) {
- return null;
- } catch (java.lang.Exception e) {
- return null;
- } finally {
- releaseProvider(provider);
- }
- }
-
- /**
- * Query the given URI, returning a {@link Cursor} over the result set.
- *
- * @param uri The URI, using the content:// scheme, for the content to
- * retrieve.
- * @param projection A list of which columns to return. Passing null will
- * return all columns, which is discouraged to prevent reading data
- * from storage that isn't going to be used.
- * @param selection A filter declaring which rows to return, formatted as an
- * SQL WHERE clause (excluding the WHERE itself). Passing null will
- * return all rows for the given URI.
- * @param selectionArgs You may include ?s in selection, which will be
- * replaced by the values from selectionArgs, in the order that they
- * appear in the selection. The values will be bound as Strings.
- * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
- * clause (excluding the ORDER BY itself). Passing null will use the
- * default sort order, which may be unordered.
- * @return A Cursor object, which is positioned before the first entry, or null
- * @see Cursor
- */
- public final Cursor query(Uri uri, String[] projection,
- String selection, String[] selectionArgs, String sortOrder) {
- IContentProvider provider = acquireProvider(uri);
- if (provider == null) {
- return null;
- }
- try {
- Cursor qCursor = provider.query(uri, projection, selection, selectionArgs, sortOrder);
- if(qCursor == null) {
- releaseProvider(provider);
- return null;
- }
- //Wrap the cursor object into CursorWrapperInner object
- return new CursorWrapperInner(qCursor, provider);
- } catch (RemoteException e) {
- releaseProvider(provider);
- return null;
- } catch(RuntimeException e) {
- releaseProvider(provider);
- throw e;
- }
- }
-
- /**
- * Open a stream on to the content associated with a content URI. If there
- * is no data associated with the URI, FileNotFoundException is thrown.
- *
- * <h5>Accepts the following URI schemes:</h5>
- * <ul>
- * <li>content ({@link #SCHEME_CONTENT})</li>
- * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li>
- * <li>file ({@link #SCHEME_FILE})</li>
- * </ul>
- * <h5>The android.resource ({@link #SCHEME_ANDROID_RESOURCE}) Scheme</h5>
- * <p>
- * A Uri object can be used to reference a resource in an APK file. The
- * Uri should be one of the following formats:
- * <ul>
- * <li><code>android.resource://package_name/id_number</code><br/>
- * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
- * For example <code>com.example.myapp</code><br/>
- * <code>id_number</code> is the int form of the ID.<br/>
- * The easiest way to construct this form is
- * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/" + R.raw.my_resource");</pre>
- * </li>
- * <li><code>android.resource://package_name/type/name</code><br/>
- * <code>package_name</code> is your package name as listed in your AndroidManifest.xml.
- * For example <code>com.example.myapp</code><br/>
- * <code>type</code> is the string form of the resource type. For example, <code>raw</code>
- * or <code>drawable</code>.
- * <code>name</code> is the string form of the resource name. That is, whatever the file
- * name was in your res directory, without the type extension.
- * The easiest way to construct this form is
- * <pre>Uri uri = Uri.parse("android.resource://com.example.myapp/raw/my_resource");</pre>
- * </li>
- * </ul>
- * @param uri The desired "content:" URI.
- * @return InputStream
- * @throws FileNotFoundException if the provided URI could not be opened.
- */
- public final InputStream openInputStream(Uri uri)
- throws FileNotFoundException {
- String scheme = uri.getScheme();
- if (SCHEME_CONTENT.equals(scheme)) {
- ParcelFileDescriptor fd = openFileDescriptor(uri, "r");
- return fd != null ? new ParcelFileDescriptor.AutoCloseInputStream(fd) : null;
- } else if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
- String authority = uri.getAuthority();
- Resources r;
- if (TextUtils.isEmpty(authority)) {
- throw new FileNotFoundException("No authority: " + uri);
- } else {
- try {
- r = mContext.getPackageManager().getResourcesForApplication(authority);
- } catch (NameNotFoundException ex) {
- throw new FileNotFoundException("No package found for authority: " + uri);
- }
- }
- List<String> path = uri.getPathSegments();
- if (path == null) {
- throw new FileNotFoundException("No path: " + uri);
- }
- int len = path.size();
- int id;
- if (len == 1) {
- try {
- id = Integer.parseInt(path.get(0));
- } catch (NumberFormatException e) {
- throw new FileNotFoundException("Single path segment is not a resource ID: " + uri);
- }
- } else if (len == 2) {
- id = r.getIdentifier(path.get(1), path.get(0), authority);
- } else {
- throw new FileNotFoundException("More than two path segments: " + uri);
- }
- if (id == 0) {
- throw new FileNotFoundException("No resource found for: " + uri);
- }
- try {
- InputStream stream = r.openRawResource(id);
- return stream;
- } catch (Resources.NotFoundException ex) {
- throw new FileNotFoundException("Resource ID does not exist: " + uri);
- }
- } else if (SCHEME_FILE.equals(scheme)) {
- return new FileInputStream(uri.getPath());
- } else {
- throw new FileNotFoundException("Unknown scheme: " + uri);
- }
- }
-
- /**
- * Open a stream on to the content associated with a content URI. If there
- * is no data associated with the URI, FileNotFoundException is thrown.
- *
- * <h5>Accepts the following URI schemes:</h5>
- * <ul>
- * <li>content ({@link #SCHEME_CONTENT})</li>
- * </ul>
- *
- * @param uri The desired "content:" URI.
- * @return OutputStream
- */
- public final OutputStream openOutputStream(Uri uri)
- throws FileNotFoundException {
- String scheme = uri.getScheme();
- if (SCHEME_CONTENT.equals(scheme)) {
- ParcelFileDescriptor fd = openFileDescriptor(uri, "rw");
- return fd != null
- ? new ParcelFileDescriptor.AutoCloseOutputStream(fd) : null;
- } else {
- throw new FileNotFoundException("Unknown scheme: " + uri);
- }
- }
-
- /**
- * Open a raw file descriptor to access data under a "content:" URI. This
- * interacts with the underlying {@link ContentProvider#openFile}
- * ContentProvider.openFile()} method of the provider associated with the
- * given URI, to retrieve any file stored there.
- *
- * <h5>Accepts the following URI schemes:</h5>
- * <ul>
- * <li>content ({@link #SCHEME_CONTENT})</li>
- * </ul>
- *
- * @param uri The desired URI to open.
- * @param mode The file mode to use, as per {@link ContentProvider#openFile
- * ContentProvider.openFile}.
- * @return Returns a new ParcelFileDescriptor pointing to the file. You
- * own this descriptor and are responsible for closing it when done.
- * @throws FileNotFoundException Throws FileNotFoundException of no
- * file exists under the URI or the mode is invalid.
- */
- public final ParcelFileDescriptor openFileDescriptor(Uri uri,
- String mode) throws FileNotFoundException {
- IContentProvider provider = acquireProvider(uri);
- if (provider == null) {
- throw new FileNotFoundException("No content provider: " + uri);
- }
- try {
- ParcelFileDescriptor fd = provider.openFile(uri, mode);
- if(fd == null) {
- releaseProvider(provider);
- return null;
- }
- return new ParcelFileDescriptorInner(fd, provider);
- } catch (RemoteException e) {
- releaseProvider(provider);
- throw new FileNotFoundException("Dead content provider: " + uri);
- } catch (FileNotFoundException e) {
- releaseProvider(provider);
- throw e;
- } catch (RuntimeException e) {
- releaseProvider(provider);
- throw e;
- }
- }
-
- /**
- * Inserts a row into a table at the given URL.
- *
- * If the content provider supports transactions the insertion will be atomic.
- *
- * @param url The URL of the table to insert into.
- * @param values The initial values for the newly inserted row. The key is the column name for
- * the field. Passing an empty ContentValues will create an empty row.
- * @return the URL of the newly created row.
- */
- public final Uri insert(Uri url, ContentValues values)
- {
- IContentProvider provider = acquireProvider(url);
- if (provider == null) {
- throw new IllegalArgumentException("Unknown URL " + url);
- }
- try {
- return provider.insert(url, values);
- } catch (RemoteException e) {
- return null;
- } finally {
- releaseProvider(provider);
- }
- }
-
- /**
- * Inserts multiple rows into a table at the given URL.
- *
- * This function make no guarantees about the atomicity of the insertions.
- *
- * @param url The URL of the table to insert into.
- * @param values The initial values for the newly inserted rows. The key is the column name for
- * the field. Passing null will create an empty row.
- * @return the number of newly created rows.
- */
- public final int bulkInsert(Uri url, ContentValues[] values)
- {
- IContentProvider provider = acquireProvider(url);
- if (provider == null) {
- throw new IllegalArgumentException("Unknown URL " + url);
- }
- try {
- return provider.bulkInsert(url, values);
- } catch (RemoteException e) {
- return 0;
- } finally {
- releaseProvider(provider);
- }
- }
-
- /**
- * Deletes row(s) specified by a content URI.
- *
- * If the content provider supports transactions, the deletion will be atomic.
- *
- * @param url The URL of the row to delete.
- * @param where A filter to apply to rows before deleting, formatted as an SQL WHERE clause
- (excluding the WHERE itself).
- * @return The number of rows deleted.
- */
- public final int delete(Uri url, String where, String[] selectionArgs)
- {
- IContentProvider provider = acquireProvider(url);
- if (provider == null) {
- throw new IllegalArgumentException("Unknown URL " + url);
- }
- try {
- return provider.delete(url, where, selectionArgs);
- } catch (RemoteException e) {
- return -1;
- } finally {
- releaseProvider(provider);
- }
- }
-
- /**
- * Update row(s) in a content URI.
- *
- * If the content provider supports transactions the update will be atomic.
- *
- * @param uri The URI to modify.
- * @param values The new field values. The key is the column name for the field.
- A null value will remove an existing field value.
- * @param where A filter to apply to rows before deleting, formatted as an SQL WHERE clause
- (excluding the WHERE itself).
- * @return the URL of the newly created row
- * @throws NullPointerException if uri or values are null
- */
- public final int update(Uri uri, ContentValues values, String where,
- String[] selectionArgs) {
- IContentProvider provider = acquireProvider(uri);
- if (provider == null) {
- throw new IllegalArgumentException("Unknown URI " + uri);
- }
- try {
- return provider.update(uri, values, where, selectionArgs);
- } catch (RemoteException e) {
- return -1;
- } finally {
- releaseProvider(provider);
- }
- }
-
- /**
- * Returns the content provider for the given content URI..
- *
- * @param uri The URI to a content provider
- * @return The ContentProvider for the given URI, or null if no content provider is found.
- * @hide
- */
- public final IContentProvider acquireProvider(Uri uri)
- {
- if (!SCHEME_CONTENT.equals(uri.getScheme())) {
- return null;
- }
- String auth = uri.getAuthority();
- if (auth != null) {
- return acquireProvider(mContext, uri.getAuthority());
- }
- return null;
- }
-
- /**
- * @hide
- */
- public final IContentProvider acquireProvider(String name) {
- if(name == null) {
- return null;
- }
- return acquireProvider(mContext, name);
- }
-
- /**
- * Register an observer class that gets callbacks when data identified by a
- * given content URI changes.
- *
- * @param uri The URI to watch for changes. This can be a specific row URI, or a base URI
- * for a whole class of content.
- * @param notifyForDescendents If <code>true</code> changes to URIs beginning with <code>uri</code>
- * will also cause notifications to be sent. If <code>false</code> only changes to the exact URI
- * specified by <em>uri</em> will cause notifications to be sent. If true, than any URI values
- * at or below the specified URI will also trigger a match.
- * @param observer The object that receives callbacks when changes occur.
- * @see #unregisterContentObserver
- */
- public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
- ContentObserver observer)
- {
- try {
- ContentServiceNative.getDefault().registerContentObserver(uri, notifyForDescendents,
- observer.getContentObserver());
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Unregisters a change observer.
- *
- * @param observer The previously registered observer that is no longer needed.
- * @see #registerContentObserver
- */
- public final void unregisterContentObserver(ContentObserver observer) {
- try {
- IContentObserver contentObserver = observer.releaseContentObserver();
- if (contentObserver != null) {
- ContentServiceNative.getDefault().unregisterContentObserver(
- contentObserver);
- }
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Notify registered observers that a row was updated.
- * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}.
- * By default, CursorAdapter objects will get this notification.
- *
- * @param uri
- * @param observer The observer that originated the change, may be <code>null</null>
- */
- public void notifyChange(Uri uri, ContentObserver observer) {
- notifyChange(uri, observer, true /* sync to network */);
- }
-
- /**
- * Notify registered observers that a row was updated.
- * To register, call {@link #registerContentObserver(android.net.Uri , boolean, android.database.ContentObserver) registerContentObserver()}.
- * By default, CursorAdapter objects will get this notification.
- *
- * @param uri
- * @param observer The observer that originated the change, may be <code>null</null>
- * @param syncToNetwork If true, attempt to sync the change to the network.
- */
- public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
- try {
- ContentServiceNative.getDefault().notifyChange(
- uri, observer == null ? null : observer.getContentObserver(),
- observer != null && observer.deliverSelfNotifications(), syncToNetwork);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Start an asynchronous sync operation. If you want to monitor the progress
- * of the sync you may register a SyncObserver. Only values of the following
- * types may be used in the extras bundle:
- * <ul>
- * <li>Integer</li>
- * <li>Long</li>
- * <li>Boolean</li>
- * <li>Float</li>
- * <li>Double</li>
- * <li>String</li>
- * </ul>
- *
- * @param uri the uri of the provider to sync or null to sync all providers.
- * @param extras any extras to pass to the SyncAdapter.
- */
- public void startSync(Uri uri, Bundle extras) {
- validateSyncExtrasBundle(extras);
- try {
- ContentServiceNative.getDefault().startSync(uri, extras);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Check that only values of the following types are in the Bundle:
- * <ul>
- * <li>Integer</li>
- * <li>Long</li>
- * <li>Boolean</li>
- * <li>Float</li>
- * <li>Double</li>
- * <li>String</li>
- * <li>null</li>
- * </ul>
- * @param extras the Bundle to check
- */
- public static void validateSyncExtrasBundle(Bundle extras) {
- try {
- for (String key : extras.keySet()) {
- Object value = extras.get(key);
- if (value == null) continue;
- if (value instanceof Long) continue;
- if (value instanceof Integer) continue;
- if (value instanceof Boolean) continue;
- if (value instanceof Float) continue;
- if (value instanceof Double) continue;
- if (value instanceof String) continue;
- throw new IllegalArgumentException("unexpected value type: "
- + value.getClass().getName());
- }
- } catch (IllegalArgumentException e) {
- throw e;
- } catch (RuntimeException exc) {
- throw new IllegalArgumentException("error unparceling Bundle", exc);
- }
- }
-
- public void cancelSync(Uri uri) {
- try {
- ContentServiceNative.getDefault().cancelSync(uri);
- } catch (RemoteException e) {
- }
- }
-
- private final class CursorWrapperInner extends CursorWrapper {
- private IContentProvider mContentProvider;
- public static final String TAG="CursorWrapperInner";
- private boolean mCloseFlag = false;
-
- CursorWrapperInner(Cursor cursor, IContentProvider icp) {
- super(cursor);
- mContentProvider = icp;
- }
-
- @Override
- public void close() {
- super.close();
- ContentResolver.this.releaseProvider(mContentProvider);
- mCloseFlag = true;
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- if(!mCloseFlag) {
- ContentResolver.this.releaseProvider(mContentProvider);
- }
- } finally {
- super.finalize();
- }
- }
- }
-
- private final class ParcelFileDescriptorInner extends ParcelFileDescriptor {
- private IContentProvider mContentProvider;
- public static final String TAG="ParcelFileDescriptorInner";
- private boolean mReleaseProviderFlag = false;
-
- ParcelFileDescriptorInner(ParcelFileDescriptor pfd, IContentProvider icp) {
- super(pfd);
- mContentProvider = icp;
- }
-
- @Override
- public void close() throws IOException {
- if(!mReleaseProviderFlag) {
- super.close();
- ContentResolver.this.releaseProvider(mContentProvider);
- mReleaseProviderFlag = true;
- }
- }
-
- @Override
- protected void finalize() throws Throwable {
- if (!mReleaseProviderFlag) {
- close();
- }
- }
- }
-
- private final Context mContext;
- private static final String TAG = "ContentResolver";
-}
diff --git a/core/java/android/content/ContentService.java b/core/java/android/content/ContentService.java
deleted file mode 100644
index b028868..0000000
--- a/core/java/android/content/ContentService.java
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.database.IContentObserver;
-import android.database.sqlite.SQLiteException;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.Config;
-import android.util.Log;
-import android.Manifest;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-
-/**
- * {@hide}
- */
-public final class ContentService extends ContentServiceNative {
- private static final String TAG = "ContentService";
- private Context mContext;
- private boolean mFactoryTest;
- private final ObserverNode mRootNode = new ObserverNode("");
- private SyncManager mSyncManager = null;
- private final Object mSyncManagerLock = new Object();
-
- private SyncManager getSyncManager() {
- synchronized(mSyncManagerLock) {
- try {
- // Try to create the SyncManager, return null if it fails (e.g. the disk is full).
- if (mSyncManager == null) mSyncManager = new SyncManager(mContext, mFactoryTest);
- } catch (SQLiteException e) {
- Log.e(TAG, "Can't create SyncManager", e);
- }
- return mSyncManager;
- }
- }
-
- @Override
- protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.DUMP,
- "caller doesn't have the DUMP permission");
-
- // This makes it so that future permission checks will be in the context of this
- // process rather than the caller's process. We will restore this before returning.
- long identityToken = clearCallingIdentity();
- try {
- if (mSyncManager == null) {
- pw.println("No SyncManager created! (Disk full?)");
- } else {
- mSyncManager.dump(fd, pw);
- }
- } finally {
- restoreCallingIdentity(identityToken);
- }
- }
-
- /*package*/ ContentService(Context context, boolean factoryTest) {
- mContext = context;
- mFactoryTest = factoryTest;
- getSyncManager();
- }
-
- public void registerContentObserver(Uri uri, boolean notifyForDescendents,
- IContentObserver observer) {
- if (observer == null || uri == null) {
- throw new IllegalArgumentException("You must pass a valid uri and observer");
- }
- synchronized (mRootNode) {
- mRootNode.addObserver(uri, observer, notifyForDescendents);
- if (Config.LOGV) Log.v(TAG, "Registered observer " + observer + " at " + uri +
- " with notifyForDescendents " + notifyForDescendents);
- }
- }
-
- public void unregisterContentObserver(IContentObserver observer) {
- if (observer == null) {
- throw new IllegalArgumentException("You must pass a valid observer");
- }
- synchronized (mRootNode) {
- mRootNode.removeObserver(observer);
- if (Config.LOGV) Log.v(TAG, "Unregistered observer " + observer);
- }
- }
-
- public void notifyChange(Uri uri, IContentObserver observer,
- boolean observerWantsSelfNotifications, boolean syncToNetwork) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Notifying update of " + uri + " from observer " + observer
- + ", syncToNetwork " + syncToNetwork);
- }
- // This makes it so that future permission checks will be in the context of this
- // process rather than the caller's process. We will restore this before returning.
- long identityToken = clearCallingIdentity();
- try {
- ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
- synchronized (mRootNode) {
- mRootNode.collectObservers(uri, 0, observer, observerWantsSelfNotifications,
- calls);
- }
- final int numCalls = calls.size();
- for (int i=0; i<numCalls; i++) {
- ObserverCall oc = calls.get(i);
- try {
- oc.mObserver.onChange(oc.mSelfNotify);
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri);
- }
- } catch (RemoteException ex) {
- synchronized (mRootNode) {
- Log.w(TAG, "Found dead observer, removing");
- IBinder binder = oc.mObserver.asBinder();
- final ArrayList<ObserverNode.ObserverEntry> list
- = oc.mNode.mObservers;
- int numList = list.size();
- for (int j=0; j<numList; j++) {
- ObserverNode.ObserverEntry oe = list.get(j);
- if (oe.observer.asBinder() == binder) {
- list.remove(j);
- j--;
- numList--;
- }
- }
- }
- }
- }
- if (syncToNetwork) {
- SyncManager syncManager = getSyncManager();
- if (syncManager != null) syncManager.scheduleLocalSync(uri);
- }
- } finally {
- restoreCallingIdentity(identityToken);
- }
- }
-
- /**
- * Hide this class since it is not part of api,
- * but current unittest framework requires it to be public
- * @hide
- *
- */
- public static final class ObserverCall {
- final ObserverNode mNode;
- final IContentObserver mObserver;
- final boolean mSelfNotify;
-
- ObserverCall(ObserverNode node, IContentObserver observer,
- boolean selfNotify) {
- mNode = node;
- mObserver = observer;
- mSelfNotify = selfNotify;
- }
- }
-
- public void startSync(Uri url, Bundle extras) {
- ContentResolver.validateSyncExtrasBundle(extras);
- // This makes it so that future permission checks will be in the context of this
- // process rather than the caller's process. We will restore this before returning.
- long identityToken = clearCallingIdentity();
- try {
- SyncManager syncManager = getSyncManager();
- if (syncManager != null) syncManager.startSync(url, extras);
- } finally {
- restoreCallingIdentity(identityToken);
- }
- }
-
- /**
- * Clear all scheduled sync operations that match the uri and cancel the active sync
- * if it matches the uri. If the uri is null, clear all scheduled syncs and cancel
- * the active one, if there is one.
- * @param uri Filter on the sync operations to cancel, or all if null.
- */
- public void cancelSync(Uri uri) {
- // This makes it so that future permission checks will be in the context of this
- // process rather than the caller's process. We will restore this before returning.
- long identityToken = clearCallingIdentity();
- try {
- SyncManager syncManager = getSyncManager();
- if (syncManager != null) {
- syncManager.clearScheduledSyncOperations(uri);
- syncManager.cancelActiveSync(uri);
- }
- } finally {
- restoreCallingIdentity(identityToken);
- }
- }
-
- public static IContentService main(Context context, boolean factoryTest) {
- ContentService service = new ContentService(context, factoryTest);
- ServiceManager.addService("content", service);
- return service;
- }
-
- /**
- * Hide this class since it is not part of api,
- * but current unittest framework requires it to be public
- * @hide
- */
- public static final class ObserverNode {
- private class ObserverEntry implements IBinder.DeathRecipient {
- public IContentObserver observer;
- public boolean notifyForDescendents;
-
- public ObserverEntry(IContentObserver o, boolean n) {
- observer = o;
- notifyForDescendents = n;
- try {
- observer.asBinder().linkToDeath(this, 0);
- } catch (RemoteException e) {
- binderDied();
- }
- }
-
- public void binderDied() {
- removeObserver(observer);
- }
- }
-
- public static final int INSERT_TYPE = 0;
- public static final int UPDATE_TYPE = 1;
- public static final int DELETE_TYPE = 2;
-
- private String mName;
- private ArrayList<ObserverNode> mChildren = new ArrayList<ObserverNode>();
- private ArrayList<ObserverEntry> mObservers = new ArrayList<ObserverEntry>();
-
- public ObserverNode(String name) {
- mName = name;
- }
-
- private String getUriSegment(Uri uri, int index) {
- if (uri != null) {
- if (index == 0) {
- return uri.getAuthority();
- } else {
- return uri.getPathSegments().get(index - 1);
- }
- } else {
- return null;
- }
- }
-
- private int countUriSegments(Uri uri) {
- if (uri == null) {
- return 0;
- }
- return uri.getPathSegments().size() + 1;
- }
-
- public void addObserver(Uri uri, IContentObserver observer, boolean notifyForDescendents) {
- addObserver(uri, 0, observer, notifyForDescendents);
- }
-
- private void addObserver(Uri uri, int index, IContentObserver observer,
- boolean notifyForDescendents) {
-
- // If this is the leaf node add the observer
- if (index == countUriSegments(uri)) {
- mObservers.add(new ObserverEntry(observer, notifyForDescendents));
- return;
- }
-
- // Look to see if the proper child already exists
- String segment = getUriSegment(uri, index);
- int N = mChildren.size();
- for (int i = 0; i < N; i++) {
- ObserverNode node = mChildren.get(i);
- if (node.mName.equals(segment)) {
- node.addObserver(uri, index + 1, observer, notifyForDescendents);
- return;
- }
- }
-
- // No child found, create one
- ObserverNode node = new ObserverNode(segment);
- mChildren.add(node);
- node.addObserver(uri, index + 1, observer, notifyForDescendents);
- }
-
- public boolean removeObserver(IContentObserver observer) {
- int size = mChildren.size();
- for (int i = 0; i < size; i++) {
- boolean empty = mChildren.get(i).removeObserver(observer);
- if (empty) {
- mChildren.remove(i);
- i--;
- size--;
- }
- }
-
- IBinder observerBinder = observer.asBinder();
- size = mObservers.size();
- for (int i = 0; i < size; i++) {
- ObserverEntry entry = mObservers.get(i);
- if (entry.observer.asBinder() == observerBinder) {
- mObservers.remove(i);
- // We no longer need to listen for death notifications. Remove it.
- observerBinder.unlinkToDeath(entry, 0);
- break;
- }
- }
-
- if (mChildren.size() == 0 && mObservers.size() == 0) {
- return true;
- }
- return false;
- }
-
- private void collectMyObservers(Uri uri,
- boolean leaf, IContentObserver observer, boolean selfNotify,
- ArrayList<ObserverCall> calls)
- {
- int N = mObservers.size();
- IBinder observerBinder = observer == null ? null : observer.asBinder();
- for (int i = 0; i < N; i++) {
- ObserverEntry entry = mObservers.get(i);
-
- // Don't notify the observer if it sent the notification and isn't interesed
- // in self notifications
- if (entry.observer.asBinder() == observerBinder && !selfNotify) {
- continue;
- }
-
- // Make sure the observer is interested in the notification
- if (leaf || (!leaf && entry.notifyForDescendents)) {
- calls.add(new ObserverCall(this, entry.observer, selfNotify));
- }
- }
- }
-
- public void collectObservers(Uri uri, int index, IContentObserver observer,
- boolean selfNotify, ArrayList<ObserverCall> calls) {
- String segment = null;
- int segmentCount = countUriSegments(uri);
- if (index >= segmentCount) {
- // This is the leaf node, notify all observers
- collectMyObservers(uri, true, observer, selfNotify, calls);
- } else if (index < segmentCount){
- segment = getUriSegment(uri, index);
- // Notify any observers at this level who are interested in descendents
- collectMyObservers(uri, false, observer, selfNotify, calls);
- }
-
- int N = mChildren.size();
- for (int i = 0; i < N; i++) {
- ObserverNode node = mChildren.get(i);
- if (segment == null || node.mName.equals(segment)) {
- // We found the child,
- node.collectObservers(uri, index + 1, observer, selfNotify, calls);
- if (segment != null) {
- break;
- }
- }
- }
- }
- }
-}
diff --git a/core/java/android/content/ContentServiceNative.java b/core/java/android/content/ContentServiceNative.java
deleted file mode 100644
index f050501..0000000
--- a/core/java/android/content/ContentServiceNative.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.database.IContentObserver;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.ServiceManager;
-import android.os.Bundle;
-import android.util.Config;
-import android.util.Log;
-
-/**
- * {@hide}
- */
-abstract class ContentServiceNative extends Binder implements IContentService
-{
- public ContentServiceNative()
- {
- attachInterface(this, descriptor);
- }
-
- /**
- * Cast a Binder object into a content resolver interface, generating
- * a proxy if needed.
- */
- static public IContentService asInterface(IBinder obj)
- {
- if (obj == null) {
- return null;
- }
- IContentService in =
- (IContentService)obj.queryLocalInterface(descriptor);
- if (in != null) {
- return in;
- }
-
- return new ContentServiceProxy(obj);
- }
-
- /**
- * Retrieve the system's default/global content service.
- */
- static public IContentService getDefault()
- {
- if (gDefault != null) {
- return gDefault;
- }
- IBinder b = ServiceManager.getService("content");
- if (Config.LOGV) Log.v("ContentService", "default service binder = " + b);
- gDefault = asInterface(b);
- if (Config.LOGV) Log.v("ContentService", "default service = " + gDefault);
- return gDefault;
- }
-
- @Override
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
- {
- try {
- switch (code) {
- case REGISTER_CONTENT_OBSERVER_TRANSACTION: {
- Uri uri = Uri.CREATOR.createFromParcel(data);
- boolean notifyForDescendents = data.readInt() != 0;
- IContentObserver observer = IContentObserver.Stub.asInterface(data.readStrongBinder());
- registerContentObserver(uri, notifyForDescendents, observer);
- return true;
- }
-
- case UNREGISTER_CHANGE_OBSERVER_TRANSACTION: {
- IContentObserver observer = IContentObserver.Stub.asInterface(data.readStrongBinder());
- unregisterContentObserver(observer);
- return true;
- }
-
- case NOTIFY_CHANGE_TRANSACTION: {
- Uri uri = Uri.CREATOR.createFromParcel(data);
- IContentObserver observer = IContentObserver.Stub.asInterface(data.readStrongBinder());
- boolean observerWantsSelfNotifications = data.readInt() != 0;
- boolean syncToNetwork = data.readInt() != 0;
- notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork);
- return true;
- }
-
- case START_SYNC_TRANSACTION: {
- Uri url = null;
- int hasUrl = data.readInt();
- if (hasUrl != 0) {
- url = Uri.CREATOR.createFromParcel(data);
- }
- startSync(url, data.readBundle());
- return true;
- }
-
- case CANCEL_SYNC_TRANSACTION: {
- Uri url = null;
- int hasUrl = data.readInt();
- if (hasUrl != 0) {
- url = Uri.CREATOR.createFromParcel(data);
- }
- cancelSync(url);
- return true;
- }
-
- default:
- return super.onTransact(code, data, reply, flags);
- }
- } catch (Exception e) {
- Log.e("ContentServiceNative", "Caught exception in transact", e);
- }
-
- return false;
- }
-
- public IBinder asBinder()
- {
- return this;
- }
-
- private static IContentService gDefault;
-}
-
-
-final class ContentServiceProxy implements IContentService
-{
- public ContentServiceProxy(IBinder remote)
- {
- mRemote = remote;
- }
-
- public IBinder asBinder()
- {
- return mRemote;
- }
-
- public void registerContentObserver(Uri uri, boolean notifyForDescendents,
- IContentObserver observer) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- uri.writeToParcel(data, 0);
- data.writeInt(notifyForDescendents ? 1 : 0);
- data.writeStrongInterface(observer);
- mRemote.transact(REGISTER_CONTENT_OBSERVER_TRANSACTION, data, null, 0);
- data.recycle();
- }
-
- public void unregisterContentObserver(IContentObserver observer) throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeStrongInterface(observer);
- mRemote.transact(UNREGISTER_CHANGE_OBSERVER_TRANSACTION, data, null, 0);
- data.recycle();
- }
-
- public void notifyChange(Uri uri, IContentObserver observer,
- boolean observerWantsSelfNotifications, boolean syncToNetwork)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- uri.writeToParcel(data, 0);
- data.writeStrongInterface(observer);
- data.writeInt(observerWantsSelfNotifications ? 1 : 0);
- data.writeInt(syncToNetwork ? 1 : 0);
- mRemote.transact(NOTIFY_CHANGE_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public void startSync(Uri url, Bundle extras) throws RemoteException {
- Parcel data = Parcel.obtain();
- if (url == null) {
- data.writeInt(0);
- } else {
- data.writeInt(1);
- url.writeToParcel(data, 0);
- }
- extras.writeToParcel(data, 0);
- mRemote.transact(START_SYNC_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- public void cancelSync(Uri url) throws RemoteException {
- Parcel data = Parcel.obtain();
- if (url == null) {
- data.writeInt(0);
- } else {
- data.writeInt(1);
- url.writeToParcel(data, 0);
- }
- mRemote.transact(CANCEL_SYNC_TRANSACTION, data, null /* reply */, IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
- private IBinder mRemote;
-}
-
diff --git a/core/java/android/content/ContentUris.java b/core/java/android/content/ContentUris.java
deleted file mode 100644
index aa76034..0000000
--- a/core/java/android/content/ContentUris.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.net.Uri;
-
-/**
- * Utility methods useful for working with content {@link android.net.Uri}s,
- * those with a "content" scheme.
- */
-public class ContentUris {
-
- /**
- * Converts the last path segment to a long.
- *
- * <p>This supports a common convention for content URIs where an ID is
- * stored in the last segment.
- *
- * @throws UnsupportedOperationException if this isn't a hierarchical URI
- * @throws NumberFormatException if the last segment isn't a number
- *
- * @return the long conversion of the last segment or -1 if the path is
- * empty
- */
- public static long parseId(Uri contentUri) {
- String last = contentUri.getLastPathSegment();
- return last == null ? -1 : Long.parseLong(last);
- }
-
- /**
- * Appends the given ID to the end of the path.
- *
- * @param builder to append the ID to
- * @param id to append
- *
- * @return the given builder
- */
- public static Uri.Builder appendId(Uri.Builder builder, long id) {
- return builder.appendEncodedPath(String.valueOf(id));
- }
-
- /**
- * Appends the given ID to the end of the path.
- *
- * @param contentUri to start with
- * @param id to append
- *
- * @return a new URI with the given ID appended to the end of the path
- */
- public static Uri withAppendedId(Uri contentUri, long id) {
- return appendId(contentUri.buildUpon(), id).build();
- }
-}
diff --git a/core/java/android/content/ContentValues.java b/core/java/android/content/ContentValues.java
deleted file mode 100644
index 532cc03..0000000
--- a/core/java/android/content/ContentValues.java
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * This class is used to store a set of values that the {@link ContentResolver}
- * can process.
- */
-public final class ContentValues implements Parcelable {
- public static final String TAG = "ContentValues";
-
- /** Holds the actual values */
- private HashMap<String, Object> mValues;
-
- /**
- * Creates an empty set of values using the default initial size
- */
- public ContentValues() {
- // Choosing a default size of 8 based on analysis of typical
- // consumption by applications.
- mValues = new HashMap<String, Object>(8);
- }
-
- /**
- * Creates an empty set of values using the given initial size
- *
- * @param size the initial size of the set of values
- */
- public ContentValues(int size) {
- mValues = new HashMap<String, Object>(size, 1.0f);
- }
-
- /**
- * Creates a set of values copied from the given set
- *
- * @param from the values to copy
- */
- public ContentValues(ContentValues from) {
- mValues = new HashMap<String, Object>(from.mValues);
- }
-
- /**
- * Creates a set of values copied from the given HashMap. This is used
- * by the Parcel unmarshalling code.
- *
- * @param from the values to start with
- * {@hide}
- */
- private ContentValues(HashMap<String, Object> values) {
- mValues = values;
- }
-
- @Override
- public boolean equals(Object object) {
- if (!(object instanceof ContentValues)) {
- return false;
- }
- return mValues.equals(((ContentValues) object).mValues);
- }
-
- @Override
- public int hashCode() {
- return mValues.hashCode();
- }
-
- /**
- * Adds a value to the set.
- *
- * @param key the name of the value to put
- * @param value the data for the value to put
- */
- public void put(String key, String value) {
- mValues.put(key, value);
- }
-
- /**
- * Adds all values from the passed in ContentValues.
- *
- * @param other the ContentValues from which to copy
- */
- public void putAll(ContentValues other) {
- mValues.putAll(other.mValues);
- }
-
- /**
- * Adds a value to the set.
- *
- * @param key the name of the value to put
- * @param value the data for the value to put
- */
- public void put(String key, Byte value) {
- mValues.put(key, value);
- }
-
- /**
- * Adds a value to the set.
- *
- * @param key the name of the value to put
- * @param value the data for the value to put
- */
- public void put(String key, Short value) {
- mValues.put(key, value);
- }
-
- /**
- * Adds a value to the set.
- *
- * @param key the name of the value to put
- * @param value the data for the value to put
- */
- public void put(String key, Integer value) {
- mValues.put(key, value);
- }
-
- /**
- * Adds a value to the set.
- *
- * @param key the name of the value to put
- * @param value the data for the value to put
- */
- public void put(String key, Long value) {
- mValues.put(key, value);
- }
-
- /**
- * Adds a value to the set.
- *
- * @param key the name of the value to put
- * @param value the data for the value to put
- */
- public void put(String key, Float value) {
- mValues.put(key, value);
- }
-
- /**
- * Adds a value to the set.
- *
- * @param key the name of the value to put
- * @param value the data for the value to put
- */
- public void put(String key, Double value) {
- mValues.put(key, value);
- }
-
- /**
- * Adds a value to the set.
- *
- * @param key the name of the value to put
- * @param value the data for the value to put
- */
- public void put(String key, Boolean value) {
- mValues.put(key, value);
- }
-
- /**
- * Adds a value to the set.
- *
- * @param key the name of the value to put
- * @param value the data for the value to put
- */
- public void put(String key, byte[] value) {
- mValues.put(key, value);
- }
-
- /**
- * Adds a null value to the set.
- *
- * @param key the name of the value to make null
- */
- public void putNull(String key) {
- mValues.put(key, null);
- }
-
- /**
- * Returns the number of values.
- *
- * @return the number of values
- */
- public int size() {
- return mValues.size();
- }
-
- /**
- * Remove a single value.
- *
- * @param key the name of the value to remove
- */
- public void remove(String key) {
- mValues.remove(key);
- }
-
- /**
- * Removes all values.
- */
- public void clear() {
- mValues.clear();
- }
-
- /**
- * Returns true if this object has the named value.
- *
- * @param key the value to check for
- * @return {@code true} if the value is present, {@code false} otherwise
- */
- public boolean containsKey(String key) {
- return mValues.containsKey(key);
- }
-
- /**
- * Gets a value. Valid value types are {@link String}, {@link Boolean}, and
- * {@link Number} implementations.
- *
- * @param key the value to get
- * @return the data for the value
- */
- public Object get(String key) {
- return mValues.get(key);
- }
-
- /**
- * Gets a value and converts it to a String.
- *
- * @param key the value to get
- * @return the String for the value
- */
- public String getAsString(String key) {
- Object value = mValues.get(key);
- return value != null ? mValues.get(key).toString() : null;
- }
-
- /**
- * Gets a value and converts it to a Long.
- *
- * @param key the value to get
- * @return the Long value, or null if the value is missing or cannot be converted
- */
- public Long getAsLong(String key) {
- Object value = mValues.get(key);
- try {
- return value != null ? ((Number) value).longValue() : null;
- } catch (ClassCastException e) {
- if (value instanceof CharSequence) {
- try {
- return Long.valueOf(value.toString());
- } catch (NumberFormatException e2) {
- Log.e(TAG, "Cannot parse Long value for " + value + " at key " + key);
- return null;
- }
- } else {
- Log.e(TAG, "Cannot cast value for " + key + " to a Long");
- return null;
- }
- }
- }
-
- /**
- * Gets a value and converts it to an Integer.
- *
- * @param key the value to get
- * @return the Integer value, or null if the value is missing or cannot be converted
- */
- public Integer getAsInteger(String key) {
- Object value = mValues.get(key);
- try {
- return value != null ? ((Number) value).intValue() : null;
- } catch (ClassCastException e) {
- if (value instanceof CharSequence) {
- try {
- return Integer.valueOf(value.toString());
- } catch (NumberFormatException e2) {
- Log.e(TAG, "Cannot parse Integer value for " + value + " at key " + key);
- return null;
- }
- } else {
- Log.e(TAG, "Cannot cast value for " + key + " to a Integer");
- return null;
- }
- }
- }
-
- /**
- * Gets a value and converts it to a Short.
- *
- * @param key the value to get
- * @return the Short value, or null if the value is missing or cannot be converted
- */
- public Short getAsShort(String key) {
- Object value = mValues.get(key);
- try {
- return value != null ? ((Number) value).shortValue() : null;
- } catch (ClassCastException e) {
- if (value instanceof CharSequence) {
- try {
- return Short.valueOf(value.toString());
- } catch (NumberFormatException e2) {
- Log.e(TAG, "Cannot parse Short value for " + value + " at key " + key);
- return null;
- }
- } else {
- Log.e(TAG, "Cannot cast value for " + key + " to a Short");
- return null;
- }
- }
- }
-
- /**
- * Gets a value and converts it to a Byte.
- *
- * @param key the value to get
- * @return the Byte value, or null if the value is missing or cannot be converted
- */
- public Byte getAsByte(String key) {
- Object value = mValues.get(key);
- try {
- return value != null ? ((Number) value).byteValue() : null;
- } catch (ClassCastException e) {
- if (value instanceof CharSequence) {
- try {
- return Byte.valueOf(value.toString());
- } catch (NumberFormatException e2) {
- Log.e(TAG, "Cannot parse Byte value for " + value + " at key " + key);
- return null;
- }
- } else {
- Log.e(TAG, "Cannot cast value for " + key + " to a Byte");
- return null;
- }
- }
- }
-
- /**
- * Gets a value and converts it to a Double.
- *
- * @param key the value to get
- * @return the Double value, or null if the value is missing or cannot be converted
- */
- public Double getAsDouble(String key) {
- Object value = mValues.get(key);
- try {
- return value != null ? ((Number) value).doubleValue() : null;
- } catch (ClassCastException e) {
- if (value instanceof CharSequence) {
- try {
- return Double.valueOf(value.toString());
- } catch (NumberFormatException e2) {
- Log.e(TAG, "Cannot parse Double value for " + value + " at key " + key);
- return null;
- }
- } else {
- Log.e(TAG, "Cannot cast value for " + key + " to a Double");
- return null;
- }
- }
- }
-
- /**
- * Gets a value and converts it to a Float.
- *
- * @param key the value to get
- * @return the Float value, or null if the value is missing or cannot be converted
- */
- public Float getAsFloat(String key) {
- Object value = mValues.get(key);
- try {
- return value != null ? ((Number) value).floatValue() : null;
- } catch (ClassCastException e) {
- if (value instanceof CharSequence) {
- try {
- return Float.valueOf(value.toString());
- } catch (NumberFormatException e2) {
- Log.e(TAG, "Cannot parse Float value for " + value + " at key " + key);
- return null;
- }
- } else {
- Log.e(TAG, "Cannot cast value for " + key + " to a Float");
- return null;
- }
- }
- }
-
- /**
- * Gets a value and converts it to a Boolean.
- *
- * @param key the value to get
- * @return the Boolean value, or null if the value is missing or cannot be converted
- */
- public Boolean getAsBoolean(String key) {
- Object value = mValues.get(key);
- try {
- return (Boolean) value;
- } catch (ClassCastException e) {
- if (value instanceof CharSequence) {
- return Boolean.valueOf(value.toString());
- } else {
- Log.e(TAG, "Cannot cast value for " + key + " to a Boolean");
- return null;
- }
- }
- }
-
- /**
- * Gets a value that is a byte array. Note that this method will not convert
- * any other types to byte arrays.
- *
- * @param key the value to get
- * @return the byte[] value, or null is the value is missing or not a byte[]
- */
- public byte[] getAsByteArray(String key) {
- Object value = mValues.get(key);
- if (value instanceof byte[]) {
- return (byte[]) value;
- } else {
- return null;
- }
- }
-
- /**
- * Returns a set of all of the keys and values
- *
- * @return a set of all of the keys and values
- */
- public Set<Map.Entry<String, Object>> valueSet() {
- return mValues.entrySet();
- }
-
- public static final Parcelable.Creator<ContentValues> CREATOR =
- new Parcelable.Creator<ContentValues>() {
- @SuppressWarnings({"deprecation", "unchecked"})
- public ContentValues createFromParcel(Parcel in) {
- // TODO - what ClassLoader should be passed to readHashMap?
- HashMap<String, Object> values = in.readHashMap(null);
- return new ContentValues(values);
- }
-
- public ContentValues[] newArray(int size) {
- return new ContentValues[size];
- }
- };
-
- public int describeContents() {
- return 0;
- }
-
- @SuppressWarnings("deprecation")
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeMap(mValues);
- }
-
- /**
- * Unsupported, here until we get proper bulk insert APIs.
- * {@hide}
- */
- @Deprecated
- public void putStringArrayList(String key, ArrayList<String> value) {
- mValues.put(key, value);
- }
-
- /**
- * Unsupported, here until we get proper bulk insert APIs.
- * {@hide}
- */
- @SuppressWarnings("unchecked")
- @Deprecated
- public ArrayList<String> getStringArrayList(String key) {
- return (ArrayList<String>) mValues.get(key);
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- for (String name : mValues.keySet()) {
- String value = getAsString(name);
- if (sb.length() > 0) sb.append(" ");
- sb.append(name + "=" + value);
- }
- return sb.toString();
- }
-}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
deleted file mode 100644
index e0fe533..0000000
--- a/core/java/android/content/Context.java
+++ /dev/null
@@ -1,1654 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.content.pm.PackageManager;
-import android.content.res.AssetManager;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteDatabase.CursorFactory;
-import android.graphics.Bitmap;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.AttributeSet;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Interface to global information about an application environment. This is
- * an abstract class whose implementation is provided by
- * the Android system. It
- * allows access to application-specific resources and classes, as well as
- * up-calls for application-level operations such as launching activities,
- * broadcasting and receiving intents, etc.
- */
-public abstract class Context {
- /**
- * File creation mode: the default mode, where the created file can only
- * be accessed by the calling application (or all applications sharing the
- * same user ID).
- * @see #MODE_WORLD_READABLE
- * @see #MODE_WORLD_WRITEABLE
- */
- public static final int MODE_PRIVATE = 0x0000;
- /**
- * File creation mode: allow all other applications to have read access
- * to the created file.
- * @see #MODE_PRIVATE
- * @see #MODE_WORLD_WRITEABLE
- */
- public static final int MODE_WORLD_READABLE = 0x0001;
- /**
- * File creation mode: allow all other applications to have write access
- * to the created file.
- * @see #MODE_PRIVATE
- * @see #MODE_WORLD_READABLE
- */
- public static final int MODE_WORLD_WRITEABLE = 0x0002;
- /**
- * File creation mode: for use with {@link #openFileOutput}, if the file
- * already exists then write data to the end of the existing file
- * instead of erasing it.
- * @see #openFileOutput
- */
- public static final int MODE_APPEND = 0x8000;
-
- /**
- * Flag for {@link #bindService}: automatically create the service as long
- * as the binding exists. Note that while this will create the service,
- * its {@link android.app.Service#onStart} method will still only be called due to an
- * explicit call to {@link #startService}. Even without that, though,
- * this still provides you with access to the service object while the
- * service is created.
- *
- * <p>Specifying this flag also tells the system to treat the service
- * as being as important as your own process -- that is, when deciding
- * which process should be killed to free memory, the service will only
- * be considered a candidate as long as the processes of any such bindings
- * is also a candidate to be killed. This is to avoid situations where
- * the service is being continually created and killed due to low memory.
- */
- public static final int BIND_AUTO_CREATE = 0x0001;
-
- /**
- * Flag for {@link #bindService}: include debugging help for mismatched
- * calls to unbind. When this flag is set, the callstack of the following
- * {@link #unbindService} call is retained, to be printed if a later
- * incorrect unbind call is made. Note that doing this requires retaining
- * information about the binding that was made for the lifetime of the app,
- * resulting in a leak -- this should only be used for debugging.
- */
- public static final int BIND_DEBUG_UNBIND = 0x0002;
-
- /** Return an AssetManager instance for your application's package. */
- public abstract AssetManager getAssets();
-
- /** Return a Resources instance for your application's package. */
- public abstract Resources getResources();
-
- /** Return PackageManager instance to find global package information. */
- public abstract PackageManager getPackageManager();
-
- /** Return a ContentResolver instance for your application's package. */
- public abstract ContentResolver getContentResolver();
-
- /**
- * Return the Looper for the main thread of the current process. This is
- * the thread used to dispatch calls to application components (activities,
- * services, etc).
- */
- public abstract Looper getMainLooper();
-
- /**
- * Return the context of the single, global Application object of the
- * current process.
- */
- public abstract Context getApplicationContext();
-
- /**
- * Return a localized, styled CharSequence from the application's package's
- * default string table.
- *
- * @param resId Resource id for the CharSequence text
- */
- public final CharSequence getText(int resId) {
- return getResources().getText(resId);
- }
-
- /**
- * Return a localized string from the application's package's
- * default string table.
- *
- * @param resId Resource id for the string
- */
- public final String getString(int resId) {
- return getResources().getString(resId);
- }
-
- /**
- * Return a localized formatted string from the application's package's
- * default string table, substituting the format arguments as defined in
- * {@link java.util.Formatter} and {@link java.lang.String#format}.
- *
- * @param resId Resource id for the format string
- * @param formatArgs The format arguments that will be used for substitution.
- */
-
- public final String getString(int resId, Object... formatArgs) {
- return getResources().getString(resId, formatArgs);
- }
-
- /**
- * Set the base theme for this context. Note that this should be called
- * before any views are instantiated in the Context (for example before
- * calling {@link android.app.Activity#setContentView} or
- * {@link android.view.LayoutInflater#inflate}).
- *
- * @param resid The style resource describing the theme.
- */
- public abstract void setTheme(int resid);
-
- /**
- * Return the Theme object associated with this Context.
- */
- public abstract Resources.Theme getTheme();
-
- /**
- * Retrieve styled attribute information in this Context's theme. See
- * {@link Resources.Theme#obtainStyledAttributes(int[])}
- * for more information.
- *
- * @see Resources.Theme#obtainStyledAttributes(int[])
- */
- public final TypedArray obtainStyledAttributes(
- int[] attrs) {
- return getTheme().obtainStyledAttributes(attrs);
- }
-
- /**
- * Retrieve styled attribute information in this Context's theme. See
- * {@link Resources.Theme#obtainStyledAttributes(int, int[])}
- * for more information.
- *
- * @see Resources.Theme#obtainStyledAttributes(int, int[])
- */
- public final TypedArray obtainStyledAttributes(
- int resid, int[] attrs) throws Resources.NotFoundException {
- return getTheme().obtainStyledAttributes(resid, attrs);
- }
-
- /**
- * Retrieve styled attribute information in this Context's theme. See
- * {@link Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)}
- * for more information.
- *
- * @see Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)
- */
- public final TypedArray obtainStyledAttributes(
- AttributeSet set, int[] attrs) {
- return getTheme().obtainStyledAttributes(set, attrs, 0, 0);
- }
-
- /**
- * Retrieve styled attribute information in this Context's theme. See
- * {@link Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)}
- * for more information.
- *
- * @see Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)
- */
- public final TypedArray obtainStyledAttributes(
- AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
- return getTheme().obtainStyledAttributes(
- set, attrs, defStyleAttr, defStyleRes);
- }
-
- /**
- * Return a class loader you can use to retrieve classes in this package.
- */
- public abstract ClassLoader getClassLoader();
-
- /** Return the name of this application's package. */
- public abstract String getPackageName();
-
- /**
- * {@hide}
- * Return the full path to this context's resource files. This is the ZIP files
- * containing the application's resources.
- *
- * <p>Note: this is not generally useful for applications, since they should
- * not be directly accessing the file system.
- *
- *
- * @return String Path to the resources.
- */
- public abstract String getPackageResourcePath();
-
- /**
- * {@hide}
- * Return the full path to this context's code and asset files. This is the ZIP files
- * containing the application's code and assets.
- *
- * <p>Note: this is not generally useful for applications, since they should
- * not be directly accessing the file system.
- *
- *
- * @return String Path to the code and assets.
- */
- public abstract String getPackageCodePath();
-
- /**
- * Retrieve and hold the contents of the preferences file 'name', returning
- * a SharedPreferences through which you can retrieve and modify its
- * values. Only one instance of the SharedPreferences object is returned
- * to any callers for the same name, meaning they will see each other's
- * edits as soon as they are made.
- *
- * @param name Desired preferences file. If a preferences file by this name
- * does not exist, it will be created when you retrieve an
- * editor (SharedPreferences.edit()) and then commit changes (Editor.commit()).
- * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
- * default operation, {@link #MODE_WORLD_READABLE}
- * and {@link #MODE_WORLD_WRITEABLE} to control permissions.
- *
- * @return Returns the single SharedPreferences instance that can be used
- * to retrieve and modify the preference values.
- *
- * @see #MODE_PRIVATE
- * @see #MODE_WORLD_READABLE
- * @see #MODE_WORLD_WRITEABLE
- */
- public abstract SharedPreferences getSharedPreferences(String name,
- int mode);
-
- /**
- * Open a private file associated with this Context's application package
- * for reading.
- *
- * @param name The name of the file to open; can not contain path
- * separators.
- *
- * @return FileInputStream Resulting input stream.
- *
- * @see #openFileOutput
- * @see #fileList
- * @see #deleteFile
- * @see java.io.FileInputStream#FileInputStream(String)
- */
- public abstract FileInputStream openFileInput(String name)
- throws FileNotFoundException;
-
- /**
- * Open a private file associated with this Context's application package
- * for writing. Creates the file if it doesn't already exist.
- *
- * @param name The name of the file to open; can not contain path
- * separators.
- * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
- * default operation, {@link #MODE_APPEND} to append to an existing file,
- * {@link #MODE_WORLD_READABLE} and {@link #MODE_WORLD_WRITEABLE} to control
- * permissions.
- *
- * @return FileOutputStream Resulting output stream.
- *
- * @see #MODE_APPEND
- * @see #MODE_PRIVATE
- * @see #MODE_WORLD_READABLE
- * @see #MODE_WORLD_WRITEABLE
- * @see #openFileInput
- * @see #fileList
- * @see #deleteFile
- * @see java.io.FileOutputStream#FileOutputStream(String)
- */
- public abstract FileOutputStream openFileOutput(String name, int mode)
- throws FileNotFoundException;
-
- /**
- * Delete the given private file associated with this Context's
- * application package.
- *
- * @param name The name of the file to delete; can not contain path
- * separators.
- *
- * @return True if the file was successfully deleted; else
- * false.
- *
- * @see #openFileInput
- * @see #openFileOutput
- * @see #fileList
- * @see java.io.File#delete()
- */
- public abstract boolean deleteFile(String name);
-
- /**
- * Returns the absolute path on the filesystem where a file created with
- * {@link #openFileOutput} is stored.
- *
- * @param name The name of the file for which you would like to get
- * its path.
- *
- * @return Returns an absolute path to the given file.
- *
- * @see #openFileOutput
- * @see #getFilesDir
- * @see #getDir
- */
- public abstract File getFileStreamPath(String name);
-
- /**
- * Returns the absolute path to the directory on the filesystem where
- * files created with {@link #openFileOutput} are stored.
- *
- * @return Returns the path of the directory holding application files.
- *
- * @see #openFileOutput
- * @see #getFileStreamPath
- * @see #getDir
- */
- public abstract File getFilesDir();
-
- /**
- * Returns the absolute path to the application specific cache directory
- * on the filesystem. These files will be ones that get deleted first when the
- * device runs low on storage
- * There is no guarantee when these files will be deleted.
- *
- * @return Returns the path of the directory holding application cache files.
- *
- * @see #openFileOutput
- * @see #getFileStreamPath
- * @see #getDir
- */
- public abstract File getCacheDir();
-
- /**
- * Returns an array of strings naming the private files associated with
- * this Context's application package.
- *
- * @return Array of strings naming the private files.
- *
- * @see #openFileInput
- * @see #openFileOutput
- * @see #deleteFile
- */
- public abstract String[] fileList();
-
- /**
- * Retrieve, creating if needed, a new directory in which the application
- * can place its own custom data files. You can use the returned File
- * object to create and access files in this directory. Note that files
- * created through a File object will only be accessible by your own
- * application; you can only set the mode of the entire directory, not
- * of individual files.
- *
- * @param name Name of the directory to retrieve. This is a directory
- * that is created as part of your application data.
- * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
- * default operation, {@link #MODE_WORLD_READABLE} and
- * {@link #MODE_WORLD_WRITEABLE} to control permissions.
- *
- * @return Returns a File object for the requested directory. The directory
- * will have been created if it does not already exist.
- *
- * @see #openFileOutput(String, int)
- */
- public abstract File getDir(String name, int mode);
-
- /**
- * Open a new private SQLiteDatabase associated with this Context's
- * application package. Create the database file if it doesn't exist.
- *
- * @param name The name (unique in the application package) of the database.
- * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
- * default operation, {@link #MODE_WORLD_READABLE}
- * and {@link #MODE_WORLD_WRITEABLE} to control permissions.
- * @param factory An optional factory class that is called to instantiate a
- * cursor when query is called.
- *
- * @return The contents of a newly created database with the given name.
- * @throws android.database.sqlite.SQLiteException if the database file could not be opened.
- *
- * @see #MODE_PRIVATE
- * @see #MODE_WORLD_READABLE
- * @see #MODE_WORLD_WRITEABLE
- * @see #deleteDatabase
- */
- public abstract SQLiteDatabase openOrCreateDatabase(String name,
- int mode, CursorFactory factory);
-
- /**
- * Delete an existing private SQLiteDatabase associated with this Context's
- * application package.
- *
- * @param name The name (unique in the application package) of the
- * database.
- *
- * @return True if the database was successfully deleted; else false.
- *
- * @see #openOrCreateDatabase
- */
- public abstract boolean deleteDatabase(String name);
-
- /**
- * Returns the absolute path on the filesystem where a database created with
- * {@link #openOrCreateDatabase} is stored.
- *
- * @param name The name of the database for which you would like to get
- * its path.
- *
- * @return Returns an absolute path to the given database.
- *
- * @see #openOrCreateDatabase
- */
- public abstract File getDatabasePath(String name);
-
- /**
- * Returns an array of strings naming the private databases associated with
- * this Context's application package.
- *
- * @return Array of strings naming the private databases.
- *
- * @see #openOrCreateDatabase
- * @see #deleteDatabase
- */
- public abstract String[] databaseList();
-
- /**
- * Like {@link #peekWallpaper}, but always returns a valid Drawable. If
- * no wallpaper is set, the system default wallpaper is returned.
- *
- * @return Returns a Drawable object that will draw the wallpaper.
- */
- public abstract Drawable getWallpaper();
-
- /**
- * Retrieve the current system wallpaper. This is returned as an
- * abstract Drawable that you can install in a View to display whatever
- * wallpaper the user has currently set. If there is no wallpaper set,
- * a null pointer is returned.
- *
- * @return Returns a Drawable object that will draw the wallpaper or a
- * null pointer if these is none.
- */
- public abstract Drawable peekWallpaper();
-
- /**
- * Returns the desired minimum width for the wallpaper. Callers of
- * {@link #setWallpaper(android.graphics.Bitmap)} or
- * {@link #setWallpaper(java.io.InputStream)} should check this value
- * beforehand to make sure the supplied wallpaper respects the desired
- * minimum width.
- *
- * If the returned value is <= 0, the caller should use the width of
- * the default display instead.
- *
- * @return The desired minimum width for the wallpaper. This value should
- * be honored by applications that set the wallpaper but it is not
- * mandatory.
- */
- public abstract int getWallpaperDesiredMinimumWidth();
-
- /**
- * Returns the desired minimum height for the wallpaper. Callers of
- * {@link #setWallpaper(android.graphics.Bitmap)} or
- * {@link #setWallpaper(java.io.InputStream)} should check this value
- * beforehand to make sure the supplied wallpaper respects the desired
- * minimum height.
- *
- * If the returned value is <= 0, the caller should use the height of
- * the default display instead.
- *
- * @return The desired minimum height for the wallpaper. This value should
- * be honored by applications that set the wallpaper but it is not
- * mandatory.
- */
- public abstract int getWallpaperDesiredMinimumHeight();
-
- /**
- * Change the current system wallpaper to a bitmap. The given bitmap is
- * converted to a PNG and stored as the wallpaper. On success, the intent
- * {@link Intent#ACTION_WALLPAPER_CHANGED} is broadcast.
- *
- * @param bitmap The bitmap to save.
- *
- * @throws IOException If an error occurs reverting to the default
- * wallpaper.
- */
- public abstract void setWallpaper(Bitmap bitmap) throws IOException;
-
- /**
- * Change the current system wallpaper to a specific byte stream. The
- * give InputStream is copied into persistent storage and will now be
- * used as the wallpaper. Currently it must be either a JPEG or PNG
- * image. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED}
- * is broadcast.
- *
- * @param data A stream containing the raw data to install as a wallpaper.
- *
- * @throws IOException If an error occurs reverting to the default
- * wallpaper.
- */
- public abstract void setWallpaper(InputStream data) throws IOException;
-
- /**
- * Remove any currently set wallpaper, reverting to the system's default
- * wallpaper. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED}
- * is broadcast.
- *
- * @throws IOException If an error occurs reverting to the default
- * wallpaper.
- */
- public abstract void clearWallpaper() throws IOException;
-
- /**
- * Launch a new activity. You will not receive any information about when
- * the activity exits.
- *
- * <p>Note that if this method is being called from outside of an
- * {@link android.app.Activity} Context, then the Intent must include
- * the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag. This is because,
- * without being started from an existing Activity, there is no existing
- * task in which to place the new activity and thus it needs to be placed
- * in its own separate task.
- *
- * <p>This method throws {@link ActivityNotFoundException}
- * if there was no Activity found to run the given Intent.
- *
- * @param intent The description of the activity to start.
- *
- * @throws ActivityNotFoundException
- *
- * @see PackageManager#resolveActivity
- */
- public abstract void startActivity(Intent intent);
-
- /**
- * Broadcast the given intent to all interested BroadcastReceivers. This
- * call is asynchronous; it returns immediately, and you will continue
- * executing while the receivers are run. No results are propagated from
- * receivers and receivers can not abort the broadcast. If you want
- * to allow receivers to propagate results or abort the broadcast, you must
- * send an ordered broadcast using
- * {@link #sendOrderedBroadcast(Intent, String)}.
- *
- * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
- *
- * @param intent The Intent to broadcast; all receivers matching this
- * Intent will receive the broadcast.
- *
- * @see android.content.BroadcastReceiver
- * @see #registerReceiver
- * @see #sendBroadcast(Intent, String)
- * @see #sendOrderedBroadcast(Intent, String)
- * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
- */
- public abstract void sendBroadcast(Intent intent);
-
- /**
- * Broadcast the given intent to all interested BroadcastReceivers, allowing
- * an optional required permission to be enforced. This
- * call is asynchronous; it returns immediately, and you will continue
- * executing while the receivers are run. No results are propagated from
- * receivers and receivers can not abort the broadcast. If you want
- * to allow receivers to propagate results or abort the broadcast, you must
- * send an ordered broadcast using
- * {@link #sendOrderedBroadcast(Intent, String)}.
- *
- * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
- *
- * @param intent The Intent to broadcast; all receivers matching this
- * Intent will receive the broadcast.
- * @param receiverPermission (optional) String naming a permissions that
- * a receiver must hold in order to receive your broadcast.
- * If null, no permission is required.
- *
- * @see android.content.BroadcastReceiver
- * @see #registerReceiver
- * @see #sendBroadcast(Intent)
- * @see #sendOrderedBroadcast(Intent, String)
- * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
- */
- public abstract void sendBroadcast(Intent intent,
- String receiverPermission);
-
- /**
- * Broadcast the given intent to all interested BroadcastReceivers, delivering
- * them one at a time to allow more preferred receivers to consume the
- * broadcast before it is delivered to less preferred receivers. This
- * call is asynchronous; it returns immediately, and you will continue
- * executing while the receivers are run.
- *
- * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
- *
- * @param intent The Intent to broadcast; all receivers matching this
- * Intent will receive the broadcast.
- * @param receiverPermission (optional) String naming a permissions that
- * a receiver must hold in order to receive your broadcast.
- * If null, no permission is required.
- *
- * @see android.content.BroadcastReceiver
- * @see #registerReceiver
- * @see #sendBroadcast(Intent)
- * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
- */
- public abstract void sendOrderedBroadcast(Intent intent,
- String receiverPermission);
-
- /**
- * Version of {@link #sendBroadcast(Intent)} that allows you to
- * receive data back from the broadcast. This is accomplished by
- * supplying your own BroadcastReceiver when calling, which will be
- * treated as a final receiver at the end of the broadcast -- its
- * {@link BroadcastReceiver#onReceive} method will be called with
- * the result values collected from the other receivers. If you use
- * an <var>resultReceiver</var> with this method, then the broadcast will
- * be serialized in the same way as calling
- * {@link #sendOrderedBroadcast(Intent, String)}.
- *
- * <p>Like {@link #sendBroadcast(Intent)}, this method is
- * asynchronous; it will return before
- * resultReceiver.onReceive() is called.
- *
- * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
- *
- * @param intent The Intent to broadcast; all receivers matching this
- * Intent will receive the broadcast.
- * @param receiverPermission String naming a permissions that
- * a receiver must hold in order to receive your broadcast.
- * If null, no permission is required.
- * @param resultReceiver Your own BroadcastReceiver to treat as the final
- * receiver of the broadcast.
- * @param scheduler A custom Handler with which to schedule the
- * resultReceiver callback; if null it will be
- * scheduled in the Context's main thread.
- * @param initialCode An initial value for the result code. Often
- * Activity.RESULT_OK.
- * @param initialData An initial value for the result data. Often
- * null.
- * @param initialExtras An initial value for the result extras. Often
- * null.
- *
- * @see #sendBroadcast(Intent)
- * @see #sendBroadcast(Intent, String)
- * @see #sendOrderedBroadcast(Intent, String)
- * @see #sendStickyBroadcast(Intent)
- * @see android.content.BroadcastReceiver
- * @see #registerReceiver
- * @see android.app.Activity#RESULT_OK
- */
- public abstract void sendOrderedBroadcast(Intent intent,
- String receiverPermission, BroadcastReceiver resultReceiver,
- Handler scheduler, int initialCode, String initialData,
- Bundle initialExtras);
-
- /**
- * Perform a {@link #sendBroadcast(Intent)} that is "sticky," meaning the
- * Intent you are sending stays around after the broadcast is complete,
- * so that others can quickly retrieve that data through the return
- * value of {@link #registerReceiver(BroadcastReceiver, IntentFilter)}. In
- * all other ways, this behaves the same as
- * {@link #sendBroadcast(Intent)}.
- *
- * <p>You must hold the {@link android.Manifest.permission#BROADCAST_STICKY}
- * permission in order to use this API. If you do not hold that
- * permission, {@link SecurityException} will be thrown.
- *
- * @param intent The Intent to broadcast; all receivers matching this
- * Intent will receive the broadcast, and the Intent will be held to
- * be re-broadcast to future receivers.
- *
- * @see #sendBroadcast(Intent)
- */
- public abstract void sendStickyBroadcast(Intent intent);
-
- /**
- * Remove the data previously sent with {@link #sendStickyBroadcast},
- * so that it is as if the sticky broadcast had never happened.
- *
- * <p>You must hold the {@link android.Manifest.permission#BROADCAST_STICKY}
- * permission in order to use this API. If you do not hold that
- * permission, {@link SecurityException} will be thrown.
- *
- * @param intent The Intent that was previously broadcast.
- *
- * @see #sendStickyBroadcast
- */
- public abstract void removeStickyBroadcast(Intent intent);
-
- /**
- * Register an BroadcastReceiver to be run in the main activity thread. The
- * <var>receiver</var> will be called with any broadcast Intent that
- * matches <var>filter</var>, in the main application thread.
- *
- * <p>The system may broadcast Intents that are "sticky" -- these stay
- * around after the broadcast as finished, to be sent to any later
- * registrations. If your IntentFilter matches one of these sticky
- * Intents, that Intent will be returned by this function
- * <strong>and</strong> sent to your <var>receiver</var> as if it had just
- * been broadcast.
- *
- * <p>There may be multiple sticky Intents that match <var>filter</var>,
- * in which case each of these will be sent to <var>receiver</var>. In
- * this case, only one of these can be returned directly by the function;
- * which of these that is returned is arbitrarily decided by the system.
- *
- * <p>If you know the Intent your are registering for is sticky, you can
- * supply null for your <var>receiver</var>. In this case, no receiver is
- * registered -- the function simply returns the sticky Intent that
- * matches <var>filter</var>. In the case of multiple matches, the same
- * rules as described above apply.
- *
- * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
- *
- * <p class="note">Note: this method <em>can not be called from an
- * {@link BroadcastReceiver} component</em>. It is okay, however, to use
- * this method from another BroadcastReceiver that has itself been registered with
- * {@link #registerReceiver}, since the lifetime of such an BroadcastReceiver
- * is tied to another object (the one that registered it).</p>
- *
- * @param receiver The BroadcastReceiver to handle the broadcast.
- * @param filter Selects the Intent broadcasts to be received.
- *
- * @return The first sticky intent found that matches <var>filter</var>,
- * or null if there are none.
- *
- * @see #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)
- * @see #sendBroadcast
- * @see #unregisterReceiver
- */
- public abstract Intent registerReceiver(BroadcastReceiver receiver,
- IntentFilter filter);
-
- /**
- * Register to receive intent broadcasts, to run in the context of
- * <var>scheduler</var>. See
- * {@link #registerReceiver(BroadcastReceiver, IntentFilter)} for more
- * information. This allows you to enforce permissions on who can
- * broadcast intents to your receiver, or have the receiver run in
- * a different thread than the main application thread.
- *
- * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
- *
- * @param receiver The BroadcastReceiver to handle the broadcast.
- * @param filter Selects the Intent broadcasts to be received.
- * @param broadcastPermission String naming a permissions that a
- * broadcaster must hold in order to send an Intent to you. If null,
- * no permission is required.
- * @param scheduler Handler identifying the thread that will receive
- * the Intent. If null, the main thread of the process will be used.
- *
- * @return The first sticky intent found that matches <var>filter</var>,
- * or null if there are none.
- *
- * @see #registerReceiver(BroadcastReceiver, IntentFilter)
- * @see #sendBroadcast
- * @see #unregisterReceiver
- */
- public abstract Intent registerReceiver(BroadcastReceiver receiver,
- IntentFilter filter,
- String broadcastPermission,
- Handler scheduler);
-
- /**
- * Unregister a previously registered BroadcastReceiver. <em>All</em>
- * filters that have been registered for this BroadcastReceiver will be
- * removed.
- *
- * @param receiver The BroadcastReceiver to unregister.
- *
- * @see #registerReceiver
- */
- public abstract void unregisterReceiver(BroadcastReceiver receiver);
-
- /**
- * Request that a given application service be started. The Intent
- * can either contain the complete class name of a specific service
- * implementation to start, or an abstract definition through the
- * action and other fields of the kind of service to start. If this service
- * is not already running, it will be instantiated and started (creating a
- * process for it if needed); if it is running then it remains running.
- *
- * <p>Every call to this method will result in a corresponding call to
- * the target service's {@link android.app.Service#onStart} method,
- * with the <var>intent</var> given here. This provides a convenient way
- * to submit jobs to a service without having to bind and call on to its
- * interface.
- *
- * <p>Using startService() overrides the default service lifetime that is
- * managed by {@link #bindService}: it requires the service to remain
- * running until {@link #stopService} is called, regardless of whether
- * any clients are connected to it. Note that calls to startService()
- * are not nesting: no matter how many times you call startService(),
- * a single call to {@link #stopService} will stop it.
- *
- * <p>The system attempts to keep running services around as much as
- * possible. The only time they should be stopped is if the current
- * foreground application is using so many resources that the service needs
- * to be killed. If any errors happen in the service's process, it will
- * automatically be restarted.
- *
- * <p>This function will throw {@link SecurityException} if you do not
- * have permission to start the given service.
- *
- * @param service Identifies the service to be started. The Intent may
- * specify either an explicit component name to start, or a logical
- * description (action, category, etc) to match an
- * {@link IntentFilter} published by a service. Additional values
- * may be included in the Intent extras to supply arguments along with
- * this specific start call.
- *
- * @return If the service is being started or is already running, the
- * {@link ComponentName} of the actual service that was started is
- * returned; else if the service does not exist null is returned.
- *
- * @throws SecurityException
- *
- * @see #stopService
- * @see #bindService
- */
- public abstract ComponentName startService(Intent service);
-
- /**
- * Request that a given application service be stopped. If the service is
- * not running, nothing happens. Otherwise it is stopped. Note that calls
- * to startService() are not counted -- this stops the service no matter
- * how many times it was started.
- *
- * <p>Note that if a stopped service still has {@link ServiceConnection}
- * objects bound to it with the {@link #BIND_AUTO_CREATE} set, it will
- * not be destroyed until all of these bindings are removed. See
- * the {@link android.app.Service} documentation for more details on a
- * service's lifecycle.
- *
- * <p>This function will throw {@link SecurityException} if you do not
- * have permission to stop the given service.
- *
- * @param service Description of the service to be stopped. The Intent may
- * specify either an explicit component name to start, or a logical
- * description (action, category, etc) to match an
- * {@link IntentFilter} published by a service.
- *
- * @return If there is a service matching the given Intent that is already
- * running, then it is stopped and true is returned; else false is returned.
- *
- * @throws SecurityException
- *
- * @see #startService
- */
- public abstract boolean stopService(Intent service);
-
- /**
- * Connect to an application service, creating it if needed. This defines
- * a dependency between your application and the service. The given
- * <var>conn</var> will receive the service object when its created and be
- * told if it dies and restarts. The service will be considered required
- * by the system only for as long as the calling context exists. For
- * example, if this Context is an Activity that is stopped, the service will
- * not be required to continue running until the Activity is resumed.
- *
- * <p>This function will throw {@link SecurityException} if you do not
- * have permission to bind to the given service.
- *
- * <p class="note">Note: this method <em>can not be called from an
- * {@link BroadcastReceiver} component</em>. A pattern you can use to
- * communicate from an BroadcastReceiver to a Service is to call
- * {@link #startService} with the arguments containing the command to be
- * sent, with the service calling its
- * {@link android.app.Service#stopSelf(int)} method when done executing
- * that command. See the API demo App/Service/Service Start Arguments
- * Controller for an illustration of this. It is okay, however, to use
- * this method from an BroadcastReceiver that has been registered with
- * {@link #registerReceiver}, since the lifetime of this BroadcastReceiver
- * is tied to another object (the one that registered it).</p>
- *
- * @param service Identifies the service to connect to. The Intent may
- * specify either an explicit component name, or a logical
- * description (action, category, etc) to match an
- * {@link IntentFilter} published by a service.
- * @param conn Receives information as the service is started and stopped.
- * @param flags Operation options for the binding. May be 0 or
- * {@link #BIND_AUTO_CREATE}.
- * @return If you have successfully bound to the service, true is returned;
- * false is returned if the connection is not made so you will not
- * receive the service object.
- *
- * @throws SecurityException
- *
- * @see #unbindService
- * @see #startService
- * @see #BIND_AUTO_CREATE
- */
- public abstract boolean bindService(Intent service, ServiceConnection conn,
- int flags);
-
- /**
- * Disconnect from an application service. You will no longer receive
- * calls as the service is restarted, and the service is now allowed to
- * stop at any time.
- *
- * @param conn The connection interface previously supplied to
- * bindService().
- *
- * @see #bindService
- */
- public abstract void unbindService(ServiceConnection conn);
-
- /**
- * Start executing an {@link android.app.Instrumentation} class. The given
- * Instrumentation component will be run by killing its target application
- * (if currently running), starting the target process, instantiating the
- * instrumentation component, and then letting it drive the application.
- *
- * <p>This function is not synchronous -- it returns as soon as the
- * instrumentation has started and while it is running.
- *
- * <p>Instrumentation is normally only allowed to run against a package
- * that is either unsigned or signed with a signature that the
- * the instrumentation package is also signed with (ensuring the target
- * trusts the instrumentation).
- *
- * @param className Name of the Instrumentation component to be run.
- * @param profileFile Optional path to write profiling data as the
- * instrumentation runs, or null for no profiling.
- * @param arguments Additional optional arguments to pass to the
- * instrumentation, or null.
- *
- * @return Returns true if the instrumentation was successfully started,
- * else false if it could not be found.
- */
- public abstract boolean startInstrumentation(ComponentName className,
- String profileFile, Bundle arguments);
-
- /**
- * Return the handle to a system-level service by name. The class of the
- * returned object varies by the requested name. Currently available names
- * are:
- *
- * <dl>
- * <dt> {@link #WINDOW_SERVICE} ("window")
- * <dd> The top-level window manager in which you can place custom
- * windows. The returned object is a {@link android.view.WindowManager}.
- * <dt> {@link #LAYOUT_INFLATER_SERVICE} ("layout_inflater")
- * <dd> A {@link android.view.LayoutInflater} for inflating layout resources
- * in this context.
- * <dt> {@link #ACTIVITY_SERVICE} ("activity")
- * <dd> A {@link android.app.ActivityManager} for interacting with the
- * global activity state of the system.
- * <dt> {@link #POWER_SERVICE} ("power")
- * <dd> A {@link android.os.PowerManager} for controlling power
- * management.
- * <dt> {@link #ALARM_SERVICE} ("alarm")
- * <dd> A {@link android.app.AlarmManager} for receiving intents at the
- * time of your choosing.
- * <dt> {@link #NOTIFICATION_SERVICE} ("notification")
- * <dd> A {@link android.app.NotificationManager} for informing the user
- * of background events.
- * <dt> {@link #KEYGUARD_SERVICE} ("keyguard")
- * <dd> A {@link android.app.KeyguardManager} for controlling keyguard.
- * <dt> {@link #LOCATION_SERVICE} ("location")
- * <dd> A {@link android.location.LocationManager} for controlling location
- * (e.g., GPS) updates.
- * <dt> {@link #SEARCH_SERVICE} ("search")
- * <dd> A {@link android.app.SearchManager} for handling search.
- * <dt> {@link #VIBRATOR_SERVICE} ("vibrator")
- * <dd> A {@link android.os.Vibrator} for interacting with the vibrator
- * hardware.
- * <dt> {@link #CONNECTIVITY_SERVICE} ("connection")
- * <dd> A {@link android.net.ConnectivityManager ConnectivityManager} for
- * handling management of network connections.
- * <dt> {@link #WIFI_SERVICE} ("wifi")
- * <dd> A {@link android.net.wifi.WifiManager WifiManager} for management of
- * Wi-Fi connectivity.
- * <dt> {@link #INPUT_METHOD_SERVICE} ("input_method")
- * <dd> An {@link android.view.inputmethod.InputMethodManager InputMethodManager}
- * for management of input methods.
- * </dl>
- *
- * <p>Note: System services obtained via this API may be closely associated with
- * the Context in which they are obtained from. In general, do not share the
- * service objects between various different contexts (Activities, Applications,
- * Services, Providers, etc.)
- *
- * @param name The name of the desired service.
- *
- * @return The service or null if the name does not exist.
- *
- * @see #WINDOW_SERVICE
- * @see android.view.WindowManager
- * @see #LAYOUT_INFLATER_SERVICE
- * @see android.view.LayoutInflater
- * @see #ACTIVITY_SERVICE
- * @see android.app.ActivityManager
- * @see #POWER_SERVICE
- * @see android.os.PowerManager
- * @see #ALARM_SERVICE
- * @see android.app.AlarmManager
- * @see #NOTIFICATION_SERVICE
- * @see android.app.NotificationManager
- * @see #KEYGUARD_SERVICE
- * @see android.app.KeyguardManager
- * @see #LOCATION_SERVICE
- * @see android.location.LocationManager
- * @see #SEARCH_SERVICE
- * @see android.app.SearchManager
- * @see #SENSOR_SERVICE
- * @see android.hardware.SensorManager
- * @see #VIBRATOR_SERVICE
- * @see android.os.Vibrator
- * @see #CONNECTIVITY_SERVICE
- * @see android.net.ConnectivityManager
- * @see #WIFI_SERVICE
- * @see android.net.wifi.WifiManager
- * @see #AUDIO_SERVICE
- * @see android.media.AudioManager
- * @see #TELEPHONY_SERVICE
- * @see android.telephony.TelephonyManager
- * @see #INPUT_METHOD_SERVICE
- * @see android.view.inputmethod.InputMethodManager
- */
- public abstract Object getSystemService(String name);
-
- /**
- * Use with {@link #getSystemService} to retrieve a
- * {@link android.os.PowerManager} for controlling power management,
- * including "wake locks," which let you keep the device on while
- * you're running long tasks.
- */
- public static final String POWER_SERVICE = "power";
- /**
- * Use with {@link #getSystemService} to retrieve a
- * {@link android.view.WindowManager} for accessing the system's window
- * manager.
- *
- * @see #getSystemService
- * @see android.view.WindowManager
- */
- public static final String WINDOW_SERVICE = "window";
- /**
- * Use with {@link #getSystemService} to retrieve a
- * {@link android.view.LayoutInflater} for inflating layout resources in this
- * context.
- *
- * @see #getSystemService
- * @see android.view.LayoutInflater
- */
- public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
- /**
- * Use with {@link #getSystemService} to retrieve a
- * {@link android.app.ActivityManager} for interacting with the global
- * system state.
- *
- * @see #getSystemService
- * @see android.app.ActivityManager
- */
- public static final String ACTIVITY_SERVICE = "activity";
- /**
- * Use with {@link #getSystemService} to retrieve a
- * {@link android.app.AlarmManager} for receiving intents at a
- * time of your choosing.
- *
- * @see #getSystemService
- * @see android.app.AlarmManager
- */
- public static final String ALARM_SERVICE = "alarm";
- /**
- * Use with {@link #getSystemService} to retrieve a
- * {@link android.app.NotificationManager} for informing the user of
- * background events.
- *
- * @see #getSystemService
- * @see android.app.NotificationManager
- */
- public static final String NOTIFICATION_SERVICE = "notification";
- /**
- * Use with {@link #getSystemService} to retrieve a
- * {@link android.app.NotificationManager} for controlling keyguard.
- *
- * @see #getSystemService
- * @see android.app.KeyguardManager
- */
- public static final String KEYGUARD_SERVICE = "keyguard";
- /**
- * Use with {@link #getSystemService} to retrieve a {@link
- * android.location.LocationManager} for controlling location
- * updates.
- *
- * @see #getSystemService
- * @see android.location.LocationManager
- */
- public static final String LOCATION_SERVICE = "location";
- /**
- * Use with {@link #getSystemService} to retrieve a {@link
- * android.app.SearchManager} for handling searches.
- *
- * @see #getSystemService
- * @see android.app.SearchManager
- */
- public static final String SEARCH_SERVICE = "search";
- /**
- * Use with {@link #getSystemService} to retrieve a {@link
- * android.hardware.SensorManager} for accessing sensors.
- *
- * @see #getSystemService
- * @see android.hardware.SensorManager
- */
- public static final String SENSOR_SERVICE = "sensor";
- /**
- * Use with {@link #getSystemService} to retrieve a {@link
- * android.bluetooth.BluetoothDevice} for interacting with Bluetooth.
- *
- * @see #getSystemService
- * @see android.bluetooth.BluetoothDevice
- * @hide
- */
- public static final String BLUETOOTH_SERVICE = "bluetooth";
- /**
- * Use with {@link #getSystemService} to retrieve a
- * com.android.server.WallpaperService for accessing wallpapers.
- *
- * @see #getSystemService
- */
- public static final String WALLPAPER_SERVICE = "wallpaper";
- /**
- * Use with {@link #getSystemService} to retrieve a {@link
- * android.os.Vibrator} for interacting with the vibration hardware.
- *
- * @see #getSystemService
- * @see android.os.Vibrator
- */
- public static final String VIBRATOR_SERVICE = "vibrator";
- /**
- * Use with {@link #getSystemService} to retrieve a {@link
- * android.app.StatusBarManager} for interacting with the status bar.
- *
- * @see #getSystemService
- * @see android.app.StatusBarManager
- * @hide
- */
- public static final String STATUS_BAR_SERVICE = "statusbar";
-
- /**
- * Use with {@link #getSystemService} to retrieve a {@link
- * android.net.ConnectivityManager} for handling management of
- * network connections.
- *
- * @see #getSystemService
- * @see android.net.ConnectivityManager
- */
- public static final String CONNECTIVITY_SERVICE = "connectivity";
-
- /**
- * Use with {@link #getSystemService} to retrieve a {@link
- * android.net.wifi.WifiManager} for handling management of
- * Wi-Fi access.
- *
- * @see #getSystemService
- * @see android.net.wifi.WifiManager
- */
- public static final String WIFI_SERVICE = "wifi";
-
- /**
- * Use with {@link #getSystemService} to retrieve a
- * {@link android.media.AudioManager} for handling management of volume,
- * ringer modes and audio routing.
- *
- * @see #getSystemService
- * @see android.media.AudioManager
- */
- public static final String AUDIO_SERVICE = "audio";
-
- /**
- * Use with {@link #getSystemService} to retrieve a
- * {@link android.telephony.TelephonyManager} for handling management the
- * telephony features of the device.
- *
- * @see #getSystemService
- * @see android.telephony.TelephonyManager
- */
- public static final String TELEPHONY_SERVICE = "phone";
-
- /**
- * Use with {@link #getSystemService} to retrieve a
- * {@link android.text.ClipboardManager} for accessing and modifying
- * the contents of the global clipboard.
- *
- * @see #getSystemService
- * @see android.text.ClipboardManager
- */
- public static final String CLIPBOARD_SERVICE = "clipboard";
-
- /**
- * Use with {@link #getSystemService} to retrieve a
- * {@link android.view.inputmethod.InputMethodManager} for accessing input
- * methods.
- *
- * @see #getSystemService
- */
- public static final String INPUT_METHOD_SERVICE = "input_method";
-
- /**
- * Use with {@link #getSystemService} to retrieve a
- * {@blink android.gadget.GadgetManager} for accessing wallpapers.
- *
- * @hide
- * @see #getSystemService
- */
- public static final String GADGET_SERVICE = "gadget";
-
- /**
- * Determine whether the given permission is allowed for a particular
- * process and user ID running in the system.
- *
- * @param permission The name of the permission being checked.
- * @param pid The process ID being checked against. Must be > 0.
- * @param uid The user ID being checked against. A uid of 0 is the root
- * user, which will pass every permission check.
- *
- * @return Returns {@link PackageManager#PERMISSION_GRANTED} if the given
- * pid/uid is allowed that permission, or
- * {@link PackageManager#PERMISSION_DENIED} if it is not.
- *
- * @see PackageManager#checkPermission(String, String)
- * @see #checkCallingPermission
- */
- public abstract int checkPermission(String permission, int pid, int uid);
-
- /**
- * Determine whether the calling process of an IPC you are handling has been
- * granted a particular permission. This is basically the same as calling
- * {@link #checkPermission(String, int, int)} with the pid and uid returned
- * by {@link android.os.Binder#getCallingPid} and
- * {@link android.os.Binder#getCallingUid}. One important difference
- * is that if you are not currently processing an IPC, this function
- * will always fail. This is done to protect against accidentally
- * leaking permissions; you can use {@link #checkCallingOrSelfPermission}
- * to avoid this protection.
- *
- * @param permission The name of the permission being checked.
- *
- * @return Returns {@link PackageManager#PERMISSION_GRANTED} if the calling
- * pid/uid is allowed that permission, or
- * {@link PackageManager#PERMISSION_DENIED} if it is not.
- *
- * @see PackageManager#checkPermission(String, String)
- * @see #checkPermission
- * @see #checkCallingOrSelfPermission
- */
- public abstract int checkCallingPermission(String permission);
-
- /**
- * Determine whether the calling process of an IPC <em>or you</em> have been
- * granted a particular permission. This is the same as
- * {@link #checkCallingPermission}, except it grants your own permissions
- * if you are not currently processing an IPC. Use with care!
- *
- * @param permission The name of the permission being checked.
- *
- * @return Returns {@link PackageManager#PERMISSION_GRANTED} if the calling
- * pid/uid is allowed that permission, or
- * {@link PackageManager#PERMISSION_DENIED} if it is not.
- *
- * @see PackageManager#checkPermission(String, String)
- * @see #checkPermission
- * @see #checkCallingPermission
- */
- public abstract int checkCallingOrSelfPermission(String permission);
-
- /**
- * If the given permission is not allowed for a particular process
- * and user ID running in the system, throw a {@link SecurityException}.
- *
- * @param permission The name of the permission being checked.
- * @param pid The process ID being checked against. Must be &gt; 0.
- * @param uid The user ID being checked against. A uid of 0 is the root
- * user, which will pass every permission check.
- * @param message A message to include in the exception if it is thrown.
- *
- * @see #checkPermission(String, int, int)
- */
- public abstract void enforcePermission(
- String permission, int pid, int uid, String message);
-
- /**
- * If the calling process of an IPC you are handling has not been
- * granted a particular permission, throw a {@link
- * SecurityException}. This is basically the same as calling
- * {@link #enforcePermission(String, int, int, String)} with the
- * pid and uid returned by {@link android.os.Binder#getCallingPid}
- * and {@link android.os.Binder#getCallingUid}. One important
- * difference is that if you are not currently processing an IPC,
- * this function will always throw the SecurityException. This is
- * done to protect against accidentally leaking permissions; you
- * can use {@link #enforceCallingOrSelfPermission} to avoid this
- * protection.
- *
- * @param permission The name of the permission being checked.
- * @param message A message to include in the exception if it is thrown.
- *
- * @see #checkCallingPermission(String)
- */
- public abstract void enforceCallingPermission(
- String permission, String message);
-
- /**
- * If neither you nor the calling process of an IPC you are
- * handling has been granted a particular permission, throw a
- * {@link SecurityException}. This is the same as {@link
- * #enforceCallingPermission}, except it grants your own
- * permissions if you are not currently processing an IPC. Use
- * with care!
- *
- * @param permission The name of the permission being checked.
- * @param message A message to include in the exception if it is thrown.
- *
- * @see #checkCallingOrSelfPermission(String)
- */
- public abstract void enforceCallingOrSelfPermission(
- String permission, String message);
-
- /**
- * Grant permission to access a specific Uri to another package, regardless
- * of whether that package has general permission to access the Uri's
- * content provider. This can be used to grant specific, temporary
- * permissions, typically in response to user interaction (such as the
- * user opening an attachment that you would like someone else to
- * display).
- *
- * <p>Normally you should use {@link Intent#FLAG_GRANT_READ_URI_PERMISSION
- * Intent.FLAG_GRANT_READ_URI_PERMISSION} or
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION
- * Intent.FLAG_GRANT_WRITE_URI_PERMISSION} with the Intent being used to
- * start an activity instead of this function directly. If you use this
- * function directly, you should be sure to call
- * {@link #revokeUriPermission} when the target should no longer be allowed
- * to access it.
- *
- * <p>To succeed, the content provider owning the Uri must have set the
- * {@link android.R.styleable#AndroidManifestProvider_grantUriPermissions
- * grantUriPermissions} attribute in its manifest or included the
- * {@link android.R.styleable#AndroidManifestGrantUriPermission
- * &lt;grant-uri-permissions&gt;} tag.
- *
- * @param toPackage The package you would like to allow to access the Uri.
- * @param uri The Uri you would like to grant access to.
- * @param modeFlags The desired access modes. Any combination of
- * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION
- * Intent.FLAG_GRANT_READ_URI_PERMISSION} or
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION
- * Intent.FLAG_GRANT_WRITE_URI_PERMISSION}.
- *
- * @see #revokeUriPermission
- */
- public abstract void grantUriPermission(String toPackage, Uri uri,
- int modeFlags);
-
- /**
- * Remove all permissions to access a particular content provider Uri
- * that were previously added with {@link #grantUriPermission}. The given
- * Uri will match all previously granted Uris that are the same or a
- * sub-path of the given Uri. That is, revoking "content://foo/one" will
- * revoke both "content://foo/target" and "content://foo/target/sub", but not
- * "content://foo".
- *
- * @param uri The Uri you would like to revoke access to.
- * @param modeFlags The desired access modes. Any combination of
- * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION
- * Intent.FLAG_GRANT_READ_URI_PERMISSION} or
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION
- * Intent.FLAG_GRANT_WRITE_URI_PERMISSION}.
- *
- * @see #grantUriPermission
- */
- public abstract void revokeUriPermission(Uri uri, int modeFlags);
-
- /**
- * Determine whether a particular process and user ID has been granted
- * permission to access a specific URI. This only checks for permissions
- * that have been explicitly granted -- if the given process/uid has
- * more general access to the URI's content provider then this check will
- * always fail.
- *
- * @param uri The uri that is being checked.
- * @param pid The process ID being checked against. Must be &gt; 0.
- * @param uid The user ID being checked against. A uid of 0 is the root
- * user, which will pass every permission check.
- * @param modeFlags The type of access to grant. May be one or both of
- * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}.
- *
- * @return Returns {@link PackageManager#PERMISSION_GRANTED} if the given
- * pid/uid is allowed to access that uri, or
- * {@link PackageManager#PERMISSION_DENIED} if it is not.
- *
- * @see #checkCallingUriPermission
- */
- public abstract int checkUriPermission(Uri uri, int pid, int uid, int modeFlags);
-
- /**
- * Determine whether the calling process and user ID has been
- * granted permission to access a specific URI. This is basically
- * the same as calling {@link #checkUriPermission(Uri, int, int,
- * int)} with the pid and uid returned by {@link
- * android.os.Binder#getCallingPid} and {@link
- * android.os.Binder#getCallingUid}. One important difference is
- * that if you are not currently processing an IPC, this function
- * will always fail.
- *
- * @param uri The uri that is being checked.
- * @param modeFlags The type of access to grant. May be one or both of
- * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}.
- *
- * @return Returns {@link PackageManager#PERMISSION_GRANTED} if the caller
- * is allowed to access that uri, or
- * {@link PackageManager#PERMISSION_DENIED} if it is not.
- *
- * @see #checkUriPermission(Uri, int, int, int)
- */
- public abstract int checkCallingUriPermission(Uri uri, int modeFlags);
-
- /**
- * Determine whether the calling process of an IPC <em>or you</em> has been granted
- * permission to access a specific URI. This is the same as
- * {@link #checkCallingUriPermission}, except it grants your own permissions
- * if you are not currently processing an IPC. Use with care!
- *
- * @param uri The uri that is being checked.
- * @param modeFlags The type of access to grant. May be one or both of
- * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}.
- *
- * @return Returns {@link PackageManager#PERMISSION_GRANTED} if the caller
- * is allowed to access that uri, or
- * {@link PackageManager#PERMISSION_DENIED} if it is not.
- *
- * @see #checkCallingUriPermission
- */
- public abstract int checkCallingOrSelfUriPermission(Uri uri, int modeFlags);
-
- /**
- * Check both a Uri and normal permission. This allows you to perform
- * both {@link #checkPermission} and {@link #checkUriPermission} in one
- * call.
- *
- * @param uri The Uri whose permission is to be checked, or null to not
- * do this check.
- * @param readPermission The permission that provides overall read access,
- * or null to not do this check.
- * @param writePermission The permission that provides overall write
- * acess, or null to not do this check.
- * @param pid The process ID being checked against. Must be &gt; 0.
- * @param uid The user ID being checked against. A uid of 0 is the root
- * user, which will pass every permission check.
- * @param modeFlags The type of access to grant. May be one or both of
- * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}.
- *
- * @return Returns {@link PackageManager#PERMISSION_GRANTED} if the caller
- * is allowed to access that uri or holds one of the given permissions, or
- * {@link PackageManager#PERMISSION_DENIED} if it is not.
- */
- public abstract int checkUriPermission(Uri uri, String readPermission,
- String writePermission, int pid, int uid, int modeFlags);
-
- /**
- * If a particular process and user ID has not been granted
- * permission to access a specific URI, throw {@link
- * SecurityException}. This only checks for permissions that have
- * been explicitly granted -- if the given process/uid has more
- * general access to the URI's content provider then this check
- * will always fail.
- *
- * @param uri The uri that is being checked.
- * @param pid The process ID being checked against. Must be &gt; 0.
- * @param uid The user ID being checked against. A uid of 0 is the root
- * user, which will pass every permission check.
- * @param modeFlags The type of access to grant. May be one or both of
- * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}.
- * @param message A message to include in the exception if it is thrown.
- *
- * @see #checkUriPermission(Uri, int, int, int)
- */
- public abstract void enforceUriPermission(
- Uri uri, int pid, int uid, int modeFlags, String message);
-
- /**
- * If the calling process and user ID has not been granted
- * permission to access a specific URI, throw {@link
- * SecurityException}. This is basically the same as calling
- * {@link #enforceUriPermission(Uri, int, int, int, String)} with
- * the pid and uid returned by {@link
- * android.os.Binder#getCallingPid} and {@link
- * android.os.Binder#getCallingUid}. One important difference is
- * that if you are not currently processing an IPC, this function
- * will always throw a SecurityException.
- *
- * @param uri The uri that is being checked.
- * @param modeFlags The type of access to grant. May be one or both of
- * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}.
- * @param message A message to include in the exception if it is thrown.
- *
- * @see #checkCallingUriPermission(Uri, int)
- */
- public abstract void enforceCallingUriPermission(
- Uri uri, int modeFlags, String message);
-
- /**
- * If the calling process of an IPC <em>or you</em> has not been
- * granted permission to access a specific URI, throw {@link
- * SecurityException}. This is the same as {@link
- * #enforceCallingUriPermission}, except it grants your own
- * permissions if you are not currently processing an IPC. Use
- * with care!
- *
- * @param uri The uri that is being checked.
- * @param modeFlags The type of access to grant. May be one or both of
- * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}.
- * @param message A message to include in the exception if it is thrown.
- *
- * @see #checkCallingOrSelfUriPermission(Uri, int)
- */
- public abstract void enforceCallingOrSelfUriPermission(
- Uri uri, int modeFlags, String message);
-
- /**
- * Enforce both a Uri and normal permission. This allows you to perform
- * both {@link #enforcePermission} and {@link #enforceUriPermission} in one
- * call.
- *
- * @param uri The Uri whose permission is to be checked, or null to not
- * do this check.
- * @param readPermission The permission that provides overall read access,
- * or null to not do this check.
- * @param writePermission The permission that provides overall write
- * acess, or null to not do this check.
- * @param pid The process ID being checked against. Must be &gt; 0.
- * @param uid The user ID being checked against. A uid of 0 is the root
- * user, which will pass every permission check.
- * @param modeFlags The type of access to grant. May be one or both of
- * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION Intent.FLAG_GRANT_READ_URI_PERMISSION} or
- * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION Intent.FLAG_GRANT_WRITE_URI_PERMISSION}.
- * @param message A message to include in the exception if it is thrown.
- *
- * @see #checkUriPermission(Uri, String, String, int, int, int)
- */
- public abstract void enforceUriPermission(
- Uri uri, String readPermission, String writePermission,
- int pid, int uid, int modeFlags, String message);
-
- /**
- * Flag for use with {@link #createPackageContext}: include the application
- * code with the context. This means loading code into the caller's
- * process, so that {@link #getClassLoader()} can be used to instantiate
- * the application's classes. Setting this flags imposes security
- * restrictions on what application context you can access; if the
- * requested application can not be safely loaded into your process,
- * java.lang.SecurityException will be thrown. If this flag is not set,
- * there will be no restrictions on the packages that can be loaded,
- * but {@link #getClassLoader} will always return the default system
- * class loader.
- */
- public static final int CONTEXT_INCLUDE_CODE = 0x00000001;
-
- /**
- * Flag for use with {@link #createPackageContext}: ignore any security
- * restrictions on the Context being requested, allowing it to always
- * be loaded. For use with {@link #CONTEXT_INCLUDE_CODE} to allow code
- * to be loaded into a process even when it isn't safe to do so. Use
- * with extreme care!
- */
- public static final int CONTEXT_IGNORE_SECURITY = 0x00000002;
-
- /**
- * Return a new Context object for the given application name. This
- * Context is the same as what the named application gets when it is
- * launched, containing the same resources and class loader. Each call to
- * this method returns a new instance of a Context object; Context objects
- * are not shared, however they share common state (Resources, ClassLoader,
- * etc) so the Context instance itself is fairly lightweight.
- *
- * <p>Throws {@link PackageManager.NameNotFoundException} if there is no
- * application with the given package name.
- *
- * <p>Throws {@link java.lang.SecurityException} if the Context requested
- * can not be loaded into the caller's process for security reasons (see
- * {@link #CONTEXT_INCLUDE_CODE} for more information}.
- *
- * @param packageName Name of the application's package.
- * @param flags Option flags, one of {@link #CONTEXT_INCLUDE_CODE}
- * or {@link #CONTEXT_IGNORE_SECURITY}.
- *
- * @return A Context for the application.
- *
- * @throws java.lang.SecurityException
- * @throws PackageManager.NameNotFoundException if there is no application with
- * the given package name
- */
- public abstract Context createPackageContext(String packageName,
- int flags) throws PackageManager.NameNotFoundException;
-}
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
deleted file mode 100644
index 36e1c34..0000000
--- a/core/java/android/content/ContextWrapper.java
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.content.pm.PackageManager;
-import android.content.res.AssetManager;
-import android.content.res.Resources;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteDatabase.CursorFactory;
-import android.graphics.Bitmap;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Proxying implementation of Context that simply delegates all of its calls to
- * another Context. Can be subclassed to modify behavior without changing
- * the original Context.
- */
-public class ContextWrapper extends Context {
- Context mBase;
-
- public ContextWrapper(Context base) {
- mBase = base;
- }
-
- /**
- * Set the base context for this ContextWrapper. All calls will then be
- * delegated to the base context. Throws
- * IllegalStateException if a base context has already been set.
- *
- * @param base The new base context for this wrapper.
- */
- protected void attachBaseContext(Context base) {
- if (mBase != null) {
- throw new IllegalStateException("Base context already set");
- }
- mBase = base;
- }
-
- /**
- * @return the base context as set by the constructor or setBaseContext
- */
- public Context getBaseContext() {
- return mBase;
- }
-
- @Override
- public AssetManager getAssets() {
- return mBase.getAssets();
- }
-
- @Override
- public Resources getResources()
- {
- return mBase.getResources();
- }
-
- @Override
- public PackageManager getPackageManager() {
- return mBase.getPackageManager();
- }
-
- @Override
- public ContentResolver getContentResolver() {
- return mBase.getContentResolver();
- }
-
- @Override
- public Looper getMainLooper() {
- return mBase.getMainLooper();
- }
-
- @Override
- public Context getApplicationContext() {
- return mBase.getApplicationContext();
- }
-
- @Override
- public void setTheme(int resid) {
- mBase.setTheme(resid);
- }
-
- @Override
- public Resources.Theme getTheme() {
- return mBase.getTheme();
- }
-
- @Override
- public ClassLoader getClassLoader() {
- return mBase.getClassLoader();
- }
-
- @Override
- public String getPackageName() {
- return mBase.getPackageName();
- }
-
- @Override
- public String getPackageResourcePath() {
- return mBase.getPackageResourcePath();
- }
-
- @Override
- public String getPackageCodePath() {
- return mBase.getPackageCodePath();
- }
-
- @Override
- public SharedPreferences getSharedPreferences(String name, int mode) {
- return mBase.getSharedPreferences(name, mode);
- }
-
- @Override
- public FileInputStream openFileInput(String name)
- throws FileNotFoundException {
- return mBase.openFileInput(name);
- }
-
- @Override
- public FileOutputStream openFileOutput(String name, int mode)
- throws FileNotFoundException {
- return mBase.openFileOutput(name, mode);
- }
-
- @Override
- public boolean deleteFile(String name) {
- return mBase.deleteFile(name);
- }
-
- @Override
- public File getFileStreamPath(String name) {
- return mBase.getFileStreamPath(name);
- }
-
- @Override
- public String[] fileList() {
- return mBase.fileList();
- }
-
- @Override
- public File getFilesDir() {
- return mBase.getFilesDir();
- }
-
- @Override
- public File getCacheDir() {
- return mBase.getCacheDir();
- }
-
- @Override
- public File getDir(String name, int mode) {
- return mBase.getDir(name, mode);
- }
-
- @Override
- public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
- return mBase.openOrCreateDatabase(name, mode, factory);
- }
-
- @Override
- public boolean deleteDatabase(String name) {
- return mBase.deleteDatabase(name);
- }
-
- @Override
- public File getDatabasePath(String name) {
- return mBase.getDatabasePath(name);
- }
-
- @Override
- public String[] databaseList() {
- return mBase.databaseList();
- }
-
- @Override
- public Drawable getWallpaper() {
- return mBase.getWallpaper();
- }
-
- @Override
- public Drawable peekWallpaper() {
- return mBase.peekWallpaper();
- }
-
- @Override
- public int getWallpaperDesiredMinimumWidth() {
- return mBase.getWallpaperDesiredMinimumWidth();
- }
-
- @Override
- public int getWallpaperDesiredMinimumHeight() {
- return mBase.getWallpaperDesiredMinimumHeight();
- }
-
- @Override
- public void setWallpaper(Bitmap bitmap) throws IOException {
- mBase.setWallpaper(bitmap);
- }
-
- @Override
- public void setWallpaper(InputStream data) throws IOException {
- mBase.setWallpaper(data);
- }
-
- @Override
- public void clearWallpaper() throws IOException {
- mBase.clearWallpaper();
- }
-
- @Override
- public void startActivity(Intent intent) {
- mBase.startActivity(intent);
- }
-
- @Override
- public void sendBroadcast(Intent intent) {
- mBase.sendBroadcast(intent);
- }
-
- @Override
- public void sendBroadcast(Intent intent, String receiverPermission) {
- mBase.sendBroadcast(intent, receiverPermission);
- }
-
- @Override
- public void sendOrderedBroadcast(Intent intent,
- String receiverPermission) {
- mBase.sendOrderedBroadcast(intent, receiverPermission);
- }
-
- @Override
- public void sendOrderedBroadcast(
- Intent intent, String receiverPermission, BroadcastReceiver resultReceiver,
- Handler scheduler, int initialCode, String initialData,
- Bundle initialExtras) {
- mBase.sendOrderedBroadcast(intent, receiverPermission,
- resultReceiver, scheduler, initialCode,
- initialData, initialExtras);
- }
-
- @Override
- public void sendStickyBroadcast(Intent intent) {
- mBase.sendStickyBroadcast(intent);
- }
-
- @Override
- public void removeStickyBroadcast(Intent intent) {
- mBase.removeStickyBroadcast(intent);
- }
-
- @Override
- public Intent registerReceiver(
- BroadcastReceiver receiver, IntentFilter filter) {
- return mBase.registerReceiver(receiver, filter);
- }
-
- @Override
- public Intent registerReceiver(
- BroadcastReceiver receiver, IntentFilter filter,
- String broadcastPermission, Handler scheduler) {
- return mBase.registerReceiver(receiver, filter, broadcastPermission,
- scheduler);
- }
-
- @Override
- public void unregisterReceiver(BroadcastReceiver receiver) {
- mBase.unregisterReceiver(receiver);
- }
-
- @Override
- public ComponentName startService(Intent service) {
- return mBase.startService(service);
- }
-
- @Override
- public boolean stopService(Intent name) {
- return mBase.stopService(name);
- }
-
- @Override
- public boolean bindService(Intent service, ServiceConnection conn,
- int flags) {
- return mBase.bindService(service, conn, flags);
- }
-
- @Override
- public void unbindService(ServiceConnection conn) {
- mBase.unbindService(conn);
- }
-
- @Override
- public boolean startInstrumentation(ComponentName className,
- String profileFile, Bundle arguments) {
- return mBase.startInstrumentation(className, profileFile, arguments);
- }
-
- @Override
- public Object getSystemService(String name) {
- return mBase.getSystemService(name);
- }
-
- @Override
- public int checkPermission(String permission, int pid, int uid) {
- return mBase.checkPermission(permission, pid, uid);
- }
-
- @Override
- public int checkCallingPermission(String permission) {
- return mBase.checkCallingPermission(permission);
- }
-
- @Override
- public int checkCallingOrSelfPermission(String permission) {
- return mBase.checkCallingOrSelfPermission(permission);
- }
-
- @Override
- public void enforcePermission(
- String permission, int pid, int uid, String message) {
- mBase.enforcePermission(permission, pid, uid, message);
- }
-
- @Override
- public void enforceCallingPermission(String permission, String message) {
- mBase.enforceCallingPermission(permission, message);
- }
-
- @Override
- public void enforceCallingOrSelfPermission(
- String permission, String message) {
- mBase.enforceCallingOrSelfPermission(permission, message);
- }
-
- @Override
- public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
- mBase.grantUriPermission(toPackage, uri, modeFlags);
- }
-
- @Override
- public void revokeUriPermission(Uri uri, int modeFlags) {
- mBase.revokeUriPermission(uri, modeFlags);
- }
-
- @Override
- public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
- return mBase.checkUriPermission(uri, pid, uid, modeFlags);
- }
-
- @Override
- public int checkCallingUriPermission(Uri uri, int modeFlags) {
- return mBase.checkCallingUriPermission(uri, modeFlags);
- }
-
- @Override
- public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
- return mBase.checkCallingOrSelfUriPermission(uri, modeFlags);
- }
-
- @Override
- public int checkUriPermission(Uri uri, String readPermission,
- String writePermission, int pid, int uid, int modeFlags) {
- return mBase.checkUriPermission(uri, readPermission, writePermission,
- pid, uid, modeFlags);
- }
-
- @Override
- public void enforceUriPermission(
- Uri uri, int pid, int uid, int modeFlags, String message) {
- mBase.enforceUriPermission(uri, pid, uid, modeFlags, message);
- }
-
- @Override
- public void enforceCallingUriPermission(
- Uri uri, int modeFlags, String message) {
- mBase.enforceCallingUriPermission(uri, modeFlags, message);
- }
-
- @Override
- public void enforceCallingOrSelfUriPermission(
- Uri uri, int modeFlags, String message) {
- mBase.enforceCallingOrSelfUriPermission(uri, modeFlags, message);
- }
-
- @Override
- public void enforceUriPermission(
- Uri uri, String readPermission, String writePermission,
- int pid, int uid, int modeFlags, String message) {
- mBase.enforceUriPermission(
- uri, readPermission, writePermission, pid, uid, modeFlags,
- message);
- }
-
- @Override
- public Context createPackageContext(String packageName, int flags)
- throws PackageManager.NameNotFoundException {
- return mBase.createPackageContext(packageName, flags);
- }
-}
diff --git a/core/java/android/content/DefaultDataHandler.java b/core/java/android/content/DefaultDataHandler.java
deleted file mode 100644
index 863c9f6..0000000
--- a/core/java/android/content/DefaultDataHandler.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.net.Uri;
-import android.util.Xml;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Stack;
-
-/**
- * Inserts default data from InputStream, should be in XML format.
- * If the provider syncs data to the server, the imported data will be synced to the server.
- * <p>Samples:</p>
- * <br/>
- * Insert one row:
- * <pre>
- * &lt;row uri="content://contacts/people">
- * &lt;Col column = "name" value = "foo feebe "/>
- * &lt;Col column = "addr" value = "Tx"/>
- * &lt;/row></pre>
- * <br/>
- * Delete, it must be in order of uri, select, and arg:
- * <pre>
- * &lt;del uri="content://contacts/people" select="name=? and addr=?"
- * arg1 = "foo feebe" arg2 ="Tx"/></pre>
- * <br/>
- * Use first row's uri to insert into another table,
- * content://contacts/people/1/phones:
- * <pre>
- * &lt;row uri="content://contacts/people">
- * &lt;col column = "name" value = "foo feebe"/>
- * &lt;col column = "addr" value = "Tx"/>
- * &lt;row postfix="phones">
- * &lt;col column="number" value="512-514-6535"/>
- * &lt;/row>
- * &lt;row postfix="phones">
- * &lt;col column="cell" value="512-514-6535"/>
- * &lt;/row>
- * &lt;/row></pre>
- * <br/>
- * Insert multiple rows in to same table and same attributes:
- * <pre>
- * &lt;row uri="content://contacts/people" >
- * &lt;row>
- * &lt;col column= "name" value = "foo feebe"/>
- * &lt;col column= "addr" value = "Tx"/>
- * &lt;/row>
- * &lt;row>
- * &lt;/row>
- * &lt;/row></pre>
- *
- * @hide
- */
-public class DefaultDataHandler implements ContentInsertHandler {
- private final static String ROW = "row";
- private final static String COL = "col";
- private final static String URI_STR = "uri";
- private final static String POSTFIX = "postfix";
- private final static String DEL = "del";
- private final static String SELECT = "select";
- private final static String ARG = "arg";
-
- private Stack<Uri> mUris = new Stack<Uri>();
- private ContentValues mValues;
- private ContentResolver mContentResolver;
-
- public void insert(ContentResolver contentResolver, InputStream in)
- throws IOException, SAXException {
- mContentResolver = contentResolver;
- Xml.parse(in, Xml.Encoding.UTF_8, this);
- }
-
- public void insert(ContentResolver contentResolver, String in)
- throws SAXException {
- mContentResolver = contentResolver;
- Xml.parse(in, this);
- }
-
- private void parseRow(Attributes atts) throws SAXException {
- String uriStr = atts.getValue(URI_STR);
- Uri uri;
- if (uriStr != null) {
- // case 1
- uri = Uri.parse(uriStr);
- if (uri == null) {
- throw new SAXException("attribute " +
- atts.getValue(URI_STR) + " parsing failure");
- }
-
- } else if (mUris.size() > 0){
- // case 2
- String postfix = atts.getValue(POSTFIX);
- if (postfix != null) {
- uri = Uri.withAppendedPath(mUris.lastElement(),
- postfix);
- } else {
- uri = mUris.lastElement();
- }
- } else {
- throw new SAXException("attribute parsing failure");
- }
-
- mUris.push(uri);
-
- }
-
- private Uri insertRow() {
- Uri u = mContentResolver.insert(mUris.lastElement(), mValues);
- mValues = null;
- return u;
- }
-
- public void startElement(String uri, String localName, String name,
- Attributes atts) throws SAXException {
- if (ROW.equals(localName)) {
- if (mValues != null) {
- // case 2, <Col> before <Row> insert last uri
- if (mUris.empty()) {
- throw new SAXException("uri is empty");
- }
- Uri nextUri = insertRow();
- if (nextUri == null) {
- throw new SAXException("insert to uri " +
- mUris.lastElement().toString() + " failure");
- } else {
- // make sure the stack lastElement save uri for more than one row
- mUris.pop();
- mUris.push(nextUri);
- parseRow(atts);
- }
- } else {
- int attrLen = atts.getLength();
- if (attrLen == 0) {
- // case 3, share same uri as last level
- mUris.push(mUris.lastElement());
- } else {
- parseRow(atts);
- }
- }
- } else if (COL.equals(localName)) {
- int attrLen = atts.getLength();
- if (attrLen != 2) {
- throw new SAXException("illegal attributes number " + attrLen);
- }
- String key = atts.getValue(0);
- String value = atts.getValue(1);
- if (key != null && key.length() > 0 && value != null && value.length() > 0) {
- if (mValues == null) {
- mValues = new ContentValues();
- }
- mValues.put(key, value);
- } else {
- throw new SAXException("illegal attributes value");
- }
- } else if (DEL.equals(localName)){
- Uri u = Uri.parse(atts.getValue(URI_STR));
- if (u == null) {
- throw new SAXException("attribute " +
- atts.getValue(URI_STR) + " parsing failure");
- }
- int attrLen = atts.getLength() - 2;
- if (attrLen > 0) {
- String[] selectionArgs = new String[attrLen];
- for (int i = 0; i < attrLen; i++) {
- selectionArgs[i] = atts.getValue(i+2);
- }
- mContentResolver.delete(u, atts.getValue(1), selectionArgs);
- } else if (attrLen == 0){
- mContentResolver.delete(u, atts.getValue(1), null);
- } else {
- mContentResolver.delete(u, null, null);
- }
-
- } else {
- throw new SAXException("unknown element: " + localName);
- }
- }
-
- public void endElement(String uri, String localName, String name)
- throws SAXException {
- if (ROW.equals(localName)) {
- if (mUris.empty()) {
- throw new SAXException("uri mismatch");
- }
- if (mValues != null) {
- insertRow();
- }
- mUris.pop();
- }
- }
-
-
- public void characters(char[] ch, int start, int length)
- throws SAXException {
- // TODO Auto-generated method stub
-
- }
-
- public void endDocument() throws SAXException {
- // TODO Auto-generated method stub
-
- }
-
- public void endPrefixMapping(String prefix) throws SAXException {
- // TODO Auto-generated method stub
-
- }
-
- public void ignorableWhitespace(char[] ch, int start, int length)
- throws SAXException {
- // TODO Auto-generated method stub
-
- }
-
- public void processingInstruction(String target, String data)
- throws SAXException {
- // TODO Auto-generated method stub
-
- }
-
- public void setDocumentLocator(Locator locator) {
- // TODO Auto-generated method stub
-
- }
-
- public void skippedEntity(String name) throws SAXException {
- // TODO Auto-generated method stub
-
- }
-
- public void startDocument() throws SAXException {
- // TODO Auto-generated method stub
-
- }
-
- public void startPrefixMapping(String prefix, String uri)
- throws SAXException {
- // TODO Auto-generated method stub
-
- }
-
-}
diff --git a/core/java/android/content/DialogInterface.java b/core/java/android/content/DialogInterface.java
deleted file mode 100644
index 4afa294..0000000
--- a/core/java/android/content/DialogInterface.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.view.KeyEvent;
-
-/**
- *
- */
-public interface DialogInterface {
- /**
- * The identifier for the positive button.
- */
- public static final int BUTTON_POSITIVE = -1;
-
- /**
- * The identifier for the negative button.
- */
- public static final int BUTTON_NEGATIVE = -2;
-
- /**
- * The identifier for the neutral button.
- */
- public static final int BUTTON_NEUTRAL = -3;
-
- /**
- * @deprecated Use {@link #BUTTON_POSITIVE}
- */
- @Deprecated
- public static final int BUTTON1 = BUTTON_POSITIVE;
-
- /**
- * @deprecated Use {@link #BUTTON_NEGATIVE}
- */
- @Deprecated
- public static final int BUTTON2 = BUTTON_NEGATIVE;
-
- /**
- * @deprecated Use {@link #BUTTON_NEUTRAL}
- */
- @Deprecated
- public static final int BUTTON3 = BUTTON_NEUTRAL;
-
- public void cancel();
-
- public void dismiss();
-
- /**
- * Interface used to allow the creator of a dialog to run some code when the
- * dialog is canceled.
- * <p>
- * This will only be called when the dialog is canceled, if the creator
- * needs to know when it is dismissed in general, use
- * {@link DialogInterface.OnDismissListener}.
- */
- interface OnCancelListener {
- /**
- * This method will be invoked when the dialog is canceled.
- *
- * @param dialog The dialog that was canceled will be passed into the
- * method.
- */
- public void onCancel(DialogInterface dialog);
- }
-
- /**
- * Interface used to allow the creator of a dialog to run some code when the
- * dialog is dismissed.
- */
- interface OnDismissListener {
- /**
- * This method will be invoked when the dialog is dismissed.
- *
- * @param dialog The dialog that was dismissed will be passed into the
- * method.
- */
- public void onDismiss(DialogInterface dialog);
- }
-
- /**
- * Interface used to allow the creator of a dialog to run some code when an
- * item on the dialog is clicked..
- */
- interface OnClickListener {
- /**
- * This method will be invoked when a button in the dialog is clicked.
- *
- * @param dialog The dialog that received the click.
- * @param which The button that was clicked (e.g.
- * {@link DialogInterface#BUTTON1}) or the position
- * of the item clicked.
- */
- /* TODO: Change to use BUTTON_POSITIVE after API council */
- public void onClick(DialogInterface dialog, int which);
- }
-
- /**
- * Interface used to allow the creator of a dialog to run some code when an
- * item in a multi-choice dialog is clicked.
- */
- interface OnMultiChoiceClickListener {
- /**
- * This method will be invoked when an item in the dialog is clicked.
- *
- * @param dialog The dialog where the selection was made.
- * @param which The position of the item in the list that was clicked.
- * @param isChecked True if the click checked the item, else false.
- */
- public void onClick(DialogInterface dialog, int which, boolean isChecked);
- }
-
- /**
- * Interface definition for a callback to be invoked when a key event is
- * dispatched to this dialog. The callback will be invoked before the key
- * event is given to the dialog.
- */
- interface OnKeyListener {
- /**
- * Called when a key is dispatched to a dialog. This allows listeners to
- * get a chance to respond before the dialog.
- *
- * @param dialog The dialog the key has been dispatched to.
- * @param keyCode The code for the physical key that was pressed
- * @param event The KeyEvent object containing full information about
- * the event.
- * @return True if the listener has consumed the event, false otherwise.
- */
- public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event);
- }
-}
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
deleted file mode 100644
index a6ef46f..0000000
--- a/core/java/android/content/IContentProvider.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.database.Cursor;
-import android.database.CursorWindow;
-import android.database.IBulkCursor;
-import android.database.IContentObserver;
-import android.net.Uri;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.ParcelFileDescriptor;
-
-import java.io.FileNotFoundException;
-
-/**
- * The ipc interface to talk to a content provider.
- * @hide
- */
-public interface IContentProvider extends IInterface {
- /**
- * @hide - hide this because return type IBulkCursor and parameter
- * IContentObserver are system private classes.
- */
- public IBulkCursor bulkQuery(Uri url, String[] projection,
- String selection, String[] selectionArgs, String sortOrder, IContentObserver observer,
- CursorWindow window) throws RemoteException;
- public Cursor query(Uri url, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) throws RemoteException;
- public String getType(Uri url) throws RemoteException;
- public Uri insert(Uri url, ContentValues initialValues)
- throws RemoteException;
- public int bulkInsert(Uri url, ContentValues[] initialValues) throws RemoteException;
- public int delete(Uri url, String selection, String[] selectionArgs)
- throws RemoteException;
- public int update(Uri url, ContentValues values, String selection,
- String[] selectionArgs) throws RemoteException;
- public ParcelFileDescriptor openFile(Uri url, String mode)
- throws RemoteException, FileNotFoundException;
- public ISyncAdapter getSyncAdapter() throws RemoteException;
-
- /* IPC constants */
- static final String descriptor = "android.content.IContentProvider";
-
- static final int QUERY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
- static final int GET_TYPE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1;
- static final int INSERT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 2;
- static final int DELETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 3;
- static final int UPDATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 9;
- static final int GET_SYNC_ADAPTER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 10;
- static final int BULK_INSERT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 12;
- static final int OPEN_FILE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 13;
-}
diff --git a/core/java/android/content/IContentService.java b/core/java/android/content/IContentService.java
deleted file mode 100644
index a3047da..0000000
--- a/core/java/android/content/IContentService.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.database.IContentObserver;
-import android.net.Uri;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.Bundle;
-
-/**
- * {@hide}
- */
-public interface IContentService extends IInterface
-{
- public void registerContentObserver(Uri uri, boolean notifyForDescendentsn,
- IContentObserver observer) throws RemoteException;
- public void unregisterContentObserver(IContentObserver observer) throws RemoteException;
-
- public void notifyChange(Uri uri, IContentObserver observer,
- boolean observerWantsSelfNotifications, boolean syncToNetwork)
- throws RemoteException;
-
- public void startSync(Uri url, Bundle extras) throws RemoteException;
- public void cancelSync(Uri uri) throws RemoteException;
-
- static final String SERVICE_NAME = "content";
-
- /* IPC constants */
- static final String descriptor = "android.content.IContentService";
-
- static final int REGISTER_CONTENT_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1;
- static final int UNREGISTER_CHANGE_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 2;
- static final int NOTIFY_CHANGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 3;
- static final int START_SYNC_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 4;
- static final int CANCEL_SYNC_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 5;
-}
-
diff --git a/core/java/android/content/ISyncAdapter.aidl b/core/java/android/content/ISyncAdapter.aidl
deleted file mode 100644
index 671188c..0000000
--- a/core/java/android/content/ISyncAdapter.aidl
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.os.Bundle;
-import android.content.ISyncContext;
-
-/**
- * Interface used to control the sync activity on a SyncAdapter
- * @hide
- */
-oneway interface ISyncAdapter {
- /**
- * Initiate a sync for this account. SyncAdapter-specific parameters may
- * be specified in extras, which is guaranteed to not be null.
- *
- * @param syncContext the ISyncContext used to indicate the progress of the sync. When
- * the sync is finished (successfully or not) ISyncContext.onFinished() must be called.
- * @param account the account that should be synced
- * @param extras SyncAdapter-specific parameters
- */
- void startSync(ISyncContext syncContext, String account, in Bundle extras);
-
- /**
- * Cancel the most recently initiated sync. Due to race conditions, this may arrive
- * after the ISyncContext.onFinished() for that sync was called.
- */
- void cancelSync();
-}
diff --git a/core/java/android/content/ISyncContext.aidl b/core/java/android/content/ISyncContext.aidl
deleted file mode 100644
index 6d18a1c..0000000
--- a/core/java/android/content/ISyncContext.aidl
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.content.SyncResult;
-
-/**
- * Interface used by the SyncAdapter to indicate its progress.
- * @hide
- */
-interface ISyncContext {
- /**
- * Call to indicate that the SyncAdapter is making progress. E.g., if this SyncAdapter
- * downloads or sends records to/from the server, this may be called after each record
- * is downloaded or uploaded.
- */
- void sendHeartbeat();
-
- /**
- * Signal that the corresponding sync session is completed.
- * @param result information about this sync session
- */
- void onFinished(in SyncResult result);
-}
diff --git a/core/java/android/content/Intent.aidl b/core/java/android/content/Intent.aidl
deleted file mode 100644
index 568986b..0000000
--- a/core/java/android/content/Intent.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/content/Intent.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content;
-
-parcelable Intent;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
deleted file mode 100644
index c1c3b49..0000000
--- a/core/java/android/content/Intent.java
+++ /dev/null
@@ -1,4522 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.util.Log;
-import com.android.internal.util.XmlUtils;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-/**
- * An intent is an abstract description of an operation to be performed. It
- * can be used with {@link Context#startActivity(Intent) startActivity} to
- * launch an {@link android.app.Activity},
- * {@link android.content.Context#sendBroadcast(Intent) broadcastIntent} to
- * send it to any interested {@link BroadcastReceiver BroadcastReceiver} components,
- * and {@link android.content.Context#startService} or
- * {@link android.content.Context#bindService} to communicate with a
- * background {@link android.app.Service}.
- *
- * <p>An Intent provides a facility for performing late runtime binding between
- * the code in different applications. Its most significant use is in the
- * launching of activities, where it can be thought of as the glue between
- * activities. It is
- * basically a passive data structure holding an abstract description of an
- * action to be performed. The primary pieces of information in an intent
- * are:</p>
- *
- * <ul>
- * <li> <p><b>action</b> -- The general action to be performed, such as
- * {@link #ACTION_VIEW}, {@link #ACTION_EDIT}, {@link #ACTION_MAIN},
- * etc.</p>
- * </li>
- * <li> <p><b>data</b> -- The data to operate on, such as a person record
- * in the contacts database, expressed as a {@link android.net.Uri}.</p>
- * </li>
- * </ul>
- *
- *
- * <p>Some examples of action/data pairs are:</p>
- *
- * <ul>
- * <li> <p><b>{@link #ACTION_VIEW} <i>content://contacts/1</i></b> -- Display
- * information about the person whose identifier is "1".</p>
- * </li>
- * <li> <p><b>{@link #ACTION_DIAL} <i>content://contacts/1</i></b> -- Display
- * the phone dialer with the person filled in.</p>
- * </li>
- * <li> <p><b>{@link #ACTION_VIEW} <i>tel:123</i></b> -- Display
- * the phone dialer with the given number filled in. Note how the
- * VIEW action does what what is considered the most reasonable thing for
- * a particular URI.</p>
- * </li>
- * <li> <p><b>{@link #ACTION_DIAL} <i>tel:123</i></b> -- Display
- * the phone dialer with the given number filled in.</p>
- * </li>
- * <li> <p><b>{@link #ACTION_EDIT} <i>content://contacts/1</i></b> -- Edit
- * information about the person whose identifier is "1".</p>
- * </li>
- * <li> <p><b>{@link #ACTION_VIEW} <i>content://contacts/</i></b> -- Display
- * a list of people, which the user can browse through. This example is a
- * typical top-level entry into the Contacts application, showing you the
- * list of people. Selecting a particular person to view would result in a
- * new intent { <b>{@link #ACTION_VIEW} <i>content://contacts/N</i></b> }
- * being used to start an activity to display that person.</p>
- * </li>
- * </ul>
- *
- * <p>In addition to these primary attributes, there are a number of secondary
- * attributes that you can also include with an intent:</p>
- *
- * <ul>
- * <li> <p><b>category</b> -- Gives additional information about the action
- * to execute. For example, {@link #CATEGORY_LAUNCHER} means it should
- * appear in the Launcher as a top-level application, while
- * {@link #CATEGORY_ALTERNATIVE} means it should be included in a list
- * of alternative actions the user can perform on a piece of data.</p>
- * <li> <p><b>type</b> -- Specifies an explicit type (a MIME type) of the
- * intent data. Normally the type is inferred from the data itself.
- * By setting this attribute, you disable that evaluation and force
- * an explicit type.</p>
- * <li> <p><b>component</b> -- Specifies an explicit name of a component
- * class to use for the intent. Normally this is determined by looking
- * at the other information in the intent (the action, data/type, and
- * categories) and matching that with a component that can handle it.
- * If this attribute is set then none of the evaluation is performed,
- * and this component is used exactly as is. By specifying this attribute,
- * all of the other Intent attributes become optional.</p>
- * <li> <p><b>extras</b> -- This is a {@link Bundle} of any additional information.
- * This can be used to provide extended information to the component.
- * For example, if we have a action to send an e-mail message, we could
- * also include extra pieces of data here to supply a subject, body,
- * etc.</p>
- * </ul>
- *
- * <p>Here are some examples of other operations you can specify as intents
- * using these additional parameters:</p>
- *
- * <ul>
- * <li> <p><b>{@link #ACTION_MAIN} with category {@link #CATEGORY_HOME}</b> --
- * Launch the home screen.</p>
- * </li>
- * <li> <p><b>{@link #ACTION_GET_CONTENT} with MIME type
- * <i>{@link android.provider.Contacts.Phones#CONTENT_URI
- * vnd.android.cursor.item/phone}</i></b>
- * -- Display the list of people's phone numbers, allowing the user to
- * browse through them and pick one and return it to the parent activity.</p>
- * </li>
- * <li> <p><b>{@link #ACTION_GET_CONTENT} with MIME type
- * <i>*{@literal /}*</i> and category {@link #CATEGORY_OPENABLE}</b>
- * -- Display all pickers for data that can be opened with
- * {@link ContentResolver#openInputStream(Uri) ContentResolver.openInputStream()},
- * allowing the user to pick one of them and then some data inside of it
- * and returning the resulting URI to the caller. This can be used,
- * for example, in an e-mail application to allow the user to pick some
- * data to include as an attachment.</p>
- * </li>
- * </ul>
- *
- * <p>There are a variety of standard Intent action and category constants
- * defined in the Intent class, but applications can also define their own.
- * These strings use java style scoping, to ensure they are unique -- for
- * example, the standard {@link #ACTION_VIEW} is called
- * "android.app.action.VIEW".</p>
- *
- * <p>Put together, the set of actions, data types, categories, and extra data
- * defines a language for the system allowing for the expression of phrases
- * such as "call john smith's cell". As applications are added to the system,
- * they can extend this language by adding new actions, types, and categories, or
- * they can modify the behavior of existing phrases by supplying their own
- * activities that handle them.</p>
- *
- * <a name="IntentResolution"></a>
- * <h3>Intent Resolution</h3>
- *
- * <p>There are two primary forms of intents you will use.
- *
- * <ul>
- * <li> <p><b>Explicit Intents</b> have specified a component (via
- * {@link #setComponent} or {@link #setClass}), which provides the exact
- * class to be run. Often these will not include any other information,
- * simply being a way for an application to launch various internal
- * activities it has as the user interacts with the application.
- *
- * <li> <p><b>Implicit Intents</b> have not specified a component;
- * instead, they must include enough information for the system to
- * determine which of the available components is best to run for that
- * intent.
- * </ul>
- *
- * <p>When using implicit intents, given such an arbitrary intent we need to
- * know what to do with it. This is handled by the process of <em>Intent
- * resolution</em>, which maps an Intent to an {@link android.app.Activity},
- * {@link BroadcastReceiver}, or {@link android.app.Service} (or sometimes two or
- * more activities/receivers) that can handle it.</p>
- *
- * <p>The intent resolution mechanism basically revolves around matching an
- * Intent against all of the &lt;intent-filter&gt; descriptions in the
- * installed application packages. (Plus, in the case of broadcasts, any {@link BroadcastReceiver}
- * objects explicitly registered with {@link Context#registerReceiver}.) More
- * details on this can be found in the documentation on the {@link
- * IntentFilter} class.</p>
- *
- * <p>There are three pieces of information in the Intent that are used for
- * resolution: the action, type, and category. Using this information, a query
- * is done on the {@link PackageManager} for a component that can handle the
- * intent. The appropriate component is determined based on the intent
- * information supplied in the <code>AndroidManifest.xml</code> file as
- * follows:</p>
- *
- * <ul>
- * <li> <p>The <b>action</b>, if given, must be listed by the component as
- * one it handles.</p>
- * <li> <p>The <b>type</b> is retrieved from the Intent's data, if not
- * already supplied in the Intent. Like the action, if a type is
- * included in the intent (either explicitly or implicitly in its
- * data), then this must be listed by the component as one it handles.</p>
- * <li> For data that is not a <code>content:</code> URI and where no explicit
- * type is included in the Intent, instead the <b>scheme</b> of the
- * intent data (such as <code>http:</code> or <code>mailto:</code>) is
- * considered. Again like the action, if we are matching a scheme it
- * must be listed by the component as one it can handle.
- * <li> <p>The <b>categories</b>, if supplied, must <em>all</em> be listed
- * by the activity as categories it handles. That is, if you include
- * the categories {@link #CATEGORY_LAUNCHER} and
- * {@link #CATEGORY_ALTERNATIVE}, then you will only resolve to components
- * with an intent that lists <em>both</em> of those categories.
- * Activities will very often need to support the
- * {@link #CATEGORY_DEFAULT} so that they can be found by
- * {@link Context#startActivity Context.startActivity()}.</p>
- * </ul>
- *
- * <p>For example, consider the Note Pad sample application that
- * allows user to browse through a list of notes data and view details about
- * individual items. Text in italics indicate places were you would replace a
- * name with one specific to your own package.</p>
- *
- * <pre> &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
- * package="<i>com.android.notepad</i>"&gt;
- * &lt;application android:icon="@drawable/app_notes"
- * android:label="@string/app_name"&gt;
- *
- * &lt;provider class=".NotePadProvider"
- * android:authorities="<i>com.google.provider.NotePad</i>" /&gt;
- *
- * &lt;activity class=".NotesList" android:label="@string/title_notes_list"&gt;
- * &lt;intent-filter&gt;
- * &lt;action android:value="android.intent.action.MAIN" /&gt;
- * &lt;category android:value="android.intent.category.LAUNCHER" /&gt;
- * &lt;/intent-filter&gt;
- * &lt;intent-filter&gt;
- * &lt;action android:value="android.intent.action.VIEW" /&gt;
- * &lt;action android:value="android.intent.action.EDIT" /&gt;
- * &lt;action android:value="android.intent.action.PICK" /&gt;
- * &lt;category android:value="android.intent.category.DEFAULT" /&gt;
- * &lt;type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /&gt;
- * &lt;/intent-filter&gt;
- * &lt;intent-filter&gt;
- * &lt;action android:value="android.intent.action.GET_CONTENT" /&gt;
- * &lt;category android:value="android.intent.category.DEFAULT" /&gt;
- * &lt;type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
- * &lt;/intent-filter&gt;
- * &lt;/activity&gt;
- *
- * &lt;activity class=".NoteEditor" android:label="@string/title_note"&gt;
- * &lt;intent-filter android:label="@string/resolve_edit"&gt;
- * &lt;action android:value="android.intent.action.VIEW" /&gt;
- * &lt;action android:value="android.intent.action.EDIT" /&gt;
- * &lt;category android:value="android.intent.category.DEFAULT" /&gt;
- * &lt;type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
- * &lt;/intent-filter&gt;
- *
- * &lt;intent-filter&gt;
- * &lt;action android:value="android.intent.action.INSERT" /&gt;
- * &lt;category android:value="android.intent.category.DEFAULT" /&gt;
- * &lt;type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /&gt;
- * &lt;/intent-filter&gt;
- *
- * &lt;/activity&gt;
- *
- * &lt;activity class=".TitleEditor" android:label="@string/title_edit_title"
- * android:theme="@android:style/Theme.Dialog"&gt;
- * &lt;intent-filter android:label="@string/resolve_title"&gt;
- * &lt;action android:value="<i>com.android.notepad.action.EDIT_TITLE</i>" /&gt;
- * &lt;category android:value="android.intent.category.DEFAULT" /&gt;
- * &lt;category android:value="android.intent.category.ALTERNATIVE" /&gt;
- * &lt;category android:value="android.intent.category.SELECTED_ALTERNATIVE" /&gt;
- * &lt;type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
- * &lt;/intent-filter&gt;
- * &lt;/activity&gt;
- *
- * &lt;/application&gt;
- * &lt;/manifest&gt;</pre>
- *
- * <p>The first activity,
- * <code>com.android.notepad.NotesList</code>, serves as our main
- * entry into the app. It can do three things as described by its three intent
- * templates:
- * <ol>
- * <li><pre>
- * &lt;intent-filter&gt;
- * &lt;action android:value="{@link #ACTION_MAIN android.intent.action.MAIN}" /&gt;
- * &lt;category android:value="{@link #CATEGORY_LAUNCHER android.intent.category.LAUNCHER}" /&gt;
- * &lt;/intent-filter&gt;</pre>
- * <p>This provides a top-level entry into the NotePad application: the standard
- * MAIN action is a main entry point (not requiring any other information in
- * the Intent), and the LAUNCHER category says that this entry point should be
- * listed in the application launcher.</p>
- * <li><pre>
- * &lt;intent-filter&gt;
- * &lt;action android:value="{@link #ACTION_VIEW android.intent.action.VIEW}" /&gt;
- * &lt;action android:value="{@link #ACTION_EDIT android.intent.action.EDIT}" /&gt;
- * &lt;action android:value="{@link #ACTION_PICK android.intent.action.PICK}" /&gt;
- * &lt;category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
- * &lt;type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /&gt;
- * &lt;/intent-filter&gt;</pre>
- * <p>This declares the things that the activity can do on a directory of
- * notes. The type being supported is given with the &lt;type&gt; tag, where
- * <code>vnd.android.cursor.dir/vnd.google.note</code> is a URI from which
- * a Cursor of zero or more items (<code>vnd.android.cursor.dir</code>) can
- * be retrieved which holds our note pad data (<code>vnd.google.note</code>).
- * The activity allows the user to view or edit the directory of data (via
- * the VIEW and EDIT actions), or to pick a particular note and return it
- * to the caller (via the PICK action). Note also the DEFAULT category
- * supplied here: this is <em>required</em> for the
- * {@link Context#startActivity Context.startActivity} method to resolve your
- * activity when its component name is not explicitly specified.</p>
- * <li><pre>
- * &lt;intent-filter&gt;
- * &lt;action android:value="{@link #ACTION_GET_CONTENT android.intent.action.GET_CONTENT}" /&gt;
- * &lt;category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
- * &lt;type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
- * &lt;/intent-filter&gt;</pre>
- * <p>This filter describes the ability return to the caller a note selected by
- * the user without needing to know where it came from. The data type
- * <code>vnd.android.cursor.item/vnd.google.note</code> is a URI from which
- * a Cursor of exactly one (<code>vnd.android.cursor.item</code>) item can
- * be retrieved which contains our note pad data (<code>vnd.google.note</code>).
- * The GET_CONTENT action is similar to the PICK action, where the activity
- * will return to its caller a piece of data selected by the user. Here,
- * however, the caller specifies the type of data they desire instead of
- * the type of data the user will be picking from.</p>
- * </ol>
- *
- * <p>Given these capabilities, the following intents will resolve to the
- * NotesList activity:</p>
- *
- * <ul>
- * <li> <p><b>{ action=android.app.action.MAIN }</b> matches all of the
- * activities that can be used as top-level entry points into an
- * application.</p>
- * <li> <p><b>{ action=android.app.action.MAIN,
- * category=android.app.category.LAUNCHER }</b> is the actual intent
- * used by the Launcher to populate its top-level list.</p>
- * <li> <p><b>{ action=android.app.action.VIEW
- * data=content://com.google.provider.NotePad/notes }</b>
- * displays a list of all the notes under
- * "content://com.google.provider.NotePad/notes", which
- * the user can browse through and see the details on.</p>
- * <li> <p><b>{ action=android.app.action.PICK
- * data=content://com.google.provider.NotePad/notes }</b>
- * provides a list of the notes under
- * "content://com.google.provider.NotePad/notes", from which
- * the user can pick a note whose data URL is returned back to the caller.</p>
- * <li> <p><b>{ action=android.app.action.GET_CONTENT
- * type=vnd.android.cursor.item/vnd.google.note }</b>
- * is similar to the pick action, but allows the caller to specify the
- * kind of data they want back so that the system can find the appropriate
- * activity to pick something of that data type.</p>
- * </ul>
- *
- * <p>The second activity,
- * <code>com.android.notepad.NoteEditor</code>, shows the user a single
- * note entry and allows them to edit it. It can do two things as described
- * by its two intent templates:
- * <ol>
- * <li><pre>
- * &lt;intent-filter android:label="@string/resolve_edit"&gt;
- * &lt;action android:value="{@link #ACTION_VIEW android.intent.action.VIEW}" /&gt;
- * &lt;action android:value="{@link #ACTION_EDIT android.intent.action.EDIT}" /&gt;
- * &lt;category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
- * &lt;type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
- * &lt;/intent-filter&gt;</pre>
- * <p>The first, primary, purpose of this activity is to let the user interact
- * with a single note, as decribed by the MIME type
- * <code>vnd.android.cursor.item/vnd.google.note</code>. The activity can
- * either VIEW a note or allow the user to EDIT it. Again we support the
- * DEFAULT category to allow the activity to be launched without explicitly
- * specifying its component.</p>
- * <li><pre>
- * &lt;intent-filter&gt;
- * &lt;action android:value="{@link #ACTION_INSERT android.intent.action.INSERT}" /&gt;
- * &lt;category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
- * &lt;type android:value="vnd.android.cursor.dir/<i>vnd.google.note</i>" /&gt;
- * &lt;/intent-filter&gt;</pre>
- * <p>The secondary use of this activity is to insert a new note entry into
- * an existing directory of notes. This is used when the user creates a new
- * note: the INSERT action is executed on the directory of notes, causing
- * this activity to run and have the user create the new note data which
- * it then adds to the content provider.</p>
- * </ol>
- *
- * <p>Given these capabilities, the following intents will resolve to the
- * NoteEditor activity:</p>
- *
- * <ul>
- * <li> <p><b>{ action=android.app.action.VIEW
- * data=content://com.google.provider.NotePad/notes/<var>{ID}</var> }</b>
- * shows the user the content of note <var>{ID}</var>.</p>
- * <li> <p><b>{ action=android.app.action.EDIT
- * data=content://com.google.provider.NotePad/notes/<var>{ID}</var> }</b>
- * allows the user to edit the content of note <var>{ID}</var>.</p>
- * <li> <p><b>{ action=android.app.action.INSERT
- * data=content://com.google.provider.NotePad/notes }</b>
- * creates a new, empty note in the notes list at
- * "content://com.google.provider.NotePad/notes"
- * and allows the user to edit it. If they keep their changes, the URI
- * of the newly created note is returned to the caller.</p>
- * </ul>
- *
- * <p>The last activity,
- * <code>com.android.notepad.TitleEditor</code>, allows the user to
- * edit the title of a note. This could be implemented as a class that the
- * application directly invokes (by explicitly setting its component in
- * the Intent), but here we show a way you can publish alternative
- * operations on existing data:</p>
- *
- * <pre>
- * &lt;intent-filter android:label="@string/resolve_title"&gt;
- * &lt;action android:value="<i>com.android.notepad.action.EDIT_TITLE</i>" /&gt;
- * &lt;category android:value="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
- * &lt;category android:value="{@link #CATEGORY_ALTERNATIVE android.intent.category.ALTERNATIVE}" /&gt;
- * &lt;category android:value="{@link #CATEGORY_SELECTED_ALTERNATIVE android.intent.category.SELECTED_ALTERNATIVE}" /&gt;
- * &lt;type android:value="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
- * &lt;/intent-filter&gt;</pre>
- *
- * <p>In the single intent template here, we
- * have created our own private action called
- * <code>com.android.notepad.action.EDIT_TITLE</code> which means to
- * edit the title of a note. It must be invoked on a specific note
- * (data type <code>vnd.android.cursor.item/vnd.google.note</code>) like the previous
- * view and edit actions, but here displays and edits the title contained
- * in the note data.
- *
- * <p>In addition to supporting the default category as usual, our title editor
- * also supports two other standard categories: ALTERNATIVE and
- * SELECTED_ALTERNATIVE. Implementing
- * these categories allows others to find the special action it provides
- * without directly knowing about it, through the
- * {@link android.content.pm.PackageManager#queryIntentActivityOptions} method, or
- * more often to build dynamic menu items with
- * {@link android.view.Menu#addIntentOptions}. Note that in the intent
- * template here was also supply an explicit name for the template
- * (via <code>android:label="@string/resolve_title"</code>) to better control
- * what the user sees when presented with this activity as an alternative
- * action to the data they are viewing.
- *
- * <p>Given these capabilities, the following intent will resolve to the
- * TitleEditor activity:</p>
- *
- * <ul>
- * <li> <p><b>{ action=com.android.notepad.action.EDIT_TITLE
- * data=content://com.google.provider.NotePad/notes/<var>{ID}</var> }</b>
- * displays and allows the user to edit the title associated
- * with note <var>{ID}</var>.</p>
- * </ul>
- *
- * <h3>Standard Activity Actions</h3>
- *
- * <p>These are the current standard actions that Intent defines for launching
- * activities (usually through {@link Context#startActivity}. The most
- * important, and by far most frequently used, are {@link #ACTION_MAIN} and
- * {@link #ACTION_EDIT}.
- *
- * <ul>
- * <li> {@link #ACTION_MAIN}
- * <li> {@link #ACTION_VIEW}
- * <li> {@link #ACTION_ATTACH_DATA}
- * <li> {@link #ACTION_EDIT}
- * <li> {@link #ACTION_PICK}
- * <li> {@link #ACTION_CHOOSER}
- * <li> {@link #ACTION_GET_CONTENT}
- * <li> {@link #ACTION_DIAL}
- * <li> {@link #ACTION_CALL}
- * <li> {@link #ACTION_SEND}
- * <li> {@link #ACTION_SENDTO}
- * <li> {@link #ACTION_ANSWER}
- * <li> {@link #ACTION_INSERT}
- * <li> {@link #ACTION_DELETE}
- * <li> {@link #ACTION_RUN}
- * <li> {@link #ACTION_SYNC}
- * <li> {@link #ACTION_PICK_ACTIVITY}
- * <li> {@link #ACTION_SEARCH}
- * <li> {@link #ACTION_WEB_SEARCH}
- * <li> {@link #ACTION_FACTORY_TEST}
- * </ul>
- *
- * <h3>Standard Broadcast Actions</h3>
- *
- * <p>These are the current standard actions that Intent defines for receiving
- * broadcasts (usually through {@link Context#registerReceiver} or a
- * &lt;receiver&gt; tag in a manifest).
- *
- * <ul>
- * <li> {@link #ACTION_TIME_TICK}
- * <li> {@link #ACTION_TIME_CHANGED}
- * <li> {@link #ACTION_TIMEZONE_CHANGED}
- * <li> {@link #ACTION_BOOT_COMPLETED}
- * <li> {@link #ACTION_PACKAGE_ADDED}
- * <li> {@link #ACTION_PACKAGE_CHANGED}
- * <li> {@link #ACTION_PACKAGE_REMOVED}
- * <li> {@link #ACTION_PACKAGE_RESTARTED}
- * <li> {@link #ACTION_PACKAGE_DATA_CLEARED}
- * <li> {@link #ACTION_UID_REMOVED}
- * <li> {@link #ACTION_BATTERY_CHANGED}
- * </ul>
- *
- * <h3>Standard Categories</h3>
- *
- * <p>These are the current standard categories that can be used to further
- * clarify an Intent via {@link #addCategory}.
- *
- * <ul>
- * <li> {@link #CATEGORY_DEFAULT}
- * <li> {@link #CATEGORY_BROWSABLE}
- * <li> {@link #CATEGORY_TAB}
- * <li> {@link #CATEGORY_ALTERNATIVE}
- * <li> {@link #CATEGORY_SELECTED_ALTERNATIVE}
- * <li> {@link #CATEGORY_LAUNCHER}
- * <li> {@link #CATEGORY_HOME}
- * <li> {@link #CATEGORY_PREFERENCE}
- * <li> {@link #CATEGORY_GADGET}
- * <li> {@link #CATEGORY_TEST}
- * </ul>
- *
- * <h3>Standard Extra Data</h3>
- *
- * <p>These are the current standard fields that can be used as extra data via
- * {@link #putExtra}.
- *
- * <ul>
- * <li> {@link #EXTRA_TEMPLATE}
- * <li> {@link #EXTRA_INTENT}
- * <li> {@link #EXTRA_STREAM}
- * <li> {@link #EXTRA_TEXT}
- * </ul>
- *
- * <h3>Flags</h3>
- *
- * <p>These are the possible flags that can be used in the Intent via
- * {@link #setFlags} and {@link #addFlags}. See {@link #setFlags} for a list
- * of all possible flags.
- */
-public class Intent implements Parcelable {
- // ---------------------------------------------------------------------
- // ---------------------------------------------------------------------
- // Standard intent activity actions (see action variable).
-
- /**
- * Activity Action: Start as a main entry point, does not expect to
- * receive data.
- * <p>Input: nothing
- * <p>Output: nothing
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_MAIN = "android.intent.action.MAIN";
-
- /**
- * Activity Action: Display the data to the user. This is the most common
- * action performed on data -- it is the generic action you can use on
- * a piece of data to get the most reasonable thing to occur. For example,
- * when used on a contacts entry it will view the entry; when used on a
- * mailto: URI it will bring up a compose window filled with the information
- * supplied by the URI; when used with a tel: URI it will invoke the
- * dialer.
- * <p>Input: {@link #getData} is URI from which to retrieve data.
- * <p>Output: nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_VIEW = "android.intent.action.VIEW";
-
- /**
- * A synonym for {@link #ACTION_VIEW}, the "standard" action that is
- * performed on a piece of data.
- */
- public static final String ACTION_DEFAULT = ACTION_VIEW;
-
- /**
- * Used to indicate that some piece of data should be attached to some other
- * place. For example, image data could be attached to a contact. It is up
- * to the recipient to decide where the data should be attached; the intent
- * does not specify the ultimate destination.
- * <p>Input: {@link #getData} is URI of data to be attached.
- * <p>Output: nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_ATTACH_DATA = "android.intent.action.ATTACH_DATA";
-
- /**
- * Activity Action: Provide explicit editable access to the given data.
- * <p>Input: {@link #getData} is URI of data to be edited.
- * <p>Output: nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_EDIT = "android.intent.action.EDIT";
-
- /**
- * Activity Action: Pick an existing item, or insert a new item, and then edit it.
- * <p>Input: {@link #getType} is the desired MIME type of the item to create or edit.
- * The extras can contain type specific data to pass through to the editing/creating
- * activity.
- * <p>Output: The URI of the item that was picked. This must be a content:
- * URI so that any receiver can access it.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
-
- /**
- * Activity Action: Pick an item from the data, returning what was selected.
- * <p>Input: {@link #getData} is URI containing a directory of data
- * (vnd.android.cursor.dir/*) from which to pick an item.
- * <p>Output: The URI of the item that was picked.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_PICK = "android.intent.action.PICK";
-
- /**
- * Activity Action: Creates a shortcut.
- * <p>Input: Nothing.</p>
- * <p>Output: An Intent representing the shortcut. The intent must contain three
- * extras: SHORTCUT_INTENT (value: Intent), SHORTCUT_NAME (value: String),
- * and SHORTCUT_ICON (value: Bitmap) or SHORTCUT_ICON_RESOURCE
- * (value: ShortcutIconResource).</p>
- *
- * @see #EXTRA_SHORTCUT_INTENT
- * @see #EXTRA_SHORTCUT_NAME
- * @see #EXTRA_SHORTCUT_ICON
- * @see #EXTRA_SHORTCUT_ICON_RESOURCE
- * @see android.content.Intent.ShortcutIconResource
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_CREATE_SHORTCUT = "android.intent.action.CREATE_SHORTCUT";
-
- /**
- * The name of the extra used to define the Intent of a shortcut.
- *
- * @see #ACTION_CREATE_SHORTCUT
- */
- public static final String EXTRA_SHORTCUT_INTENT = "android.intent.extra.shortcut.INTENT";
- /**
- * The name of the extra used to define the name of a shortcut.
- *
- * @see #ACTION_CREATE_SHORTCUT
- */
- public static final String EXTRA_SHORTCUT_NAME = "android.intent.extra.shortcut.NAME";
- /**
- * The name of the extra used to define the icon, as a Bitmap, of a shortcut.
- *
- * @see #ACTION_CREATE_SHORTCUT
- */
- public static final String EXTRA_SHORTCUT_ICON = "android.intent.extra.shortcut.ICON";
- /**
- * The name of the extra used to define the icon, as a ShortcutIconResource, of a shortcut.
- *
- * @see #ACTION_CREATE_SHORTCUT
- * @see android.content.Intent.ShortcutIconResource
- */
- public static final String EXTRA_SHORTCUT_ICON_RESOURCE =
- "android.intent.extra.shortcut.ICON_RESOURCE";
-
- /**
- * Represents a shortcut/live folder icon resource.
- *
- * @see Intent#ACTION_CREATE_SHORTCUT
- * @see Intent#EXTRA_SHORTCUT_ICON_RESOURCE
- * @see android.provider.LiveFolders#ACTION_CREATE_LIVE_FOLDER
- * @see android.provider.LiveFolders#EXTRA_LIVE_FOLDER_ICON
- */
- public static class ShortcutIconResource implements Parcelable {
- /**
- * The package name of the application containing the icon.
- */
- public String packageName;
-
- /**
- * The resource name of the icon, including package, name and type.
- */
- public String resourceName;
-
- /**
- * Creates a new ShortcutIconResource for the specified context and resource
- * identifier.
- *
- * @param context The context of the application.
- * @param resourceId The resource idenfitier for the icon.
- * @return A new ShortcutIconResource with the specified's context package name
- * and icon resource idenfitier.
- */
- public static ShortcutIconResource fromContext(Context context, int resourceId) {
- ShortcutIconResource icon = new ShortcutIconResource();
- icon.packageName = context.getPackageName();
- icon.resourceName = context.getResources().getResourceName(resourceId);
- return icon;
- }
-
- /**
- * Used to read a ShortcutIconResource from a Parcel.
- */
- public static final Parcelable.Creator<ShortcutIconResource> CREATOR =
- new Parcelable.Creator<ShortcutIconResource>() {
-
- public ShortcutIconResource createFromParcel(Parcel source) {
- ShortcutIconResource icon = new ShortcutIconResource();
- icon.packageName = source.readString();
- icon.resourceName = source.readString();
- return icon;
- }
-
- public ShortcutIconResource[] newArray(int size) {
- return new ShortcutIconResource[size];
- }
- };
-
- /**
- * No special parcel contents.
- */
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(packageName);
- dest.writeString(resourceName);
- }
-
- @Override
- public String toString() {
- return resourceName;
- }
- }
-
- /**
- * Activity Action: Display an activity chooser, allowing the user to pick
- * what they want to before proceeding. This can be used as an alternative
- * to the standard activity picker that is displayed by the system when
- * you try to start an activity with multiple possible matches, with these
- * differences in behavior:
- * <ul>
- * <li>You can specify the title that will appear in the activity chooser.
- * <li>The user does not have the option to make one of the matching
- * activities a preferred activity, and all possible activities will
- * always be shown even if one of them is currently marked as the
- * preferred activity.
- * </ul>
- * <p>
- * This action should be used when the user will naturally expect to
- * select an activity in order to proceed. An example if when not to use
- * it is when the user clicks on a "mailto:" link. They would naturally
- * expect to go directly to their mail app, so startActivity() should be
- * called directly: it will
- * either launch the current preferred app, or put up a dialog allowing the
- * user to pick an app to use and optionally marking that as preferred.
- * <p>
- * In contrast, if the user is selecting a menu item to send a picture
- * they are viewing to someone else, there are many different things they
- * may want to do at this point: send it through e-mail, upload it to a
- * web service, etc. In this case the CHOOSER action should be used, to
- * always present to the user a list of the things they can do, with a
- * nice title given by the caller such as "Send this photo with:".
- * <p>
- * As a convenience, an Intent of this form can be created with the
- * {@link #createChooser} function.
- * <p>Input: No data should be specified. get*Extra must have
- * a {@link #EXTRA_INTENT} field containing the Intent being executed,
- * and can optionally have a {@link #EXTRA_TITLE} field containing the
- * title text to display in the chooser.
- * <p>Output: Depends on the protocol of {@link #EXTRA_INTENT}.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_CHOOSER = "android.intent.action.CHOOSER";
-
- /**
- * Convenience function for creating a {@link #ACTION_CHOOSER} Intent.
- *
- * @param target The Intent that the user will be selecting an activity
- * to perform.
- * @param title Optional title that will be displayed in the chooser.
- * @return Return a new Intent object that you can hand to
- * {@link Context#startActivity(Intent) Context.startActivity()} and
- * related methods.
- */
- public static Intent createChooser(Intent target, CharSequence title) {
- Intent intent = new Intent(ACTION_CHOOSER);
- intent.putExtra(EXTRA_INTENT, target);
- if (title != null) {
- intent.putExtra(EXTRA_TITLE, title);
- }
- return intent;
- }
- /**
- * Activity Action: Allow the user to select a particular kind of data and
- * return it. This is different than {@link #ACTION_PICK} in that here we
- * just say what kind of data is desired, not a URI of existing data from
- * which the user can pick. A ACTION_GET_CONTENT could allow the user to
- * create the data as it runs (for example taking a picture or recording a
- * sound), let them browser over the web and download the desired data,
- * etc.
- * <p>
- * There are two main ways to use this action: if you want an specific kind
- * of data, such as a person contact, you set the MIME type to the kind of
- * data you want and launch it with {@link Context#startActivity(Intent)}.
- * The system will then launch the best application to select that kind
- * of data for you.
- * <p>
- * You may also be interested in any of a set of types of content the user
- * can pick. For example, an e-mail application that wants to allow the
- * user to add an attachment to an e-mail message can use this action to
- * bring up a list of all of the types of content the user can attach.
- * <p>
- * In this case, you should wrap the GET_CONTENT intent with a chooser
- * (through {@link #createChooser}), which will give the proper interface
- * for the user to pick how to send your data and allow you to specify
- * a prompt indicating what they are doing. You will usually specify a
- * broad MIME type (such as image/* or {@literal *}/*), resulting in a
- * broad range of content types the user can select from.
- * <p>
- * When using such a broad GET_CONTENT action, it is often desireable to
- * only pick from data that can be represented as a stream. This is
- * accomplished by requiring the {@link #CATEGORY_OPENABLE} in the Intent.
- * <p>
- * Input: {@link #getType} is the desired MIME type to retrieve. Note
- * that no URI is supplied in the intent, as there are no constraints on
- * where the returned data originally comes from. You may also include the
- * {@link #CATEGORY_OPENABLE} if you can only accept data that can be
- * opened as a stream.
- * <p>
- * Output: The URI of the item that was picked. This must be a content:
- * URI so that any receiver can access it.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_GET_CONTENT = "android.intent.action.GET_CONTENT";
- /**
- * Activity Action: Dial a number as specified by the data. This shows a
- * UI with the number being dialed, allowing the user to explicitly
- * initiate the call.
- * <p>Input: If nothing, an empty dialer is started; else {@link #getData}
- * is URI of a phone number to be dialed or a tel: URI of an explicit phone
- * number.
- * <p>Output: nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_DIAL = "android.intent.action.DIAL";
- /**
- * Activity Action: Perform a call to someone specified by the data.
- * <p>Input: If nothing, an empty dialer is started; else {@link #getData}
- * is URI of a phone number to be dialed or a tel: URI of an explicit phone
- * number.
- * <p>Output: nothing.
- *
- * <p>Note: there will be restrictions on which applications can initiate a
- * call; most applications should use the {@link #ACTION_DIAL}.
- * <p>Note: this Intent <strong>cannot</strong> be used to call emergency
- * numbers. Applications can <strong>dial</strong> emergency numbers using
- * {@link #ACTION_DIAL}, however.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_CALL = "android.intent.action.CALL";
- /**
- * Activity Action: Perform a call to an emergency number specified by the
- * data.
- * <p>Input: {@link #getData} is URI of a phone number to be dialed or a
- * tel: URI of an explicit phone number.
- * <p>Output: nothing.
- * @hide
- */
- public static final String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY";
- /**
- * Activity action: Perform a call to any number (emergency or not)
- * specified by the data.
- * <p>Input: {@link #getData} is URI of a phone number to be dialed or a
- * tel: URI of an explicit phone number.
- * <p>Output: nothing.
- * @hide
- */
- public static final String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED";
- /**
- * Activity Action: Send a message to someone specified by the data.
- * <p>Input: {@link #getData} is URI describing the target.
- * <p>Output: nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_SENDTO = "android.intent.action.SENDTO";
- /**
- * Activity Action: Deliver some data to someone else. Who the data is
- * being delivered to is not specified; it is up to the receiver of this
- * action to ask the user where the data should be sent.
- * <p>
- * When launching a SEND intent, you should usually wrap it in a chooser
- * (through {@link #createChooser}), which will give the proper interface
- * for the user to pick how to send your data and allow you to specify
- * a prompt indicating what they are doing.
- * <p>
- * Input: {@link #getType} is the MIME type of the data being sent.
- * get*Extra can have either a {@link #EXTRA_TEXT}
- * or {@link #EXTRA_STREAM} field, containing the data to be sent. If
- * using EXTRA_TEXT, the MIME type should be "text/plain"; otherwise it
- * should be the MIME type of the data in EXTRA_STREAM. Use {@literal *}/*
- * if the MIME type is unknown (this will only allow senders that can
- * handle generic data streams).
- * <p>
- * Optional standard extras, which may be interpreted by some recipients as
- * appropriate, are: {@link #EXTRA_EMAIL}, {@link #EXTRA_CC},
- * {@link #EXTRA_BCC}, {@link #EXTRA_SUBJECT}.
- * <p>
- * Output: nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_SEND = "android.intent.action.SEND";
- /**
- * Activity Action: Handle an incoming phone call.
- * <p>Input: nothing.
- * <p>Output: nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_ANSWER = "android.intent.action.ANSWER";
- /**
- * Activity Action: Insert an empty item into the given container.
- * <p>Input: {@link #getData} is URI of the directory (vnd.android.cursor.dir/*)
- * in which to place the data.
- * <p>Output: URI of the new data that was created.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_INSERT = "android.intent.action.INSERT";
- /**
- * Activity Action: Delete the given data from its container.
- * <p>Input: {@link #getData} is URI of data to be deleted.
- * <p>Output: nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_DELETE = "android.intent.action.DELETE";
- /**
- * Activity Action: Run the data, whatever that means.
- * <p>Input: ? (Note: this is currently specific to the test harness.)
- * <p>Output: nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_RUN = "android.intent.action.RUN";
- /**
- * Activity Action: Perform a data synchronization.
- * <p>Input: ?
- * <p>Output: ?
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_SYNC = "android.intent.action.SYNC";
- /**
- * Activity Action: Pick an activity given an intent, returning the class
- * selected.
- * <p>Input: get*Extra field {@link #EXTRA_INTENT} is an Intent
- * used with {@link PackageManager#queryIntentActivities} to determine the
- * set of activities from which to pick.
- * <p>Output: Class name of the activity that was selected.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_PICK_ACTIVITY = "android.intent.action.PICK_ACTIVITY";
- /**
- * Activity Action: Perform a search.
- * <p>Input: {@link android.app.SearchManager#QUERY getStringExtra(SearchManager.QUERY)}
- * is the text to search for. If empty, simply
- * enter your search results Activity with the search UI activated.
- * <p>Output: nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_SEARCH = "android.intent.action.SEARCH";
- /**
- * Activity Action: Perform a web search.
- * <p>
- * Input: {@link android.app.SearchManager#QUERY
- * getStringExtra(SearchManager.QUERY)} is the text to search for. If it is
- * a url starts with http or https, the site will be opened. If it is plain
- * text, Google search will be applied.
- * <p>
- * Output: nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
- /**
- * Activity Action: List all available applications
- * <p>Input: Nothing.
- * <p>Output: nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_ALL_APPS = "android.intent.action.ALL_APPS";
- /**
- * Activity Action: Show settings for choosing wallpaper
- * <p>Input: Nothing.
- * <p>Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_SET_WALLPAPER = "android.intent.action.SET_WALLPAPER";
-
- /**
- * Activity Action: Show activity for reporting a bug.
- * <p>Input: Nothing.
- * <p>Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_BUG_REPORT = "android.intent.action.BUG_REPORT";
-
- /**
- * Activity Action: Main entry point for factory tests. Only used when
- * the device is booting in factory test node. The implementing package
- * must be installed in the system image.
- * <p>Input: nothing
- * <p>Output: nothing
- */
- public static final String ACTION_FACTORY_TEST = "android.intent.action.FACTORY_TEST";
-
- /**
- * Activity Action: The user pressed the "call" button to go to the dialer
- * or other appropriate UI for placing a call.
- * <p>Input: Nothing.
- * <p>Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON";
-
- /**
- * Activity Action: Start Voice Command.
- * <p>Input: Nothing.
- * <p>Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND";
-
- // ---------------------------------------------------------------------
- // ---------------------------------------------------------------------
- // Standard intent broadcast actions (see action variable).
-
- /**
- * Broadcast Action: Sent after the screen turns off.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";
- /**
- * Broadcast Action: Sent after the screen turns on.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON";
- /**
- * Broadcast Action: The current time has changed. Sent every
- * minute. You can <em>not</em> receive this through components declared
- * in manifests, only by exlicitly registering for it with
- * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
- * Context.registerReceiver()}.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_TIME_TICK = "android.intent.action.TIME_TICK";
- /**
- * Broadcast Action: The time was set.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_TIME_CHANGED = "android.intent.action.TIME_SET";
- /**
- * Broadcast Action: The date has changed.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_DATE_CHANGED = "android.intent.action.DATE_CHANGED";
- /**
- * Broadcast Action: The timezone has changed. The intent will have the following extra values:</p>
- * <ul>
- * <li><em>time-zone</em> - The java.util.TimeZone.getID() value identifying the new time zone.</li>
- * </ul>
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_TIMEZONE_CHANGED = "android.intent.action.TIMEZONE_CHANGED";
- /**
- * Alarm Changed Action: This is broadcast when the AlarmClock
- * application's alarm is set or unset. It is used by the
- * AlarmClock application and the StatusBar service.
- * @hide
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_ALARM_CHANGED = "android.intent.action.ALARM_CHANGED";
- /**
- * Sync State Changed Action: This is broadcast when the sync starts or stops or when one has
- * been failing for a long time. It is used by the SyncManager and the StatusBar service.
- * @hide
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_SYNC_STATE_CHANGED
- = "android.intent.action.SYNC_STATE_CHANGED";
- /**
- * Broadcast Action: This is broadcast once, after the system has finished
- * booting. It can be used to perform application-specific initialization,
- * such as installing alarms. You must hold the
- * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission
- * in order to receive this broadcast.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
- /**
- * Broadcast Action: This is broadcast when a user action should request a
- * temporary system dialog to dismiss. Some examples of temporary system
- * dialogs are the notification window-shade and the recent tasks dialog.
- */
- public static final String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
- /**
- * Broadcast Action: Trigger the download and eventual installation
- * of a package.
- * <p>Input: {@link #getData} is the URI of the package file to download.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
- /**
- * Broadcast Action: A new application package has been installed on the
- * device. The data contains the name of the package.
- * <p>My include the following extras:
- * <ul>
- * <li> {@link #EXTRA_UID} containing the integer uid assigned to the new package.
- * <li> {@link #EXTRA_REPLACING} is set to true if this is following
- * an {@link #ACTION_PACKAGE_REMOVED} broadcast for the same package.
- * </ul>
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
- /**
- * Broadcast Action: An existing application package has been removed from
- * the device. The data contains the name of the package. The package
- * that is being installed does <em>not</em> receive this Intent.
- * <ul>
- * <li> {@link #EXTRA_UID} containing the integer uid previously assigned
- * to the package.
- * <li> {@link #EXTRA_DATA_REMOVED} is set to true if the entire
- * application -- data and code -- is being removed.
- * <li> {@link #EXTRA_REPLACING} is set to true if this will be followed
- * by an {@link #ACTION_PACKAGE_ADDED} broadcast for the same package.
- * </ul>
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED";
- /**
- * Broadcast Action: An existing application package has been changed (e.g. a component has been
- * enabled or disabled. The data contains the name of the package.
- * <ul>
- * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package.
- * </ul>
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
- /**
- * Broadcast Action: The user has restarted a package, and all of its
- * processes have been killed. All runtime state
- * associated with it (processes, alarms, notifications, etc) should
- * be removed. The data contains the name of the package.
- * <ul>
- * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package.
- * </ul>
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED";
- /**
- * Broadcast Action: The user has cleared the data of a package. This should
- * be preceded by {@link #ACTION_PACKAGE_RESTARTED}, after which all of
- * its persistent data is erased and this broadcast sent. The data contains
- * the name of the package.
- * <ul>
- * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package.
- * </ul>
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
- /**
- * Broadcast Action: A user ID has been removed from the system. The user
- * ID number is stored in the extra data under {@link #EXTRA_UID}.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_UID_REMOVED = "android.intent.action.UID_REMOVED";
- /**
- * Broadcast Action: The current system wallpaper has changed. See
- * {@link Context#getWallpaper} for retrieving the new wallpaper.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED";
- /**
- * Broadcast Action: The current device {@link android.content.res.Configuration}
- * (orientation, locale, etc) has changed. When such a change happens, the
- * UIs (view hierarchy) will need to be rebuilt based on this new
- * information; for the most part, applications don't need to worry about
- * this, because the system will take care of stopping and restarting the
- * application to make sure it sees the new changes. Some system code that
- * can not be restarted will need to watch for this action and handle it
- * appropriately.
- *
- * @see android.content.res.Configuration
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CONFIGURATION_CHANGED = "android.intent.action.CONFIGURATION_CHANGED";
- /**
- * Broadcast Action: The charging state, or charge level of the battery has
- * changed.
- *
- * <p class="note">
- * You can <em>not</em> receive this through components declared
- * in manifests, only by exlicitly registering for it with
- * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
- * Context.registerReceiver()}.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED";
- /**
- * Broadcast Action: Indicates low battery condition on the device.
- * This broadcast corresponds to the "Low battery warning" system dialog.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_BATTERY_LOW = "android.intent.action.BATTERY_LOW";
- /**
- * Broadcast Action: Indicates low memory condition on the device
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_DEVICE_STORAGE_LOW = "android.intent.action.DEVICE_STORAGE_LOW";
- /**
- * Broadcast Action: Indicates low memory condition on the device no longer exists
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK";
- /**
- * Broadcast Action: Indicates low memory condition notification acknowledged by user
- * and package management should be started.
- * This is triggered by the user from the ACTION_DEVICE_STORAGE_LOW
- * notification.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
- /**
- * Broadcast Action: The device has entered USB Mass Storage mode.
- * This is used mainly for the USB Settings panel.
- * Apps should listen for ACTION_MEDIA_MOUNTED and ACTION_MEDIA_UNMOUNTED broadcasts to be notified
- * when the SD card file system is mounted or unmounted
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_UMS_CONNECTED = "android.intent.action.UMS_CONNECTED";
-
- /**
- * Broadcast Action: The device has exited USB Mass Storage mode.
- * This is used mainly for the USB Settings panel.
- * Apps should listen for ACTION_MEDIA_MOUNTED and ACTION_MEDIA_UNMOUNTED broadcasts to be notified
- * when the SD card file system is mounted or unmounted
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_UMS_DISCONNECTED = "android.intent.action.UMS_DISCONNECTED";
-
- /**
- * Broadcast Action: External media has been removed.
- * The path to the mount point for the removed media is contained in the Intent.mData field.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MEDIA_REMOVED = "android.intent.action.MEDIA_REMOVED";
-
- /**
- * Broadcast Action: External media is present, but not mounted at its mount point.
- * The path to the mount point for the removed media is contained in the Intent.mData field.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MEDIA_UNMOUNTED = "android.intent.action.MEDIA_UNMOUNTED";
-
- /**
- * Broadcast Action: External media is present, and being disk-checked
- * The path to the mount point for the checking media is contained in the Intent.mData field.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MEDIA_CHECKING = "android.intent.action.MEDIA_CHECKING";
-
- /**
- * Broadcast Action: External media is present, but is using an incompatible fs (or is blank)
- * The path to the mount point for the checking media is contained in the Intent.mData field.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MEDIA_NOFS = "android.intent.action.MEDIA_NOFS";
-
- /**
- * Broadcast Action: External media is present and mounted at its mount point.
- * The path to the mount point for the removed media is contained in the Intent.mData field.
- * The Intent contains an extra with name "read-only" and Boolean value to indicate if the
- * media was mounted read only.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MEDIA_MOUNTED = "android.intent.action.MEDIA_MOUNTED";
-
- /**
- * Broadcast Action: External media is unmounted because it is being shared via USB mass storage.
- * The path to the mount point for the removed media is contained in the Intent.mData field.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MEDIA_SHARED = "android.intent.action.MEDIA_SHARED";
-
- /**
- * Broadcast Action: External media was removed from SD card slot, but mount point was not unmounted.
- * The path to the mount point for the removed media is contained in the Intent.mData field.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
-
- /**
- * Broadcast Action: External media is present but cannot be mounted.
- * The path to the mount point for the removed media is contained in the Intent.mData field.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MEDIA_UNMOUNTABLE = "android.intent.action.MEDIA_UNMOUNTABLE";
-
- /**
- * Broadcast Action: User has expressed the desire to remove the external storage media.
- * Applications should close all files they have open within the mount point when they receive this intent.
- * The path to the mount point for the media to be ejected is contained in the Intent.mData field.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MEDIA_EJECT = "android.intent.action.MEDIA_EJECT";
-
- /**
- * Broadcast Action: The media scanner has started scanning a directory.
- * The path to the directory being scanned is contained in the Intent.mData field.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MEDIA_SCANNER_STARTED = "android.intent.action.MEDIA_SCANNER_STARTED";
-
- /**
- * Broadcast Action: The media scanner has finished scanning a directory.
- * The path to the scanned directory is contained in the Intent.mData field.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MEDIA_SCANNER_FINISHED = "android.intent.action.MEDIA_SCANNER_FINISHED";
-
- /**
- * Broadcast Action: Request the media scanner to scan a file and add it to the media database.
- * The path to the file is contained in the Intent.mData field.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MEDIA_SCANNER_SCAN_FILE = "android.intent.action.MEDIA_SCANNER_SCAN_FILE";
-
- /**
- * Broadcast Action: The "Media Button" was pressed. Includes a single
- * extra field, {@link #EXTRA_KEY_EVENT}, containing the key event that
- * caused the broadcast.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
-
- /**
- * Broadcast Action: The "Camera Button" was pressed. Includes a single
- * extra field, {@link #EXTRA_KEY_EVENT}, containing the key event that
- * caused the broadcast.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON";
-
- // *** NOTE: @todo(*) The following really should go into a more domain-specific
- // location; they are not general-purpose actions.
-
- /**
- * Broadcast Action: An GTalk connection has been established.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_GTALK_SERVICE_CONNECTED =
- "android.intent.action.GTALK_CONNECTED";
-
- /**
- * Broadcast Action: An GTalk connection has been disconnected.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_GTALK_SERVICE_DISCONNECTED =
- "android.intent.action.GTALK_DISCONNECTED";
-
- /**
- * Broadcast Action: An input method has been changed.
- * {@hide pending API Council approval}
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_INPUT_METHOD_CHANGED =
- "android.intent.action.INPUT_METHOD_CHANGED";
-
- /**
- * <p>Broadcast Action: The user has switched the phone into or out of Airplane Mode. One or
- * more radios have been turned off or on. The intent will have the following extra value:</p>
- * <ul>
- * <li><em>state</em> - A boolean value indicating whether Airplane Mode is on. If true,
- * then cell radio and possibly other radios such as bluetooth or WiFi may have also been
- * turned off</li>
- * </ul>
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE";
-
- /**
- * Broadcast Action: Some content providers have parts of their namespace
- * where they publish new events or items that the user may be especially
- * interested in. For these things, they may broadcast this action when the
- * set of interesting items change.
- *
- * For example, GmailProvider sends this notification when the set of unread
- * mail in the inbox changes.
- *
- * <p>The data of the intent identifies which part of which provider
- * changed. When queried through the content resolver, the data URI will
- * return the data set in question.
- *
- * <p>The intent will have the following extra values:
- * <ul>
- * <li><em>count</em> - The number of items in the data set. This is the
- * same as the number of items in the cursor returned by querying the
- * data URI. </li>
- * </ul>
- *
- * This intent will be sent at boot (if the count is non-zero) and when the
- * data set changes. It is possible for the data set to change without the
- * count changing (for example, if a new unread message arrives in the same
- * sync operation in which a message is archived). The phone should still
- * ring/vibrate/etc as normal in this case.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_PROVIDER_CHANGED =
- "android.intent.action.PROVIDER_CHANGED";
-
- /**
- * Broadcast Action: Wired Headset plugged in or unplugged.
- *
- * <p>The intent will have the following extra values:
- * <ul>
- * <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
- * <li><em>name</em> - Headset type, human readable string </li>
- * </ul>
- * </ul>
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_HEADSET_PLUG =
- "android.intent.action.HEADSET_PLUG";
-
- /**
- * Broadcast Action: An outgoing call is about to be placed.
- *
- * <p>The Intent will have the following extra value:
- * <ul>
- * <li><em>{@link android.content.Intent#EXTRA_PHONE_NUMBER}</em> -
- * the phone number originally intended to be dialed.</li>
- * </ul>
- * <p>Once the broadcast is finished, the resultData is used as the actual
- * number to call. If <code>null</code>, no call will be placed.</p>
- * <p>It is perfectly acceptable for multiple receivers to process the
- * outgoing call in turn: for example, a parental control application
- * might verify that the user is authorized to place the call at that
- * time, then a number-rewriting application might add an area code if
- * one was not specified.</p>
- * <p>For consistency, any receiver whose purpose is to prohibit phone
- * calls should have a priority of 0, to ensure it will see the final
- * phone number to be dialed.
- * Any receiver whose purpose is to rewrite phone numbers to be called
- * should have a positive priority.
- * Negative priorities are reserved for the system for this broadcast;
- * using them may cause problems.</p>
- * <p>Any BroadcastReceiver receiving this Intent <em>must not</em>
- * abort the broadcast.</p>
- * <p>Emergency calls cannot be intercepted using this mechanism, and
- * other calls cannot be modified to call emergency numbers using this
- * mechanism.
- * <p>You must hold the
- * {@link android.Manifest.permission#PROCESS_OUTGOING_CALLS}
- * permission to receive this Intent.</p>
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_NEW_OUTGOING_CALL =
- "android.intent.action.NEW_OUTGOING_CALL";
-
- /**
- * Broadcast Action: Have the device reboot. This is only for use by
- * system code.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_REBOOT =
- "android.intent.action.REBOOT";
-
- // ---------------------------------------------------------------------
- // ---------------------------------------------------------------------
- // Standard intent categories (see addCategory()).
-
- /**
- * Set if the activity should be an option for the default action
- * (center press) to perform on a piece of data. Setting this will
- * hide from the user any activities without it set when performing an
- * action on some data. Note that this is normal -not- set in the
- * Intent when initiating an action -- it is for use in intent filters
- * specified in packages.
- */
- @SdkConstant(SdkConstantType.INTENT_CATEGORY)
- public static final String CATEGORY_DEFAULT = "android.intent.category.DEFAULT";
- /**
- * Activities that can be safely invoked from a browser must support this
- * category. For example, if the user is viewing a web page or an e-mail
- * and clicks on a link in the text, the Intent generated execute that
- * link will require the BROWSABLE category, so that only activities
- * supporting this category will be considered as possible actions. By
- * supporting this category, you are promising that there is nothing
- * damaging (without user intervention) that can happen by invoking any
- * matching Intent.
- */
- @SdkConstant(SdkConstantType.INTENT_CATEGORY)
- public static final String CATEGORY_BROWSABLE = "android.intent.category.BROWSABLE";
- /**
- * Set if the activity should be considered as an alternative action to
- * the data the user is currently viewing. See also
- * {@link #CATEGORY_SELECTED_ALTERNATIVE} for an alternative action that
- * applies to the selection in a list of items.
- *
- * <p>Supporting this category means that you would like your activity to be
- * displayed in the set of alternative things the user can do, usually as
- * part of the current activity's options menu. You will usually want to
- * include a specific label in the &lt;intent-filter&gt; of this action
- * describing to the user what it does.
- *
- * <p>The action of IntentFilter with this category is important in that it
- * describes the specific action the target will perform. This generally
- * should not be a generic action (such as {@link #ACTION_VIEW}, but rather
- * a specific name such as "com.android.camera.action.CROP. Only one
- * alternative of any particular action will be shown to the user, so using
- * a specific action like this makes sure that your alternative will be
- * displayed while also allowing other applications to provide their own
- * overrides of that particular action.
- */
- @SdkConstant(SdkConstantType.INTENT_CATEGORY)
- public static final String CATEGORY_ALTERNATIVE = "android.intent.category.ALTERNATIVE";
- /**
- * Set if the activity should be considered as an alternative selection
- * action to the data the user has currently selected. This is like
- * {@link #CATEGORY_ALTERNATIVE}, but is used in activities showing a list
- * of items from which the user can select, giving them alternatives to the
- * default action that will be performed on it.
- */
- @SdkConstant(SdkConstantType.INTENT_CATEGORY)
- public static final String CATEGORY_SELECTED_ALTERNATIVE = "android.intent.category.SELECTED_ALTERNATIVE";
- /**
- * Intended to be used as a tab inside of an containing TabActivity.
- */
- @SdkConstant(SdkConstantType.INTENT_CATEGORY)
- public static final String CATEGORY_TAB = "android.intent.category.TAB";
- /**
- * This activity can be embedded inside of another activity that is hosting
- * gadgets.
- */
- @SdkConstant(SdkConstantType.INTENT_CATEGORY)
- public static final String CATEGORY_GADGET = "android.intent.category.GADGET";
- /**
- * Should be displayed in the top-level launcher.
- */
- @SdkConstant(SdkConstantType.INTENT_CATEGORY)
- public static final String CATEGORY_LAUNCHER = "android.intent.category.LAUNCHER";
- /**
- * This is the home activity, that is the first activity that is displayed
- * when the device boots.
- */
- @SdkConstant(SdkConstantType.INTENT_CATEGORY)
- public static final String CATEGORY_HOME = "android.intent.category.HOME";
- /**
- * This activity is a preference panel.
- */
- @SdkConstant(SdkConstantType.INTENT_CATEGORY)
- public static final String CATEGORY_PREFERENCE = "android.intent.category.PREFERENCE";
- /**
- * This activity is a development preference panel.
- */
- @SdkConstant(SdkConstantType.INTENT_CATEGORY)
- public static final String CATEGORY_DEVELOPMENT_PREFERENCE = "android.intent.category.DEVELOPMENT_PREFERENCE";
- /**
- * Capable of running inside a parent activity container.
- *
- * <p>Note: being removed in favor of more explicit categories such as
- * CATEGORY_GADGET
- */
- @SdkConstant(SdkConstantType.INTENT_CATEGORY)
- public static final String CATEGORY_EMBED = "android.intent.category.EMBED";
- /**
- * This activity may be exercised by the monkey or other automated test tools.
- */
- @SdkConstant(SdkConstantType.INTENT_CATEGORY)
- public static final String CATEGORY_MONKEY = "android.intent.category.MONKEY";
- /**
- * To be used as a test (not part of the normal user experience).
- */
- public static final String CATEGORY_TEST = "android.intent.category.TEST";
- /**
- * To be used as a unit test (run through the Test Harness).
- */
- public static final String CATEGORY_UNIT_TEST = "android.intent.category.UNIT_TEST";
- /**
- * To be used as an sample code example (not part of the normal user
- * experience).
- */
- public static final String CATEGORY_SAMPLE_CODE = "android.intent.category.SAMPLE_CODE";
- /**
- * Used to indicate that a GET_CONTENT intent only wants URIs that can be opened with
- * ContentResolver.openInputStream. Openable URIs must support the columns in OpenableColumns
- * when queried, though it is allowable for those columns to be blank.
- */
- @SdkConstant(SdkConstantType.INTENT_CATEGORY)
- public static final String CATEGORY_OPENABLE = "android.intent.category.OPENABLE";
-
- /**
- * To be used as code under test for framework instrumentation tests.
- */
- public static final String CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST =
- "android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST";
- // ---------------------------------------------------------------------
- // ---------------------------------------------------------------------
- // Standard extra data keys.
-
- /**
- * The initial data to place in a newly created record. Use with
- * {@link #ACTION_INSERT}. The data here is a Map containing the same
- * fields as would be given to the underlying ContentProvider.insert()
- * call.
- */
- public static final String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE";
-
- /**
- * A constant CharSequence that is associated with the Intent, used with
- * {@link #ACTION_SEND} to supply the literal data to be sent. Note that
- * this may be a styled CharSequence, so you must use
- * {@link Bundle#getCharSequence(String) Bundle.getCharSequence()} to
- * retrieve it.
- */
- public static final String EXTRA_TEXT = "android.intent.extra.TEXT";
-
- /**
- * A content: URI holding a stream of data associated with the Intent,
- * used with {@link #ACTION_SEND} to supply the data being sent.
- */
- public static final String EXTRA_STREAM = "android.intent.extra.STREAM";
-
- /**
- * A String[] holding e-mail addresses that should be delivered to.
- */
- public static final String EXTRA_EMAIL = "android.intent.extra.EMAIL";
-
- /**
- * A String[] holding e-mail addresses that should be carbon copied.
- */
- public static final String EXTRA_CC = "android.intent.extra.CC";
-
- /**
- * A String[] holding e-mail addresses that should be blind carbon copied.
- */
- public static final String EXTRA_BCC = "android.intent.extra.BCC";
-
- /**
- * A constant string holding the desired subject line of a message.
- */
- public static final String EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
-
- /**
- * An Intent describing the choices you would like shown with
- * {@link #ACTION_PICK_ACTIVITY}.
- */
- public static final String EXTRA_INTENT = "android.intent.extra.INTENT";
-
- /**
- * A CharSequence dialog title to provide to the user when used with a
- * {@link #ACTION_CHOOSER}.
- */
- public static final String EXTRA_TITLE = "android.intent.extra.TITLE";
-
- /**
- * A {@link android.view.KeyEvent} object containing the event that
- * triggered the creation of the Intent it is in.
- */
- public static final String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT";
-
- /**
- * Used as an boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED} or
- * {@link android.content.Intent#ACTION_PACKAGE_CHANGED} intents to override the default action
- * of restarting the application.
- */
- public static final String EXTRA_DONT_KILL_APP = "android.intent.extra.DONT_KILL_APP";
-
- /**
- * A String holding the phone number originally entered in
- * {@link android.content.Intent#ACTION_NEW_OUTGOING_CALL}, or the actual
- * number to call in a {@link android.content.Intent#ACTION_CALL}.
- */
- public static final String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
- /**
- * Used as an int extra field in {@link android.content.Intent#ACTION_UID_REMOVED}
- * intents to supply the uid the package had been assigned. Also an optional
- * extra in {@link android.content.Intent#ACTION_PACKAGE_REMOVED} or
- * {@link android.content.Intent#ACTION_PACKAGE_CHANGED} for the same
- * purpose.
- */
- public static final String EXTRA_UID = "android.intent.extra.UID";
-
- /**
- * Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED}
- * intents to indicate whether this represents a full uninstall (removing
- * both the code and its data) or a partial uninstall (leaving its data,
- * implying that this is an update).
- */
- public static final String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED";
-
- /**
- * Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED}
- * intents to indicate that this is a replacement of the package, so this
- * broadcast will immediately be followed by an add broadcast for a
- * different version of the same package.
- */
- public static final String EXTRA_REPLACING = "android.intent.extra.REPLACING";
-
- /**
- * Used as an int extra field in {@link android.app.AlarmManager} intents
- * to tell the application being invoked how many pending alarms are being
- * delievered with the intent. For one-shot alarms this will always be 1.
- * For recurring alarms, this might be greater than 1 if the device was
- * asleep or powered off at the time an earlier alarm would have been
- * delivered.
- */
- public static final String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
-
- /**
- * Used as an int extra field in {@link android.content.Intent#ACTION_VOICE_COMMAND}
- * intents to request which audio route the voice command should prefer.
- * The value should be a route from {@link android.media.AudioManager}, for
- * example ROUTE_BLUETOOTH_SCO. Providing this value is optional.
- * {@hide pending API Council approval}
- */
- public static final String EXTRA_AUDIO_ROUTE = "android.intent.extra.AUDIO_ROUTE";
-
- // ---------------------------------------------------------------------
- // ---------------------------------------------------------------------
- // Intent flags (see mFlags variable).
-
- /**
- * If set, the recipient of this Intent will be granted permission to
- * perform read operations on the Uri in the Intent's data.
- */
- public static final int FLAG_GRANT_READ_URI_PERMISSION = 0x00000001;
- /**
- * If set, the recipient of this Intent will be granted permission to
- * perform write operations on the Uri in the Intent's data.
- */
- public static final int FLAG_GRANT_WRITE_URI_PERMISSION = 0x00000002;
- /**
- * Can be set by the caller to indicate that this Intent is coming from
- * a background operation, not from direct user interaction.
- */
- public static final int FLAG_FROM_BACKGROUND = 0x00000004;
- /**
- * A flag you can enable for debugging: when set, log messages will be
- * printed during the resolution of this intent to show you what has
- * been found to create the final resolved list.
- */
- public static final int FLAG_DEBUG_LOG_RESOLUTION = 0x00000008;
-
- /**
- * If set, the new activity is not kept in the history stack. As soon as
- * the user navigates away from it, the activity is finished. This may also
- * be set with the {@link android.R.styleable#AndroidManifestActivity_noHistory
- * noHistory} attribute.
- */
- public static final int FLAG_ACTIVITY_NO_HISTORY = 0x40000000;
- /**
- * If set, the activity will not be launched if it is already running
- * at the top of the history stack.
- */
- public static final int FLAG_ACTIVITY_SINGLE_TOP = 0x20000000;
- /**
- * If set, this activity will become the start of a new task on this
- * history stack. A task (from the activity that started it to the
- * next task activity) defines an atomic group of activities that the
- * user can move to. Tasks can be moved to the foreground and background;
- * all of the activities inside of a particular task always remain in
- * the same order. See
- * <a href="{@docRoot}guide/topics/fundamentals.html#acttask">Application Fundamentals:
- * Activities and Tasks</a> for more details on tasks.
- *
- * <p>This flag is generally used by activities that want
- * to present a "launcher" style behavior: they give the user a list of
- * separate things that can be done, which otherwise run completely
- * independently of the activity launching them.
- *
- * <p>When using this flag, if a task is already running for the activity
- * you are now starting, then a new activity will not be started; instead,
- * the current task will simply be brought to the front of the screen with
- * the state it was last in. See {@link #FLAG_ACTIVITY_MULTIPLE_TASK} for a flag
- * to disable this behavior.
- *
- * <p>This flag can not be used when the caller is requesting a result from
- * the activity being launched.
- */
- public static final int FLAG_ACTIVITY_NEW_TASK = 0x10000000;
- /**
- * <strong>Do not use this flag unless you are implementing your own
- * top-level application launcher.</strong> Used in conjunction with
- * {@link #FLAG_ACTIVITY_NEW_TASK} to disable the
- * behavior of bringing an existing task to the foreground. When set,
- * a new task is <em>always</em> started to host the Activity for the
- * Intent, regardless of whether there is already an existing task running
- * the same thing.
- *
- * <p><strong>Because the default system does not include graphical task management,
- * you should not use this flag unless you provide some way for a user to
- * return back to the tasks you have launched.</strong>
- *
- * <p>This flag is ignored if
- * {@link #FLAG_ACTIVITY_NEW_TASK} is not set.
- *
- * <p>See <a href="{@docRoot}guide/topics/fundamentals.html#acttask">Application Fundamentals:
- * Activities and Tasks</a> for more details on tasks.
- */
- public static final int FLAG_ACTIVITY_MULTIPLE_TASK = 0x08000000;
- /**
- * If set, and the activity being launched is already running in the
- * current task, then instead of launching a new instance of that activity,
- * all of the other activities on top of it will be closed and this Intent
- * will be delivered to the (now on top) old activity as a new Intent.
- *
- * <p>For example, consider a task consisting of the activities: A, B, C, D.
- * If D calls startActivity() with an Intent that resolves to the component
- * of activity B, then C and D will be finished and B receive the given
- * Intent, resulting in the stack now being: A, B.
- *
- * <p>The currently running instance of task B in the above example will
- * either receive the new intent you are starting here in its
- * onNewIntent() method, or be itself finished and restarted with the
- * new intent. If it has declared its launch mode to be "multiple" (the
- * default) it will be finished and re-created; for all other launch modes
- * it will receive the Intent in the current instance.
- *
- * <p>This launch mode can also be used to good effect in conjunction with
- * {@link #FLAG_ACTIVITY_NEW_TASK}: if used to start the root activity
- * of a task, it will bring any currently running instance of that task
- * to the foreground, and then clear it to its root state. This is
- * especially useful, for example, when launching an activity from the
- * notification manager.
- *
- * <p>See <a href="{@docRoot}guide/topics/fundamentals.html#acttask">Application Fundamentals:
- * Activities and Tasks</a> for more details on tasks.
- */
- public static final int FLAG_ACTIVITY_CLEAR_TOP = 0x04000000;
- /**
- * If set and this intent is being used to launch a new activity from an
- * existing one, then the reply target of the existing activity will be
- * transfered to the new activity. This way the new activity can call
- * {@link android.app.Activity#setResult} and have that result sent back to
- * the reply target of the original activity.
- */
- public static final int FLAG_ACTIVITY_FORWARD_RESULT = 0x02000000;
- /**
- * If set and this intent is being used to launch a new activity from an
- * existing one, the current activity will not be counted as the top
- * activity for deciding whether the new intent should be delivered to
- * the top instead of starting a new one. The previous activity will
- * be used as the top, with the assumption being that the current activity
- * will finish itself immediately.
- */
- public static final int FLAG_ACTIVITY_PREVIOUS_IS_TOP = 0x01000000;
- /**
- * If set, the new activity is not kept in the list of recently launched
- * activities.
- */
- public static final int FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS = 0x00800000;
- /**
- * This flag is not normally set by application code, but set for you by
- * the system as described in the
- * {@link android.R.styleable#AndroidManifestActivity_launchMode
- * launchMode} documentation for the singleTask mode.
- */
- public static final int FLAG_ACTIVITY_BROUGHT_TO_FRONT = 0x00400000;
- /**
- * If set, and this activity is either being started in a new task or
- * bringing to the top an existing task, then it will be launched as
- * the front door of the task. This will result in the application of
- * any affinities needed to have that task in the proper state (either
- * moving activities to or from it), or simply resetting that task to
- * its initial state if needed.
- */
- public static final int FLAG_ACTIVITY_RESET_TASK_IF_NEEDED = 0x00200000;
- /**
- * This flag is not normally set by application code, but set for you by
- * the system if this activity is being launched from history
- * (longpress home key).
- */
- public static final int FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY = 0x00100000;
- /**
- * If set, this marks a point in the task's activity stack that should
- * be cleared when the task is reset. That is, the next time the task
- * is broad to the foreground with
- * {@link #FLAG_ACTIVITY_RESET_TASK_IF_NEEDED} (typically as a result of
- * the user re-launching it from home), this activity and all on top of
- * it will be finished so that the user does not return to them, but
- * instead returns to whatever activity preceeded it.
- *
- * <p>This is useful for cases where you have a logical break in your
- * application. For example, an e-mail application may have a command
- * to view an attachment, which launches an image view activity to
- * display it. This activity should be part of the e-mail application's
- * task, since it is a part of the task the user is involved in. However,
- * if the user leaves that task, and later selects the e-mail app from
- * home, we may like them to return to the conversation they were
- * viewing, not the picture attachment, since that is confusing. By
- * setting this flag when launching the image viewer, that viewer and
- * any activities it starts will be removed the next time the user returns
- * to mail.
- */
- public static final int FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET = 0x00080000;
- /**
- * If set, this flag will prevent the normal {@link android.app.Activity#onUserLeaveHint}
- * callback from occurring on the current frontmost activity before it is
- * paused as the newly-started activity is brought to the front.
- *
- * <p>Typically, an activity can rely on that callback to indicate that an
- * explicit user action has caused their activity to be moved out of the
- * foreground. The callback marks an appropriate point in the activity's
- * lifecycle for it to dismiss any notifications that it intends to display
- * "until the user has seen them," such as a blinking LED.
- *
- * <p>If an activity is ever started via any non-user-driven events such as
- * phone-call receipt or an alarm handler, this flag should be passed to {@link
- * Context#startActivity Context.startActivity}, ensuring that the pausing
- * activity does not think the user has acknowledged its notification.
- */
- public static final int FLAG_ACTIVITY_NO_USER_ACTION = 0x00040000;
- /**
- * If set in an Intent passed to {@link Context#startActivity Context.startActivity()},
- * this flag will cause the launched activity to be brought to the front of its
- * task's history stack if it is already running.
- *
- * <p>For example, consider a task consisting of four activities: A, B, C, D.
- * If D calls startActivity() with an Intent that resolves to the component
- * of activity B, then B will be brought to the front of the history stack,
- * with this resulting order: A, C, D, B.
- *
- * This flag will be ignored if {@link #FLAG_ACTIVITY_CLEAR_TOP} is also
- * specified.
- */
- public static final int FLAG_ACTIVITY_REORDER_TO_FRONT = 0X00020000;
- /**
- * If set, when sending a broadcast only registered receivers will be
- * called -- no BroadcastReceiver components will be launched.
- */
- public static final int FLAG_RECEIVER_REGISTERED_ONLY = 0x40000000;
- /**
- * If set, when sending a broadcast <i>before boot has completed</i> only
- * registered receivers will be called -- no BroadcastReceiver components
- * will be launched. Sticky intent state will be recorded properly even
- * if no receivers wind up being called. If {@link #FLAG_RECEIVER_REGISTERED_ONLY}
- * is specified in the broadcast intent, this flag is unnecessary.
- *
- * <p>This flag is only for use by system sevices as a convenience to
- * avoid having to implement a more complex mechanism around detection
- * of boot completion.
- *
- * @hide
- */
- public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 0x20000000;
-
- // ---------------------------------------------------------------------
-
- private String mAction;
- private Uri mData;
- private String mType;
- private ComponentName mComponent;
- private int mFlags;
- private HashSet<String> mCategories;
- private Bundle mExtras;
-
- // ---------------------------------------------------------------------
-
- /**
- * Create an empty intent.
- */
- public Intent() {
- }
-
- /**
- * Copy constructor.
- */
- public Intent(Intent o) {
- this.mAction = o.mAction;
- this.mData = o.mData;
- this.mType = o.mType;
- this.mComponent = o.mComponent;
- this.mFlags = o.mFlags;
- if (o.mCategories != null) {
- this.mCategories = new HashSet<String>(o.mCategories);
- }
- if (o.mExtras != null) {
- this.mExtras = new Bundle(o.mExtras);
- }
- }
-
- @Override
- public Object clone() {
- return new Intent(this);
- }
-
- private Intent(Intent o, boolean all) {
- this.mAction = o.mAction;
- this.mData = o.mData;
- this.mType = o.mType;
- this.mComponent = o.mComponent;
- if (o.mCategories != null) {
- this.mCategories = new HashSet<String>(o.mCategories);
- }
- }
-
- /**
- * Make a clone of only the parts of the Intent that are relevant for
- * filter matching: the action, data, type, component, and categories.
- */
- public Intent cloneFilter() {
- return new Intent(this, false);
- }
-
- /**
- * Create an intent with a given action. All other fields (data, type,
- * class) are null. Note that the action <em>must</em> be in a
- * namespace because Intents are used globally in the system -- for
- * example the system VIEW action is android.intent.action.VIEW; an
- * application's custom action would be something like
- * com.google.app.myapp.CUSTOM_ACTION.
- *
- * @param action The Intent action, such as ACTION_VIEW.
- */
- public Intent(String action) {
- mAction = action;
- }
-
- /**
- * Create an intent with a given action and for a given data url. Note
- * that the action <em>must</em> be in a namespace because Intents are
- * used globally in the system -- for example the system VIEW action is
- * android.intent.action.VIEW; an application's custom action would be
- * something like com.google.app.myapp.CUSTOM_ACTION.
- *
- * @param action The Intent action, such as ACTION_VIEW.
- * @param uri The Intent data URI.
- */
- public Intent(String action, Uri uri) {
- mAction = action;
- mData = uri;
- }
-
- /**
- * Create an intent for a specific component. All other fields (action, data,
- * type, class) are null, though they can be modified later with explicit
- * calls. This provides a convenient way to create an intent that is
- * intended to execute a hard-coded class name, rather than relying on the
- * system to find an appropriate class for you; see {@link #setComponent}
- * for more information on the repercussions of this.
- *
- * @param packageContext A Context of the application package implementing
- * this class.
- * @param cls The component class that is to be used for the intent.
- *
- * @see #setClass
- * @see #setComponent
- * @see #Intent(String, android.net.Uri , Context, Class)
- */
- public Intent(Context packageContext, Class<?> cls) {
- mComponent = new ComponentName(packageContext, cls);
- }
-
- /**
- * Create an intent for a specific component with a specified action and data.
- * This is equivalent using {@link #Intent(String, android.net.Uri)} to
- * construct the Intent and then calling {@link #setClass} to set its
- * class.
- *
- * @param action The Intent action, such as ACTION_VIEW.
- * @param uri The Intent data URI.
- * @param packageContext A Context of the application package implementing
- * this class.
- * @param cls The component class that is to be used for the intent.
- *
- * @see #Intent(String, android.net.Uri)
- * @see #Intent(Context, Class)
- * @see #setClass
- * @see #setComponent
- */
- public Intent(String action, Uri uri,
- Context packageContext, Class<?> cls) {
- mAction = action;
- mData = uri;
- mComponent = new ComponentName(packageContext, cls);
- }
-
- /**
- * Create an intent from a URI. This URI may encode the action,
- * category, and other intent fields, if it was returned by toURI(). If
- * the Intent was not generate by toURI(), its data will be the entire URI
- * and its action will be ACTION_VIEW.
- *
- * <p>The URI given here must not be relative -- that is, it must include
- * the scheme and full path.
- *
- * @param uri The URI to turn into an Intent.
- *
- * @return Intent The newly created Intent object.
- *
- * @see #toURI
- */
- public static Intent getIntent(String uri) throws URISyntaxException {
- int i = 0;
- try {
- // simple case
- i = uri.lastIndexOf("#");
- if (i == -1) return new Intent(ACTION_VIEW, Uri.parse(uri));
-
- // old format Intent URI
- if (!uri.startsWith("#Intent;", i)) return getIntentOld(uri);
-
- // new format
- Intent intent = new Intent(ACTION_VIEW);
-
- // fetch data part, if present
- if (i > 0) {
- intent.mData = Uri.parse(uri.substring(0, i));
- }
- i += "#Intent;".length();
-
- // loop over contents of Intent, all name=value;
- while (!uri.startsWith("end", i)) {
- int eq = uri.indexOf('=', i);
- int semi = uri.indexOf(';', eq);
- String value = uri.substring(eq + 1, semi);
-
- // action
- if (uri.startsWith("action=", i)) {
- intent.mAction = value;
- }
-
- // categories
- else if (uri.startsWith("category=", i)) {
- intent.addCategory(value);
- }
-
- // type
- else if (uri.startsWith("type=", i)) {
- intent.mType = value;
- }
-
- // launch flags
- else if (uri.startsWith("launchFlags=", i)) {
- intent.mFlags = Integer.decode(value).intValue();
- }
-
- // component
- else if (uri.startsWith("component=", i)) {
- intent.mComponent = ComponentName.unflattenFromString(value);
- }
-
- // extra
- else {
- String key = Uri.decode(uri.substring(i + 2, eq));
- value = Uri.decode(value);
- // create Bundle if it doesn't already exist
- if (intent.mExtras == null) intent.mExtras = new Bundle();
- Bundle b = intent.mExtras;
- // add EXTRA
- if (uri.startsWith("S.", i)) b.putString(key, value);
- else if (uri.startsWith("B.", i)) b.putBoolean(key, Boolean.parseBoolean(value));
- else if (uri.startsWith("b.", i)) b.putByte(key, Byte.parseByte(value));
- else if (uri.startsWith("c.", i)) b.putChar(key, value.charAt(0));
- else if (uri.startsWith("d.", i)) b.putDouble(key, Double.parseDouble(value));
- else if (uri.startsWith("f.", i)) b.putFloat(key, Float.parseFloat(value));
- else if (uri.startsWith("i.", i)) b.putInt(key, Integer.parseInt(value));
- else if (uri.startsWith("l.", i)) b.putLong(key, Long.parseLong(value));
- else if (uri.startsWith("s.", i)) b.putShort(key, Short.parseShort(value));
- else throw new URISyntaxException(uri, "unknown EXTRA type", i);
- }
-
- // move to the next item
- i = semi + 1;
- }
-
- return intent;
-
- } catch (IndexOutOfBoundsException e) {
- throw new URISyntaxException(uri, "illegal Intent URI format", i);
- }
- }
-
- public static Intent getIntentOld(String uri) throws URISyntaxException {
- Intent intent;
-
- int i = uri.lastIndexOf('#');
- if (i >= 0) {
- Uri data = null;
- String action = null;
- if (i > 0) {
- data = Uri.parse(uri.substring(0, i));
- }
-
- i++;
-
- if (uri.regionMatches(i, "action(", 0, 7)) {
- i += 7;
- int j = uri.indexOf(')', i);
- action = uri.substring(i, j);
- i = j + 1;
- }
-
- intent = new Intent(action, data);
-
- if (uri.regionMatches(i, "categories(", 0, 11)) {
- i += 11;
- int j = uri.indexOf(')', i);
- while (i < j) {
- int sep = uri.indexOf('!', i);
- if (sep < 0) sep = j;
- if (i < sep) {
- intent.addCategory(uri.substring(i, sep));
- }
- i = sep + 1;
- }
- i = j + 1;
- }
-
- if (uri.regionMatches(i, "type(", 0, 5)) {
- i += 5;
- int j = uri.indexOf(')', i);
- intent.mType = uri.substring(i, j);
- i = j + 1;
- }
-
- if (uri.regionMatches(i, "launchFlags(", 0, 12)) {
- i += 12;
- int j = uri.indexOf(')', i);
- intent.mFlags = Integer.decode(uri.substring(i, j)).intValue();
- i = j + 1;
- }
-
- if (uri.regionMatches(i, "component(", 0, 10)) {
- i += 10;
- int j = uri.indexOf(')', i);
- int sep = uri.indexOf('!', i);
- if (sep >= 0 && sep < j) {
- String pkg = uri.substring(i, sep);
- String cls = uri.substring(sep + 1, j);
- intent.mComponent = new ComponentName(pkg, cls);
- }
- i = j + 1;
- }
-
- if (uri.regionMatches(i, "extras(", 0, 7)) {
- i += 7;
-
- final int closeParen = uri.indexOf(')', i);
- if (closeParen == -1) throw new URISyntaxException(uri,
- "EXTRA missing trailing ')'", i);
-
- while (i < closeParen) {
- // fetch the key value
- int j = uri.indexOf('=', i);
- if (j <= i + 1 || i >= closeParen) {
- throw new URISyntaxException(uri, "EXTRA missing '='", i);
- }
- char type = uri.charAt(i);
- i++;
- String key = uri.substring(i, j);
- i = j + 1;
-
- // get type-value
- j = uri.indexOf('!', i);
- if (j == -1 || j >= closeParen) j = closeParen;
- if (i >= j) throw new URISyntaxException(uri, "EXTRA missing '!'", i);
- String value = uri.substring(i, j);
- i = j;
-
- // create Bundle if it doesn't already exist
- if (intent.mExtras == null) intent.mExtras = new Bundle();
-
- // add item to bundle
- try {
- switch (type) {
- case 'S':
- intent.mExtras.putString(key, Uri.decode(value));
- break;
- case 'B':
- intent.mExtras.putBoolean(key, Boolean.parseBoolean(value));
- break;
- case 'b':
- intent.mExtras.putByte(key, Byte.parseByte(value));
- break;
- case 'c':
- intent.mExtras.putChar(key, Uri.decode(value).charAt(0));
- break;
- case 'd':
- intent.mExtras.putDouble(key, Double.parseDouble(value));
- break;
- case 'f':
- intent.mExtras.putFloat(key, Float.parseFloat(value));
- break;
- case 'i':
- intent.mExtras.putInt(key, Integer.parseInt(value));
- break;
- case 'l':
- intent.mExtras.putLong(key, Long.parseLong(value));
- break;
- case 's':
- intent.mExtras.putShort(key, Short.parseShort(value));
- break;
- default:
- throw new URISyntaxException(uri, "EXTRA has unknown type", i);
- }
- } catch (NumberFormatException e) {
- throw new URISyntaxException(uri, "EXTRA value can't be parsed", i);
- }
-
- char ch = uri.charAt(i);
- if (ch == ')') break;
- if (ch != '!') throw new URISyntaxException(uri, "EXTRA missing '!'", i);
- i++;
- }
- }
-
- if (intent.mAction == null) {
- // By default, if no action is specified, then use VIEW.
- intent.mAction = ACTION_VIEW;
- }
-
- } else {
- intent = new Intent(ACTION_VIEW, Uri.parse(uri));
- }
-
- return intent;
- }
-
- /**
- * Retrieve the general action to be performed, such as
- * {@link #ACTION_VIEW}. The action describes the general way the rest of
- * the information in the intent should be interpreted -- most importantly,
- * what to do with the data returned by {@link #getData}.
- *
- * @return The action of this intent or null if none is specified.
- *
- * @see #setAction
- */
- public String getAction() {
- return mAction;
- }
-
- /**
- * Retrieve data this intent is operating on. This URI specifies the name
- * of the data; often it uses the content: scheme, specifying data in a
- * content provider. Other schemes may be handled by specific activities,
- * such as http: by the web browser.
- *
- * @return The URI of the data this intent is targeting or null.
- *
- * @see #getScheme
- * @see #setData
- */
- public Uri getData() {
- return mData;
- }
-
- /**
- * The same as {@link #getData()}, but returns the URI as an encoded
- * String.
- */
- public String getDataString() {
- return mData != null ? mData.toString() : null;
- }
-
- /**
- * Return the scheme portion of the intent's data. If the data is null or
- * does not include a scheme, null is returned. Otherwise, the scheme
- * prefix without the final ':' is returned, i.e. "http".
- *
- * <p>This is the same as calling getData().getScheme() (and checking for
- * null data).
- *
- * @return The scheme of this intent.
- *
- * @see #getData
- */
- public String getScheme() {
- return mData != null ? mData.getScheme() : null;
- }
-
- /**
- * Retrieve any explicit MIME type included in the intent. This is usually
- * null, as the type is determined by the intent data.
- *
- * @return If a type was manually set, it is returned; else null is
- * returned.
- *
- * @see #resolveType(ContentResolver)
- * @see #setType
- */
- public String getType() {
- return mType;
- }
-
- /**
- * Return the MIME data type of this intent. If the type field is
- * explicitly set, that is simply returned. Otherwise, if the data is set,
- * the type of that data is returned. If neither fields are set, a null is
- * returned.
- *
- * @return The MIME type of this intent.
- *
- * @see #getType
- * @see #resolveType(ContentResolver)
- */
- public String resolveType(Context context) {
- return resolveType(context.getContentResolver());
- }
-
- /**
- * Return the MIME data type of this intent. If the type field is
- * explicitly set, that is simply returned. Otherwise, if the data is set,
- * the type of that data is returned. If neither fields are set, a null is
- * returned.
- *
- * @param resolver A ContentResolver that can be used to determine the MIME
- * type of the intent's data.
- *
- * @return The MIME type of this intent.
- *
- * @see #getType
- * @see #resolveType(Context)
- */
- public String resolveType(ContentResolver resolver) {
- if (mType != null) {
- return mType;
- }
- if (mData != null) {
- if ("content".equals(mData.getScheme())) {
- return resolver.getType(mData);
- }
- }
- return null;
- }
-
- /**
- * Return the MIME data type of this intent, only if it will be needed for
- * intent resolution. This is not generally useful for application code;
- * it is used by the frameworks for communicating with back-end system
- * services.
- *
- * @param resolver A ContentResolver that can be used to determine the MIME
- * type of the intent's data.
- *
- * @return The MIME type of this intent, or null if it is unknown or not
- * needed.
- */
- public String resolveTypeIfNeeded(ContentResolver resolver) {
- if (mComponent != null) {
- return mType;
- }
- return resolveType(resolver);
- }
-
- /**
- * Check if an category exists in the intent.
- *
- * @param category The category to check.
- *
- * @return boolean True if the intent contains the category, else false.
- *
- * @see #getCategories
- * @see #addCategory
- */
- public boolean hasCategory(String category) {
- return mCategories != null && mCategories.contains(category);
- }
-
- /**
- * Return the set of all categories in the intent. If there are no categories,
- * returns NULL.
- *
- * @return Set The set of categories you can examine. Do not modify!
- *
- * @see #hasCategory
- * @see #addCategory
- */
- public Set<String> getCategories() {
- return mCategories;
- }
-
- /**
- * Sets the ClassLoader that will be used when unmarshalling
- * any Parcelable values from the extras of this Intent.
- *
- * @param loader a ClassLoader, or null to use the default loader
- * at the time of unmarshalling.
- */
- public void setExtrasClassLoader(ClassLoader loader) {
- if (mExtras != null) {
- mExtras.setClassLoader(loader);
- }
- }
-
- /**
- * Returns true if an extra value is associated with the given name.
- * @param name the extra's name
- * @return true if the given extra is present.
- */
- public boolean hasExtra(String name) {
- return mExtras != null && mExtras.containsKey(name);
- }
-
- /**
- * Returns true if the Intent's extras contain a parcelled file descriptor.
- * @return true if the Intent contains a parcelled file descriptor.
- */
- public boolean hasFileDescriptors() {
- return mExtras != null && mExtras.hasFileDescriptors();
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if none was found.
- *
- * @deprecated
- * @hide
- */
- @Deprecated
- public Object getExtra(String name) {
- return getExtra(name, null);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- * @param defaultValue the value to be returned if no value of the desired
- * type is stored with the given name.
- *
- * @return the value of an item that previously added with putExtra()
- * or the default value if none was found.
- *
- * @see #putExtra(String, boolean)
- */
- public boolean getBooleanExtra(String name, boolean defaultValue) {
- return mExtras == null ? defaultValue :
- mExtras.getBoolean(name, defaultValue);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- * @param defaultValue the value to be returned if no value of the desired
- * type is stored with the given name.
- *
- * @return the value of an item that previously added with putExtra()
- * or the default value if none was found.
- *
- * @see #putExtra(String, byte)
- */
- public byte getByteExtra(String name, byte defaultValue) {
- return mExtras == null ? defaultValue :
- mExtras.getByte(name, defaultValue);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- * @param defaultValue the value to be returned if no value of the desired
- * type is stored with the given name.
- *
- * @return the value of an item that previously added with putExtra()
- * or the default value if none was found.
- *
- * @see #putExtra(String, short)
- */
- public short getShortExtra(String name, short defaultValue) {
- return mExtras == null ? defaultValue :
- mExtras.getShort(name, defaultValue);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- * @param defaultValue the value to be returned if no value of the desired
- * type is stored with the given name.
- *
- * @return the value of an item that previously added with putExtra()
- * or the default value if none was found.
- *
- * @see #putExtra(String, char)
- */
- public char getCharExtra(String name, char defaultValue) {
- return mExtras == null ? defaultValue :
- mExtras.getChar(name, defaultValue);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- * @param defaultValue the value to be returned if no value of the desired
- * type is stored with the given name.
- *
- * @return the value of an item that previously added with putExtra()
- * or the default value if none was found.
- *
- * @see #putExtra(String, int)
- */
- public int getIntExtra(String name, int defaultValue) {
- return mExtras == null ? defaultValue :
- mExtras.getInt(name, defaultValue);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- * @param defaultValue the value to be returned if no value of the desired
- * type is stored with the given name.
- *
- * @return the value of an item that previously added with putExtra()
- * or the default value if none was found.
- *
- * @see #putExtra(String, long)
- */
- public long getLongExtra(String name, long defaultValue) {
- return mExtras == null ? defaultValue :
- mExtras.getLong(name, defaultValue);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- * @param defaultValue the value to be returned if no value of the desired
- * type is stored with the given name.
- *
- * @return the value of an item that previously added with putExtra(),
- * or the default value if no such item is present
- *
- * @see #putExtra(String, float)
- */
- public float getFloatExtra(String name, float defaultValue) {
- return mExtras == null ? defaultValue :
- mExtras.getFloat(name, defaultValue);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- * @param defaultValue the value to be returned if no value of the desired
- * type is stored with the given name.
- *
- * @return the value of an item that previously added with putExtra()
- * or the default value if none was found.
- *
- * @see #putExtra(String, double)
- */
- public double getDoubleExtra(String name, double defaultValue) {
- return mExtras == null ? defaultValue :
- mExtras.getDouble(name, defaultValue);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no String value was found.
- *
- * @see #putExtra(String, String)
- */
- public String getStringExtra(String name) {
- return mExtras == null ? null : mExtras.getString(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no CharSequence value was found.
- *
- * @see #putExtra(String, CharSequence)
- */
- public CharSequence getCharSequenceExtra(String name) {
- return mExtras == null ? null : mExtras.getCharSequence(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no Parcelable value was found.
- *
- * @see #putExtra(String, Parcelable)
- */
- public <T extends Parcelable> T getParcelableExtra(String name) {
- return mExtras == null ? null : mExtras.<T>getParcelable(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no Parcelable[] value was found.
- *
- * @see #putExtra(String, Parcelable[])
- */
- public Parcelable[] getParcelableArrayExtra(String name) {
- return mExtras == null ? null : mExtras.getParcelableArray(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no ArrayList<Parcelable> value was found.
- *
- * @see #putParcelableArrayListExtra(String, ArrayList)
- */
- public <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra(String name) {
- return mExtras == null ? null : mExtras.<T>getParcelableArrayList(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no Serializable value was found.
- *
- * @see #putExtra(String, Serializable)
- */
- public Serializable getSerializableExtra(String name) {
- return mExtras == null ? null : mExtras.getSerializable(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no ArrayList<Integer> value was found.
- *
- * @see #putIntegerArrayListExtra(String, ArrayList)
- */
- public ArrayList<Integer> getIntegerArrayListExtra(String name) {
- return mExtras == null ? null : mExtras.getIntegerArrayList(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no ArrayList<String> value was found.
- *
- * @see #putStringArrayListExtra(String, ArrayList)
- */
- public ArrayList<String> getStringArrayListExtra(String name) {
- return mExtras == null ? null : mExtras.getStringArrayList(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no boolean array value was found.
- *
- * @see #putExtra(String, boolean[])
- */
- public boolean[] getBooleanArrayExtra(String name) {
- return mExtras == null ? null : mExtras.getBooleanArray(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no byte array value was found.
- *
- * @see #putExtra(String, byte[])
- */
- public byte[] getByteArrayExtra(String name) {
- return mExtras == null ? null : mExtras.getByteArray(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no short array value was found.
- *
- * @see #putExtra(String, short[])
- */
- public short[] getShortArrayExtra(String name) {
- return mExtras == null ? null : mExtras.getShortArray(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no char array value was found.
- *
- * @see #putExtra(String, char[])
- */
- public char[] getCharArrayExtra(String name) {
- return mExtras == null ? null : mExtras.getCharArray(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no int array value was found.
- *
- * @see #putExtra(String, int[])
- */
- public int[] getIntArrayExtra(String name) {
- return mExtras == null ? null : mExtras.getIntArray(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no long array value was found.
- *
- * @see #putExtra(String, long[])
- */
- public long[] getLongArrayExtra(String name) {
- return mExtras == null ? null : mExtras.getLongArray(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no float array value was found.
- *
- * @see #putExtra(String, float[])
- */
- public float[] getFloatArrayExtra(String name) {
- return mExtras == null ? null : mExtras.getFloatArray(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no double array value was found.
- *
- * @see #putExtra(String, double[])
- */
- public double[] getDoubleArrayExtra(String name) {
- return mExtras == null ? null : mExtras.getDoubleArray(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no String array value was found.
- *
- * @see #putExtra(String, String[])
- */
- public String[] getStringArrayExtra(String name) {
- return mExtras == null ? null : mExtras.getStringArray(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no Bundle value was found.
- *
- * @see #putExtra(String, Bundle)
- */
- public Bundle getBundleExtra(String name) {
- return mExtras == null ? null : mExtras.getBundle(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- *
- * @return the value of an item that previously added with putExtra()
- * or null if no IBinder value was found.
- *
- * @see #putExtra(String, IBinder)
- *
- * @deprecated
- * @hide
- */
- @Deprecated
- public IBinder getIBinderExtra(String name) {
- return mExtras == null ? null : mExtras.getIBinder(name);
- }
-
- /**
- * Retrieve extended data from the intent.
- *
- * @param name The name of the desired item.
- * @param defaultValue The default value to return in case no item is
- * associated with the key 'name'
- *
- * @return the value of an item that previously added with putExtra()
- * or defaultValue if none was found.
- *
- * @see #putExtra
- *
- * @deprecated
- * @hide
- */
- @Deprecated
- public Object getExtra(String name, Object defaultValue) {
- Object result = defaultValue;
- if (mExtras != null) {
- Object result2 = mExtras.get(name);
- if (result2 != null) {
- result = result2;
- }
- }
-
- return result;
- }
-
- /**
- * Retrieves a map of extended data from the intent.
- *
- * @return the map of all extras previously added with putExtra(),
- * or null if none have been added.
- */
- public Bundle getExtras() {
- return (mExtras != null)
- ? new Bundle(mExtras)
- : null;
- }
-
- /**
- * Retrieve any special flags associated with this intent. You will
- * normally just set them with {@link #setFlags} and let the system
- * take the appropriate action with them.
- *
- * @return int The currently set flags.
- *
- * @see #setFlags
- */
- public int getFlags() {
- return mFlags;
- }
-
- /**
- * Retrieve the concrete component associated with the intent. When receiving
- * an intent, this is the component that was found to best handle it (that is,
- * yourself) and will always be non-null; in all other cases it will be
- * null unless explicitly set.
- *
- * @return The name of the application component to handle the intent.
- *
- * @see #resolveActivity
- * @see #setComponent
- */
- public ComponentName getComponent() {
- return mComponent;
- }
-
- /**
- * Return the Activity component that should be used to handle this intent.
- * The appropriate component is determined based on the information in the
- * intent, evaluated as follows:
- *
- * <p>If {@link #getComponent} returns an explicit class, that is returned
- * without any further consideration.
- *
- * <p>The activity must handle the {@link Intent#CATEGORY_DEFAULT} Intent
- * category to be considered.
- *
- * <p>If {@link #getAction} is non-NULL, the activity must handle this
- * action.
- *
- * <p>If {@link #resolveType} returns non-NULL, the activity must handle
- * this type.
- *
- * <p>If {@link #addCategory} has added any categories, the activity must
- * handle ALL of the categories specified.
- *
- * <p>If there are no activities that satisfy all of these conditions, a
- * null string is returned.
- *
- * <p>If multiple activities are found to satisfy the intent, the one with
- * the highest priority will be used. If there are multiple activities
- * with the same priority, the system will either pick the best activity
- * based on user preference, or resolve to a system class that will allow
- * the user to pick an activity and forward from there.
- *
- * <p>This method is implemented simply by calling
- * {@link PackageManager#resolveActivity} with the "defaultOnly" parameter
- * true.</p>
- * <p> This API is called for you as part of starting an activity from an
- * intent. You do not normally need to call it yourself.</p>
- *
- * @param pm The package manager with which to resolve the Intent.
- *
- * @return Name of the component implementing an activity that can
- * display the intent.
- *
- * @see #setComponent
- * @see #getComponent
- * @see #resolveActivityInfo
- */
- public ComponentName resolveActivity(PackageManager pm) {
- if (mComponent != null) {
- return mComponent;
- }
-
- ResolveInfo info = pm.resolveActivity(
- this, PackageManager.MATCH_DEFAULT_ONLY);
- if (info != null) {
- return new ComponentName(
- info.activityInfo.applicationInfo.packageName,
- info.activityInfo.name);
- }
-
- return null;
- }
-
- /**
- * Resolve the Intent into an {@link ActivityInfo}
- * describing the activity that should execute the intent. Resolution
- * follows the same rules as described for {@link #resolveActivity}, but
- * you get back the completely information about the resolved activity
- * instead of just its class name.
- *
- * @param pm The package manager with which to resolve the Intent.
- * @param flags Addition information to retrieve as per
- * {@link PackageManager#getActivityInfo(ComponentName, int)
- * PackageManager.getActivityInfo()}.
- *
- * @return PackageManager.ActivityInfo
- *
- * @see #resolveActivity
- */
- public ActivityInfo resolveActivityInfo(PackageManager pm, int flags) {
- ActivityInfo ai = null;
- if (mComponent != null) {
- try {
- ai = pm.getActivityInfo(mComponent, flags);
- } catch (PackageManager.NameNotFoundException e) {
- // ignore
- }
- } else {
- ResolveInfo info = pm.resolveActivity(
- this, PackageManager.MATCH_DEFAULT_ONLY);
- if (info != null) {
- ai = info.activityInfo;
- }
- }
-
- return ai;
- }
-
- /**
- * Set the general action to be performed.
- *
- * @param action An action name, such as ACTION_VIEW. Application-specific
- * actions should be prefixed with the vendor's package name.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #getAction
- */
- public Intent setAction(String action) {
- mAction = action;
- return this;
- }
-
- /**
- * Set the data this intent is operating on. This method automatically
- * clears any type that was previously set by {@link #setType}.
- *
- * @param data The URI of the data this intent is now targeting.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #getData
- * @see #setType
- * @see #setDataAndType
- */
- public Intent setData(Uri data) {
- mData = data;
- mType = null;
- return this;
- }
-
- /**
- * Set an explicit MIME data type. This is used to create intents that
- * only specify a type and not data, for example to indicate the type of
- * data to return. This method automatically clears any data that was
- * previously set by {@link #setData}.
- *
- * @param type The MIME type of the data being handled by this intent.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #getType
- * @see #setData
- * @see #setDataAndType
- */
- public Intent setType(String type) {
- mData = null;
- mType = type;
- return this;
- }
-
- /**
- * (Usually optional) Set the data for the intent along with an explicit
- * MIME data type. This method should very rarely be used -- it allows you
- * to override the MIME type that would ordinarily be inferred from the
- * data with your own type given here.
- *
- * @param data The URI of the data this intent is now targeting.
- * @param type The MIME type of the data being handled by this intent.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #setData
- * @see #setType
- */
- public Intent setDataAndType(Uri data, String type) {
- mData = data;
- mType = type;
- return this;
- }
-
- /**
- * Add a new category to the intent. Categories provide additional detail
- * about the action the intent is perform. When resolving an intent, only
- * activities that provide <em>all</em> of the requested categories will be
- * used.
- *
- * @param category The desired category. This can be either one of the
- * predefined Intent categories, or a custom category in your own
- * namespace.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #hasCategory
- * @see #removeCategory
- */
- public Intent addCategory(String category) {
- if (mCategories == null) {
- mCategories = new HashSet<String>();
- }
- mCategories.add(category);
- return this;
- }
-
- /**
- * Remove an category from an intent.
- *
- * @param category The category to remove.
- *
- * @see #addCategory
- */
- public void removeCategory(String category) {
- if (mCategories != null) {
- mCategories.remove(category);
- if (mCategories.size() == 0) {
- mCategories = null;
- }
- }
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The boolean data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getBooleanExtra(String, boolean)
- */
- public Intent putExtra(String name, boolean value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putBoolean(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The byte data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getByteExtra(String, byte)
- */
- public Intent putExtra(String name, byte value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putByte(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The char data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getCharExtra(String, char)
- */
- public Intent putExtra(String name, char value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putChar(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The short data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getShortExtra(String, short)
- */
- public Intent putExtra(String name, short value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putShort(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The integer data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getIntExtra(String, int)
- */
- public Intent putExtra(String name, int value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putInt(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The long data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getLongExtra(String, long)
- */
- public Intent putExtra(String name, long value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putLong(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The float data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getFloatExtra(String, float)
- */
- public Intent putExtra(String name, float value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putFloat(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The double data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getDoubleExtra(String, double)
- */
- public Intent putExtra(String name, double value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putDouble(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The String data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getStringExtra(String)
- */
- public Intent putExtra(String name, String value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putString(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The CharSequence data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getCharSequenceExtra(String)
- */
- public Intent putExtra(String name, CharSequence value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putCharSequence(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The Parcelable data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getParcelableExtra(String)
- */
- public Intent putExtra(String name, Parcelable value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putParcelable(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The Parcelable[] data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getParcelableArrayExtra(String)
- */
- public Intent putExtra(String name, Parcelable[] value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putParcelableArray(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The ArrayList<Parcelable> data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getParcelableArrayListExtra(String)
- */
- public Intent putParcelableArrayListExtra(String name, ArrayList<? extends Parcelable> value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putParcelableArrayList(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The ArrayList<Integer> data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getIntegerArrayListExtra(String)
- */
- public Intent putIntegerArrayListExtra(String name, ArrayList<Integer> value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putIntegerArrayList(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The ArrayList<String> data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getStringArrayListExtra(String)
- */
- public Intent putStringArrayListExtra(String name, ArrayList<String> value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putStringArrayList(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The Serializable data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getSerializableExtra(String)
- */
- public Intent putExtra(String name, Serializable value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putSerializable(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The boolean array data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getBooleanArrayExtra(String)
- */
- public Intent putExtra(String name, boolean[] value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putBooleanArray(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The byte array data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getByteArrayExtra(String)
- */
- public Intent putExtra(String name, byte[] value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putByteArray(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The short array data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getShortArrayExtra(String)
- */
- public Intent putExtra(String name, short[] value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putShortArray(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The char array data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getCharArrayExtra(String)
- */
- public Intent putExtra(String name, char[] value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putCharArray(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The int array data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getIntArrayExtra(String)
- */
- public Intent putExtra(String name, int[] value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putIntArray(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The byte array data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getLongArrayExtra(String)
- */
- public Intent putExtra(String name, long[] value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putLongArray(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The float array data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getFloatArrayExtra(String)
- */
- public Intent putExtra(String name, float[] value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putFloatArray(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The double array data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getDoubleArrayExtra(String)
- */
- public Intent putExtra(String name, double[] value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putDoubleArray(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The String array data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getStringArrayExtra(String)
- */
- public Intent putExtra(String name, String[] value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putStringArray(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The Bundle data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getBundleExtra(String)
- */
- public Intent putExtra(String name, Bundle value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putBundle(name, value);
- return this;
- }
-
- /**
- * Add extended data to the intent. The name must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param name The name of the extra data, with package prefix.
- * @param value The IBinder data value.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #putExtras
- * @see #removeExtra
- * @see #getIBinderExtra(String)
- *
- * @deprecated
- * @hide
- */
- @Deprecated
- public Intent putExtra(String name, IBinder value) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putIBinder(name, value);
- return this;
- }
-
- /**
- * Copy all extras in 'src' in to this intent.
- *
- * @param src Contains the extras to copy.
- *
- * @see #putExtra
- */
- public Intent putExtras(Intent src) {
- if (src.mExtras != null) {
- if (mExtras == null) {
- mExtras = new Bundle(src.mExtras);
- } else {
- mExtras.putAll(src.mExtras);
- }
- }
- return this;
- }
-
- /**
- * Add a set of extended data to the intent. The keys must include a package
- * prefix, for example the app com.android.contacts would use names
- * like "com.android.contacts.ShowAll".
- *
- * @param extras The Bundle of extras to add to this intent.
- *
- * @see #putExtra
- * @see #removeExtra
- */
- public Intent putExtras(Bundle extras) {
- if (mExtras == null) {
- mExtras = new Bundle();
- }
- mExtras.putAll(extras);
- return this;
- }
-
- /**
- * Completely replace the extras in the Intent with the extras in the
- * given Intent.
- *
- * @param src The exact extras contained in this Intent are copied
- * into the target intent, replacing any that were previously there.
- */
- public Intent replaceExtras(Intent src) {
- mExtras = src.mExtras != null ? new Bundle(src.mExtras) : null;
- return this;
- }
-
- /**
- * Completely replace the extras in the Intent with the given Bundle of
- * extras.
- *
- * @param extras The new set of extras in the Intent, or null to erase
- * all extras.
- */
- public Intent replaceExtras(Bundle extras) {
- mExtras = extras != null ? new Bundle(extras) : null;
- return this;
- }
-
- /**
- * Remove extended data from the intent.
- *
- * @see #putExtra
- */
- public void removeExtra(String name) {
- if (mExtras != null) {
- mExtras.remove(name);
- if (mExtras.size() == 0) {
- mExtras = null;
- }
- }
- }
-
- /**
- * Set special flags controlling how this intent is handled. Most values
- * here depend on the type of component being executed by the Intent,
- * specifically the FLAG_ACTIVITY_* flags are all for use with
- * {@link Context#startActivity Context.startActivity()} and the
- * FLAG_RECEIVER_* flags are all for use with
- * {@link Context#sendBroadcast(Intent) Context.sendBroadcast()}.
- *
- * <p>See the <a href="{@docRoot}guide/topics/fundamentals.html#acttask">Application Fundamentals:
- * Activities and Tasks</a> documentation for important information on how some of these options impact
- * the behavior of your application.
- *
- * @param flags The desired flags.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #getFlags
- * @see #addFlags
- *
- * @see #FLAG_GRANT_READ_URI_PERMISSION
- * @see #FLAG_GRANT_WRITE_URI_PERMISSION
- * @see #FLAG_DEBUG_LOG_RESOLUTION
- * @see #FLAG_FROM_BACKGROUND
- * @see #FLAG_ACTIVITY_BROUGHT_TO_FRONT
- * @see #FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
- * @see #FLAG_ACTIVITY_CLEAR_TOP
- * @see #FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- * @see #FLAG_ACTIVITY_FORWARD_RESULT
- * @see #FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
- * @see #FLAG_ACTIVITY_MULTIPLE_TASK
- * @see #FLAG_ACTIVITY_NEW_TASK
- * @see #FLAG_ACTIVITY_NO_HISTORY
- * @see #FLAG_ACTIVITY_NO_USER_ACTION
- * @see #FLAG_ACTIVITY_PREVIOUS_IS_TOP
- * @see #FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
- * @see #FLAG_ACTIVITY_SINGLE_TOP
- * @see #FLAG_RECEIVER_REGISTERED_ONLY
- */
- public Intent setFlags(int flags) {
- mFlags = flags;
- return this;
- }
-
- /**
- * Add additional flags to the intent (or with existing flags
- * value).
- *
- * @param flags The new flags to set.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #setFlags
- */
- public Intent addFlags(int flags) {
- mFlags |= flags;
- return this;
- }
-
- /**
- * (Usually optional) Explicitly set the component to handle the intent.
- * If left with the default value of null, the system will determine the
- * appropriate class to use based on the other fields (action, data,
- * type, categories) in the Intent. If this class is defined, the
- * specified class will always be used regardless of the other fields. You
- * should only set this value when you know you absolutely want a specific
- * class to be used; otherwise it is better to let the system find the
- * appropriate class so that you will respect the installed applications
- * and user preferences.
- *
- * @param component The name of the application component to handle the
- * intent, or null to let the system find one for you.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #setClass
- * @see #setClassName(Context, String)
- * @see #setClassName(String, String)
- * @see #getComponent
- * @see #resolveActivity
- */
- public Intent setComponent(ComponentName component) {
- mComponent = component;
- return this;
- }
-
- /**
- * Convenience for calling {@link #setComponent} with an
- * explicit class name.
- *
- * @param packageContext A Context of the application package implementing
- * this class.
- * @param className The name of a class inside of the application package
- * that will be used as the component for this Intent.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #setComponent
- * @see #setClass
- */
- public Intent setClassName(Context packageContext, String className) {
- mComponent = new ComponentName(packageContext, className);
- return this;
- }
-
- /**
- * Convenience for calling {@link #setComponent} with an
- * explicit application package name and class name.
- *
- * @param packageName The name of the package implementing the desired
- * component.
- * @param className The name of a class inside of the application package
- * that will be used as the component for this Intent.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #setComponent
- * @see #setClass
- */
- public Intent setClassName(String packageName, String className) {
- mComponent = new ComponentName(packageName, className);
- return this;
- }
-
- /**
- * Convenience for calling {@link #setComponent(ComponentName)} with the
- * name returned by a {@link Class} object.
- *
- * @param packageContext A Context of the application package implementing
- * this class.
- * @param cls The class name to set, equivalent to
- * <code>setClassName(context, cls.getName())</code>.
- *
- * @return Returns the same Intent object, for chaining multiple calls
- * into a single statement.
- *
- * @see #setComponent
- */
- public Intent setClass(Context packageContext, Class<?> cls) {
- mComponent = new ComponentName(packageContext, cls);
- return this;
- }
-
- /**
- * Use with {@link #fillIn} to allow the current action value to be
- * overwritten, even if it is already set.
- */
- public static final int FILL_IN_ACTION = 1<<0;
-
- /**
- * Use with {@link #fillIn} to allow the current data or type value
- * overwritten, even if it is already set.
- */
- public static final int FILL_IN_DATA = 1<<1;
-
- /**
- * Use with {@link #fillIn} to allow the current categories to be
- * overwritten, even if they are already set.
- */
- public static final int FILL_IN_CATEGORIES = 1<<2;
-
- /**
- * Use with {@link #fillIn} to allow the current component value to be
- * overwritten, even if it is already set.
- */
- public static final int FILL_IN_COMPONENT = 1<<3;
-
- /**
- * Copy the contents of <var>other</var> in to this object, but only
- * where fields are not defined by this object. For purposes of a field
- * being defined, the following pieces of data in the Intent are
- * considered to be separate fields:
- *
- * <ul>
- * <li> action, as set by {@link #setAction}.
- * <li> data URI and MIME type, as set by {@link #setData(Uri)},
- * {@link #setType(String)}, or {@link #setDataAndType(Uri, String)}.
- * <li> categories, as set by {@link #addCategory}.
- * <li> component, as set by {@link #setComponent(ComponentName)} or
- * related methods.
- * <li> each top-level name in the associated extras.
- * </ul>
- *
- * <p>In addition, you can use the {@link #FILL_IN_ACTION},
- * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, and
- * {@link #FILL_IN_COMPONENT} to override the restriction where the
- * corresponding field will not be replaced if it is already set.
- *
- * <p>For example, consider Intent A with {data="foo", categories="bar"}
- * and Intent B with {action="gotit", data-type="some/thing",
- * categories="one","two"}.
- *
- * <p>Calling A.fillIn(B, Intent.FILL_IN_DATA) will result in A now
- * containing: {action="gotit", data-type="some/thing",
- * categories="bar"}.
- *
- * @param other Another Intent whose values are to be used to fill in
- * the current one.
- * @param flags Options to control which fields can be filled in.
- *
- * @return Returns a bit mask of {@link #FILL_IN_ACTION},
- * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, and
- * {@link #FILL_IN_COMPONENT} indicating which fields were changed.
- */
- public int fillIn(Intent other, int flags) {
- int changes = 0;
- if ((mAction == null && other.mAction == null)
- || (flags&FILL_IN_ACTION) != 0) {
- mAction = other.mAction;
- changes |= FILL_IN_ACTION;
- }
- if ((mData == null && mType == null &&
- (other.mData != null || other.mType != null))
- || (flags&FILL_IN_DATA) != 0) {
- mData = other.mData;
- mType = other.mType;
- changes |= FILL_IN_DATA;
- }
- if ((mCategories == null && other.mCategories == null)
- || (flags&FILL_IN_CATEGORIES) != 0) {
- if (other.mCategories != null) {
- mCategories = new HashSet<String>(other.mCategories);
- }
- changes |= FILL_IN_CATEGORIES;
- }
- if ((mComponent == null && other.mComponent == null)
- || (flags&FILL_IN_COMPONENT) != 0) {
- mComponent = other.mComponent;
- changes |= FILL_IN_COMPONENT;
- }
- mFlags |= other.mFlags;
- if (mExtras == null) {
- if (other.mExtras != null) {
- mExtras = new Bundle(other.mExtras);
- }
- } else if (other.mExtras != null) {
- try {
- Bundle newb = new Bundle(other.mExtras);
- newb.putAll(mExtras);
- mExtras = newb;
- } catch (RuntimeException e) {
- // Modifying the extras can cause us to unparcel the contents
- // of the bundle, and if we do this in the system process that
- // may fail. We really should handle this (i.e., the Bundle
- // impl shouldn't be on top of a plain map), but for now just
- // ignore it and keep the original contents. :(
- Log.w("Intent", "Failure filling in extras", e);
- }
- }
- return changes;
- }
-
- /**
- * Wrapper class holding an Intent and implementing comparisons on it for
- * the purpose of filtering. The class implements its
- * {@link #equals equals()} and {@link #hashCode hashCode()} methods as
- * simple calls to {@link Intent#filterEquals(Intent)} filterEquals()} and
- * {@link android.content.Intent#filterHashCode()} filterHashCode()}
- * on the wrapped Intent.
- */
- public static final class FilterComparison {
- private final Intent mIntent;
- private final int mHashCode;
-
- public FilterComparison(Intent intent) {
- mIntent = intent;
- mHashCode = intent.filterHashCode();
- }
-
- /**
- * Return the Intent that this FilterComparison represents.
- * @return Returns the Intent held by the FilterComparison. Do
- * not modify!
- */
- public Intent getIntent() {
- return mIntent;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof FilterComparison) {
- Intent other = ((FilterComparison)obj).mIntent;
- return mIntent.filterEquals(other);
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return mHashCode;
- }
- }
-
- /**
- * Determine if two intents are the same for the purposes of intent
- * resolution (filtering). That is, if their action, data, type,
- * class, and categories are the same. This does <em>not</em> compare
- * any extra data included in the intents.
- *
- * @param other The other Intent to compare against.
- *
- * @return Returns true if action, data, type, class, and categories
- * are the same.
- */
- public boolean filterEquals(Intent other) {
- if (other == null) {
- return false;
- }
- if (mAction != other.mAction) {
- if (mAction != null) {
- if (!mAction.equals(other.mAction)) {
- return false;
- }
- } else {
- if (!other.mAction.equals(mAction)) {
- return false;
- }
- }
- }
- if (mData != other.mData) {
- if (mData != null) {
- if (!mData.equals(other.mData)) {
- return false;
- }
- } else {
- if (!other.mData.equals(mData)) {
- return false;
- }
- }
- }
- if (mType != other.mType) {
- if (mType != null) {
- if (!mType.equals(other.mType)) {
- return false;
- }
- } else {
- if (!other.mType.equals(mType)) {
- return false;
- }
- }
- }
- if (mComponent != other.mComponent) {
- if (mComponent != null) {
- if (!mComponent.equals(other.mComponent)) {
- return false;
- }
- } else {
- if (!other.mComponent.equals(mComponent)) {
- return false;
- }
- }
- }
- if (mCategories != other.mCategories) {
- if (mCategories != null) {
- if (!mCategories.equals(other.mCategories)) {
- return false;
- }
- } else {
- if (!other.mCategories.equals(mCategories)) {
- return false;
- }
- }
- }
-
- return true;
- }
-
- /**
- * Generate hash code that matches semantics of filterEquals().
- *
- * @return Returns the hash value of the action, data, type, class, and
- * categories.
- *
- * @see #filterEquals
- */
- public int filterHashCode() {
- int code = 0;
- if (mAction != null) {
- code += mAction.hashCode();
- }
- if (mData != null) {
- code += mData.hashCode();
- }
- if (mType != null) {
- code += mType.hashCode();
- }
- if (mComponent != null) {
- code += mComponent.hashCode();
- }
- if (mCategories != null) {
- code += mCategories.hashCode();
- }
- return code;
- }
-
- @Override
- public String toString() {
- StringBuilder b = new StringBuilder();
-
- b.append("Intent {");
- if (mAction != null) b.append(" action=").append(mAction);
- if (mCategories != null) {
- b.append(" categories={");
- Iterator<String> i = mCategories.iterator();
- boolean didone = false;
- while (i.hasNext()) {
- if (didone) b.append(",");
- didone = true;
- b.append(i.next());
- }
- b.append("}");
- }
- if (mData != null) b.append(" data=").append(mData);
- if (mType != null) b.append(" type=").append(mType);
- if (mFlags != 0) b.append(" flags=0x").append(Integer.toHexString(mFlags));
- if (mComponent != null) b.append(" comp=").append(mComponent.toShortString());
- if (mExtras != null) b.append(" (has extras)");
- b.append(" }");
-
- return b.toString();
- }
-
- public String toURI() {
- StringBuilder uri = new StringBuilder(mData != null ? mData.toString() : "");
-
- uri.append("#Intent;");
-
- if (mAction != null) {
- uri.append("action=").append(mAction).append(';');
- }
- if (mCategories != null) {
- for (String category : mCategories) {
- uri.append("category=").append(category).append(';');
- }
- }
- if (mType != null) {
- uri.append("type=").append(mType).append(';');
- }
- if (mFlags != 0) {
- uri.append("launchFlags=0x").append(Integer.toHexString(mFlags)).append(';');
- }
- if (mComponent != null) {
- uri.append("component=").append(mComponent.flattenToShortString()).append(';');
- }
- if (mExtras != null) {
- for (String key : mExtras.keySet()) {
- final Object value = mExtras.get(key);
- char entryType =
- value instanceof String ? 'S' :
- value instanceof Boolean ? 'B' :
- value instanceof Byte ? 'b' :
- value instanceof Character ? 'c' :
- value instanceof Double ? 'd' :
- value instanceof Float ? 'f' :
- value instanceof Integer ? 'i' :
- value instanceof Long ? 'l' :
- value instanceof Short ? 's' :
- '\0';
-
- if (entryType != '\0') {
- uri.append(entryType);
- uri.append('.');
- uri.append(Uri.encode(key));
- uri.append('=');
- uri.append(Uri.encode(value.toString()));
- uri.append(';');
- }
- }
- }
-
- uri.append("end");
-
- return uri.toString();
- }
-
- public int describeContents() {
- return (mExtras != null) ? mExtras.describeContents() : 0;
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(mAction);
- Uri.writeToParcel(out, mData);
- out.writeString(mType);
- out.writeInt(mFlags);
- ComponentName.writeToParcel(mComponent, out);
-
- if (mCategories != null) {
- out.writeInt(mCategories.size());
- for (String category : mCategories) {
- out.writeString(category);
- }
- } else {
- out.writeInt(0);
- }
-
- out.writeBundle(mExtras);
- }
-
- public static final Parcelable.Creator<Intent> CREATOR
- = new Parcelable.Creator<Intent>() {
- public Intent createFromParcel(Parcel in) {
- return new Intent(in);
- }
- public Intent[] newArray(int size) {
- return new Intent[size];
- }
- };
-
- private Intent(Parcel in) {
- readFromParcel(in);
- }
-
- public void readFromParcel(Parcel in) {
- mAction = in.readString();
- mData = Uri.CREATOR.createFromParcel(in);
- mType = in.readString();
- mFlags = in.readInt();
- mComponent = ComponentName.readFromParcel(in);
-
- int N = in.readInt();
- if (N > 0) {
- mCategories = new HashSet<String>();
- int i;
- for (i=0; i<N; i++) {
- mCategories.add(in.readString());
- }
- } else {
- mCategories = null;
- }
-
- mExtras = in.readBundle();
- }
-
- /**
- * Parses the "intent" element (and its children) from XML and instantiates
- * an Intent object. The given XML parser should be located at the tag
- * where parsing should start (often named "intent"), from which the
- * basic action, data, type, and package and class name will be
- * retrieved. The function will then parse in to any child elements,
- * looking for <category android:name="xxx"> tags to add categories and
- * <extra android:name="xxx" android:value="yyy"> to attach extra data
- * to the intent.
- *
- * @param resources The Resources to use when inflating resources.
- * @param parser The XML parser pointing at an "intent" tag.
- * @param attrs The AttributeSet interface for retrieving extended
- * attribute data at the current <var>parser</var> location.
- * @return An Intent object matching the XML data.
- * @throws XmlPullParserException If there was an XML parsing error.
- * @throws IOException If there was an I/O error.
- */
- public static Intent parseIntent(Resources resources, XmlPullParser parser, AttributeSet attrs)
- throws XmlPullParserException, IOException {
- Intent intent = new Intent();
-
- TypedArray sa = resources.obtainAttributes(attrs,
- com.android.internal.R.styleable.Intent);
-
- intent.setAction(sa.getString(com.android.internal.R.styleable.Intent_action));
-
- String data = sa.getString(com.android.internal.R.styleable.Intent_data);
- String mimeType = sa.getString(com.android.internal.R.styleable.Intent_mimeType);
- intent.setDataAndType(data != null ? Uri.parse(data) : null, mimeType);
-
- String packageName = sa.getString(com.android.internal.R.styleable.Intent_targetPackage);
- String className = sa.getString(com.android.internal.R.styleable.Intent_targetClass);
- if (packageName != null && className != null) {
- intent.setComponent(new ComponentName(packageName, className));
- }
-
- sa.recycle();
-
- int outerDepth = parser.getDepth();
- int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
-
- String nodeName = parser.getName();
- if (nodeName.equals("category")) {
- sa = resources.obtainAttributes(attrs,
- com.android.internal.R.styleable.IntentCategory);
- String cat = sa.getString(com.android.internal.R.styleable.IntentCategory_name);
- sa.recycle();
-
- if (cat != null) {
- intent.addCategory(cat);
- }
- XmlUtils.skipCurrentTag(parser);
-
- } else if (nodeName.equals("extra")) {
- if (intent.mExtras == null) {
- intent.mExtras = new Bundle();
- }
- resources.parseBundleExtra("extra", attrs, intent.mExtras);
- XmlUtils.skipCurrentTag(parser);
-
- } else {
- XmlUtils.skipCurrentTag(parser);
- }
- }
-
- return intent;
- }
-}
diff --git a/core/java/android/content/IntentFilter.aidl b/core/java/android/content/IntentFilter.aidl
deleted file mode 100644
index a9bcd5e..0000000
--- a/core/java/android/content/IntentFilter.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-parcelable IntentFilter;
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
deleted file mode 100644
index e81bc86..0000000
--- a/core/java/android/content/IntentFilter.java
+++ /dev/null
@@ -1,1408 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Set;
-
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.PatternMatcher;
-import android.util.AndroidException;
-import android.util.Config;
-import android.util.Log;
-import android.util.Printer;
-import com.android.internal.util.XmlUtils;
-
-/**
- * Structured description of Intent values to be matched. An IntentFilter can
- * match against actions, categories, and data (either via its type, scheme,
- * and/or path) in an Intent. It also includes a "priority" value which is
- * used to order multiple matching filters.
- *
- * <p>IntentFilter objects are often created in XML as part of a package's
- * {@link android.R.styleable#AndroidManifest AndroidManifest.xml} file,
- * using {@link android.R.styleable#AndroidManifestIntentFilter intent-filter}
- * tags.
- *
- * <p>There are three Intent characteristics you can filter on: the
- * <em>action</em>, <em>data</em>, and <em>categories</em>. For each of these
- * characteristics you can provide
- * multiple possible matching values (via {@link #addAction},
- * {@link #addDataType}, {@link #addDataScheme} {@link #addDataAuthority},
- * {@link #addDataPath}, and {@link #addCategory}, respectively).
- * For actions, the field
- * will not be tested if no values have been given (treating it as a wildcard);
- * if no data characteristics are specified, however, then the filter will
- * only match intents that contain no data.
- *
- * <p>The data characteristic is
- * itself divided into three attributes: type, scheme, authority, and path.
- * Any that are
- * specified must match the contents of the Intent. If you specify a scheme
- * but no type, only Intent that does not have a type (such as mailto:) will
- * match; a content: URI will never match because they always have a MIME type
- * that is supplied by their content provider. Specifying a type with no scheme
- * has somewhat special meaning: it will match either an Intent with no URI
- * field, or an Intent with a content: or file: URI. If you specify neither,
- * then only an Intent with no data or type will match. To specify an authority,
- * you must also specify one or more schemes that it is associated with.
- * To specify a path, you also must specify both one or more authorities and
- * one or more schemes it is associated with.
- *
- * <p>A match is based on the following rules. Note that
- * for an IntentFilter to match an Intent, three conditions must hold:
- * the <strong>action</strong> and <strong>category</strong> must match, and
- * the data (both the <strong>data type</strong> and
- * <strong>data scheme+authority+path</strong> if specified) must match.
- *
- * <p><strong>Action</strong> matches if any of the given values match the
- * Intent action, <em>or</em> if no actions were specified in the filter.
- *
- * <p><strong>Data Type</strong> matches if any of the given values match the
- * Intent type. The Intent
- * type is determined by calling {@link Intent#resolveType}. A wildcard can be
- * used for the MIME sub-type, in both the Intent and IntentFilter, so that the
- * type "audio/*" will match "audio/mpeg", "audio/aiff", "audio/*", etc.
- *
- * <p><strong>Data Scheme</strong> matches if any of the given values match the
- * Intent data's scheme.
- * The Intent scheme is determined by calling {@link Intent#getData}
- * and {@link android.net.Uri#getScheme} on that URI.
- *
- * <p><strong>Data Authority</strong> matches if any of the given values match
- * the Intent's data authority <em>and</em> one of the data scheme's in the filter
- * has matched the Intent, <em>or</em> no authories were supplied in the filter.
- * The Intent authority is determined by calling
- * {@link Intent#getData} and {@link android.net.Uri#getAuthority} on that URI.
- *
- * <p><strong>Data Path</strong> matches if any of the given values match the
- * Intent's data path <em>and</em> both a scheme and authority in the filter
- * has matched against the Intent, <em>or</em> no paths were supplied in the
- * filter. The Intent authority is determined by calling
- * {@link Intent#getData} and {@link android.net.Uri#getPath} on that URI.
- *
- * <p><strong>Categories</strong> match if <em>all</em> of the categories in
- * the Intent match categories given in the filter. Extra categories in the
- * filter that are not in the Intent will not cause the match to fail. Note
- * that unlike the action, an IntentFilter with no categories
- * will only match an Intent that does not have any categories.
- */
-public class IntentFilter implements Parcelable {
- private static final String SGLOB_STR = "sglob";
- private static final String PREFIX_STR = "prefix";
- private static final String LITERAL_STR = "literal";
- private static final String PATH_STR = "path";
- private static final String PORT_STR = "port";
- private static final String HOST_STR = "host";
- private static final String AUTH_STR = "auth";
- private static final String SCHEME_STR = "scheme";
- private static final String TYPE_STR = "type";
- private static final String CAT_STR = "cat";
- private static final String NAME_STR = "name";
- private static final String ACTION_STR = "action";
-
- /**
- * The filter {@link #setPriority} value at which system high-priority
- * receivers are placed; that is, receivers that should execute before
- * application code. Applications should never use filters with this or
- * higher priorities.
- *
- * @see #setPriority
- */
- public static final int SYSTEM_HIGH_PRIORITY = 1000;
-
- /**
- * The filter {@link #setPriority} value at which system low-priority
- * receivers are placed; that is, receivers that should execute after
- * application code. Applications should never use filters with this or
- * lower priorities.
- *
- * @see #setPriority
- */
- public static final int SYSTEM_LOW_PRIORITY = -1000;
-
- /**
- * The part of a match constant that describes the category of match
- * that occurred. May be either {@link #MATCH_CATEGORY_EMPTY},
- * {@link #MATCH_CATEGORY_SCHEME}, {@link #MATCH_CATEGORY_HOST},
- * {@link #MATCH_CATEGORY_PORT},
- * {@link #MATCH_CATEGORY_PATH}, or {@link #MATCH_CATEGORY_TYPE}. Higher
- * values indicate a better match.
- */
- public static final int MATCH_CATEGORY_MASK = 0xfff0000;
-
- /**
- * The part of a match constant that applies a quality adjustment to the
- * basic category of match. The value {@link #MATCH_ADJUSTMENT_NORMAL}
- * is no adjustment; higher numbers than that improve the quality, while
- * lower numbers reduce it.
- */
- public static final int MATCH_ADJUSTMENT_MASK = 0x000ffff;
-
- /**
- * Quality adjustment applied to the category of match that signifies
- * the default, base value; higher numbers improve the quality while
- * lower numbers reduce it.
- */
- public static final int MATCH_ADJUSTMENT_NORMAL = 0x8000;
-
- /**
- * The filter matched an intent that had no data specified.
- */
- public static final int MATCH_CATEGORY_EMPTY = 0x0100000;
- /**
- * The filter matched an intent with the same data URI scheme.
- */
- public static final int MATCH_CATEGORY_SCHEME = 0x0200000;
- /**
- * The filter matched an intent with the same data URI scheme and
- * authority host.
- */
- public static final int MATCH_CATEGORY_HOST = 0x0300000;
- /**
- * The filter matched an intent with the same data URI scheme and
- * authority host and port.
- */
- public static final int MATCH_CATEGORY_PORT = 0x0400000;
- /**
- * The filter matched an intent with the same data URI scheme,
- * authority, and path.
- */
- public static final int MATCH_CATEGORY_PATH = 0x0500000;
- /**
- * The filter matched an intent with the same data MIME type.
- */
- public static final int MATCH_CATEGORY_TYPE = 0x0600000;
-
- /**
- * The filter didn't match due to different MIME types.
- */
- public static final int NO_MATCH_TYPE = -1;
- /**
- * The filter didn't match due to different data URIs.
- */
- public static final int NO_MATCH_DATA = -2;
- /**
- * The filter didn't match due to different actions.
- */
- public static final int NO_MATCH_ACTION = -3;
- /**
- * The filter didn't match because it required one or more categories
- * that were not in the Intent.
- */
- public static final int NO_MATCH_CATEGORY = -4;
-
- private int mPriority;
- private final ArrayList<String> mActions;
- private ArrayList<String> mCategories = null;
- private ArrayList<String> mDataSchemes = null;
- private ArrayList<AuthorityEntry> mDataAuthorities = null;
- private ArrayList<PatternMatcher> mDataPaths = null;
- private ArrayList<String> mDataTypes = null;
- private boolean mHasPartialTypes = false;
-
- // These functions are the start of more optimized code for managing
- // the string sets... not yet implemented.
-
- private static int findStringInSet(String[] set, String string,
- int[] lengths, int lenPos) {
- if (set == null) return -1;
- final int N = lengths[lenPos];
- for (int i=0; i<N; i++) {
- if (set[i].equals(string)) return i;
- }
- return -1;
- }
-
- private static String[] addStringToSet(String[] set, String string,
- int[] lengths, int lenPos) {
- if (findStringInSet(set, string, lengths, lenPos) >= 0) return set;
- if (set == null) {
- set = new String[2];
- set[0] = string;
- lengths[lenPos] = 1;
- return set;
- }
- final int N = lengths[lenPos];
- if (N < set.length) {
- set[N] = string;
- lengths[lenPos] = N+1;
- return set;
- }
-
- String[] newSet = new String[(N*3)/2 + 2];
- System.arraycopy(set, 0, newSet, 0, N);
- set = newSet;
- set[N] = string;
- lengths[lenPos] = N+1;
- return set;
- }
-
- private static String[] removeStringFromSet(String[] set, String string,
- int[] lengths, int lenPos) {
- int pos = findStringInSet(set, string, lengths, lenPos);
- if (pos < 0) return set;
- final int N = lengths[lenPos];
- if (N > (set.length/4)) {
- int copyLen = N-(pos+1);
- if (copyLen > 0) {
- System.arraycopy(set, pos+1, set, pos, copyLen);
- }
- set[N-1] = null;
- lengths[lenPos] = N-1;
- return set;
- }
-
- String[] newSet = new String[set.length/3];
- if (pos > 0) System.arraycopy(set, 0, newSet, 0, pos);
- if ((pos+1) < N) System.arraycopy(set, pos+1, newSet, pos, N-(pos+1));
- return newSet;
- }
-
- /**
- * This exception is thrown when a given MIME type does not have a valid
- * syntax.
- */
- public static class MalformedMimeTypeException extends AndroidException {
- public MalformedMimeTypeException() {
- }
-
- public MalformedMimeTypeException(String name) {
- super(name);
- }
- };
-
- /**
- * Create a new IntentFilter instance with a specified action and MIME
- * type, where you know the MIME type is correctly formatted. This catches
- * the {@link MalformedMimeTypeException} exception that the constructor
- * can call and turns it into a runtime exception.
- *
- * @param action The action to match, i.e. Intent.ACTION_VIEW.
- * @param dataType The type to match, i.e. "vnd.android.cursor.dir/person".
- *
- * @return A new IntentFilter for the given action and type.
- *
- * @see #IntentFilter(String, String)
- */
- public static IntentFilter create(String action, String dataType) {
- try {
- return new IntentFilter(action, dataType);
- } catch (MalformedMimeTypeException e) {
- throw new RuntimeException("Bad MIME type", e);
- }
- }
-
- /**
- * New empty IntentFilter.
- */
- public IntentFilter() {
- mPriority = 0;
- mActions = new ArrayList<String>();
- }
-
- /**
- * New IntentFilter that matches a single action with no data. If
- * no data characteristics are subsequently specified, then the
- * filter will only match intents that contain no data.
- *
- * @param action The action to match, i.e. Intent.ACTION_MAIN.
- */
- public IntentFilter(String action) {
- mPriority = 0;
- mActions = new ArrayList<String>();
- addAction(action);
- }
-
- /**
- * New IntentFilter that matches a single action and data type.
- *
- * <p>Throws {@link MalformedMimeTypeException} if the given MIME type is
- * not syntactically correct.
- *
- * @param action The action to match, i.e. Intent.ACTION_VIEW.
- * @param dataType The type to match, i.e. "vnd.android.cursor.dir/person".
- *
- */
- public IntentFilter(String action, String dataType)
- throws MalformedMimeTypeException {
- mPriority = 0;
- mActions = new ArrayList<String>();
- addDataType(dataType);
- }
-
- /**
- * New IntentFilter containing a copy of an existing filter.
- *
- * @param o The original filter to copy.
- */
- public IntentFilter(IntentFilter o) {
- mPriority = o.mPriority;
- mActions = new ArrayList<String>(o.mActions);
- if (o.mCategories != null) {
- mCategories = new ArrayList<String>(o.mCategories);
- }
- if (o.mDataTypes != null) {
- mDataTypes = new ArrayList<String>(o.mDataTypes);
- }
- if (o.mDataSchemes != null) {
- mDataSchemes = new ArrayList<String>(o.mDataSchemes);
- }
- if (o.mDataAuthorities != null) {
- mDataAuthorities = new ArrayList<AuthorityEntry>(o.mDataAuthorities);
- }
- if (o.mDataPaths != null) {
- mDataPaths = new ArrayList<PatternMatcher>(o.mDataPaths);
- }
- mHasPartialTypes = o.mHasPartialTypes;
- }
-
- /**
- * Modify priority of this filter. The default priority is 0. Positive
- * values will be before the default, lower values will be after it.
- * Applications must use a value that is larger than
- * {@link #SYSTEM_LOW_PRIORITY} and smaller than
- * {@link #SYSTEM_HIGH_PRIORITY} .
- *
- * @param priority The new priority value.
- *
- * @see #getPriority
- * @see #SYSTEM_LOW_PRIORITY
- * @see #SYSTEM_HIGH_PRIORITY
- */
- public final void setPriority(int priority) {
- mPriority = priority;
- }
-
- /**
- * Return the priority of this filter.
- *
- * @return The priority of the filter.
- *
- * @see #setPriority
- */
- public final int getPriority() {
- return mPriority;
- }
-
- /**
- * Add a new Intent action to match against. If any actions are included
- * in the filter, then an Intent's action must be one of those values for
- * it to match. If no actions are included, the Intent action is ignored.
- *
- * @param action Name of the action to match, i.e. Intent.ACTION_VIEW.
- */
- public final void addAction(String action) {
- if (!mActions.contains(action)) {
- mActions.add(action.intern());
- }
- }
-
- /**
- * Return the number of actions in the filter.
- */
- public final int countActions() {
- return mActions.size();
- }
-
- /**
- * Return an action in the filter.
- */
- public final String getAction(int index) {
- return mActions.get(index);
- }
-
- /**
- * Is the given action included in the filter? Note that if the filter
- * does not include any actions, false will <em>always</em> be returned.
- *
- * @param action The action to look for.
- *
- * @return True if the action is explicitly mentioned in the filter.
- */
- public final boolean hasAction(String action) {
- return mActions.contains(action);
- }
-
- /**
- * Match this filter against an Intent's action. If the filter does not
- * specify any actions, the match will always fail.
- *
- * @param action The desired action to look for.
- *
- * @return True if the action is listed in the filter or the filter does
- * not specify any actions.
- */
- public final boolean matchAction(String action) {
- if (action == null || mActions == null || mActions.size() == 0) {
- return false;
- }
- return mActions.contains(action);
- }
-
- /**
- * Return an iterator over the filter's actions. If there are no actions,
- * returns null.
- */
- public final Iterator<String> actionsIterator() {
- return mActions != null ? mActions.iterator() : null;
- }
-
- /**
- * Add a new Intent data type to match against. If any types are
- * included in the filter, then an Intent's data must be <em>either</em>
- * one of these types <em>or</em> a matching scheme. If no data types
- * are included, then an Intent will only match if it specifies no data.
- *
- * <p>Throws {@link MalformedMimeTypeException} if the given MIME type is
- * not syntactically correct.
- *
- * @param type Name of the data type to match, i.e. "vnd.android.cursor.dir/person".
- *
- * @see #matchData
- */
- public final void addDataType(String type)
- throws MalformedMimeTypeException {
- final int slashpos = type.indexOf('/');
- final int typelen = type.length();
- if (slashpos > 0 && typelen >= slashpos+2) {
- if (mDataTypes == null) mDataTypes = new ArrayList<String>();
- if (typelen == slashpos+2 && type.charAt(slashpos+1) == '*') {
- String str = type.substring(0, slashpos);
- if (!mDataTypes.contains(str)) {
- mDataTypes.add(str.intern());
- }
- mHasPartialTypes = true;
- } else {
- if (!mDataTypes.contains(type)) {
- mDataTypes.add(type.intern());
- }
- }
- return;
- }
-
- throw new MalformedMimeTypeException(type);
- }
-
- /**
- * Is the given data type included in the filter? Note that if the filter
- * does not include any type, false will <em>always</em> be returned.
- *
- * @param type The data type to look for.
- *
- * @return True if the type is explicitly mentioned in the filter.
- */
- public final boolean hasDataType(String type) {
- return mDataTypes != null && findMimeType(type);
- }
-
- /**
- * Return the number of data types in the filter.
- */
- public final int countDataTypes() {
- return mDataTypes != null ? mDataTypes.size() : 0;
- }
-
- /**
- * Return a data type in the filter.
- */
- public final String getDataType(int index) {
- return mDataTypes.get(index);
- }
-
- /**
- * Return an iterator over the filter's data types.
- */
- public final Iterator<String> typesIterator() {
- return mDataTypes != null ? mDataTypes.iterator() : null;
- }
-
- /**
- * Add a new Intent data scheme to match against. If any schemes are
- * included in the filter, then an Intent's data must be <em>either</em>
- * one of these schemes <em>or</em> a matching data type. If no schemes
- * are included, then an Intent will match only if it includes no data.
- *
- * @param scheme Name of the scheme to match, i.e. "http".
- *
- * @see #matchData
- */
- public final void addDataScheme(String scheme) {
- if (mDataSchemes == null) mDataSchemes = new ArrayList<String>();
- if (!mDataSchemes.contains(scheme)) {
- mDataSchemes.add(scheme.intern());
- }
- }
-
- /**
- * Return the number of data schemes in the filter.
- */
- public final int countDataSchemes() {
- return mDataSchemes != null ? mDataSchemes.size() : 0;
- }
-
- /**
- * Return a data scheme in the filter.
- */
- public final String getDataScheme(int index) {
- return mDataSchemes.get(index);
- }
-
- /**
- * Is the given data scheme included in the filter? Note that if the
- * filter does not include any scheme, false will <em>always</em> be
- * returned.
- *
- * @param scheme The data scheme to look for.
- *
- * @return True if the scheme is explicitly mentioned in the filter.
- */
- public final boolean hasDataScheme(String scheme) {
- return mDataSchemes != null && mDataSchemes.contains(scheme);
- }
-
- /**
- * Return an iterator over the filter's data schemes.
- */
- public final Iterator<String> schemesIterator() {
- return mDataSchemes != null ? mDataSchemes.iterator() : null;
- }
-
- /**
- * This is an entry for a single authority in the Iterator returned by
- * {@link #authoritiesIterator()}.
- */
- public final static class AuthorityEntry {
- private final String mOrigHost;
- private final String mHost;
- private final boolean mWild;
- private final int mPort;
-
- public AuthorityEntry(String host, String port) {
- mOrigHost = host;
- mWild = host.length() > 0 && host.charAt(0) == '*';
- mHost = mWild ? host.substring(1).intern() : host;
- mPort = port != null ? Integer.parseInt(port) : -1;
- }
-
- AuthorityEntry(Parcel src) {
- mOrigHost = src.readString();
- mHost = src.readString();
- mWild = src.readInt() != 0;
- mPort = src.readInt();
- }
-
- void writeToParcel(Parcel dest) {
- dest.writeString(mOrigHost);
- dest.writeString(mHost);
- dest.writeInt(mWild ? 1 : 0);
- dest.writeInt(mPort);
- }
-
- public String getHost() {
- return mOrigHost;
- }
-
- public int getPort() {
- return mPort;
- }
-
- public int match(Uri data) {
- String host = data.getHost();
- if (host == null) {
- return NO_MATCH_DATA;
- }
- if (Config.LOGV) Log.v("IntentFilter",
- "Match host " + host + ": " + mHost);
- if (mWild) {
- if (host.length() < mHost.length()) {
- return NO_MATCH_DATA;
- }
- host = host.substring(host.length()-mHost.length());
- }
- if (host.compareToIgnoreCase(mHost) != 0) {
- return NO_MATCH_DATA;
- }
- if (mPort >= 0) {
- if (mPort != data.getPort()) {
- return NO_MATCH_DATA;
- }
- return MATCH_CATEGORY_PORT;
- }
- return MATCH_CATEGORY_HOST;
- }
- };
-
- /**
- * Add a new Intent data authority to match against. The filter must
- * include one or more schemes (via {@link #addDataScheme}) for the
- * authority to be considered. If any authorities are
- * included in the filter, then an Intent's data must match one of
- * them. If no authorities are included, then only the scheme must match.
- *
- * @param host The host part of the authority to match. May start with a
- * single '*' to wildcard the front of the host name.
- * @param port Optional port part of the authority to match. If null, any
- * port is allowed.
- *
- * @see #matchData
- * @see #addDataScheme
- */
- public final void addDataAuthority(String host, String port) {
- if (mDataAuthorities == null) mDataAuthorities =
- new ArrayList<AuthorityEntry>();
- if (port != null) port = port.intern();
- mDataAuthorities.add(new AuthorityEntry(host.intern(), port));
- }
-
- /**
- * Return the number of data authorities in the filter.
- */
- public final int countDataAuthorities() {
- return mDataAuthorities != null ? mDataAuthorities.size() : 0;
- }
-
- /**
- * Return a data authority in the filter.
- */
- public final AuthorityEntry getDataAuthority(int index) {
- return mDataAuthorities.get(index);
- }
-
- /**
- * Is the given data authority included in the filter? Note that if the
- * filter does not include any authorities, false will <em>always</em> be
- * returned.
- *
- * @param data The data whose authority is being looked for.
- *
- * @return Returns true if the data string matches an authority listed in the
- * filter.
- */
- public final boolean hasDataAuthority(Uri data) {
- return matchDataAuthority(data) >= 0;
- }
-
- /**
- * Return an iterator over the filter's data authorities.
- */
- public final Iterator<AuthorityEntry> authoritiesIterator() {
- return mDataAuthorities != null ? mDataAuthorities.iterator() : null;
- }
-
- /**
- * Add a new Intent data oath to match against. The filter must
- * include one or more schemes (via {@link #addDataScheme}) <em>and</em>
- * one or more authorities (via {@link #addDataAuthority}) for the
- * path to be considered. If any paths are
- * included in the filter, then an Intent's data must match one of
- * them. If no paths are included, then only the scheme/authority must
- * match.
- *
- * <p>The path given here can either be a literal that must directly
- * match or match against a prefix, or it can be a simple globbing pattern.
- * If the latter, you can use '*' anywhere in the pattern to match zero
- * or more instances of the previous character, '.' as a wildcard to match
- * any character, and '\' to escape the next character.
- *
- * @param path Either a raw string that must exactly match the file
- * path, or a simple pattern, depending on <var>type</var>.
- * @param type Determines how <var>path</var> will be compared to
- * determine a match: either {@link PatternMatcher#PATTERN_LITERAL},
- * {@link PatternMatcher#PATTERN_PREFIX}, or
- * {@link PatternMatcher#PATTERN_SIMPLE_GLOB}.
- *
- * @see #matchData
- * @see #addDataScheme
- * @see #addDataAuthority
- */
- public final void addDataPath(String path, int type) {
- if (mDataPaths == null) mDataPaths = new ArrayList<PatternMatcher>();
- mDataPaths.add(new PatternMatcher(path.intern(), type));
- }
-
- /**
- * Return the number of data paths in the filter.
- */
- public final int countDataPaths() {
- return mDataPaths != null ? mDataPaths.size() : 0;
- }
-
- /**
- * Return a data path in the filter.
- */
- public final PatternMatcher getDataPath(int index) {
- return mDataPaths.get(index);
- }
-
- /**
- * Is the given data path included in the filter? Note that if the
- * filter does not include any paths, false will <em>always</em> be
- * returned.
- *
- * @param data The data path to look for. This is without the scheme
- * prefix.
- *
- * @return True if the data string matches a path listed in the
- * filter.
- */
- public final boolean hasDataPath(String data) {
- if (mDataPaths == null) {
- return false;
- }
- Iterator<PatternMatcher> i = mDataPaths.iterator();
- while (i.hasNext()) {
- final PatternMatcher pe = i.next();
- if (pe.match(data)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Return an iterator over the filter's data paths.
- */
- public final Iterator<PatternMatcher> pathsIterator() {
- return mDataPaths != null ? mDataPaths.iterator() : null;
- }
-
- /**
- * Match this intent filter against the given Intent data. This ignores
- * the data scheme -- unlike {@link #matchData}, the authority will match
- * regardless of whether there is a matching scheme.
- *
- * @param data The data whose authority is being looked for.
- *
- * @return Returns either {@link #MATCH_CATEGORY_HOST},
- * {@link #MATCH_CATEGORY_PORT}, {@link #NO_MATCH_DATA}.
- */
- public final int matchDataAuthority(Uri data) {
- if (mDataAuthorities == null) {
- return NO_MATCH_DATA;
- }
- Iterator<AuthorityEntry> i = mDataAuthorities.iterator();
- while (i.hasNext()) {
- final AuthorityEntry ae = i.next();
- int match = ae.match(data);
- if (match >= 0) {
- return match;
- }
- }
- return NO_MATCH_DATA;
- }
-
- /**
- * Match this filter against an Intent's data (type, scheme and path). If
- * the filter does not specify any types and does not specify any
- * schemes/paths, the match will only succeed if the intent does not
- * also specify a type or data.
- *
- * <p>Note that to match against an authority, you must also specify a base
- * scheme the authority is in. To match against a data path, both a scheme
- * and authority must be specified. If the filter does not specify any
- * types or schemes that it matches against, it is considered to be empty
- * (any authority or data path given is ignored, as if it were empty as
- * well).
- *
- * @param type The desired data type to look for, as returned by
- * Intent.resolveType().
- * @param scheme The desired data scheme to look for, as returned by
- * Intent.getScheme().
- * @param data The full data string to match against, as supplied in
- * Intent.data.
- *
- * @return Returns either a valid match constant (a combination of
- * {@link #MATCH_CATEGORY_MASK} and {@link #MATCH_ADJUSTMENT_MASK}),
- * or one of the error codes {@link #NO_MATCH_TYPE} if the type didn't match
- * or {@link #NO_MATCH_DATA} if the scheme/path didn't match.
- *
- * @see #match
- */
- public final int matchData(String type, String scheme, Uri data) {
- final ArrayList<String> types = mDataTypes;
- final ArrayList<String> schemes = mDataSchemes;
- final ArrayList<AuthorityEntry> authorities = mDataAuthorities;
- final ArrayList<PatternMatcher> paths = mDataPaths;
-
- int match = MATCH_CATEGORY_EMPTY;
-
- if (types == null && schemes == null) {
- return ((type == null && data == null)
- ? (MATCH_CATEGORY_EMPTY+MATCH_ADJUSTMENT_NORMAL) : NO_MATCH_DATA);
- }
-
- if (schemes != null) {
- if (schemes.contains(scheme != null ? scheme : "")) {
- match = MATCH_CATEGORY_SCHEME;
- } else {
- return NO_MATCH_DATA;
- }
-
- if (authorities != null) {
- int authMatch = matchDataAuthority(data);
- if (authMatch >= 0) {
- if (paths == null) {
- match = authMatch;
- } else if (hasDataPath(data.getPath())) {
- match = MATCH_CATEGORY_PATH;
- } else {
- return NO_MATCH_DATA;
- }
- } else {
- return NO_MATCH_DATA;
- }
- }
- } else {
- // Special case: match either an Intent with no data URI,
- // or with a scheme: URI. This is to give a convenience for
- // the common case where you want to deal with data in a
- // content provider, which is done by type, and we don't want
- // to force everyone to say they handle content: or file: URIs.
- if (scheme != null && !"".equals(scheme)
- && !"content".equals(scheme)
- && !"file".equals(scheme)) {
- return NO_MATCH_DATA;
- }
- }
-
- if (types != null) {
- if (findMimeType(type)) {
- match = MATCH_CATEGORY_TYPE;
- } else {
- return NO_MATCH_TYPE;
- }
- } else {
- // If no MIME types are specified, then we will only match against
- // an Intent that does not have a MIME type.
- if (type != null) {
- return NO_MATCH_TYPE;
- }
- }
-
- return match + MATCH_ADJUSTMENT_NORMAL;
- }
-
- /**
- * Add a new Intent category to match against. The semantics of
- * categories is the opposite of actions -- an Intent includes the
- * categories that it requires, all of which must be included in the
- * filter in order to match. In other words, adding a category to the
- * filter has no impact on matching unless that category is specified in
- * the intent.
- *
- * @param category Name of category to match, i.e. Intent.CATEGORY_EMBED.
- */
- public final void addCategory(String category) {
- if (mCategories == null) mCategories = new ArrayList<String>();
- if (!mCategories.contains(category)) {
- mCategories.add(category.intern());
- }
- }
-
- /**
- * Return the number of categories in the filter.
- */
- public final int countCategories() {
- return mCategories != null ? mCategories.size() : 0;
- }
-
- /**
- * Return a category in the filter.
- */
- public final String getCategory(int index) {
- return mCategories.get(index);
- }
-
- /**
- * Is the given category included in the filter?
- *
- * @param category The category that the filter supports.
- *
- * @return True if the category is explicitly mentioned in the filter.
- */
- public final boolean hasCategory(String category) {
- return mCategories != null && mCategories.contains(category);
- }
-
- /**
- * Return an iterator over the filter's categories.
- */
- public final Iterator<String> categoriesIterator() {
- return mCategories != null ? mCategories.iterator() : null;
- }
-
- /**
- * Match this filter against an Intent's categories. Each category in
- * the Intent must be specified by the filter; if any are not in the
- * filter, the match fails.
- *
- * @param categories The categories included in the intent, as returned by
- * Intent.getCategories().
- *
- * @return If all categories match (success), null; else the name of the
- * first category that didn't match.
- */
- public final String matchCategories(Set<String> categories) {
- if (categories == null) {
- return null;
- }
-
- Iterator<String> it = categories.iterator();
-
- if (mCategories == null) {
- return it.hasNext() ? it.next() : null;
- }
-
- while (it.hasNext()) {
- final String category = it.next();
- if (!mCategories.contains(category)) {
- return category;
- }
- }
-
- return null;
- }
-
- /**
- * Test whether this filter matches the given <var>intent</var>.
- *
- * @param intent The Intent to compare against.
- * @param resolve If true, the intent's type will be resolved by calling
- * Intent.resolveType(); otherwise a simple match against
- * Intent.type will be performed.
- * @param logTag Tag to use in debugging messages.
- *
- * @return Returns either a valid match constant (a combination of
- * {@link #MATCH_CATEGORY_MASK} and {@link #MATCH_ADJUSTMENT_MASK}),
- * or one of the error codes {@link #NO_MATCH_TYPE} if the type didn't match,
- * {@link #NO_MATCH_DATA} if the scheme/path didn't match,
- * {@link #NO_MATCH_ACTION if the action didn't match, or
- * {@link #NO_MATCH_CATEGORY} if one or more categories didn't match.
- *
- * @return How well the filter matches. Negative if it doesn't match,
- * zero or positive positive value if it does with a higher
- * value representing a better match.
- *
- * @see #match(String, String, String, android.net.Uri , Set, String)
- */
- public final int match(ContentResolver resolver, Intent intent,
- boolean resolve, String logTag) {
- String type = resolve ? intent.resolveType(resolver) : intent.getType();
- return match(intent.getAction(), type, intent.getScheme(),
- intent.getData(), intent.getCategories(), logTag);
- }
-
- /**
- * Test whether this filter matches the given intent data. A match is
- * only successful if the actions and categories in the Intent match
- * against the filter, as described in {@link IntentFilter}; in that case,
- * the match result returned will be as per {@link #matchData}.
- *
- * @param action The intent action to match against (Intent.getAction).
- * @param type The intent type to match against (Intent.resolveType()).
- * @param scheme The data scheme to match against (Intent.getScheme()).
- * @param data The data URI to match against (Intent.getData()).
- * @param categories The categories to match against
- * (Intent.getCategories()).
- * @param logTag Tag to use in debugging messages.
- *
- * @return Returns either a valid match constant (a combination of
- * {@link #MATCH_CATEGORY_MASK} and {@link #MATCH_ADJUSTMENT_MASK}),
- * or one of the error codes {@link #NO_MATCH_TYPE} if the type didn't match,
- * {@link #NO_MATCH_DATA} if the scheme/path didn't match,
- * {@link #NO_MATCH_ACTION if the action didn't match, or
- * {@link #NO_MATCH_CATEGORY} if one or more categories didn't match.
- *
- * @see #matchData
- * @see Intent#getAction
- * @see Intent#resolveType
- * @see Intent#getScheme
- * @see Intent#getData
- * @see Intent#getCategories
- */
- public final int match(String action, String type, String scheme,
- Uri data, Set<String> categories, String logTag) {
- if (action != null && !matchAction(action)) {
- if (Config.LOGV) Log.v(
- logTag, "No matching action " + action + " for " + this);
- return NO_MATCH_ACTION;
- }
-
- int dataMatch = matchData(type, scheme, data);
- if (dataMatch < 0) {
- if (Config.LOGV) {
- if (dataMatch == NO_MATCH_TYPE) {
- Log.v(logTag, "No matching type " + type
- + " for " + this);
- }
- if (dataMatch == NO_MATCH_DATA) {
- Log.v(logTag, "No matching scheme/path " + data
- + " for " + this);
- }
- }
- return dataMatch;
- }
-
- String categoryMatch = matchCategories(categories);
- if (categoryMatch != null) {
- if (Config.LOGV) Log.v(
- logTag, "No matching category "
- + categoryMatch + " for " + this);
- return NO_MATCH_CATEGORY;
- }
-
- // It would be nice to treat container activities as more
- // important than ones that can be embedded, but this is not the way...
- if (false) {
- if (categories != null) {
- dataMatch -= mCategories.size() - categories.size();
- }
- }
-
- return dataMatch;
- }
-
- /**
- * Write the contents of the IntentFilter as an XML stream.
- */
- public void writeToXml(XmlSerializer serializer) throws IOException {
- int N = countActions();
- for (int i=0; i<N; i++) {
- serializer.startTag(null, ACTION_STR);
- serializer.attribute(null, NAME_STR, mActions.get(i));
- serializer.endTag(null, ACTION_STR);
- }
- N = countCategories();
- for (int i=0; i<N; i++) {
- serializer.startTag(null, CAT_STR);
- serializer.attribute(null, NAME_STR, mCategories.get(i));
- serializer.endTag(null, CAT_STR);
- }
- N = countDataTypes();
- for (int i=0; i<N; i++) {
- serializer.startTag(null, TYPE_STR);
- String type = mDataTypes.get(i);
- if (type.indexOf('/') < 0) type = type + "/*";
- serializer.attribute(null, NAME_STR, type);
- serializer.endTag(null, TYPE_STR);
- }
- N = countDataSchemes();
- for (int i=0; i<N; i++) {
- serializer.startTag(null, SCHEME_STR);
- serializer.attribute(null, NAME_STR, mDataSchemes.get(i));
- serializer.endTag(null, SCHEME_STR);
- }
- N = countDataAuthorities();
- for (int i=0; i<N; i++) {
- serializer.startTag(null, AUTH_STR);
- AuthorityEntry ae = mDataAuthorities.get(i);
- serializer.attribute(null, HOST_STR, ae.getHost());
- if (ae.getPort() >= 0) {
- serializer.attribute(null, PORT_STR, Integer.toString(ae.getPort()));
- }
- serializer.endTag(null, AUTH_STR);
- }
- N = countDataPaths();
- for (int i=0; i<N; i++) {
- serializer.startTag(null, PATH_STR);
- PatternMatcher pe = mDataPaths.get(i);
- switch (pe.getType()) {
- case PatternMatcher.PATTERN_LITERAL:
- serializer.attribute(null, LITERAL_STR, pe.getPath());
- break;
- case PatternMatcher.PATTERN_PREFIX:
- serializer.attribute(null, PREFIX_STR, pe.getPath());
- break;
- case PatternMatcher.PATTERN_SIMPLE_GLOB:
- serializer.attribute(null, SGLOB_STR, pe.getPath());
- break;
- }
- serializer.endTag(null, PATH_STR);
- }
- }
-
- public void readFromXml(XmlPullParser parser) throws XmlPullParserException,
- IOException {
- int outerDepth = parser.getDepth();
- int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG
- || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG
- || type == XmlPullParser.TEXT) {
- continue;
- }
-
- String tagName = parser.getName();
- if (tagName.equals(ACTION_STR)) {
- String name = parser.getAttributeValue(null, NAME_STR);
- if (name != null) {
- addAction(name);
- }
- } else if (tagName.equals(CAT_STR)) {
- String name = parser.getAttributeValue(null, NAME_STR);
- if (name != null) {
- addCategory(name);
- }
- } else if (tagName.equals(TYPE_STR)) {
- String name = parser.getAttributeValue(null, NAME_STR);
- if (name != null) {
- try {
- addDataType(name);
- } catch (MalformedMimeTypeException e) {
- }
- }
- } else if (tagName.equals(SCHEME_STR)) {
- String name = parser.getAttributeValue(null, NAME_STR);
- if (name != null) {
- addDataScheme(name);
- }
- } else if (tagName.equals(AUTH_STR)) {
- String host = parser.getAttributeValue(null, HOST_STR);
- String port = parser.getAttributeValue(null, PORT_STR);
- if (host != null) {
- addDataAuthority(host, port);
- }
- } else if (tagName.equals(PATH_STR)) {
- String path = parser.getAttributeValue(null, LITERAL_STR);
- if (path != null) {
- addDataPath(path, PatternMatcher.PATTERN_LITERAL);
- } else if ((path=parser.getAttributeValue(null, PREFIX_STR)) != null) {
- addDataPath(path, PatternMatcher.PATTERN_PREFIX);
- } else if ((path=parser.getAttributeValue(null, SGLOB_STR)) != null) {
- addDataPath(path, PatternMatcher.PATTERN_SIMPLE_GLOB);
- }
- } else {
- Log.w("IntentFilter", "Unknown tag parsing IntentFilter: " + tagName);
- }
- XmlUtils.skipCurrentTag(parser);
- }
- }
-
- public void dump(Printer du, String prefix) {
- if (mActions.size() > 0) {
- Iterator<String> it = mActions.iterator();
- while (it.hasNext()) {
- du.println(prefix + "Action: \"" + it.next() + "\"");
- }
- }
- if (mCategories != null) {
- Iterator<String> it = mCategories.iterator();
- while (it.hasNext()) {
- du.println(prefix + "Category: \"" + it.next() + "\"");
- }
- }
- if (mDataSchemes != null) {
- Iterator<String> it = mDataSchemes.iterator();
- while (it.hasNext()) {
- du.println(prefix + "Data Scheme: \"" + it.next() + "\"");
- }
- }
- if (mDataAuthorities != null) {
- Iterator<AuthorityEntry> it = mDataAuthorities.iterator();
- while (it.hasNext()) {
- AuthorityEntry ae = it.next();
- du.println(prefix + "Data Authority: \"" + ae.mHost + "\":"
- + ae.mPort + (ae.mWild ? " WILD" : ""));
- }
- }
- if (mDataPaths != null) {
- Iterator<PatternMatcher> it = mDataPaths.iterator();
- while (it.hasNext()) {
- PatternMatcher pe = it.next();
- du.println(prefix + "Data Path: \"" + pe + "\"");
- }
- }
- if (mDataTypes != null) {
- Iterator<String> it = mDataTypes.iterator();
- while (it.hasNext()) {
- du.println(prefix + "Data Type: \"" + it.next() + "\"");
- }
- }
- du.println(prefix + "mPriority=" + mPriority
- + ", mHasPartialTypes=" + mHasPartialTypes);
- }
-
- public static final Parcelable.Creator<IntentFilter> CREATOR
- = new Parcelable.Creator<IntentFilter>() {
- public IntentFilter createFromParcel(Parcel source) {
- return new IntentFilter(source);
- }
-
- public IntentFilter[] newArray(int size) {
- return new IntentFilter[size];
- }
- };
-
- public final int describeContents() {
- return 0;
- }
-
- public final void writeToParcel(Parcel dest, int flags) {
- dest.writeStringList(mActions);
- if (mCategories != null) {
- dest.writeInt(1);
- dest.writeStringList(mCategories);
- } else {
- dest.writeInt(0);
- }
- if (mDataSchemes != null) {
- dest.writeInt(1);
- dest.writeStringList(mDataSchemes);
- } else {
- dest.writeInt(0);
- }
- if (mDataTypes != null) {
- dest.writeInt(1);
- dest.writeStringList(mDataTypes);
- } else {
- dest.writeInt(0);
- }
- if (mDataAuthorities != null) {
- final int N = mDataAuthorities.size();
- dest.writeInt(N);
- for (int i=0; i<N; i++) {
- mDataAuthorities.get(i).writeToParcel(dest);
- }
- } else {
- dest.writeInt(0);
- }
- if (mDataPaths != null) {
- final int N = mDataPaths.size();
- dest.writeInt(N);
- for (int i=0; i<N; i++) {
- mDataPaths.get(i).writeToParcel(dest, 0);
- }
- } else {
- dest.writeInt(0);
- }
- dest.writeInt(mPriority);
- dest.writeInt(mHasPartialTypes ? 1 : 0);
- }
-
- /**
- * For debugging -- perform a check on the filter, return true if it passed
- * or false if it failed.
- *
- * {@hide}
- */
- public boolean debugCheck() {
- return true;
-
- // This code looks for intent filters that do not specify data.
- /*
- if (mActions != null && mActions.size() == 1
- && mActions.contains(Intent.ACTION_MAIN)) {
- return true;
- }
-
- if (mDataTypes == null && mDataSchemes == null) {
- Log.w("IntentFilter", "QUESTIONABLE INTENT FILTER:");
- dump(Log.WARN, "IntentFilter", " ");
- return false;
- }
-
- return true;
- */
- }
-
- private IntentFilter(Parcel source) {
- mActions = new ArrayList<String>();
- source.readStringList(mActions);
- if (source.readInt() != 0) {
- mCategories = new ArrayList<String>();
- source.readStringList(mCategories);
- }
- if (source.readInt() != 0) {
- mDataSchemes = new ArrayList<String>();
- source.readStringList(mDataSchemes);
- }
- if (source.readInt() != 0) {
- mDataTypes = new ArrayList<String>();
- source.readStringList(mDataTypes);
- }
- int N = source.readInt();
- if (N > 0) {
- mDataAuthorities = new ArrayList<AuthorityEntry>();
- for (int i=0; i<N; i++) {
- mDataAuthorities.add(new AuthorityEntry(source));
- }
- }
- N = source.readInt();
- if (N > 0) {
- mDataPaths = new ArrayList<PatternMatcher>();
- for (int i=0; i<N; i++) {
- mDataPaths.add(new PatternMatcher(source));
- }
- }
- mPriority = source.readInt();
- mHasPartialTypes = source.readInt() > 0;
- }
-
- private final boolean findMimeType(String type) {
- final ArrayList<String> t = mDataTypes;
-
- if (type == null) {
- return false;
- }
-
- if (t.contains(type)) {
- return true;
- }
-
- // Deal with an Intent wanting to match every type in the IntentFilter.
- final int typeLength = type.length();
- if (typeLength == 3 && type.equals("*/*")) {
- return !t.isEmpty();
- }
-
- // Deal with this IntentFilter wanting to match every Intent type.
- if (mHasPartialTypes && t.contains("*")) {
- return true;
- }
-
- final int slashpos = type.indexOf('/');
- if (slashpos > 0) {
- if (mHasPartialTypes && t.contains(type.substring(0, slashpos))) {
- return true;
- }
- if (typeLength == slashpos+2 && type.charAt(slashpos+1) == '*') {
- // Need to look through all types for one that matches
- // our base...
- final Iterator<String> it = t.iterator();
- while (it.hasNext()) {
- String v = it.next();
- if (type.regionMatches(0, v, 0, slashpos+1)) {
- return true;
- }
- }
- }
- }
-
- return false;
- }
-}
diff --git a/core/java/android/content/MutableContextWrapper.java b/core/java/android/content/MutableContextWrapper.java
deleted file mode 100644
index 820479c..0000000
--- a/core/java/android/content/MutableContextWrapper.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-/**
- * Special version of {@link ContextWrapper} that allows the base context to
- * be modified after it is initially set.
- */
-public class MutableContextWrapper extends ContextWrapper {
- public MutableContextWrapper(Context base) {
- super(base);
- }
-
- /**
- * Change the base context for this ContextWrapper. All calls will then be
- * delegated to the base context. Unlike ContextWrapper, the base context
- * can be changed even after one is already set.
- *
- * @param base The new base context for this wrapper.
- */
- public void setBaseContext(Context base) {
- mBase = base;
- }
-}
diff --git a/core/java/android/content/ReceiverCallNotAllowedException.java b/core/java/android/content/ReceiverCallNotAllowedException.java
deleted file mode 100644
index 96b269c..0000000
--- a/core/java/android/content/ReceiverCallNotAllowedException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.util.AndroidRuntimeException;
-
-/**
- * This exception is thrown from {@link Context#registerReceiver} and
- * {@link Context#bindService} when these methods are being used from
- * an {@link BroadcastReceiver} component. In this case, the component will no
- * longer be active upon returning from receiving the Intent, so it is
- * not valid to use asynchronous APIs.
- */
-public class ReceiverCallNotAllowedException extends AndroidRuntimeException {
- public ReceiverCallNotAllowedException(String msg) {
- super(msg);
- }
-}
diff --git a/core/java/android/content/SearchRecentSuggestionsProvider.java b/core/java/android/content/SearchRecentSuggestionsProvider.java
deleted file mode 100644
index 3d89e92..0000000
--- a/core/java/android/content/SearchRecentSuggestionsProvider.java
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.app.SearchManager;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.text.TextUtils;
-import android.util.Log;
-
-/**
- * This superclass can be used to create a simple search suggestions provider for your application.
- * It creates suggestions (as the user types) based on recent queries and/or recent views.
- *
- * <p>In order to use this class, you must do the following.
- *
- * <ul>
- * <li>Implement and test query search, as described in {@link android.app.SearchManager}. (This
- * provider will send any suggested queries via the standard
- * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} Intent, which you'll already
- * support once you have implemented and tested basic searchability.)</li>
- * <li>Create a Content Provider within your application by extending
- * {@link android.content.SearchRecentSuggestionsProvider}. The class you create will be
- * very simple - typically, it will have only a constructor. But the constructor has a very
- * important responsibility: When it calls {@link #setupSuggestions(String, int)}, it
- * <i>configures</i> the provider to match the requirements of your searchable activity.</li>
- * <li>Create a manifest entry describing your provider. Typically this would be as simple
- * as adding the following lines:
- * <pre class="prettyprint">
- * &lt;!-- Content provider for search suggestions --&gt;
- * &lt;provider android:name="YourSuggestionProviderClass"
- * android:authorities="your.suggestion.authority" /&gt;</pre>
- * </li>
- * <li>Please note that you <i>do not</i> instantiate this content provider directly from within
- * your code. This is done automatically by the system Content Resolver, when the search dialog
- * looks for suggestions.</li>
- * <li>In order for the Content Resolver to do this, you must update your searchable activity's
- * XML configuration file with information about your content provider. The following additions
- * are usually sufficient:
- * <pre class="prettyprint">
- * android:searchSuggestAuthority="your.suggestion.authority"
- * android:searchSuggestSelection=" ? "</pre>
- * </li>
- * <li>In your searchable activities, capture any user-generated queries and record them
- * for future searches by calling {@link android.provider.SearchRecentSuggestions#saveRecentQuery
- * SearchRecentSuggestions.saveRecentQuery()}.</li>
- * </ul>
- *
- * @see android.provider.SearchRecentSuggestions
- */
-public class SearchRecentSuggestionsProvider extends ContentProvider {
- // debugging support
- private static final String TAG = "SuggestionsProvider";
-
- // client-provided configuration values
- private String mAuthority;
- private int mMode;
- private boolean mTwoLineDisplay;
-
- // general database configuration and tables
- private SQLiteOpenHelper mOpenHelper;
- private static final String sDatabaseName = "suggestions.db";
- private static final String sSuggestions = "suggestions";
- private static final String ORDER_BY = "date DESC";
- private static final String NULL_COLUMN = "query";
-
- // Table of database versions. Don't forget to update!
- // NOTE: These version values are shifted left 8 bits (x 256) in order to create space for
- // a small set of mode bitflags in the version int.
- //
- // 1 original implementation with queries, and 1 or 2 display columns
- // 1->2 added UNIQUE constraint to display1 column
- private static final int DATABASE_VERSION = 2 * 256;
-
- /**
- * This mode bit configures the database to record recent queries. <i>required</i>
- *
- * @see #setupSuggestions(String, int)
- */
- public static final int DATABASE_MODE_QUERIES = 1;
- /**
- * This mode bit configures the database to include a 2nd annotation line with each entry.
- * <i>optional</i>
- *
- * @see #setupSuggestions(String, int)
- */
- public static final int DATABASE_MODE_2LINES = 2;
-
- // Uri and query support
- private static final int URI_MATCH_SUGGEST = 1;
-
- private Uri mSuggestionsUri;
- private UriMatcher mUriMatcher;
-
- private String mSuggestSuggestionClause;
- private String[] mSuggestionProjection;
-
- /**
- * Builds the database. This version has extra support for using the version field
- * as a mode flags field, and configures the database columns depending on the mode bits
- * (features) requested by the extending class.
- *
- * @hide
- */
- private static class DatabaseHelper extends SQLiteOpenHelper {
-
- private int mNewVersion;
-
- public DatabaseHelper(Context context, int newVersion) {
- super(context, sDatabaseName, null, newVersion);
- mNewVersion = newVersion;
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- StringBuilder builder = new StringBuilder();
- builder.append("CREATE TABLE suggestions (" +
- "_id INTEGER PRIMARY KEY" +
- ",display1 TEXT UNIQUE ON CONFLICT REPLACE");
- if (0 != (mNewVersion & DATABASE_MODE_2LINES)) {
- builder.append(",display2 TEXT");
- }
- builder.append(",query TEXT" +
- ",date LONG" +
- ");");
- db.execSQL(builder.toString());
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
- + newVersion + ", which will destroy all old data");
- db.execSQL("DROP TABLE IF EXISTS suggestions");
- onCreate(db);
- }
- }
-
- /**
- * In order to use this class, you must extend it, and call this setup function from your
- * constructor. In your application or activities, you must provide the same values when
- * you create the {@link android.provider.SearchRecentSuggestions} helper.
- *
- * @param authority This must match the authority that you've declared in your manifest.
- * @param mode You can use mode flags here to determine certain functional aspects of your
- * database. Note, this value should not change from run to run, because when it does change,
- * your suggestions database may be wiped.
- *
- * @see #DATABASE_MODE_QUERIES
- * @see #DATABASE_MODE_2LINES
- */
- protected void setupSuggestions(String authority, int mode) {
- if (TextUtils.isEmpty(authority) ||
- ((mode & DATABASE_MODE_QUERIES) == 0)) {
- throw new IllegalArgumentException();
- }
- // unpack mode flags
- mTwoLineDisplay = (0 != (mode & DATABASE_MODE_2LINES));
-
- // saved values
- mAuthority = new String(authority);
- mMode = mode;
-
- // derived values
- mSuggestionsUri = Uri.parse("content://" + mAuthority + "/suggestions");
- mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
- mUriMatcher.addURI(mAuthority, SearchManager.SUGGEST_URI_PATH_QUERY, URI_MATCH_SUGGEST);
-
- if (mTwoLineDisplay) {
- mSuggestSuggestionClause = "display1 LIKE ? OR display2 LIKE ?";
-
- mSuggestionProjection = new String [] {
- "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT,
- "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1,
- "display2 AS " + SearchManager.SUGGEST_COLUMN_TEXT_2,
- "query AS " + SearchManager.SUGGEST_COLUMN_QUERY,
- "_id"
- };
- } else {
- mSuggestSuggestionClause = "display1 LIKE ?";
-
- mSuggestionProjection = new String [] {
- "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT,
- "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1,
- "query AS " + SearchManager.SUGGEST_COLUMN_QUERY,
- "_id"
- };
- }
-
-
- }
-
- /**
- * This method is provided for use by the ContentResolver. Do not override, or directly
- * call from your own code.
- */
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-
- final int length = uri.getPathSegments().size();
- if (length != 1) {
- throw new IllegalArgumentException("Unknown Uri");
- }
-
- final String base = uri.getPathSegments().get(0);
- int count = 0;
- if (base.equals(sSuggestions)) {
- count = db.delete(sSuggestions, selection, selectionArgs);
- } else {
- throw new IllegalArgumentException("Unknown Uri");
- }
- getContext().getContentResolver().notifyChange(uri, null);
- return count;
- }
-
- /**
- * This method is provided for use by the ContentResolver. Do not override, or directly
- * call from your own code.
- */
- @Override
- public String getType(Uri uri) {
- if (mUriMatcher.match(uri) == URI_MATCH_SUGGEST) {
- return SearchManager.SUGGEST_MIME_TYPE;
- }
- int length = uri.getPathSegments().size();
- if (length >= 1) {
- String base = uri.getPathSegments().get(0);
- if (base.equals(sSuggestions)) {
- if (length == 1) {
- return "vnd.android.cursor.dir/suggestion";
- } else if (length == 2) {
- return "vnd.android.cursor.item/suggestion";
- }
- }
- }
- throw new IllegalArgumentException("Unknown Uri");
- }
-
- /**
- * This method is provided for use by the ContentResolver. Do not override, or directly
- * call from your own code.
- */
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-
- int length = uri.getPathSegments().size();
- if (length < 1) {
- throw new IllegalArgumentException("Unknown Uri");
- }
- // Note: This table has on-conflict-replace semantics, so insert() may actually replace()
- long rowID = -1;
- String base = uri.getPathSegments().get(0);
- Uri newUri = null;
- if (base.equals(sSuggestions)) {
- if (length == 1) {
- rowID = db.insert(sSuggestions, NULL_COLUMN, values);
- if (rowID > 0) {
- newUri = Uri.withAppendedPath(mSuggestionsUri, String.valueOf(rowID));
- }
- }
- }
- if (rowID < 0) {
- throw new IllegalArgumentException("Unknown Uri");
- }
- getContext().getContentResolver().notifyChange(newUri, null);
- return newUri;
- }
-
- /**
- * This method is provided for use by the ContentResolver. Do not override, or directly
- * call from your own code.
- */
- @Override
- public boolean onCreate() {
- if (mAuthority == null || mMode == 0) {
- throw new IllegalArgumentException("Provider not configured");
- }
- int mWorkingDbVersion = DATABASE_VERSION + mMode;
- mOpenHelper = new DatabaseHelper(getContext(), mWorkingDbVersion);
-
- return true;
- }
-
- /**
- * This method is provided for use by the ContentResolver. Do not override, or directly
- * call from your own code.
- */
- // TODO: Confirm no injection attacks here, or rewrite.
- @Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
-
- // special case for actual suggestions (from search manager)
- if (mUriMatcher.match(uri) == URI_MATCH_SUGGEST) {
- String suggestSelection;
- String[] myArgs;
- if (TextUtils.isEmpty(selectionArgs[0])) {
- suggestSelection = null;
- myArgs = null;
- } else {
- String like = "%" + selectionArgs[0] + "%";
- if (mTwoLineDisplay) {
- myArgs = new String [] { like, like };
- } else {
- myArgs = new String [] { like };
- }
- suggestSelection = mSuggestSuggestionClause;
- }
- // Suggestions are always performed with the default sort order
- Cursor c = db.query(sSuggestions, mSuggestionProjection,
- suggestSelection, myArgs, null, null, ORDER_BY, null);
- c.setNotificationUri(getContext().getContentResolver(), uri);
- return c;
- }
-
- // otherwise process arguments and perform a standard query
- int length = uri.getPathSegments().size();
- if (length != 1 && length != 2) {
- throw new IllegalArgumentException("Unknown Uri");
- }
-
- String base = uri.getPathSegments().get(0);
- if (!base.equals(sSuggestions)) {
- throw new IllegalArgumentException("Unknown Uri");
- }
-
- String[] useProjection = null;
- if (projection != null && projection.length > 0) {
- useProjection = new String[projection.length + 1];
- System.arraycopy(projection, 0, useProjection, 0, projection.length);
- useProjection[projection.length] = "_id AS _id";
- }
-
- StringBuilder whereClause = new StringBuilder(256);
- if (length == 2) {
- whereClause.append("(_id = ").append(uri.getPathSegments().get(1)).append(")");
- }
-
- // Tack on the user's selection, if present
- if (selection != null && selection.length() > 0) {
- if (whereClause.length() > 0) {
- whereClause.append(" AND ");
- }
-
- whereClause.append('(');
- whereClause.append(selection);
- whereClause.append(')');
- }
-
- // And perform the generic query as requested
- Cursor c = db.query(base, useProjection, whereClause.toString(),
- selectionArgs, null, null, sortOrder,
- null);
- c.setNotificationUri(getContext().getContentResolver(), uri);
- return c;
- }
-
- /**
- * This method is provided for use by the ContentResolver. Do not override, or directly
- * call from your own code.
- */
- @Override
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- throw new UnsupportedOperationException("Not implemented");
- }
-
-}
diff --git a/core/java/android/content/ServiceConnection.java b/core/java/android/content/ServiceConnection.java
deleted file mode 100644
index d115ce4..0000000
--- a/core/java/android/content/ServiceConnection.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.os.IBinder;
-
-/**
- * Interface for monitoring the state of an application service. See
- * {@link android.app.Service} and
- * {@link Context#bindService Context.bindService()} for more information.
- * <p>Like many callbacks from the system, the methods on this class are called
- * from the main thread of your process.
- */
-public interface ServiceConnection {
- /**
- * Called when a connection to the Service has been established, with
- * the {@link android.os.IBinder} of the communication channel to the
- * Service.
- *
- * @param name The concrete component name of the service that has
- * been connected.
- *
- * @param service The IBinder of the Service's communication channel,
- * which you can now make calls on.
- */
- public void onServiceConnected(ComponentName name, IBinder service);
-
- /**
- * Called when a connection to the Service has been lost. This typically
- * happens when the process hosting the service has crashed or been killed.
- * This does <em>not</em> remove the ServiceConnection itself -- this
- * binding to the service will remain active, and you will receive a call
- * to {@link #onServiceConnected} when the Service is next running.
- *
- * @param name The concrete component name of the service whose
- * connection has been lost.
- */
- public void onServiceDisconnected(ComponentName name);
-}
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
deleted file mode 100644
index a15e29e..0000000
--- a/core/java/android/content/SharedPreferences.java
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import java.util.Map;
-
-/**
- * Interface for accessing and modifying preference data returned by {@link
- * Context#getSharedPreferences}. For any particular set of preferences,
- * there is a single instance of this class that all clients share.
- * Modifications to the preferences must go through an {@link Editor} object
- * to ensure the preference values remain in a consistent state and control
- * when they are committed to storage.
- *
- * <p><em>Note: currently this class does not support use across multiple
- * processes. This will be added later.</em>
- *
- * @see Context#getSharedPreferences
- */
-public interface SharedPreferences {
- /**
- * Interface definition for a callback to be invoked when a shared
- * preference is changed.
- */
- public interface OnSharedPreferenceChangeListener {
- /**
- * Called when a shared preference is changed, added, or removed. This
- * may be called even if a preference is set to its existing value.
- *
- * @param sharedPreferences The {@link SharedPreferences} that received
- * the change.
- * @param key The key of the preference that was changed, added, or
- * removed.
- */
- void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key);
- }
-
- /**
- * Interface used for modifying values in a {@link SharedPreferences}
- * object. All changes you make in an editor are batched, and not copied
- * back to the original {@link SharedPreferences} or persistent storage
- * until you call {@link #commit}.
- */
- public interface Editor {
- /**
- * Set a String value in the preferences editor, to be written back once
- * {@link #commit} is called.
- *
- * @param key The name of the preference to modify.
- * @param value The new value for the preference.
- *
- * @return Returns a reference to the same Editor object, so you can
- * chain put calls together.
- */
- Editor putString(String key, String value);
-
- /**
- * Set an int value in the preferences editor, to be written back once
- * {@link #commit} is called.
- *
- * @param key The name of the preference to modify.
- * @param value The new value for the preference.
- *
- * @return Returns a reference to the same Editor object, so you can
- * chain put calls together.
- */
- Editor putInt(String key, int value);
-
- /**
- * Set a long value in the preferences editor, to be written back once
- * {@link #commit} is called.
- *
- * @param key The name of the preference to modify.
- * @param value The new value for the preference.
- *
- * @return Returns a reference to the same Editor object, so you can
- * chain put calls together.
- */
- Editor putLong(String key, long value);
-
- /**
- * Set a float value in the preferences editor, to be written back once
- * {@link #commit} is called.
- *
- * @param key The name of the preference to modify.
- * @param value The new value for the preference.
- *
- * @return Returns a reference to the same Editor object, so you can
- * chain put calls together.
- */
- Editor putFloat(String key, float value);
-
- /**
- * Set a boolean value in the preferences editor, to be written back
- * once {@link #commit} is called.
- *
- * @param key The name of the preference to modify.
- * @param value The new value for the preference.
- *
- * @return Returns a reference to the same Editor object, so you can
- * chain put calls together.
- */
- Editor putBoolean(String key, boolean value);
-
- /**
- * Mark in the editor that a preference value should be removed, which
- * will be done in the actual preferences once {@link #commit} is
- * called.
- *
- * <p>Note that when committing back to the preferences, all removals
- * are done first, regardless of whether you called remove before
- * or after put methods on this editor.
- *
- * @param key The name of the preference to remove.
- *
- * @return Returns a reference to the same Editor object, so you can
- * chain put calls together.
- */
- Editor remove(String key);
-
- /**
- * Mark in the editor to remove <em>all</em> values from the
- * preferences. Once commit is called, the only remaining preferences
- * will be any that you have defined in this editor.
- *
- * <p>Note that when committing back to the preferences, the clear
- * is done first, regardless of whether you called clear before
- * or after put methods on this editor.
- *
- * @return Returns a reference to the same Editor object, so you can
- * chain put calls together.
- */
- Editor clear();
-
- /**
- * Commit your preferences changes back from this Editor to the
- * {@link SharedPreferences} object it is editing. This atomically
- * performs the requested modifications, replacing whatever is currently
- * in the SharedPreferences.
- *
- * <p>Note that when two editors are modifying preferences at the same
- * time, the last one to call commit wins.
- *
- * @return Returns true if the new values were successfully written
- * to persistent storage.
- */
- boolean commit();
- }
-
- /**
- * Retrieve all values from the preferences.
- *
- * @return Returns a map containing a list of pairs key/value representing
- * the preferences.
- *
- * @throws NullPointerException
- */
- Map<String, ?> getAll();
-
- /**
- * Retrieve a String value from the preferences.
- *
- * @param key The name of the preference to retrieve.
- * @param defValue Value to return if this preference does not exist.
- *
- * @return Returns the preference value if it exists, or defValue. Throws
- * ClassCastException if there is a preference with this name that is not
- * a String.
- *
- * @throws ClassCastException
- */
- String getString(String key, String defValue);
-
- /**
- * Retrieve an int value from the preferences.
- *
- * @param key The name of the preference to retrieve.
- * @param defValue Value to return if this preference does not exist.
- *
- * @return Returns the preference value if it exists, or defValue. Throws
- * ClassCastException if there is a preference with this name that is not
- * an int.
- *
- * @throws ClassCastException
- */
- int getInt(String key, int defValue);
-
- /**
- * Retrieve a long value from the preferences.
- *
- * @param key The name of the preference to retrieve.
- * @param defValue Value to return if this preference does not exist.
- *
- * @return Returns the preference value if it exists, or defValue. Throws
- * ClassCastException if there is a preference with this name that is not
- * a long.
- *
- * @throws ClassCastException
- */
- long getLong(String key, long defValue);
-
- /**
- * Retrieve a float value from the preferences.
- *
- * @param key The name of the preference to retrieve.
- * @param defValue Value to return if this preference does not exist.
- *
- * @return Returns the preference value if it exists, or defValue. Throws
- * ClassCastException if there is a preference with this name that is not
- * a float.
- *
- * @throws ClassCastException
- */
- float getFloat(String key, float defValue);
-
- /**
- * Retrieve a boolean value from the preferences.
- *
- * @param key The name of the preference to retrieve.
- * @param defValue Value to return if this preference does not exist.
- *
- * @return Returns the preference value if it exists, or defValue. Throws
- * ClassCastException if there is a preference with this name that is not
- * a boolean.
- *
- * @throws ClassCastException
- */
- boolean getBoolean(String key, boolean defValue);
-
- /**
- * Checks whether the preferences contains a preference.
- *
- * @param key The name of the preference to check.
- * @return Returns true if the preference exists in the preferences,
- * otherwise false.
- */
- boolean contains(String key);
-
- /**
- * Create a new Editor for these preferences, through which you can make
- * modifications to the data in the preferences and atomically commit those
- * changes back to the SharedPreferences object.
- *
- * <p>Note that you <em>must</em> call {@link Editor#commit} to have any
- * changes you perform in the Editor actually show up in the
- * SharedPreferences.
- *
- * @return Returns a new instance of the {@link Editor} interface, allowing
- * you to modify the values in this SharedPreferences object.
- */
- Editor edit();
-
- /**
- * Registers a callback to be invoked when a change happens to a preference.
- *
- * @param listener The callback that will run.
- * @see #unregisterOnSharedPreferenceChangeListener
- */
- void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener);
-
- /**
- * Unregisters a previous callback.
- *
- * @param listener The callback that should be unregistered.
- * @see #registerOnSharedPreferenceChangeListener
- */
- void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener);
-}
diff --git a/core/java/android/content/SyncAdapter.java b/core/java/android/content/SyncAdapter.java
deleted file mode 100644
index 7826e50..0000000
--- a/core/java/android/content/SyncAdapter.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.os.Bundle;
-import android.os.RemoteException;
-
-/**
- * @hide
- */
-public abstract class SyncAdapter {
- private static final String TAG = "SyncAdapter";
-
- /** Kernel event log tag. Also listed in data/etc/event-log-tags. */
- public static final int LOG_SYNC_DETAILS = 2743;
-
- class Transport extends ISyncAdapter.Stub {
- public void startSync(ISyncContext syncContext, String account,
- Bundle extras) throws RemoteException {
- SyncAdapter.this.startSync(new SyncContext(syncContext), account, extras);
- }
-
- public void cancelSync() throws RemoteException {
- SyncAdapter.this.cancelSync();
- }
- }
-
- Transport mTransport = new Transport();
-
- /**
- * Get the Transport object. (note this is package private).
- */
- final ISyncAdapter getISyncAdapter()
- {
- return mTransport;
- }
-
- /**
- * Initiate a sync for this account. SyncAdapter-specific parameters may
- * be specified in extras, which is guaranteed to not be null. IPC invocations
- * of this method and cancelSync() are guaranteed to be serialized.
- *
- * @param syncContext the ISyncContext used to indicate the progress of the sync. When
- * the sync is finished (successfully or not) ISyncContext.onFinished() must be called.
- * @param account the account that should be synced
- * @param extras SyncAdapter-specific parameters
- */
- public abstract void startSync(SyncContext syncContext, String account, Bundle extras);
-
- /**
- * Cancel the most recently initiated sync. Due to race conditions, this may arrive
- * after the ISyncContext.onFinished() for that sync was called. IPC invocations
- * of this method and startSync() are guaranteed to be serialized.
- */
- public abstract void cancelSync();
-}
diff --git a/core/java/android/content/SyncContext.java b/core/java/android/content/SyncContext.java
deleted file mode 100644
index f4faa04..0000000
--- a/core/java/android/content/SyncContext.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.os.RemoteException;
-import android.os.SystemClock;
-
-/**
- * @hide
- */
-public class SyncContext {
- private ISyncContext mSyncContext;
- private long mLastHeartbeatSendTime;
-
- private static final long HEARTBEAT_SEND_INTERVAL_IN_MS = 1000;
-
- public SyncContext(ISyncContext syncContextInterface) {
- mSyncContext = syncContextInterface;
- mLastHeartbeatSendTime = 0;
- }
-
- /**
- * Call to update the status text for this sync. This internally invokes
- * {@link #updateHeartbeat}, so it also takes the place of a call to that.
- *
- * @param message the current status message for this sync
- */
- public void setStatusText(String message) {
- updateHeartbeat();
- }
-
- /**
- * Call to indicate that the SyncAdapter is making progress. E.g., if this SyncAdapter
- * downloads or sends records to/from the server, this may be called after each record
- * is downloaded or uploaded.
- */
- public void updateHeartbeat() {
- final long now = SystemClock.elapsedRealtime();
- if (now < mLastHeartbeatSendTime + HEARTBEAT_SEND_INTERVAL_IN_MS) return;
- try {
- mLastHeartbeatSendTime = now;
- mSyncContext.sendHeartbeat();
- } catch (RemoteException e) {
- // this should never happen
- }
- }
-
- public void onFinished(SyncResult result) {
- try {
- mSyncContext.onFinished(result);
- } catch (RemoteException e) {
- // this should never happen
- }
- }
-
- public ISyncContext getISyncContext() {
- return mSyncContext;
- }
-}
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
deleted file mode 100644
index 96470c3..0000000
--- a/core/java/android/content/SyncManager.java
+++ /dev/null
@@ -1,2175 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import com.google.android.collect.Maps;
-
-import com.android.internal.R;
-import com.android.internal.util.ArrayUtils;
-
-import android.accounts.AccountMonitor;
-import android.accounts.AccountMonitorListener;
-import android.app.AlarmManager;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ResolveInfo;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Parcel;
-import android.os.PowerManager;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.preference.Preference;
-import android.preference.PreferenceGroup;
-import android.provider.Sync;
-import android.provider.Settings;
-import android.provider.Sync.History;
-import android.text.TextUtils;
-import android.text.format.DateUtils;
-import android.text.format.Time;
-import android.util.Config;
-import android.util.EventLog;
-import android.util.Log;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.PriorityQueue;
-import java.util.Random;
-import java.util.Observer;
-import java.util.Observable;
-
-/**
- * @hide
- */
-class SyncManager {
- private static final String TAG = "SyncManager";
-
- // used during dumping of the Sync history
- private static final long MILLIS_IN_HOUR = 1000 * 60 * 60;
- private static final long MILLIS_IN_DAY = MILLIS_IN_HOUR * 24;
- private static final long MILLIS_IN_WEEK = MILLIS_IN_DAY * 7;
- private static final long MILLIS_IN_4WEEKS = MILLIS_IN_WEEK * 4;
-
- /** Delay a sync due to local changes this long. In milliseconds */
- private static final long LOCAL_SYNC_DELAY = 30 * 1000; // 30 seconds
-
- /**
- * If a sync takes longer than this and the sync queue is not empty then we will
- * cancel it and add it back to the end of the sync queue. In milliseconds.
- */
- private static final long MAX_TIME_PER_SYNC = 5 * 60 * 1000; // 5 minutes
-
- private static final long SYNC_NOTIFICATION_DELAY = 30 * 1000; // 30 seconds
-
- /**
- * When retrying a sync for the first time use this delay. After that
- * the retry time will double until it reached MAX_SYNC_RETRY_TIME.
- * In milliseconds.
- */
- private static final long INITIAL_SYNC_RETRY_TIME_IN_MS = 30 * 1000; // 30 seconds
-
- /**
- * Default the max sync retry time to this value.
- */
- private static final long DEFAULT_MAX_SYNC_RETRY_TIME_IN_SECONDS = 60 * 60; // one hour
-
- /**
- * An error notification is sent if sync of any of the providers has been failing for this long.
- */
- private static final long ERROR_NOTIFICATION_DELAY_MS = 1000 * 60 * 10; // 10 minutes
-
- private static final String SYNC_WAKE_LOCK = "SyncManagerSyncWakeLock";
- private static final String HANDLE_SYNC_ALARM_WAKE_LOCK = "SyncManagerHandleSyncAlarmWakeLock";
-
- private Context mContext;
- private ContentResolver mContentResolver;
-
- private String mStatusText = "";
- private long mHeartbeatTime = 0;
-
- private AccountMonitor mAccountMonitor;
-
- private volatile String[] mAccounts = null;
-
- volatile private PowerManager.WakeLock mSyncWakeLock;
- volatile private PowerManager.WakeLock mHandleAlarmWakeLock;
- volatile private boolean mDataConnectionIsConnected = false;
- volatile private boolean mStorageIsLow = false;
- private Sync.Settings.QueryMap mSyncSettings;
-
- private final NotificationManager mNotificationMgr;
- private AlarmManager mAlarmService = null;
- private HandlerThread mSyncThread;
-
- private volatile IPackageManager mPackageManager;
-
- private final SyncStorageEngine mSyncStorageEngine;
- private final SyncQueue mSyncQueue;
-
- private ActiveSyncContext mActiveSyncContext = null;
-
- // set if the sync error indicator should be reported.
- private boolean mNeedSyncErrorNotification = false;
- // set if the sync active indicator should be reported
- private boolean mNeedSyncActiveNotification = false;
-
- private volatile boolean mSyncPollInitialized;
- private final PendingIntent mSyncAlarmIntent;
- private final PendingIntent mSyncPollAlarmIntent;
-
- private BroadcastReceiver mStorageIntentReceiver =
- new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- ensureContentResolver();
- String action = intent.getAction();
- if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(action)) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Internal storage is low.");
- }
- mStorageIsLow = true;
- cancelActiveSync(null /* no url */);
- } else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Internal storage is ok.");
- }
- mStorageIsLow = false;
- sendCheckAlarmsMessage();
- }
- }
- };
-
- private BroadcastReceiver mConnectivityIntentReceiver =
- new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- NetworkInfo networkInfo =
- intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
- NetworkInfo.State state = (networkInfo == null ? NetworkInfo.State.UNKNOWN :
- networkInfo.getState());
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "received connectivity action. network info: " + networkInfo);
- }
-
- // only pay attention to the CONNECTED and DISCONNECTED states.
- // if connected, we are connected.
- // if disconnected, we may not be connected. in some cases, we may be connected on
- // a different network.
- // e.g., if switching from GPRS to WiFi, we may receive the CONNECTED to WiFi and
- // DISCONNECTED for GPRS in any order. if we receive the CONNECTED first, and then
- // a DISCONNECTED, we want to make sure we set mDataConnectionIsConnected to true
- // since we still have a WiFi connection.
- switch (state) {
- case CONNECTED:
- mDataConnectionIsConnected = true;
- break;
- case DISCONNECTED:
- if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)) {
- mDataConnectionIsConnected = false;
- } else {
- mDataConnectionIsConnected = true;
- }
- break;
- default:
- // ignore the rest of the states -- leave our boolean alone.
- }
- if (mDataConnectionIsConnected) {
- initializeSyncPoll();
- sendCheckAlarmsMessage();
- }
- }
- };
-
- private static final String ACTION_SYNC_ALARM = "android.content.syncmanager.SYNC_ALARM";
- private static final String SYNC_POLL_ALARM = "android.content.syncmanager.SYNC_POLL_ALARM";
- private final SyncHandler mSyncHandler;
-
- private static final String[] SYNC_ACTIVE_PROJECTION = new String[]{
- Sync.Active.ACCOUNT,
- Sync.Active.AUTHORITY,
- Sync.Active.START_TIME,
- };
-
- private static final String[] SYNC_PENDING_PROJECTION = new String[]{
- Sync.Pending.ACCOUNT,
- Sync.Pending.AUTHORITY
- };
-
- private static final int MAX_SYNC_POLL_DELAY_SECONDS = 36 * 60 * 60; // 36 hours
- private static final int MIN_SYNC_POLL_DELAY_SECONDS = 24 * 60 * 60; // 24 hours
-
- private static final String SYNCMANAGER_PREFS_FILENAME = "/data/system/syncmanager.prefs";
-
- public SyncManager(Context context, boolean factoryTest) {
- // Initialize the SyncStorageEngine first, before registering observers
- // and creating threads and so on; it may fail if the disk is full.
- SyncStorageEngine.init(context);
- mSyncStorageEngine = SyncStorageEngine.getSingleton();
- mSyncQueue = new SyncQueue(mSyncStorageEngine);
-
- mContext = context;
-
- mSyncThread = new HandlerThread("SyncHandlerThread", Process.THREAD_PRIORITY_BACKGROUND);
- mSyncThread.start();
- mSyncHandler = new SyncHandler(mSyncThread.getLooper());
-
- mPackageManager = null;
-
- mSyncAlarmIntent = PendingIntent.getBroadcast(
- mContext, 0 /* ignored */, new Intent(ACTION_SYNC_ALARM), 0);
-
- mSyncPollAlarmIntent = PendingIntent.getBroadcast(
- mContext, 0 /* ignored */, new Intent(SYNC_POLL_ALARM), 0);
-
- IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
- context.registerReceiver(mConnectivityIntentReceiver, intentFilter);
-
- intentFilter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW);
- intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
- context.registerReceiver(mStorageIntentReceiver, intentFilter);
-
- if (!factoryTest) {
- mNotificationMgr = (NotificationManager)
- context.getSystemService(Context.NOTIFICATION_SERVICE);
- context.registerReceiver(new SyncAlarmIntentReceiver(),
- new IntentFilter(ACTION_SYNC_ALARM));
- } else {
- mNotificationMgr = null;
- }
- PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- mSyncWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, SYNC_WAKE_LOCK);
- mSyncWakeLock.setReferenceCounted(false);
-
- // This WakeLock is used to ensure that we stay awake between the time that we receive
- // a sync alarm notification and when we finish processing it. We need to do this
- // because we don't do the work in the alarm handler, rather we do it in a message
- // handler.
- mHandleAlarmWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
- HANDLE_SYNC_ALARM_WAKE_LOCK);
- mHandleAlarmWakeLock.setReferenceCounted(false);
-
- if (!factoryTest) {
- AccountMonitorListener listener = new AccountMonitorListener() {
- public void onAccountsUpdated(String[] accounts) {
- final boolean hadAccountsAlready = mAccounts != null;
- // copy the accounts into a new array and change mAccounts to point to it
- String[] newAccounts = new String[accounts.length];
- System.arraycopy(accounts, 0, newAccounts, 0, accounts.length);
- mAccounts = newAccounts;
-
- // if a sync is in progress yet it is no longer in the accounts list, cancel it
- ActiveSyncContext activeSyncContext = mActiveSyncContext;
- if (activeSyncContext != null) {
- if (!ArrayUtils.contains(newAccounts,
- activeSyncContext.mSyncOperation.account)) {
- Log.d(TAG, "canceling sync since the account has been removed");
- sendSyncFinishedOrCanceledMessage(activeSyncContext,
- null /* no result since this is a cancel */);
- }
- }
-
- // we must do this since we don't bother scheduling alarms when
- // the accounts are not set yet
- sendCheckAlarmsMessage();
-
- mSyncStorageEngine.doDatabaseCleanup(accounts);
-
- if (hadAccountsAlready && mAccounts.length > 0) {
- // request a sync so that if the password was changed we will retry any sync
- // that failed when it was wrong
- startSync(null /* all providers */, null /* no extras */);
- }
- }
- };
- mAccountMonitor = new AccountMonitor(context, listener);
- }
- }
-
- private synchronized void initializeSyncPoll() {
- if (mSyncPollInitialized) return;
- mSyncPollInitialized = true;
-
- mContext.registerReceiver(new SyncPollAlarmReceiver(), new IntentFilter(SYNC_POLL_ALARM));
-
- // load the next poll time from shared preferences
- long absoluteAlarmTime = readSyncPollTime();
-
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "initializeSyncPoll: absoluteAlarmTime is " + absoluteAlarmTime);
- }
-
- // Convert absoluteAlarmTime to elapsed realtime. If this time was in the past then
- // schedule the poll immediately, if it is too far in the future then cap it at
- // MAX_SYNC_POLL_DELAY_SECONDS.
- long absoluteNow = System.currentTimeMillis();
- long relativeNow = SystemClock.elapsedRealtime();
- long relativeAlarmTime = relativeNow;
- if (absoluteAlarmTime > absoluteNow) {
- long delayInMs = absoluteAlarmTime - absoluteNow;
- final int maxDelayInMs = MAX_SYNC_POLL_DELAY_SECONDS * 1000;
- if (delayInMs > maxDelayInMs) {
- delayInMs = MAX_SYNC_POLL_DELAY_SECONDS * 1000;
- }
- relativeAlarmTime += delayInMs;
- }
-
- // schedule an alarm for the next poll time
- scheduleSyncPollAlarm(relativeAlarmTime);
- }
-
- private void scheduleSyncPollAlarm(long relativeAlarmTime) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "scheduleSyncPollAlarm: relativeAlarmTime is " + relativeAlarmTime
- + ", now is " + SystemClock.elapsedRealtime()
- + ", delay is " + (relativeAlarmTime - SystemClock.elapsedRealtime()));
- }
- ensureAlarmService();
- mAlarmService.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, relativeAlarmTime,
- mSyncPollAlarmIntent);
- }
-
- /**
- * Return a random value v that satisfies minValue <= v < maxValue. The difference between
- * maxValue and minValue must be less than Integer.MAX_VALUE.
- */
- private long jitterize(long minValue, long maxValue) {
- Random random = new Random(SystemClock.elapsedRealtime());
- long spread = maxValue - minValue;
- if (spread > Integer.MAX_VALUE) {
- throw new IllegalArgumentException("the difference between the maxValue and the "
- + "minValue must be less than " + Integer.MAX_VALUE);
- }
- return minValue + random.nextInt((int)spread);
- }
-
- private void handleSyncPollAlarm() {
- // determine the next poll time
- long delayMs = jitterize(MIN_SYNC_POLL_DELAY_SECONDS, MAX_SYNC_POLL_DELAY_SECONDS) * 1000;
- long nextRelativePollTimeMs = SystemClock.elapsedRealtime() + delayMs;
-
- if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "handleSyncPollAlarm: delay " + delayMs);
-
- // write the absolute time to shared preferences
- writeSyncPollTime(System.currentTimeMillis() + delayMs);
-
- // schedule an alarm for the next poll time
- scheduleSyncPollAlarm(nextRelativePollTimeMs);
-
- // perform a poll
- scheduleSync(null /* sync all syncable providers */, new Bundle(), 0 /* no delay */);
- }
-
- private void writeSyncPollTime(long when) {
- File f = new File(SYNCMANAGER_PREFS_FILENAME);
- DataOutputStream str = null;
- try {
- str = new DataOutputStream(new FileOutputStream(f));
- str.writeLong(when);
- } catch (FileNotFoundException e) {
- Log.w(TAG, "error writing to file " + f, e);
- } catch (IOException e) {
- Log.w(TAG, "error writing to file " + f, e);
- } finally {
- if (str != null) {
- try {
- str.close();
- } catch (IOException e) {
- Log.w(TAG, "error closing file " + f, e);
- }
- }
- }
- }
-
- private long readSyncPollTime() {
- File f = new File(SYNCMANAGER_PREFS_FILENAME);
-
- DataInputStream str = null;
- try {
- str = new DataInputStream(new FileInputStream(f));
- return str.readLong();
- } catch (FileNotFoundException e) {
- writeSyncPollTime(0);
- } catch (IOException e) {
- Log.w(TAG, "error reading file " + f, e);
- } finally {
- if (str != null) {
- try {
- str.close();
- } catch (IOException e) {
- Log.w(TAG, "error closing file " + f, e);
- }
- }
- }
- return 0;
- }
-
- public ActiveSyncContext getActiveSyncContext() {
- return mActiveSyncContext;
- }
-
- private Sync.Settings.QueryMap getSyncSettings() {
- if (mSyncSettings == null) {
- mSyncSettings = new Sync.Settings.QueryMap(mContext.getContentResolver(), true,
- new Handler());
- mSyncSettings.addObserver(new Observer(){
- public void update(Observable o, Object arg) {
- // force the sync loop to run if the settings change
- sendCheckAlarmsMessage();
- }
- });
- }
- return mSyncSettings;
- }
-
- private void ensureContentResolver() {
- if (mContentResolver == null) {
- mContentResolver = mContext.getContentResolver();
- }
- }
-
- private void ensureAlarmService() {
- if (mAlarmService == null) {
- mAlarmService = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
- }
- }
-
- public String getSyncingAccount() {
- ActiveSyncContext activeSyncContext = mActiveSyncContext;
- return (activeSyncContext != null) ? activeSyncContext.mSyncOperation.account : null;
- }
-
- /**
- * Returns whether or not sync is enabled. Sync can be enabled by
- * setting the system property "ro.config.sync" to the value "yes".
- * This is normally done at boot time on builds that support sync.
- * @return true if sync is enabled
- */
- private boolean isSyncEnabled() {
- // Require the precise value "yes" to discourage accidental activation.
- return "yes".equals(SystemProperties.get("ro.config.sync"));
- }
-
- /**
- * Initiate a sync. This can start a sync for all providers
- * (pass null to url, set onlyTicklable to false), only those
- * providers that are marked as ticklable (pass null to url,
- * set onlyTicklable to true), or a specific provider (set url
- * to the content url of the provider).
- *
- * <p>If the ContentResolver.SYNC_EXTRAS_UPLOAD boolean in extras is
- * true then initiate a sync that just checks for local changes to send
- * to the server, otherwise initiate a sync that first gets any
- * changes from the server before sending local changes back to
- * the server.
- *
- * <p>If a specific provider is being synced (the url is non-null)
- * then the extras can contain SyncAdapter-specific information
- * to control what gets synced (e.g. which specific feed to sync).
- *
- * <p>You'll start getting callbacks after this.
- *
- * @param url The Uri of a specific provider to be synced, or
- * null to sync all providers.
- * @param extras a Map of SyncAdapter-specific information to control
-* syncs of a specific provider. Can be null. Is ignored
-* if the url is null.
- * @param delay how many milliseconds in the future to wait before performing this
- * sync. -1 means to make this the next sync to perform.
- */
- public void scheduleSync(Uri url, Bundle extras, long delay) {
- boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
- if (isLoggable) {
- Log.v(TAG, "scheduleSync:"
- + " delay " + delay
- + ", url " + ((url == null) ? "(null)" : url)
- + ", extras " + ((extras == null) ? "(null)" : extras));
- }
-
- if (!isSyncEnabled()) {
- if (isLoggable) {
- Log.v(TAG, "not syncing because sync is disabled");
- }
- setStatusText("Sync is disabled.");
- return;
- }
-
- if (mAccounts == null) setStatusText("The accounts aren't known yet.");
- if (!mDataConnectionIsConnected) setStatusText("No data connection");
- if (mStorageIsLow) setStatusText("Memory low");
-
- if (extras == null) extras = new Bundle();
-
- Boolean expedited = extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
- if (expedited) {
- delay = -1; // this means schedule at the front of the queue
- }
-
- String[] accounts;
- String accountFromExtras = extras.getString(ContentResolver.SYNC_EXTRAS_ACCOUNT);
- if (!TextUtils.isEmpty(accountFromExtras)) {
- accounts = new String[]{accountFromExtras};
- } else {
- // if the accounts aren't configured yet then we can't support an account-less
- // sync request
- accounts = mAccounts;
- if (accounts == null) {
- // not ready yet
- if (isLoggable) {
- Log.v(TAG, "scheduleSync: no accounts yet, dropping");
- }
- return;
- }
- if (accounts.length == 0) {
- if (isLoggable) {
- Log.v(TAG, "scheduleSync: no accounts configured, dropping");
- }
- setStatusText("No accounts are configured.");
- return;
- }
- }
-
- final boolean uploadOnly = extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false);
- final boolean force = extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false);
-
- int source;
- if (uploadOnly) {
- source = Sync.History.SOURCE_LOCAL;
- } else if (force) {
- source = Sync.History.SOURCE_USER;
- } else if (url == null) {
- source = Sync.History.SOURCE_POLL;
- } else {
- // this isn't strictly server, since arbitrary callers can (and do) request
- // a non-forced two-way sync on a specific url
- source = Sync.History.SOURCE_SERVER;
- }
-
- List<String> names = new ArrayList<String>();
- List<ProviderInfo> providers = new ArrayList<ProviderInfo>();
- populateProvidersList(url, names, providers);
-
- final int numProviders = providers.size();
- for (int i = 0; i < numProviders; i++) {
- if (!providers.get(i).isSyncable) continue;
- final String name = names.get(i);
- for (String account : accounts) {
- scheduleSyncOperation(new SyncOperation(account, source, name, extras, delay));
- // TODO: remove this when Calendar supports multiple accounts. Until then
- // pretend that only the first account exists when syncing calendar.
- if ("calendar".equals(name)) {
- break;
- }
- }
- }
- }
-
- private void setStatusText(String message) {
- mStatusText = message;
- }
-
- private void populateProvidersList(Uri url, List<String> names, List<ProviderInfo> providers) {
- try {
- final IPackageManager packageManager = getPackageManager();
- if (url == null) {
- packageManager.querySyncProviders(names, providers);
- } else {
- final String authority = url.getAuthority();
- ProviderInfo info = packageManager.resolveContentProvider(url.getAuthority(), 0);
- if (info != null) {
- // only set this provider if the requested authority is the primary authority
- String[] providerNames = info.authority.split(";");
- if (url.getAuthority().equals(providerNames[0])) {
- names.add(authority);
- providers.add(info);
- }
- }
- }
- } catch (RemoteException ex) {
- // we should really never get this, but if we do then clear the lists, which
- // will result in the dropping of the sync request
- Log.e(TAG, "error trying to get the ProviderInfo for " + url, ex);
- names.clear();
- providers.clear();
- }
- }
-
- public void scheduleLocalSync(Uri url) {
- final Bundle extras = new Bundle();
- extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
- scheduleSync(url, extras, LOCAL_SYNC_DELAY);
- }
-
- private IPackageManager getPackageManager() {
- // Don't bother synchronizing on this. The worst that can happen is that two threads
- // can try to get the package manager at the same time but only one result gets
- // used. Since there is only one package manager in the system this doesn't matter.
- if (mPackageManager == null) {
- IBinder b = ServiceManager.getService("package");
- mPackageManager = IPackageManager.Stub.asInterface(b);
- }
- return mPackageManager;
- }
-
- /**
- * Initiate a sync for this given URL, or pass null for a full sync.
- *
- * <p>You'll start getting callbacks after this.
- *
- * @param url The Uri of a specific provider to be synced, or
- * null to sync all providers.
- * @param extras a Map of SyncAdapter specific information to control
- * syncs of a specific provider. Can be null. Is ignored
- */
- public void startSync(Uri url, Bundle extras) {
- scheduleSync(url, extras, 0 /* no delay */);
- }
-
- public void updateHeartbeatTime() {
- mHeartbeatTime = SystemClock.elapsedRealtime();
- ensureContentResolver();
- mContentResolver.notifyChange(Sync.Active.CONTENT_URI,
- null /* this change wasn't made through an observer */);
- }
-
- private void sendSyncAlarmMessage() {
- if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "sending MESSAGE_SYNC_ALARM");
- mSyncHandler.sendEmptyMessage(SyncHandler.MESSAGE_SYNC_ALARM);
- }
-
- private void sendCheckAlarmsMessage() {
- if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "sending MESSAGE_CHECK_ALARMS");
- mSyncHandler.sendEmptyMessage(SyncHandler.MESSAGE_CHECK_ALARMS);
- }
-
- private void sendSyncFinishedOrCanceledMessage(ActiveSyncContext syncContext,
- SyncResult syncResult) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "sending MESSAGE_SYNC_FINISHED");
- Message msg = mSyncHandler.obtainMessage();
- msg.what = SyncHandler.MESSAGE_SYNC_FINISHED;
- msg.obj = new SyncHandlerMessagePayload(syncContext, syncResult);
- mSyncHandler.sendMessage(msg);
- }
-
- class SyncHandlerMessagePayload {
- public final ActiveSyncContext activeSyncContext;
- public final SyncResult syncResult;
-
- SyncHandlerMessagePayload(ActiveSyncContext syncContext, SyncResult syncResult) {
- this.activeSyncContext = syncContext;
- this.syncResult = syncResult;
- }
- }
-
- class SyncAlarmIntentReceiver extends BroadcastReceiver {
- public void onReceive(Context context, Intent intent) {
- mHandleAlarmWakeLock.acquire();
- sendSyncAlarmMessage();
- }
- }
-
- class SyncPollAlarmReceiver extends BroadcastReceiver {
- public void onReceive(Context context, Intent intent) {
- handleSyncPollAlarm();
- }
- }
-
- private void rescheduleImmediately(SyncOperation syncOperation) {
- SyncOperation rescheduledSyncOperation = new SyncOperation(syncOperation);
- rescheduledSyncOperation.setDelay(0);
- scheduleSyncOperation(rescheduledSyncOperation);
- }
-
- private long rescheduleWithDelay(SyncOperation syncOperation) {
- long newDelayInMs;
-
- if (syncOperation.delay == 0) {
- // The initial delay is the jitterized INITIAL_SYNC_RETRY_TIME_IN_MS
- newDelayInMs = jitterize(INITIAL_SYNC_RETRY_TIME_IN_MS,
- (long)(INITIAL_SYNC_RETRY_TIME_IN_MS * 1.1));
- } else {
- // Subsequent delays are the double of the previous delay
- newDelayInMs = syncOperation.delay * 2;
- }
-
- // Cap the delay
- ensureContentResolver();
- long maxSyncRetryTimeInSeconds = Settings.Gservices.getLong(mContentResolver,
- Settings.Gservices.SYNC_MAX_RETRY_DELAY_IN_SECONDS,
- DEFAULT_MAX_SYNC_RETRY_TIME_IN_SECONDS);
- if (newDelayInMs > maxSyncRetryTimeInSeconds * 1000) {
- newDelayInMs = maxSyncRetryTimeInSeconds * 1000;
- }
-
- SyncOperation rescheduledSyncOperation = new SyncOperation(syncOperation);
- rescheduledSyncOperation.setDelay(newDelayInMs);
- scheduleSyncOperation(rescheduledSyncOperation);
- return newDelayInMs;
- }
-
- /**
- * Cancel the active sync if it matches the uri. The uri corresponds to the one passed
- * in to startSync().
- * @param uri If non-null, the active sync is only canceled if it matches the uri.
- * If null, any active sync is canceled.
- */
- public void cancelActiveSync(Uri uri) {
- ActiveSyncContext activeSyncContext = mActiveSyncContext;
- if (activeSyncContext != null) {
- // if a Uri was specified then only cancel the sync if it matches the the uri
- if (uri != null) {
- if (!uri.getAuthority().equals(activeSyncContext.mSyncOperation.authority)) {
- return;
- }
- }
- sendSyncFinishedOrCanceledMessage(activeSyncContext,
- null /* no result since this is a cancel */);
- }
- }
-
- /**
- * Create and schedule a SyncOperation.
- *
- * @param syncOperation the SyncOperation to schedule
- */
- public void scheduleSyncOperation(SyncOperation syncOperation) {
- // If this operation is expedited and there is a sync in progress then
- // reschedule the current operation and send a cancel for it.
- final boolean expedited = syncOperation.delay < 0;
- final ActiveSyncContext activeSyncContext = mActiveSyncContext;
- if (expedited && activeSyncContext != null) {
- final boolean activeIsExpedited = activeSyncContext.mSyncOperation.delay < 0;
- final boolean hasSameKey =
- activeSyncContext.mSyncOperation.key.equals(syncOperation.key);
- // This request is expedited and there is a sync in progress.
- // Interrupt the current sync only if it is not expedited and if it has a different
- // key than the one we are scheduling.
- if (!activeIsExpedited && !hasSameKey) {
- rescheduleImmediately(activeSyncContext.mSyncOperation);
- sendSyncFinishedOrCanceledMessage(activeSyncContext,
- null /* no result since this is a cancel */);
- }
- }
-
- boolean operationEnqueued;
- synchronized (mSyncQueue) {
- operationEnqueued = mSyncQueue.add(syncOperation);
- }
-
- if (operationEnqueued) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "scheduleSyncOperation: enqueued " + syncOperation);
- }
- sendCheckAlarmsMessage();
- } else {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "scheduleSyncOperation: dropping duplicate sync operation "
- + syncOperation);
- }
- }
- }
-
- /**
- * Remove any scheduled sync operations that match uri. The uri corresponds to the one passed
- * in to startSync().
- * @param uri If non-null, only operations that match the uri are cleared.
- * If null, all operations are cleared.
- */
- public void clearScheduledSyncOperations(Uri uri) {
- synchronized (mSyncQueue) {
- mSyncQueue.clear(null, uri != null ? uri.getAuthority() : null);
- }
- }
-
- void maybeRescheduleSync(SyncResult syncResult, SyncOperation previousSyncOperation) {
- boolean isLoggable = Log.isLoggable(TAG, Log.DEBUG);
- if (isLoggable) {
- Log.d(TAG, "encountered error(s) during the sync: " + syncResult + ", "
- + previousSyncOperation);
- }
-
- // If the operation succeeded to some extent then retry immediately.
- // If this was a two-way sync then retry soft errors with an exponential backoff.
- // If this was an upward sync then schedule a two-way sync immediately.
- // Otherwise do not reschedule.
-
- if (syncResult.madeSomeProgress()) {
- if (isLoggable) {
- Log.d(TAG, "retrying sync operation immediately because "
- + "even though it had an error it achieved some success");
- }
- rescheduleImmediately(previousSyncOperation);
- } else if (previousSyncOperation.extras.getBoolean(
- ContentResolver.SYNC_EXTRAS_UPLOAD, false)) {
- final SyncOperation newSyncOperation = new SyncOperation(previousSyncOperation);
- newSyncOperation.extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false);
- newSyncOperation.setDelay(0);
- if (Config.LOGD) {
- Log.d(TAG, "retrying sync operation as a two-way sync because an upload-only sync "
- + "encountered an error: " + previousSyncOperation);
- }
- scheduleSyncOperation(newSyncOperation);
- } else if (syncResult.hasSoftError()) {
- long delay = rescheduleWithDelay(previousSyncOperation);
- if (delay >= 0) {
- if (isLoggable) {
- Log.d(TAG, "retrying sync operation in " + delay + " ms because "
- + "it encountered a soft error: " + previousSyncOperation);
- }
- }
- } else {
- if (Config.LOGD) {
- Log.d(TAG, "not retrying sync operation because the error is a hard error: "
- + previousSyncOperation);
- }
- }
- }
-
- /**
- * Value type that represents a sync operation.
- */
- static class SyncOperation implements Comparable {
- final String account;
- int syncSource;
- String authority;
- Bundle extras;
- final String key;
- long earliestRunTime;
- long delay;
- Long rowId = null;
-
- SyncOperation(String account, int source, String authority, Bundle extras, long delay) {
- this.account = account;
- this.syncSource = source;
- this.authority = authority;
- this.extras = new Bundle(extras);
- this.setDelay(delay);
- this.key = toKey();
- }
-
- SyncOperation(SyncOperation other) {
- this.account = other.account;
- this.syncSource = other.syncSource;
- this.authority = other.authority;
- this.extras = new Bundle(other.extras);
- this.delay = other.delay;
- this.earliestRunTime = other.earliestRunTime;
- this.key = toKey();
- }
-
- public void setDelay(long delay) {
- this.delay = delay;
- if (delay >= 0) {
- this.earliestRunTime = SystemClock.elapsedRealtime() + delay;
- } else {
- this.earliestRunTime = 0;
- }
- }
-
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("authority: ").append(authority);
- sb.append(" account: ").append(account);
- sb.append(" extras: ");
- extrasToStringBuilder(extras, sb);
- sb.append(" syncSource: ").append(syncSource);
- sb.append(" when: ").append(earliestRunTime);
- sb.append(" delay: ").append(delay);
- sb.append(" key: {").append(key).append("}");
- if (rowId != null) sb.append(" rowId: ").append(rowId);
- return sb.toString();
- }
-
- private String toKey() {
- StringBuilder sb = new StringBuilder();
- sb.append("authority: ").append(authority);
- sb.append(" account: ").append(account);
- sb.append(" extras: ");
- extrasToStringBuilder(extras, sb);
- return sb.toString();
- }
-
- private static void extrasToStringBuilder(Bundle bundle, StringBuilder sb) {
- sb.append("[");
- for (String key : bundle.keySet()) {
- sb.append(key).append("=").append(bundle.get(key)).append(" ");
- }
- sb.append("]");
- }
-
- public int compareTo(Object o) {
- SyncOperation other = (SyncOperation)o;
- if (earliestRunTime == other.earliestRunTime) {
- return 0;
- }
- return (earliestRunTime < other.earliestRunTime) ? -1 : 1;
- }
- }
-
- /**
- * @hide
- */
- class ActiveSyncContext extends ISyncContext.Stub {
- final SyncOperation mSyncOperation;
- final long mHistoryRowId;
- final IContentProvider mContentProvider;
- final ISyncAdapter mSyncAdapter;
- final long mStartTime;
- long mTimeoutStartTime;
-
- public ActiveSyncContext(SyncOperation syncOperation, IContentProvider contentProvider,
- ISyncAdapter syncAdapter, long historyRowId) {
- super();
- mSyncOperation = syncOperation;
- mHistoryRowId = historyRowId;
- mContentProvider = contentProvider;
- mSyncAdapter = syncAdapter;
- mStartTime = SystemClock.elapsedRealtime();
- mTimeoutStartTime = mStartTime;
- }
-
- public void sendHeartbeat() {
- // ignore this call if it corresponds to an old sync session
- if (mActiveSyncContext == this) {
- SyncManager.this.updateHeartbeatTime();
- }
- }
-
- public void onFinished(SyncResult result) {
- // include "this" in the message so that the handler can ignore it if this
- // ActiveSyncContext is no longer the mActiveSyncContext at message handling
- // time
- sendSyncFinishedOrCanceledMessage(this, result);
- }
-
- public void toString(StringBuilder sb) {
- sb.append("startTime ").append(mStartTime)
- .append(", mTimeoutStartTime ").append(mTimeoutStartTime)
- .append(", mHistoryRowId ").append(mHistoryRowId)
- .append(", syncOperation ").append(mSyncOperation);
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- toString(sb);
- return sb.toString();
- }
- }
-
- protected void dump(FileDescriptor fd, PrintWriter pw) {
- StringBuilder sb = new StringBuilder();
- dumpSyncState(sb);
- sb.append("\n");
- if (isSyncEnabled()) {
- dumpSyncHistory(sb);
- }
- pw.println(sb.toString());
- }
-
- protected void dumpSyncState(StringBuilder sb) {
- sb.append("sync enabled: ").append(isSyncEnabled()).append("\n");
- sb.append("data connected: ").append(mDataConnectionIsConnected).append("\n");
- sb.append("memory low: ").append(mStorageIsLow).append("\n");
-
- final String[] accounts = mAccounts;
- sb.append("accounts: ");
- if (accounts != null) {
- sb.append(accounts.length);
- } else {
- sb.append("none");
- }
- sb.append("\n");
- final long now = SystemClock.elapsedRealtime();
- sb.append("now: ").append(now).append("\n");
- sb.append("uptime: ").append(DateUtils.formatElapsedTime(now/1000)).append(" (HH:MM:SS)\n");
- sb.append("time spent syncing : ")
- .append(DateUtils.formatElapsedTime(
- mSyncHandler.mSyncTimeTracker.timeSpentSyncing() / 1000))
- .append(" (HH:MM:SS), sync ")
- .append(mSyncHandler.mSyncTimeTracker.mLastWasSyncing ? "" : "not ")
- .append("in progress").append("\n");
- if (mSyncHandler.mAlarmScheduleTime != null) {
- sb.append("next alarm time: ").append(mSyncHandler.mAlarmScheduleTime)
- .append(" (")
- .append(DateUtils.formatElapsedTime((mSyncHandler.mAlarmScheduleTime-now)/1000))
- .append(" (HH:MM:SS) from now)\n");
- } else {
- sb.append("no alarm is scheduled (there had better not be any pending syncs)\n");
- }
-
- sb.append("active sync: ").append(mActiveSyncContext).append("\n");
-
- sb.append("notification info: ");
- mSyncHandler.mSyncNotificationInfo.toString(sb);
- sb.append("\n");
-
- synchronized (mSyncQueue) {
- sb.append("sync queue: ");
- mSyncQueue.dump(sb);
- }
-
- Cursor c = mSyncStorageEngine.query(Sync.Active.CONTENT_URI,
- SYNC_ACTIVE_PROJECTION, null, null, null);
- sb.append("\n");
- try {
- if (c.moveToNext()) {
- final long durationInSeconds = (now - c.getLong(2)) / 1000;
- sb.append("Active sync: ").append(c.getString(0))
- .append(" ").append(c.getString(1))
- .append(", duration is ")
- .append(DateUtils.formatElapsedTime(durationInSeconds)).append(".\n");
- } else {
- sb.append("No sync is in progress.\n");
- }
- } finally {
- c.close();
- }
-
- c = mSyncStorageEngine.query(Sync.Pending.CONTENT_URI,
- SYNC_PENDING_PROJECTION, null, null, "account, authority");
- sb.append("\nPending Syncs\n");
- try {
- if (c.getCount() != 0) {
- dumpSyncPendingHeader(sb);
- while (c.moveToNext()) {
- dumpSyncPendingRow(sb, c);
- }
- dumpSyncPendingFooter(sb);
- } else {
- sb.append("none\n");
- }
- } finally {
- c.close();
- }
-
- String currentAccount = null;
- c = mSyncStorageEngine.query(Sync.Status.CONTENT_URI,
- STATUS_PROJECTION, null, null, "account, authority");
- sb.append("\nSync history by account and authority\n");
- try {
- while (c.moveToNext()) {
- if (!TextUtils.equals(currentAccount, c.getString(0))) {
- if (currentAccount != null) {
- dumpSyncHistoryFooter(sb);
- }
- currentAccount = c.getString(0);
- dumpSyncHistoryHeader(sb, currentAccount);
- }
-
- dumpSyncHistoryRow(sb, c);
- }
- if (c.getCount() > 0) dumpSyncHistoryFooter(sb);
- } finally {
- c.close();
- }
- }
-
- private void dumpSyncHistoryHeader(StringBuilder sb, String account) {
- sb.append(" Account: ").append(account).append("\n");
- sb.append(" ___________________________________________________________________________________________________________________________\n");
- sb.append(" | | num times synced | total | last success | |\n");
- sb.append(" | authority | local | poll | server | user | total | duration | source | time | result if failing |\n");
- }
-
- private static String[] STATUS_PROJECTION = new String[]{
- Sync.Status.ACCOUNT, // 0
- Sync.Status.AUTHORITY, // 1
- Sync.Status.NUM_SYNCS, // 2
- Sync.Status.TOTAL_ELAPSED_TIME, // 3
- Sync.Status.NUM_SOURCE_LOCAL, // 4
- Sync.Status.NUM_SOURCE_POLL, // 5
- Sync.Status.NUM_SOURCE_SERVER, // 6
- Sync.Status.NUM_SOURCE_USER, // 7
- Sync.Status.LAST_SUCCESS_SOURCE, // 8
- Sync.Status.LAST_SUCCESS_TIME, // 9
- Sync.Status.LAST_FAILURE_SOURCE, // 10
- Sync.Status.LAST_FAILURE_TIME, // 11
- Sync.Status.LAST_FAILURE_MESG // 12
- };
-
- private void dumpSyncHistoryRow(StringBuilder sb, Cursor c) {
- boolean hasSuccess = !c.isNull(9);
- boolean hasFailure = !c.isNull(11);
- Time timeSuccess = new Time();
- if (hasSuccess) timeSuccess.set(c.getLong(9));
- Time timeFailure = new Time();
- if (hasFailure) timeFailure.set(c.getLong(11));
- sb.append(String.format(" | %-15s | %5d | %5d | %6d | %5d | %5d | %8s | %7s | %19s | %19s |\n",
- c.getString(1),
- c.getLong(4),
- c.getLong(5),
- c.getLong(6),
- c.getLong(7),
- c.getLong(2),
- DateUtils.formatElapsedTime(c.getLong(3)/1000),
- hasSuccess ? Sync.History.SOURCES[c.getInt(8)] : "",
- hasSuccess ? timeSuccess.format("%Y-%m-%d %H:%M:%S") : "",
- hasFailure ? History.mesgToString(c.getString(12)) : ""));
- }
-
- private void dumpSyncHistoryFooter(StringBuilder sb) {
- sb.append(" |___________________________________________________________________________________________________________________________|\n");
- }
-
- private void dumpSyncPendingHeader(StringBuilder sb) {
- sb.append(" ____________________________________________________\n");
- sb.append(" | account | authority |\n");
- }
-
- private void dumpSyncPendingRow(StringBuilder sb, Cursor c) {
- sb.append(String.format(" | %-30s | %-15s |\n", c.getString(0), c.getString(1)));
- }
-
- private void dumpSyncPendingFooter(StringBuilder sb) {
- sb.append(" |__________________________________________________|\n");
- }
-
- protected void dumpSyncHistory(StringBuilder sb) {
- Cursor c = mSyncStorageEngine.query(Sync.History.CONTENT_URI, null, "event=?",
- new String[]{String.valueOf(Sync.History.EVENT_STOP)},
- Sync.HistoryColumns.EVENT_TIME + " desc");
- try {
- long numSyncsLastHour = 0, durationLastHour = 0;
- long numSyncsLastDay = 0, durationLastDay = 0;
- long numSyncsLastWeek = 0, durationLastWeek = 0;
- long numSyncsLast4Weeks = 0, durationLast4Weeks = 0;
- long numSyncsTotal = 0, durationTotal = 0;
-
- long now = System.currentTimeMillis();
- int indexEventTime = c.getColumnIndexOrThrow(Sync.History.EVENT_TIME);
- int indexElapsedTime = c.getColumnIndexOrThrow(Sync.History.ELAPSED_TIME);
- while (c.moveToNext()) {
- long duration = c.getLong(indexElapsedTime);
- long endTime = c.getLong(indexEventTime) + duration;
- long millisSinceStart = now - endTime;
- numSyncsTotal++;
- durationTotal += duration;
- if (millisSinceStart < MILLIS_IN_HOUR) {
- numSyncsLastHour++;
- durationLastHour += duration;
- }
- if (millisSinceStart < MILLIS_IN_DAY) {
- numSyncsLastDay++;
- durationLastDay += duration;
- }
- if (millisSinceStart < MILLIS_IN_WEEK) {
- numSyncsLastWeek++;
- durationLastWeek += duration;
- }
- if (millisSinceStart < MILLIS_IN_4WEEKS) {
- numSyncsLast4Weeks++;
- durationLast4Weeks += duration;
- }
- }
- dumpSyncIntervalHeader(sb);
- dumpSyncInterval(sb, "hour", MILLIS_IN_HOUR, numSyncsLastHour, durationLastHour);
- dumpSyncInterval(sb, "day", MILLIS_IN_DAY, numSyncsLastDay, durationLastDay);
- dumpSyncInterval(sb, "week", MILLIS_IN_WEEK, numSyncsLastWeek, durationLastWeek);
- dumpSyncInterval(sb, "4 weeks",
- MILLIS_IN_4WEEKS, numSyncsLast4Weeks, durationLast4Weeks);
- dumpSyncInterval(sb, "total", 0, numSyncsTotal, durationTotal);
- dumpSyncIntervalFooter(sb);
- } finally {
- c.close();
- }
- }
-
- private void dumpSyncIntervalHeader(StringBuilder sb) {
- sb.append("Sync Stats\n");
- sb.append(" ___________________________________________________________\n");
- sb.append(" | | | duration in sec | |\n");
- sb.append(" | interval | count | average | total | % of interval |\n");
- }
-
- private void dumpSyncInterval(StringBuilder sb, String label,
- long interval, long numSyncs, long duration) {
- sb.append(String.format(" | %-8s | %6d | %8.1f | %8.1f",
- label, numSyncs, ((float)duration/numSyncs)/1000, (float)duration/1000));
- if (interval > 0) {
- sb.append(String.format(" | %13.2f |\n", ((float)duration/interval)*100.0));
- } else {
- sb.append(String.format(" | %13s |\n", "na"));
- }
- }
-
- private void dumpSyncIntervalFooter(StringBuilder sb) {
- sb.append(" |_________________________________________________________|\n");
- }
-
- /**
- * A helper object to keep track of the time we have spent syncing since the last boot
- */
- private class SyncTimeTracker {
- /** True if a sync was in progress on the most recent call to update() */
- boolean mLastWasSyncing = false;
- /** Used to track when lastWasSyncing was last set */
- long mWhenSyncStarted = 0;
- /** The cumulative time we have spent syncing */
- private long mTimeSpentSyncing;
-
- /** Call to let the tracker know that the sync state may have changed */
- public synchronized void update() {
- final boolean isSyncInProgress = mActiveSyncContext != null;
- if (isSyncInProgress == mLastWasSyncing) return;
- final long now = SystemClock.elapsedRealtime();
- if (isSyncInProgress) {
- mWhenSyncStarted = now;
- } else {
- mTimeSpentSyncing += now - mWhenSyncStarted;
- }
- mLastWasSyncing = isSyncInProgress;
- }
-
- /** Get how long we have been syncing, in ms */
- public synchronized long timeSpentSyncing() {
- if (!mLastWasSyncing) return mTimeSpentSyncing;
-
- final long now = SystemClock.elapsedRealtime();
- return mTimeSpentSyncing + (now - mWhenSyncStarted);
- }
- }
-
- /**
- * Handles SyncOperation Messages that are posted to the associated
- * HandlerThread.
- */
- class SyncHandler extends Handler {
- // Messages that can be sent on mHandler
- private static final int MESSAGE_SYNC_FINISHED = 1;
- private static final int MESSAGE_SYNC_ALARM = 2;
- private static final int MESSAGE_CHECK_ALARMS = 3;
-
- public final SyncNotificationInfo mSyncNotificationInfo = new SyncNotificationInfo();
- private Long mAlarmScheduleTime = null;
- public final SyncTimeTracker mSyncTimeTracker = new SyncTimeTracker();
-
- // used to track if we have installed the error notification so that we don't reinstall
- // it if sync is still failing
- private boolean mErrorNotificationInstalled = false;
-
- /**
- * Used to keep track of whether a sync notification is active and who it is for.
- */
- class SyncNotificationInfo {
- // only valid if isActive is true
- public String account;
-
- // only valid if isActive is true
- public String authority;
-
- // true iff the notification manager has been asked to send the notification
- public boolean isActive = false;
-
- // Set when we transition from not running a sync to running a sync, and cleared on
- // the opposite transition.
- public Long startTime = null;
-
- public void toString(StringBuilder sb) {
- sb.append("account ").append(account)
- .append(", authority ").append(authority)
- .append(", isActive ").append(isActive)
- .append(", startTime ").append(startTime);
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- toString(sb);
- return sb.toString();
- }
- }
-
- public SyncHandler(Looper looper) {
- super(looper);
- }
-
- public void handleMessage(Message msg) {
- handleSyncHandlerMessage(msg);
- }
-
- private void handleSyncHandlerMessage(Message msg) {
- try {
- switch (msg.what) {
- case SyncHandler.MESSAGE_SYNC_FINISHED:
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_SYNC_FINISHED");
- }
- SyncHandlerMessagePayload payload = (SyncHandlerMessagePayload)msg.obj;
- if (mActiveSyncContext != payload.activeSyncContext) {
- if (Config.LOGD) {
- Log.d(TAG, "handleSyncHandlerMessage: sync context doesn't match, "
- + "dropping: mActiveSyncContext " + mActiveSyncContext
- + " != " + payload.activeSyncContext);
- }
- return;
- }
- runSyncFinishedOrCanceled(payload.syncResult);
-
- // since we are no longer syncing, check if it is time to start a new sync
- runStateIdle();
- break;
-
- case SyncHandler.MESSAGE_SYNC_ALARM: {
- boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
- if (isLoggable) {
- Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_SYNC_ALARM");
- }
- mAlarmScheduleTime = null;
- try {
- if (mActiveSyncContext != null) {
- if (isLoggable) {
- Log.v(TAG, "handleSyncHandlerMessage: sync context is active");
- }
- runStateSyncing();
- }
-
- // if the above call to runStateSyncing() resulted in the end of a sync,
- // check if it is time to start a new sync
- if (mActiveSyncContext == null) {
- if (isLoggable) {
- Log.v(TAG, "handleSyncHandlerMessage: "
- + "sync context is not active");
- }
- runStateIdle();
- }
- } finally {
- mHandleAlarmWakeLock.release();
- }
- break;
- }
-
- case SyncHandler.MESSAGE_CHECK_ALARMS:
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_CHECK_ALARMS");
- }
- // we do all the work for this case in the finally block
- break;
- }
- } finally {
- final boolean isSyncInProgress = mActiveSyncContext != null;
- if (!isSyncInProgress) {
- mSyncWakeLock.release();
- }
- manageSyncNotification();
- manageErrorNotification();
- manageSyncAlarm();
- mSyncTimeTracker.update();
- }
- }
-
- private void runStateSyncing() {
- // if the sync timeout has been reached then cancel it
-
- ActiveSyncContext activeSyncContext = mActiveSyncContext;
-
- final long now = SystemClock.elapsedRealtime();
- if (now > activeSyncContext.mTimeoutStartTime + MAX_TIME_PER_SYNC) {
- SyncOperation nextSyncOperation;
- synchronized (mSyncQueue) {
- nextSyncOperation = mSyncQueue.head();
- }
- if (nextSyncOperation != null && nextSyncOperation.earliestRunTime <= now) {
- if (Config.LOGD) {
- Log.d(TAG, "canceling and rescheduling sync because it ran too long: "
- + activeSyncContext.mSyncOperation);
- }
- rescheduleImmediately(activeSyncContext.mSyncOperation);
- sendSyncFinishedOrCanceledMessage(activeSyncContext,
- null /* no result since this is a cancel */);
- } else {
- activeSyncContext.mTimeoutStartTime = now + MAX_TIME_PER_SYNC;
- }
- }
-
- // no need to schedule an alarm, as that will be done by our caller.
- }
-
- private void runStateIdle() {
- boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
- if (isLoggable) Log.v(TAG, "runStateIdle");
-
- // If we aren't ready to run (e.g. the data connection is down), get out.
- if (!mDataConnectionIsConnected) {
- if (isLoggable) {
- Log.v(TAG, "runStateIdle: no data connection, skipping");
- }
- setStatusText("No data connection");
- return;
- }
-
- if (mStorageIsLow) {
- if (isLoggable) {
- Log.v(TAG, "runStateIdle: memory low, skipping");
- }
- setStatusText("Memory low");
- return;
- }
-
- // If the accounts aren't known yet then we aren't ready to run. We will be kicked
- // when the account lookup request does complete.
- String[] accounts = mAccounts;
- if (accounts == null) {
- if (isLoggable) {
- Log.v(TAG, "runStateIdle: accounts not known, skipping");
- }
- setStatusText("Accounts not known yet");
- return;
- }
-
- // Otherwise consume SyncOperations from the head of the SyncQueue until one is
- // found that is runnable (not disabled, etc). If that one is ready to run then
- // start it, otherwise just get out.
- SyncOperation syncOperation;
- final Sync.Settings.QueryMap syncSettings = getSyncSettings();
- final ConnectivityManager connManager = (ConnectivityManager)
- mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- final boolean backgroundDataSetting = connManager.getBackgroundDataSetting();
- synchronized (mSyncQueue) {
- while (true) {
- syncOperation = mSyncQueue.head();
- if (syncOperation == null) {
- if (isLoggable) {
- Log.v(TAG, "runStateIdle: no more sync operations, returning");
- }
- return;
- }
-
- // Sync is disabled, drop this operation.
- if (!isSyncEnabled()) {
- if (isLoggable) {
- Log.v(TAG, "runStateIdle: sync disabled, dropping " + syncOperation);
- }
- mSyncQueue.popHead();
- continue;
- }
-
- // skip the sync if it isn't a force and the settings are off for this provider
- final boolean force = syncOperation.extras.getBoolean(
- ContentResolver.SYNC_EXTRAS_FORCE, false);
- if (!force && (!backgroundDataSetting
- || !syncSettings.getListenForNetworkTickles()
- || !syncSettings.getSyncProviderAutomatically(
- syncOperation.authority))) {
- if (isLoggable) {
- Log.v(TAG, "runStateIdle: sync off, dropping " + syncOperation);
- }
- mSyncQueue.popHead();
- continue;
- }
-
- // skip the sync if the account of this operation no longer exists
- if (!ArrayUtils.contains(accounts, syncOperation.account)) {
- mSyncQueue.popHead();
- if (isLoggable) {
- Log.v(TAG, "runStateIdle: account not present, dropping "
- + syncOperation);
- }
- continue;
- }
-
- // go ahead and try to sync this syncOperation
- if (isLoggable) {
- Log.v(TAG, "runStateIdle: found sync candidate: " + syncOperation);
- }
- break;
- }
-
- // If the first SyncOperation isn't ready to run schedule a wakeup and
- // get out.
- final long now = SystemClock.elapsedRealtime();
- if (syncOperation.earliestRunTime > now) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "runStateIdle: the time is " + now + " yet the next "
- + "sync operation is for " + syncOperation.earliestRunTime
- + ": " + syncOperation);
- }
- return;
- }
-
- // We will do this sync. Remove it from the queue and run it outside of the
- // synchronized block.
- if (isLoggable) {
- Log.v(TAG, "runStateIdle: we are going to sync " + syncOperation);
- }
- mSyncQueue.popHead();
- }
-
- String providerName = syncOperation.authority;
- ensureContentResolver();
- IContentProvider contentProvider;
-
- // acquire the provider and update the sync history
- try {
- contentProvider = mContentResolver.acquireProvider(providerName);
- if (contentProvider == null) {
- Log.e(TAG, "Provider " + providerName + " doesn't exist");
- return;
- }
- if (contentProvider.getSyncAdapter() == null) {
- Log.e(TAG, "Provider " + providerName + " isn't syncable, " + contentProvider);
- return;
- }
- } catch (RemoteException remoteExc) {
- Log.e(TAG, "Caught a RemoteException while preparing for sync, rescheduling "
- + syncOperation, remoteExc);
- rescheduleWithDelay(syncOperation);
- return;
- } catch (RuntimeException exc) {
- Log.e(TAG, "Caught a RuntimeException while validating sync of " + providerName,
- exc);
- return;
- }
-
- final long historyRowId = insertStartSyncEvent(syncOperation);
-
- try {
- ISyncAdapter syncAdapter = contentProvider.getSyncAdapter();
- ActiveSyncContext activeSyncContext = new ActiveSyncContext(syncOperation,
- contentProvider, syncAdapter, historyRowId);
- mSyncWakeLock.acquire();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "starting sync of " + syncOperation);
- }
- syncAdapter.startSync(activeSyncContext, syncOperation.account,
- syncOperation.extras);
- mActiveSyncContext = activeSyncContext;
- mSyncStorageEngine.setActiveSync(mActiveSyncContext);
- } catch (RemoteException remoteExc) {
- if (Config.LOGD) {
- Log.d(TAG, "runStateIdle: caught a RemoteException, rescheduling", remoteExc);
- }
- mActiveSyncContext = null;
- mSyncStorageEngine.setActiveSync(mActiveSyncContext);
- rescheduleWithDelay(syncOperation);
- } catch (RuntimeException exc) {
- mActiveSyncContext = null;
- mSyncStorageEngine.setActiveSync(mActiveSyncContext);
- Log.e(TAG, "Caught a RuntimeException while starting the sync " + syncOperation,
- exc);
- }
-
- // no need to schedule an alarm, as that will be done by our caller.
- }
-
- private void runSyncFinishedOrCanceled(SyncResult syncResult) {
- boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
- if (isLoggable) Log.v(TAG, "runSyncFinishedOrCanceled");
- ActiveSyncContext activeSyncContext = mActiveSyncContext;
- mActiveSyncContext = null;
- mSyncStorageEngine.setActiveSync(mActiveSyncContext);
-
- final SyncOperation syncOperation = activeSyncContext.mSyncOperation;
-
- final long elapsedTime = SystemClock.elapsedRealtime() - activeSyncContext.mStartTime;
-
- String historyMessage;
- int downstreamActivity;
- int upstreamActivity;
- if (syncResult != null) {
- if (isLoggable) {
- Log.v(TAG, "runSyncFinishedOrCanceled: is a finished: operation "
- + syncOperation + ", result " + syncResult);
- }
-
- if (!syncResult.hasError()) {
- if (isLoggable) {
- Log.v(TAG, "finished sync operation " + syncOperation);
- }
- historyMessage = History.MESG_SUCCESS;
- // TODO: set these correctly when the SyncResult is extended to include it
- downstreamActivity = 0;
- upstreamActivity = 0;
- } else {
- maybeRescheduleSync(syncResult, syncOperation);
- if (Config.LOGD) {
- Log.d(TAG, "failed sync operation " + syncOperation);
- }
- historyMessage = Integer.toString(syncResultToErrorNumber(syncResult));
- // TODO: set these correctly when the SyncResult is extended to include it
- downstreamActivity = 0;
- upstreamActivity = 0;
- }
- } else {
- if (isLoggable) {
- Log.v(TAG, "runSyncFinishedOrCanceled: is a cancel: operation "
- + syncOperation);
- }
- try {
- activeSyncContext.mSyncAdapter.cancelSync();
- } catch (RemoteException e) {
- // we don't need to retry this in this case
- }
- historyMessage = History.MESG_CANCELED;
- downstreamActivity = 0;
- upstreamActivity = 0;
- }
-
- stopSyncEvent(activeSyncContext.mHistoryRowId, syncOperation, historyMessage,
- upstreamActivity, downstreamActivity, elapsedTime);
-
- mContentResolver.releaseProvider(activeSyncContext.mContentProvider);
-
- if (syncResult != null && syncResult.tooManyDeletions) {
- installHandleTooManyDeletesNotification(syncOperation.account,
- syncOperation.authority, syncResult.stats.numDeletes);
- } else {
- mNotificationMgr.cancel(
- syncOperation.account.hashCode() ^ syncOperation.authority.hashCode());
- }
-
- if (syncResult != null && syncResult.fullSyncRequested) {
- scheduleSyncOperation(new SyncOperation(syncOperation.account,
- syncOperation.syncSource, syncOperation.authority, new Bundle(), 0));
- }
- // no need to schedule an alarm, as that will be done by our caller.
- }
-
- /**
- * Convert the error-containing SyncResult into the Sync.History error number. Since
- * the SyncResult may indicate multiple errors at once, this method just returns the
- * most "serious" error.
- * @param syncResult the SyncResult from which to read
- * @return the most "serious" error set in the SyncResult
- * @throws IllegalStateException if the SyncResult does not indicate any errors.
- * If SyncResult.error() is true then it is safe to call this.
- */
- private int syncResultToErrorNumber(SyncResult syncResult) {
- if (syncResult.syncAlreadyInProgress) return History.ERROR_SYNC_ALREADY_IN_PROGRESS;
- if (syncResult.stats.numAuthExceptions > 0) return History.ERROR_AUTHENTICATION;
- if (syncResult.stats.numIoExceptions > 0) return History.ERROR_IO;
- if (syncResult.stats.numParseExceptions > 0) return History.ERROR_PARSE;
- if (syncResult.stats.numConflictDetectedExceptions > 0) return History.ERROR_CONFLICT;
- if (syncResult.tooManyDeletions) return History.ERROR_TOO_MANY_DELETIONS;
- if (syncResult.tooManyRetries) return History.ERROR_TOO_MANY_RETRIES;
- if (syncResult.databaseError) return History.ERROR_INTERNAL;
- throw new IllegalStateException("we are not in an error state, " + syncResult);
- }
-
- private void manageSyncNotification() {
- boolean shouldCancel;
- boolean shouldInstall;
-
- if (mActiveSyncContext == null) {
- mSyncNotificationInfo.startTime = null;
-
- // we aren't syncing. if the notification is active then remember that we need
- // to cancel it and then clear out the info
- shouldCancel = mSyncNotificationInfo.isActive;
- shouldInstall = false;
- } else {
- // we are syncing
- final SyncOperation syncOperation = mActiveSyncContext.mSyncOperation;
-
- final long now = SystemClock.elapsedRealtime();
- if (mSyncNotificationInfo.startTime == null) {
- mSyncNotificationInfo.startTime = now;
- }
-
- // cancel the notification if it is up and the authority or account is wrong
- shouldCancel = mSyncNotificationInfo.isActive &&
- (!syncOperation.authority.equals(mSyncNotificationInfo.authority)
- || !syncOperation.account.equals(mSyncNotificationInfo.account));
-
- // there are four cases:
- // - the notification is up and there is no change: do nothing
- // - the notification is up but we should cancel since it is stale:
- // need to install
- // - the notification is not up but it isn't time yet: don't install
- // - the notification is not up and it is time: need to install
-
- if (mSyncNotificationInfo.isActive) {
- shouldInstall = shouldCancel;
- } else {
- final boolean timeToShowNotification =
- now > mSyncNotificationInfo.startTime + SYNC_NOTIFICATION_DELAY;
- final boolean syncIsForced = syncOperation.extras
- .getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false);
- shouldInstall = timeToShowNotification || syncIsForced;
- }
- }
-
- if (shouldCancel && !shouldInstall) {
- mNeedSyncActiveNotification = false;
- sendSyncStateIntent();
- mSyncNotificationInfo.isActive = false;
- }
-
- if (shouldInstall) {
- SyncOperation syncOperation = mActiveSyncContext.mSyncOperation;
- mNeedSyncActiveNotification = true;
- sendSyncStateIntent();
- mSyncNotificationInfo.isActive = true;
- mSyncNotificationInfo.account = syncOperation.account;
- mSyncNotificationInfo.authority = syncOperation.authority;
- }
- }
-
- /**
- * Check if there were any long-lasting errors, if so install the error notification,
- * otherwise cancel the error notification.
- */
- private void manageErrorNotification() {
- //
- long when = mSyncStorageEngine.getInitialSyncFailureTime();
- if ((when > 0) && (when + ERROR_NOTIFICATION_DELAY_MS < System.currentTimeMillis())) {
- if (!mErrorNotificationInstalled) {
- mNeedSyncErrorNotification = true;
- sendSyncStateIntent();
- }
- mErrorNotificationInstalled = true;
- } else {
- if (mErrorNotificationInstalled) {
- mNeedSyncErrorNotification = false;
- sendSyncStateIntent();
- }
- mErrorNotificationInstalled = false;
- }
- }
-
- private void manageSyncAlarm() {
- // in each of these cases the sync loop will be kicked, which will cause this
- // method to be called again
- if (!mDataConnectionIsConnected) return;
- if (mAccounts == null) return;
- if (mStorageIsLow) return;
-
- // Compute the alarm fire time:
- // - not syncing: time of the next sync operation
- // - syncing, no notification: time from sync start to notification create time
- // - syncing, with notification: time till timeout of the active sync operation
- Long alarmTime = null;
- ActiveSyncContext activeSyncContext = mActiveSyncContext;
- if (activeSyncContext == null) {
- SyncOperation syncOperation;
- synchronized (mSyncQueue) {
- syncOperation = mSyncQueue.head();
- }
- if (syncOperation != null) {
- alarmTime = syncOperation.earliestRunTime;
- }
- } else {
- final long notificationTime =
- mSyncHandler.mSyncNotificationInfo.startTime + SYNC_NOTIFICATION_DELAY;
- final long timeoutTime =
- mActiveSyncContext.mTimeoutStartTime + MAX_TIME_PER_SYNC;
- if (mSyncHandler.mSyncNotificationInfo.isActive) {
- alarmTime = timeoutTime;
- } else {
- alarmTime = Math.min(notificationTime, timeoutTime);
- }
- }
-
- // adjust the alarmTime so that we will wake up when it is time to
- // install the error notification
- if (!mErrorNotificationInstalled) {
- long when = mSyncStorageEngine.getInitialSyncFailureTime();
- if (when > 0) {
- when += ERROR_NOTIFICATION_DELAY_MS;
- // convert when fron absolute time to elapsed run time
- long delay = when - System.currentTimeMillis();
- when = SystemClock.elapsedRealtime() + delay;
- alarmTime = alarmTime != null ? Math.min(alarmTime, when) : when;
- }
- }
-
- // determine if we need to set or cancel the alarm
- boolean shouldSet = false;
- boolean shouldCancel = false;
- final boolean alarmIsActive = mAlarmScheduleTime != null;
- final boolean needAlarm = alarmTime != null;
- if (needAlarm) {
- if (!alarmIsActive || alarmTime < mAlarmScheduleTime) {
- shouldSet = true;
- }
- } else {
- shouldCancel = alarmIsActive;
- }
-
- // set or cancel the alarm as directed
- ensureAlarmService();
- if (shouldSet) {
- mAlarmScheduleTime = alarmTime;
- mAlarmService.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime,
- mSyncAlarmIntent);
- } else if (shouldCancel) {
- mAlarmScheduleTime = null;
- mAlarmService.cancel(mSyncAlarmIntent);
- }
- }
-
- private void sendSyncStateIntent() {
- Intent syncStateIntent = new Intent(Intent.ACTION_SYNC_STATE_CHANGED);
- syncStateIntent.putExtra("active", mNeedSyncActiveNotification);
- syncStateIntent.putExtra("failing", mNeedSyncErrorNotification);
- mContext.sendBroadcast(syncStateIntent);
- }
-
- private void installHandleTooManyDeletesNotification(String account, String authority,
- long numDeletes) {
- if (mNotificationMgr == null) return;
- Intent clickIntent = new Intent();
- clickIntent.setClassName("com.android.providers.subscribedfeeds",
- "com.android.settings.SyncActivityTooManyDeletes");
- clickIntent.putExtra("account", account);
- clickIntent.putExtra("provider", authority);
- clickIntent.putExtra("numDeletes", numDeletes);
-
- if (!isActivityAvailable(clickIntent)) {
- Log.w(TAG, "No activity found to handle too many deletes.");
- return;
- }
-
- final PendingIntent pendingIntent = PendingIntent
- .getActivity(mContext, 0, clickIntent, PendingIntent.FLAG_CANCEL_CURRENT);
-
- CharSequence tooManyDeletesDescFormat = mContext.getResources().getText(
- R.string.contentServiceTooManyDeletesNotificationDesc);
-
- String[] authorities = authority.split(";");
- Notification notification =
- new Notification(R.drawable.stat_notify_sync_error,
- mContext.getString(R.string.contentServiceSync),
- System.currentTimeMillis());
- notification.setLatestEventInfo(mContext,
- mContext.getString(R.string.contentServiceSyncNotificationTitle),
- String.format(tooManyDeletesDescFormat.toString(), authorities[0]),
- pendingIntent);
- notification.flags |= Notification.FLAG_ONGOING_EVENT;
- mNotificationMgr.notify(account.hashCode() ^ authority.hashCode(), notification);
- }
-
- /**
- * Checks whether an activity exists on the system image for the given intent.
- *
- * @param intent The intent for an activity.
- * @return Whether or not an activity exists.
- */
- private boolean isActivityAvailable(Intent intent) {
- PackageManager pm = mContext.getPackageManager();
- List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
- int listSize = list.size();
- for (int i = 0; i < listSize; i++) {
- ResolveInfo resolveInfo = list.get(i);
- if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
- != 0) {
- return true;
- }
- }
-
- return false;
- }
-
- public long insertStartSyncEvent(SyncOperation syncOperation) {
- final int source = syncOperation.syncSource;
- final long now = System.currentTimeMillis();
-
- EventLog.writeEvent(2720, syncOperation.authority, Sync.History.EVENT_START, source);
-
- return mSyncStorageEngine.insertStartSyncEvent(
- syncOperation.account, syncOperation.authority, now, source);
- }
-
- public void stopSyncEvent(long rowId, SyncOperation syncOperation, String resultMessage,
- int upstreamActivity, int downstreamActivity, long elapsedTime) {
- EventLog.writeEvent(2720, syncOperation.authority, Sync.History.EVENT_STOP, syncOperation.syncSource);
-
- mSyncStorageEngine.stopSyncEvent(rowId, elapsedTime, resultMessage,
- downstreamActivity, upstreamActivity);
- }
- }
-
- static class SyncQueue {
- private SyncStorageEngine mSyncStorageEngine;
- private final String[] COLUMNS = new String[]{
- "_id",
- "authority",
- "account",
- "extras",
- "source"
- };
- private static final int COLUMN_ID = 0;
- private static final int COLUMN_AUTHORITY = 1;
- private static final int COLUMN_ACCOUNT = 2;
- private static final int COLUMN_EXTRAS = 3;
- private static final int COLUMN_SOURCE = 4;
-
- private static final boolean DEBUG_CHECK_DATA_CONSISTENCY = false;
-
- // A priority queue of scheduled SyncOperations that is designed to make it quick
- // to find the next SyncOperation that should be considered for running.
- private final PriorityQueue<SyncOperation> mOpsByWhen = new PriorityQueue<SyncOperation>();
-
- // A Map of SyncOperations operationKey -> SyncOperation that is designed for
- // quick lookup of an enqueued SyncOperation.
- private final HashMap<String, SyncOperation> mOpsByKey = Maps.newHashMap();
-
- public SyncQueue(SyncStorageEngine syncStorageEngine) {
- mSyncStorageEngine = syncStorageEngine;
- Cursor cursor = mSyncStorageEngine.getPendingSyncsCursor(COLUMNS);
- try {
- while (cursor.moveToNext()) {
- add(cursorToOperation(cursor),
- true /* this is being added from the database */);
- }
- } finally {
- cursor.close();
- if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */);
- }
- }
-
- public boolean add(SyncOperation operation) {
- return add(new SyncOperation(operation),
- false /* this is not coming from the database */);
- }
-
- private boolean add(SyncOperation operation, boolean fromDatabase) {
- if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(!fromDatabase);
-
- // If this operation is expedited then set its earliestRunTime to be immediately
- // before the head of the list, or not if none are in the list.
- if (operation.delay < 0) {
- SyncOperation headOperation = head();
- if (headOperation != null) {
- operation.earliestRunTime = Math.min(SystemClock.elapsedRealtime(),
- headOperation.earliestRunTime - 1);
- } else {
- operation.earliestRunTime = SystemClock.elapsedRealtime();
- }
- }
-
- // - if an operation with the same key exists and this one should run earlier,
- // delete the old one and add the new one
- // - if an operation with the same key exists and if this one should run
- // later, ignore it
- // - if no operation exists then add the new one
- final String operationKey = operation.key;
- SyncOperation existingOperation = mOpsByKey.get(operationKey);
-
- // if this operation matches an existing operation that is being retried (delay > 0)
- // and this operation isn't forced, ignore this operation
- if (existingOperation != null && existingOperation.delay > 0) {
- if (!operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false)) {
- return false;
- }
- }
-
- if (existingOperation != null
- && operation.earliestRunTime >= existingOperation.earliestRunTime) {
- if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(!fromDatabase);
- return false;
- }
-
- if (existingOperation != null) {
- removeByKey(operationKey);
- }
-
- if (operation.rowId == null) {
- byte[] extrasData = null;
- Parcel parcel = Parcel.obtain();
- try {
- operation.extras.writeToParcel(parcel, 0);
- extrasData = parcel.marshall();
- } finally {
- parcel.recycle();
- }
- ContentValues values = new ContentValues();
- values.put("account", operation.account);
- values.put("authority", operation.authority);
- values.put("source", operation.syncSource);
- values.put("extras", extrasData);
- Uri pendingUri = mSyncStorageEngine.insertIntoPending(values);
- operation.rowId = pendingUri == null ? null : ContentUris.parseId(pendingUri);
- if (operation.rowId == null) {
- throw new IllegalStateException("error adding pending sync operation "
- + operation);
- }
- }
-
- if (DEBUG_CHECK_DATA_CONSISTENCY) {
- debugCheckDataStructures(
- false /* don't compare with the DB, since we know
- it is inconsistent right now */ );
- }
- mOpsByKey.put(operationKey, operation);
- mOpsByWhen.add(operation);
- if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(!fromDatabase);
- return true;
- }
-
- public void removeByKey(String operationKey) {
- if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */);
- SyncOperation operationToRemove = mOpsByKey.remove(operationKey);
- if (!mOpsByWhen.remove(operationToRemove)) {
- throw new IllegalStateException(
- "unable to find " + operationToRemove + " in mOpsByWhen");
- }
-
- if (mSyncStorageEngine.deleteFromPending(operationToRemove.rowId) != 1) {
- throw new IllegalStateException("unable to find pending row for "
- + operationToRemove);
- }
-
- if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */);
- }
-
- public SyncOperation head() {
- if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */);
- return mOpsByWhen.peek();
- }
-
- public void popHead() {
- if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */);
- SyncOperation operation = mOpsByWhen.remove();
- if (mOpsByKey.remove(operation.key) == null) {
- throw new IllegalStateException("unable to find " + operation + " in mOpsByKey");
- }
-
- if (mSyncStorageEngine.deleteFromPending(operation.rowId) != 1) {
- throw new IllegalStateException("unable to find pending row for " + operation);
- }
-
- if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */);
- }
-
- public void clear(String account, String authority) {
- Iterator<Map.Entry<String, SyncOperation>> entries = mOpsByKey.entrySet().iterator();
- while (entries.hasNext()) {
- Map.Entry<String, SyncOperation> entry = entries.next();
- SyncOperation syncOperation = entry.getValue();
- if (account != null && !syncOperation.account.equals(account)) continue;
- if (authority != null && !syncOperation.authority.equals(authority)) continue;
-
- if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */);
- entries.remove();
- if (!mOpsByWhen.remove(syncOperation)) {
- throw new IllegalStateException(
- "unable to find " + syncOperation + " in mOpsByWhen");
- }
-
- if (mSyncStorageEngine.deleteFromPending(syncOperation.rowId) != 1) {
- throw new IllegalStateException("unable to find pending row for "
- + syncOperation);
- }
-
- if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */);
- }
- }
-
- public void dump(StringBuilder sb) {
- sb.append("SyncQueue: ").append(mOpsByWhen.size()).append(" operation(s)\n");
- for (SyncOperation operation : mOpsByWhen) {
- sb.append(operation).append("\n");
- }
- }
-
- private void debugCheckDataStructures(boolean checkDatabase) {
- if (mOpsByKey.size() != mOpsByWhen.size()) {
- throw new IllegalStateException("size mismatch: "
- + mOpsByKey .size() + " != " + mOpsByWhen.size());
- }
- for (SyncOperation operation : mOpsByWhen) {
- if (!mOpsByKey.containsKey(operation.key)) {
- throw new IllegalStateException(
- "operation " + operation + " is in mOpsByWhen but not mOpsByKey");
- }
- }
- for (Map.Entry<String, SyncOperation> entry : mOpsByKey.entrySet()) {
- final SyncOperation operation = entry.getValue();
- final String key = entry.getKey();
- if (!key.equals(operation.key)) {
- throw new IllegalStateException(
- "operation " + operation + " in mOpsByKey doesn't match key " + key);
- }
- if (!mOpsByWhen.contains(operation)) {
- throw new IllegalStateException(
- "operation " + operation + " is in mOpsByKey but not mOpsByWhen");
- }
- }
-
- if (checkDatabase) {
- // check that the DB contains the same rows as the in-memory data structures
- Cursor cursor = mSyncStorageEngine.getPendingSyncsCursor(COLUMNS);
- try {
- if (mOpsByKey.size() != cursor.getCount()) {
- StringBuilder sb = new StringBuilder();
- DatabaseUtils.dumpCursor(cursor, sb);
- sb.append("\n");
- dump(sb);
- throw new IllegalStateException("DB size mismatch: "
- + mOpsByKey .size() + " != " + cursor.getCount() + "\n"
- + sb.toString());
- }
- } finally {
- cursor.close();
- }
- }
- }
-
- private SyncOperation cursorToOperation(Cursor cursor) {
- byte[] extrasData = cursor.getBlob(COLUMN_EXTRAS);
- Bundle extras;
- Parcel parcel = Parcel.obtain();
- try {
- parcel.unmarshall(extrasData, 0, extrasData.length);
- parcel.setDataPosition(0);
- extras = parcel.readBundle();
- } catch (RuntimeException e) {
- // A RuntimeException is thrown if we were unable to parse the parcel.
- // Create an empty parcel in this case.
- extras = new Bundle();
- } finally {
- parcel.recycle();
- }
-
- SyncOperation syncOperation = new SyncOperation(
- cursor.getString(COLUMN_ACCOUNT),
- cursor.getInt(COLUMN_SOURCE),
- cursor.getString(COLUMN_AUTHORITY),
- extras,
- 0 /* delay */);
- syncOperation.rowId = cursor.getLong(COLUMN_ID);
- return syncOperation;
- }
- }
-}
diff --git a/core/java/android/content/SyncProvider.java b/core/java/android/content/SyncProvider.java
deleted file mode 100644
index 6ddd046..0000000
--- a/core/java/android/content/SyncProvider.java
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2007 The Android Open Source Project
-package android.content;
-
-import android.database.Cursor;
-import android.net.Uri;
-
-/**
- * ContentProvider that tracks the sync data and overall sync
- * history on the device.
- *
- * @hide
- */
-public class SyncProvider extends ContentProvider {
- public SyncProvider() {
- }
-
- private SyncStorageEngine mSyncStorageEngine;
-
- @Override
- public boolean onCreate() {
- mSyncStorageEngine = SyncStorageEngine.getSingleton();
- return true;
- }
-
- @Override
- public Cursor query(Uri url, String[] projectionIn,
- String selection, String[] selectionArgs, String sort) {
- return mSyncStorageEngine.query(url, projectionIn, selection, selectionArgs, sort);
- }
-
- @Override
- public Uri insert(Uri url, ContentValues initialValues) {
- return mSyncStorageEngine.insert(true /* the caller is the provider */,
- url, initialValues);
- }
-
- @Override
- public int delete(Uri url, String where, String[] whereArgs) {
- return mSyncStorageEngine.delete(true /* the caller is the provider */,
- url, where, whereArgs);
- }
-
- @Override
- public int update(Uri url, ContentValues initialValues, String where, String[] whereArgs) {
- return mSyncStorageEngine.update(true /* the caller is the provider */,
- url, initialValues, where, whereArgs);
- }
-
- @Override
- public String getType(Uri url) {
- return mSyncStorageEngine.getType(url);
- }
-}
diff --git a/core/java/android/content/SyncResult.aidl b/core/java/android/content/SyncResult.aidl
deleted file mode 100644
index 061b81c..0000000
--- a/core/java/android/content/SyncResult.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-parcelable SyncResult;
diff --git a/core/java/android/content/SyncResult.java b/core/java/android/content/SyncResult.java
deleted file mode 100644
index f3260f3..0000000
--- a/core/java/android/content/SyncResult.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package android.content;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * This class is used to store information about the result of a sync
- *
- * @hide
- */
-public final class SyncResult implements Parcelable {
- public final boolean syncAlreadyInProgress;
- public boolean tooManyDeletions;
- public boolean tooManyRetries;
- public boolean databaseError;
- public boolean fullSyncRequested;
- public boolean partialSyncUnavailable;
- public boolean moreRecordsToGet;
- public final SyncStats stats;
- public static final SyncResult ALREADY_IN_PROGRESS;
-
- static {
- ALREADY_IN_PROGRESS = new SyncResult(true);
- }
-
- public SyncResult() {
- this(false);
- }
-
- private SyncResult(boolean syncAlreadyInProgress) {
- this.syncAlreadyInProgress = syncAlreadyInProgress;
- this.tooManyDeletions = false;
- this.tooManyRetries = false;
- this.fullSyncRequested = false;
- this.partialSyncUnavailable = false;
- this.moreRecordsToGet = false;
- this.stats = new SyncStats();
- }
-
- private SyncResult(Parcel parcel) {
- syncAlreadyInProgress = parcel.readInt() != 0;
- tooManyDeletions = parcel.readInt() != 0;
- tooManyRetries = parcel.readInt() != 0;
- databaseError = parcel.readInt() != 0;
- fullSyncRequested = parcel.readInt() != 0;
- partialSyncUnavailable = parcel.readInt() != 0;
- moreRecordsToGet = parcel.readInt() != 0;
- stats = new SyncStats(parcel);
- }
-
- public boolean hasHardError() {
- return stats.numParseExceptions > 0
- || stats.numConflictDetectedExceptions > 0
- || stats.numAuthExceptions > 0
- || tooManyDeletions
- || tooManyRetries
- || databaseError;
- }
-
- public boolean hasSoftError() {
- return syncAlreadyInProgress || stats.numIoExceptions > 0;
- }
-
- public boolean hasError() {
- return hasSoftError() || hasHardError();
- }
-
- public boolean madeSomeProgress() {
- return ((stats.numDeletes > 0) && !tooManyDeletions)
- || stats.numInserts > 0
- || stats.numUpdates > 0;
- }
-
- public void clear() {
- if (syncAlreadyInProgress) {
- throw new UnsupportedOperationException(
- "you are not allowed to clear the ALREADY_IN_PROGRESS SyncStats");
- }
- tooManyDeletions = false;
- tooManyRetries = false;
- databaseError = false;
- fullSyncRequested = false;
- partialSyncUnavailable = false;
- moreRecordsToGet = false;
- stats.clear();
- }
-
- public static final Creator<SyncResult> CREATOR = new Creator<SyncResult>() {
- public SyncResult createFromParcel(Parcel in) {
- return new SyncResult(in);
- }
-
- public SyncResult[] newArray(int size) {
- return new SyncResult[size];
- }
- };
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeInt(syncAlreadyInProgress ? 1 : 0);
- parcel.writeInt(tooManyDeletions ? 1 : 0);
- parcel.writeInt(tooManyRetries ? 1 : 0);
- parcel.writeInt(databaseError ? 1 : 0);
- parcel.writeInt(fullSyncRequested ? 1 : 0);
- parcel.writeInt(partialSyncUnavailable ? 1 : 0);
- parcel.writeInt(moreRecordsToGet ? 1 : 0);
- stats.writeToParcel(parcel, flags);
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append(" syncAlreadyInProgress: ").append(syncAlreadyInProgress);
- sb.append(" tooManyDeletions: ").append(tooManyDeletions);
- sb.append(" tooManyRetries: ").append(tooManyRetries);
- sb.append(" databaseError: ").append(databaseError);
- sb.append(" fullSyncRequested: ").append(fullSyncRequested);
- sb.append(" partialSyncUnavailable: ").append(partialSyncUnavailable);
- sb.append(" moreRecordsToGet: ").append(moreRecordsToGet);
- sb.append(" stats: ").append(stats);
- return sb.toString();
- }
-
- /**
- * Generates a debugging string indicating the status.
- * The string consist of a sequence of code letter followed by the count.
- * Code letters are f - fullSyncRequested, r - partialSyncUnavailable,
- * X - hardError, e - numParseExceptions, c - numConflictDetectedExceptions,
- * a - numAuthExceptions, D - tooManyDeletions, R - tooManyRetries,
- * b - databaseError, x - softError, l - syncAlreadyInProgress,
- * I - numIoExceptions
- * @return debugging string.
- */
- public String toDebugString() {
- StringBuffer sb = new StringBuffer();
-
- if (fullSyncRequested) {
- sb.append("f1");
- }
- if (partialSyncUnavailable) {
- sb.append("r1");
- }
- if (hasHardError()) {
- sb.append("X1");
- }
- if (stats.numParseExceptions > 0) {
- sb.append("e").append(stats.numParseExceptions);
- }
- if (stats.numConflictDetectedExceptions > 0) {
- sb.append("c").append(stats.numConflictDetectedExceptions);
- }
- if (stats.numAuthExceptions > 0) {
- sb.append("a").append(stats.numAuthExceptions);
- }
- if (tooManyDeletions) {
- sb.append("D1");
- }
- if (tooManyRetries) {
- sb.append("R1");
- }
- if (databaseError) {
- sb.append("b1");
- }
- if (hasSoftError()) {
- sb.append("x1");
- }
- if (syncAlreadyInProgress) {
- sb.append("l1");
- }
- if (stats.numIoExceptions > 0) {
- sb.append("I").append(stats.numIoExceptions);
- }
- return sb.toString();
- }
-}
diff --git a/core/java/android/content/SyncStateContentProviderHelper.java b/core/java/android/content/SyncStateContentProviderHelper.java
deleted file mode 100644
index f503e6f..0000000
--- a/core/java/android/content/SyncStateContentProviderHelper.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import com.android.internal.util.ArrayUtils;
-
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-
-/**
- * Extends the schema of a ContentProvider to include the _sync_state table
- * and implements query/insert/update/delete to access that table using the
- * authority "syncstate". This can be used to store the sync state for a
- * set of accounts.
- *
- * @hide
- */
-public class SyncStateContentProviderHelper {
- final SQLiteOpenHelper mOpenHelper;
-
- private static final String SYNC_STATE_AUTHORITY = "syncstate";
- private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
-
- private static final int STATE = 0;
-
- private static final Uri CONTENT_URI =
- Uri.parse("content://" + SYNC_STATE_AUTHORITY + "/state");
-
- private static final String ACCOUNT_WHERE = "_sync_account = ?";
-
- private final Provider mInternalProviderInterface;
-
- private static final String SYNC_STATE_TABLE = "_sync_state";
- private static long DB_VERSION = 2;
-
- private static final String[] ACCOUNT_PROJECTION = new String[]{"_sync_account"};
-
- static {
- sURIMatcher.addURI(SYNC_STATE_AUTHORITY, "state", STATE);
- }
-
- public SyncStateContentProviderHelper(SQLiteOpenHelper openHelper) {
- mOpenHelper = openHelper;
- mInternalProviderInterface = new Provider();
- }
-
- public ContentProvider asContentProvider() {
- return mInternalProviderInterface;
- }
-
- public void createDatabase(SQLiteDatabase db) {
- db.execSQL("DROP TABLE IF EXISTS _sync_state");
- db.execSQL("CREATE TABLE _sync_state (" +
- "_id INTEGER PRIMARY KEY," +
- "_sync_account TEXT," +
- "data TEXT," +
- "UNIQUE(_sync_account)" +
- ");");
-
- db.execSQL("DROP TABLE IF EXISTS _sync_state_metadata");
- db.execSQL("CREATE TABLE _sync_state_metadata (" +
- "version INTEGER" +
- ");");
- ContentValues values = new ContentValues();
- values.put("version", DB_VERSION);
- db.insert("_sync_state_metadata", "version", values);
- }
-
- protected void onDatabaseOpened(SQLiteDatabase db) {
- long version = DatabaseUtils.longForQuery(db,
- "select version from _sync_state_metadata", null);
- if (version != DB_VERSION) {
- createDatabase(db);
- }
- }
-
- class Provider extends ContentProvider {
- public boolean onCreate() {
- throw new UnsupportedOperationException("not implemented");
- }
-
- public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- int match = sURIMatcher.match(url);
- switch (match) {
- case STATE:
- return db.query(SYNC_STATE_TABLE, projection, selection, selectionArgs,
- null, null, sortOrder);
- default:
- throw new UnsupportedOperationException("Cannot query URL: " + url);
- }
- }
-
- public String getType(Uri uri) {
- throw new UnsupportedOperationException("not implemented");
- }
-
- public Uri insert(Uri url, ContentValues values) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- int match = sURIMatcher.match(url);
- switch (match) {
- case STATE: {
- long id = db.insert(SYNC_STATE_TABLE, "feed", values);
- return CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).build();
- }
- default:
- throw new UnsupportedOperationException("Cannot insert into URL: " + url);
- }
- }
-
- public int delete(Uri url, String userWhere, String[] whereArgs) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- switch (sURIMatcher.match(url)) {
- case STATE:
- return db.delete(SYNC_STATE_TABLE, userWhere, whereArgs);
- default:
- throw new IllegalArgumentException("Unknown URL " + url);
- }
-
- }
-
- public int update(Uri url, ContentValues values, String selection, String[] selectionArgs) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- switch (sURIMatcher.match(url)) {
- case STATE:
- return db.update(SYNC_STATE_TABLE, values, selection, selectionArgs);
- default:
- throw new UnsupportedOperationException("Cannot update URL: " + url);
- }
-
- }
- }
-
- /**
- * Check if the url matches content that this ContentProvider manages.
- * @param url the Uri to check
- * @return true if this ContentProvider can handle that Uri.
- */
- public boolean matches(Uri url) {
- return (SYNC_STATE_AUTHORITY.equals(url.getAuthority()));
- }
-
- /**
- * Replaces the contents of the _sync_state table in the destination ContentProvider
- * with the row that matches account, if any, in the source ContentProvider.
- * <p>
- * The ContentProviders must expose the _sync_state table as URI content://syncstate/state.
- * @param dbSrc the database to read from
- * @param dbDest the database to write to
- * @param account the account of the row that should be copied over.
- */
- public void copySyncState(SQLiteDatabase dbSrc, SQLiteDatabase dbDest,
- String account) {
- final String[] whereArgs = new String[]{account};
- Cursor c = dbSrc.query(SYNC_STATE_TABLE, new String[]{"_sync_account", "data"},
- ACCOUNT_WHERE, whereArgs, null, null, null);
- try {
- if (c.moveToNext()) {
- ContentValues values = new ContentValues();
- values.put("_sync_account", c.getString(0));
- values.put("data", c.getBlob(1));
- dbDest.replace(SYNC_STATE_TABLE, "_sync_account", values);
- }
- } finally {
- c.close();
- }
- }
-
- public void onAccountsChanged(String[] accounts) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- Cursor c = db.query(SYNC_STATE_TABLE, ACCOUNT_PROJECTION, null, null, null, null, null);
- try {
- while (c.moveToNext()) {
- final String account = c.getString(0);
- if (!ArrayUtils.contains(accounts, account)) {
- db.delete(SYNC_STATE_TABLE, ACCOUNT_WHERE, new String[]{account});
- }
- }
- } finally {
- c.close();
- }
- }
-
- public void discardSyncData(SQLiteDatabase db, String account) {
- if (account != null) {
- db.delete(SYNC_STATE_TABLE, ACCOUNT_WHERE, new String[]{account});
- } else {
- db.delete(SYNC_STATE_TABLE, null, null);
- }
- }
-
- /**
- * Retrieves the SyncData bytes for the given account. The byte array returned may be null.
- */
- public byte[] readSyncDataBytes(SQLiteDatabase db, String account) {
- Cursor c = db.query(SYNC_STATE_TABLE, null, ACCOUNT_WHERE,
- new String[]{account}, null, null, null);
- try {
- if (c.moveToFirst()) {
- return c.getBlob(c.getColumnIndexOrThrow("data"));
- }
- } finally {
- c.close();
- }
- return null;
- }
-
- /**
- * Sets the SyncData bytes for the given account. The bytes array may be null.
- */
- public void writeSyncDataBytes(SQLiteDatabase db, String account, byte[] data) {
- ContentValues values = new ContentValues();
- values.put("data", data);
- db.update(SYNC_STATE_TABLE, values, ACCOUNT_WHERE, new String[]{account});
- }
-}
diff --git a/core/java/android/content/SyncStats.aidl b/core/java/android/content/SyncStats.aidl
deleted file mode 100644
index dff0ebf..0000000
--- a/core/java/android/content/SyncStats.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-parcelable SyncStats;
diff --git a/core/java/android/content/SyncStats.java b/core/java/android/content/SyncStats.java
deleted file mode 100644
index b561b05..0000000
--- a/core/java/android/content/SyncStats.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-/**
- * @hide
- */
-public class SyncStats implements Parcelable {
- public long numAuthExceptions;
- public long numIoExceptions;
- public long numParseExceptions;
- public long numConflictDetectedExceptions;
- public long numInserts;
- public long numUpdates;
- public long numDeletes;
- public long numEntries;
- public long numSkippedEntries;
-
- public SyncStats() {
- numAuthExceptions = 0;
- numIoExceptions = 0;
- numParseExceptions = 0;
- numConflictDetectedExceptions = 0;
- numInserts = 0;
- numUpdates = 0;
- numDeletes = 0;
- numEntries = 0;
- numSkippedEntries = 0;
- }
-
- public SyncStats(Parcel in) {
- numAuthExceptions = in.readLong();
- numIoExceptions = in.readLong();
- numParseExceptions = in.readLong();
- numConflictDetectedExceptions = in.readLong();
- numInserts = in.readLong();
- numUpdates = in.readLong();
- numDeletes = in.readLong();
- numEntries = in.readLong();
- numSkippedEntries = in.readLong();
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("numAuthExceptions: ").append(numAuthExceptions);
- sb.append(" numIoExceptions: ").append(numIoExceptions);
- sb.append(" numParseExceptions: ").append(numParseExceptions);
- sb.append(" numConflictDetectedExceptions: ").append(numConflictDetectedExceptions);
- sb.append(" numInserts: ").append(numInserts);
- sb.append(" numUpdates: ").append(numUpdates);
- sb.append(" numDeletes: ").append(numDeletes);
- sb.append(" numEntries: ").append(numEntries);
- sb.append(" numSkippedEntries: ").append(numSkippedEntries);
- return sb.toString();
- }
-
- public void clear() {
- numAuthExceptions = 0;
- numIoExceptions = 0;
- numParseExceptions = 0;
- numConflictDetectedExceptions = 0;
- numInserts = 0;
- numUpdates = 0;
- numDeletes = 0;
- numEntries = 0;
- numSkippedEntries = 0;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(numAuthExceptions);
- dest.writeLong(numIoExceptions);
- dest.writeLong(numParseExceptions);
- dest.writeLong(numConflictDetectedExceptions);
- dest.writeLong(numInserts);
- dest.writeLong(numUpdates);
- dest.writeLong(numDeletes);
- dest.writeLong(numEntries);
- dest.writeLong(numSkippedEntries);
- }
-
- public static final Creator<SyncStats> CREATOR = new Creator<SyncStats>() {
- public SyncStats createFromParcel(Parcel in) {
- return new SyncStats(in);
- }
-
- public SyncStats[] newArray(int size) {
- return new SyncStats[size];
- }
- };
-}
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
deleted file mode 100644
index 282f6e7..0000000
--- a/core/java/android/content/SyncStorageEngine.java
+++ /dev/null
@@ -1,758 +0,0 @@
-package android.content;
-
-import android.Manifest;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteQueryBuilder;
-import android.net.Uri;
-import android.provider.Sync;
-import android.text.TextUtils;
-import android.util.Config;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-
-/**
- * ContentProvider that tracks the sync data and overall sync
- * history on the device.
- *
- * @hide
- */
-public class SyncStorageEngine {
- private static final String TAG = "SyncManager";
-
- private static final String DATABASE_NAME = "syncmanager.db";
- private static final int DATABASE_VERSION = 10;
-
- private static final int STATS = 1;
- private static final int STATS_ID = 2;
- private static final int HISTORY = 3;
- private static final int HISTORY_ID = 4;
- private static final int SETTINGS = 5;
- private static final int PENDING = 7;
- private static final int ACTIVE = 8;
- private static final int STATUS = 9;
-
- private static final UriMatcher sURLMatcher =
- new UriMatcher(UriMatcher.NO_MATCH);
-
- private static final HashMap<String,String> HISTORY_PROJECTION_MAP;
- private static final HashMap<String,String> PENDING_PROJECTION_MAP;
- private static final HashMap<String,String> ACTIVE_PROJECTION_MAP;
- private static final HashMap<String,String> STATUS_PROJECTION_MAP;
-
- private final Context mContext;
- private final SQLiteOpenHelper mOpenHelper;
- private static SyncStorageEngine sSyncStorageEngine = null;
-
- static {
- sURLMatcher.addURI("sync", "stats", STATS);
- sURLMatcher.addURI("sync", "stats/#", STATS_ID);
- sURLMatcher.addURI("sync", "history", HISTORY);
- sURLMatcher.addURI("sync", "history/#", HISTORY_ID);
- sURLMatcher.addURI("sync", "settings", SETTINGS);
- sURLMatcher.addURI("sync", "status", STATUS);
- sURLMatcher.addURI("sync", "active", ACTIVE);
- sURLMatcher.addURI("sync", "pending", PENDING);
-
- HashMap<String,String> map;
- PENDING_PROJECTION_MAP = map = new HashMap<String,String>();
- map.put(Sync.History._ID, Sync.History._ID);
- map.put(Sync.History.ACCOUNT, Sync.History.ACCOUNT);
- map.put(Sync.History.AUTHORITY, Sync.History.AUTHORITY);
-
- ACTIVE_PROJECTION_MAP = map = new HashMap<String,String>();
- map.put(Sync.History._ID, Sync.History._ID);
- map.put(Sync.History.ACCOUNT, Sync.History.ACCOUNT);
- map.put(Sync.History.AUTHORITY, Sync.History.AUTHORITY);
- map.put("startTime", "startTime");
-
- HISTORY_PROJECTION_MAP = map = new HashMap<String,String>();
- map.put(Sync.History._ID, "history._id as _id");
- map.put(Sync.History.ACCOUNT, "stats.account as account");
- map.put(Sync.History.AUTHORITY, "stats.authority as authority");
- map.put(Sync.History.EVENT, Sync.History.EVENT);
- map.put(Sync.History.EVENT_TIME, Sync.History.EVENT_TIME);
- map.put(Sync.History.ELAPSED_TIME, Sync.History.ELAPSED_TIME);
- map.put(Sync.History.SOURCE, Sync.History.SOURCE);
- map.put(Sync.History.UPSTREAM_ACTIVITY, Sync.History.UPSTREAM_ACTIVITY);
- map.put(Sync.History.DOWNSTREAM_ACTIVITY, Sync.History.DOWNSTREAM_ACTIVITY);
- map.put(Sync.History.MESG, Sync.History.MESG);
-
- STATUS_PROJECTION_MAP = map = new HashMap<String,String>();
- map.put(Sync.Status._ID, "status._id as _id");
- map.put(Sync.Status.ACCOUNT, "stats.account as account");
- map.put(Sync.Status.AUTHORITY, "stats.authority as authority");
- map.put(Sync.Status.TOTAL_ELAPSED_TIME, Sync.Status.TOTAL_ELAPSED_TIME);
- map.put(Sync.Status.NUM_SYNCS, Sync.Status.NUM_SYNCS);
- map.put(Sync.Status.NUM_SOURCE_LOCAL, Sync.Status.NUM_SOURCE_LOCAL);
- map.put(Sync.Status.NUM_SOURCE_POLL, Sync.Status.NUM_SOURCE_POLL);
- map.put(Sync.Status.NUM_SOURCE_SERVER, Sync.Status.NUM_SOURCE_SERVER);
- map.put(Sync.Status.NUM_SOURCE_USER, Sync.Status.NUM_SOURCE_USER);
- map.put(Sync.Status.LAST_SUCCESS_SOURCE, Sync.Status.LAST_SUCCESS_SOURCE);
- map.put(Sync.Status.LAST_SUCCESS_TIME, Sync.Status.LAST_SUCCESS_TIME);
- map.put(Sync.Status.LAST_FAILURE_SOURCE, Sync.Status.LAST_FAILURE_SOURCE);
- map.put(Sync.Status.LAST_FAILURE_TIME, Sync.Status.LAST_FAILURE_TIME);
- map.put(Sync.Status.LAST_FAILURE_MESG, Sync.Status.LAST_FAILURE_MESG);
- map.put(Sync.Status.PENDING, Sync.Status.PENDING);
- }
-
- private static final String[] STATS_ACCOUNT_PROJECTION =
- new String[] { Sync.Stats.ACCOUNT };
-
- private static final int MAX_HISTORY_EVENTS_TO_KEEP = 5000;
-
- private static final String SELECT_INITIAL_FAILURE_TIME_QUERY_STRING = ""
- + "SELECT min(a) "
- + "FROM ("
- + " SELECT initialFailureTime AS a "
- + " FROM status "
- + " WHERE stats_id=? AND a IS NOT NULL "
- + " UNION "
- + " SELECT ? AS a"
- + " )";
-
- private SyncStorageEngine(Context context) {
- mContext = context;
- mOpenHelper = new SyncStorageEngine.DatabaseHelper(context);
- sSyncStorageEngine = this;
- }
-
- public static SyncStorageEngine newTestInstance(Context context) {
- return new SyncStorageEngine(context);
- }
-
- public static void init(Context context) {
- if (sSyncStorageEngine != null) {
- throw new IllegalStateException("already initialized");
- }
- sSyncStorageEngine = new SyncStorageEngine(context);
- }
-
- public static SyncStorageEngine getSingleton() {
- if (sSyncStorageEngine == null) {
- throw new IllegalStateException("not initialized");
- }
- return sSyncStorageEngine;
- }
-
- private class DatabaseHelper extends SQLiteOpenHelper {
- DatabaseHelper(Context context) {
- super(context, DATABASE_NAME, null, DATABASE_VERSION);
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL("CREATE TABLE pending ("
- + "_id INTEGER PRIMARY KEY,"
- + "authority TEXT NOT NULL,"
- + "account TEXT NOT NULL,"
- + "extras BLOB NOT NULL,"
- + "source INTEGER NOT NULL"
- + ");");
-
- db.execSQL("CREATE TABLE stats (" +
- "_id INTEGER PRIMARY KEY," +
- "account TEXT, " +
- "authority TEXT, " +
- "syncdata TEXT, " +
- "UNIQUE (account, authority)" +
- ");");
-
- db.execSQL("CREATE TABLE history (" +
- "_id INTEGER PRIMARY KEY," +
- "stats_id INTEGER," +
- "eventTime INTEGER," +
- "elapsedTime INTEGER," +
- "source INTEGER," +
- "event INTEGER," +
- "upstreamActivity INTEGER," +
- "downstreamActivity INTEGER," +
- "mesg TEXT);");
-
- db.execSQL("CREATE TABLE status ("
- + "_id INTEGER PRIMARY KEY,"
- + "stats_id INTEGER NOT NULL,"
- + "totalElapsedTime INTEGER NOT NULL DEFAULT 0,"
- + "numSyncs INTEGER NOT NULL DEFAULT 0,"
- + "numSourcePoll INTEGER NOT NULL DEFAULT 0,"
- + "numSourceServer INTEGER NOT NULL DEFAULT 0,"
- + "numSourceLocal INTEGER NOT NULL DEFAULT 0,"
- + "numSourceUser INTEGER NOT NULL DEFAULT 0,"
- + "lastSuccessTime INTEGER,"
- + "lastSuccessSource INTEGER,"
- + "lastFailureTime INTEGER,"
- + "lastFailureSource INTEGER,"
- + "lastFailureMesg STRING,"
- + "initialFailureTime INTEGER,"
- + "pending INTEGER NOT NULL DEFAULT 0);");
-
- db.execSQL("CREATE TABLE active ("
- + "_id INTEGER PRIMARY KEY,"
- + "authority TEXT,"
- + "account TEXT,"
- + "startTime INTEGER);");
-
- db.execSQL("CREATE INDEX historyEventTime ON history (eventTime)");
-
- db.execSQL("CREATE TABLE settings (" +
- "name TEXT PRIMARY KEY," +
- "value TEXT);");
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- if (oldVersion == 9 && newVersion == 10) {
- Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
- + newVersion + ", which will preserve old data");
- db.execSQL("ALTER TABLE status ADD COLUMN initialFailureTime INTEGER");
- return;
- }
-
- Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
- + newVersion + ", which will destroy all old data");
- db.execSQL("DROP TABLE IF EXISTS pending");
- db.execSQL("DROP TABLE IF EXISTS stats");
- db.execSQL("DROP TABLE IF EXISTS history");
- db.execSQL("DROP TABLE IF EXISTS settings");
- db.execSQL("DROP TABLE IF EXISTS active");
- db.execSQL("DROP TABLE IF EXISTS status");
- onCreate(db);
- }
-
- @Override
- public void onOpen(SQLiteDatabase db) {
- if (!db.isReadOnly()) {
- db.delete("active", null, null);
- db.insert("active", "account", null);
- }
- }
- }
-
- protected void doDatabaseCleanup(String[] accounts) {
- HashSet<String> currentAccounts = new HashSet<String>();
- for (String account : accounts) currentAccounts.add(account);
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- Cursor cursor = db.query("stats", STATS_ACCOUNT_PROJECTION,
- null /* where */, null /* where args */, Sync.Stats.ACCOUNT,
- null /* having */, null /* order by */);
- try {
- while (cursor.moveToNext()) {
- String account = cursor.getString(0);
- if (TextUtils.isEmpty(account)) {
- continue;
- }
- if (!currentAccounts.contains(account)) {
- String where = Sync.Stats.ACCOUNT + "=?";
- int numDeleted;
- numDeleted = db.delete("stats", where, new String[]{account});
- if (Config.LOGD) {
- Log.d(TAG, "deleted " + numDeleted
- + " records from stats table"
- + " for account " + account);
- }
- }
- }
- } finally {
- cursor.close();
- }
- }
-
- protected void setActiveSync(SyncManager.ActiveSyncContext activeSyncContext) {
- if (activeSyncContext != null) {
- updateActiveSync(activeSyncContext.mSyncOperation.account,
- activeSyncContext.mSyncOperation.authority, activeSyncContext.mStartTime);
- } else {
- // we indicate that the sync is not active by passing null for all the parameters
- updateActiveSync(null, null, null);
- }
- }
-
- private int updateActiveSync(String account, String authority, Long startTime) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- ContentValues values = new ContentValues();
- values.put("account", account);
- values.put("authority", authority);
- values.put("startTime", startTime);
- int numChanges = db.update("active", values, null, null);
- if (numChanges > 0) {
- mContext.getContentResolver().notifyChange(Sync.Active.CONTENT_URI,
- null /* this change wasn't made through an observer */);
- }
- return numChanges;
- }
-
- /**
- * Implements the {@link ContentProvider#query} method
- */
- public Cursor query(Uri url, String[] projectionIn,
- String selection, String[] selectionArgs, String sort) {
- SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
-
- // Generate the body of the query
- int match = sURLMatcher.match(url);
- String groupBy = null;
- switch (match) {
- case STATS:
- qb.setTables("stats");
- break;
- case STATS_ID:
- qb.setTables("stats");
- qb.appendWhere("_id=");
- qb.appendWhere(url.getPathSegments().get(1));
- break;
- case HISTORY:
- // join the stats and history tables, so the caller can get
- // the account and authority information as part of this query.
- qb.setTables("stats, history");
- qb.setProjectionMap(HISTORY_PROJECTION_MAP);
- qb.appendWhere("stats._id = history.stats_id");
- break;
- case ACTIVE:
- qb.setTables("active");
- qb.setProjectionMap(ACTIVE_PROJECTION_MAP);
- qb.appendWhere("account is not null");
- break;
- case PENDING:
- qb.setTables("pending");
- qb.setProjectionMap(PENDING_PROJECTION_MAP);
- groupBy = "account, authority";
- break;
- case STATUS:
- // join the stats and status tables, so the caller can get
- // the account and authority information as part of this query.
- qb.setTables("stats, status");
- qb.setProjectionMap(STATUS_PROJECTION_MAP);
- qb.appendWhere("stats._id = status.stats_id");
- break;
- case HISTORY_ID:
- // join the stats and history tables, so the caller can get
- // the account and authority information as part of this query.
- qb.setTables("stats, history");
- qb.setProjectionMap(HISTORY_PROJECTION_MAP);
- qb.appendWhere("stats._id = history.stats_id");
- qb.appendWhere("AND history._id=");
- qb.appendWhere(url.getPathSegments().get(1));
- break;
- case SETTINGS:
- qb.setTables("settings");
- break;
- default:
- throw new IllegalArgumentException("Unknown URL " + url);
- }
-
- if (match == SETTINGS) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
- "no permission to read the sync settings");
- } else {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
- "no permission to read the sync stats");
- }
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- Cursor c = qb.query(db, projectionIn, selection, selectionArgs, groupBy, null, sort);
- c.setNotificationUri(mContext.getContentResolver(), url);
- return c;
- }
-
- /**
- * Implements the {@link ContentProvider#insert} method
- * @param callerIsTheProvider true if this is being called via the
- * {@link ContentProvider#insert} in method rather than directly.
- * @throws UnsupportedOperationException if callerIsTheProvider is true and the url isn't
- * for the Settings table.
- */
- public Uri insert(boolean callerIsTheProvider, Uri url, ContentValues values) {
- String table;
- long rowID;
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- final int match = sURLMatcher.match(url);
- checkCaller(callerIsTheProvider, match);
- switch (match) {
- case SETTINGS:
- mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
- "no permission to write the sync settings");
- table = "settings";
- rowID = db.replace(table, null, values);
- break;
- default:
- throw new IllegalArgumentException("Unknown URL " + url);
- }
-
-
- if (rowID > 0) {
- mContext.getContentResolver().notifyChange(url, null /* observer */);
- return Uri.parse("content://sync/" + table + "/" + rowID);
- }
-
- return null;
- }
-
- private static void checkCaller(boolean callerIsTheProvider, int match) {
- if (callerIsTheProvider && match != SETTINGS) {
- throw new UnsupportedOperationException(
- "only the settings are modifiable via the ContentProvider interface");
- }
- }
-
- /**
- * Implements the {@link ContentProvider#delete} method
- * @param callerIsTheProvider true if this is being called via the
- * {@link ContentProvider#delete} in method rather than directly.
- * @throws UnsupportedOperationException if callerIsTheProvider is true and the url isn't
- * for the Settings table.
- */
- public int delete(boolean callerIsTheProvider, Uri url, String where, String[] whereArgs) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- int match = sURLMatcher.match(url);
-
- int numRows;
- switch (match) {
- case SETTINGS:
- mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
- "no permission to write the sync settings");
- numRows = db.delete("settings", where, whereArgs);
- break;
- default:
- throw new UnsupportedOperationException("Cannot delete URL: " + url);
- }
-
- if (numRows > 0) {
- mContext.getContentResolver().notifyChange(url, null /* observer */);
- }
- return numRows;
- }
-
- /**
- * Implements the {@link ContentProvider#update} method
- * @param callerIsTheProvider true if this is being called via the
- * {@link ContentProvider#update} in method rather than directly.
- * @throws UnsupportedOperationException if callerIsTheProvider is true and the url isn't
- * for the Settings table.
- */
- public int update(boolean callerIsTheProvider, Uri url, ContentValues initialValues,
- String where, String[] whereArgs) {
- switch (sURLMatcher.match(url)) {
- case SETTINGS:
- throw new UnsupportedOperationException("updating url " + url
- + " is not allowed, use insert instead");
- default:
- throw new UnsupportedOperationException("Cannot update URL: " + url);
- }
- }
-
- /**
- * Implements the {@link ContentProvider#getType} method
- */
- public String getType(Uri url) {
- int match = sURLMatcher.match(url);
- switch (match) {
- case SETTINGS:
- return "vnd.android.cursor.dir/sync-settings";
- default:
- throw new IllegalArgumentException("Unknown URL");
- }
- }
-
- protected Uri insertIntoPending(ContentValues values) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- try {
- db.beginTransaction();
- long rowId = db.insert("pending", Sync.Pending.ACCOUNT, values);
- if (rowId < 0) return null;
- String account = values.getAsString(Sync.Pending.ACCOUNT);
- String authority = values.getAsString(Sync.Pending.AUTHORITY);
-
- long statsId = createStatsRowIfNecessary(account, authority);
- createStatusRowIfNecessary(statsId);
-
- values.clear();
- values.put(Sync.Status.PENDING, 1);
- int numUpdatesStatus = db.update("status", values, "stats_id=" + statsId, null);
-
- db.setTransactionSuccessful();
-
- mContext.getContentResolver().notifyChange(Sync.Pending.CONTENT_URI,
- null /* no observer initiated this change */);
- if (numUpdatesStatus > 0) {
- mContext.getContentResolver().notifyChange(Sync.Status.CONTENT_URI,
- null /* no observer initiated this change */);
- }
- return ContentUris.withAppendedId(Sync.Pending.CONTENT_URI, rowId);
- } finally {
- db.endTransaction();
- }
- }
-
- int deleteFromPending(long rowId) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- db.beginTransaction();
- try {
- String account;
- String authority;
- Cursor c = db.query("pending",
- new String[]{Sync.Pending.ACCOUNT, Sync.Pending.AUTHORITY},
- "_id=" + rowId, null, null, null, null);
- try {
- if (c.getCount() != 1) {
- return 0;
- }
- c.moveToNext();
- account = c.getString(0);
- authority = c.getString(1);
- } finally {
- c.close();
- }
- db.delete("pending", "_id=" + rowId, null /* no where args */);
- final String[] accountAuthorityWhereArgs = new String[]{account, authority};
- boolean isPending = 0 < DatabaseUtils.longForQuery(db,
- "SELECT COUNT(*) FROM PENDING WHERE account=? AND authority=?",
- accountAuthorityWhereArgs);
- if (!isPending) {
- long statsId = createStatsRowIfNecessary(account, authority);
- db.execSQL("UPDATE status SET pending=0 WHERE stats_id=" + statsId);
- }
- db.setTransactionSuccessful();
-
- mContext.getContentResolver().notifyChange(Sync.Pending.CONTENT_URI,
- null /* no observer initiated this change */);
- if (!isPending) {
- mContext.getContentResolver().notifyChange(Sync.Status.CONTENT_URI,
- null /* no observer initiated this change */);
- }
- return 1;
- } finally {
- db.endTransaction();
- }
- }
-
- int clearPending() {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- db.beginTransaction();
- try {
- int numChanges = db.delete("pending", null, null /* no where args */);
- if (numChanges > 0) {
- db.execSQL("UPDATE status SET pending=0");
- mContext.getContentResolver().notifyChange(Sync.Pending.CONTENT_URI,
- null /* no observer initiated this change */);
- mContext.getContentResolver().notifyChange(Sync.Status.CONTENT_URI,
- null /* no observer initiated this change */);
- }
- db.setTransactionSuccessful();
- return numChanges;
- } finally {
- db.endTransaction();
- }
- }
-
- /**
- * Returns a cursor over all the pending syncs in no particular order. This cursor is not
- * "live", in that if changes are made to the pending table any observers on this cursor
- * will not be notified.
- * @param projection Return only these columns. If null then all columns are returned.
- * @return the cursor of pending syncs
- */
- public Cursor getPendingSyncsCursor(String[] projection) {
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- return db.query("pending", projection, null, null, null, null, null);
- }
-
- // @VisibleForTesting
- static final long MILLIS_IN_4WEEKS = 1000L * 60 * 60 * 24 * 7 * 4;
-
- private boolean purgeOldHistoryEvents(long now) {
- // remove events that are older than MILLIS_IN_4WEEKS
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- int numDeletes = db.delete("history", "eventTime<" + (now - MILLIS_IN_4WEEKS), null);
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- if (numDeletes > 0) {
- Log.v(TAG, "deleted " + numDeletes + " old event(s) from the sync history");
- }
- }
-
- // keep only the last MAX_HISTORY_EVENTS_TO_KEEP history events
- numDeletes += db.delete("history", "eventTime < (select min(eventTime) from "
- + "(select eventTime from history order by eventTime desc limit ?))",
- new String[]{String.valueOf(MAX_HISTORY_EVENTS_TO_KEEP)});
-
- return numDeletes > 0;
- }
-
- public long insertStartSyncEvent(String account, String authority, long now, int source) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- long statsId = createStatsRowIfNecessary(account, authority);
-
- purgeOldHistoryEvents(now);
- ContentValues values = new ContentValues();
- values.put(Sync.History.STATS_ID, statsId);
- values.put(Sync.History.EVENT_TIME, now);
- values.put(Sync.History.SOURCE, source);
- values.put(Sync.History.EVENT, Sync.History.EVENT_START);
- long rowId = db.insert("history", null, values);
- mContext.getContentResolver().notifyChange(Sync.History.CONTENT_URI, null /* observer */);
- mContext.getContentResolver().notifyChange(Sync.Status.CONTENT_URI, null /* observer */);
- return rowId;
- }
-
- public void stopSyncEvent(long historyId, long elapsedTime, String resultMessage,
- long downstreamActivity, long upstreamActivity) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- db.beginTransaction();
- try {
- ContentValues values = new ContentValues();
- values.put(Sync.History.ELAPSED_TIME, elapsedTime);
- values.put(Sync.History.EVENT, Sync.History.EVENT_STOP);
- values.put(Sync.History.MESG, resultMessage);
- values.put(Sync.History.DOWNSTREAM_ACTIVITY, downstreamActivity);
- values.put(Sync.History.UPSTREAM_ACTIVITY, upstreamActivity);
-
- int count = db.update("history", values, "_id=?",
- new String[]{Long.toString(historyId)});
- // We think that count should always be 1 but don't want to change this until after
- // launch.
- if (count > 0) {
- int source = (int) DatabaseUtils.longForQuery(db,
- "SELECT source FROM history WHERE _id=" + historyId, null);
- long eventTime = DatabaseUtils.longForQuery(db,
- "SELECT eventTime FROM history WHERE _id=" + historyId, null);
- long statsId = DatabaseUtils.longForQuery(db,
- "SELECT stats_id FROM history WHERE _id=" + historyId, null);
-
- createStatusRowIfNecessary(statsId);
-
- // update the status table to reflect this sync
- StringBuilder sb = new StringBuilder();
- ArrayList<String> bindArgs = new ArrayList<String>();
- sb.append("UPDATE status SET");
- sb.append(" numSyncs=numSyncs+1");
- sb.append(", totalElapsedTime=totalElapsedTime+" + elapsedTime);
- switch (source) {
- case Sync.History.SOURCE_LOCAL:
- sb.append(", numSourceLocal=numSourceLocal+1");
- break;
- case Sync.History.SOURCE_POLL:
- sb.append(", numSourcePoll=numSourcePoll+1");
- break;
- case Sync.History.SOURCE_USER:
- sb.append(", numSourceUser=numSourceUser+1");
- break;
- case Sync.History.SOURCE_SERVER:
- sb.append(", numSourceServer=numSourceServer+1");
- break;
- }
-
- final String statsIdString = String.valueOf(statsId);
- final long lastSyncTime = (eventTime + elapsedTime);
- if (Sync.History.MESG_SUCCESS.equals(resultMessage)) {
- // - if successful, update the successful columns
- sb.append(", lastSuccessTime=" + lastSyncTime);
- sb.append(", lastSuccessSource=" + source);
- sb.append(", lastFailureTime=null");
- sb.append(", lastFailureSource=null");
- sb.append(", lastFailureMesg=null");
- sb.append(", initialFailureTime=null");
- } else if (!Sync.History.MESG_CANCELED.equals(resultMessage)) {
- sb.append(", lastFailureTime=" + lastSyncTime);
- sb.append(", lastFailureSource=" + source);
- sb.append(", lastFailureMesg=?");
- bindArgs.add(resultMessage);
- long initialFailureTime = DatabaseUtils.longForQuery(db,
- SELECT_INITIAL_FAILURE_TIME_QUERY_STRING,
- new String[]{statsIdString, String.valueOf(lastSyncTime)});
- sb.append(", initialFailureTime=" + initialFailureTime);
- }
- sb.append(" WHERE stats_id=?");
- bindArgs.add(statsIdString);
- db.execSQL(sb.toString(), bindArgs.toArray());
- db.setTransactionSuccessful();
- mContext.getContentResolver().notifyChange(Sync.History.CONTENT_URI,
- null /* observer */);
- mContext.getContentResolver().notifyChange(Sync.Status.CONTENT_URI,
- null /* observer */);
- }
- } finally {
- db.endTransaction();
- }
- }
-
- /**
- * If sync is failing for any of the provider/accounts then determine the time at which it
- * started failing and return the earliest time over all the provider/accounts. If none are
- * failing then return 0.
- */
- public long getInitialSyncFailureTime() {
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- // Join the settings for a provider with the status so that we can easily
- // check if each provider is enabled for syncing. We also join in the overall
- // enabled flag ("listen_for_tickles") to each row so that we don't need to
- // make a separate DB lookup to access it.
- Cursor c = db.rawQuery(""
- + "SELECT initialFailureTime, s1.value, s2.value "
- + "FROM status "
- + "LEFT JOIN stats ON status.stats_id=stats._id "
- + "LEFT JOIN settings as s1 ON 'sync_provider_' || authority=s1.name "
- + "LEFT JOIN settings as s2 ON s2.name='listen_for_tickles' "
- + "where initialFailureTime is not null "
- + " AND lastFailureMesg!=" + Sync.History.ERROR_TOO_MANY_DELETIONS
- + " AND lastFailureMesg!=" + Sync.History.ERROR_AUTHENTICATION
- + " AND lastFailureMesg!=" + Sync.History.ERROR_SYNC_ALREADY_IN_PROGRESS
- + " AND authority!='subscribedfeeds' "
- + " ORDER BY initialFailureTime", null);
- try {
- while (c.moveToNext()) {
- // these settings default to true, so if they are null treat them as enabled
- final String providerEnabledString = c.getString(1);
- if (providerEnabledString != null && !Boolean.parseBoolean(providerEnabledString)) {
- continue;
- }
- final String allEnabledString = c.getString(2);
- if (allEnabledString != null && !Boolean.parseBoolean(allEnabledString)) {
- continue;
- }
- return c.getLong(0);
- }
- } finally {
- c.close();
- }
- return 0;
- }
-
- private void createStatusRowIfNecessary(long statsId) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- boolean statusExists = 0 != DatabaseUtils.longForQuery(db,
- "SELECT count(*) FROM status WHERE stats_id=" + statsId, null);
- if (!statusExists) {
- ContentValues values = new ContentValues();
- values.put("stats_id", statsId);
- db.insert("status", null, values);
- }
- }
-
- private long createStatsRowIfNecessary(String account, String authority) {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- StringBuilder where = new StringBuilder();
- where.append(Sync.Stats.ACCOUNT + "= ?");
- where.append(" and " + Sync.Stats.AUTHORITY + "= ?");
- Cursor cursor = query(Sync.Stats.CONTENT_URI,
- Sync.Stats.SYNC_STATS_PROJECTION,
- where.toString(), new String[] { account, authority },
- null /* order */);
- try {
- long id;
- if (cursor.moveToFirst()) {
- id = cursor.getLong(cursor.getColumnIndexOrThrow(Sync.Stats._ID));
- } else {
- ContentValues values = new ContentValues();
- values.put(Sync.Stats.ACCOUNT, account);
- values.put(Sync.Stats.AUTHORITY, authority);
- id = db.insert("stats", null, values);
- }
- return id;
- } finally {
- cursor.close();
- }
- }
-}
diff --git a/core/java/android/content/SyncUIContext.java b/core/java/android/content/SyncUIContext.java
deleted file mode 100644
index 6dde004..0000000
--- a/core/java/android/content/SyncUIContext.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-/**
- * Class with callback methods for SyncAdapters and ContentProviders
- * that are called in response to the calls on SyncContext. This class
- * is really only meant to be used by the Sync UI activities.
- *
- * <p>All of the onXXX callback methods here are called from a handler
- * on the thread this object was created in.
- *
- * <p>This interface is unused. It should be removed.
- *
- * @hide
- */
-@Deprecated
-public interface SyncUIContext {
-
- void setStatusText(String text);
-
- Context context();
-}
diff --git a/core/java/android/content/SyncableContentProvider.java b/core/java/android/content/SyncableContentProvider.java
deleted file mode 100644
index e0cd786..0000000
--- a/core/java/android/content/SyncableContentProvider.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.net.Uri;
-
-import java.util.Map;
-
-/**
- * A specialization of the ContentProvider that centralizes functionality
- * used by ContentProviders that are syncable. It also wraps calls to the ContentProvider
- * inside of database transactions.
- *
- * @hide
- */
-public abstract class SyncableContentProvider extends ContentProvider {
- protected abstract boolean isTemporary();
-
- /**
- * Close resources that must be closed. You must call this to properly release
- * the resources used by the SyncableContentProvider.
- */
- public abstract void close();
-
- /**
- * Override to create your schema and do anything else you need to do with a new database.
- * This is run inside a transaction (so you don't need to use one).
- * This method may not use getDatabase(), or call content provider methods, it must only
- * use the database handle passed to it.
- */
- protected abstract void bootstrapDatabase(SQLiteDatabase db);
-
- /**
- * Override to upgrade your database from an old version to the version you specified.
- * Don't set the DB version, this will automatically be done after the method returns.
- * This method may not use getDatabase(), or call content provider methods, it must only
- * use the database handle passed to it.
- *
- * @param oldVersion version of the existing database
- * @param newVersion current version to upgrade to
- * @return true if the upgrade was lossless, false if it was lossy
- */
- protected abstract boolean upgradeDatabase(SQLiteDatabase db, int oldVersion, int newVersion);
-
- /**
- * Override to do anything (like cleanups or checks) you need to do after opening a database.
- * Does nothing by default. This is run inside a transaction (so you don't need to use one).
- * This method may not use getDatabase(), or call content provider methods, it must only
- * use the database handle passed to it.
- */
- protected abstract void onDatabaseOpened(SQLiteDatabase db);
-
- /**
- * Get a non-persistent instance of this content provider.
- * You must call {@link #close} on the returned
- * SyncableContentProvider when you are done with it.
- *
- * @return a non-persistent content provider with the same layout as this
- * provider.
- */
- public abstract SyncableContentProvider getTemporaryInstance();
-
- public abstract SQLiteDatabase getDatabase();
-
- public abstract boolean getContainsDiffs();
-
- public abstract void setContainsDiffs(boolean containsDiffs);
-
- /**
- * Each subclass of this class should define a subclass of {@link
- * AbstractTableMerger} for each table they wish to merge. It
- * should then override this method and return one instance of
- * each merger, in sequence. Their {@link
- * AbstractTableMerger#merge merge} methods will be called, one at a
- * time, in the order supplied.
- *
- * <p>The default implementation returns an empty list, so that no
- * merging will occur.
- * @return A sequence of subclasses of {@link
- * AbstractTableMerger}, one for each table that should be merged.
- */
- protected abstract Iterable<? extends AbstractTableMerger> getMergers();
-
- /**
- * Check if changes to this URI can be syncable changes.
- * @param uri the URI of the resource that was changed
- * @return true if changes to this URI can be syncable changes, false otherwise
- */
- public abstract boolean changeRequiresLocalSync(Uri uri);
-
- /**
- * Called right before a sync is started.
- *
- * @param context the sync context for the operation
- * @param account
- */
- public abstract void onSyncStart(SyncContext context, String account);
-
- /**
- * Called right after a sync is completed
- *
- * @param context the sync context for the operation
- * @param success true if the sync succeeded, false if an error occurred
- */
- public abstract void onSyncStop(SyncContext context, boolean success);
-
- /**
- * The account of the most recent call to onSyncStart()
- * @return the account
- */
- public abstract String getSyncingAccount();
-
- /**
- * Merge diffs from a sync source with this content provider.
- *
- * @param context the SyncContext within which this merge is taking place
- * @param diffs A temporary content provider containing diffs from a sync
- * source.
- * @param result a MergeResult that contains information about the merge, including
- * a temporary content provider with the same layout as this provider containing
- * @param syncResult
- */
- public abstract void merge(SyncContext context, SyncableContentProvider diffs,
- TempProviderSyncResult result, SyncResult syncResult);
-
-
- /**
- * Invoked when the active sync has been canceled. The default
- * implementation doesn't do anything (except ensure that this
- * provider is syncable). Subclasses of ContentProvider
- * that support canceling of sync should override this.
- */
- public abstract void onSyncCanceled();
-
-
- public abstract boolean isMergeCancelled();
-
- /**
- * Subclasses should override this instead of update(). See update()
- * for details.
- *
- * <p> This method is called within a acquireDbLock()/releaseDbLock() block,
- * which means a database transaction will be active during the call;
- */
- protected abstract int updateInternal(Uri url, ContentValues values,
- String selection, String[] selectionArgs);
-
- /**
- * Subclasses should override this instead of delete(). See delete()
- * for details.
- *
- * <p> This method is called within a acquireDbLock()/releaseDbLock() block,
- * which means a database transaction will be active during the call;
- */
- protected abstract int deleteInternal(Uri url, String selection, String[] selectionArgs);
-
- /**
- * Subclasses should override this instead of insert(). See insert()
- * for details.
- *
- * <p> This method is called within a acquireDbLock()/releaseDbLock() block,
- * which means a database transaction will be active during the call;
- */
- protected abstract Uri insertInternal(Uri url, ContentValues values);
-
- /**
- * Subclasses should override this instead of query(). See query()
- * for details.
- *
- * <p> This method is *not* called within a acquireDbLock()/releaseDbLock()
- * block for performance reasons. If an implementation needs atomic access
- * to the database the lock can be acquired then.
- */
- protected abstract Cursor queryInternal(Uri url, String[] projection,
- String selection, String[] selectionArgs, String sortOrder);
-
- /**
- * Make sure that there are no entries for accounts that no longer exist
- * @param accountsArray the array of currently-existing accounts
- */
- protected abstract void onAccountsChanged(String[] accountsArray);
-
- /**
- * A helper method to delete all rows whose account is not in the accounts
- * map. The accountColumnName is the name of the column that is expected
- * to hold the account. If a row has an empty account it is never deleted.
- *
- * @param accounts a map of existing accounts
- * @param table the table to delete from
- * @param accountColumnName the name of the column that is expected
- * to hold the account.
- */
- protected abstract void deleteRowsForRemovedAccounts(Map<String, Boolean> accounts,
- String table, String accountColumnName);
-
- /**
- * Called when the sync system determines that this provider should no longer
- * contain records for the specified account.
- */
- public abstract void wipeAccount(String account);
-
- /**
- * Retrieves the SyncData bytes for the given account. The byte array returned may be null.
- */
- public abstract byte[] readSyncDataBytes(String account);
-
- /**
- * Sets the SyncData bytes for the given account. The bytes array may be null.
- */
- public abstract void writeSyncDataBytes(String account, byte[] data);
-}
-
diff --git a/core/java/android/content/TempProviderSyncAdapter.java b/core/java/android/content/TempProviderSyncAdapter.java
deleted file mode 100644
index eb3a5da..0000000
--- a/core/java/android/content/TempProviderSyncAdapter.java
+++ /dev/null
@@ -1,550 +0,0 @@
-package android.content;
-
-import android.database.SQLException;
-import android.os.Bundle;
-import android.os.Debug;
-import android.os.NetStat;
-import android.os.Parcelable;
-import android.os.Process;
-import android.os.SystemProperties;
-import android.text.TextUtils;
-import android.util.Config;
-import android.util.EventLog;
-import android.util.Log;
-import android.util.TimingLogger;
-
-/**
- * @hide
- */
-public abstract class TempProviderSyncAdapter extends SyncAdapter {
- private static final String TAG = "Sync";
-
- private static final int MAX_GET_SERVER_DIFFS_LOOP_COUNT = 20;
- private static final int MAX_UPLOAD_CHANGES_LOOP_COUNT = 10;
- private static final int NUM_ALLOWED_SIMULTANEOUS_DELETIONS = 5;
- private static final long PERCENT_ALLOWED_SIMULTANEOUS_DELETIONS = 20;
-
- private volatile SyncableContentProvider mProvider;
- private volatile SyncThread mSyncThread = null;
- private volatile boolean mProviderSyncStarted;
- private volatile boolean mAdapterSyncStarted;
-
- public TempProviderSyncAdapter(SyncableContentProvider provider) {
- super();
- mProvider = provider;
- }
-
- /**
- * Used by getServerDiffs() to track the sync progress for a given
- * sync adapter. Implementations of SyncAdapter generally specialize
- * this class in order to track specific data about that SyncAdapter's
- * sync. If an implementation of SyncAdapter doesn't need to store
- * any data for a sync it may use TrivialSyncData.
- */
- public static abstract class SyncData implements Parcelable {
-
- }
-
- public final void setContext(Context context) {
- mContext = context;
- }
-
- /**
- * Retrieve the Context this adapter is running in. Only available
- * once onSyncStarting() is called (not available from constructor).
- */
- final public Context getContext() {
- return mContext;
- }
-
- /**
- * Called right before a sync is started.
- *
- * @param context allows you to publish status and interact with the
- * @param account the account to sync
- * @param forced if true then the sync was forced
- * @param result information to track what happened during this sync attempt
- * @return true, if the sync was successfully started. One reason it can
- * fail to start is if there is no user configured on the device.
- */
- public abstract void onSyncStarting(SyncContext context, String account, boolean forced,
- SyncResult result);
-
- /**
- * Called right after a sync is completed
- *
- * @param context allows you to publish status and interact with the
- * user during interactive syncs.
- * @param success true if the sync suceeded, false if an error occured
- */
- public abstract void onSyncEnding(SyncContext context, boolean success);
-
- /**
- * Implement this to return true if the data in your content provider
- * is read only.
- */
- public abstract boolean isReadOnly();
-
- /**
- * Get diffs from the server since the last completed sync and put them
- * into a temporary provider.
- *
- * @param context allows you to publish status and interact with the
- * user during interactive syncs.
- * @param syncData used to track the progress this client has made in syncing data
- * from the server
- * @param tempProvider this is where the diffs should be stored
- * @param extras any extra data describing the sync that is desired
- * @param syncInfo sync adapter-specific data that is used during a single sync operation
- * @param syncResult information to track what happened during this sync attempt
- */
- public abstract void getServerDiffs(SyncContext context,
- SyncData syncData, SyncableContentProvider tempProvider,
- Bundle extras, Object syncInfo, SyncResult syncResult);
-
- /**
- * Send client diffs to the server, optionally receiving more diffs from the server
- *
- * @param context allows you to publish status and interact with the
- * user during interactive syncs.
- * @param clientDiffs the diffs from the client
- * @param serverDiffs the SyncableContentProvider that should be populated with
-* the entries that were returned in response to an insert/update/delete request
-* to the server
- * @param syncResult information to track what happened during this sync attempt
- * @param dontActuallySendDeletes
- */
- public abstract void sendClientDiffs(SyncContext context,
- SyncableContentProvider clientDiffs,
- SyncableContentProvider serverDiffs, SyncResult syncResult,
- boolean dontActuallySendDeletes);
-
- /**
- * Reads the sync data from the ContentProvider
- * @param contentProvider the ContentProvider to read from
- * @return the SyncData for the provider. This may be null.
- */
- public SyncData readSyncData(SyncableContentProvider contentProvider) {
- return null;
- }
-
- /**
- * Create and return a new, empty SyncData object
- */
- public SyncData newSyncData() {
- return null;
- }
-
- /**
- * Stores the sync data in the Sync Stats database, keying it by
- * the account that was set in the last call to onSyncStarting()
- */
- public void writeSyncData(SyncData syncData, SyncableContentProvider contentProvider) {}
-
- /**
- * Indicate to the SyncAdapter that the last sync that was started has
- * been cancelled.
- */
- public abstract void onSyncCanceled();
-
- /**
- * Initializes the temporary content providers used during
- * {@link TempProviderSyncAdapter#sendClientDiffs}.
- * May copy relevant data from the underlying db into this provider so
- * joins, etc., can work.
- *
- * @param cp The ContentProvider to initialize.
- */
- protected void initTempProvider(SyncableContentProvider cp) {}
-
- protected Object createSyncInfo() {
- return null;
- }
-
- /**
- * Called when the accounts list possibly changed, to give the
- * SyncAdapter a chance to do any necessary bookkeeping, e.g.
- * to make sure that any required SubscribedFeeds subscriptions
- * exist.
- * @param accounts the list of accounts
- */
- public abstract void onAccountsChanged(String[] accounts);
-
- private Context mContext;
-
- private class SyncThread extends Thread {
- private final String mAccount;
- private final Bundle mExtras;
- private final SyncContext mSyncContext;
- private volatile boolean mIsCanceled = false;
- private long mInitialTxBytes;
- private long mInitialRxBytes;
- private final SyncResult mResult;
-
- SyncThread(SyncContext syncContext, String account, Bundle extras) {
- super("SyncThread");
- mAccount = account;
- mExtras = extras;
- mSyncContext = syncContext;
- mResult = new SyncResult();
- }
-
- void cancelSync() {
- mIsCanceled = true;
- if (mAdapterSyncStarted) onSyncCanceled();
- if (mProviderSyncStarted) mProvider.onSyncCanceled();
- // We may lose the last few sync events when canceling. Oh well.
- int uid = Process.myUid();
- logSyncDetails(NetStat.getUidTxBytes(uid) - mInitialTxBytes,
- NetStat.getUidRxBytes(uid) - mInitialRxBytes, mResult);
- }
-
- @Override
- public void run() {
- Process.setThreadPriority(Process.myTid(),
- Process.THREAD_PRIORITY_BACKGROUND);
- int uid = Process.myUid();
- mInitialTxBytes = NetStat.getUidTxBytes(uid);
- mInitialRxBytes = NetStat.getUidRxBytes(uid);
- try {
- sync(mSyncContext, mAccount, mExtras);
- } catch (SQLException e) {
- Log.e(TAG, "Sync failed", e);
- mResult.databaseError = true;
- } finally {
- mSyncThread = null;
- if (!mIsCanceled) {
- logSyncDetails(NetStat.getUidTxBytes(uid) - mInitialTxBytes,
- NetStat.getUidRxBytes(uid) - mInitialRxBytes, mResult);
- mSyncContext.onFinished(mResult);
- }
- }
- }
-
- private void sync(SyncContext syncContext, String account, Bundle extras) {
- mIsCanceled = false;
-
- mProviderSyncStarted = false;
- mAdapterSyncStarted = false;
- String message = null;
-
- boolean syncForced = extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false);
-
- try {
- mProvider.onSyncStart(syncContext, account);
- mProviderSyncStarted = true;
- onSyncStarting(syncContext, account, syncForced, mResult);
- if (mResult.hasError()) {
- message = "SyncAdapter failed while trying to start sync";
- return;
- }
- mAdapterSyncStarted = true;
- if (mIsCanceled) {
- return;
- }
- final String syncTracingEnabledValue = SystemProperties.get(TAG + "Tracing");
- final boolean syncTracingEnabled = !TextUtils.isEmpty(syncTracingEnabledValue);
- try {
- if (syncTracingEnabled) {
- System.gc();
- System.gc();
- Debug.startMethodTracing("synctrace." + System.currentTimeMillis());
- }
- runSyncLoop(syncContext, account, extras);
- } finally {
- if (syncTracingEnabled) Debug.stopMethodTracing();
- }
- onSyncEnding(syncContext, !mResult.hasError());
- mAdapterSyncStarted = false;
- mProvider.onSyncStop(syncContext, true);
- mProviderSyncStarted = false;
- } finally {
- if (mAdapterSyncStarted) {
- mAdapterSyncStarted = false;
- onSyncEnding(syncContext, false);
- }
- if (mProviderSyncStarted) {
- mProviderSyncStarted = false;
- mProvider.onSyncStop(syncContext, false);
- }
- if (!mIsCanceled) {
- if (message != null) syncContext.setStatusText(message);
- }
- }
- }
-
- private void runSyncLoop(SyncContext syncContext, String account, Bundle extras) {
- TimingLogger syncTimer = new TimingLogger(TAG + "Profiling", "sync");
- syncTimer.addSplit("start");
- int loopCount = 0;
- boolean tooManyGetServerDiffsAttempts = false;
-
- final boolean overrideTooManyDeletions =
- extras.getBoolean(ContentResolver.SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS,
- false);
- final boolean discardLocalDeletions =
- extras.getBoolean(ContentResolver.SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS, false);
- boolean uploadOnly = extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD,
- false /* default this flag to false */);
- SyncableContentProvider serverDiffs = null;
- TempProviderSyncResult result = new TempProviderSyncResult();
- try {
- if (!uploadOnly) {
- /**
- * This loop repeatedly calls SyncAdapter.getServerDiffs()
- * (to get changes from the feed) followed by
- * ContentProvider.merge() (to incorporate these changes
- * into the provider), stopping when the SyncData returned
- * from getServerDiffs() indicates that all the data was
- * fetched.
- */
- while (!mIsCanceled) {
- // Don't let a bad sync go forever
- if (loopCount++ == MAX_GET_SERVER_DIFFS_LOOP_COUNT) {
- Log.e(TAG, "runSyncLoop: Hit max loop count while getting server diffs "
- + getClass().getName());
- // TODO: change the structure here to schedule a new sync
- // with a backoff time, keeping track to be sure
- // we don't keep doing this forever (due to some bug or
- // mismatch between the client and the server)
- tooManyGetServerDiffsAttempts = true;
- break;
- }
-
- // Get an empty content provider to put the diffs into
- if (serverDiffs != null) serverDiffs.close();
- serverDiffs = mProvider.getTemporaryInstance();
-
- // Get records from the server which will be put into the serverDiffs
- initTempProvider(serverDiffs);
- Object syncInfo = createSyncInfo();
- SyncData syncData = readSyncData(serverDiffs);
- // syncData will only be null if there was a demarshalling error
- // while reading the sync data.
- if (syncData == null) {
- mProvider.wipeAccount(account);
- syncData = newSyncData();
- }
- mResult.clear();
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "runSyncLoop: running getServerDiffs using syncData "
- + syncData.toString());
- }
- getServerDiffs(syncContext, syncData, serverDiffs, extras, syncInfo,
- mResult);
-
- if (mIsCanceled) return;
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "runSyncLoop: result: " + mResult);
- }
- if (mResult.hasError()) return;
- if (mResult.partialSyncUnavailable) {
- if (Config.LOGD) {
- Log.d(TAG, "partialSyncUnavailable is set, setting "
- + "ignoreSyncData and retrying");
- }
- mProvider.wipeAccount(account);
- continue;
- }
-
- // write the updated syncData back into the temp provider
- writeSyncData(syncData, serverDiffs);
-
- // apply the downloaded changes to the provider
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "runSyncLoop: running merge");
- }
- mProvider.merge(syncContext, serverDiffs,
- null /* don't return client diffs */, mResult);
- if (mIsCanceled) return;
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "runSyncLoop: result: " + mResult);
- }
-
- // if the server has no more changes then break out of the loop
- if (!mResult.moreRecordsToGet) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "runSyncLoop: fetched all data, moving on");
- }
- break;
- }
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "runSyncLoop: more data to fetch, looping");
- }
- }
- }
-
- /**
- * This loop repeatedly calls ContentProvider.merge() followed
- * by SyncAdapter.merge() until either indicate that there is
- * no more work to do by returning null.
- * <p>
- * The initial ContentProvider.merge() returns a temporary
- * ContentProvider that contains any local changes that need
- * to be committed to the server.
- * <p>
- * The SyncAdapter.merge() calls upload the changes to the server
- * and populates temporary provider (the serverDiffs) with the
- * result.
- * <p>
- * Subsequent calls to ContentProvider.merge() incoporate the
- * result of previous SyncAdapter.merge() calls into the
- * real ContentProvider and again return a temporary
- * ContentProvider that contains any local changes that need
- * to be committed to the server.
- */
- loopCount = 0;
- boolean readOnly = isReadOnly();
- long previousNumModifications = 0;
- if (serverDiffs != null) {
- serverDiffs.close();
- serverDiffs = null;
- }
-
- // If we are discarding local deletions then we need to redownload all the items
- // again (since some of them might have been deleted). We do this by deleting the
- // sync data for the current account by writing in a null one.
- if (discardLocalDeletions) {
- serverDiffs = mProvider.getTemporaryInstance();
- initTempProvider(serverDiffs);
- writeSyncData(null, serverDiffs);
- }
-
- while (!mIsCanceled) {
- if (Config.LOGV) {
- Log.v(TAG, "runSyncLoop: Merging diffs from server to client");
- }
- if (result.tempContentProvider != null) {
- result.tempContentProvider.close();
- result.tempContentProvider = null;
- }
- mResult.clear();
- mProvider.merge(syncContext, serverDiffs, readOnly ? null : result,
- mResult);
- if (mIsCanceled) return;
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "runSyncLoop: result: " + mResult);
- }
-
- SyncableContentProvider clientDiffs =
- readOnly ? null : result.tempContentProvider;
- if (clientDiffs == null) {
- // Nothing to commit back to the server
- if (Config.LOGV) Log.v(TAG, "runSyncLoop: No client diffs");
- break;
- }
-
- long numModifications = mResult.stats.numUpdates
- + mResult.stats.numDeletes
- + mResult.stats.numInserts;
-
- // as long as we are making progress keep resetting the loop count
- if (numModifications < previousNumModifications) {
- loopCount = 0;
- }
- previousNumModifications = numModifications;
-
- // Don't let a bad sync go forever
- if (loopCount++ >= MAX_UPLOAD_CHANGES_LOOP_COUNT) {
- Log.e(TAG, "runSyncLoop: Hit max loop count while syncing "
- + getClass().getName());
- mResult.tooManyRetries = true;
- break;
- }
-
- if (!overrideTooManyDeletions && !discardLocalDeletions
- && hasTooManyDeletions(mResult.stats)) {
- if (Config.LOGD) {
- Log.d(TAG, "runSyncLoop: Too many deletions were found in provider "
- + getClass().getName() + ", not doing any more updates");
- }
- long numDeletes = mResult.stats.numDeletes;
- mResult.stats.clear();
- mResult.tooManyDeletions = true;
- mResult.stats.numDeletes = numDeletes;
- break;
- }
-
- if (Config.LOGV) Log.v(TAG, "runSyncLoop: Merging diffs from client to server");
- if (serverDiffs != null) serverDiffs.close();
- serverDiffs = clientDiffs.getTemporaryInstance();
- initTempProvider(serverDiffs);
- mResult.clear();
- sendClientDiffs(syncContext, clientDiffs, serverDiffs, mResult,
- discardLocalDeletions);
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "runSyncLoop: result: " + mResult);
- }
-
- if (!mResult.madeSomeProgress()) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "runSyncLoop: No data from client diffs merge");
- }
- break;
- }
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "runSyncLoop: made some progress, looping");
- }
- }
-
- // add in any status codes that we saved from earlier
- mResult.tooManyRetries |= tooManyGetServerDiffsAttempts;
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "runSyncLoop: final result: " + mResult);
- }
- } finally {
- // do this in the finally block to guarantee that is is set and not overwritten
- if (discardLocalDeletions) {
- mResult.fullSyncRequested = true;
- }
- if (serverDiffs != null) serverDiffs.close();
- if (result.tempContentProvider != null) result.tempContentProvider.close();
- syncTimer.addSplit("stop");
- syncTimer.dumpToLog();
- }
- }
- }
-
- /**
- * Logs details on the sync.
- * Normally this will be overridden by a subclass that will provide
- * provider-specific details.
- *
- * @param bytesSent number of bytes the sync sent over the network
- * @param bytesReceived number of bytes the sync received over the network
- * @param result The SyncResult object holding info on the sync
- */
- protected void logSyncDetails(long bytesSent, long bytesReceived, SyncResult result) {
- EventLog.writeEvent(SyncAdapter.LOG_SYNC_DETAILS, TAG, bytesSent, bytesReceived, "");
- }
-
- public void startSync(SyncContext syncContext, String account, Bundle extras) {
- if (mSyncThread != null) {
- syncContext.onFinished(SyncResult.ALREADY_IN_PROGRESS);
- return;
- }
-
- mSyncThread = new SyncThread(syncContext, account, extras);
- mSyncThread.start();
- }
-
- public void cancelSync() {
- if (mSyncThread != null) {
- mSyncThread.cancelSync();
- }
- }
-
- protected boolean hasTooManyDeletions(SyncStats stats) {
- long numEntries = stats.numEntries;
- long numDeletedEntries = stats.numDeletes;
-
- long percentDeleted = (numDeletedEntries == 0)
- ? 0
- : (100 * numDeletedEntries /
- (numEntries + numDeletedEntries));
- boolean tooManyDeletions =
- (numDeletedEntries > NUM_ALLOWED_SIMULTANEOUS_DELETIONS)
- && (percentDeleted > PERCENT_ALLOWED_SIMULTANEOUS_DELETIONS);
- return tooManyDeletions;
- }
-}
diff --git a/core/java/android/content/TempProviderSyncResult.java b/core/java/android/content/TempProviderSyncResult.java
deleted file mode 100644
index 81f6f79..0000000
--- a/core/java/android/content/TempProviderSyncResult.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-/**
- * Used to hold data returned from a given phase of a TempProviderSync.
- * @hide
- */
-public class TempProviderSyncResult {
- /**
- * An interface to a temporary content provider that contains
- * the result of updates that were sent to the server. This
- * provider must be merged into the permanent content provider.
- * This may be null, which indicates that there is nothing to
- * merge back into the content provider.
- */
- public SyncableContentProvider tempContentProvider;
-
- public TempProviderSyncResult() {
- tempContentProvider = null;
- }
-}
diff --git a/core/java/android/content/UriMatcher.java b/core/java/android/content/UriMatcher.java
deleted file mode 100644
index a98e6d5..0000000
--- a/core/java/android/content/UriMatcher.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.net.Uri;
-
-import java.util.ArrayList;
-import java.util.regex.Pattern;
-
-/**
-Utility class to aid in matching URIs in content providers.
-
-<p>To use this class, build up a tree of UriMatcher objects.
-Typically, it looks something like this:
-<pre>
- private static final int PEOPLE = 1;
- private static final int PEOPLE_ID = 2;
- private static final int PEOPLE_PHONES = 3;
- private static final int PEOPLE_PHONES_ID = 4;
- private static final int PEOPLE_CONTACTMETHODS = 7;
- private static final int PEOPLE_CONTACTMETHODS_ID = 8;
-
- private static final int DELETED_PEOPLE = 20;
-
- private static final int PHONES = 9;
- private static final int PHONES_ID = 10;
- private static final int PHONES_FILTER = 14;
-
- private static final int CONTACTMETHODS = 18;
- private static final int CONTACTMETHODS_ID = 19;
-
- private static final int CALLS = 11;
- private static final int CALLS_ID = 12;
- private static final int CALLS_FILTER = 15;
-
- private static final UriMatcher sURIMatcher = new UriMatcher();
-
- static
- {
- sURIMatcher.addURI("contacts", "/people", PEOPLE);
- sURIMatcher.addURI("contacts", "/people/#", PEOPLE_ID);
- sURIMatcher.addURI("contacts", "/people/#/phones", PEOPLE_PHONES);
- sURIMatcher.addURI("contacts", "/people/#/phones/#", PEOPLE_PHONES_ID);
- sURIMatcher.addURI("contacts", "/people/#/contact_methods", PEOPLE_CONTACTMETHODS);
- sURIMatcher.addURI("contacts", "/people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID);
- sURIMatcher.addURI("contacts", "/deleted_people", DELETED_PEOPLE);
- sURIMatcher.addURI("contacts", "/phones", PHONES);
- sURIMatcher.addURI("contacts", "/phones/filter/*", PHONES_FILTER);
- sURIMatcher.addURI("contacts", "/phones/#", PHONES_ID);
- sURIMatcher.addURI("contacts", "/contact_methods", CONTACTMETHODS);
- sURIMatcher.addURI("contacts", "/contact_methods/#", CONTACTMETHODS_ID);
- sURIMatcher.addURI("call_log", "/calls", CALLS);
- sURIMatcher.addURI("call_log", "/calls/filter/*", CALLS_FILTER);
- sURIMatcher.addURI("call_log", "/calls/#", CALLS_ID);
- }
-</pre>
-<p>Then when you need to match match against a URI, call {@link #match}, providing
-the tokenized url you've been given, and the value you want if there isn't
-a match. You can use the result to build a query, return a type, insert or
-delete a row, or whatever you need, without duplicating all of the if-else
-logic you'd otherwise need. Like this:
-<pre>
- public String getType(String[] url)
- {
- int match = sURIMatcher.match(url, NO_MATCH);
- switch (match)
- {
- case PEOPLE:
- return "vnd.android.cursor.dir/person";
- case PEOPLE_ID:
- return "vnd.android.cursor.item/person";
-... snip ...
- return "vnd.android.cursor.dir/snail-mail";
- case PEOPLE_ADDRESS_ID:
- return "vnd.android.cursor.item/snail-mail";
- default:
- return null;
- }
- }
-</pre>
-instead of
-<pre>
- public String getType(String[] url)
- {
- if (url.length >= 2) {
- if (url[1].equals("people")) {
- if (url.length == 2) {
- return "vnd.android.cursor.dir/person";
- } else if (url.length == 3) {
- return "vnd.android.cursor.item/person";
-... snip ...
- return "vnd.android.cursor.dir/snail-mail";
- } else if (url.length == 3) {
- return "vnd.android.cursor.item/snail-mail";
- }
- }
- }
- return null;
- }
-</pre>
-*/
-public class UriMatcher
-{
- public static final int NO_MATCH = -1;
- /**
- * Creates the root node of the URI tree.
- *
- * @param code the code to match for the root URI
- */
- public UriMatcher(int code)
- {
- mCode = code;
- mWhich = -1;
- mChildren = new ArrayList<UriMatcher>();
- mText = null;
- }
-
- private UriMatcher()
- {
- mCode = NO_MATCH;
- mWhich = -1;
- mChildren = new ArrayList<UriMatcher>();
- mText = null;
- }
-
- /**
- * Add a URI to match, and the code to return when this URI is
- * matched. URI nodes may be exact match string, the token "*"
- * that matches any text, or the token "#" that matches only
- * numbers.
- *
- * @param authority the authority to match
- * @param path the path to match. * may be used as a wild card for
- * any text, and # may be used as a wild card for numbers.
- * @param code the code that is returned when a URI is matched
- * against the given components. Must be positive.
- */
- public void addURI(String authority, String path, int code)
- {
- if (code < 0) {
- throw new IllegalArgumentException("code " + code + " is invalid: it must be positive");
- }
- String[] tokens = path != null ? PATH_SPLIT_PATTERN.split(path) : null;
- int numTokens = tokens != null ? tokens.length : 0;
- UriMatcher node = this;
- for (int i = -1; i < numTokens; i++) {
- String token = i < 0 ? authority : tokens[i];
- ArrayList<UriMatcher> children = node.mChildren;
- int numChildren = children.size();
- UriMatcher child;
- int j;
- for (j = 0; j < numChildren; j++) {
- child = children.get(j);
- if (token.equals(child.mText)) {
- node = child;
- break;
- }
- }
- if (j == numChildren) {
- // Child not found, create it
- child = new UriMatcher();
- if (token.equals("#")) {
- child.mWhich = NUMBER;
- } else if (token.equals("*")) {
- child.mWhich = TEXT;
- } else {
- child.mWhich = EXACT;
- }
- child.mText = token;
- node.mChildren.add(child);
- node = child;
- }
- }
- node.mCode = code;
- }
-
- static final Pattern PATH_SPLIT_PATTERN = Pattern.compile("/");
-
- /**
- * Try to match against the path in a url.
- *
- * @param uri The url whose path we will match against.
- *
- * @return The code for the matched node (added using addURI),
- * or -1 if there is no matched node.
- */
- public int match(Uri uri)
- {
- final int li = uri.getPathSegments().size();
-
- UriMatcher node = this;
-
- if (li == 0 && uri.getAuthority() == null) {
- return this.mCode;
- }
-
- for (int i=-1; i<li; i++) {
- String u = i < 0 ? uri.getAuthority() : uri.getPathSegments().get(i);
- ArrayList<UriMatcher> list = node.mChildren;
- if (list == null) {
- break;
- }
- node = null;
- int lj = list.size();
- for (int j=0; j<lj; j++) {
- UriMatcher n = list.get(j);
- which_switch:
- switch (n.mWhich) {
- case EXACT:
- if (n.mText.equals(u)) {
- node = n;
- }
- break;
- case NUMBER:
- int lk = u.length();
- for (int k=0; k<lk; k++) {
- char c = u.charAt(k);
- if (c < '0' || c > '9') {
- break which_switch;
- }
- }
- node = n;
- break;
- case TEXT:
- node = n;
- break;
- }
- if (node != null) {
- break;
- }
- }
- if (node == null) {
- return NO_MATCH;
- }
- }
-
- return node.mCode;
- }
-
- private static final int EXACT = 0;
- private static final int NUMBER = 1;
- private static final int TEXT = 2;
-
- private int mCode;
- private int mWhich;
- private String mText;
- private ArrayList<UriMatcher> mChildren;
-}
diff --git a/core/java/android/content/package.html b/core/java/android/content/package.html
deleted file mode 100644
index dd5360f..0000000
--- a/core/java/android/content/package.html
+++ /dev/null
@@ -1,650 +0,0 @@
-<html>
-<head>
-<script type="text/javascript" src="http://www.corp.google.com/style/prettify.js"></script>
-<script src="http://www.corp.google.com/eng/techpubs/include/navbar.js" type="text/javascript"></script>
-</head>
-
-<body>
-
-<p>Contains classes for accessing and publishing data
-on the device. It includes three main categories of APIs:
-the {@link android.content.res.Resources Resources} for
-retrieving resource data associated with an application;
-{@link android.content.ContentProvider Content Providers} and
-{@link android.content.ContentResolver ContentResolver} for managing and
-publishing persistent data associated with an application; and
-the {@link android.content.pm.PackageManager Package Manager}
-for finding out information about the application packages installed
-on the device.</p>
-
-<p>In addition, the {@link android.content.Context Context} abstract class
-is a base API for pulling these pieces together, allowing you to access
-an application's resources and transfer data between applications.</p>
-
-<p>This package builds on top of the lower-level Android packages
-{@link android.database}, {@link android.text},
-{@link android.graphics.drawable}, {@link android.graphics},
-{@link android.os}, and {@link android.util}.</p>
-
-<ol>
- <li> <a href="#Resources">Resources</a>
- <ol>
- <li> <a href="#ResourcesTerminology">Terminology</a>
- <li> <a href="#ResourcesQuickStart">Examples</a>
- <ol>
- <li> <a href="#UsingSystemResources">Using System Resources</a>
- <li> <a href="#StringResources">String Resources</a>
- <li> <a href="#ColorResources">Color Resources</a>
- <li> <a href="#DrawableResources">Drawable Resources</a>
- <li> <a href="#LayoutResources">Layout Resources</a>
- <li> <a href="#ReferencesToResources">References to Resources</a>
- <li> <a href="#ReferencesToThemeAttributes">References to Theme Attributes</a>
- <li> <a href="#StyleResources">Style Resources</a>
- <li> <a href="#StylesInLayoutResources">Styles in Layout Resources</a>
- </ol>
- </ol>
-</ol>
-
-<a name="Resources"></a>
-<h2>Resources</h2>
-
-<p>This topic includes a terminology list associated with resources, and a series
- of examples of using resources in code. For a complete guide on creating and
- using resources, see the document on <a href="{@docRoot}guide/topics/resources/resources-i18n.html">Resources
- and Internationalization</a>. For a reference on the supported Android resource types,
- see <a href="{@docRoot}guide/topics/resources/available-resources.html">Available Resource Types</a>.</p>
-<p>The Android resource system keeps track of all non-code
- assets associated with an application. You use the
- {@link android.content.res.Resources Resources} class to access your
- application's resources; the Resources instance associated with your
- application can generally be found through
- {@link android.content.Context#getResources Context.getResources()}.</p>
-<p>An application's resources are compiled into the application
-binary at build time for you by the build system. To use a resource,
-you must install it correctly in the source tree and build your
-application. As part of the build process, Java symbols for each
-of the resources are generated that you can use in your source
-code -- this allows the compiler to verify that your application code matches
-up with the resources you defined.</p>
-
-<p>The rest of this section is organized as a tutorial on how to
-use resources in an application.</p>
-
-<a name="ResourcesTerminology"></a>
-<h3>Terminology</h3>
-
-<p>The resource system brings a number of different pieces together to
-form the final complete resource functionality. To help understand the
-overall system, here are some brief definitions of the core concepts and
-components you will encounter in using it:</p>
-
-<p><b>Asset</b>: A single blob of data associated with an application. This
-includes Java object files, graphics (such as PNG images), XML files, etc.
-These files are organized in a directory hierarchy that, during final packaging
-of the application, is bundled together into a single ZIP file.</p>
-
-<p><b>aapt</b>: The tool that generates the final ZIP file of application
-assets. In addition to collecting raw assets together, it also parses
-resource definitions into binary asset data.</p>
-
-<p><b>Resource Table</b>: A special asset that aapt generates for you,
-describing all of the resources contained in an application/package.
-This file is accessed for you by the Resources class; it is not touched
-directly by applications.</p>
-
-<p><b>Resource</b>: An entry in the Resource Table describing a single
-named value. Broadly, there are two types of resources: primitives and
-bags.</p>
-
-<p><b>Resource Identifier</b>: In the Resource Table all resources are
-identified by a unique integer number. In source code (resource descriptions,
-XML files, Java code) you can use symbolic names that stand as constants for
-the actual resource identifier integer.</p>
-
-<p><b>Primitive Resource</b>: All primitive resources can be written as a
-simple string, using formatting to describe a variety of primitive types
-included in the resource system: integers, colors, strings, references to
-other resources, etc. Complex resources, such as bitmaps and XML
-describes, are stored as a primitive string resource whose value is the path
-of the underlying Asset holding its actual data.</p>
-
-<p><b>Bag Resource</b>: A special kind of resource entry that, instead of a
-simple string, holds an arbitrary list of name/value pairs. Each name is
-itself a resource identifier, and each value can hold
-the same kinds of string formatted data as a normal resource. Bags also
-support inheritance: a bag can inherit the values from another bag, selectively
-replacing or extending them to generate its own contents.</p>
-
-<p><b>Kind</b>: The resource kind is a way to organize resource identifiers
-for various purposes. For example, drawable resources are used to
-instantiate Drawable objects, so their data is a primitive resource containing
-either a color constant or string path to a bitmap or XML asset. Other
-common resource kinds are string (localized string primitives), color
-(color primitives), layout (a string path to an XML asset describing a view
-layout), and style (a bag resource describing user interface attributes).
-There is also a standard "attr" resource kind, which defines the resource
-identifiers to be used for naming bag items and XML attributes</p>
-
-<p><b>Style</b>: The name of the resource kind containing bags that are used
-to supply a set of user interface attributes. For example, a TextView class may
-be given a style resource that defines its text size, color, and alignment.
-In a layout XML file, you associate a style with a bag using the "style"
-attribute, whose value is the name of the style resource.</p>
-
-<p><b>Style Class</b>: Specifies a related set of attribute resources.
-This data is not placed in the resource table itself, but used to generate
-Java constants that make it easier for you to retrieve values out of
-a style resource and/or XML tag's attributes. For example, the
-Android platform defines a "View" style class that
-contains all of the standard view attributes: padding, visibility,
-background, etc.; when View is inflated it uses this style class to
-retrieve those values from the XML file (at which point style and theme
-information is applied as approriate) and load them into its instance.</p>
-
-<p><b>Configuration</b>: For any particular resource identifier, there may be
-multiple different available values depending on the current configuration.
-The configuration includes the locale (language and country), screen
-orientation, screen density, etc. The current configuration is used to
-select which resource values are in effect when the resource table is
-loaded.</p>
-
-<p><b>Theme</b>: A standard style resource that supplies global
-attribute values for a particular context. For example, when writing a
-Activity the application developer can select a standard theme to use, such
-as the Theme.White or Theme.Black styles; this style supplies information
-such as the screen background image/color, default text color, button style,
-text editor style, text size, etc. When inflating a layout resource, most
-values for widgets (the text color, selector, background) if not explicitly
-set will come from the current theme; style and attribute
-values supplied in the layout can also assign their value from explicitly
-named values in the theme attributes if desired.</p>
-
-<p><b>Overlay</b>: A resource table that does not define a new set of resources,
-but instead replaces the values of resources that are in another resource table.
-Like a configuration, this is applied at load time
-to the resource data; it can add new configuration values (for example
-strings in a new locale), replace existing values (for example change
-the standard white background image to a "Hello Kitty" background image),
-and modify resource bags (for example change the font size of the Theme.White
-style to have an 18 pt font size). This is the facility that allows the
-user to select between different global appearances of their device, or
-download files with new appearances.</p>
-
-<a name="ResourcesQuickStart"></a>
-<h3>Examples</h3>
-
-<p>This section gives a few quick examples you can use to make your own resources.
- For more details on how to define and use resources, see <a
- href="{@docRoot}guide/topics/resources/resources-i18n.html">Resources and
- Internationalization</a>. </p>
-
-<a name="UsingSystemResources"></a>
-<h4>Using System Resources</h4>
-
-<p>Many resources included with the system are available to applications.
-All such resources are defined under the class "android.R". For example,
-you can display the standard application icon in a screen with the following
-code:</p>
-
-<pre class="prettyprint">
-public class MyActivity extends Activity
-{
- public void onStart()
- {
- requestScreenFeatures(FEATURE_BADGE_IMAGE);
-
- super.onStart();
-
- setBadgeResource(android.R.drawable.sym_def_app_icon);
- }
-}
-</pre>
-
-<p>In a similar way, this code will apply to your screen the standard
-"green background" visual treatment defined by the system:</p>
-
-<pre class="prettyprint">
-public class MyActivity extends Activity
-{
- public void onStart()
- {
- super.onStart();
-
- setTheme(android.R.style.Theme_Black);
- }
-}
-</pre>
-
-<a name="StringResources"></a>
-<h4>String Resources</h4>
-
-<p>String resources are defined using an XML resource description syntax.
-The file or multiple files containing these resources can be given any name
-(as long as it has a .xml suffix) and placed at an appropriate location in
-the source tree for the desired configuration (locale/orientation/density).
-
-<p>Here is a simple resource file describing a few strings:</p>
-
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?&gt;
-&lt;resources&gt;
- &lt;string id="mainLabel"&gt;Hello &lt;u&gt;th&lt;ignore&gt;e&lt;/ignore&gt;re&lt;/u&gt;, &lt;i&gt;you&lt;/i&gt; &lt;b&gt;Activity&lt;/b&gt;!&lt;/string&gt;
- &lt;string id="back"&gt;Back&lt;/string&gt;
- &lt;string id="clear"&gt;Clear&lt;/string&gt;
-&lt;/resources&gt;
-</pre>
-
-<p>Typically this file will be called "strings.xml", and must be placed
-in the <code>values</code> directory:</p>
-
-<pre>
-MyApp/res/values/strings.xml
-</pre>
-
-<p>The strings can now be retrieved by your application through the
-symbol specified in the "id" attribute:</p>
-
-<pre class="prettyprint">
-public class MyActivity extends Activity
-{
- public void onStart()
- {
- super.onStart();
-
- String back = getResources().getString(R.string.back).toString();
- back = getString(R.string.back).toString(); // synonym
- }
-}
-</pre>
-
-<p>Unlike system resources, the resource symbol (the R class) we are using
-here comes from our own application's package, not android.R.</p>
-
-<p>Note that the "mainLabel" string is complex, including style information.
-To support this, the <code>getString()</code> method returns a
-<code>CharSequence</code> object that you can pass to a
-<code>TextView</code> to retain those style. This is why code
-must call <code>toString()</code> on the returned resource if it wants
-a raw string.</p>
-
-<a name="ColorResources"></a>
-<h4>Color Resources</h4>
-
-<p>Color resources are created in a way very similar to string resources,
-but with the &lt;color&gt; resource tag. The data for these resources
-must be a hex color constant of the form "#rgb", "#argb", "#rrggbb", or
-"#aarrggbb". The alpha channel is 0xff (or 0xf) for opaque and 0
-for transparent.</p>
-
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?&gt;
-&lt;resources&gt;
- &lt;color id="opaque_red"&gt;#ffff0000&lt;/color&gt;
- &lt;color id="transparent_red"&gt;#80ff0000&lt;/color&gt;
- &lt;color id="opaque_blue"&gt;#0000ff&lt;/color&gt;
- &lt;color id="opaque_green"&gt;#0f0&lt;/color&gt;
-&lt;/resources&gt;
-</pre>
-
-<p>While color definitions could be placed in the same resource file
-as the previously shown string data, usually you will place the colors in
-their own file:</p>
-
-<pre>
-MyApp/res/values/colors.xml
-</pre>
-
-<p>The colors can now be retrieved by your application through the
-symbol specified in the "id" attribute:</p>
-
-<pre class="prettyprint">
-public class MyActivity extends Activity
-{
- public void onStart()
- {
- super.onStart();
-
- int red = getResources().getColor(R.color.opaque_red);
- }
-}
-</pre>
-
-<a name="DrawableResources"></a>
-<h4>Drawable Resources</h4>
-
-<p>For simple drawable resources, all you need to do is place your
-image in a special resource sub-directory called "drawable". Files here
-are things that can be handled by an implementation of the
-{@link android.graphics.drawable.Drawable Drawable} class, often bitmaps
-(such as PNG images) but also various kinds of XML descriptions
-for selectors, gradients, etc.</p>
-
-<p>The drawable files will be scanned by the
-resource tool, automatically generating a resource entry for each found.
-For example the file <code>res/drawable/&lt;myimage&gt;.&lt;ext&gt;</code>
-will result in a resource symbol named "myimage" (without the extension). Note
-that these file names <em>must</em> be valid Java identifiers, and should
-have only lower-case letters.</p>
-
-<p>For example, to use your own custom image as a badge in a screen,
-you can place the image here:</p>
-
-<pre>
-MyApp/res/drawable/my_badge.png
-</pre>
-
-<p>The image can then be used in your code like this:</p>
-
-<pre class="prettyprint">
-public class MyActivity extends Activity
-{
- public void onStart()
- {
- requestScreenFeatures(FEATURE_BADGE_IMAGE);
-
- super.onStart();
-
- setBadgeResource(R.drawable.my_badge);
- }
-}
-</pre>
-
-<p>For drawables that are a single solid color, you can also define them
-in a resource file very much like colors shown previously. The only
-difference is that here we use the &lt;drawable&gt; tag to create a
-drawable resource.</p>
-
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?&gt;
-&lt;resources&gt;
- &lt;drawable id="opaque_red"&gt;#ffff0000&lt;/drawable&gt;
- &lt;drawable id="transparent_red"&gt;#80ff0000&lt;/drawable&gt;
- &lt;drawable id="opaque_blue"&gt;#0000ff&lt;/drawable&gt;
- &lt;drawable id="opaque_green"&gt;#0f0&lt;/drawable&gt;
-&lt;/resources&gt;
-</pre>
-
-<p>These resource entries are often placed in the same resource file
-as color definitions:</p>
-
-<pre>
-MyApp/res/values/colors.xml
-</pre>
-
-<a name="LayoutResources"></a>
-<h4>Layout Resources</h4>
-
-<p>Layout resources describe a view hierarchy configuration that is
-generated at runtime. These resources are XML files placed in the
-resource directory "layout", and are how you should create the content
-views inside of your screen (instead of creating them by hand) so that
-they can be themed, styled, configured, and overlayed.</p>
-
-<p>Here is a simple layout resource consisting of a single view, a text
-editor:</p>
-
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?&gt;
-&lt;root&gt;
- &lt;EditText id="text"
- android:layout_width="fill-parent" android:layout_height="fill-parent"
- android:text="Hello, World!" /&gt;
-&lt;/root&gt;
-</pre>
-
-<p>To use this layout, it can be placed in a file like this:</p>
-
-<pre>
-MyApp/res/layout/my_layout.xml
-</pre>
-
-<p>The layout can then be instantiated in your screen like this:</p>
-
-<pre class="prettyprint">
-public class MyActivity extends Activity
-{
- public void onStart()
- {
- super.onStart();
- setContentView(R.layout.my_layout);
- }
-}
-</pre>
-
-<p>Note that there are a number of visual attributes that can be supplied
-to TextView (including textSize, textColor, and textStyle) that we did
-not define in the previous example; in such a sitation, the default values for
-those attributes come from the theme. If we want to customize them, we
-can supply them explicitly in the XML file:</p>
-
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?&gt;
-&lt;root&gt;
- &lt;EditText id="text"
- android:layout_width="fill_parent" android:layout_height="fill_parent"
- <b>android:textSize="18" android:textColor="#008"</b>
- android:text="Hello, World!" /&gt;
-&lt;/root&gt;
-</pre>
-
-<p>However, usually these kinds of attributes (those being attributes that
-usually make sense to vary with theme or overlay) should be defined through
-the theme or separate style resource. Later we will see how this is done.</p>
-
-<a name="ReferencesToResources"></a>
-<h4>References to Resources</h4>
-
-<p>A value supplied in an attribute (or resource) can also be a reference to
-a resource. This is often used in layout files to supply strings (so they
-can be localized) and images (which exist in another file), though a reference
-can be do any resource type including colors and integers.</p>
-
-<p>For example, if we have the previously defined color resources, we can
-write a layout file that sets the text color size to be the value contained in
-one of those resources:</p>
-
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?&gt;
-&lt;root&gt;
- &lt;EditText id="text"
- android:layout_width="fill_parent" android:layout_height="fill_parent"
- <b>android:textColor="@color/opaque_red"</b>
- android:text="Hello, World!" /&gt;
-&lt;/root&gt;
-</pre>
-
-<p>Note here the use of the '@' prefix to introduce a resource reference -- the
-text following that is the name of a resource in the form
-of <code>@[package:]type/name</code>. In this case we didn't need to specify
-the package because we are referencing a resource in our own package. To
-reference a system resource, you would need to write:</p>
-
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?&gt;
-&lt;root&gt;
- &lt;EditText id="text"
- android:layout_width="fill_parent" android:layout_height="fill_parent"
- android:textColor="@<b>android:</b>color/opaque_red"
- android:text="Hello, World!" /&gt;
-&lt;/root&gt;
-</pre>
-
-<p>As another example, you should always use resource references when supplying
-strings in a layout file so that they can be localized:</p>
-
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?&gt;
-&lt;root&gt;
- &lt;EditText id="text"
- android:layout_width="fill_parent" android:layout_height="fill_parent"
- android:textColor="@android:color/opaque_red"
- android:text="@string/hello_world" /&gt;
-&lt;/root&gt;
-</pre>
-
-<p>This facility can also be used to create references between resources.
-For example, we can create new drawable resources that are aliases for
-existing images:</p>
-
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?&gt;
-&lt;resources&gt;
- &lt;drawable id="my_background"&gt;@android:drawable/theme2_background&lt;/drawable&gt;
-&lt;/resources&gt;
-</pre>
-
-<a name="ReferencesToThemeAttributes"></a>
-<h4>References to Theme Attributes</h4>
-
-<p>Another kind of resource value allows you to reference the value of an
-attribute in the current theme. This attribute reference can <em>only</em>
-be used in style resources and XML attributes; it allows you to customize the
-look of UI elements by changing them to standard variations supplied by the
-current theme, instead of supplying more concrete values.</p>
-
-<p>As an example, we can use this in our layout to set the text color to
-one of the standard colors defined in the base system theme:</p>
-
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?&gt;
-&lt;root&gt;
- &lt;EditText id="text"
- android:layout_width="fill_parent" android:layout_height="fill_parent"
- <b>android:textColor="?android:textDisabledColor"</b>
- android:text="@string/hello_world" /&gt;
-&lt;/root&gt;
-</pre>
-
-<p>Note that this is very similar to a resource reference, except we are using
-an '?' prefix instead of '@'. When you use this markup, you are supplying
-the name of an attribute resource that will be looked up in the theme --
-because the resource tool knows that an attribute resource is expected,
-you do not need to explicitly state the type (which would be
-<code>?android:attr/android:textDisabledColor</code>).</p>
-
-<p>Other than using this resource identifier to find the value in the
-theme instead of raw resources, the name syntax is identical to the '@' format:
-<code>?[package:]type/name</code> with the type here being optional.</p>
-
-<a name="StyleResources"></a>
-<h4>Style Resources</h4>
-
-<p>A style resource is a set of name/value pairs describing a group
-of related attributes. There are two main uses for these resources:
-defining overall visual themes, and describing a set of visual attributes
-to apply to a class in a layout resource. In this section we will look
-at their use to describe themes; later we will look at using them in
-conjunction with layouts.</p>
-
-<p>Like strings, styles are defined through a resource XML file. In the
-situation where we want to define a new theme, we can create a custom theme
-style that inherits from one of the standard system themes:</p>
-
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?&gt;
-&lt;resources&gt;
- &lt;style id="Theme" parent="android:Theme.White"&gt;
- &lt;item id="android:foregroundColor"&gt;#FFF8D96F&lt;/item&gt;
- &lt;item id="android:textColor"&gt;@color/opaque_blue&lt;/item&gt;
- &lt;item id="android:textSelectedColor"&gt;?android:textColor&lt;/item&gt;
- &lt;/style&gt;
-&lt;/resources&gt;
-</pre>
-
-<p>Typically these resource definitions will be placed in a file
-called "styles.xml" , and must be placed in the <code>values</code>
-directory:</p>
-
-<pre>
-MyApp/res/values/styles.xml
-</pre>
-
-<p>Similar to how we previously used a system style for an Activity theme,
-you can apply this style to your Activity:</p>
-
-<pre class="prettyprint">
-public class MyActivity extends Activity
-{
- public void onStart()
- {
- super.onStart();
-
- setTheme(R.style.Theme);
- }
-}
-</pre>
-
-<p>In the style resource shown here, we used the <code>parent</code>
-attribute to specify another style resource from which it inherits
-its values -- in this case the <code>Theme.White</code> system resource:</p>
-
-<pre>
- &lt;style id="Home" parent="android:Theme.White"&gt;
- ...
- &lt;/style&gt;
-</pre>
-
-<p>Note, when doing this, that you must use the "android" prefix in front
-to tell the compiler the namespace to look in for the resource --
-the resources you are specifying here are in your application's namespace,
-not the system. This explicit namespace specification ensures that names
-the application uses will not accidentally conflict with those defined by
-the system.</p>
-
-<p>If you don't specify an explicit parent style, it will be inferred
-from the style name -- everything before the final '.' in the name of the
-style being defined is taken as the parent style name. Thus, to make
-another style in your application that inherits from this base Theme style,
-you can write:</p>
-
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?&gt;
-&lt;resources&gt;
- &lt;style id="Theme.WhiteText"&gt;
- &lt;item id="android:foregroundColor"&gt;#FFFFFFFF&lt;/item&gt;
- &lt;item id="android:textColor"&gt;?android:foregroundColor&lt;/item&gt;
- &lt;/style&gt;
-&lt;/resources&gt;
-</pre>
-
-<p>This results in the symbol <code>R.style.Theme_WhiteText</code> that
-can be used in Java just like we did with <code>R.style.Theme</code>
-above.</p>
-
-<a name="StylesInLayoutResources"></a>
-<h4>Styles in Layout Resources</h4>
-
-<p>Often you will have a number fo views in a layout that all use the same
-set of attributes, or want to allow resource overlays to modify the values of
-attributes. Style resources can be used for both of these purposes, to put
-attribute definitions in a single place that can be references by multiple
-XML tags and modified by overlays. To do this, you simply define a
-new style resource with the desired values:</p>
-
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?&gt;
-&lt;resources&gt;
- &lt;style id="SpecialText"&gt;
- &lt;item id="android:textSize"&gt;18&lt;/item&gt;
- &lt;item id="android:textColor"&gt;#008&lt;/item&gt;
- &lt;/style&gt;
-&lt;/resources&gt;
-</pre>
-
-<p>You can now apply this style to your TextView in the XML file:</p>
-
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?&gt;
-&lt;root&gt;
- &lt;EditText id="text1" <b>style="@style/SpecialText"</b>
- android:layout_width="fill_parent" android:layout_height="wrap_content"
- android:text="Hello, World!" /&gt;
- &lt;EditText id="text2" <b>style="@style/SpecialText"</b>
- android:layout_width="fill_parent" android:layout_height="wrap_content"
- android:text="I love you all." /&gt;
-&lt;/root&gt;</pre>
-<h4>&nbsp;</h4>
-
-</body>
-</html>
-
diff --git a/core/java/android/content/pm/ActivityInfo.aidl b/core/java/android/content/pm/ActivityInfo.aidl
deleted file mode 100755
index dd90302..0000000
--- a/core/java/android/content/pm/ActivityInfo.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/view/WindowManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-parcelable ActivityInfo;
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
deleted file mode 100644
index 85d877a..0000000
--- a/core/java/android/content/pm/ActivityInfo.java
+++ /dev/null
@@ -1,353 +0,0 @@
-package android.content.pm;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Printer;
-
-/**
- * Information you can retrieve about a particular application
- * activity or receiver. This corresponds to information collected
- * from the AndroidManifest.xml's &lt;activity&gt; and
- * &lt;receiver&gt; tags.
- */
-public class ActivityInfo extends ComponentInfo
- implements Parcelable {
- /**
- * A style resource identifier (in the package's resources) of this
- * activity's theme. From the "theme" attribute or, if not set, 0.
- */
- public int theme;
-
- /**
- * Constant corresponding to <code>standard</code> in
- * the {@link android.R.attr#launchMode} attribute.
- */
- public static final int LAUNCH_MULTIPLE = 0;
- /**
- * Constant corresponding to <code>singleTop</code> in
- * the {@link android.R.attr#launchMode} attribute.
- */
- public static final int LAUNCH_SINGLE_TOP = 1;
- /**
- * Constant corresponding to <code>singleTask</code> in
- * the {@link android.R.attr#launchMode} attribute.
- */
- public static final int LAUNCH_SINGLE_TASK = 2;
- /**
- * Constant corresponding to <code>singleInstance</code> in
- * the {@link android.R.attr#launchMode} attribute.
- */
- public static final int LAUNCH_SINGLE_INSTANCE = 3;
- /**
- * The launch mode style requested by the activity. From the
- * {@link android.R.attr#launchMode} attribute, one of
- * {@link #LAUNCH_MULTIPLE},
- * {@link #LAUNCH_SINGLE_TOP}, {@link #LAUNCH_SINGLE_TASK}, or
- * {@link #LAUNCH_SINGLE_INSTANCE}.
- */
- public int launchMode;
-
- /**
- * Optional name of a permission required to be able to access this
- * Activity. From the "permission" attribute.
- */
- public String permission;
-
- /**
- * The affinity this activity has for another task in the system. The
- * string here is the name of the task, often the package name of the
- * overall package. If null, the activity has no affinity. Set from the
- * {@link android.R.attr#taskAffinity} attribute.
- */
- public String taskAffinity;
-
- /**
- * If this is an activity alias, this is the real activity class to run
- * for it. Otherwise, this is null.
- */
- public String targetActivity;
-
- /**
- * Bit in {@link #flags} indicating whether this activity is able to
- * run in multiple processes. If
- * true, the system may instantiate it in the some process as the
- * process starting it in order to conserve resources. If false, the
- * default, it always runs in {@link #processName}. Set from the
- * {@link android.R.attr#multiprocess} attribute.
- */
- public static final int FLAG_MULTIPROCESS = 0x0001;
- /**
- * Bit in {@link #flags} indicating that, when the activity's task is
- * relaunched from home, this activity should be finished.
- * Set from the
- * {@link android.R.attr#finishOnTaskLaunch} attribute.
- */
- public static final int FLAG_FINISH_ON_TASK_LAUNCH = 0x0002;
- /**
- * Bit in {@link #flags} indicating that, when the activity is the root
- * of a task, that task's stack should be cleared each time the user
- * re-launches it from home. As a result, the user will always
- * return to the original activity at the top of the task.
- * This flag only applies to activities that
- * are used to start the root of a new task. Set from the
- * {@link android.R.attr#clearTaskOnLaunch} attribute.
- */
- public static final int FLAG_CLEAR_TASK_ON_LAUNCH = 0x0004;
- /**
- * Bit in {@link #flags} indicating that, when the activity is the root
- * of a task, that task's stack should never be cleared when it is
- * relaunched from home. Set from the
- * {@link android.R.attr#alwaysRetainTaskState} attribute.
- */
- public static final int FLAG_ALWAYS_RETAIN_TASK_STATE = 0x0008;
- /**
- * Bit in {@link #flags} indicating that the activity's state
- * is not required to be saved, so that if there is a failure the
- * activity will not be removed from the activity stack. Set from the
- * {@link android.R.attr#stateNotNeeded} attribute.
- */
- public static final int FLAG_STATE_NOT_NEEDED = 0x0010;
- /**
- * Bit in {@link #flags} that indicates that the activity should not
- * appear in the list of recently launched activities. Set from the
- * {@link android.R.attr#excludeFromRecents} attribute.
- */
- public static final int FLAG_EXCLUDE_FROM_RECENTS = 0x0020;
- /**
- * Bit in {@link #flags} that indicates that the activity can be moved
- * between tasks based on its task affinity. Set from the
- * {@link android.R.attr#allowTaskReparenting} attribute.
- */
- public static final int FLAG_ALLOW_TASK_REPARENTING = 0x0040;
- /**
- * Bit in {@link #flags} indicating that, when the user navigates away
- * from an activity, it should be finished.
- * Set from the
- * {@link android.R.attr#noHistory} attribute.
- */
- public static final int FLAG_NO_HISTORY = 0x0080;
- /**
- * Options that have been set in the activity declaration in the
- * manifest: {@link #FLAG_MULTIPROCESS},
- * {@link #FLAG_FINISH_ON_TASK_LAUNCH}, {@link #FLAG_CLEAR_TASK_ON_LAUNCH},
- * {@link #FLAG_ALWAYS_RETAIN_TASK_STATE},
- * {@link #FLAG_STATE_NOT_NEEDED}, {@link #FLAG_EXCLUDE_FROM_RECENTS},
- * {@link #FLAG_ALLOW_TASK_REPARENTING}, {@link #FLAG_NO_HISTORY}.
- */
- public int flags;
-
- /**
- * Constant corresponding to <code>unspecified</code> in
- * the {@link android.R.attr#screenOrientation} attribute.
- */
- public static final int SCREEN_ORIENTATION_UNSPECIFIED = -1;
- /**
- * Constant corresponding to <code>landscape</code> in
- * the {@link android.R.attr#screenOrientation} attribute.
- */
- public static final int SCREEN_ORIENTATION_LANDSCAPE = 0;
- /**
- * Constant corresponding to <code>portrait</code> in
- * the {@link android.R.attr#screenOrientation} attribute.
- */
- public static final int SCREEN_ORIENTATION_PORTRAIT = 1;
- /**
- * Constant corresponding to <code>user</code> in
- * the {@link android.R.attr#screenOrientation} attribute.
- */
- public static final int SCREEN_ORIENTATION_USER = 2;
- /**
- * Constant corresponding to <code>behind</code> in
- * the {@link android.R.attr#screenOrientation} attribute.
- */
- public static final int SCREEN_ORIENTATION_BEHIND = 3;
- /**
- * Constant corresponding to <code>sensor</code> in
- * the {@link android.R.attr#screenOrientation} attribute.
- */
- public static final int SCREEN_ORIENTATION_SENSOR = 4;
-
- /**
- * Constant corresponding to <code>sensor</code> in
- * the {@link android.R.attr#screenOrientation} attribute.
- */
- public static final int SCREEN_ORIENTATION_NOSENSOR = 5;
- /**
- * The preferred screen orientation this activity would like to run in.
- * From the {@link android.R.attr#screenOrientation} attribute, one of
- * {@link #SCREEN_ORIENTATION_UNSPECIFIED},
- * {@link #SCREEN_ORIENTATION_LANDSCAPE},
- * {@link #SCREEN_ORIENTATION_PORTRAIT},
- * {@link #SCREEN_ORIENTATION_USER},
- * {@link #SCREEN_ORIENTATION_BEHIND},
- * {@link #SCREEN_ORIENTATION_SENSOR},
- * {@link #SCREEN_ORIENTATION_NOSENSOR}.
- */
- public int screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
-
- /**
- * Bit in {@link #configChanges} that indicates that the activity
- * can itself handle changes to the IMSI MCC. Set from the
- * {@link android.R.attr#configChanges} attribute.
- */
- public static final int CONFIG_MCC = 0x0001;
- /**
- * Bit in {@link #configChanges} that indicates that the activity
- * can itself handle changes to the IMSI MNC. Set from the
- * {@link android.R.attr#configChanges} attribute.
- */
- public static final int CONFIG_MNC = 0x0002;
- /**
- * Bit in {@link #configChanges} that indicates that the activity
- * can itself handle changes to the locale. Set from the
- * {@link android.R.attr#configChanges} attribute.
- */
- public static final int CONFIG_LOCALE = 0x0004;
- /**
- * Bit in {@link #configChanges} that indicates that the activity
- * can itself handle changes to the touchscreen type. Set from the
- * {@link android.R.attr#configChanges} attribute.
- */
- public static final int CONFIG_TOUCHSCREEN = 0x0008;
- /**
- * Bit in {@link #configChanges} that indicates that the activity
- * can itself handle changes to the keyboard type. Set from the
- * {@link android.R.attr#configChanges} attribute.
- */
- public static final int CONFIG_KEYBOARD = 0x0010;
- /**
- * Bit in {@link #configChanges} that indicates that the activity
- * can itself handle changes to the keyboard being hidden/exposed.
- * Set from the {@link android.R.attr#configChanges} attribute.
- */
- public static final int CONFIG_KEYBOARD_HIDDEN = 0x0020;
- /**
- * Bit in {@link #configChanges} that indicates that the activity
- * can itself handle changes to the navigation type. Set from the
- * {@link android.R.attr#configChanges} attribute.
- */
- public static final int CONFIG_NAVIGATION = 0x0040;
- /**
- * Bit in {@link #configChanges} that indicates that the activity
- * can itself handle changes to the screen orientation. Set from the
- * {@link android.R.attr#configChanges} attribute.
- */
- public static final int CONFIG_ORIENTATION = 0x0080;
- /**
- * Bit in {@link #configChanges} that indicates that the activity
- * can itself handle changes to the font scaling factor. Set from the
- * {@link android.R.attr#configChanges} attribute. This is
- * not a core resource configutation, but a higher-level value, so its
- * constant starts at the high bits.
- */
- public static final int CONFIG_FONT_SCALE = 0x40000000;
-
- /**
- * Bit mask of kinds of configuration changes that this activity
- * can handle itself (without being restarted by the system).
- * Contains any combination of {@link #CONFIG_FONT_SCALE},
- * {@link #CONFIG_MCC}, {@link #CONFIG_MNC},
- * {@link #CONFIG_LOCALE}, {@link #CONFIG_TOUCHSCREEN},
- * {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION}, and
- * {@link #CONFIG_ORIENTATION}. Set from the
- * {@link android.R.attr#configChanges} attribute.
- */
- public int configChanges;
-
- /**
- * The desired soft input mode for this activity's main window.
- * Set from the {@link android.R.attr#windowSoftInputMode} attribute
- * in the activity's manifest. May be any of the same values allowed
- * for {@link android.view.WindowManager.LayoutParams#softInputMode
- * WindowManager.LayoutParams.softInputMode}. If 0 (unspecified),
- * the mode from the theme will be used.
- */
- public int softInputMode;
-
- public ActivityInfo() {
- }
-
- public ActivityInfo(ActivityInfo orig) {
- super(orig);
- theme = orig.theme;
- launchMode = orig.launchMode;
- permission = orig.permission;
- taskAffinity = orig.taskAffinity;
- targetActivity = orig.targetActivity;
- flags = orig.flags;
- screenOrientation = orig.screenOrientation;
- configChanges = orig.configChanges;
- softInputMode = orig.softInputMode;
- }
-
- /**
- * Return the theme resource identifier to use for this activity. If
- * the activity defines a theme, that is used; else, the application
- * theme is used.
- *
- * @return The theme associated with this activity.
- */
- public final int getThemeResource() {
- return theme != 0 ? theme : applicationInfo.theme;
- }
-
- public void dump(Printer pw, String prefix) {
- super.dumpFront(pw, prefix);
- pw.println(prefix + "permission=" + permission);
- pw.println(prefix + "taskAffinity=" + taskAffinity
- + " targetActivity=" + targetActivity);
- pw.println(prefix + "launchMode=" + launchMode
- + " flags=0x" + Integer.toHexString(flags)
- + " theme=0x" + Integer.toHexString(theme));
- pw.println(prefix + "screenOrientation=" + screenOrientation
- + " configChanges=0x" + Integer.toHexString(configChanges)
- + " softInputMode=0x" + Integer.toHexString(softInputMode));
- super.dumpBack(pw, prefix);
- }
-
- public String toString() {
- return "ActivityInfo{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + name + "}";
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags) {
- super.writeToParcel(dest, parcelableFlags);
- dest.writeInt(theme);
- dest.writeInt(launchMode);
- dest.writeString(permission);
- dest.writeString(taskAffinity);
- dest.writeString(targetActivity);
- dest.writeInt(flags);
- dest.writeInt(screenOrientation);
- dest.writeInt(configChanges);
- dest.writeInt(softInputMode);
- }
-
- public static final Parcelable.Creator<ActivityInfo> CREATOR
- = new Parcelable.Creator<ActivityInfo>() {
- public ActivityInfo createFromParcel(Parcel source) {
- return new ActivityInfo(source);
- }
- public ActivityInfo[] newArray(int size) {
- return new ActivityInfo[size];
- }
- };
-
- private ActivityInfo(Parcel source) {
- super(source);
- theme = source.readInt();
- launchMode = source.readInt();
- permission = source.readString();
- taskAffinity = source.readString();
- targetActivity = source.readString();
- flags = source.readInt();
- screenOrientation = source.readInt();
- configChanges = source.readInt();
- softInputMode = source.readInt();
- }
-}
diff --git a/core/java/android/content/pm/ApplicationInfo.aidl b/core/java/android/content/pm/ApplicationInfo.aidl
deleted file mode 100755
index 006d1bd..0000000
--- a/core/java/android/content/pm/ApplicationInfo.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/view/WindowManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-parcelable ApplicationInfo;
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
deleted file mode 100644
index 8d727ed..0000000
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ /dev/null
@@ -1,310 +0,0 @@
-package android.content.pm;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Printer;
-
-import java.text.Collator;
-import java.util.Comparator;
-
-/**
- * Information you can retrieve about a particular application. This
- * corresponds to information collected from the AndroidManifest.xml's
- * &lt;application&gt; tag.
- */
-public class ApplicationInfo extends PackageItemInfo implements Parcelable {
-
- /**
- * Default task affinity of all activities in this application. See
- * {@link ActivityInfo#taskAffinity} for more information. This comes
- * from the "taskAffinity" attribute.
- */
- public String taskAffinity;
-
- /**
- * Optional name of a permission required to be able to access this
- * application's components. From the "permission" attribute.
- */
- public String permission;
-
- /**
- * The name of the process this application should run in. From the
- * "process" attribute or, if not set, the same as
- * <var>packageName</var>.
- */
- public String processName;
-
- /**
- * Class implementing the Application object. From the "class"
- * attribute.
- */
- public String className;
-
- /**
- * A style resource identifier (in the package's resources) of the
- * description of an application. From the "description" attribute
- * or, if not set, 0.
- */
- public int descriptionRes;
-
- /**
- * A style resource identifier (in the package's resources) of the
- * default visual theme of the application. From the "theme" attribute
- * or, if not set, 0.
- */
- public int theme;
-
- /**
- * Class implementing the Application's manage space
- * functionality. From the "manageSpaceActivity"
- * attribute. This is an optional attribute and will be null if
- * application's dont specify it in their manifest
- */
- public String manageSpaceActivityName;
-
- /**
- * Value for {@link #flags}: if set, this application is installed in the
- * device's system image.
- */
- public static final int FLAG_SYSTEM = 1<<0;
-
- /**
- * Value for {@link #flags}: set to true if this application would like to
- * allow debugging of its
- * code, even when installed on a non-development system. Comes
- * from {@link android.R.styleable#AndroidManifestApplication_debuggable
- * android:debuggable} of the &lt;application&gt; tag.
- */
- public static final int FLAG_DEBUGGABLE = 1<<1;
-
- /**
- * Value for {@link #flags}: set to true if this application has code
- * associated with it. Comes
- * from {@link android.R.styleable#AndroidManifestApplication_hasCode
- * android:hasCode} of the &lt;application&gt; tag.
- */
- public static final int FLAG_HAS_CODE = 1<<2;
-
- /**
- * Value for {@link #flags}: set to true if this application is persistent.
- * Comes from {@link android.R.styleable#AndroidManifestApplication_persistent
- * android:persistent} of the &lt;application&gt; tag.
- */
- public static final int FLAG_PERSISTENT = 1<<3;
-
- /**
- * Value for {@link #flags}: set to true iif this application holds the
- * {@link android.Manifest.permission#FACTORY_TEST} permission and the
- * device is running in factory test mode.
- */
- public static final int FLAG_FACTORY_TEST = 1<<4;
-
- /**
- * Value for {@link #flags}: default value for the corresponding ActivityInfo flag.
- * Comes from {@link android.R.styleable#AndroidManifestApplication_allowTaskReparenting
- * android:allowTaskReparenting} of the &lt;application&gt; tag.
- */
- public static final int FLAG_ALLOW_TASK_REPARENTING = 1<<5;
-
- /**
- * Value for {@link #flags}: default value for the corresponding ActivityInfo flag.
- * Comes from {@link android.R.styleable#AndroidManifestApplication_allowClearUserData
- * android:allowClearUserData} of the &lt;application&gt; tag.
- */
- public static final int FLAG_ALLOW_CLEAR_USER_DATA = 1<<6;
-
-
- /**
- * Value for {@link #flags}: default value for the corresponding ActivityInfo flag.
- * {@hide}
- */
- public static final int FLAG_UPDATED_SYSTEM_APP = 1<<7;
-
- /**
- * Flags associated with the application. Any combination of
- * {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE},
- * {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
- * {@link #FLAG_ALLOW_TASK_REPARENTING}
- * {@link #FLAG_ALLOW_CLEAR_USER_DATA}.
- */
- public int flags = 0;
-
- /**
- * Full path to the location of this package.
- */
- public String sourceDir;
-
- /**
- * Full path to the location of the publicly available parts of this package (i.e. the resources
- * and manifest). For non-forward-locked apps this will be the same as {@link #sourceDir).
- */
- public String publicSourceDir;
-
- /**
- * Paths to all shared libraries this application is linked against. This
- * field is only set if the {@link PackageManager#GET_SHARED_LIBRARY_FILES
- * PackageManager.GET_SHARED_LIBRARY_FILES} flag was used when retrieving
- * the structure.
- */
- public String[] sharedLibraryFiles;
-
- /**
- * Full path to a directory assigned to the package for its persistent
- * data.
- */
- public String dataDir;
-
- /**
- * The kernel user-ID that has been assigned to this application;
- * currently this is not a unique ID (multiple applications can have
- * the same uid).
- */
- public int uid;
-
- /**
- * When false, indicates that all components within this application are
- * considered disabled, regardless of their individually set enabled status.
- */
- public boolean enabled = true;
-
- public void dump(Printer pw, String prefix) {
- super.dumpFront(pw, prefix);
- pw.println(prefix + "className=" + className);
- pw.println(prefix + "permission=" + permission
- + " uid=" + uid);
- pw.println(prefix + "taskAffinity=" + taskAffinity);
- pw.println(prefix + "theme=0x" + Integer.toHexString(theme));
- pw.println(prefix + "flags=0x" + Integer.toHexString(flags)
- + " processName=" + processName);
- pw.println(prefix + "sourceDir=" + sourceDir);
- pw.println(prefix + "publicSourceDir=" + publicSourceDir);
- pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles);
- pw.println(prefix + "dataDir=" + dataDir);
- pw.println(prefix + "enabled=" + enabled);
- pw.println(prefix+"manageSpaceActivityName="+manageSpaceActivityName);
- pw.println(prefix+"description=0x"+Integer.toHexString(descriptionRes));
- super.dumpBack(pw, prefix);
- }
-
- public static class DisplayNameComparator
- implements Comparator<ApplicationInfo> {
- public DisplayNameComparator(PackageManager pm) {
- mPM = pm;
- }
-
- public final int compare(ApplicationInfo aa, ApplicationInfo ab) {
- CharSequence sa = mPM.getApplicationLabel(aa);
- if (sa == null) {
- sa = aa.packageName;
- }
- CharSequence sb = mPM.getApplicationLabel(ab);
- if (sb == null) {
- sb = ab.packageName;
- }
-
- return sCollator.compare(sa.toString(), sb.toString());
- }
-
- private final Collator sCollator = Collator.getInstance();
- private PackageManager mPM;
- }
-
- public ApplicationInfo() {
- }
-
- public ApplicationInfo(ApplicationInfo orig) {
- super(orig);
- taskAffinity = orig.taskAffinity;
- permission = orig.permission;
- processName = orig.processName;
- className = orig.className;
- theme = orig.theme;
- flags = orig.flags;
- sourceDir = orig.sourceDir;
- publicSourceDir = orig.publicSourceDir;
- sharedLibraryFiles = orig.sharedLibraryFiles;
- dataDir = orig.dataDir;
- uid = orig.uid;
- enabled = orig.enabled;
- manageSpaceActivityName = orig.manageSpaceActivityName;
- descriptionRes = orig.descriptionRes;
- }
-
-
- public String toString() {
- return "ApplicationInfo{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + packageName + "}";
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags) {
- super.writeToParcel(dest, parcelableFlags);
- dest.writeString(taskAffinity);
- dest.writeString(permission);
- dest.writeString(processName);
- dest.writeString(className);
- dest.writeInt(theme);
- dest.writeInt(flags);
- dest.writeString(sourceDir);
- dest.writeString(publicSourceDir);
- dest.writeStringArray(sharedLibraryFiles);
- dest.writeString(dataDir);
- dest.writeInt(uid);
- dest.writeInt(enabled ? 1 : 0);
- dest.writeString(manageSpaceActivityName);
- dest.writeInt(descriptionRes);
- }
-
- public static final Parcelable.Creator<ApplicationInfo> CREATOR
- = new Parcelable.Creator<ApplicationInfo>() {
- public ApplicationInfo createFromParcel(Parcel source) {
- return new ApplicationInfo(source);
- }
- public ApplicationInfo[] newArray(int size) {
- return new ApplicationInfo[size];
- }
- };
-
- private ApplicationInfo(Parcel source) {
- super(source);
- taskAffinity = source.readString();
- permission = source.readString();
- processName = source.readString();
- className = source.readString();
- theme = source.readInt();
- flags = source.readInt();
- sourceDir = source.readString();
- publicSourceDir = source.readString();
- sharedLibraryFiles = source.readStringArray();
- dataDir = source.readString();
- uid = source.readInt();
- enabled = source.readInt() != 0;
- manageSpaceActivityName = source.readString();
- descriptionRes = source.readInt();
- }
-
- /**
- * Retrieve the textual description of the application. This
- * will call back on the given PackageManager to load the description from
- * the application.
- *
- * @param pm A PackageManager from which the label can be loaded; usually
- * the PackageManager from which you originally retrieved this item.
- *
- * @return Returns a CharSequence containing the application's description.
- * If there is no description, null is returned.
- */
- public CharSequence loadDescription(PackageManager pm) {
- if (descriptionRes != 0) {
- CharSequence label = pm.getText(packageName, descriptionRes, null);
- if (label != null) {
- return label;
- }
- }
- return null;
- }
-}
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
deleted file mode 100644
index 73c9244..0000000
--- a/core/java/android/content/pm/ComponentInfo.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package android.content.pm;
-
-import android.graphics.drawable.Drawable;
-import android.os.Parcel;
-import android.util.Printer;
-
-/**
- * Base class containing information common to all application components
- * ({@link ActivityInfo}, {@link ServiceInfo}). This class is not intended
- * to be used by itself; it is simply here to share common definitions
- * between all application components. As such, it does not itself
- * implement Parcelable, but does provide convenience methods to assist
- * in the implementation of Parcelable in subclasses.
- */
-public class ComponentInfo extends PackageItemInfo {
- /**
- * Global information about the application/package this component is a
- * part of.
- */
- public ApplicationInfo applicationInfo;
-
- /**
- * The name of the process this component should run in.
- * From the "android:process" attribute or, if not set, the same
- * as <var>applicationInfo.processName</var>.
- */
- public String processName;
-
- /**
- * Indicates whether or not this component may be instantiated. Note that this value can be
- * overriden by the one in its parent {@link ApplicationInfo}.
- */
- public boolean enabled = true;
-
- /**
- * Set to true if this component is available for use by other applications.
- * Comes from {@link android.R.attr#exported android:exported} of the
- * &lt;activity&gt;, &lt;receiver&gt;, &lt;service&gt;, or
- * &lt;provider&gt; tag.
- */
- public boolean exported = false;
-
- public ComponentInfo() {
- }
-
- public ComponentInfo(ComponentInfo orig) {
- super(orig);
- applicationInfo = orig.applicationInfo;
- processName = orig.processName;
- enabled = orig.enabled;
- exported = orig.exported;
- }
-
- @Override public CharSequence loadLabel(PackageManager pm) {
- if (nonLocalizedLabel != null) {
- return nonLocalizedLabel;
- }
- ApplicationInfo ai = applicationInfo;
- CharSequence label;
- if (labelRes != 0) {
- label = pm.getText(packageName, labelRes, ai);
- if (label != null) {
- return label;
- }
- }
- if (ai.nonLocalizedLabel != null) {
- return ai.nonLocalizedLabel;
- }
- if (ai.labelRes != 0) {
- label = pm.getText(packageName, ai.labelRes, ai);
- if (label != null) {
- return label;
- }
- }
- return name;
- }
-
- @Override public Drawable loadIcon(PackageManager pm) {
- ApplicationInfo ai = applicationInfo;
- Drawable dr;
- if (icon != 0) {
- dr = pm.getDrawable(packageName, icon, ai);
- if (dr != null) {
- return dr;
- }
- }
- if (ai.icon != 0) {
- dr = pm.getDrawable(packageName, ai.icon, ai);
- if (dr != null) {
- return dr;
- }
- }
- return pm.getDefaultActivityIcon();
- }
-
- /**
- * Return the icon resource identifier to use for this component. If
- * the component defines an icon, that is used; else, the application
- * icon is used.
- *
- * @return The icon associated with this component.
- */
- public final int getIconResource() {
- return icon != 0 ? icon : applicationInfo.icon;
- }
-
- protected void dumpFront(Printer pw, String prefix) {
- super.dumpFront(pw, prefix);
- pw.println(prefix + "enabled=" + enabled + " exported=" + exported
- + " processName=" + processName);
- }
-
- protected void dumpBack(Printer pw, String prefix) {
- if (applicationInfo != null) {
- pw.println(prefix + "ApplicationInfo:");
- applicationInfo.dump(pw, prefix + " ");
- } else {
- pw.println(prefix + "ApplicationInfo: null");
- }
- super.dumpBack(pw, prefix);
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags) {
- super.writeToParcel(dest, parcelableFlags);
- applicationInfo.writeToParcel(dest, parcelableFlags);
- dest.writeString(processName);
- dest.writeInt(enabled ? 1 : 0);
- dest.writeInt(exported ? 1 : 0);
- }
-
- protected ComponentInfo(Parcel source) {
- super(source);
- applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source);
- processName = source.readString();
- enabled = (source.readInt() != 0);
- exported = (source.readInt() != 0);
- }
-}
diff --git a/core/java/android/content/pm/ConfigurationInfo.java b/core/java/android/content/pm/ConfigurationInfo.java
deleted file mode 100755
index dcc7463..0000000
--- a/core/java/android/content/pm/ConfigurationInfo.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Information you can retrieve about hardware configuration preferences
- * declared by an application. This corresponds to information collected from the
- * AndroidManifest.xml's &lt;uses-configuration&gt; tags.
- */
-public class ConfigurationInfo implements Parcelable {
- /**
- * The kind of touch screen attached to the device.
- * One of: {@link android.content.res.Configuration#TOUCHSCREEN_NOTOUCH},
- * {@link android.content.res.Configuration#TOUCHSCREEN_STYLUS},
- * {@link android.content.res.Configuration#TOUCHSCREEN_FINGER}.
- */
- public int reqTouchScreen;
-
- /**
- * Application's input method preference.
- * One of: {@link android.content.res.Configuration#KEYBOARD_UNDEFINED},
- * {@link android.content.res.Configuration#KEYBOARD_NOKEYS},
- * {@link android.content.res.Configuration#KEYBOARD_QWERTY},
- * {@link android.content.res.Configuration#KEYBOARD_12KEY}
- */
- public int reqKeyboardType;
-
- /**
- * A flag indicating whether any keyboard is available.
- * one of: {@link android.content.res.Configuration#NAVIGATION_UNDEFINED},
- * {@link android.content.res.Configuration#NAVIGATION_DPAD},
- * {@link android.content.res.Configuration#NAVIGATION_TRACKBALL},
- * {@link android.content.res.Configuration#NAVIGATION_WHEEL}
- */
- public int reqNavigation;
-
- /**
- * Value for {@link #reqInputFeatures}: if set, indicates that the application
- * requires a hard keyboard
- */
- public static final int INPUT_FEATURE_HARD_KEYBOARD = 0x00000001;
-
- /**
- * Value for {@link #reqInputFeatures}: if set, indicates that the application
- * requires a five way navigation device
- */
- public static final int INPUT_FEATURE_FIVE_WAY_NAV = 0x00000002;
-
- /**
- * Flags associated with the input features. Any combination of
- * {@link #INPUT_FEATURE_HARD_KEYBOARD},
- * {@link #INPUT_FEATURE_FIVE_WAY_NAV}
- */
- public int reqInputFeatures = 0;
-
- public ConfigurationInfo() {
- }
-
- public ConfigurationInfo(ConfigurationInfo orig) {
- reqTouchScreen = orig.reqTouchScreen;
- reqKeyboardType = orig.reqKeyboardType;
- reqNavigation = orig.reqNavigation;
- reqInputFeatures = orig.reqInputFeatures;
- }
-
- public String toString() {
- return "ApplicationHardwarePreferences{"
- + Integer.toHexString(System.identityHashCode(this))
- + ", touchscreen = " + reqTouchScreen + "}"
- + ", inputMethod = " + reqKeyboardType + "}"
- + ", navigation = " + reqNavigation + "}"
- + ", reqInputFeatures = " + reqInputFeatures + "}";
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags) {
- dest.writeInt(reqTouchScreen);
- dest.writeInt(reqKeyboardType);
- dest.writeInt(reqNavigation);
- dest.writeInt(reqInputFeatures);
- }
-
- public static final Creator<ConfigurationInfo> CREATOR =
- new Creator<ConfigurationInfo>() {
- public ConfigurationInfo createFromParcel(Parcel source) {
- return new ConfigurationInfo(source);
- }
- public ConfigurationInfo[] newArray(int size) {
- return new ConfigurationInfo[size];
- }
- };
-
- private ConfigurationInfo(Parcel source) {
- reqTouchScreen = source.readInt();
- reqKeyboardType = source.readInt();
- reqNavigation = source.readInt();
- reqInputFeatures = source.readInt();
- }
-}
diff --git a/core/java/android/content/pm/IPackageDataObserver.aidl b/core/java/android/content/pm/IPackageDataObserver.aidl
deleted file mode 100755
index d010ee4..0000000
--- a/core/java/android/content/pm/IPackageDataObserver.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-/**
- * API for package data change related callbacks from the Package Manager.
- * Some usage scenarios include deletion of cache directory, generate
- * statistics related to code, data, cache usage(TODO)
- * {@hide}
- */
-oneway interface IPackageDataObserver {
- void onRemoveCompleted(in String packageName, boolean succeeded);
-}
diff --git a/core/java/android/content/pm/IPackageDeleteObserver.aidl b/core/java/android/content/pm/IPackageDeleteObserver.aidl
deleted file mode 100644
index bc16b3e..0000000
--- a/core/java/android/content/pm/IPackageDeleteObserver.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-/**
- * API for deletion callbacks from the Package Manager.
- *
- * {@hide}
- */
-oneway interface IPackageDeleteObserver {
- void packageDeleted(in boolean succeeded);
-}
-
diff --git a/core/java/android/content/pm/IPackageInstallObserver.aidl b/core/java/android/content/pm/IPackageInstallObserver.aidl
deleted file mode 100644
index e83bbc6..0000000
--- a/core/java/android/content/pm/IPackageInstallObserver.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-/**
- * API for installation callbacks from the Package Manager.
- *
- */
-oneway interface IPackageInstallObserver {
- void packageInstalled(in String packageName, int returnCode);
-}
-
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
deleted file mode 100644
index d3f6f3c..0000000
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageInstallObserver;
-import android.content.pm.IPackageDeleteObserver;
-import android.content.pm.IPackageDataObserver;
-import android.content.pm.IPackageStatsObserver;
-import android.content.pm.InstrumentationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.ProviderInfo;
-import android.content.pm.PermissionGroupInfo;
-import android.content.pm.PermissionInfo;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.net.Uri;
-import android.app.PendingIntent;
-
-/**
- * See {@link PackageManager} for documentation on most of the APIs
- * here.
- *
- * {@hide}
- */
-interface IPackageManager {
- PackageInfo getPackageInfo(String packageName, int flags);
- int getPackageUid(String packageName);
- int[] getPackageGids(String packageName);
-
- PermissionInfo getPermissionInfo(String name, int flags);
-
- List<PermissionInfo> queryPermissionsByGroup(String group, int flags);
-
- PermissionGroupInfo getPermissionGroupInfo(String name, int flags);
-
- List<PermissionGroupInfo> getAllPermissionGroups(int flags);
-
- ApplicationInfo getApplicationInfo(String packageName, int flags);
-
- ActivityInfo getActivityInfo(in ComponentName className, int flags);
-
- ActivityInfo getReceiverInfo(in ComponentName className, int flags);
-
- ServiceInfo getServiceInfo(in ComponentName className, int flags);
-
- int checkPermission(String permName, String pkgName);
-
- int checkUidPermission(String permName, int uid);
-
- boolean addPermission(in PermissionInfo info);
-
- void removePermission(String name);
-
- int checkSignatures(String pkg1, String pkg2);
-
- String[] getPackagesForUid(int uid);
-
- String getNameForUid(int uid);
-
- int getUidForSharedUser(String sharedUserName);
-
- ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags);
-
- List<ResolveInfo> queryIntentActivities(in Intent intent,
- String resolvedType, int flags);
-
- List<ResolveInfo> queryIntentActivityOptions(
- in ComponentName caller, in Intent[] specifics,
- in String[] specificTypes, in Intent intent,
- String resolvedType, int flags);
-
- List<ResolveInfo> queryIntentReceivers(in Intent intent,
- String resolvedType, int flags);
-
- ResolveInfo resolveService(in Intent intent,
- String resolvedType, int flags);
-
- List<ResolveInfo> queryIntentServices(in Intent intent,
- String resolvedType, int flags);
-
- List<PackageInfo> getInstalledPackages(int flags);
-
- List<ApplicationInfo> getInstalledApplications(int flags);
-
- /**
- * Retrieve all applications that are marked as persistent.
- *
- * @return A List&lt;applicationInfo> containing one entry for each persistent
- * application.
- */
- List<ApplicationInfo> getPersistentApplications(int flags);
-
- ProviderInfo resolveContentProvider(String name, int flags);
-
- /**
- * Retrieve sync information for all content providers.
- *
- * @param outNames Filled in with a list of the root names of the content
- * providers that can sync.
- * @param outInfo Filled in with a list of the ProviderInfo for each
- * name in 'outNames'.
- */
- void querySyncProviders(inout List<String> outNames,
- inout List<ProviderInfo> outInfo);
-
- List<ProviderInfo> queryContentProviders(
- String processName, int uid, int flags);
-
- InstrumentationInfo getInstrumentationInfo(
- in ComponentName className, int flags);
-
- List<InstrumentationInfo> queryInstrumentation(
- String targetPackage, int flags);
-
- /**
- * Install a package.
- *
- * @param packageURI The location of the package file to install.
- * @param observer a callback to use to notify when the package installation in finished.
- * @param flags - possible values: {@link #FORWARD_LOCK_PACKAGE},
- * {@link #REPLACE_EXISITING_PACKAGE}
- */
- void installPackage(in Uri packageURI, IPackageInstallObserver observer, int flags);
-
- /**
- * Delete a package.
- *
- * @param packageName The fully qualified name of the package to delete.
- * @param observer a callback to use to notify when the package deletion in finished.
- * @param flags - possible values: {@link #DONT_DELETE_DATA}
- */
- void deletePackage(in String packageName, IPackageDeleteObserver observer, int flags);
-
- void addPackageToPreferred(String packageName);
-
- void removePackageFromPreferred(String packageName);
-
- List<PackageInfo> getPreferredPackages(int flags);
-
- void addPreferredActivity(in IntentFilter filter, int match,
- in ComponentName[] set, in ComponentName activity);
- void clearPackagePreferredActivities(String packageName);
- int getPreferredActivities(out List<IntentFilter> outFilters,
- out List<ComponentName> outActivities, String packageName);
-
- /**
- * As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}.
- */
- void setComponentEnabledSetting(in ComponentName componentName,
- in int newState, in int flags);
-
- /**
- * As per {@link android.content.pm.PackageManager#getComponentEnabledSetting}.
- */
- int getComponentEnabledSetting(in ComponentName componentName);
-
- /**
- * As per {@link android.content.pm.PackageManager#setApplicationEnabledSetting}.
- */
- void setApplicationEnabledSetting(in String packageName, in int newState, int flags);
-
- /**
- * As per {@link android.content.pm.PackageManager#getApplicationEnabledSetting}.
- */
- int getApplicationEnabledSetting(in String packageName);
-
- /**
- * Free storage by deleting LRU sorted list of cache files across
- * all applications. If the currently available free storage
- * on the device is greater than or equal to the requested
- * free storage, no cache files are cleared. If the currently
- * available storage on the device is less than the requested
- * free storage, some or all of the cache files across
- * all applications are deleted (based on last accessed time)
- * to increase the free storage space on the device to
- * the requested value. There is no guarantee that clearing all
- * the cache files from all applications will clear up
- * enough storage to achieve the desired value.
- * @param freeStorageSize The number of bytes of storage to be
- * freed by the system. Say if freeStorageSize is XX,
- * and the current free storage is YY,
- * if XX is less than YY, just return. if not free XX-YY number
- * of bytes if possible.
- * @param observer call back used to notify when
- * the operation is completed
- */
- void freeStorageAndNotify(in long freeStorageSize,
- IPackageDataObserver observer);
-
- /**
- * Free storage by deleting LRU sorted list of cache files across
- * all applications. If the currently available free storage
- * on the device is greater than or equal to the requested
- * free storage, no cache files are cleared. If the currently
- * available storage on the device is less than the requested
- * free storage, some or all of the cache files across
- * all applications are deleted (based on last accessed time)
- * to increase the free storage space on the device to
- * the requested value. There is no guarantee that clearing all
- * the cache files from all applications will clear up
- * enough storage to achieve the desired value.
- * @param freeStorageSize The number of bytes of storage to be
- * freed by the system. Say if freeStorageSize is XX,
- * and the current free storage is YY,
- * if XX is less than YY, just return. if not free XX-YY number
- * of bytes if possible.
- * @param opFinishedIntent PendingIntent call back used to
- * notify when the operation is completed.May be null
- * to indicate that no call back is desired.
- */
- void freeStorage(in long freeStorageSize,
- in PendingIntent opFinishedIntent);
-
- /**
- * Delete all the cache files in an applications cache directory
- * @param packageName The package name of the application whose cache
- * files need to be deleted
- * @param observer a callback used to notify when the deletion is finished.
- */
- void deleteApplicationCacheFiles(in String packageName, IPackageDataObserver observer);
-
- /**
- * Clear the user data directory of an application.
- * @param packageName The package name of the application whose cache
- * files need to be deleted
- * @param observer a callback used to notify when the operation is completed.
- */
- void clearApplicationUserData(in String packageName, IPackageDataObserver observer);
-
- /**
- * Get package statistics including the code, data and cache size for
- * an already installed package
- * @param packageName The package name of the application
- * @param observer a callback to use to notify when the asynchronous
- * retrieval of information is complete.
- */
- void getPackageSizeInfo(in String packageName, IPackageStatsObserver observer);
-
- /**
- * Get a list of shared libraries that are available on the
- * system.
- */
- String[] getSystemSharedLibraryNames();
-
- void enterSafeMode();
- boolean isSafeMode();
- void systemReady();
- boolean hasSystemUidErrors();
-}
diff --git a/core/java/android/content/pm/IPackageStatsObserver.aidl b/core/java/android/content/pm/IPackageStatsObserver.aidl
deleted file mode 100755
index ede4d1d..0000000
--- a/core/java/android/content/pm/IPackageStatsObserver.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-import android.content.pm.PackageStats;
-/**
- * API for package data change related callbacks from the Package Manager.
- * Some usage scenarios include deletion of cache directory, generate
- * statistics related to code, data, cache usage(TODO)
- * {@hide}
- */
-oneway interface IPackageStatsObserver {
-
- void onGetStatsCompleted(in PackageStats pStats, boolean succeeded);
-}
diff --git a/core/java/android/content/pm/InstrumentationInfo.aidl b/core/java/android/content/pm/InstrumentationInfo.aidl
deleted file mode 100755
index 3d847ae..0000000
--- a/core/java/android/content/pm/InstrumentationInfo.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/view/WindowManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-parcelable InstrumentationInfo;
diff --git a/core/java/android/content/pm/InstrumentationInfo.java b/core/java/android/content/pm/InstrumentationInfo.java
deleted file mode 100644
index 30ca002..0000000
--- a/core/java/android/content/pm/InstrumentationInfo.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package android.content.pm;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-import java.text.Collator;
-import java.util.Comparator;
-
-/**
- * Information you can retrieve about a particular piece of test
- * instrumentation. This corresponds to information collected
- * from the AndroidManifest.xml's &lt;instrumentation&gt; tag.
- */
-public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
- /**
- * The name of the application package being instrumented. From the
- * "package" attribute.
- */
- public String targetPackage;
-
- /**
- * Full path to the location of this package.
- */
- public String sourceDir;
-
- /**
- * Full path to the location of the publicly available parts of this package (i.e. the resources
- * and manifest). For non-forward-locked apps this will be the same as {@link #sourceDir).
- */
- public String publicSourceDir;
- /**
- * Full path to a directory assigned to the package for its persistent
- * data.
- */
- public String dataDir;
-
- /**
- * Specifies whether or not this instrumentation will handle profiling.
- */
- public boolean handleProfiling;
-
- /** Specifies whether or not to run this instrumentation as a functional test */
- public boolean functionalTest;
-
- public InstrumentationInfo() {
- }
-
- public InstrumentationInfo(InstrumentationInfo orig) {
- super(orig);
- targetPackage = orig.targetPackage;
- sourceDir = orig.sourceDir;
- publicSourceDir = orig.publicSourceDir;
- dataDir = orig.dataDir;
- handleProfiling = orig.handleProfiling;
- functionalTest = orig.functionalTest;
- }
-
- public String toString() {
- return "InstrumentationInfo{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + packageName + "}";
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags) {
- super.writeToParcel(dest, parcelableFlags);
- dest.writeString(targetPackage);
- dest.writeString(sourceDir);
- dest.writeString(publicSourceDir);
- dest.writeString(dataDir);
- dest.writeInt((handleProfiling == false) ? 0 : 1);
- dest.writeInt((functionalTest == false) ? 0 : 1);
- }
-
- public static final Parcelable.Creator<InstrumentationInfo> CREATOR
- = new Parcelable.Creator<InstrumentationInfo>() {
- public InstrumentationInfo createFromParcel(Parcel source) {
- return new InstrumentationInfo(source);
- }
- public InstrumentationInfo[] newArray(int size) {
- return new InstrumentationInfo[size];
- }
- };
-
- private InstrumentationInfo(Parcel source) {
- super(source);
- targetPackage = source.readString();
- sourceDir = source.readString();
- publicSourceDir = source.readString();
- dataDir = source.readString();
- handleProfiling = source.readInt() != 0;
- functionalTest = source.readInt() != 0;
- }
-}
diff --git a/core/java/android/content/pm/PackageInfo.aidl b/core/java/android/content/pm/PackageInfo.aidl
deleted file mode 100755
index 35e2322..0000000
--- a/core/java/android/content/pm/PackageInfo.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/view/WindowManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-parcelable PackageInfo;
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
deleted file mode 100644
index d9326f2..0000000
--- a/core/java/android/content/pm/PackageInfo.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package android.content.pm;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Overall information about the contents of a package. This corresponds
- * to all of the information collected from AndroidManifest.xml.
- */
-public class PackageInfo implements Parcelable {
- /**
- * The name of this package. From the &lt;manifest&gt; tag's "name"
- * attribute.
- */
- public String packageName;
-
- /**
- * The version number of this package, as specified by the &lt;manifest&gt;
- * tag's {@link android.R.styleable#AndroidManifest_versionCode versionCode}
- * attribute.
- */
- public int versionCode;
-
- /**
- * The version name of this package, as specified by the &lt;manifest&gt;
- * tag's {@link android.R.styleable#AndroidManifest_versionName versionName}
- * attribute.
- */
- public String versionName;
-
- /**
- * The shared user ID name of this package, as specified by the &lt;manifest&gt;
- * tag's {@link android.R.styleable#AndroidManifest_sharedUserId sharedUserId}
- * attribute.
- */
- public String sharedUserId;
-
- /**
- * The shared user ID label of this package, as specified by the &lt;manifest&gt;
- * tag's {@link android.R.styleable#AndroidManifest_sharedUserLabel sharedUserLabel}
- * attribute.
- */
- public int sharedUserLabel;
-
- /**
- * Information collected from the &lt;application&gt; tag, or null if
- * there was none.
- */
- public ApplicationInfo applicationInfo;
-
- /**
- * All kernel group-IDs that have been assigned to this package.
- * This is only filled in if the flag {@link PackageManager#GET_GIDS} was set.
- */
- public int[] gids;
-
- /**
- * Array of all {@link android.R.styleable#AndroidManifestActivity
- * &lt;activity&gt;} tags included under &lt;application&gt;,
- * or null if there were none. This is only filled in if the flag
- * {@link PackageManager#GET_ACTIVITIES} was set.
- */
- public ActivityInfo[] activities;
-
- /**
- * Array of all {@link android.R.styleable#AndroidManifestReceiver
- * &lt;receiver&gt;} tags included under &lt;application&gt;,
- * or null if there were none. This is only filled in if the flag
- * {@link PackageManager#GET_RECEIVERS} was set.
- */
- public ActivityInfo[] receivers;
-
- /**
- * Array of all {@link android.R.styleable#AndroidManifestService
- * &lt;service&gt;} tags included under &lt;application&gt;,
- * or null if there were none. This is only filled in if the flag
- * {@link PackageManager#GET_SERVICES} was set.
- */
- public ServiceInfo[] services;
-
- /**
- * Array of all {@link android.R.styleable#AndroidManifestProvider
- * &lt;provider&gt;} tags included under &lt;application&gt;,
- * or null if there were none. This is only filled in if the flag
- * {@link PackageManager#GET_PROVIDERS} was set.
- */
- public ProviderInfo[] providers;
-
- /**
- * Array of all {@link android.R.styleable#AndroidManifestInstrumentation
- * &lt;instrumentation&gt;} tags included under &lt;manifest&gt;,
- * or null if there were none. This is only filled in if the flag
- * {@link PackageManager#GET_INSTRUMENTATION} was set.
- */
- public InstrumentationInfo[] instrumentation;
-
- /**
- * Array of all {@link android.R.styleable#AndroidManifestPermission
- * &lt;permission&gt;} tags included under &lt;manifest&gt;,
- * or null if there were none. This is only filled in if the flag
- * {@link PackageManager#GET_PERMISSIONS} was set.
- */
- public PermissionInfo[] permissions;
-
- /**
- * Array of all {@link android.R.styleable#AndroidManifestUsesPermission
- * &lt;uses-permission&gt;} tags included under &lt;manifest&gt;,
- * or null if there were none. This is only filled in if the flag
- * {@link PackageManager#GET_PERMISSIONS} was set. This list includes
- * all permissions requested, even those that were not granted or known
- * by the system at install time.
- */
- public String[] requestedPermissions;
-
- /**
- * Array of all signatures read from the package file. This is only filled
- * in if the flag {@link PackageManager#GET_SIGNATURES} was set.
- */
- public Signature[] signatures;
-
- /**
- * Application specified preferred configuration
- * {@link android.R.styleable#AndroidManifestUsesConfiguration
- * &lt;uses-configuration&gt;} tags included under &lt;manifest&gt;,
- * or null if there were none. This is only filled in if the flag
- * {@link PackageManager#GET_CONFIGURATIONS} was set.
- */
- public ConfigurationInfo[] configPreferences;
-
- public PackageInfo() {
- }
-
- public String toString() {
- return "PackageInfo{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + packageName + "}";
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags) {
- dest.writeString(packageName);
- dest.writeInt(versionCode);
- dest.writeString(versionName);
- dest.writeString(sharedUserId);
- dest.writeInt(sharedUserLabel);
- if (applicationInfo != null) {
- dest.writeInt(1);
- applicationInfo.writeToParcel(dest, parcelableFlags);
- } else {
- dest.writeInt(0);
- }
- dest.writeIntArray(gids);
- dest.writeTypedArray(activities, parcelableFlags);
- dest.writeTypedArray(receivers, parcelableFlags);
- dest.writeTypedArray(services, parcelableFlags);
- dest.writeTypedArray(providers, parcelableFlags);
- dest.writeTypedArray(instrumentation, parcelableFlags);
- dest.writeTypedArray(permissions, parcelableFlags);
- dest.writeStringArray(requestedPermissions);
- dest.writeTypedArray(signatures, parcelableFlags);
- dest.writeTypedArray(configPreferences, parcelableFlags);
- }
-
- public static final Parcelable.Creator<PackageInfo> CREATOR
- = new Parcelable.Creator<PackageInfo>() {
- public PackageInfo createFromParcel(Parcel source) {
- return new PackageInfo(source);
- }
-
- public PackageInfo[] newArray(int size) {
- return new PackageInfo[size];
- }
- };
-
- private PackageInfo(Parcel source) {
- packageName = source.readString();
- versionCode = source.readInt();
- versionName = source.readString();
- sharedUserId = source.readString();
- sharedUserLabel = source.readInt();
- int hasApp = source.readInt();
- if (hasApp != 0) {
- applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source);
- }
- gids = source.createIntArray();
- activities = source.createTypedArray(ActivityInfo.CREATOR);
- receivers = source.createTypedArray(ActivityInfo.CREATOR);
- services = source.createTypedArray(ServiceInfo.CREATOR);
- providers = source.createTypedArray(ProviderInfo.CREATOR);
- instrumentation = source.createTypedArray(InstrumentationInfo.CREATOR);
- permissions = source.createTypedArray(PermissionInfo.CREATOR);
- requestedPermissions = source.createStringArray();
- signatures = source.createTypedArray(Signature.CREATOR);
- configPreferences = source.createTypedArray(ConfigurationInfo.CREATOR);
- }
-}
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
deleted file mode 100644
index 46e7ca4..0000000
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ /dev/null
@@ -1,191 +0,0 @@
-package android.content.pm;
-
-import android.content.res.XmlResourceParser;
-
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.text.TextUtils;
-import android.util.Printer;
-
-import java.text.Collator;
-import java.util.Comparator;
-
-/**
- * Base class containing information common to all package items held by
- * the package manager. This provides a very common basic set of attributes:
- * a label, icon, and meta-data. This class is not intended
- * to be used by itself; it is simply here to share common definitions
- * between all items returned by the package manager. As such, it does not
- * itself implement Parcelable, but does provide convenience methods to assist
- * in the implementation of Parcelable in subclasses.
- */
-public class PackageItemInfo {
- /**
- * Public name of this item. From the "android:name" attribute.
- */
- public String name;
-
- /**
- * Name of the package that this item is in.
- */
- public String packageName;
-
- /**
- * A string resource identifier (in the package's resources) of this
- * component's label. From the "label" attribute or, if not set, 0.
- */
- public int labelRes;
-
- /**
- * The string provided in the AndroidManifest file, if any. You
- * probably don't want to use this. You probably want
- * {@link PackageManager#getApplicationLabel}
- */
- public CharSequence nonLocalizedLabel;
-
- /**
- * A drawable resource identifier (in the package's resources) of this
- * component's icon. From the "icon" attribute or, if not set, 0.
- */
- public int icon;
-
- /**
- * Additional meta-data associated with this component. This field
- * will only be filled in if you set the
- * {@link PackageManager#GET_META_DATA} flag when requesting the info.
- */
- public Bundle metaData;
-
- public PackageItemInfo() {
- }
-
- public PackageItemInfo(PackageItemInfo orig) {
- name = orig.name;
- packageName = orig.packageName;
- labelRes = orig.labelRes;
- nonLocalizedLabel = orig.nonLocalizedLabel;
- icon = orig.icon;
- metaData = orig.metaData;
- }
-
- /**
- * Retrieve the current textual label associated with this item. This
- * will call back on the given PackageManager to load the label from
- * the application.
- *
- * @param pm A PackageManager from which the label can be loaded; usually
- * the PackageManager from which you originally retrieved this item.
- *
- * @return Returns a CharSequence containing the item's label. If the
- * item does not have a label, its name is returned.
- */
- public CharSequence loadLabel(PackageManager pm) {
- if (nonLocalizedLabel != null) {
- return nonLocalizedLabel;
- }
- if (labelRes != 0) {
- CharSequence label = pm.getText(packageName, labelRes, null);
- if (label != null) {
- return label;
- }
- }
- if(name != null) {
- return name;
- }
- return packageName;
- }
-
- /**
- * Retrieve the current graphical icon associated with this item. This
- * will call back on the given PackageManager to load the icon from
- * the application.
- *
- * @param pm A PackageManager from which the icon can be loaded; usually
- * the PackageManager from which you originally retrieved this item.
- *
- * @return Returns a Drawable containing the item's icon. If the
- * item does not have an icon, the default activity icon is returned.
- */
- public Drawable loadIcon(PackageManager pm) {
- if (icon != 0) {
- Drawable dr = pm.getDrawable(packageName, icon, null);
- if (dr != null) {
- return dr;
- }
- }
- return pm.getDefaultActivityIcon();
- }
-
- /**
- * Load an XML resource attached to the meta-data of this item. This will
- * retrieved the name meta-data entry, and if defined call back on the
- * given PackageManager to load its XML file from the application.
- *
- * @param pm A PackageManager from which the XML can be loaded; usually
- * the PackageManager from which you originally retrieved this item.
- * @param name Name of the meta-date you would like to load.
- *
- * @return Returns an XmlPullParser you can use to parse the XML file
- * assigned as the given meta-data. If the meta-data name is not defined
- * or the XML resource could not be found, null is returned.
- */
- public XmlResourceParser loadXmlMetaData(PackageManager pm, String name) {
- if (metaData != null) {
- int resid = metaData.getInt(name);
- if (resid != 0) {
- return pm.getXml(packageName, resid, null);
- }
- }
- return null;
- }
-
- protected void dumpFront(Printer pw, String prefix) {
- pw.println(prefix + "name=" + name);
- pw.println(prefix + "packageName=" + packageName);
- pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
- + " nonLocalizedLabel=" + nonLocalizedLabel
- + " icon=0x" + Integer.toHexString(icon));
- }
-
- protected void dumpBack(Printer pw, String prefix) {
- // no back here
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags) {
- dest.writeString(name);
- dest.writeString(packageName);
- dest.writeInt(labelRes);
- TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags);
- dest.writeInt(icon);
- dest.writeBundle(metaData);
- }
-
- protected PackageItemInfo(Parcel source) {
- name = source.readString();
- packageName = source.readString();
- labelRes = source.readInt();
- nonLocalizedLabel
- = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- icon = source.readInt();
- metaData = source.readBundle();
- }
-
- public static class DisplayNameComparator
- implements Comparator<PackageItemInfo> {
- public DisplayNameComparator(PackageManager pm) {
- mPM = pm;
- }
-
- public final int compare(PackageItemInfo aa, PackageItemInfo ab) {
- CharSequence sa = aa.loadLabel(mPM);
- if (sa == null) sa = aa.name;
- CharSequence sb = ab.loadLabel(mPM);
- if (sb == null) sb = ab.name;
- return sCollator.compare(sa.toString(), sb.toString());
- }
-
- private final Collator sCollator = Collator.getInstance();
- private PackageManager mPM;
- }
-}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
deleted file mode 100644
index 698f27f..0000000
--- a/core/java/android/content/pm/PackageManager.java
+++ /dev/null
@@ -1,1626 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.util.AndroidException;
-import android.util.DisplayMetrics;
-
-import java.io.File;
-import java.util.List;
-
-/**
- * Class for retrieving various kinds of information related to the application
- * packages that are currently installed on the device.
- *
- * You can find this class through {@link Context#getPackageManager}.
- */
-public abstract class PackageManager {
-
- /**
- * This exception is thrown when a given package, application, or component
- * name can not be found.
- */
- public static class NameNotFoundException extends AndroidException {
- public NameNotFoundException() {
- }
-
- public NameNotFoundException(String name) {
- super(name);
- }
- }
-
- /**
- * {@link PackageInfo} flag: return information about
- * activities in the package in {@link PackageInfo#activities}.
- */
- public static final int GET_ACTIVITIES = 0x00000001;
-
- /**
- * {@link PackageInfo} flag: return information about
- * intent receivers in the package in
- * {@link PackageInfo#receivers}.
- */
- public static final int GET_RECEIVERS = 0x00000002;
-
- /**
- * {@link PackageInfo} flag: return information about
- * services in the package in {@link PackageInfo#services}.
- */
- public static final int GET_SERVICES = 0x00000004;
-
- /**
- * {@link PackageInfo} flag: return information about
- * content providers in the package in
- * {@link PackageInfo#providers}.
- */
- public static final int GET_PROVIDERS = 0x00000008;
-
- /**
- * {@link PackageInfo} flag: return information about
- * instrumentation in the package in
- * {@link PackageInfo#instrumentation}.
- */
- public static final int GET_INSTRUMENTATION = 0x00000010;
-
- /**
- * {@link PackageInfo} flag: return information about the
- * intent filters supported by the activity.
- */
- public static final int GET_INTENT_FILTERS = 0x00000020;
-
- /**
- * {@link PackageInfo} flag: return information about the
- * signatures included in the package.
- */
- public static final int GET_SIGNATURES = 0x00000040;
-
- /**
- * {@link ResolveInfo} flag: return the IntentFilter that
- * was matched for a particular ResolveInfo in
- * {@link ResolveInfo#filter}.
- */
- public static final int GET_RESOLVED_FILTER = 0x00000040;
-
- /**
- * {@link ComponentInfo} flag: return the {@link ComponentInfo#metaData}
- * data {@link android.os.Bundle}s that are associated with a component.
- * This applies for any API returning a ComponentInfo subclass.
- */
- public static final int GET_META_DATA = 0x00000080;
-
- /**
- * {@link PackageInfo} flag: return the
- * {@link PackageInfo#gids group ids} that are associated with an
- * application.
- * This applies for any API returning an PackageInfo class, either
- * directly or nested inside of another.
- */
- public static final int GET_GIDS = 0x00000100;
-
- /**
- * {@link PackageInfo} flag: include disabled components in the returned info.
- */
- public static final int GET_DISABLED_COMPONENTS = 0x00000200;
-
- /**
- * {@link ApplicationInfo} flag: return the
- * {@link ApplicationInfo#sharedLibraryFiles paths to the shared libraries}
- * that are associated with an application.
- * This applies for any API returning an ApplicationInfo class, either
- * directly or nested inside of another.
- */
- public static final int GET_SHARED_LIBRARY_FILES = 0x00000400;
-
- /**
- * {@link ProviderInfo} flag: return the
- * {@link ProviderInfo#uriPermissionPatterns URI permission patterns}
- * that are associated with a content provider.
- * This applies for any API returning an ProviderInfo class, either
- * directly or nested inside of another.
- */
- public static final int GET_URI_PERMISSION_PATTERNS = 0x00000800;
- /**
- * {@link PackageInfo} flag: return information about
- * permissions in the package in
- * {@link PackageInfo#permissions}.
- */
- public static final int GET_PERMISSIONS = 0x00001000;
-
- /**
- * Flag parameter to retrieve all applications(even uninstalled ones) with data directories.
- * This state could have resulted if applications have been deleted with flag
- * DONT_DELETE_DATA
- * with a possibility of being replaced or reinstalled in future
- */
- public static final int GET_UNINSTALLED_PACKAGES = 0x00002000;
-
- /**
- * {@link PackageInfo} flag: return information about
- * hardware preferences
- * {@link PackageInfo#configPreferences}
- */
- public static final int GET_CONFIGURATIONS = 0x00004000;
-
- /**
- * Permission check result: this is returned by {@link #checkPermission}
- * if the permission has been granted to the given package.
- */
- public static final int PERMISSION_GRANTED = 0;
-
- /**
- * Permission check result: this is returned by {@link #checkPermission}
- * if the permission has not been granted to the given package.
- */
- public static final int PERMISSION_DENIED = -1;
-
- /**
- * Signature check result: this is returned by {@link #checkSignatures}
- * if the two packages have a matching signature.
- */
- public static final int SIGNATURE_MATCH = 0;
-
- /**
- * Signature check result: this is returned by {@link #checkSignatures}
- * if neither of the two packages is signed.
- */
- public static final int SIGNATURE_NEITHER_SIGNED = 1;
-
- /**
- * Signature check result: this is returned by {@link #checkSignatures}
- * if the first package is not signed, but the second is.
- */
- public static final int SIGNATURE_FIRST_NOT_SIGNED = -1;
-
- /**
- * Signature check result: this is returned by {@link #checkSignatures}
- * if the second package is not signed, but the first is.
- */
- public static final int SIGNATURE_SECOND_NOT_SIGNED = -2;
-
- /**
- * Signature check result: this is returned by {@link #checkSignatures}
- * if both packages are signed but there is no matching signature.
- */
- public static final int SIGNATURE_NO_MATCH = -3;
-
- /**
- * Signature check result: this is returned by {@link #checkSignatures}
- * if either of the given package names are not valid.
- */
- public static final int SIGNATURE_UNKNOWN_PACKAGE = -4;
-
- /**
- * Resolution and querying flag: if set, only filters that support the
- * {@link android.content.Intent#CATEGORY_DEFAULT} will be considered for
- * matching. This is a synonym for including the CATEGORY_DEFAULT in your
- * supplied Intent.
- */
- public static final int MATCH_DEFAULT_ONLY = 0x00010000;
-
- public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0;
- public static final int COMPONENT_ENABLED_STATE_ENABLED = 1;
- public static final int COMPONENT_ENABLED_STATE_DISABLED = 2;
-
- /**
- * Flag parameter for {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} to
- * indicate that this package should be installed as forward locked, i.e. only the app itself
- * should have access to it's code and non-resource assets.
- */
- public static final int FORWARD_LOCK_PACKAGE = 0x00000001;
-
- /**
- * Flag parameter for {@link #installPackage} to indicate that you want to replace an already
- * installed package, if one exists
- */
- public static final int REPLACE_EXISTING_PACKAGE = 0x00000002;
-
- /**
- * Flag parameter for
- * {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate
- * that you don't want to kill the app containing the component. Be careful when you set this
- * since changing component states can make the containing application's behavior unpredictable.
- */
- public static final int DONT_KILL_APP = 0x00000001;
-
- /**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} on success.
- */
- public static final int INSTALL_SUCCEEDED = 1;
-
- /**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package is
- * already installed.
- */
- public static final int INSTALL_FAILED_ALREADY_EXISTS = -1;
-
- /**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package archive
- * file is invalid.
- */
- public static final int INSTALL_FAILED_INVALID_APK = -2;
-
- /**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the URI passed in
- * is invalid.
- */
- public static final int INSTALL_FAILED_INVALID_URI = -3;
-
- /**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package manager
- * service found that the device didn't have enough storage space to install the app
- */
- public static final int INSTALL_FAILED_INSUFFICIENT_STORAGE = -4;
-
- /**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if a
- * package is already installed with the same name.
- */
- public static final int INSTALL_FAILED_DUPLICATE_PACKAGE = -5;
-
- /**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the requested shared user does not exist.
- */
- public static final int INSTALL_FAILED_NO_SHARED_USER = -6;
-
- /**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * a previously installed package of the same name has a different signature
- * than the new package (and the old package's data was not removed).
- */
- public static final int INSTALL_FAILED_UPDATE_INCOMPATIBLE = -7;
-
- /**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package is requested a shared user which is already installed on the
- * device and does not have matching signature.
- */
- public static final int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE = -8;
-
- /**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package uses a shared library that is not available.
- */
- public static final int INSTALL_FAILED_MISSING_SHARED_LIBRARY = -9;
-
- /**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package uses a shared library that is not available.
- */
- public static final int INSTALL_FAILED_REPLACE_COULDNT_DELETE = -10;
-
- /**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package failed while optimizing and validating its dex files,
- * either because there was not enough storage or the validation failed.
- */
- public static final int INSTALL_FAILED_DEXOPT = -11;
-
- /**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package failed because the current SDK version is older than
- * that required by the package.
- */
- public static final int INSTALL_FAILED_OLDER_SDK = -12;
-
- /**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser was given a path that is not a file, or does not end with the expected
- * '.apk' extension.
- */
- public static final int INSTALL_PARSE_FAILED_NOT_APK = -100;
-
- /**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser was unable to retrieve the AndroidManifest.xml file.
- */
- public static final int INSTALL_PARSE_FAILED_BAD_MANIFEST = -101;
-
- /**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser encountered an unexpected exception.
- */
- public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102;
-
- /**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser did not find any certificates in the .apk.
- */
- public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103;
-
- /**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser found inconsistent certificates on the files in the .apk.
- */
- public static final int INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES = -104;
-
- /**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser encountered a CertificateEncodingException in one of the
- * files in the .apk.
- */
- public static final int INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING = -105;
-
- /**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser encountered a bad or missing package name in the manifest.
- */
- public static final int INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME = -106;
-
- /**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser encountered a bad shared user id name in the manifest.
- */
- public static final int INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID = -107;
-
- /**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser encountered some structural problem in the manifest.
- */
- public static final int INSTALL_PARSE_FAILED_MANIFEST_MALFORMED = -108;
-
- /**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser did not find any actionable tags (instrumentation or application)
- * in the manifest.
- */
- public static final int INSTALL_PARSE_FAILED_MANIFEST_EMPTY = -109;
-
- /**
- * Indicates the state of installation. Used by PackageManager to
- * figure out incomplete installations. Say a package is being installed
- * (the state is set to PKG_INSTALL_INCOMPLETE) and remains so till
- * the package installation is successful or unsuccesful lin which case
- * the PackageManager will no longer maintain state information associated
- * with the package. If some exception(like device freeze or battery being
- * pulled out) occurs during installation of a package, the PackageManager
- * needs this information to clean up the previously failed installation.
- */
- public static final int PKG_INSTALL_INCOMPLETE = 0;
- public static final int PKG_INSTALL_COMPLETE = 1;
-
- /**
- * Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the
- * package's data directory.
- *
- * @hide
- */
- public static final int DONT_DELETE_DATA = 0x00000001;
-
- /**
- * Retrieve overall information about an application package that is
- * installed on the system.
- *
- * <p>Throws {@link NameNotFoundException} if a package with the given
- * name can not be found on the system.
- *
- * @param packageName The full name (i.e. com.google.apps.contacts) of the
- * desired package.
-
- * @param flags Additional option flags. Use any combination of
- * {@link #GET_ACTIVITIES},
- * {@link #GET_GIDS},
- * {@link #GET_CONFIGURATIONS},
- * {@link #GET_INSTRUMENTATION},
- * {@link #GET_PERMISSIONS},
- * {@link #GET_PROVIDERS},
- * {@link #GET_RECEIVERS},
- * {@link #GET_SERVICES},
- * {@link #GET_SIGNATURES},
- * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned.
- *
- * @return Returns a PackageInfo object containing information about the package.
- * If flag GET_UNINSTALLED_PACKAGES is set and if the package is not
- * found in the list of installed applications, the package information is
- * retrieved from the list of uninstalled applications(which includes
- * installed applications as well as applications
- * with data directory ie applications which had been
- * deleted with DONT_DELTE_DATA flag set).
- *
- * @see #GET_ACTIVITIES
- * @see #GET_GIDS
- * @see #GET_CONFIGURATIONS
- * @see #GET_INSTRUMENTATION
- * @see #GET_PERMISSIONS
- * @see #GET_PROVIDERS
- * @see #GET_RECEIVERS
- * @see #GET_SERVICES
- * @see #GET_SIGNATURES
- * @see #GET_UNINSTALLED_PACKAGES
- *
- */
- public abstract PackageInfo getPackageInfo(String packageName, int flags)
- throws NameNotFoundException;
-
- /**
- * Return an array of all of the secondary group-ids that have been
- * assigned to a package.
- *
- * <p>Throws {@link NameNotFoundException} if a package with the given
- * name can not be found on the system.
- *
- * @param packageName The full name (i.e. com.google.apps.contacts) of the
- * desired package.
- *
- * @return Returns an int array of the assigned gids, or null if there
- * are none.
- */
- public abstract int[] getPackageGids(String packageName)
- throws NameNotFoundException;
-
- /**
- * Retrieve all of the information we know about a particular permission.
- *
- * <p>Throws {@link NameNotFoundException} if a permission with the given
- * name can not be found on the system.
- *
- * @param name The fully qualified name (i.e. com.google.permission.LOGIN)
- * of the permission you are interested in.
- * @param flags Additional option flags. Use {@link #GET_META_DATA} to
- * retrieve any meta-data associated with the permission.
- *
- * @return Returns a {@link PermissionInfo} containing information about the
- * permission.
- */
- public abstract PermissionInfo getPermissionInfo(String name, int flags)
- throws NameNotFoundException;
-
- /**
- * Query for all of the permissions associated with a particular group.
- *
- * <p>Throws {@link NameNotFoundException} if the given group does not
- * exist.
- *
- * @param group The fully qualified name (i.e. com.google.permission.LOGIN)
- * of the permission group you are interested in. Use null to
- * find all of the permissions not associated with a group.
- * @param flags Additional option flags. Use {@link #GET_META_DATA} to
- * retrieve any meta-data associated with the permissions.
- *
- * @return Returns a list of {@link PermissionInfo} containing information
- * about all of the permissions in the given group.
- */
- public abstract List<PermissionInfo> queryPermissionsByGroup(String group,
- int flags) throws NameNotFoundException;
-
- /**
- * Retrieve all of the information we know about a particular group of
- * permissions.
- *
- * <p>Throws {@link NameNotFoundException} if a permission group with the given
- * name can not be found on the system.
- *
- * @param name The fully qualified name (i.e. com.google.permission_group.APPS)
- * of the permission you are interested in.
- * @param flags Additional option flags. Use {@link #GET_META_DATA} to
- * retrieve any meta-data associated with the permission group.
- *
- * @return Returns a {@link PermissionGroupInfo} containing information
- * about the permission.
- */
- public abstract PermissionGroupInfo getPermissionGroupInfo(String name,
- int flags) throws NameNotFoundException;
-
- /**
- * Retrieve all of the known permission groups in the system.
- *
- * @param flags Additional option flags. Use {@link #GET_META_DATA} to
- * retrieve any meta-data associated with the permission group.
- *
- * @return Returns a list of {@link PermissionGroupInfo} containing
- * information about all of the known permission groups.
- */
- public abstract List<PermissionGroupInfo> getAllPermissionGroups(int flags);
-
- /**
- * Retrieve all of the information we know about a particular
- * package/application.
- *
- * <p>Throws {@link NameNotFoundException} if an application with the given
- * package name can not be found on the system.
- *
- * @param packageName The full name (i.e. com.google.apps.contacts) of an
- * application.
- * @param flags Additional option flags. Use any combination of
- * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
- * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned.
- *
- * @return {@link ApplicationInfo} Returns ApplicationInfo object containing
- * information about the package.
- * If flag GET_UNINSTALLED_PACKAGES is set and if the package is not
- * found in the list of installed applications,
- * the application information is retrieved from the
- * list of uninstalled applications(which includes
- * installed applications as well as applications
- * with data directory ie applications which had been
- * deleted with DONT_DELTE_DATA flag set).
- *
- * @see #GET_META_DATA
- * @see #GET_SHARED_LIBRARY_FILES
- * @see #GET_UNINSTALLED_PACKAGES
- */
- public abstract ApplicationInfo getApplicationInfo(String packageName,
- int flags) throws NameNotFoundException;
-
- /**
- * Retrieve all of the information we know about a particular activity
- * class.
- *
- * <p>Throws {@link NameNotFoundException} if an activity with the given
- * class name can not be found on the system.
- *
- * @param className The full name (i.e.
- * com.google.apps.contacts.ContactsList) of an Activity
- * class.
- * @param flags Additional option flags. Use any combination of
- * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
- * to modify the data (in ApplicationInfo) returned.
- *
- * @return {@link ActivityInfo} containing information about the activity.
- *
- * @see #GET_INTENT_FILTERS
- * @see #GET_META_DATA
- * @see #GET_SHARED_LIBRARY_FILES
- */
- public abstract ActivityInfo getActivityInfo(ComponentName className,
- int flags) throws NameNotFoundException;
-
- /**
- * Retrieve all of the information we know about a particular receiver
- * class.
- *
- * <p>Throws {@link NameNotFoundException} if a receiver with the given
- * class name can not be found on the system.
- *
- * @param className The full name (i.e.
- * com.google.apps.contacts.CalendarAlarm) of a Receiver
- * class.
- * @param flags Additional option flags. Use any combination of
- * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
- * to modify the data returned.
- *
- * @return {@link ActivityInfo} containing information about the receiver.
- *
- * @see #GET_INTENT_FILTERS
- * @see #GET_META_DATA
- * @see #GET_SHARED_LIBRARY_FILES
- */
- public abstract ActivityInfo getReceiverInfo(ComponentName className,
- int flags) throws NameNotFoundException;
-
- /**
- * Retrieve all of the information we know about a particular service
- * class.
- *
- * <p>Throws {@link NameNotFoundException} if a service with the given
- * class name can not be found on the system.
- *
- * @param className The full name (i.e.
- * com.google.apps.media.BackgroundPlayback) of a Service
- * class.
- * @param flags Additional option flags. Use any combination of
- * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
- * to modify the data returned.
- *
- * @return ServiceInfo containing information about the service.
- *
- * @see #GET_META_DATA
- * @see #GET_SHARED_LIBRARY_FILES
- */
- public abstract ServiceInfo getServiceInfo(ComponentName className,
- int flags) throws NameNotFoundException;
-
- /**
- * Return a List of all packages that are installed
- * on the device.
- *
- * @param flags Additional option flags. Use any combination of
- * {@link #GET_ACTIVITIES},
- * {@link #GET_GIDS},
- * {@link #GET_CONFIGURATIONS},
- * {@link #GET_INSTRUMENTATION},
- * {@link #GET_PERMISSIONS},
- * {@link #GET_PROVIDERS},
- * {@link #GET_RECEIVERS},
- * {@link #GET_SERVICES},
- * {@link #GET_SIGNATURES},
- * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned.
- *
- * @return A List of PackageInfo objects, one for each package that is
- * installed on the device. In the unlikely case of there being no
- * installed packages, an empty list is returned.
- * If flag GET_UNINSTALLED_PACKAGES is set, a list of all
- * applications including those deleted with DONT_DELETE_DATA
- * (partially installed apps with data directory) will be returned.
- *
- * @see #GET_ACTIVITIES
- * @see #GET_GIDS
- * @see #GET_CONFIGURATIONS
- * @see #GET_INSTRUMENTATION
- * @see #GET_PERMISSIONS
- * @see #GET_PROVIDERS
- * @see #GET_RECEIVERS
- * @see #GET_SERVICES
- * @see #GET_SIGNATURES
- * @see #GET_UNINSTALLED_PACKAGES
- *
- */
- public abstract List<PackageInfo> getInstalledPackages(int flags);
-
- /**
- * Check whether a particular package has been granted a particular
- * permission.
- *
- * @param permName The name of the permission you are checking for,
- * @param pkgName The name of the package you are checking against.
- *
- * @return If the package has the permission, PERMISSION_GRANTED is
- * returned. If it does not have the permission, PERMISSION_DENIED
- * is returned.
- *
- * @see #PERMISSION_GRANTED
- * @see #PERMISSION_DENIED
- */
- public abstract int checkPermission(String permName, String pkgName);
-
- /**
- * Add a new dynamic permission to the system. For this to work, your
- * package must have defined a permission tree through the
- * {@link android.R.styleable#AndroidManifestPermissionTree
- * &lt;permission-tree&gt;} tag in its manifest. A package can only add
- * permissions to trees that were defined by either its own package or
- * another with the same user id; a permission is in a tree if it
- * matches the name of the permission tree + ".": for example,
- * "com.foo.bar" is a member of the permission tree "com.foo".
- *
- * <p>It is good to make your permission tree name descriptive, because you
- * are taking possession of that entire set of permission names. Thus, it
- * must be under a domain you control, with a suffix that will not match
- * any normal permissions that may be declared in any applications that
- * are part of that domain.
- *
- * <p>New permissions must be added before
- * any .apks are installed that use those permissions. Permissions you
- * add through this method are remembered across reboots of the device.
- * If the given permission already exists, the info you supply here
- * will be used to update it.
- *
- * @param info Description of the permission to be added.
- *
- * @return Returns true if a new permission was created, false if an
- * existing one was updated.
- *
- * @throws SecurityException if you are not allowed to add the
- * given permission name.
- *
- * @see #removePermission(String)
- */
- public abstract boolean addPermission(PermissionInfo info);
-
- /**
- * Removes a permission that was previously added with
- * {@link #addPermission(PermissionInfo)}. The same ownership rules apply
- * -- you are only allowed to remove permissions that you are allowed
- * to add.
- *
- * @param name The name of the permission to remove.
- *
- * @throws SecurityException if you are not allowed to remove the
- * given permission name.
- *
- * @see #addPermission(PermissionInfo)
- */
- public abstract void removePermission(String name);
-
- /**
- * Compare the signatures of two packages to determine if the same
- * signature appears in both of them. If they do contain the same
- * signature, then they are allowed special privileges when working
- * with each other: they can share the same user-id, run instrumentation
- * against each other, etc.
- *
- * @param pkg1 First package name whose signature will be compared.
- * @param pkg2 Second package name whose signature will be compared.
- * @return Returns an integer indicating whether there is a matching
- * signature: the value is >= 0 if there is a match (or neither package
- * is signed), or < 0 if there is not a match. The match result can be
- * further distinguished with the success (>= 0) constants
- * {@link #SIGNATURE_MATCH}, {@link #SIGNATURE_NEITHER_SIGNED}; or
- * failure (< 0) constants {@link #SIGNATURE_FIRST_NOT_SIGNED},
- * {@link #SIGNATURE_SECOND_NOT_SIGNED}, {@link #SIGNATURE_NO_MATCH},
- * or {@link #SIGNATURE_UNKNOWN_PACKAGE}.
- *
- * @see #SIGNATURE_MATCH
- * @see #SIGNATURE_NEITHER_SIGNED
- * @see #SIGNATURE_FIRST_NOT_SIGNED
- * @see #SIGNATURE_SECOND_NOT_SIGNED
- * @see #SIGNATURE_NO_MATCH
- * @see #SIGNATURE_UNKNOWN_PACKAGE
- */
- public abstract int checkSignatures(String pkg1, String pkg2);
-
- /**
- * Retrieve the names of all packages that are associated with a particular
- * user id. In most cases, this will be a single package name, the package
- * that has been assigned that user id. Where there are multiple packages
- * sharing the same user id through the "sharedUserId" mechanism, all
- * packages with that id will be returned.
- *
- * @param uid The user id for which you would like to retrieve the
- * associated packages.
- *
- * @return Returns an array of one or more packages assigned to the user
- * id, or null if there are no known packages with the given id.
- */
- public abstract String[] getPackagesForUid(int uid);
-
- /**
- * Retrieve the official name associated with a user id. This name is
- * guaranteed to never change, though it is possibly for the underlying
- * user id to be changed. That is, if you are storing information about
- * user ids in persistent storage, you should use the string returned
- * by this function instead of the raw user-id.
- *
- * @param uid The user id for which you would like to retrieve a name.
- * @return Returns a unique name for the given user id, or null if the
- * user id is not currently assigned.
- */
- public abstract String getNameForUid(int uid);
-
- /**
- * Return the user id associated with a shared user name. Multiple
- * applications can specify a shared user name in their manifest and thus
- * end up using a common uid. This might be used for new applications
- * that use an existing shared user name and need to know the uid of the
- * shared user.
- *
- * @param sharedUserName The shared user name whose uid is to be retrieved.
- * @return Returns the uid associated with the shared user, or NameNotFoundException
- * if the shared user name is not being used by any installed packages
- * @hide
- */
- public abstract int getUidForSharedUser(String sharedUserName)
- throws NameNotFoundException;
-
- /**
- * Return a List of all application packages that are installed on the
- * device. If flag GET_UNINSTALLED_PACKAGES has been set, a list of all
- * applications including those deleted with DONT_DELETE_DATA(partially
- * installed apps with data directory) will be returned.
- *
- * @param flags Additional option flags. Use any combination of
- * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
- * {link #GET_UNINSTALLED_PACKAGES} to modify the data returned.
- *
- * @return A List of ApplicationInfo objects, one for each application that
- * is installed on the device. In the unlikely case of there being
- * no installed applications, an empty list is returned.
- * If flag GET_UNINSTALLED_PACKAGES is set, a list of all
- * applications including those deleted with DONT_DELETE_DATA
- * (partially installed apps with data directory) will be returned.
- *
- * @see #GET_META_DATA
- * @see #GET_SHARED_LIBRARY_FILES
- * @see #GET_UNINSTALLED_PACKAGES
- */
- public abstract List<ApplicationInfo> getInstalledApplications(int flags);
-
- /**
- * Get a list of shared libraries that are available on the
- * system.
- *
- * @return An array of shared library names that are
- * available on the system, or null if none are installed.
- *
- */
- public abstract String[] getSystemSharedLibraryNames();
-
- /**
- * Determine the best action to perform for a given Intent. This is how
- * {@link Intent#resolveActivity} finds an activity if a class has not
- * been explicitly specified.
- *
- * @param intent An intent containing all of the desired specification
- * (action, data, type, category, and/or component).
- * @param flags Additional option flags. The most important is
- * MATCH_DEFAULT_ONLY, to limit the resolution to only
- * those activities that support the CATEGORY_DEFAULT.
- *
- * @return Returns a ResolveInfo containing the final activity intent that
- * was determined to be the best action. Returns null if no
- * matching activity was found.
- *
- * @see #MATCH_DEFAULT_ONLY
- * @see #GET_INTENT_FILTERS
- * @see #GET_RESOLVED_FILTER
- */
- public abstract ResolveInfo resolveActivity(Intent intent, int flags);
-
- /**
- * Retrieve all activities that can be performed for the given intent.
- *
- * @param intent The desired intent as per resolveActivity().
- * @param flags Additional option flags. The most important is
- * MATCH_DEFAULT_ONLY, to limit the resolution to only
- * those activities that support the CATEGORY_DEFAULT.
- *
- * @return A List<ResolveInfo> containing one entry for each matching
- * Activity. These are ordered from best to worst match -- that
- * is, the first item in the list is what is returned by
- * resolveActivity(). If there are no matching activities, an empty
- * list is returned.
- *
- * @see #MATCH_DEFAULT_ONLY
- * @see #GET_INTENT_FILTERS
- * @see #GET_RESOLVED_FILTER
- */
- public abstract List<ResolveInfo> queryIntentActivities(Intent intent,
- int flags);
-
- /**
- * Retrieve a set of activities that should be presented to the user as
- * similar options. This is like {@link #queryIntentActivities}, except it
- * also allows you to supply a list of more explicit Intents that you would
- * like to resolve to particular options, and takes care of returning the
- * final ResolveInfo list in a reasonable order, with no duplicates, based
- * on those inputs.
- *
- * @param caller The class name of the activity that is making the
- * request. This activity will never appear in the output
- * list. Can be null.
- * @param specifics An array of Intents that should be resolved to the
- * first specific results. Can be null.
- * @param intent The desired intent as per resolveActivity().
- * @param flags Additional option flags. The most important is
- * MATCH_DEFAULT_ONLY, to limit the resolution to only
- * those activities that support the CATEGORY_DEFAULT.
- *
- * @return A List<ResolveInfo> containing one entry for each matching
- * Activity. These are ordered first by all of the intents resolved
- * in <var>specifics</var> and then any additional activities that
- * can handle <var>intent</var> but did not get included by one of
- * the <var>specifics</var> intents. If there are no matching
- * activities, an empty list is returned.
- *
- * @see #MATCH_DEFAULT_ONLY
- * @see #GET_INTENT_FILTERS
- * @see #GET_RESOLVED_FILTER
- */
- public abstract List<ResolveInfo> queryIntentActivityOptions(
- ComponentName caller, Intent[] specifics, Intent intent, int flags);
-
- /**
- * Retrieve all receivers that can handle a broadcast of the given intent.
- *
- * @param intent The desired intent as per resolveActivity().
- * @param flags Additional option flags. The most important is
- * MATCH_DEFAULT_ONLY, to limit the resolution to only
- * those activities that support the CATEGORY_DEFAULT.
- *
- * @return A List<ResolveInfo> containing one entry for each matching
- * Receiver. These are ordered from first to last in priority. If
- * there are no matching receivers, an empty list is returned.
- *
- * @see #MATCH_DEFAULT_ONLY
- * @see #GET_INTENT_FILTERS
- * @see #GET_RESOLVED_FILTER
- */
- public abstract List<ResolveInfo> queryBroadcastReceivers(Intent intent,
- int flags);
-
- /**
- * Determine the best service to handle for a given Intent.
- *
- * @param intent An intent containing all of the desired specification
- * (action, data, type, category, and/or component).
- * @param flags Additional option flags.
- *
- * @return Returns a ResolveInfo containing the final service intent that
- * was determined to be the best action. Returns null if no
- * matching service was found.
- *
- * @see #GET_INTENT_FILTERS
- * @see #GET_RESOLVED_FILTER
- */
- public abstract ResolveInfo resolveService(Intent intent, int flags);
-
- /**
- * Retrieve all services that can match the given intent.
- *
- * @param intent The desired intent as per resolveService().
- * @param flags Additional option flags.
- *
- * @return A List<ResolveInfo> containing one entry for each matching
- * ServiceInfo. These are ordered from best to worst match -- that
- * is, the first item in the list is what is returned by
- * resolveService(). If there are no matching services, an empty
- * list is returned.
- *
- * @see #GET_INTENT_FILTERS
- * @see #GET_RESOLVED_FILTER
- */
- public abstract List<ResolveInfo> queryIntentServices(Intent intent,
- int flags);
-
- /**
- * Find a single content provider by its base path name.
- *
- * @param name The name of the provider to find.
- * @param flags Additional option flags. Currently should always be 0.
- *
- * @return ContentProviderInfo Information about the provider, if found,
- * else null.
- */
- public abstract ProviderInfo resolveContentProvider(String name,
- int flags);
-
- /**
- * Retrieve content provider information.
- *
- * <p><em>Note: unlike most other methods, an empty result set is indicated
- * by a null return instead of an empty list.</em>
- *
- * @param processName If non-null, limits the returned providers to only
- * those that are hosted by the given process. If null,
- * all content providers are returned.
- * @param uid If <var>processName</var> is non-null, this is the required
- * uid owning the requested content providers.
- * @param flags Additional option flags. Currently should always be 0.
- *
- * @return A List<ContentProviderInfo> containing one entry for each
- * content provider either patching <var>processName</var> or, if
- * <var>processName</var> is null, all known content providers.
- * <em>If there are no matching providers, null is returned.</em>
- */
- public abstract List<ProviderInfo> queryContentProviders(
- String processName, int uid, int flags);
-
- /**
- * Retrieve all of the information we know about a particular
- * instrumentation class.
- *
- * <p>Throws {@link NameNotFoundException} if instrumentation with the
- * given class name can not be found on the system.
- *
- * @param className The full name (i.e.
- * com.google.apps.contacts.InstrumentList) of an
- * Instrumentation class.
- * @param flags Additional option flags. Currently should always be 0.
- *
- * @return InstrumentationInfo containing information about the
- * instrumentation.
- */
- public abstract InstrumentationInfo getInstrumentationInfo(
- ComponentName className, int flags) throws NameNotFoundException;
-
- /**
- * Retrieve information about available instrumentation code. May be used
- * to retrieve either all instrumentation code, or only the code targeting
- * a particular package.
- *
- * @param targetPackage If null, all instrumentation is returned; only the
- * instrumentation targeting this package name is
- * returned.
- * @param flags Additional option flags. Currently should always be 0.
- *
- * @return A List<InstrumentationInfo> containing one entry for each
- * matching available Instrumentation. Returns an empty list if
- * there is no instrumentation available for the given package.
- */
- public abstract List<InstrumentationInfo> queryInstrumentation(
- String targetPackage, int flags);
-
- /**
- * Retrieve an image from a package. This is a low-level API used by
- * the various package manager info structures (such as
- * {@link ComponentInfo} to implement retrieval of their associated
- * icon.
- *
- * @param packageName The name of the package that this icon is coming from.
- * Can not be null.
- * @param resid The resource identifier of the desired image. Can not be 0.
- * @param appInfo Overall information about <var>packageName</var>. This
- * may be null, in which case the application information will be retrieved
- * for you if needed; if you already have this information around, it can
- * be much more efficient to supply it here.
- *
- * @return Returns a Drawable holding the requested image. Returns null if
- * an image could not be found for any reason.
- */
- public abstract Drawable getDrawable(String packageName, int resid,
- ApplicationInfo appInfo);
-
- /**
- * Retrieve the icon associated with an activity. Given the full name of
- * an activity, retrieves the information about it and calls
- * {@link ComponentInfo#loadIcon ComponentInfo.loadIcon()} to return its icon.
- * If the activity can not be found, NameNotFoundException is thrown.
- *
- * @param activityName Name of the activity whose icon is to be retrieved.
- *
- * @return Returns the image of the icon, or the default activity icon if
- * it could not be found. Does not return null.
- * @throws NameNotFoundException Thrown if the resources for the given
- * activity could not be loaded.
- *
- * @see #getActivityIcon(Intent)
- */
- public abstract Drawable getActivityIcon(ComponentName activityName)
- throws NameNotFoundException;
-
- /**
- * Retrieve the icon associated with an Intent. If intent.getClassName() is
- * set, this simply returns the result of
- * getActivityIcon(intent.getClassName()). Otherwise it resolves the intent's
- * component and returns the icon associated with the resolved component.
- * If intent.getClassName() can not be found or the Intent can not be resolved
- * to a component, NameNotFoundException is thrown.
- *
- * @param intent The intent for which you would like to retrieve an icon.
- *
- * @return Returns the image of the icon, or the default activity icon if
- * it could not be found. Does not return null.
- * @throws NameNotFoundException Thrown if the resources for application
- * matching the given intent could not be loaded.
- *
- * @see #getActivityIcon(ComponentName)
- */
- public abstract Drawable getActivityIcon(Intent intent)
- throws NameNotFoundException;
-
- /**
- * Return the generic icon for an activity that is used when no specific
- * icon is defined.
- *
- * @return Drawable Image of the icon.
- */
- public abstract Drawable getDefaultActivityIcon();
-
- /**
- * Retrieve the icon associated with an application. If it has not defined
- * an icon, the default app icon is returned. Does not return null.
- *
- * @param info Information about application being queried.
- *
- * @return Returns the image of the icon, or the default application icon
- * if it could not be found.
- *
- * @see #getApplicationIcon(String)
- */
- public abstract Drawable getApplicationIcon(ApplicationInfo info);
-
- /**
- * Retrieve the icon associated with an application. Given the name of the
- * application's package, retrieves the information about it and calls
- * getApplicationIcon() to return its icon. If the application can not be
- * found, NameNotFoundException is thrown.
- *
- * @param packageName Name of the package whose application icon is to be
- * retrieved.
- *
- * @return Returns the image of the icon, or the default application icon
- * if it could not be found. Does not return null.
- * @throws NameNotFoundException Thrown if the resources for the given
- * application could not be loaded.
- *
- * @see #getApplicationIcon(ApplicationInfo)
- */
- public abstract Drawable getApplicationIcon(String packageName)
- throws NameNotFoundException;
-
- /**
- * Retrieve text from a package. This is a low-level API used by
- * the various package manager info structures (such as
- * {@link ComponentInfo} to implement retrieval of their associated
- * labels and other text.
- *
- * @param packageName The name of the package that this text is coming from.
- * Can not be null.
- * @param resid The resource identifier of the desired text. Can not be 0.
- * @param appInfo Overall information about <var>packageName</var>. This
- * may be null, in which case the application information will be retrieved
- * for you if needed; if you already have this information around, it can
- * be much more efficient to supply it here.
- *
- * @return Returns a CharSequence holding the requested text. Returns null
- * if the text could not be found for any reason.
- */
- public abstract CharSequence getText(String packageName, int resid,
- ApplicationInfo appInfo);
-
- /**
- * Retrieve an XML file from a package. This is a low-level API used to
- * retrieve XML meta data.
- *
- * @param packageName The name of the package that this xml is coming from.
- * Can not be null.
- * @param resid The resource identifier of the desired xml. Can not be 0.
- * @param appInfo Overall information about <var>packageName</var>. This
- * may be null, in which case the application information will be retrieved
- * for you if needed; if you already have this information around, it can
- * be much more efficient to supply it here.
- *
- * @return Returns an XmlPullParser allowing you to parse out the XML
- * data. Returns null if the xml resource could not be found for any
- * reason.
- */
- public abstract XmlResourceParser getXml(String packageName, int resid,
- ApplicationInfo appInfo);
-
- /**
- * Return the label to use for this application.
- *
- * @return Returns the label associated with this application, or null if
- * it could not be found for any reason.
- * @param info The application to get the label of
- */
- public abstract CharSequence getApplicationLabel(ApplicationInfo info);
-
- /**
- * Retrieve the resources associated with an activity. Given the full
- * name of an activity, retrieves the information about it and calls
- * getResources() to return its application's resources. If the activity
- * can not be found, NameNotFoundException is thrown.
- *
- * @param activityName Name of the activity whose resources are to be
- * retrieved.
- *
- * @return Returns the application's Resources.
- * @throws NameNotFoundException Thrown if the resources for the given
- * application could not be loaded.
- *
- * @see #getResourcesForApplication(ApplicationInfo)
- */
- public abstract Resources getResourcesForActivity(ComponentName activityName)
- throws NameNotFoundException;
-
- /**
- * Retrieve the resources for an application. Throws NameNotFoundException
- * if the package is no longer installed.
- *
- * @param app Information about the desired application.
- *
- * @return Returns the application's Resources.
- * @throws NameNotFoundException Thrown if the resources for the given
- * application could not be loaded (most likely because it was uninstalled).
- */
- public abstract Resources getResourcesForApplication(ApplicationInfo app)
- throws NameNotFoundException;
-
- /**
- * Retrieve the resources associated with an application. Given the full
- * package name of an application, retrieves the information about it and
- * calls getResources() to return its application's resources. If the
- * appPackageName can not be found, NameNotFoundException is thrown.
- *
- * @param appPackageName Package name of the application whose resources
- * are to be retrieved.
- *
- * @return Returns the application's Resources.
- * @throws NameNotFoundException Thrown if the resources for the given
- * application could not be loaded.
- *
- * @see #getResourcesForApplication(ApplicationInfo)
- */
- public abstract Resources getResourcesForApplication(String appPackageName)
- throws NameNotFoundException;
-
- /**
- * Retrieve overall information about an application package defined
- * in a package archive file
- *
- * @param archiveFilePath The path to the archive file
- * @param flags Additional option flags. Use any combination of
- * {@link #GET_ACTIVITIES},
- * {@link #GET_GIDS},
- * {@link #GET_CONFIGURATIONS},
- * {@link #GET_INSTRUMENTATION},
- * {@link #GET_PERMISSIONS},
- * {@link #GET_PROVIDERS},
- * {@link #GET_RECEIVERS},
- * {@link #GET_SERVICES},
- * {@link #GET_SIGNATURES}, to modify the data returned.
- *
- * @return Returns the information about the package. Returns
- * null if the package could not be successfully parsed.
- *
- * @see #GET_ACTIVITIES
- * @see #GET_GIDS
- * @see #GET_CONFIGURATIONS
- * @see #GET_INSTRUMENTATION
- * @see #GET_PERMISSIONS
- * @see #GET_PROVIDERS
- * @see #GET_RECEIVERS
- * @see #GET_SERVICES
- * @see #GET_SIGNATURES
- *
- */
- public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) {
- PackageParser packageParser = new PackageParser(archiveFilePath);
- DisplayMetrics metrics = new DisplayMetrics();
- metrics.setToDefaults();
- final File sourceFile = new File(archiveFilePath);
- PackageParser.Package pkg = packageParser.parsePackage(
- sourceFile, archiveFilePath, metrics, 0);
- if (pkg == null) {
- return null;
- }
- return PackageParser.generatePackageInfo(pkg, null, flags);
- }
-
- /**
- * Install a package. Since this may take a little while, the result will
- * be posted back to the given observer. An installation will fail if the calling context
- * lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the
- * package named in the package file's manifest is already installed, or if there's no space
- * available on the device.
- *
- * @param packageURI The location of the package file to install. This can be a 'file:' or a
- * 'content:' URI.
- * @param observer An observer callback to get notified when the package installation is
- * complete. {@link IPackageInstallObserver#packageInstalled(String, int)} will be
- * called when that happens. observer may be null to indicate that no callback is desired.
- * @param flags - possible values: {@link #FORWARD_LOCK_PACKAGE},
- * {@link #REPLACE_EXISTING_PACKAGE}
- *
- * @see #installPackage(android.net.Uri)
- */
- public abstract void installPackage(
- Uri packageURI, IPackageInstallObserver observer, int flags);
-
- /**
- * Attempts to delete a package. Since this may take a little while, the result will
- * be posted back to the given observer. A deletion will fail if the calling context
- * lacks the {@link android.Manifest.permission#DELETE_PACKAGES} permission, if the
- * named package cannot be found, or if the named package is a "system package".
- * (TODO: include pointer to documentation on "system packages")
- *
- * @param packageName The name of the package to delete
- * @param observer An observer callback to get notified when the package deletion is
- * complete. {@link android.content.pm.IPackageDeleteObserver#packageDeleted(boolean)} will be
- * called when that happens. observer may be null to indicate that no callback is desired.
- * @param flags - possible values: {@link #DONT_DELETE_DATA}
- *
- * @hide
- */
- public abstract void deletePackage(
- String packageName, IPackageDeleteObserver observer, int flags);
- /**
- * Attempts to clear the user data directory of an application.
- * Since this may take a little while, the result will
- * be posted back to the given observer. A deletion will fail if the
- * named package cannot be found, or if the named package is a "system package".
- *
- * @param packageName The name of the package
- * @param observer An observer callback to get notified when the operation is finished
- * {@link android.content.pm.IPackageDataObserver#onRemoveCompleted(String, boolean)}
- * will be called when that happens. observer may be null to indicate that
- * no callback is desired.
- *
- * @hide
- */
- public abstract void clearApplicationUserData(String packageName,
- IPackageDataObserver observer);
- /**
- * Attempts to delete the cache files associated with an application.
- * Since this may take a little while, the result will
- * be posted back to the given observer. A deletion will fail if the calling context
- * lacks the {@link android.Manifest.permission#DELETE_CACHE_FILES} permission, if the
- * named package cannot be found, or if the named package is a "system package".
- *
- * @param packageName The name of the package to delete
- * @param observer An observer callback to get notified when the cache file deletion
- * is complete.
- * {@link android.content.pm.IPackageDataObserver#onRemoveCompleted(String, boolean)}
- * will be called when that happens. observer may be null to indicate that
- * no callback is desired.
- *
- * @hide
- */
- public abstract void deleteApplicationCacheFiles(String packageName,
- IPackageDataObserver observer);
-
- /**
- * Free storage by deleting LRU sorted list of cache files across
- * all applications. If the currently available free storage
- * on the device is greater than or equal to the requested
- * free storage, no cache files are cleared. If the currently
- * available storage on the device is less than the requested
- * free storage, some or all of the cache files across
- * all applications are deleted (based on last accessed time)
- * to increase the free storage space on the device to
- * the requested value. There is no guarantee that clearing all
- * the cache files from all applications will clear up
- * enough storage to achieve the desired value.
- * @param freeStorageSize The number of bytes of storage to be
- * freed by the system. Say if freeStorageSize is XX,
- * and the current free storage is YY,
- * if XX is less than YY, just return. if not free XX-YY number
- * of bytes if possible.
- * @param observer call back used to notify when
- * the operation is completed
- *
- * @hide
- */
- public abstract void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer);
-
- /**
- * Free storage by deleting LRU sorted list of cache files across
- * all applications. If the currently available free storage
- * on the device is greater than or equal to the requested
- * free storage, no cache files are cleared. If the currently
- * available storage on the device is less than the requested
- * free storage, some or all of the cache files across
- * all applications are deleted (based on last accessed time)
- * to increase the free storage space on the device to
- * the requested value. There is no guarantee that clearing all
- * the cache files from all applications will clear up
- * enough storage to achieve the desired value.
- * @param freeStorageSize The number of bytes of storage to be
- * freed by the system. Say if freeStorageSize is XX,
- * and the current free storage is YY,
- * if XX is less than YY, just return. if not free XX-YY number
- * of bytes if possible.
- * @param opFinishedIntent PendingIntent call back used to
- * notify when the operation is completed.May be null
- * to indicate that no call back is desired.
- *
- * @hide
- */
- public abstract void freeStorage(long freeStorageSize, PendingIntent opFinishedIntent);
-
- /**
- * Retrieve the size information for a package.
- * Since this may take a little while, the result will
- * be posted back to the given observer. The calling context
- * should have the {@link android.Manifest.permission#GET_PACKAGE_SIZE} permission.
- *
- * @param packageName The name of the package whose size information is to be retrieved
- * @param observer An observer callback to get notified when the operation
- * is complete.
- * {@link android.content.pm.IPackageStatsObserver#onGetStatsCompleted(PackageStats, boolean)}
- * The observer's callback is invoked with a PackageStats object(containing the
- * code, data and cache sizes of the package) and a boolean value representing
- * the status of the operation. observer may be null to indicate that
- * no callback is desired.
- *
- * @hide
- */
- public abstract void getPackageSizeInfo(String packageName,
- IPackageStatsObserver observer);
-
- /**
- * Install a package.
- *
- * @param packageURI The location of the package file to install
- *
- * @see #installPackage(android.net.Uri, IPackageInstallObserver, int)
- */
- public void installPackage(Uri packageURI) {
- installPackage(packageURI, null, 0);
- }
-
- /**
- * Add a new package to the list of preferred packages. This new package
- * will be added to the front of the list (removed from its current location
- * if already listed), meaning it will now be preferred over all other
- * packages when resolving conflicts.
- *
- * @param packageName The package name of the new package to make preferred.
- */
- public abstract void addPackageToPreferred(String packageName);
-
- /**
- * Remove a package from the list of preferred packages. If it was on
- * the list, it will no longer be preferred over other packages.
- *
- * @param packageName The package name to remove.
- */
- public abstract void removePackageFromPreferred(String packageName);
-
- /**
- * Retrieve the list of all currently configured preferred packages. The
- * first package on the list is the most preferred, the last is the
- * least preferred.
- *
- * @param flags Additional option flags. Use any combination of
- * {@link #GET_ACTIVITIES},
- * {@link #GET_GIDS},
- * {@link #GET_CONFIGURATIONS},
- * {@link #GET_INSTRUMENTATION},
- * {@link #GET_PERMISSIONS},
- * {@link #GET_PROVIDERS},
- * {@link #GET_RECEIVERS},
- * {@link #GET_SERVICES},
- * {@link #GET_SIGNATURES}, to modify the data returned.
- *
- * @return Returns a list of PackageInfo objects describing each
- * preferred application, in order of preference.
- *
- * @see #GET_ACTIVITIES
- * @see #GET_GIDS
- * @see #GET_CONFIGURATIONS
- * @see #GET_INSTRUMENTATION
- * @see #GET_PERMISSIONS
- * @see #GET_PROVIDERS
- * @see #GET_RECEIVERS
- * @see #GET_SERVICES
- * @see #GET_SIGNATURES
- */
- public abstract List<PackageInfo> getPreferredPackages(int flags);
-
- /**
- * Add a new preferred activity mapping to the system. This will be used
- * to automatically select the given activity component when
- * {@link Context#startActivity(Intent) Context.startActivity()} finds
- * multiple matching activities and also matches the given filter.
- *
- * @param filter The set of intents under which this activity will be
- * made preferred.
- * @param match The IntentFilter match category that this preference
- * applies to.
- * @param set The set of activities that the user was picking from when
- * this preference was made.
- * @param activity The component name of the activity that is to be
- * preferred.
- */
- public abstract void addPreferredActivity(IntentFilter filter, int match,
- ComponentName[] set, ComponentName activity);
-
- /**
- * Remove all preferred activity mappings, previously added with
- * {@link #addPreferredActivity}, from the
- * system whose activities are implemented in the given package name.
- *
- * @param packageName The name of the package whose preferred activity
- * mappings are to be removed.
- */
- public abstract void clearPackagePreferredActivities(String packageName);
-
- /**
- * Retrieve all preferred activities, previously added with
- * {@link #addPreferredActivity}, that are
- * currently registered with the system.
- *
- * @param outFilters A list in which to place the filters of all of the
- * preferred activities, or null for none.
- * @param outActivities A list in which to place the component names of
- * all of the preferred activities, or null for none.
- * @param packageName An option package in which you would like to limit
- * the list. If null, all activities will be returned; if non-null, only
- * those activities in the given package are returned.
- *
- * @return Returns the total number of registered preferred activities
- * (the number of distinct IntentFilter records, not the number of unique
- * activity components) that were found.
- */
- public abstract int getPreferredActivities(List<IntentFilter> outFilters,
- List<ComponentName> outActivities, String packageName);
-
- /**
- * Set the enabled setting for a package component (activity, receiver, service, provider).
- * This setting will override any enabled state which may have been set by the component in its
- * manifest.
- *
- * @param componentName The component to enable
- * @param newState The new enabled state for the component. The legal values for this state
- * are:
- * {@link #COMPONENT_ENABLED_STATE_ENABLED},
- * {@link #COMPONENT_ENABLED_STATE_DISABLED}
- * and
- * {@link #COMPONENT_ENABLED_STATE_DEFAULT}
- * The last one removes the setting, thereby restoring the component's state to
- * whatever was set in it's manifest (or enabled, by default).
- * @param flags Optional behavior flags: {@link #DONT_KILL_APP} or 0.
- */
- public abstract void setComponentEnabledSetting(ComponentName componentName,
- int newState, int flags);
-
-
- /**
- * Return the the enabled setting for a package component (activity,
- * receiver, service, provider). This returns the last value set by
- * {@link #setComponentEnabledSetting(ComponentName, int, int)}; in most
- * cases this value will be {@link #COMPONENT_ENABLED_STATE_DEFAULT} since
- * the value originally specified in the manifest has not been modified.
- *
- * @param componentName The component to retrieve.
- * @return Returns the current enabled state for the component. May
- * be one of {@link #COMPONENT_ENABLED_STATE_ENABLED},
- * {@link #COMPONENT_ENABLED_STATE_DISABLED}, or
- * {@link #COMPONENT_ENABLED_STATE_DEFAULT}. The last one means the
- * component's enabled state is based on the original information in
- * the manifest as found in {@link ComponentInfo}.
- */
- public abstract int getComponentEnabledSetting(ComponentName componentName);
-
- /**
- * Set the enabled setting for an application
- * This setting will override any enabled state which may have been set by the application in
- * its manifest. It also overrides the enabled state set in the manifest for any of the
- * application's components. It does not override any enabled state set by
- * {@link #setComponentEnabledSetting} for any of the application's components.
- *
- * @param packageName The package name of the application to enable
- * @param newState The new enabled state for the component. The legal values for this state
- * are:
- * {@link #COMPONENT_ENABLED_STATE_ENABLED},
- * {@link #COMPONENT_ENABLED_STATE_DISABLED}
- * and
- * {@link #COMPONENT_ENABLED_STATE_DEFAULT}
- * The last one removes the setting, thereby restoring the applications's state to
- * whatever was set in its manifest (or enabled, by default).
- * @param flags Optional behavior flags: {@link #DONT_KILL_APP} or 0.
- */
- public abstract void setApplicationEnabledSetting(String packageName,
- int newState, int flags);
-
- /**
- * Return the the enabled setting for an application. This returns
- * the last value set by
- * {@link #setApplicationEnabledSetting(String, int, int)}; in most
- * cases this value will be {@link #COMPONENT_ENABLED_STATE_DEFAULT} since
- * the value originally specified in the manifest has not been modified.
- *
- * @param packageName The component to retrieve.
- * @return Returns the current enabled state for the component. May
- * be one of {@link #COMPONENT_ENABLED_STATE_ENABLED},
- * {@link #COMPONENT_ENABLED_STATE_DISABLED}, or
- * {@link #COMPONENT_ENABLED_STATE_DEFAULT}. The last one means the
- * application's enabled state is based on the original information in
- * the manifest as found in {@link ComponentInfo}.
- */
- public abstract int getApplicationEnabledSetting(String packageName);
-
- /**
- * Return whether the device has been booted into safe mode.
- */
- public abstract boolean isSafeMode();
-}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
deleted file mode 100644
index 4ae8b08..0000000
--- a/core/java/android/content/pm/PackageParser.java
+++ /dev/null
@@ -1,2352 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.AssetManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.os.Bundle;
-import android.os.PatternMatcher;
-import android.util.AttributeSet;
-import android.util.Config;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.TypedValue;
-import com.android.internal.util.XmlUtils;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.ref.WeakReference;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateEncodingException;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-
-/**
- * Package archive parsing
- *
- * {@hide}
- */
-public class PackageParser {
-
- private String mArchiveSourcePath;
- private String[] mSeparateProcesses;
- private int mSdkVersion;
-
- private int mParseError = PackageManager.INSTALL_SUCCEEDED;
-
- private static final Object mSync = new Object();
- private static WeakReference<byte[]> mReadBuffer;
-
- /** If set to true, we will only allow package files that exactly match
- * the DTD. Otherwise, we try to get as much from the package as we
- * can without failing. This should normally be set to false, to
- * support extensions to the DTD in future versions. */
- private static final boolean RIGID_PARSER = false;
-
- private static final String TAG = "PackageParser";
-
- public PackageParser(String archiveSourcePath) {
- mArchiveSourcePath = archiveSourcePath;
- }
-
- public void setSeparateProcesses(String[] procs) {
- mSeparateProcesses = procs;
- }
-
- public void setSdkVersion(int sdkVersion) {
- mSdkVersion = sdkVersion;
- }
-
- private static final boolean isPackageFilename(String name) {
- return name.endsWith(".apk");
- }
-
- /**
- * Generate and return the {@link PackageInfo} for a parsed package.
- *
- * @param p the parsed package.
- * @param flags indicating which optional information is included.
- */
- public static PackageInfo generatePackageInfo(PackageParser.Package p,
- int gids[], int flags) {
-
- PackageInfo pi = new PackageInfo();
- pi.packageName = p.packageName;
- pi.versionCode = p.mVersionCode;
- pi.versionName = p.mVersionName;
- pi.sharedUserId = p.mSharedUserId;
- pi.sharedUserLabel = p.mSharedUserLabel;
- pi.applicationInfo = p.applicationInfo;
- if ((flags&PackageManager.GET_GIDS) != 0) {
- pi.gids = gids;
- }
- if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
- int N = p.configPreferences.size();
- if (N > 0) {
- pi.configPreferences = new ConfigurationInfo[N];
- for (int i=0; i<N; i++) {
- pi.configPreferences[i] = p.configPreferences.get(i);
- }
- }
- }
- if ((flags&PackageManager.GET_ACTIVITIES) != 0) {
- int N = p.activities.size();
- if (N > 0) {
- pi.activities = new ActivityInfo[N];
- for (int i=0; i<N; i++) {
- final Activity activity = p.activities.get(i);
- if (activity.info.enabled
- || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.activities[i] = generateActivityInfo(p.activities.get(i), flags);
- }
- }
- }
- }
- if ((flags&PackageManager.GET_RECEIVERS) != 0) {
- int N = p.receivers.size();
- if (N > 0) {
- pi.receivers = new ActivityInfo[N];
- for (int i=0; i<N; i++) {
- final Activity activity = p.receivers.get(i);
- if (activity.info.enabled
- || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.receivers[i] = generateActivityInfo(p.receivers.get(i), flags);
- }
- }
- }
- }
- if ((flags&PackageManager.GET_SERVICES) != 0) {
- int N = p.services.size();
- if (N > 0) {
- pi.services = new ServiceInfo[N];
- for (int i=0; i<N; i++) {
- final Service service = p.services.get(i);
- if (service.info.enabled
- || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.services[i] = generateServiceInfo(p.services.get(i), flags);
- }
- }
- }
- }
- if ((flags&PackageManager.GET_PROVIDERS) != 0) {
- int N = p.providers.size();
- if (N > 0) {
- pi.providers = new ProviderInfo[N];
- for (int i=0; i<N; i++) {
- final Provider provider = p.providers.get(i);
- if (provider.info.enabled
- || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.providers[i] = generateProviderInfo(p.providers.get(i), flags);
- }
- }
- }
- }
- if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
- int N = p.instrumentation.size();
- if (N > 0) {
- pi.instrumentation = new InstrumentationInfo[N];
- for (int i=0; i<N; i++) {
- pi.instrumentation[i] = generateInstrumentationInfo(
- p.instrumentation.get(i), flags);
- }
- }
- }
- if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
- int N = p.permissions.size();
- if (N > 0) {
- pi.permissions = new PermissionInfo[N];
- for (int i=0; i<N; i++) {
- pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
- }
- }
- N = p.requestedPermissions.size();
- if (N > 0) {
- pi.requestedPermissions = new String[N];
- for (int i=0; i<N; i++) {
- pi.requestedPermissions[i] = p.requestedPermissions.get(i);
- }
- }
- }
- if ((flags&PackageManager.GET_SIGNATURES) != 0) {
- int N = p.mSignatures.length;
- if (N > 0) {
- pi.signatures = new Signature[N];
- System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N);
- }
- }
- return pi;
- }
-
- private Certificate[] loadCertificates(JarFile jarFile, JarEntry je,
- byte[] readBuffer) {
- try {
- // We must read the stream for the JarEntry to retrieve
- // its certificates.
- InputStream is = jarFile.getInputStream(je);
- while (is.read(readBuffer, 0, readBuffer.length) != -1) {
- // not using
- }
- is.close();
- return je != null ? je.getCertificates() : null;
- } catch (IOException e) {
- Log.w(TAG, "Exception reading " + je.getName() + " in "
- + jarFile.getName(), e);
- }
- return null;
- }
-
- public final static int PARSE_IS_SYSTEM = 0x0001;
- public final static int PARSE_CHATTY = 0x0002;
- public final static int PARSE_MUST_BE_APK = 0x0004;
- public final static int PARSE_IGNORE_PROCESSES = 0x0008;
-
- public int getParseError() {
- return mParseError;
- }
-
- public Package parsePackage(File sourceFile, String destFileName,
- DisplayMetrics metrics, int flags) {
- mParseError = PackageManager.INSTALL_SUCCEEDED;
-
- mArchiveSourcePath = sourceFile.getPath();
- if (!sourceFile.isFile()) {
- Log.w(TAG, "Skipping dir: " + mArchiveSourcePath);
- mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
- return null;
- }
- if (!isPackageFilename(sourceFile.getName())
- && (flags&PARSE_MUST_BE_APK) != 0) {
- if ((flags&PARSE_IS_SYSTEM) == 0) {
- // We expect to have non-.apk files in the system dir,
- // so don't warn about them.
- Log.w(TAG, "Skipping non-package file: " + mArchiveSourcePath);
- }
- mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
- return null;
- }
-
- if ((flags&PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
- TAG, "Scanning package: " + mArchiveSourcePath);
-
- XmlResourceParser parser = null;
- AssetManager assmgr = null;
- boolean assetError = true;
- try {
- assmgr = new AssetManager();
- if(assmgr.addAssetPath(mArchiveSourcePath) != 0) {
- parser = assmgr.openXmlResourceParser("AndroidManifest.xml");
- assetError = false;
- } else {
- Log.w(TAG, "Failed adding asset path:"+mArchiveSourcePath);
- }
- } catch (Exception e) {
- Log.w(TAG, "Unable to read AndroidManifest.xml of "
- + mArchiveSourcePath, e);
- }
- if(assetError) {
- if (assmgr != null) assmgr.close();
- mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
- return null;
- }
- String[] errorText = new String[1];
- Package pkg = null;
- Exception errorException = null;
- try {
- // XXXX todo: need to figure out correct configuration.
- Resources res = new Resources(assmgr, metrics, null);
- pkg = parsePackage(res, parser, flags, errorText);
- } catch (Exception e) {
- errorException = e;
- mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
- }
-
-
- if (pkg == null) {
- if (errorException != null) {
- Log.w(TAG, mArchiveSourcePath, errorException);
- } else {
- Log.w(TAG, mArchiveSourcePath + " (at "
- + parser.getPositionDescription()
- + "): " + errorText[0]);
- }
- parser.close();
- assmgr.close();
- if (mParseError == PackageManager.INSTALL_SUCCEEDED) {
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- }
- return null;
- }
-
- parser.close();
- assmgr.close();
-
- pkg.applicationInfo.sourceDir = destFileName;
- pkg.applicationInfo.publicSourceDir = destFileName;
- pkg.mSignatures = null;
-
- return pkg;
- }
-
- public boolean collectCertificates(Package pkg, int flags) {
- pkg.mSignatures = null;
-
- WeakReference<byte[]> readBufferRef;
- byte[] readBuffer = null;
- synchronized (mSync) {
- readBufferRef = mReadBuffer;
- if (readBufferRef != null) {
- mReadBuffer = null;
- readBuffer = readBufferRef.get();
- }
- if (readBuffer == null) {
- readBuffer = new byte[8192];
- readBufferRef = new WeakReference<byte[]>(readBuffer);
- }
- }
-
- try {
- JarFile jarFile = new JarFile(mArchiveSourcePath);
-
- Certificate[] certs = null;
-
- if ((flags&PARSE_IS_SYSTEM) != 0) {
- // If this package comes from the system image, then we
- // can trust it... we'll just use the AndroidManifest.xml
- // to retrieve its signatures, not validating all of the
- // files.
- JarEntry jarEntry = jarFile.getJarEntry("AndroidManifest.xml");
- certs = loadCertificates(jarFile, jarEntry, readBuffer);
- if (certs == null) {
- Log.e(TAG, "Package " + pkg.packageName
- + " has no certificates at entry "
- + jarEntry.getName() + "; ignoring!");
- jarFile.close();
- mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
- return false;
- }
- if (false) {
- Log.i(TAG, "File " + mArchiveSourcePath + ": entry=" + jarEntry
- + " certs=" + (certs != null ? certs.length : 0));
- if (certs != null) {
- final int N = certs.length;
- for (int i=0; i<N; i++) {
- Log.i(TAG, " Public key: "
- + certs[i].getPublicKey().getEncoded()
- + " " + certs[i].getPublicKey());
- }
- }
- }
-
- } else {
- Enumeration entries = jarFile.entries();
- while (entries.hasMoreElements()) {
- JarEntry je = (JarEntry)entries.nextElement();
- if (je.isDirectory()) continue;
- if (je.getName().startsWith("META-INF/")) continue;
- Certificate[] localCerts = loadCertificates(jarFile, je,
- readBuffer);
- if (false) {
- Log.i(TAG, "File " + mArchiveSourcePath + " entry " + je.getName()
- + ": certs=" + certs + " ("
- + (certs != null ? certs.length : 0) + ")");
- }
- if (localCerts == null) {
- Log.e(TAG, "Package " + pkg.packageName
- + " has no certificates at entry "
- + je.getName() + "; ignoring!");
- jarFile.close();
- mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
- return false;
- } else if (certs == null) {
- certs = localCerts;
- } else {
- // Ensure all certificates match.
- for (int i=0; i<certs.length; i++) {
- boolean found = false;
- for (int j=0; j<localCerts.length; j++) {
- if (certs[i] != null &&
- certs[i].equals(localCerts[j])) {
- found = true;
- break;
- }
- }
- if (!found || certs.length != localCerts.length) {
- Log.e(TAG, "Package " + pkg.packageName
- + " has mismatched certificates at entry "
- + je.getName() + "; ignoring!");
- jarFile.close();
- mParseError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
- return false;
- }
- }
- }
- }
- }
- jarFile.close();
-
- synchronized (mSync) {
- mReadBuffer = readBufferRef;
- }
-
- if (certs != null && certs.length > 0) {
- final int N = certs.length;
- pkg.mSignatures = new Signature[certs.length];
- for (int i=0; i<N; i++) {
- pkg.mSignatures[i] = new Signature(
- certs[i].getEncoded());
- }
- } else {
- Log.e(TAG, "Package " + pkg.packageName
- + " has no certificates; ignoring!");
- mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
- return false;
- }
- } catch (CertificateEncodingException e) {
- Log.w(TAG, "Exception reading " + mArchiveSourcePath, e);
- mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
- return false;
- } catch (IOException e) {
- Log.w(TAG, "Exception reading " + mArchiveSourcePath, e);
- mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
- return false;
- } catch (RuntimeException e) {
- Log.w(TAG, "Exception reading " + mArchiveSourcePath, e);
- mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
- return false;
- }
-
- return true;
- }
-
- public static String parsePackageName(String packageFilePath, int flags) {
- XmlResourceParser parser = null;
- AssetManager assmgr = null;
- try {
- assmgr = new AssetManager();
- int cookie = assmgr.addAssetPath(packageFilePath);
- parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");
- } catch (Exception e) {
- if (assmgr != null) assmgr.close();
- Log.w(TAG, "Unable to read AndroidManifest.xml of "
- + packageFilePath, e);
- return null;
- }
- AttributeSet attrs = parser;
- String errors[] = new String[1];
- String packageName = null;
- try {
- packageName = parsePackageName(parser, attrs, flags, errors);
- } catch (IOException e) {
- Log.w(TAG, packageFilePath, e);
- } catch (XmlPullParserException e) {
- Log.w(TAG, packageFilePath, e);
- } finally {
- if (parser != null) parser.close();
- if (assmgr != null) assmgr.close();
- }
- if (packageName == null) {
- Log.e(TAG, "parsePackageName error: " + errors[0]);
- return null;
- }
- return packageName;
- }
-
- private static String validateName(String name, boolean requiresSeparator) {
- final int N = name.length();
- boolean hasSep = false;
- boolean front = true;
- for (int i=0; i<N; i++) {
- final char c = name.charAt(i);
- if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
- front = false;
- continue;
- }
- if (!front) {
- if ((c >= '0' && c <= '9') || c == '_') {
- continue;
- }
- }
- if (c == '.') {
- hasSep = true;
- front = true;
- continue;
- }
- return "bad character '" + c + "'";
- }
- return hasSep || !requiresSeparator
- ? null : "must have at least one '.' separator";
- }
-
- private static String parsePackageName(XmlPullParser parser,
- AttributeSet attrs, int flags, String[] outError)
- throws IOException, XmlPullParserException {
-
- int type;
- while ((type=parser.next()) != parser.START_TAG
- && type != parser.END_DOCUMENT) {
- ;
- }
-
- if (type != parser.START_TAG) {
- outError[0] = "No start tag found";
- return null;
- }
- if ((flags&PARSE_CHATTY) != 0 && Config.LOGV) Log.v(
- TAG, "Root element name: '" + parser.getName() + "'");
- if (!parser.getName().equals("manifest")) {
- outError[0] = "No <manifest> tag";
- return null;
- }
- String pkgName = attrs.getAttributeValue(null, "package");
- if (pkgName == null || pkgName.length() == 0) {
- outError[0] = "<manifest> does not specify package";
- return null;
- }
- String nameError = validateName(pkgName, true);
- if (nameError != null && !"android".equals(pkgName)) {
- outError[0] = "<manifest> specifies bad package name \""
- + pkgName + "\": " + nameError;
- return null;
- }
-
- return pkgName.intern();
- }
-
- /**
- * Temporary.
- */
- static public Signature stringToSignature(String str) {
- final int N = str.length();
- byte[] sig = new byte[N];
- for (int i=0; i<N; i++) {
- sig[i] = (byte)str.charAt(i);
- }
- return new Signature(sig);
- }
-
- private Package parsePackage(
- Resources res, XmlResourceParser parser, int flags, String[] outError)
- throws XmlPullParserException, IOException {
- AttributeSet attrs = parser;
-
- String pkgName = parsePackageName(parser, attrs, flags, outError);
- if (pkgName == null) {
- mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
- return null;
- }
- int type;
-
- final Package pkg = new Package(pkgName);
- pkg.mSystem = (flags&PARSE_IS_SYSTEM) != 0;
- boolean foundApp = false;
-
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifest);
- pkg.mVersionCode = sa.getInteger(
- com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
- pkg.mVersionName = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifest_versionName);
- if (pkg.mVersionName != null) {
- pkg.mVersionName = pkg.mVersionName.intern();
- }
- String str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifest_sharedUserId);
- if (str != null) {
- String nameError = validateName(str, true);
- if (nameError != null && !"android".equals(pkgName)) {
- outError[0] = "<manifest> specifies bad sharedUserId name \""
- + str + "\": " + nameError;
- mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
- return null;
- }
- pkg.mSharedUserId = str.intern();
- pkg.mSharedUserLabel = sa.getResourceId(
- com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
- }
- sa.recycle();
-
- final int innerDepth = parser.getDepth();
-
- int outerDepth = parser.getDepth();
- while ((type=parser.next()) != parser.END_DOCUMENT
- && (type != parser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == parser.END_TAG || type == parser.TEXT) {
- continue;
- }
-
- String tagName = parser.getName();
- if (tagName.equals("application")) {
- if (foundApp) {
- if (RIGID_PARSER) {
- outError[0] = "<manifest> has more than one <application>";
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return null;
- } else {
- Log.w(TAG, "<manifest> has more than one <application>");
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
- }
-
- foundApp = true;
- if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
- return null;
- }
- } else if (tagName.equals("permission-group")) {
- if (parsePermissionGroup(pkg, res, parser, attrs, outError) == null) {
- return null;
- }
- } else if (tagName.equals("permission")) {
- if (parsePermission(pkg, res, parser, attrs, outError) == null) {
- return null;
- }
- } else if (tagName.equals("permission-tree")) {
- if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
- return null;
- }
- } else if (tagName.equals("uses-permission")) {
- sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestUsesPermission);
-
- String name = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
-
- sa.recycle();
-
- if (name != null && !pkg.requestedPermissions.contains(name)) {
- pkg.requestedPermissions.add(name);
- }
-
- XmlUtils.skipCurrentTag(parser);
-
- } else if (tagName.equals("uses-configuration")) {
- ConfigurationInfo cPref = new ConfigurationInfo();
- sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
- cPref.reqTouchScreen = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
- Configuration.TOUCHSCREEN_UNDEFINED);
- cPref.reqKeyboardType = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
- Configuration.KEYBOARD_UNDEFINED);
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
- false)) {
- cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
- }
- cPref.reqNavigation = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
- Configuration.NAVIGATION_UNDEFINED);
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
- false)) {
- cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
- }
- sa.recycle();
- pkg.configPreferences.add(cPref);
-
- XmlUtils.skipCurrentTag(parser);
-
- } else if (tagName.equals("uses-sdk")) {
- if (mSdkVersion > 0) {
- sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestUsesSdk);
-
- int vers = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion, 0);
-
- sa.recycle();
-
- if (vers > mSdkVersion) {
- outError[0] = "Requires newer sdk version #" + vers
- + " (current version is #" + mSdkVersion + ")";
- mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
- return null;
- }
- }
-
- XmlUtils.skipCurrentTag(parser);
-
- } else if (tagName.equals("instrumentation")) {
- if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) {
- return null;
- }
- } else if (tagName.equals("eat-comment")) {
- // Just skip this tag
- XmlUtils.skipCurrentTag(parser);
- continue;
- } else if (RIGID_PARSER) {
- outError[0] = "Bad element under <manifest>: "
- + parser.getName();
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return null;
- } else {
- Log.w(TAG, "Bad element under <manifest>: "
- + parser.getName());
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
- }
-
- if (!foundApp && pkg.instrumentation.size() == 0) {
- outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
- }
-
- if (pkg.usesLibraries.size() > 0) {
- pkg.usesLibraryFiles = new String[pkg.usesLibraries.size()];
- pkg.usesLibraries.toArray(pkg.usesLibraryFiles);
- }
-
- return pkg;
- }
-
- private static String buildClassName(String pkg, CharSequence clsSeq,
- String[] outError) {
- if (clsSeq == null || clsSeq.length() <= 0) {
- outError[0] = "Empty class name in package " + pkg;
- return null;
- }
- String cls = clsSeq.toString();
- char c = cls.charAt(0);
- if (c == '.') {
- return (pkg + cls).intern();
- }
- if (cls.indexOf('.') < 0) {
- StringBuilder b = new StringBuilder(pkg);
- b.append('.');
- b.append(cls);
- return b.toString().intern();
- }
- if (c >= 'a' && c <= 'z') {
- return cls.intern();
- }
- outError[0] = "Bad class name " + cls + " in package " + pkg;
- return null;
- }
-
- private static String buildCompoundName(String pkg,
- CharSequence procSeq, String type, String[] outError) {
- String proc = procSeq.toString();
- char c = proc.charAt(0);
- if (pkg != null && c == ':') {
- if (proc.length() < 2) {
- outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
- + ": must be at least two characters";
- return null;
- }
- String subName = proc.substring(1);
- String nameError = validateName(subName, false);
- if (nameError != null) {
- outError[0] = "Invalid " + type + " name " + proc + " in package "
- + pkg + ": " + nameError;
- return null;
- }
- return (pkg + proc).intern();
- }
- String nameError = validateName(proc, true);
- if (nameError != null && !"system".equals(proc)) {
- outError[0] = "Invalid " + type + " name " + proc + " in package "
- + pkg + ": " + nameError;
- return null;
- }
- return proc.intern();
- }
-
- private static String buildProcessName(String pkg, String defProc,
- CharSequence procSeq, int flags, String[] separateProcesses,
- String[] outError) {
- if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
- return defProc != null ? defProc : pkg;
- }
- if (separateProcesses != null) {
- for (int i=separateProcesses.length-1; i>=0; i--) {
- String sp = separateProcesses[i];
- if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
- return pkg;
- }
- }
- }
- if (procSeq == null || procSeq.length() <= 0) {
- return defProc;
- }
- return buildCompoundName(pkg, procSeq, "package", outError);
- }
-
- private static String buildTaskAffinityName(String pkg, String defProc,
- CharSequence procSeq, String[] outError) {
- if (procSeq == null) {
- return defProc;
- }
- if (procSeq.length() <= 0) {
- return null;
- }
- return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
- }
-
- private PermissionGroup parsePermissionGroup(Package owner, Resources res,
- XmlPullParser parser, AttributeSet attrs, String[] outError)
- throws XmlPullParserException, IOException {
- PermissionGroup perm = new PermissionGroup(owner);
-
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestPermissionGroup);
-
- if (!parsePackageItemInfo(owner, perm.info, outError,
- "<permission-group>", sa,
- com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
- com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
- com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon)) {
- sa.recycle();
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return null;
- }
-
- perm.info.descriptionRes = sa.getResourceId(
- com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
- 0);
-
- sa.recycle();
-
- if (!parseAllMetaData(res, parser, attrs, "<permission-group>", perm,
- outError)) {
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return null;
- }
-
- owner.permissionGroups.add(perm);
-
- return perm;
- }
-
- private Permission parsePermission(Package owner, Resources res,
- XmlPullParser parser, AttributeSet attrs, String[] outError)
- throws XmlPullParserException, IOException {
- Permission perm = new Permission(owner);
-
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestPermission);
-
- if (!parsePackageItemInfo(owner, perm.info, outError,
- "<permission>", sa,
- com.android.internal.R.styleable.AndroidManifestPermission_name,
- com.android.internal.R.styleable.AndroidManifestPermission_label,
- com.android.internal.R.styleable.AndroidManifestPermission_icon)) {
- sa.recycle();
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return null;
- }
-
- perm.info.group = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
- if (perm.info.group != null) {
- perm.info.group = perm.info.group.intern();
- }
-
- perm.info.descriptionRes = sa.getResourceId(
- com.android.internal.R.styleable.AndroidManifestPermission_description,
- 0);
-
- perm.info.protectionLevel = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
- PermissionInfo.PROTECTION_NORMAL);
-
- sa.recycle();
-
- if (perm.info.protectionLevel == -1) {
- outError[0] = "<permission> does not specify protectionLevel";
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return null;
- }
-
- if (!parseAllMetaData(res, parser, attrs, "<permission>", perm,
- outError)) {
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return null;
- }
-
- owner.permissions.add(perm);
-
- return perm;
- }
-
- private Permission parsePermissionTree(Package owner, Resources res,
- XmlPullParser parser, AttributeSet attrs, String[] outError)
- throws XmlPullParserException, IOException {
- Permission perm = new Permission(owner);
-
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestPermissionTree);
-
- if (!parsePackageItemInfo(owner, perm.info, outError,
- "<permission-tree>", sa,
- com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
- com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
- com.android.internal.R.styleable.AndroidManifestPermissionTree_icon)) {
- sa.recycle();
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return null;
- }
-
- sa.recycle();
-
- int index = perm.info.name.indexOf('.');
- if (index > 0) {
- index = perm.info.name.indexOf('.', index+1);
- }
- if (index < 0) {
- outError[0] = "<permission-tree> name has less than three segments: "
- + perm.info.name;
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return null;
- }
-
- perm.info.descriptionRes = 0;
- perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
- perm.tree = true;
-
- if (!parseAllMetaData(res, parser, attrs, "<permission-tree>", perm,
- outError)) {
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return null;
- }
-
- owner.permissions.add(perm);
-
- return perm;
- }
-
- private Instrumentation parseInstrumentation(Package owner, Resources res,
- XmlPullParser parser, AttributeSet attrs, String[] outError)
- throws XmlPullParserException, IOException {
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestInstrumentation);
-
- Instrumentation a = new Instrumentation(owner);
-
- if (!parsePackageItemInfo(owner, a.info, outError, "<instrumentation>", sa,
- com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
- com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
- com.android.internal.R.styleable.AndroidManifestInstrumentation_icon)) {
- sa.recycle();
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return null;
- }
-
- a.component = new ComponentName(owner.applicationInfo.packageName,
- a.info.name);
-
- String str;
- str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
- a.info.targetPackage = str != null ? str.intern() : null;
-
- a.info.handleProfiling = sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
- false);
-
- a.info.functionalTest = sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
- false);
-
- sa.recycle();
-
- if (a.info.targetPackage == null) {
- outError[0] = "<instrumentation> does not specify targetPackage";
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return null;
- }
-
- if (!parseAllMetaData(res, parser, attrs, "<instrumentation>", a,
- outError)) {
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return null;
- }
-
- owner.instrumentation.add(a);
-
- return a;
- }
-
- private boolean parseApplication(Package owner, Resources res,
- XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
- throws XmlPullParserException, IOException {
- final ApplicationInfo ai = owner.applicationInfo;
- final String pkgName = owner.applicationInfo.packageName;
-
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestApplication);
-
- String name = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestApplication_name);
- if (name != null) {
- ai.className = buildClassName(pkgName, name, outError);
- if (ai.className == null) {
- sa.recycle();
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return false;
- }
- }
-
- String manageSpaceActivity = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity);
- if (manageSpaceActivity != null) {
- ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
- outError);
- }
-
- TypedValue v = sa.peekValue(
- com.android.internal.R.styleable.AndroidManifestApplication_label);
- if (v != null && (ai.labelRes=v.resourceId) == 0) {
- ai.nonLocalizedLabel = v.coerceToString();
- }
-
- ai.icon = sa.getResourceId(
- com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
- ai.theme = sa.getResourceId(
- com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
- ai.descriptionRes = sa.getResourceId(
- com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
-
- if ((flags&PARSE_IS_SYSTEM) != 0) {
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestApplication_persistent,
- false)) {
- ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
- }
- }
-
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
- false)) {
- ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
- }
-
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
- true)) {
- ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
- }
-
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
- false)) {
- ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
- }
-
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
- true)) {
- ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
- }
-
- String str;
- str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestApplication_permission);
- ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
-
- str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
- ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
- str, outError);
-
- if (outError[0] == null) {
- ai.processName = buildProcessName(ai.packageName, null, sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestApplication_process),
- flags, mSeparateProcesses, outError);
-
- ai.enabled = sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
- }
-
- sa.recycle();
-
- if (outError[0] != null) {
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return false;
- }
-
- final int innerDepth = parser.getDepth();
-
- int type;
- while ((type=parser.next()) != parser.END_DOCUMENT
- && (type != parser.END_TAG || parser.getDepth() > innerDepth)) {
- if (type == parser.END_TAG || type == parser.TEXT) {
- continue;
- }
-
- String tagName = parser.getName();
- if (tagName.equals("activity")) {
- Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false);
- if (a == null) {
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return false;
- }
-
- owner.activities.add(a);
-
- } else if (tagName.equals("receiver")) {
- Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true);
- if (a == null) {
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return false;
- }
-
- owner.receivers.add(a);
-
- } else if (tagName.equals("service")) {
- Service s = parseService(owner, res, parser, attrs, flags, outError);
- if (s == null) {
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return false;
- }
-
- owner.services.add(s);
-
- } else if (tagName.equals("provider")) {
- Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
- if (p == null) {
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return false;
- }
-
- owner.providers.add(p);
-
- } else if (tagName.equals("activity-alias")) {
- Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError, false);
- if (a == null) {
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return false;
- }
-
- owner.activities.add(a);
-
- } else if (parser.getName().equals("meta-data")) {
- // note: application meta-data is stored off to the side, so it can
- // remain null in the primary copy (we like to avoid extra copies because
- // it can be large)
- if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,
- outError)) == null) {
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return false;
- }
-
- } else if (tagName.equals("uses-library")) {
- sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestUsesLibrary);
-
- String lname = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
-
- sa.recycle();
-
- if (lname != null && !owner.usesLibraries.contains(lname)) {
- owner.usesLibraries.add(lname);
- }
-
- XmlUtils.skipCurrentTag(parser);
-
- } else {
- if (!RIGID_PARSER) {
- Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
- Log.w(TAG, "Unknown element under <application>: " + tagName);
- XmlUtils.skipCurrentTag(parser);
- continue;
- } else {
- outError[0] = "Bad element under <application>: " + tagName;
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- return false;
- }
- }
- }
-
- return true;
- }
-
- private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
- String[] outError, String tag, TypedArray sa,
- int nameRes, int labelRes, int iconRes) {
- String name = sa.getNonResourceString(nameRes);
- if (name == null) {
- outError[0] = tag + " does not specify android:name";
- return false;
- }
-
- outInfo.name
- = buildClassName(owner.applicationInfo.packageName, name, outError);
- if (outInfo.name == null) {
- return false;
- }
-
- int iconVal = sa.getResourceId(iconRes, 0);
- if (iconVal != 0) {
- outInfo.icon = iconVal;
- outInfo.nonLocalizedLabel = null;
- }
-
- TypedValue v = sa.peekValue(labelRes);
- if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
- outInfo.nonLocalizedLabel = v.coerceToString();
- }
-
- outInfo.packageName = owner.packageName;
-
- return true;
- }
-
- private boolean parseComponentInfo(Package owner, int flags,
- ComponentInfo outInfo, String[] outError, String tag, TypedArray sa,
- int nameRes, int labelRes, int iconRes, int processRes,
- int enabledRes) {
- if (!parsePackageItemInfo(owner, outInfo, outError, tag, sa,
- nameRes, labelRes, iconRes)) {
- return false;
- }
-
- if (processRes != 0) {
- outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
- owner.applicationInfo.processName, sa.getNonResourceString(processRes),
- flags, mSeparateProcesses, outError);
- }
- outInfo.enabled = sa.getBoolean(enabledRes, true);
-
- return outError[0] == null;
- }
-
- private Activity parseActivity(Package owner, Resources res,
- XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,
- boolean receiver) throws XmlPullParserException, IOException {
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestActivity);
-
- Activity a = new Activity(owner);
-
- if (!parseComponentInfo(owner, flags, a.info, outError,
- receiver ? "<receiver>" : "<activity>", sa,
- com.android.internal.R.styleable.AndroidManifestActivity_name,
- com.android.internal.R.styleable.AndroidManifestActivity_label,
- com.android.internal.R.styleable.AndroidManifestActivity_icon,
- com.android.internal.R.styleable.AndroidManifestActivity_process,
- com.android.internal.R.styleable.AndroidManifestActivity_enabled)) {
- sa.recycle();
- return null;
- }
-
- final boolean setExported = sa.hasValue(
- com.android.internal.R.styleable.AndroidManifestActivity_exported);
- if (setExported) {
- a.info.exported = sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_exported, false);
- }
-
- a.component = new ComponentName(owner.applicationInfo.packageName,
- a.info.name);
-
- a.info.theme = sa.getResourceId(
- com.android.internal.R.styleable.AndroidManifestActivity_theme, 0);
-
- String str;
- str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestActivity_permission);
- if (str == null) {
- a.info.permission = owner.applicationInfo.permission;
- } else {
- a.info.permission = str.length() > 0 ? str.toString().intern() : null;
- }
-
- str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestActivity_taskAffinity);
- a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
- owner.applicationInfo.taskAffinity, str, outError);
-
- a.info.flags = 0;
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_multiprocess,
- false)) {
- a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
- }
-
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_finishOnTaskLaunch,
- false)) {
- a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
- }
-
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_clearTaskOnLaunch,
- false)) {
- a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
- }
-
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_noHistory,
- false)) {
- a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
- }
-
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_alwaysRetainTaskState,
- false)) {
- a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
- }
-
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_stateNotNeeded,
- false)) {
- a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
- }
-
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_excludeFromRecents,
- false)) {
- a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
- }
-
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_allowTaskReparenting,
- (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
- a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
- }
-
- if (!receiver) {
- a.info.launchMode = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestActivity_launchMode,
- ActivityInfo.LAUNCH_MULTIPLE);
- a.info.screenOrientation = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestActivity_screenOrientation,
- ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
- a.info.configChanges = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestActivity_configChanges,
- 0);
- a.info.softInputMode = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestActivity_windowSoftInputMode,
- 0);
- } else {
- a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
- a.info.configChanges = 0;
- }
-
- sa.recycle();
-
- if (outError[0] != null) {
- return null;
- }
-
- int outerDepth = parser.getDepth();
- int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG
- || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
-
- if (parser.getName().equals("intent-filter")) {
- ActivityIntentInfo intent = new ActivityIntentInfo(a);
- if (!parseIntent(res, parser, attrs, flags, intent, outError, !receiver)) {
- return null;
- }
- if (intent.countActions() == 0) {
- Log.w(TAG, "Intent filter for activity " + intent
- + " defines no actions");
- } else {
- a.intents.add(intent);
- }
- } else if (parser.getName().equals("meta-data")) {
- if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
- outError)) == null) {
- return null;
- }
- } else {
- if (!RIGID_PARSER) {
- Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
- if (receiver) {
- Log.w(TAG, "Unknown element under <receiver>: " + parser.getName());
- } else {
- Log.w(TAG, "Unknown element under <activity>: " + parser.getName());
- }
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
- if (receiver) {
- outError[0] = "Bad element under <receiver>: " + parser.getName();
- } else {
- outError[0] = "Bad element under <activity>: " + parser.getName();
- }
- return null;
- }
- }
-
- if (!setExported) {
- a.info.exported = a.intents.size() > 0;
- }
-
- return a;
- }
-
- private Activity parseActivityAlias(Package owner, Resources res,
- XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,
- boolean receiver) throws XmlPullParserException, IOException {
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestActivityAlias);
-
- String targetActivity = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity);
- if (targetActivity == null) {
- outError[0] = "<activity-alias> does not specify android:targetActivity";
- sa.recycle();
- return null;
- }
-
- targetActivity = buildClassName(owner.applicationInfo.packageName,
- targetActivity, outError);
- if (targetActivity == null) {
- sa.recycle();
- return null;
- }
-
- Activity a = new Activity(owner);
- Activity target = null;
-
- final int NA = owner.activities.size();
- for (int i=0; i<NA; i++) {
- Activity t = owner.activities.get(i);
- if (targetActivity.equals(t.info.name)) {
- target = t;
- break;
- }
- }
-
- if (target == null) {
- outError[0] = "<activity-alias> target activity " + targetActivity
- + " not found in manifest";
- sa.recycle();
- return null;
- }
-
- a.info.targetActivity = targetActivity;
-
- a.info.configChanges = target.info.configChanges;
- a.info.flags = target.info.flags;
- a.info.icon = target.info.icon;
- a.info.labelRes = target.info.labelRes;
- a.info.launchMode = target.info.launchMode;
- a.info.nonLocalizedLabel = target.info.nonLocalizedLabel;
- a.info.processName = target.info.processName;
- a.info.screenOrientation = target.info.screenOrientation;
- a.info.taskAffinity = target.info.taskAffinity;
- a.info.theme = target.info.theme;
-
- if (!parseComponentInfo(owner, flags, a.info, outError,
- receiver ? "<receiver>" : "<activity>", sa,
- com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
- com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
- com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
- 0,
- com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled)) {
- sa.recycle();
- return null;
- }
-
- final boolean setExported = sa.hasValue(
- com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
- if (setExported) {
- a.info.exported = sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
- }
-
- a.component = new ComponentName(owner.applicationInfo.packageName,
- a.info.name);
-
- String str;
- str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestActivityAlias_permission);
- if (str != null) {
- a.info.permission = str.length() > 0 ? str.toString().intern() : null;
- }
-
- sa.recycle();
-
- if (outError[0] != null) {
- return null;
- }
-
- int outerDepth = parser.getDepth();
- int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG
- || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
-
- if (parser.getName().equals("intent-filter")) {
- ActivityIntentInfo intent = new ActivityIntentInfo(a);
- if (!parseIntent(res, parser, attrs, flags, intent, outError, true)) {
- return null;
- }
- if (intent.countActions() == 0) {
- Log.w(TAG, "Intent filter for activity alias " + intent
- + " defines no actions");
- } else {
- a.intents.add(intent);
- }
- } else if (parser.getName().equals("meta-data")) {
- if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
- outError)) == null) {
- return null;
- }
- } else {
- if (!RIGID_PARSER) {
- Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
- Log.w(TAG, "Unknown element under <activity-alias>: " + parser.getName());
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
- outError[0] = "Bad element under <activity-alias>: " + parser.getName();
- return null;
- }
- }
-
- if (!setExported) {
- a.info.exported = a.intents.size() > 0;
- }
-
- return a;
- }
-
- private Provider parseProvider(Package owner, Resources res,
- XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
- throws XmlPullParserException, IOException {
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestProvider);
-
- Provider p = new Provider(owner);
-
- if (!parseComponentInfo(owner, flags, p.info, outError, "<provider>", sa,
- com.android.internal.R.styleable.AndroidManifestProvider_name,
- com.android.internal.R.styleable.AndroidManifestProvider_label,
- com.android.internal.R.styleable.AndroidManifestProvider_icon,
- com.android.internal.R.styleable.AndroidManifestProvider_process,
- com.android.internal.R.styleable.AndroidManifestProvider_enabled)) {
- sa.recycle();
- return null;
- }
-
- p.info.exported = sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestProvider_exported, true);
-
- p.component = new ComponentName(owner.applicationInfo.packageName,
- p.info.name);
-
- String cpname = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestProvider_authorities);
-
- p.info.isSyncable = sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestProvider_syncable,
- false);
-
- String permission = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestProvider_permission);
- String str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestProvider_readPermission);
- if (str == null) {
- str = permission;
- }
- if (str == null) {
- p.info.readPermission = owner.applicationInfo.permission;
- } else {
- p.info.readPermission =
- str.length() > 0 ? str.toString().intern() : null;
- }
- str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestProvider_writePermission);
- if (str == null) {
- str = permission;
- }
- if (str == null) {
- p.info.writePermission = owner.applicationInfo.permission;
- } else {
- p.info.writePermission =
- str.length() > 0 ? str.toString().intern() : null;
- }
-
- p.info.grantUriPermissions = sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
- false);
-
- p.info.multiprocess = sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
- false);
-
- p.info.initOrder = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
- 0);
-
- sa.recycle();
-
- if (cpname == null) {
- outError[0] = "<provider> does not incude authorities attribute";
- return null;
- }
- p.info.authority = cpname.intern();
-
- if (!parseProviderTags(res, parser, attrs, p, outError)) {
- return null;
- }
-
- return p;
- }
-
- private boolean parseProviderTags(Resources res,
- XmlPullParser parser, AttributeSet attrs,
- Provider outInfo, String[] outError)
- throws XmlPullParserException, IOException {
- int outerDepth = parser.getDepth();
- int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG
- || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
-
- if (parser.getName().equals("meta-data")) {
- if ((outInfo.metaData=parseMetaData(res, parser, attrs,
- outInfo.metaData, outError)) == null) {
- return false;
- }
- } else if (parser.getName().equals("grant-uri-permission")) {
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
-
- PatternMatcher pa = null;
-
- String str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path);
- if (str != null) {
- pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
- }
-
- str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix);
- if (str != null) {
- pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
- }
-
- str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern);
- if (str != null) {
- pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
- }
-
- sa.recycle();
-
- if (pa != null) {
- if (outInfo.info.uriPermissionPatterns == null) {
- outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
- outInfo.info.uriPermissionPatterns[0] = pa;
- } else {
- final int N = outInfo.info.uriPermissionPatterns.length;
- PatternMatcher[] newp = new PatternMatcher[N+1];
- System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
- newp[N] = pa;
- outInfo.info.uriPermissionPatterns = newp;
- }
- outInfo.info.grantUriPermissions = true;
- }
- XmlUtils.skipCurrentTag(parser);
-
- } else {
- if (!RIGID_PARSER) {
- Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
- Log.w(TAG, "Unknown element under <provider>: "
- + parser.getName());
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
- outError[0] = "Bad element under <provider>: "
- + parser.getName();
- return false;
- }
- }
- return true;
- }
-
- private Service parseService(Package owner, Resources res,
- XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
- throws XmlPullParserException, IOException {
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestService);
-
- Service s = new Service(owner);
-
- if (!parseComponentInfo(owner, flags, s.info, outError, "<service>", sa,
- com.android.internal.R.styleable.AndroidManifestService_name,
- com.android.internal.R.styleable.AndroidManifestService_label,
- com.android.internal.R.styleable.AndroidManifestService_icon,
- com.android.internal.R.styleable.AndroidManifestService_process,
- com.android.internal.R.styleable.AndroidManifestService_enabled)) {
- sa.recycle();
- return null;
- }
-
- final boolean setExported = sa.hasValue(
- com.android.internal.R.styleable.AndroidManifestService_exported);
- if (setExported) {
- s.info.exported = sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestService_exported, false);
- }
-
- s.component = new ComponentName(owner.applicationInfo.packageName,
- s.info.name);
-
- String str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestService_permission);
- if (str == null) {
- s.info.permission = owner.applicationInfo.permission;
- } else {
- s.info.permission = str.length() > 0 ? str.toString().intern() : null;
- }
-
- sa.recycle();
-
- int outerDepth = parser.getDepth();
- int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG
- || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
-
- if (parser.getName().equals("intent-filter")) {
- ServiceIntentInfo intent = new ServiceIntentInfo(s);
- if (!parseIntent(res, parser, attrs, flags, intent, outError, false)) {
- return null;
- }
-
- s.intents.add(intent);
- } else if (parser.getName().equals("meta-data")) {
- if ((s.metaData=parseMetaData(res, parser, attrs, s.metaData,
- outError)) == null) {
- return null;
- }
- } else {
- if (!RIGID_PARSER) {
- Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
- Log.w(TAG, "Unknown element under <service>: "
- + parser.getName());
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
- outError[0] = "Bad element under <service>: "
- + parser.getName();
- return null;
- }
- }
-
- if (!setExported) {
- s.info.exported = s.intents.size() > 0;
- }
-
- return s;
- }
-
- private boolean parseAllMetaData(Resources res,
- XmlPullParser parser, AttributeSet attrs, String tag,
- Component outInfo, String[] outError)
- throws XmlPullParserException, IOException {
- int outerDepth = parser.getDepth();
- int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG
- || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
-
- if (parser.getName().equals("meta-data")) {
- if ((outInfo.metaData=parseMetaData(res, parser, attrs,
- outInfo.metaData, outError)) == null) {
- return false;
- }
- } else {
- if (!RIGID_PARSER) {
- Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
- Log.w(TAG, "Unknown element under " + tag + ": "
- + parser.getName());
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
- outError[0] = "Bad element under " + tag + ": "
- + parser.getName();
- return false;
- }
- }
- return true;
- }
-
- private Bundle parseMetaData(Resources res,
- XmlPullParser parser, AttributeSet attrs,
- Bundle data, String[] outError)
- throws XmlPullParserException, IOException {
-
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestMetaData);
-
- if (data == null) {
- data = new Bundle();
- }
-
- String name = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestMetaData_name);
- if (name == null) {
- outError[0] = "<meta-data> requires an android:name attribute";
- sa.recycle();
- return null;
- }
-
- boolean success = true;
-
- TypedValue v = sa.peekValue(
- com.android.internal.R.styleable.AndroidManifestMetaData_resource);
- if (v != null && v.resourceId != 0) {
- //Log.i(TAG, "Meta data ref " + name + ": " + v);
- data.putInt(name, v.resourceId);
- } else {
- v = sa.peekValue(
- com.android.internal.R.styleable.AndroidManifestMetaData_value);
- //Log.i(TAG, "Meta data " + name + ": " + v);
- if (v != null) {
- if (v.type == TypedValue.TYPE_STRING) {
- CharSequence cs = v.coerceToString();
- data.putString(name, cs != null ? cs.toString() : null);
- } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
- data.putBoolean(name, v.data != 0);
- } else if (v.type >= TypedValue.TYPE_FIRST_INT
- && v.type <= TypedValue.TYPE_LAST_INT) {
- data.putInt(name, v.data);
- } else if (v.type == TypedValue.TYPE_FLOAT) {
- data.putFloat(name, v.getFloat());
- } else {
- if (!RIGID_PARSER) {
- Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
- Log.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types");
- } else {
- outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
- data = null;
- }
- }
- } else {
- outError[0] = "<meta-data> requires an android:value or android:resource attribute";
- data = null;
- }
- }
-
- sa.recycle();
-
- XmlUtils.skipCurrentTag(parser);
-
- return data;
- }
-
- private static final String ANDROID_RESOURCES
- = "http://schemas.android.com/apk/res/android";
-
- private boolean parseIntent(Resources res,
- XmlPullParser parser, AttributeSet attrs, int flags,
- IntentInfo outInfo, String[] outError, boolean isActivity)
- throws XmlPullParserException, IOException {
-
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestIntentFilter);
-
- int priority = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
- if (priority > 0 && isActivity && (flags&PARSE_IS_SYSTEM) == 0) {
- Log.w(TAG, "Activity with priority > 0, forcing to 0 at "
- + parser.getPositionDescription());
- priority = 0;
- }
- outInfo.setPriority(priority);
-
- TypedValue v = sa.peekValue(
- com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
- if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
- outInfo.nonLocalizedLabel = v.coerceToString();
- }
-
- outInfo.icon = sa.getResourceId(
- com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
-
- sa.recycle();
-
- int outerDepth = parser.getDepth();
- int type;
- while ((type=parser.next()) != parser.END_DOCUMENT
- && (type != parser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == parser.END_TAG || type == parser.TEXT) {
- continue;
- }
-
- String nodeName = parser.getName();
- if (nodeName.equals("action")) {
- String value = attrs.getAttributeValue(
- ANDROID_RESOURCES, "name");
- if (value == null || value == "") {
- outError[0] = "No value supplied for <android:name>";
- return false;
- }
- XmlUtils.skipCurrentTag(parser);
-
- outInfo.addAction(value);
- } else if (nodeName.equals("category")) {
- String value = attrs.getAttributeValue(
- ANDROID_RESOURCES, "name");
- if (value == null || value == "") {
- outError[0] = "No value supplied for <android:name>";
- return false;
- }
- XmlUtils.skipCurrentTag(parser);
-
- outInfo.addCategory(value);
-
- } else if (nodeName.equals("data")) {
- sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestData);
-
- String str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestData_mimeType);
- if (str != null) {
- try {
- outInfo.addDataType(str);
- } catch (IntentFilter.MalformedMimeTypeException e) {
- outError[0] = e.toString();
- sa.recycle();
- return false;
- }
- }
-
- str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestData_scheme);
- if (str != null) {
- outInfo.addDataScheme(str);
- }
-
- String host = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestData_host);
- String port = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestData_port);
- if (host != null) {
- outInfo.addDataAuthority(host, port);
- }
-
- str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestData_path);
- if (str != null) {
- outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
- }
-
- str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestData_pathPrefix);
- if (str != null) {
- outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
- }
-
- str = sa.getNonResourceString(
- com.android.internal.R.styleable.AndroidManifestData_pathPattern);
- if (str != null) {
- outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
- }
-
- sa.recycle();
- XmlUtils.skipCurrentTag(parser);
- } else if (!RIGID_PARSER) {
- Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
- Log.w(TAG, "Unknown element under <intent-filter>: " + parser.getName());
- XmlUtils.skipCurrentTag(parser);
- } else {
- outError[0] = "Bad element under <intent-filter>: " + parser.getName();
- return false;
- }
- }
-
- outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
- if (false) {
- String cats = "";
- Iterator<String> it = outInfo.categoriesIterator();
- while (it != null && it.hasNext()) {
- cats += " " + it.next();
- }
- System.out.println("Intent d=" +
- outInfo.hasDefault + ", cat=" + cats);
- }
-
- return true;
- }
-
- public final static class Package {
- public final String packageName;
-
- // For now we only support one application per package.
- public final ApplicationInfo applicationInfo = new ApplicationInfo();
-
- public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
- public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
- public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
- public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
- public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
- public final ArrayList<Service> services = new ArrayList<Service>(0);
- public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
-
- public final ArrayList<String> requestedPermissions = new ArrayList<String>();
-
- public final ArrayList<String> usesLibraries = new ArrayList<String>();
- public String[] usesLibraryFiles = null;
-
- // We store the application meta-data independently to avoid multiple unwanted references
- public Bundle mAppMetaData = null;
-
- // If this is a 3rd party app, this is the path of the zip file.
- public String mPath;
-
- // True if this package is part of the system image.
- public boolean mSystem;
-
- // The version code declared for this package.
- public int mVersionCode;
-
- // The version name declared for this package.
- public String mVersionName;
-
- // The shared user id that this package wants to use.
- public String mSharedUserId;
-
- // The shared user label that this package wants to use.
- public int mSharedUserLabel;
-
- // Signatures that were read from the package.
- public Signature mSignatures[];
-
- // For use by package manager service for quick lookup of
- // preferred up order.
- public int mPreferredOrder = 0;
-
- // Additional data supplied by callers.
- public Object mExtras;
-
- /*
- * Applications hardware preferences
- */
- public final ArrayList<ConfigurationInfo> configPreferences =
- new ArrayList<ConfigurationInfo>();
-
- public Package(String _name) {
- packageName = _name;
- applicationInfo.packageName = _name;
- applicationInfo.uid = -1;
- }
-
- public String toString() {
- return "Package{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + packageName + "}";
- }
- }
-
- public static class Component<II extends IntentInfo> {
- public final Package owner;
- public final ArrayList<II> intents = new ArrayList<II>(0);
- public ComponentName component;
- public Bundle metaData;
-
- public Component(Package _owner) {
- owner = _owner;
- }
-
- public Component(Component<II> clone) {
- owner = clone.owner;
- metaData = clone.metaData;
- }
- }
-
- public final static class Permission extends Component<IntentInfo> {
- public final PermissionInfo info;
- public boolean tree;
- public PermissionGroup group;
-
- public Permission(Package _owner) {
- super(_owner);
- info = new PermissionInfo();
- }
-
- public Permission(Package _owner, PermissionInfo _info) {
- super(_owner);
- info = _info;
- }
-
- public String toString() {
- return "Permission{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + info.name + "}";
- }
- }
-
- public final static class PermissionGroup extends Component<IntentInfo> {
- public final PermissionGroupInfo info;
-
- public PermissionGroup(Package _owner) {
- super(_owner);
- info = new PermissionGroupInfo();
- }
-
- public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
- super(_owner);
- info = _info;
- }
-
- public String toString() {
- return "PermissionGroup{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + info.name + "}";
- }
- }
-
- private static boolean copyNeeded(int flags, Package p, Bundle metaData) {
- if ((flags & PackageManager.GET_META_DATA) != 0
- && (metaData != null || p.mAppMetaData != null)) {
- return true;
- }
- if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
- && p.usesLibraryFiles != null) {
- return true;
- }
- return false;
- }
-
- public static ApplicationInfo generateApplicationInfo(Package p, int flags) {
- if (p == null) return null;
- if (!copyNeeded(flags, p, null)) {
- return p.applicationInfo;
- }
-
- // Make shallow copy so we can store the metadata/libraries safely
- ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
- if ((flags & PackageManager.GET_META_DATA) != 0) {
- ai.metaData = p.mAppMetaData;
- }
- if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
- ai.sharedLibraryFiles = p.usesLibraryFiles;
- }
- return ai;
- }
-
- public static final PermissionInfo generatePermissionInfo(
- Permission p, int flags) {
- if (p == null) return null;
- if ((flags&PackageManager.GET_META_DATA) == 0) {
- return p.info;
- }
- PermissionInfo pi = new PermissionInfo(p.info);
- pi.metaData = p.metaData;
- return pi;
- }
-
- public static final PermissionGroupInfo generatePermissionGroupInfo(
- PermissionGroup pg, int flags) {
- if (pg == null) return null;
- if ((flags&PackageManager.GET_META_DATA) == 0) {
- return pg.info;
- }
- PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
- pgi.metaData = pg.metaData;
- return pgi;
- }
-
- public final static class Activity extends Component<ActivityIntentInfo> {
- public final ActivityInfo info =
- new ActivityInfo();
-
- public Activity(Package _owner) {
- super(_owner);
- info.applicationInfo = owner.applicationInfo;
- }
-
- public String toString() {
- return "Activity{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + component.flattenToString() + "}";
- }
- }
-
- public static final ActivityInfo generateActivityInfo(Activity a,
- int flags) {
- if (a == null) return null;
- if (!copyNeeded(flags, a.owner, a.metaData)) {
- return a.info;
- }
- // Make shallow copies so we can store the metadata safely
- ActivityInfo ai = new ActivityInfo(a.info);
- ai.metaData = a.metaData;
- ai.applicationInfo = generateApplicationInfo(a.owner, flags);
- return ai;
- }
-
- public final static class Service extends Component<ServiceIntentInfo> {
- public final ServiceInfo info =
- new ServiceInfo();
-
- public Service(Package _owner) {
- super(_owner);
- info.applicationInfo = owner.applicationInfo;
- }
-
- public String toString() {
- return "Service{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + component.flattenToString() + "}";
- }
- }
-
- public static final ServiceInfo generateServiceInfo(Service s, int flags) {
- if (s == null) return null;
- if (!copyNeeded(flags, s.owner, s.metaData)) {
- return s.info;
- }
- // Make shallow copies so we can store the metadata safely
- ServiceInfo si = new ServiceInfo(s.info);
- si.metaData = s.metaData;
- si.applicationInfo = generateApplicationInfo(s.owner, flags);
- return si;
- }
-
- public final static class Provider extends Component {
- public final ProviderInfo info;
- public boolean syncable;
-
- public Provider(Package _owner) {
- super(_owner);
- info = new ProviderInfo();
- info.applicationInfo = owner.applicationInfo;
- syncable = false;
- }
-
- public Provider(Provider existingProvider) {
- super(existingProvider);
- this.info = existingProvider.info;
- this.syncable = existingProvider.syncable;
- }
-
- public String toString() {
- return "Provider{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + info.name + "}";
- }
- }
-
- public static final ProviderInfo generateProviderInfo(Provider p,
- int flags) {
- if (p == null) return null;
- if (!copyNeeded(flags, p.owner, p.metaData)
- && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
- || p.info.uriPermissionPatterns == null)) {
- return p.info;
- }
- // Make shallow copies so we can store the metadata safely
- ProviderInfo pi = new ProviderInfo(p.info);
- pi.metaData = p.metaData;
- if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
- pi.uriPermissionPatterns = null;
- }
- pi.applicationInfo = generateApplicationInfo(p.owner, flags);
- return pi;
- }
-
- public final static class Instrumentation extends Component {
- public final InstrumentationInfo info =
- new InstrumentationInfo();
-
- public Instrumentation(Package _owner) {
- super(_owner);
- }
-
- public String toString() {
- return "Instrumentation{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + component.flattenToString() + "}";
- }
- }
-
- public static final InstrumentationInfo generateInstrumentationInfo(
- Instrumentation i, int flags) {
- if (i == null) return null;
- if ((flags&PackageManager.GET_META_DATA) == 0) {
- return i.info;
- }
- InstrumentationInfo ii = new InstrumentationInfo(i.info);
- ii.metaData = i.metaData;
- return ii;
- }
-
- public static class IntentInfo extends IntentFilter {
- public boolean hasDefault;
- public int labelRes;
- public CharSequence nonLocalizedLabel;
- public int icon;
- }
-
- public final static class ActivityIntentInfo extends IntentInfo {
- public final Activity activity;
-
- public ActivityIntentInfo(Activity _activity) {
- activity = _activity;
- }
-
- public String toString() {
- return "ActivityIntentInfo{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + activity.info.name + "}";
- }
- }
-
- public final static class ServiceIntentInfo extends IntentInfo {
- public final Service service;
-
- public ServiceIntentInfo(Service _service) {
- service = _service;
- }
-
- public String toString() {
- return "ServiceIntentInfo{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + service.info.name + "}";
- }
- }
-}
diff --git a/core/java/android/content/pm/PackageStats.aidl b/core/java/android/content/pm/PackageStats.aidl
deleted file mode 100755
index 8c9786f..0000000
--- a/core/java/android/content/pm/PackageStats.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/view/WindowManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-parcelable PackageStats;
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java
deleted file mode 100755
index 66c6efd..0000000
--- a/core/java/android/content/pm/PackageStats.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package android.content.pm;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Arrays;
-
-/**
- * implementation of PackageStats associated with a
- * application package.
- */
-public class PackageStats implements Parcelable {
- public String packageName;
- public long codeSize;
- public long dataSize;
- public long cacheSize;
-
- public static final Parcelable.Creator<PackageStats> CREATOR
- = new Parcelable.Creator<PackageStats>() {
- public PackageStats createFromParcel(Parcel in) {
- return new PackageStats(in);
- }
-
- public PackageStats[] newArray(int size) {
- return new PackageStats[size];
- }
- };
-
- public String toString() {
- return "PackageStats{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + packageName + "}";
- }
-
- public PackageStats(String pkgName) {
- packageName = pkgName;
- }
-
- public PackageStats(Parcel source) {
- packageName = source.readString();
- codeSize = source.readLong();
- dataSize = source.readLong();
- cacheSize = source.readLong();
- }
-
- public PackageStats(PackageStats pStats) {
- packageName = pStats.packageName;
- codeSize = pStats.codeSize;
- dataSize = pStats.dataSize;
- cacheSize = pStats.cacheSize;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags){
- dest.writeString(packageName);
- dest.writeLong(codeSize);
- dest.writeLong(dataSize);
- dest.writeLong(cacheSize);
- }
-}
diff --git a/core/java/android/content/pm/PermissionGroupInfo.aidl b/core/java/android/content/pm/PermissionGroupInfo.aidl
deleted file mode 100755
index 9f215f1..0000000
--- a/core/java/android/content/pm/PermissionGroupInfo.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/view/WindowManager.aidl
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-parcelable PermissionGroupInfo;
diff --git a/core/java/android/content/pm/PermissionGroupInfo.java b/core/java/android/content/pm/PermissionGroupInfo.java
deleted file mode 100644
index 02eb816..0000000
--- a/core/java/android/content/pm/PermissionGroupInfo.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-/**
- * Information you can retrieve about a particular security permission
- * group known to the system. This corresponds to information collected from the
- * AndroidManifest.xml's &lt;permission-group&gt; tags.
- */
-public class PermissionGroupInfo extends PackageItemInfo implements Parcelable {
- /**
- * A string resource identifier (in the package's resources) of this
- * permission's description. From the "description" attribute or,
- * if not set, 0.
- */
- public int descriptionRes;
-
- /**
- * The description string provided in the AndroidManifest file, if any. You
- * probably don't want to use this, since it will be null if the description
- * is in a resource. You probably want
- * {@link PermissionInfo#loadDescription} instead.
- */
- public CharSequence nonLocalizedDescription;
-
- public PermissionGroupInfo() {
- }
-
- public PermissionGroupInfo(PermissionGroupInfo orig) {
- super(orig);
- descriptionRes = orig.descriptionRes;
- nonLocalizedDescription = orig.nonLocalizedDescription;
- }
-
- /**
- * Retrieve the textual description of this permission. This
- * will call back on the given PackageManager to load the description from
- * the application.
- *
- * @param pm A PackageManager from which the label can be loaded; usually
- * the PackageManager from which you originally retrieved this item.
- *
- * @return Returns a CharSequence containing the permission's description.
- * If there is no description, null is returned.
- */
- public CharSequence loadDescription(PackageManager pm) {
- if (nonLocalizedDescription != null) {
- return nonLocalizedDescription;
- }
- if (descriptionRes != 0) {
- CharSequence label = pm.getText(packageName, descriptionRes, null);
- if (label != null) {
- return label;
- }
- }
- return null;
- }
-
- public String toString() {
- return "PermissionGroupInfo{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + name + "}";
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags) {
- super.writeToParcel(dest, parcelableFlags);
- dest.writeInt(descriptionRes);
- TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags);
- }
-
- public static final Creator<PermissionGroupInfo> CREATOR =
- new Creator<PermissionGroupInfo>() {
- public PermissionGroupInfo createFromParcel(Parcel source) {
- return new PermissionGroupInfo(source);
- }
- public PermissionGroupInfo[] newArray(int size) {
- return new PermissionGroupInfo[size];
- }
- };
-
- private PermissionGroupInfo(Parcel source) {
- super(source);
- descriptionRes = source.readInt();
- nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- }
-}
diff --git a/core/java/android/content/pm/PermissionInfo.aidl b/core/java/android/content/pm/PermissionInfo.aidl
deleted file mode 100755
index 5a7d4f4..0000000
--- a/core/java/android/content/pm/PermissionInfo.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/view/WindowManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-parcelable PermissionInfo;
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
deleted file mode 100644
index 3cc884b..0000000
--- a/core/java/android/content/pm/PermissionInfo.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-/**
- * Information you can retrieve about a particular security permission
- * known to the system. This corresponds to information collected from the
- * AndroidManifest.xml's &lt;permission&gt; tags.
- */
-public class PermissionInfo extends PackageItemInfo implements Parcelable {
- /**
- * A normal application value for {@link #protectionLevel}, corresponding
- * to the <code>normal</code> value of
- * {@link android.R.attr#protectionLevel}.
- */
- public static final int PROTECTION_NORMAL = 0;
-
- /**
- * Dangerous value for {@link #protectionLevel}, corresponding
- * to the <code>dangerous</code> value of
- * {@link android.R.attr#protectionLevel}.
- */
- public static final int PROTECTION_DANGEROUS = 1;
-
- /**
- * System-level value for {@link #protectionLevel}, corresponding
- * to the <code>signature</code> value of
- * {@link android.R.attr#protectionLevel}.
- */
- public static final int PROTECTION_SIGNATURE = 2;
-
- /**
- * System-level value for {@link #protectionLevel}, corresponding
- * to the <code>signatureOrSystem</code> value of
- * {@link android.R.attr#protectionLevel}.
- */
- public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3;
-
- /**
- * The group this permission is a part of, as per
- * {@link android.R.attr#permissionGroup}.
- */
- public String group;
-
- /**
- * A string resource identifier (in the package's resources) of this
- * permission's description. From the "description" attribute or,
- * if not set, 0.
- */
- public int descriptionRes;
-
- /**
- * The description string provided in the AndroidManifest file, if any. You
- * probably don't want to use this, since it will be null if the description
- * is in a resource. You probably want
- * {@link PermissionInfo#loadDescription} instead.
- */
- public CharSequence nonLocalizedDescription;
-
- /**
- * The level of access this permission is protecting, as per
- * {@link android.R.attr#protectionLevel}. Values may be
- * {@link #PROTECTION_NORMAL}, {@link #PROTECTION_DANGEROUS}, or
- * {@link #PROTECTION_SIGNATURE}.
- */
- public int protectionLevel;
-
- public PermissionInfo() {
- }
-
- public PermissionInfo(PermissionInfo orig) {
- super(orig);
- group = orig.group;
- descriptionRes = orig.descriptionRes;
- protectionLevel = orig.protectionLevel;
- nonLocalizedDescription = orig.nonLocalizedDescription;
- }
-
- /**
- * Retrieve the textual description of this permission. This
- * will call back on the given PackageManager to load the description from
- * the application.
- *
- * @param pm A PackageManager from which the label can be loaded; usually
- * the PackageManager from which you originally retrieved this item.
- *
- * @return Returns a CharSequence containing the permission's description.
- * If there is no description, null is returned.
- */
- public CharSequence loadDescription(PackageManager pm) {
- if (nonLocalizedDescription != null) {
- return nonLocalizedDescription;
- }
- if (descriptionRes != 0) {
- CharSequence label = pm.getText(packageName, descriptionRes, null);
- if (label != null) {
- return label;
- }
- }
- return null;
- }
-
- public String toString() {
- return "PermissionInfo{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + name + "}";
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags) {
- super.writeToParcel(dest, parcelableFlags);
- dest.writeString(group);
- dest.writeInt(descriptionRes);
- dest.writeInt(protectionLevel);
- TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags);
- }
-
- public static final Creator<PermissionInfo> CREATOR =
- new Creator<PermissionInfo>() {
- public PermissionInfo createFromParcel(Parcel source) {
- return new PermissionInfo(source);
- }
- public PermissionInfo[] newArray(int size) {
- return new PermissionInfo[size];
- }
- };
-
- private PermissionInfo(Parcel source) {
- super(source);
- group = source.readString();
- descriptionRes = source.readInt();
- protectionLevel = source.readInt();
- nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- }
-}
diff --git a/core/java/android/content/pm/ProviderInfo.aidl b/core/java/android/content/pm/ProviderInfo.aidl
deleted file mode 100755
index 18fbc8a..0000000
--- a/core/java/android/content/pm/ProviderInfo.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/view/WindowManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-parcelable ProviderInfo;
diff --git a/core/java/android/content/pm/ProviderInfo.java b/core/java/android/content/pm/ProviderInfo.java
deleted file mode 100644
index b67ddf6..0000000
--- a/core/java/android/content/pm/ProviderInfo.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.PatternMatcher;
-
-/**
- * Holds information about a specific
- * {@link android.content.ContentProvider content provider}. This is returned by
- * {@link android.content.pm.PackageManager#resolveContentProvider(java.lang.String, int)
- * PackageManager.resolveContentProvider()}.
- */
-public final class ProviderInfo extends ComponentInfo
- implements Parcelable {
- /** The name provider is published under content:// */
- public String authority = null;
-
- /** Optional permission required for read-only access this content
- * provider. */
- public String readPermission = null;
-
- /** Optional permission required for read/write access this content
- * provider. */
- public String writePermission = null;
-
- /** If true, additional permissions to specific Uris in this content
- * provider can be granted, as per the
- * {@link android.R.styleable#AndroidManifestProvider_grantUriPermissions
- * grantUriPermissions} attribute.
- */
- public boolean grantUriPermissions = false;
-
- /**
- * If non-null, these are the patterns that are allowed for granting URI
- * permissions. Any URI that does not match one of these patterns will not
- * allowed to be granted. If null, all URIs are allowed. The
- * {@link PackageManager#GET_URI_PERMISSION_PATTERNS
- * PackageManager.GET_URI_PERMISSION_PATTERNS} flag must be specified for
- * this field to be filled in.
- */
- public PatternMatcher[] uriPermissionPatterns = null;
-
- /** If true, this content provider allows multiple instances of itself
- * to run in different process. If false, a single instances is always
- * run in {@link #processName}. */
- public boolean multiprocess = false;
-
- /** Used to control initialization order of single-process providers
- * running in the same process. Higher goes first. */
- public int initOrder = 0;
-
- /** Whether or not this provider is syncable. */
- public boolean isSyncable = false;
-
- public ProviderInfo() {
- }
-
- public ProviderInfo(ProviderInfo orig) {
- super(orig);
- authority = orig.authority;
- readPermission = orig.readPermission;
- writePermission = orig.writePermission;
- grantUriPermissions = orig.grantUriPermissions;
- uriPermissionPatterns = orig.uriPermissionPatterns;
- multiprocess = orig.multiprocess;
- initOrder = orig.initOrder;
- isSyncable = orig.isSyncable;
- }
-
- public int describeContents() {
- return 0;
- }
-
- @Override public void writeToParcel(Parcel out, int parcelableFlags) {
- super.writeToParcel(out, parcelableFlags);
- out.writeString(authority);
- out.writeString(readPermission);
- out.writeString(writePermission);
- out.writeInt(grantUriPermissions ? 1 : 0);
- out.writeTypedArray(uriPermissionPatterns, parcelableFlags);
- out.writeInt(multiprocess ? 1 : 0);
- out.writeInt(initOrder);
- out.writeInt(isSyncable ? 1 : 0);
- }
-
- public static final Parcelable.Creator<ProviderInfo> CREATOR
- = new Parcelable.Creator<ProviderInfo>() {
- public ProviderInfo createFromParcel(Parcel in) {
- return new ProviderInfo(in);
- }
-
- public ProviderInfo[] newArray(int size) {
- return new ProviderInfo[size];
- }
- };
-
- public String toString() {
- return "ContentProviderInfo{name=" + authority + " className=" + name
- + " isSyncable=" + (isSyncable ? "true" : "false") + "}";
- }
-
- private ProviderInfo(Parcel in) {
- super(in);
- authority = in.readString();
- readPermission = in.readString();
- writePermission = in.readString();
- grantUriPermissions = in.readInt() != 0;
- uriPermissionPatterns = in.createTypedArray(PatternMatcher.CREATOR);
- multiprocess = in.readInt() != 0;
- initOrder = in.readInt();
- isSyncable = in.readInt() != 0;
- }
-}
diff --git a/core/java/android/content/pm/ResolveInfo.aidl b/core/java/android/content/pm/ResolveInfo.aidl
deleted file mode 100755
index b4e7f8b..0000000
--- a/core/java/android/content/pm/ResolveInfo.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/view/WindowManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-parcelable ResolveInfo;
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
deleted file mode 100644
index ee49c02..0000000
--- a/core/java/android/content/pm/ResolveInfo.java
+++ /dev/null
@@ -1,280 +0,0 @@
-package android.content.pm;
-
-import android.content.IntentFilter;
-import android.graphics.drawable.Drawable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Printer;
-
-import java.text.Collator;
-import java.util.Comparator;
-
-/**
- * Information that is returned from resolving an intent
- * against an IntentFilter. This partially corresponds to
- * information collected from the AndroidManifest.xml's
- * &lt;intent&gt; tags.
- */
-public class ResolveInfo implements Parcelable {
- /**
- * The activity that corresponds to this resolution match, if this
- * resolution is for an activity. One and only one of this and
- * serviceInfo must be non-null.
- */
- public ActivityInfo activityInfo;
-
- /**
- * The service that corresponds to this resolution match, if this
- * resolution is for a service. One and only one of this and
- * activityInfo must be non-null.
- */
- public ServiceInfo serviceInfo;
-
- /**
- * The IntentFilter that was matched for this ResolveInfo.
- */
- public IntentFilter filter;
-
- /**
- * The declared priority of this match. Comes from the "priority"
- * attribute or, if not set, defaults to 0. Higher values are a higher
- * priority.
- */
- public int priority;
-
- /**
- * Order of result according to the user's preference. If the user
- * has not set a preference for this result, the value is 0; higher
- * values are a higher priority.
- */
- public int preferredOrder;
-
- /**
- * The system's evaluation of how well the activity matches the
- * IntentFilter. This is a match constant, a combination of
- * {@link IntentFilter#MATCH_CATEGORY_MASK IntentFilter.MATCH_CATEGORY_MASK}
- * and {@link IntentFilter#MATCH_ADJUSTMENT_MASK IntentFiler.MATCH_ADJUSTMENT_MASK}.
- */
- public int match;
-
- /**
- * Only set when returned by
- * {@link PackageManager#queryIntentActivityOptions}, this tells you
- * which of the given specific intents this result came from. 0 is the
- * first in the list, < 0 means it came from the generic Intent query.
- */
- public int specificIndex = -1;
-
- /**
- * This filter has specified the Intent.CATEGORY_DEFAULT, meaning it
- * would like to be considered a default action that the user can
- * perform on this data.
- */
- public boolean isDefault;
-
- /**
- * A string resource identifier (in the package's resources) of this
- * match's label. From the "label" attribute or, if not set, 0.
- */
- public int labelRes;
-
- /**
- * The actual string retrieve from <var>labelRes</var> or null if none
- * was provided.
- */
- public CharSequence nonLocalizedLabel;
-
- /**
- * A drawable resource identifier (in the package's resources) of this
- * match's icon. From the "icon" attribute or, if not set, 0.
- */
- public int icon;
-
- /**
- * Retrieve the current textual label associated with this resolution. This
- * will call back on the given PackageManager to load the label from
- * the application.
- *
- * @param pm A PackageManager from which the label can be loaded; usually
- * the PackageManager from which you originally retrieved this item.
- *
- * @return Returns a CharSequence containing the resolutions's label. If the
- * item does not have a label, its name is returned.
- */
- public CharSequence loadLabel(PackageManager pm) {
- if (nonLocalizedLabel != null) {
- return nonLocalizedLabel;
- }
- ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo;
- ApplicationInfo ai = ci.applicationInfo;
- CharSequence label;
- if (labelRes != 0) {
- label = pm.getText(ci.packageName, labelRes, ai);
- if (label != null) {
- return label;
- }
- }
- return ci.loadLabel(pm);
- }
-
- /**
- * Retrieve the current graphical icon associated with this resolution. This
- * will call back on the given PackageManager to load the icon from
- * the application.
- *
- * @param pm A PackageManager from which the icon can be loaded; usually
- * the PackageManager from which you originally retrieved this item.
- *
- * @return Returns a Drawable containing the resolution's icon. If the
- * item does not have an icon, the default activity icon is returned.
- */
- public Drawable loadIcon(PackageManager pm) {
- ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo;
- ApplicationInfo ai = ci.applicationInfo;
- Drawable dr;
- if (icon != 0) {
- dr = pm.getDrawable(ci.packageName, icon, ai);
- if (dr != null) {
- return dr;
- }
- }
- return ci.loadIcon(pm);
- }
-
- /**
- * Return the icon resource identifier to use for this match. If the
- * match defines an icon, that is used; else if the activity defines
- * an icon, that is used; else, the application icon is used.
- *
- * @return The icon associated with this match.
- */
- public final int getIconResource() {
- if (icon != 0) return icon;
- if (activityInfo != null) return activityInfo.getIconResource();
- if (serviceInfo != null) return serviceInfo.getIconResource();
- return 0;
- }
-
- public void dump(Printer pw, String prefix) {
- if (filter != null) {
- pw.println(prefix + "Filter:");
- filter.dump(pw, prefix + " ");
- } else {
- pw.println(prefix + "Filter: null");
- }
- pw.println(prefix + "priority=" + priority
- + " preferredOrder=" + preferredOrder
- + " match=0x" + Integer.toHexString(match)
- + " specificIndex=" + specificIndex
- + " isDefault=" + isDefault);
- pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
- + " nonLocalizedLabel=" + nonLocalizedLabel
- + " icon=0x" + Integer.toHexString(icon));
- if (activityInfo != null) {
- pw.println(prefix + "ActivityInfo:");
- activityInfo.dump(pw, prefix + " ");
- } else if (serviceInfo != null) {
- pw.println(prefix + "ServiceInfo:");
- // TODO
- //serviceInfo.dump(pw, prefix + " ");
- }
- }
-
- public ResolveInfo() {
- }
-
- public String toString() {
- ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo;
- return "ResolveInfo{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + ci.name + " p=" + priority + " o="
- + preferredOrder + " m=0x" + Integer.toHexString(match) + "}";
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags) {
- if (activityInfo != null) {
- dest.writeInt(1);
- activityInfo.writeToParcel(dest, parcelableFlags);
- } else if (serviceInfo != null) {
- dest.writeInt(2);
- serviceInfo.writeToParcel(dest, parcelableFlags);
- } else {
- dest.writeInt(0);
- }
- if (filter != null) {
- dest.writeInt(1);
- filter.writeToParcel(dest, parcelableFlags);
- } else {
- dest.writeInt(0);
- }
- dest.writeInt(priority);
- dest.writeInt(preferredOrder);
- dest.writeInt(match);
- dest.writeInt(specificIndex);
- dest.writeInt(labelRes);
- TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags);
- dest.writeInt(icon);
- }
-
- public static final Creator<ResolveInfo> CREATOR
- = new Creator<ResolveInfo>() {
- public ResolveInfo createFromParcel(Parcel source) {
- return new ResolveInfo(source);
- }
- public ResolveInfo[] newArray(int size) {
- return new ResolveInfo[size];
- }
- };
-
- private ResolveInfo(Parcel source) {
- switch (source.readInt()) {
- case 1:
- activityInfo = ActivityInfo.CREATOR.createFromParcel(source);
- serviceInfo = null;
- break;
- case 2:
- serviceInfo = ServiceInfo.CREATOR.createFromParcel(source);
- activityInfo = null;
- break;
- default:
- activityInfo = null;
- serviceInfo = null;
- break;
- }
- if (source.readInt() != 0) {
- filter = IntentFilter.CREATOR.createFromParcel(source);
- }
- priority = source.readInt();
- preferredOrder = source.readInt();
- match = source.readInt();
- specificIndex = source.readInt();
- labelRes = source.readInt();
- nonLocalizedLabel
- = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- icon = source.readInt();
- }
-
- public static class DisplayNameComparator
- implements Comparator<ResolveInfo> {
- public DisplayNameComparator(PackageManager pm) {
- mPM = pm;
- }
-
- public final int compare(ResolveInfo a, ResolveInfo b) {
- CharSequence sa = a.loadLabel(mPM);
- if (sa == null) sa = a.activityInfo.name;
- CharSequence sb = b.loadLabel(mPM);
- if (sb == null) sb = b.activityInfo.name;
-
- return sCollator.compare(sa.toString(), sb.toString());
- }
-
- private final Collator sCollator = Collator.getInstance();
- private PackageManager mPM;
- }
-}
diff --git a/core/java/android/content/pm/ServiceInfo.aidl b/core/java/android/content/pm/ServiceInfo.aidl
deleted file mode 100755
index 5ddae1a..0000000
--- a/core/java/android/content/pm/ServiceInfo.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/view/WindowManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-parcelable ServiceInfo;
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
deleted file mode 100644
index b60650c..0000000
--- a/core/java/android/content/pm/ServiceInfo.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package android.content.pm;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Information you can retrieve about a particular application
- * service. This corresponds to information collected from the
- * AndroidManifest.xml's &lt;service&gt; tags.
- */
-public class ServiceInfo extends ComponentInfo
- implements Parcelable {
- /**
- * Optional name of a permission required to be able to access this
- * Service. From the "permission" attribute.
- */
- public String permission;
-
- public ServiceInfo() {
- }
-
- public ServiceInfo(ServiceInfo orig) {
- super(orig);
- permission = orig.permission;
- }
-
- public String toString() {
- return "ServiceInfo{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + name + "}";
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags) {
- super.writeToParcel(dest, parcelableFlags);
- dest.writeString(permission);
- }
-
- public static final Creator<ServiceInfo> CREATOR =
- new Creator<ServiceInfo>() {
- public ServiceInfo createFromParcel(Parcel source) {
- return new ServiceInfo(source);
- }
- public ServiceInfo[] newArray(int size) {
- return new ServiceInfo[size];
- }
- };
-
- private ServiceInfo(Parcel source) {
- super(source);
- permission = source.readString();
- }
-}
diff --git a/core/java/android/content/pm/Signature.aidl b/core/java/android/content/pm/Signature.aidl
deleted file mode 100755
index 3a0d775..0000000
--- a/core/java/android/content/pm/Signature.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/view/WindowManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm;
-
-parcelable Signature;
diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java
deleted file mode 100644
index 1bb3857..0000000
--- a/core/java/android/content/pm/Signature.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-import android.content.ComponentName;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Arrays;
-
-/**
- * Opaque, immutable representation of a signature associated with an
- * application package.
- */
-public class Signature implements Parcelable {
- private final byte[] mSignature;
- private int mHashCode;
- private boolean mHaveHashCode;
- private String mString;
-
- /**
- * Create Signature from an existing raw byte array.
- */
- public Signature(byte[] signature) {
- mSignature = signature.clone();
- }
-
- /**
- * Create Signature from a text representation previously returned by
- * {@link #toChars} or {@link #toCharsString()}.
- */
- public Signature(String text) {
- final int N = text.length()/2;
- byte[] sig = new byte[N];
- for (int i=0; i<N; i++) {
- char c = text.charAt(i*2);
- byte b = (byte)(
- (c >= 'a' ? (c - 'a' + 10) : (c - '0'))<<4);
- c = text.charAt(i*2 + 1);
- b |= (byte)(c >= 'a' ? (c - 'a' + 10) : (c - '0'));
- sig[i] = b;
- }
- mSignature = sig;
- }
-
- /**
- * Encode the Signature as ASCII text.
- */
- public char[] toChars() {
- return toChars(null, null);
- }
-
- /**
- * Encode the Signature as ASCII text in to an existing array.
- *
- * @param existingArray Existing char array or null.
- * @param outLen Output parameter for the number of characters written in
- * to the array.
- * @return Returns either <var>existingArray</var> if it was large enough
- * to hold the ASCII representation, or a newly created char[] array if
- * needed.
- */
- public char[] toChars(char[] existingArray, int[] outLen) {
- byte[] sig = mSignature;
- final int N = sig.length;
- final int N2 = N*2;
- char[] text = existingArray == null || N2 > existingArray.length
- ? new char[N2] : existingArray;
- for (int j=0; j<N; j++) {
- byte v = sig[j];
- int d = (v>>4)&0xf;
- text[j*2] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d));
- d = v&0xf;
- text[j*2+1] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d));
- }
- if (outLen != null) outLen[0] = N;
- return text;
- }
-
- /**
- * Return the result of {@link #toChars()} as a String. This result is
- * cached so future calls will return the same String.
- */
- public String toCharsString() {
- if (mString != null) return mString;
- String str = new String(toChars());
- mString = str;
- return mString;
- }
-
- /**
- * @return the contents of this signature as a byte array.
- */
- public byte[] toByteArray() {
- byte[] bytes = new byte[mSignature.length];
- System.arraycopy(mSignature, 0, bytes, 0, mSignature.length);
- return bytes;
- }
-
- @Override
- public boolean equals(Object obj) {
- try {
- if (obj != null) {
- Signature other = (Signature)obj;
- return Arrays.equals(mSignature, other.mSignature);
- }
- } catch (ClassCastException e) {
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- if (mHaveHashCode) {
- return mHashCode;
- }
- mHashCode = Arrays.hashCode(mSignature);
- mHaveHashCode = true;
- return mHashCode;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags) {
- dest.writeByteArray(mSignature);
- }
-
- public static final Parcelable.Creator<Signature> CREATOR
- = new Parcelable.Creator<Signature>() {
- public Signature createFromParcel(Parcel source) {
- return new Signature(source);
- }
-
- public Signature[] newArray(int size) {
- return new Signature[size];
- }
- };
-
- private Signature(Parcel source) {
- mSignature = source.createByteArray();
- }
-}
diff --git a/core/java/android/content/pm/package.html b/core/java/android/content/pm/package.html
deleted file mode 100644
index 766b7dd..0000000
--- a/core/java/android/content/pm/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<HTML>
-<BODY>
-Contains classes for accessing information about an
-application package, including information about its activities,
-permissions, services, signatures, and providers.
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/core/java/android/content/res/AssetFileDescriptor.java b/core/java/android/content/res/AssetFileDescriptor.java
deleted file mode 100644
index 4a073f7..0000000
--- a/core/java/android/content/res/AssetFileDescriptor.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res;
-
-import android.os.ParcelFileDescriptor;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-
-/**
- * File descriptor of an entry in the AssetManager. This provides your own
- * opened FileDescriptor that can be used to read the data, as well as the
- * offset and length of that entry's data in the file.
- */
-public class AssetFileDescriptor {
- private final ParcelFileDescriptor mFd;
- private final long mStartOffset;
- private final long mLength;
-
- /**
- * Create a new AssetFileDescriptor from the given values.
- */
- public AssetFileDescriptor(ParcelFileDescriptor fd, long startOffset,
- long length) {
- mFd = fd;
- mStartOffset = startOffset;
- mLength = length;
- }
-
- /**
- * The AssetFileDescriptor contains its own ParcelFileDescriptor, which
- * in addition to the normal FileDescriptor object also allows you to close
- * the descriptor when you are done with it.
- */
- public ParcelFileDescriptor getParcelFileDescriptor() {
- return mFd;
- }
-
- /**
- * Returns the FileDescriptor that can be used to read the data in the
- * file.
- */
- public FileDescriptor getFileDescriptor() {
- return mFd.getFileDescriptor();
- }
-
- /**
- * Returns the byte offset where this asset entry's data starts.
- */
- public long getStartOffset() {
- return mStartOffset;
- }
-
- /**
- * Returns the total number of bytes of this asset entry's data.
- */
- public long getLength() {
- return mLength;
- }
-
- /**
- * Convenience for calling <code>getParcelFileDescriptor().close()</code>.
- */
- public void close() throws IOException {
- mFd.close();
- }
-}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
deleted file mode 100644
index fadcb35..0000000
--- a/core/java/android/content/res/AssetManager.java
+++ /dev/null
@@ -1,697 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res;
-
-import android.os.ParcelFileDescriptor;
-import android.util.Config;
-import android.util.Log;
-import android.util.TypedValue;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Locale;
-
-/**
- * Provides access to an application's raw asset files; see {@link Resources}
- * for the way most applications will want to retrieve their resource data.
- * This class presents a lower-level API that allows you to open and read raw
- * files that have been bundled with the application as a simple stream of
- * bytes.
- */
-public final class AssetManager {
- /* modes used when opening an asset */
-
- /**
- * Mode for {@link #open(String, int)}: no specific information about how
- * data will be accessed.
- */
- public static final int ACCESS_UNKNOWN = 0;
- /**
- * Mode for {@link #open(String, int)}: Read chunks, and seek forward and
- * backward.
- */
- public static final int ACCESS_RANDOM = 1;
- /**
- * Mode for {@link #open(String, int)}: Read sequentially, with an
- * occasional forward seek.
- */
- public static final int ACCESS_STREAMING = 2;
- /**
- * Mode for {@link #open(String, int)}: Attempt to load contents into
- * memory, for fast small reads.
- */
- public static final int ACCESS_BUFFER = 3;
-
- private static final String TAG = "AssetManager";
- private static final boolean localLOGV = Config.LOGV || false;
-
- private static final Object mSync = new Object();
- private static final TypedValue mValue = new TypedValue();
- private static final long[] mOffsets = new long[2];
- private static AssetManager mSystem = null;
-
- // For communication with native code.
- private int mObject;
-
- private StringBlock mStringBlocks[] = null;
-
- private int mNumRefs = 1;
- private boolean mOpen = true;
- private String mAssetDir;
- private String mAppName;
-
- /**
- * Create a new AssetManager containing only the basic system assets.
- * Applications will not generally use this method, instead retrieving the
- * appropriate asset manager with {@link Resources#getAssets}. Not for
- * use by applications.
- * {@hide}
- */
- public AssetManager() {
- synchronized (mSync) {
- init();
- if (localLOGV) Log.v(TAG, "New asset manager: " + this);
- ensureSystemAssets();
- }
- }
-
- private static void ensureSystemAssets() {
- synchronized (mSync) {
- if (mSystem == null) {
- AssetManager system = new AssetManager(true);
- system.makeStringBlocks(false);
- mSystem = system;
- }
- }
- }
-
- private AssetManager(boolean isSystem) {
- init();
- if (localLOGV) Log.v(TAG, "New asset manager: " + this);
- }
-
- /**
- * Return a global shared asset manager that provides access to only
- * system assets (no application assets).
- * {@hide}
- */
- public static AssetManager getSystem() {
- ensureSystemAssets();
- return mSystem;
- }
-
- /**
- * Close this asset manager.
- */
- public void close() {
- synchronized(mSync) {
- //System.out.println("Release: num=" + mNumRefs
- // + ", released=" + mReleased);
- if (mOpen) {
- mOpen = false;
- decRefsLocked();
- }
- }
- }
-
- /**
- * Retrieve the string value associated with a particular resource
- * identifier for the current configuration / skin.
- */
- /*package*/ final CharSequence getResourceText(int ident) {
- synchronized (mSync) {
- TypedValue tmpValue = mValue;
- int block = loadResourceValue(ident, tmpValue, true);
- if (block >= 0) {
- if (tmpValue.type == TypedValue.TYPE_STRING) {
- return mStringBlocks[block].get(tmpValue.data);
- }
- return tmpValue.coerceToString();
- }
- }
- return null;
- }
-
- /**
- * Retrieve the string value associated with a particular resource
- * identifier for the current configuration / skin.
- */
- /*package*/ final CharSequence getResourceBagText(int ident, int bagEntryId) {
- synchronized (mSync) {
- TypedValue tmpValue = mValue;
- int block = loadResourceBagValue(ident, bagEntryId, tmpValue, true);
- if (block >= 0) {
- if (tmpValue.type == TypedValue.TYPE_STRING) {
- return mStringBlocks[block].get(tmpValue.data);
- }
- return tmpValue.coerceToString();
- }
- }
- return null;
- }
-
- /**
- * Retrieve the string array associated with a particular resource
- * identifier.
- * @param id Resource id of the string array
- */
- /*package*/ final String[] getResourceStringArray(final int id) {
- String[] retArray = getArrayStringResource(id);
- return retArray;
- }
-
-
- /*package*/ final boolean getResourceValue(int ident,
- TypedValue outValue,
- boolean resolveRefs)
- {
- int block = loadResourceValue(ident, outValue, resolveRefs);
- if (block >= 0) {
- if (outValue.type != TypedValue.TYPE_STRING) {
- return true;
- }
- outValue.string = mStringBlocks[block].get(outValue.data);
- return true;
- }
- return false;
- }
-
- /**
- * Retrieve the text array associated with a particular resource
- * identifier.
- * @param id Resource id of the string array
- */
- /*package*/ final CharSequence[] getResourceTextArray(final int id) {
- int[] rawInfoArray = getArrayStringInfo(id);
- int rawInfoArrayLen = rawInfoArray.length;
- final int infoArrayLen = rawInfoArrayLen / 2;
- int block;
- int index;
- CharSequence[] retArray = new CharSequence[infoArrayLen];
- for (int i = 0, j = 0; i < rawInfoArrayLen; i = i + 2, j++) {
- block = rawInfoArray[i];
- index = rawInfoArray[i + 1];
- retArray[j] = index >= 0 ? mStringBlocks[block].get(index) : null;
- }
- return retArray;
- }
-
- /*package*/ final boolean getThemeValue(int theme, int ident,
- TypedValue outValue, boolean resolveRefs) {
- int block = loadThemeAttributeValue(theme, ident, outValue, resolveRefs);
- if (block >= 0) {
- if (outValue.type != TypedValue.TYPE_STRING) {
- return true;
- }
- StringBlock[] blocks = mStringBlocks;
- if (blocks == null) {
- ensureStringBlocks();
- }
- outValue.string = blocks[block].get(outValue.data);
- return true;
- }
- return false;
- }
-
- /*package*/ final void ensureStringBlocks() {
- if (mStringBlocks == null) {
- synchronized (mSync) {
- if (mStringBlocks == null) {
- makeStringBlocks(true);
- }
- }
- }
- }
-
- private final void makeStringBlocks(boolean copyFromSystem) {
- final int sysNum = copyFromSystem ? mSystem.mStringBlocks.length : 0;
- final int num = getStringBlockCount();
- mStringBlocks = new StringBlock[num];
- if (localLOGV) Log.v(TAG, "Making string blocks for " + this
- + ": " + num);
- for (int i=0; i<num; i++) {
- if (i < sysNum) {
- mStringBlocks[i] = mSystem.mStringBlocks[i];
- } else {
- mStringBlocks[i] = new StringBlock(getNativeStringBlock(i), true);
- }
- }
- }
-
- /*package*/ final CharSequence getPooledString(int block, int id) {
- //System.out.println("Get pooled: block=" + block
- // + ", id=#" + Integer.toHexString(id)
- // + ", blocks=" + mStringBlocks);
- return mStringBlocks[block-1].get(id);
- }
-
- /**
- * Open an asset using ACCESS_STREAMING mode. This provides access to
- * files that have been bundled with an application as assets -- that is,
- * files placed in to the "assets" directory.
- *
- * @param fileName The name of the asset to open. This name can be
- * hierarchical.
- *
- * @see #open(String, int)
- * @see #list
- */
- public final InputStream open(String fileName) throws IOException {
- return open(fileName, ACCESS_STREAMING);
- }
-
- /**
- * Open an asset using an explicit access mode, returning an InputStream to
- * read its contents. This provides access to files that have been bundled
- * with an application as assets -- that is, files placed in to the
- * "assets" directory.
- *
- * @param fileName The name of the asset to open. This name can be
- * hierarchical.
- * @param accessMode Desired access mode for retrieving the data.
- *
- * @see #ACCESS_UNKNOWN
- * @see #ACCESS_STREAMING
- * @see #ACCESS_RANDOM
- * @see #ACCESS_BUFFER
- * @see #open(String)
- * @see #list
- */
- public final InputStream open(String fileName, int accessMode)
- throws IOException {
- synchronized (mSync) {
- if (!mOpen) {
- throw new RuntimeException("Assetmanager has been closed");
- }
- int asset = openAsset(fileName, accessMode);
- if (asset != 0) {
- mNumRefs++;
- return new AssetInputStream(asset);
- }
- }
- throw new FileNotFoundException("Asset file: " + fileName);
- }
-
- public final AssetFileDescriptor openFd(String fileName)
- throws IOException {
- synchronized (mSync) {
- if (!mOpen) {
- throw new RuntimeException("Assetmanager has been closed");
- }
- ParcelFileDescriptor pfd = openAssetFd(fileName, mOffsets);
- if (pfd != null) {
- return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
- }
- }
- throw new FileNotFoundException("Asset file: " + fileName);
- }
-
- /**
- * Return a String array of all the assets at the given path.
- *
- * @param path A relative path within the assets, i.e., "docs/home.html".
- *
- * @return String[] Array of strings, one for each asset. These file
- * names are relative to 'path'. You can open the file by
- * concatenating 'path' and a name in the returned string (via
- * File) and passing that to open().
- *
- * @see #open
- */
- public native final String[] list(String path)
- throws IOException;
-
- /**
- * {@hide}
- * Open a non-asset file as an asset using ACCESS_STREAMING mode. This
- * provides direct access to all of the files included in an application
- * package (not only its assets). Applications should not normally use
- * this.
- *
- * @see #open(String)
- */
- public final InputStream openNonAsset(String fileName) throws IOException {
- return openNonAsset(0, fileName, ACCESS_STREAMING);
- }
-
- /**
- * {@hide}
- * Open a non-asset file as an asset using a specific access mode. This
- * provides direct access to all of the files included in an application
- * package (not only its assets). Applications should not normally use
- * this.
- *
- * @see #open(String, int)
- */
- public final InputStream openNonAsset(String fileName, int accessMode)
- throws IOException {
- return openNonAsset(0, fileName, accessMode);
- }
-
- /**
- * {@hide}
- * Open a non-asset in a specified package. Not for use by applications.
- *
- * @param cookie Identifier of the package to be opened.
- * @param fileName Name of the asset to retrieve.
- */
- public final InputStream openNonAsset(int cookie, String fileName)
- throws IOException {
- return openNonAsset(cookie, fileName, ACCESS_STREAMING);
- }
-
- /**
- * {@hide}
- * Open a non-asset in a specified package. Not for use by applications.
- *
- * @param cookie Identifier of the package to be opened.
- * @param fileName Name of the asset to retrieve.
- * @param accessMode Desired access mode for retrieving the data.
- */
- public final InputStream openNonAsset(int cookie, String fileName, int accessMode)
- throws IOException {
- synchronized (mSync) {
- if (!mOpen) {
- throw new RuntimeException("Assetmanager has been closed");
- }
- int asset = openNonAssetNative(cookie, fileName, accessMode);
- if (asset != 0) {
- mNumRefs++;
- return new AssetInputStream(asset);
- }
- }
- throw new FileNotFoundException("Asset absolute file: " + fileName);
- }
-
- public final AssetFileDescriptor openNonAssetFd(String fileName)
- throws IOException {
- return openNonAssetFd(0, fileName);
- }
-
- public final AssetFileDescriptor openNonAssetFd(int cookie,
- String fileName) throws IOException {
- synchronized (mSync) {
- if (!mOpen) {
- throw new RuntimeException("Assetmanager has been closed");
- }
- ParcelFileDescriptor pfd = openNonAssetFdNative(cookie,
- fileName, mOffsets);
- if (pfd != null) {
- return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
- }
- }
- throw new FileNotFoundException("Asset absolute file: " + fileName);
- }
-
- /**
- * Retrieve a parser for a compiled XML file.
- *
- * @param fileName The name of the file to retrieve.
- */
- public final XmlResourceParser openXmlResourceParser(String fileName)
- throws IOException {
- return openXmlResourceParser(0, fileName);
- }
-
- /**
- * Retrieve a parser for a compiled XML file.
- *
- * @param cookie Identifier of the package to be opened.
- * @param fileName The name of the file to retrieve.
- */
- public final XmlResourceParser openXmlResourceParser(int cookie,
- String fileName) throws IOException {
- XmlBlock block = openXmlBlockAsset(cookie, fileName);
- XmlResourceParser rp = block.newParser();
- block.close();
- return rp;
- }
-
- /**
- * {@hide}
- * Retrieve a non-asset as a compiled XML file. Not for use by
- * applications.
- *
- * @param fileName The name of the file to retrieve.
- */
- /*package*/ final XmlBlock openXmlBlockAsset(String fileName)
- throws IOException {
- return openXmlBlockAsset(0, fileName);
- }
-
- /**
- * {@hide}
- * Retrieve a non-asset as a compiled XML file. Not for use by
- * applications.
- *
- * @param cookie Identifier of the package to be opened.
- * @param fileName Name of the asset to retrieve.
- */
- /*package*/ final XmlBlock openXmlBlockAsset(int cookie, String fileName)
- throws IOException {
- synchronized (mSync) {
- if (!mOpen) {
- throw new RuntimeException("Assetmanager has been closed");
- }
- int xmlBlock = openXmlAssetNative(cookie, fileName);
- if (xmlBlock != 0) {
- mNumRefs++;
- return new XmlBlock(this, xmlBlock);
- }
- }
- throw new FileNotFoundException("Asset XML file: " + fileName);
- }
-
- /*package*/ void xmlBlockGone() {
- synchronized (mSync) {
- decRefsLocked();
- }
- }
-
- /*package*/ final int createTheme() {
- synchronized (mSync) {
- if (!mOpen) {
- throw new RuntimeException("Assetmanager has been closed");
- }
- mNumRefs++;
- return newTheme();
- }
- }
-
- /*package*/ final void releaseTheme(int theme) {
- synchronized (mSync) {
- deleteTheme(theme);
- decRefsLocked();
- }
- }
-
- protected void finalize() throws Throwable {
- destroy();
- }
-
- public final class AssetInputStream extends InputStream {
- public final int getAssetInt() {
- return mAsset;
- }
- private AssetInputStream(int asset)
- {
- mAsset = asset;
- mLength = getAssetLength(asset);
- }
- public final int read() throws IOException {
- return readAssetChar(mAsset);
- }
- public final boolean markSupported() {
- return true;
- }
- public final int available() throws IOException {
- long len = getAssetRemainingLength(mAsset);
- return len > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)len;
- }
- public final void close() throws IOException {
- synchronized (AssetManager.mSync) {
- if (mAsset != 0) {
- destroyAsset(mAsset);
- mAsset = 0;
- decRefsLocked();
- }
- }
- }
- public final void mark(int readlimit) {
- mMarkPos = seekAsset(mAsset, 0, 0);
- }
- public final void reset() throws IOException {
- seekAsset(mAsset, mMarkPos, -1);
- }
- public final int read(byte[] b) throws IOException {
- return readAsset(mAsset, b, 0, b.length);
- }
- public final int read(byte[] b, int off, int len) throws IOException {
- return readAsset(mAsset, b, off, len);
- }
- public final long skip(long n) throws IOException {
- long pos = seekAsset(mAsset, 0, 0);
- if ((pos+n) > mLength) {
- n = mLength-pos;
- }
- if (n > 0) {
- seekAsset(mAsset, n, 0);
- }
- return n;
- }
-
- protected void finalize() throws Throwable
- {
- close();
- }
-
- private int mAsset;
- private long mLength;
- private long mMarkPos;
- }
-
- /**
- * Add an additional set of assets to the asset manager. This can be
- * either a directory or ZIP file. Not for use by applications. A
- * zero return value indicates failure.
- * {@hide}
- */
- public native final int addAssetPath(String path);
-
- /**
- * Determine whether the state in this asset manager is up-to-date with
- * the files on the filesystem. If false is returned, you need to
- * instantiate a new AssetManager class to see the new data.
- * {@hide}
- */
- public native final boolean isUpToDate();
-
- /**
- * Change the locale being used by this asset manager. Not for use by
- * applications.
- * {@hide}
- */
- public native final void setLocale(String locale);
-
- /**
- * Get the locales that this asset manager contains data for.
- */
- public native final String[] getLocales();
-
- /**
- * Change the configuation used when retrieving resources. Not for use by
- * applications.
- * {@hide}
- */
- public native final void setConfiguration(int mcc, int mnc, String locale,
- int orientation, int touchscreen, int density, int keyboard,
- int keyboardHidden, int navigation, int screenWidth, int screenHeight,
- int majorVersion);
-
- /**
- * Retrieve the resource identifier for the given resource name.
- */
- /*package*/ native final int getResourceIdentifier(String type,
- String name,
- String defPackage);
-
- /*package*/ native final String getResourceName(int resid);
- /*package*/ native final String getResourcePackageName(int resid);
- /*package*/ native final String getResourceTypeName(int resid);
- /*package*/ native final String getResourceEntryName(int resid);
-
- private native final int openAsset(String fileName, int accessMode);
- private final native ParcelFileDescriptor openAssetFd(String fileName,
- long[] outOffsets) throws IOException;
- private native final int openNonAssetNative(int cookie, String fileName,
- int accessMode);
- private native ParcelFileDescriptor openNonAssetFdNative(int cookie,
- String fileName, long[] outOffsets) throws IOException;
- private native final void destroyAsset(int asset);
- private native final int readAssetChar(int asset);
- private native final int readAsset(int asset, byte[] b, int off, int len);
- private native final long seekAsset(int asset, long offset, int whence);
- private native final long getAssetLength(int asset);
- private native final long getAssetRemainingLength(int asset);
-
- /** Returns true if the resource was found, filling in mRetStringBlock and
- * mRetData. */
- private native final int loadResourceValue(int ident, TypedValue outValue,
- boolean resolve);
- /** Returns true if the resource was found, filling in mRetStringBlock and
- * mRetData. */
- private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue,
- boolean resolve);
- /*package*/ static final int STYLE_NUM_ENTRIES = 5;
- /*package*/ static final int STYLE_TYPE = 0;
- /*package*/ static final int STYLE_DATA = 1;
- /*package*/ static final int STYLE_ASSET_COOKIE = 2;
- /*package*/ static final int STYLE_RESOURCE_ID = 3;
- /*package*/ static final int STYLE_CHANGING_CONFIGURATIONS = 4;
- /*package*/ native static final boolean applyStyle(int theme,
- int defStyleAttr, int defStyleRes, int xmlParser,
- int[] inAttrs, int[] outValues, int[] outIndices);
- /*package*/ native final boolean retrieveAttributes(
- int xmlParser, int[] inAttrs, int[] outValues, int[] outIndices);
- /*package*/ native final int getArraySize(int resource);
- /*package*/ native final int retrieveArray(int resource, int[] outValues);
- private native final int getStringBlockCount();
- private native final int getNativeStringBlock(int block);
-
- /**
- * {@hide}
- */
- public native final String getCookieName(int cookie);
-
- /**
- * {@hide}
- */
- public native static final int getGlobalAssetCount();
-
- /**
- * {@hide}
- */
- public native static final int getGlobalAssetManagerCount();
-
- private native final int newTheme();
- private native final void deleteTheme(int theme);
- /*package*/ native static final void applyThemeStyle(int theme, int styleRes, boolean force);
- /*package*/ native static final void copyTheme(int dest, int source);
- /*package*/ native static final int loadThemeAttributeValue(int theme, int ident,
- TypedValue outValue,
- boolean resolve);
- /*package*/ native static final void dumpTheme(int theme, int priority, String tag, String prefix);
-
- private native final int openXmlAssetNative(int cookie, String fileName);
-
- private native final String[] getArrayStringResource(int arrayRes);
- private native final int[] getArrayStringInfo(int arrayRes);
- /*package*/ native final int[] getArrayIntResource(int arrayRes);
-
- private native final void init();
- private native final void destroy();
-
- private final void decRefsLocked() {
- mNumRefs--;
- //System.out.println("Dec streams: mNumRefs=" + mNumRefs
- // + " mReleased=" + mReleased);
- if (mNumRefs == 0) {
- destroy();
- }
- }
-}
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
deleted file mode 100644
index 17cb687..0000000
--- a/core/java/android/content/res/ColorStateList.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res;
-
-import com.google.android.collect.Lists;
-
-import com.android.internal.util.ArrayUtils;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.util.AttributeSet;
-import android.util.SparseArray;
-import android.util.StateSet;
-import android.util.Xml;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.util.Arrays;
-
-/**
- *
- * Lets you map {@link android.view.View} state sets to colors.
- *
- * {@link android.content.res.ColorStateList}s are created from XML resource files defined in the
- * "color" subdirectory directory of an application's resource directory. The XML file contains
- * a single "selector" element with a number of "item" elements inside. For example:
- *
- * <pre>
- * &lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&gt;
- * &lt;item android:state_focused="true" android:color="@color/testcolor1"/&gt;
- * &lt;item android:state_pressed="true" android:state_enabled="false" android:color="@color/testcolor2" /&gt;
- * &lt;item android:state_enabled="false" android:colore="@color/testcolor3" /&gt;
- * &lt;item android:state_active="true" android:color="@color/testcolor4" /&gt;
- * &lt;item android:color="@color/testcolor5"/&gt;
- * &lt;/selector&gt;
- * </pre>
- *
- * This defines a set of state spec / color pairs where each state spec specifies a set of
- * states that a view must either be in or not be in and the color specifies the color associated
- * with that spec. The list of state specs will be processed in order of the items in the XML file.
- * An item with no state spec is considered to match any set of states and is generally useful as
- * a final item to be used as a default. Note that if you have such an item before any other items
- * in the list then any subsequent items will end up being ignored.
- */
-public class ColorStateList implements Parcelable {
-
- private int[][] mStateSpecs; // must be parallel to mColors
- private int[] mColors; // must be parallel to mStateSpecs
- private int mDefaultColor = 0xffff0000;
-
- private static final int[][] EMPTY = new int[][] { new int[0] };
- private static final SparseArray<WeakReference<ColorStateList>> sCache =
- new SparseArray<WeakReference<ColorStateList>>();
-
- private ColorStateList() { }
-
- /**
- * Creates a ColorStateList that returns the specified mapping from
- * states to colors.
- */
- public ColorStateList(int[][] states, int[] colors) {
- mStateSpecs = states;
- mColors = colors;
-
- if (states.length > 0) {
- mDefaultColor = colors[0];
-
- for (int i = 0; i < states.length; i++) {
- if (states[i].length == 0) {
- mDefaultColor = colors[i];
- }
- }
- }
- }
-
- /**
- * Creates or retrieves a ColorStateList that always returns a single color.
- */
- public static ColorStateList valueOf(int color) {
- // TODO: should we collect these eventually?
- synchronized (sCache) {
- WeakReference<ColorStateList> ref = sCache.get(color);
- ColorStateList csl = ref != null ? ref.get() : null;
-
- if (csl != null) {
- return csl;
- }
-
- csl = new ColorStateList(EMPTY, new int[] { color });
- sCache.put(color, new WeakReference<ColorStateList>(csl));
- return csl;
- }
- }
-
- /**
- * Create a ColorStateList from an XML document, given a set of {@link Resources}.
- */
- public static ColorStateList createFromXml(Resources r, XmlPullParser parser)
- throws XmlPullParserException, IOException {
- AttributeSet attrs = Xml.asAttributeSet(parser);
-
- int type;
- while ((type=parser.next()) != XmlPullParser.START_TAG
- && type != XmlPullParser.END_DOCUMENT) {
- }
-
- if (type != XmlPullParser.START_TAG) {
- throw new XmlPullParserException("No start tag found");
- }
-
- final ColorStateList colorStateList = createFromXmlInner(r, parser, attrs);
-
- return colorStateList;
- }
-
- /* Create from inside an XML document. Called on a parser positioned at
- * a tag in an XML document, tries to create a ColorStateList from that tag.
- * Returns null if the tag is not a valid ColorStateList.
- */
- private static ColorStateList createFromXmlInner(Resources r,
- XmlPullParser parser,
- AttributeSet attrs)
- throws XmlPullParserException, IOException {
- ColorStateList colorStateList;
-
- final String name = parser.getName();
-
- if (name.equals("selector")) {
- colorStateList = new ColorStateList();
- } else {
- throw new XmlPullParserException(
- parser.getPositionDescription() + ": invalid drawable tag "
- + name);
- }
-
- colorStateList.inflate(r, parser, attrs);
- return colorStateList;
- }
-
- /**
- * Creates a new ColorStateList that has the same states and
- * colors as this one but where each color has the specified alpha value
- * (0-255).
- */
- public ColorStateList withAlpha(int alpha) {
- int[] colors = new int[mColors.length];
-
- int len = colors.length;
- for (int i = 0; i < len; i++) {
- colors[i] = (mColors[i] & 0xFFFFFF) | (alpha << 24);
- }
-
- return new ColorStateList(mStateSpecs, colors);
- }
-
- /**
- * Fill in this object based on the contents of an XML "selector" element.
- */
- private void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
- throws XmlPullParserException, IOException {
-
- int type;
-
- final int innerDepth = parser.getDepth()+1;
- int depth;
-
- int listAllocated = 20;
- int listSize = 0;
- int[] colorList = new int[listAllocated];
- int[][] stateSpecList = new int[listAllocated][];
-
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && ((depth=parser.getDepth()) >= innerDepth
- || type != XmlPullParser.END_TAG)) {
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
-
- if (depth > innerDepth || !parser.getName().equals("item")) {
- continue;
- }
-
- int colorRes = 0;
- int color = 0xffff0000;
- boolean haveColor = false;
-
- int i;
- int j = 0;
- final int numAttrs = attrs.getAttributeCount();
- int[] stateSpec = new int[numAttrs];
- for (i = 0; i < numAttrs; i++) {
- final int stateResId = attrs.getAttributeNameResource(i);
- if (stateResId == 0) break;
- if (stateResId == com.android.internal.R.attr.color) {
- colorRes = attrs.getAttributeResourceValue(i, 0);
-
- if (colorRes == 0) {
- color = attrs.getAttributeIntValue(i, color);
- haveColor = true;
- }
- } else {
- stateSpec[j++] = attrs.getAttributeBooleanValue(i, false)
- ? stateResId
- : -stateResId;
- }
- }
- stateSpec = StateSet.trimStateSet(stateSpec, j);
-
- if (colorRes != 0) {
- color = r.getColor(colorRes);
- } else if (!haveColor) {
- throw new XmlPullParserException(
- parser.getPositionDescription()
- + ": <item> tag requires a 'android:color' attribute.");
- }
-
- if (listSize == 0 || stateSpec.length == 0) {
- mDefaultColor = color;
- }
-
- if (listSize + 1 >= listAllocated) {
- listAllocated = ArrayUtils.idealIntArraySize(listSize + 1);
-
- int[] ncolor = new int[listAllocated];
- System.arraycopy(colorList, 0, ncolor, 0, listSize);
-
- int[][] nstate = new int[listAllocated][];
- System.arraycopy(stateSpecList, 0, nstate, 0, listSize);
-
- colorList = ncolor;
- stateSpecList = nstate;
- }
-
- colorList[listSize] = color;
- stateSpecList[listSize] = stateSpec;
- listSize++;
- }
-
- mColors = new int[listSize];
- mStateSpecs = new int[listSize][];
- System.arraycopy(colorList, 0, mColors, 0, listSize);
- System.arraycopy(stateSpecList, 0, mStateSpecs, 0, listSize);
- }
-
- public boolean isStateful() {
- return mStateSpecs.length > 1;
- }
-
- /**
- * Return the color associated with the given set of {@link android.view.View} states.
- *
- * @param stateSet an array of {@link android.view.View} states
- * @param defaultColor the color to return if there's not state spec in this
- * {@link ColorStateList} that matches the stateSet.
- *
- * @return the color associated with that set of states in this {@link ColorStateList}.
- */
- public int getColorForState(int[] stateSet, int defaultColor) {
- final int setLength = mStateSpecs.length;
- for (int i = 0; i < setLength; i++) {
- int[] stateSpec = mStateSpecs[i];
- if (StateSet.stateSetMatches(stateSpec, stateSet)) {
- return mColors[i];
- }
- }
- return defaultColor;
- }
-
- /**
- * Return the default color in this {@link ColorStateList}.
- *
- * @return the default color in this {@link ColorStateList}.
- */
- public int getDefaultColor() {
- return mDefaultColor;
- }
-
- public String toString() {
- return "ColorStateList{" +
- "mStateSpecs=" + Arrays.deepToString(mStateSpecs) +
- "mColors=" + Arrays.toString(mColors) +
- "mDefaultColor=" + mDefaultColor + '}';
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- final int N = mStateSpecs.length;
- dest.writeInt(N);
- for (int i=0; i<N; i++) {
- dest.writeIntArray(mStateSpecs[i]);
- }
- dest.writeArray(mStateSpecs);
- dest.writeIntArray(mColors);
- }
-
- public static final Parcelable.Creator<ColorStateList> CREATOR =
- new Parcelable.Creator<ColorStateList>() {
- public ColorStateList[] newArray(int size) {
- return new ColorStateList[size];
- }
-
- public ColorStateList createFromParcel(Parcel source) {
- final int N = source.readInt();
- int[][] stateSpecs = new int[N][];
- for (int i=0; i<N; i++) {
- stateSpecs[i] = source.createIntArray();
- }
- int[] colors = source.createIntArray();
- return new ColorStateList(stateSpecs, colors);
- }
- };
-}
diff --git a/core/java/android/content/res/Configuration.aidl b/core/java/android/content/res/Configuration.aidl
deleted file mode 100755
index bb7f2dd..0000000
--- a/core/java/android/content/res/Configuration.aidl
+++ /dev/null
@@ -1,21 +0,0 @@
-/* //device/java/android/android/view/WindowManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.res;
-
-parcelable Configuration;
-
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
deleted file mode 100644
index 7e4b7ac..0000000
--- a/core/java/android/content/res/Configuration.java
+++ /dev/null
@@ -1,436 +0,0 @@
-package android.content.res;
-
-import android.content.pm.ActivityInfo;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Locale;
-
-/**
- * This class describes all device configuration information that can
- * impact the resources the application retrieves. This includes both
- * user-specified configuration options (locale and scaling) as well
- * as dynamic device configuration (various types of input devices).
- */
-public final class Configuration implements Parcelable, Comparable<Configuration> {
- /**
- * Current user preference for the scaling factor for fonts, relative
- * to the base density scaling.
- */
- public float fontScale;
-
- /**
- * IMSI MCC (Mobile Country Code). 0 if undefined.
- */
- public int mcc;
-
- /**
- * IMSI MNC (Mobile Network Code). 0 if undefined.
- */
- public int mnc;
-
- /**
- * Current user preference for the locale.
- */
- public Locale locale;
-
- /**
- * Locale should persist on setting
- * @hide pending API council approval
- */
- public boolean userSetLocale;
-
- public static final int TOUCHSCREEN_UNDEFINED = 0;
- public static final int TOUCHSCREEN_NOTOUCH = 1;
- public static final int TOUCHSCREEN_STYLUS = 2;
- public static final int TOUCHSCREEN_FINGER = 3;
-
- /**
- * The kind of touch screen attached to the device.
- * One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_STYLUS},
- * {@link #TOUCHSCREEN_FINGER}.
- */
- public int touchscreen;
-
- public static final int KEYBOARD_UNDEFINED = 0;
- public static final int KEYBOARD_NOKEYS = 1;
- public static final int KEYBOARD_QWERTY = 2;
- public static final int KEYBOARD_12KEY = 3;
-
- /**
- * The kind of keyboard attached to the device.
- * One of: {@link #KEYBOARD_QWERTY}, {@link #KEYBOARD_12KEY}.
- */
- public int keyboard;
-
- public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
- public static final int KEYBOARDHIDDEN_NO = 1;
- public static final int KEYBOARDHIDDEN_YES = 2;
- /** Constant matching actual resource implementation. {@hide} */
- public static final int KEYBOARDHIDDEN_SOFT = 3;
-
- /**
- * A flag indicating whether any keyboard is available. Unlike
- * {@link #hardKeyboardHidden}, this also takes into account a soft
- * keyboard, so if the hard keyboard is hidden but there is soft
- * keyboard available, it will be set to NO. Value is one of:
- * {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}.
- */
- public int keyboardHidden;
-
- public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0;
- public static final int HARDKEYBOARDHIDDEN_NO = 1;
- public static final int HARDKEYBOARDHIDDEN_YES = 2;
-
- /**
- * A flag indicating whether the hard keyboard has been hidden. This will
- * be set on a device with a mechanism to hide the keyboard from the
- * user, when that mechanism is closed. One of:
- * {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}.
- */
- public int hardKeyboardHidden;
-
- public static final int NAVIGATION_UNDEFINED = 0;
- public static final int NAVIGATION_NONAV = 1;
- public static final int NAVIGATION_DPAD = 2;
- public static final int NAVIGATION_TRACKBALL = 3;
- public static final int NAVIGATION_WHEEL = 4;
-
- /**
- * The kind of navigation method available on the device.
- * One of: {@link #NAVIGATION_DPAD}, {@link #NAVIGATION_TRACKBALL},
- * {@link #NAVIGATION_WHEEL}.
- */
- public int navigation;
-
- public static final int ORIENTATION_UNDEFINED = 0;
- public static final int ORIENTATION_PORTRAIT = 1;
- public static final int ORIENTATION_LANDSCAPE = 2;
- public static final int ORIENTATION_SQUARE = 3;
-
- /**
- * Overall orientation of the screen. May be one of
- * {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT},
- * or {@link #ORIENTATION_SQUARE}.
- */
- public int orientation;
-
- /**
- * Construct an invalid Configuration. You must call {@link #setToDefaults}
- * for this object to be valid. {@more}
- */
- public Configuration() {
- setToDefaults();
- }
-
- /**
- * Makes a deep copy suitable for modification.
- */
- public Configuration(Configuration o) {
- fontScale = o.fontScale;
- mcc = o.mcc;
- mnc = o.mnc;
- if (o.locale != null) {
- locale = (Locale) o.locale.clone();
- }
- userSetLocale = o.userSetLocale;
- touchscreen = o.touchscreen;
- keyboard = o.keyboard;
- keyboardHidden = o.keyboardHidden;
- hardKeyboardHidden = o.hardKeyboardHidden;
- navigation = o.navigation;
- orientation = o.orientation;
- }
-
- public String toString() {
- return "{ scale=" + fontScale + " imsi=" + mcc + "/" + mnc
- + " locale=" + locale
- + " touch=" + touchscreen + " key=" + keyboard + "/"
- + keyboardHidden + "/" + hardKeyboardHidden
- + " nav=" + navigation + " orien=" + orientation + " }";
- }
-
- /**
- * Set this object to the system defaults.
- */
- public void setToDefaults() {
- fontScale = 1;
- mcc = mnc = 0;
- locale = Locale.getDefault();
- userSetLocale = false;
- touchscreen = TOUCHSCREEN_UNDEFINED;
- keyboard = KEYBOARD_UNDEFINED;
- keyboardHidden = KEYBOARDHIDDEN_UNDEFINED;
- hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
- navigation = NAVIGATION_UNDEFINED;
- orientation = ORIENTATION_UNDEFINED;
- }
-
- /** {@hide} */
- @Deprecated public void makeDefault() {
- setToDefaults();
- }
-
- /**
- * Copy the fields from delta into this Configuration object, keeping
- * track of which ones have changed. Any undefined fields in
- * <var>delta</var> are ignored and not copied in to the current
- * Configuration.
- * @return Returns a bit mask of the changed fields, as per
- * {@link #diff}.
- */
- public int updateFrom(Configuration delta) {
- int changed = 0;
- if (delta.fontScale > 0 && fontScale != delta.fontScale) {
- changed |= ActivityInfo.CONFIG_FONT_SCALE;
- fontScale = delta.fontScale;
- }
- if (delta.mcc != 0 && mcc != delta.mcc) {
- changed |= ActivityInfo.CONFIG_MCC;
- mcc = delta.mcc;
- }
- if (delta.mnc != 0 && mnc != delta.mnc) {
- changed |= ActivityInfo.CONFIG_MNC;
- mnc = delta.mnc;
- }
- if (delta.locale != null
- && (locale == null || !locale.equals(delta.locale))) {
- changed |= ActivityInfo.CONFIG_LOCALE;
- locale = delta.locale != null
- ? (Locale) delta.locale.clone() : null;
- }
- if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0)))
- {
- userSetLocale = true;
- changed |= ActivityInfo.CONFIG_LOCALE;
- }
- if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
- && touchscreen != delta.touchscreen) {
- changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
- touchscreen = delta.touchscreen;
- }
- if (delta.keyboard != KEYBOARD_UNDEFINED
- && keyboard != delta.keyboard) {
- changed |= ActivityInfo.CONFIG_KEYBOARD;
- keyboard = delta.keyboard;
- }
- if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
- && keyboardHidden != delta.keyboardHidden) {
- changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
- keyboardHidden = delta.keyboardHidden;
- }
- if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
- && hardKeyboardHidden != delta.hardKeyboardHidden) {
- changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
- hardKeyboardHidden = delta.hardKeyboardHidden;
- }
- if (delta.navigation != NAVIGATION_UNDEFINED
- && navigation != delta.navigation) {
- changed |= ActivityInfo.CONFIG_NAVIGATION;
- navigation = delta.navigation;
- }
- if (delta.orientation != ORIENTATION_UNDEFINED
- && orientation != delta.orientation) {
- changed |= ActivityInfo.CONFIG_ORIENTATION;
- orientation = delta.orientation;
- }
-
- return changed;
- }
-
- /**
- * Return a bit mask of the differences between this Configuration
- * object and the given one. Does not change the values of either. Any
- * undefined fields in <var>delta</var> are ignored.
- * @return Returns a bit mask indicating which configuration
- * values has changed, containing any combination of
- * {@link android.content.pm.ActivityInfo#CONFIG_FONT_SCALE
- * PackageManager.ActivityInfo.CONFIG_FONT_SCALE},
- * {@link android.content.pm.ActivityInfo#CONFIG_MCC
- * PackageManager.ActivityInfo.CONFIG_MCC},
- * {@link android.content.pm.ActivityInfo#CONFIG_MNC
- * PackageManager.ActivityInfo.CONFIG_MNC},
- * {@link android.content.pm.ActivityInfo#CONFIG_LOCALE
- * PackageManager.ActivityInfo.CONFIG_LOCALE},
- * {@link android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN
- * PackageManager.ActivityInfo.CONFIG_TOUCHSCREEN},
- * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD
- * PackageManager.ActivityInfo.CONFIG_KEYBOARD},
- * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION
- * PackageManager.ActivityInfo.CONFIG_NAVIGATION}, or
- * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION
- * PackageManager.ActivityInfo.CONFIG_ORIENTATION}.
- */
- public int diff(Configuration delta) {
- int changed = 0;
- if (delta.fontScale > 0 && fontScale != delta.fontScale) {
- changed |= ActivityInfo.CONFIG_FONT_SCALE;
- }
- if (delta.mcc != 0 && mcc != delta.mcc) {
- changed |= ActivityInfo.CONFIG_MCC;
- }
- if (delta.mnc != 0 && mnc != delta.mnc) {
- changed |= ActivityInfo.CONFIG_MNC;
- }
- if (delta.locale != null
- && (locale == null || !locale.equals(delta.locale))) {
- changed |= ActivityInfo.CONFIG_LOCALE;
- }
- if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
- && touchscreen != delta.touchscreen) {
- changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
- }
- if (delta.keyboard != KEYBOARD_UNDEFINED
- && keyboard != delta.keyboard) {
- changed |= ActivityInfo.CONFIG_KEYBOARD;
- }
- if (delta.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED
- && keyboardHidden != delta.keyboardHidden) {
- changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
- }
- if (delta.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED
- && hardKeyboardHidden != delta.hardKeyboardHidden) {
- changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
- }
- if (delta.navigation != NAVIGATION_UNDEFINED
- && navigation != delta.navigation) {
- changed |= ActivityInfo.CONFIG_NAVIGATION;
- }
- if (delta.orientation != ORIENTATION_UNDEFINED
- && orientation != delta.orientation) {
- changed |= ActivityInfo.CONFIG_ORIENTATION;
- }
-
- return changed;
- }
-
- /**
- * Determine if a new resource needs to be loaded from the bit set of
- * configuration changes returned by {@link #updateFrom(Configuration)}.
- *
- * @param configChanges The mask of changes configurations as returned by
- * {@link #updateFrom(Configuration)}.
- * @param interestingChanges The configuration changes that the resource
- * can handled, as given in {@link android.util.TypedValue#changingConfigurations}.
- *
- * @return Return true if the resource needs to be loaded, else false.
- */
- public static boolean needNewResources(int configChanges, int interestingChanges) {
- return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0;
- }
-
- /**
- * Parcelable methods
- */
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeFloat(fontScale);
- dest.writeInt(mcc);
- dest.writeInt(mnc);
- if (locale == null) {
- dest.writeInt(0);
- } else {
- dest.writeInt(1);
- dest.writeString(locale.getLanguage());
- dest.writeString(locale.getCountry());
- dest.writeString(locale.getVariant());
- }
- if(userSetLocale) {
- dest.writeInt(1);
- } else {
- dest.writeInt(0);
- }
- dest.writeInt(touchscreen);
- dest.writeInt(keyboard);
- dest.writeInt(keyboardHidden);
- dest.writeInt(hardKeyboardHidden);
- dest.writeInt(navigation);
- dest.writeInt(orientation);
- }
-
- public static final Parcelable.Creator<Configuration> CREATOR
- = new Parcelable.Creator<Configuration>() {
- public Configuration createFromParcel(Parcel source) {
- return new Configuration(source);
- }
-
- public Configuration[] newArray(int size) {
- return new Configuration[size];
- }
- };
-
- /**
- * Construct this Configuration object, reading from the Parcel.
- */
- private Configuration(Parcel source) {
- fontScale = source.readFloat();
- mcc = source.readInt();
- mnc = source.readInt();
- if (source.readInt() != 0) {
- locale = new Locale(source.readString(), source.readString(),
- source.readString());
- }
- userSetLocale = (source.readInt()==1);
- touchscreen = source.readInt();
- keyboard = source.readInt();
- keyboardHidden = source.readInt();
- hardKeyboardHidden = source.readInt();
- navigation = source.readInt();
- orientation = source.readInt();
- }
-
- public int compareTo(Configuration that) {
- int n;
- float a = this.fontScale;
- float b = that.fontScale;
- if (a < b) return -1;
- if (a > b) return 1;
- n = this.mcc - that.mcc;
- if (n != 0) return n;
- n = this.mnc - that.mnc;
- if (n != 0) return n;
- n = this.locale.getLanguage().compareTo(that.locale.getLanguage());
- if (n != 0) return n;
- n = this.locale.getCountry().compareTo(that.locale.getCountry());
- if (n != 0) return n;
- n = this.locale.getVariant().compareTo(that.locale.getVariant());
- if (n != 0) return n;
- n = this.touchscreen - that.touchscreen;
- if (n != 0) return n;
- n = this.keyboard - that.keyboard;
- if (n != 0) return n;
- n = this.keyboardHidden - that.keyboardHidden;
- if (n != 0) return n;
- n = this.hardKeyboardHidden - that.hardKeyboardHidden;
- if (n != 0) return n;
- n = this.navigation - that.navigation;
- if (n != 0) return n;
- n = this.orientation - that.orientation;
- //if (n != 0) return n;
- return n;
- }
-
- public boolean equals(Configuration that) {
- if (that == null) return false;
- if (that == this) return true;
- return this.compareTo(that) == 0;
- }
-
- public boolean equals(Object that) {
- try {
- return equals((Configuration)that);
- } catch (ClassCastException e) {
- }
- return false;
- }
-
- public int hashCode() {
- return ((int)this.fontScale) + this.mcc + this.mnc
- + this.locale.hashCode() + this.touchscreen
- + this.keyboard + this.keyboardHidden + this.hardKeyboardHidden
- + this.navigation + this.orientation;
- }
-}
diff --git a/core/java/android/content/res/PluralRules.java b/core/java/android/content/res/PluralRules.java
deleted file mode 100644
index 2dce3c1..0000000
--- a/core/java/android/content/res/PluralRules.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res;
-
-import java.util.Locale;
-
-/*
- * Yuck-o. This is not the right way to implement this. When the ICU PluralRules
- * object has been integrated to android, we should switch to that. For now, yuck-o.
- */
-
-abstract class PluralRules {
-
- static final int QUANTITY_OTHER = 0x0000;
- static final int QUANTITY_ZERO = 0x0001;
- static final int QUANTITY_ONE = 0x0002;
- static final int QUANTITY_TWO = 0x0004;
- static final int QUANTITY_FEW = 0x0008;
- static final int QUANTITY_MANY = 0x0010;
-
- static final int ID_OTHER = 0x01000004;
-
- abstract int quantityForNumber(int n);
-
- final int attrForNumber(int n) {
- return PluralRules.attrForQuantity(quantityForNumber(n));
- }
-
- static final int attrForQuantity(int quantity) {
- // see include/utils/ResourceTypes.h
- switch (quantity) {
- case QUANTITY_ZERO: return 0x01000005;
- case QUANTITY_ONE: return 0x01000006;
- case QUANTITY_TWO: return 0x01000007;
- case QUANTITY_FEW: return 0x01000008;
- case QUANTITY_MANY: return 0x01000009;
- default: return ID_OTHER;
- }
- }
-
- static final String stringForQuantity(int quantity) {
- switch (quantity) {
- case QUANTITY_ZERO:
- return "zero";
- case QUANTITY_ONE:
- return "one";
- case QUANTITY_TWO:
- return "two";
- case QUANTITY_FEW:
- return "few";
- case QUANTITY_MANY:
- return "many";
- default:
- return "other";
- }
- }
-
- static final PluralRules ruleForLocale(Locale locale) {
- String lang = locale.getLanguage();
- if ("cs".equals(lang)) {
- if (cs == null) cs = new cs();
- return cs;
- }
- else {
- if (en == null) en = new en();
- return en;
- }
- }
-
- private static PluralRules cs;
- private static class cs extends PluralRules {
- int quantityForNumber(int n) {
- if (n == 1) {
- return QUANTITY_ONE;
- }
- else if (n >= 2 && n <= 4) {
- return QUANTITY_FEW;
- }
- else {
- return QUANTITY_OTHER;
- }
- }
- }
-
- private static PluralRules en;
- private static class en extends PluralRules {
- int quantityForNumber(int n) {
- if (n == 1) {
- return QUANTITY_ONE;
- }
- else {
- return QUANTITY_OTHER;
- }
- }
- }
-}
-
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
deleted file mode 100644
index 5a0daea..0000000
--- a/core/java/android/content/res/Resources.java
+++ /dev/null
@@ -1,1850 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res;
-
-
-import com.android.internal.util.XmlUtils;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.graphics.Movie;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.ColorDrawable;
-import android.os.Bundle;
-import android.os.SystemProperties;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.SparseArray;
-import android.util.TypedValue;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.ref.WeakReference;
-
-/**
- * Class for accessing an application's resources. This sits on top of the
- * asset manager of the application (accessible through getAssets()) and
- * provides a higher-level API for getting typed data from the assets.
- */
-public class Resources {
- static final String TAG = "Resources";
- private static final boolean DEBUG_LOAD = false;
- private static final boolean DEBUG_CONFIG = false;
-
- private static final int sSdkVersion = SystemProperties.getInt(
- "ro.build.version.sdk", 0);
- private static final Object mSync = new Object();
- private static Resources mSystem = null;
-
- // Information about preloaded resources. Note that they are not
- // protected by a lock, because while preloading in zygote we are all
- // single-threaded, and after that these are immutable.
- private static final SparseArray<Drawable.ConstantState> mPreloadedDrawables
- = new SparseArray<Drawable.ConstantState>();
- private static boolean mPreloaded;
-
- /*package*/ final TypedValue mTmpValue = new TypedValue();
-
- // These are protected by the mTmpValue lock.
- private final SparseArray<WeakReference<Drawable.ConstantState> > mDrawableCache
- = new SparseArray<WeakReference<Drawable.ConstantState> >();
- private final SparseArray<WeakReference<ColorStateList> > mColorStateListCache
- = new SparseArray<WeakReference<ColorStateList> >();
- private boolean mPreloading;
-
- /*package*/ TypedArray mCachedStyledAttributes = null;
-
- private int mLastCachedXmlBlockIndex = -1;
- private final int[] mCachedXmlBlockIds = { 0, 0, 0, 0 };
- private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[4];
-
- /*package*/ final AssetManager mAssets;
- private final Configuration mConfiguration = new Configuration();
- /*package*/ final DisplayMetrics mMetrics = new DisplayMetrics();
- PluralRules mPluralRule;
-
- /**
- * This exception is thrown by the resource APIs when a requested resource
- * can not be found.
- */
- public static class NotFoundException extends RuntimeException {
- public NotFoundException() {
- }
-
- public NotFoundException(String name) {
- super(name);
- }
- };
-
- /**
- * Create a new Resources object on top of an existing set of assets in an
- * AssetManager.
- *
- * @param assets Previously created AssetManager.
- * @param metrics Current display metrics to consider when
- * selecting/computing resource values.
- * @param config Desired device configuration to consider when
- * selecting/computing resource values (optional).
- */
- public Resources(AssetManager assets, DisplayMetrics metrics,
- Configuration config) {
- mAssets = assets;
- mConfiguration.setToDefaults();
- mMetrics.setToDefaults();
- updateConfiguration(config, metrics);
- assets.ensureStringBlocks();
- }
-
- /**
- * Return a global shared Resources object that provides access to only
- * system resources (no application resources), and is not configured for
- * the current screen (can not use dimension units, does not change based
- * on orientation, etc).
- */
- public static Resources getSystem() {
- synchronized (mSync) {
- Resources ret = mSystem;
- if (ret == null) {
- ret = new Resources();
- mSystem = ret;
- }
-
- return ret;
- }
- }
-
- /**
- * Return the string value associated with a particular resource ID. The
- * returned object will be a String if this is a plain string; it will be
- * some other type of CharSequence if it is styled.
- * {@more}
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return CharSequence The string data associated with the resource, plus
- * possibly styled text information.
- */
- public CharSequence getText(int id) throws NotFoundException {
- CharSequence res = mAssets.getResourceText(id);
- if (res != null) {
- return res;
- }
- throw new NotFoundException("String resource ID #0x"
- + Integer.toHexString(id));
- }
-
- /**
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return CharSequence The string data associated with the resource, plus
- * possibly styled text information.
- */
- public CharSequence getQuantityText(int id, int quantity) throws NotFoundException {
- PluralRules rule = getPluralRule();
- CharSequence res = mAssets.getResourceBagText(id, rule.attrForNumber(quantity));
- if (res != null) {
- return res;
- }
- res = mAssets.getResourceBagText(id, PluralRules.ID_OTHER);
- if (res != null) {
- return res;
- }
- throw new NotFoundException("Plural resource ID #0x" + Integer.toHexString(id)
- + " quantity=" + quantity
- + " item=" + PluralRules.stringForQuantity(rule.quantityForNumber(quantity)));
- }
-
- private PluralRules getPluralRule() {
- synchronized (mSync) {
- if (mPluralRule == null) {
- mPluralRule = PluralRules.ruleForLocale(mConfiguration.locale);
- }
- return mPluralRule;
- }
- }
-
- /**
- * Return the string value associated with a particular resource ID. It
- * will be stripped of any styled text information.
- * {@more}
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return String The string data associated with the resource,
- * stripped of styled text information.
- */
- public String getString(int id) throws NotFoundException {
- CharSequence res = getText(id);
- if (res != null) {
- return res.toString();
- }
- throw new NotFoundException("String resource ID #0x"
- + Integer.toHexString(id));
- }
-
-
- /**
- * Return the string value associated with a particular resource ID,
- * substituting the format arguments as defined in {@link java.util.Formatter}
- * and {@link java.lang.String#format}. It will be stripped of any styled text
- * information.
- * {@more}
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @param formatArgs The format arguments that will be used for substitution.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return String The string data associated with the resource,
- * stripped of styled text information.
- */
- public String getString(int id, Object... formatArgs) throws NotFoundException {
- String raw = getString(id);
- return String.format(mConfiguration.locale, raw, formatArgs);
- }
-
- /**
- * Return the string value associated with a particular resource ID for a particular
- * numerical quantity, substituting the format arguments as defined in
- * {@link java.util.Formatter} and {@link java.lang.String#format}. It will be
- * stripped of any styled text information.
- * {@more}
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- * @param quantity The number used to get the correct string for the current language's
- * plural rules.
- * @param formatArgs The format arguments that will be used for substitution.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return String The string data associated with the resource,
- * stripped of styled text information.
- */
- public String getQuantityString(int id, int quantity, Object... formatArgs)
- throws NotFoundException {
- String raw = getQuantityText(id, quantity).toString();
- return String.format(mConfiguration.locale, raw, formatArgs);
- }
-
- /**
- * Return the string value associated with a particular resource ID for a particular
- * numerical quantity.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- * @param quantity The number used to get the correct string for the current language's
- * plural rules.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return String The string data associated with the resource,
- * stripped of styled text information.
- */
- public String getQuantityString(int id, int quantity) throws NotFoundException {
- return getQuantityText(id, quantity).toString();
- }
-
- /**
- * Return the string value associated with a particular resource ID. The
- * returned object will be a String if this is a plain string; it will be
- * some other type of CharSequence if it is styled.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @param def The default CharSequence to return.
- *
- * @return CharSequence The string data associated with the resource, plus
- * possibly styled text information, or def if id is 0 or not found.
- */
- public CharSequence getText(int id, CharSequence def) {
- CharSequence res = id != 0 ? mAssets.getResourceText(id) : null;
- return res != null ? res : def;
- }
-
- /**
- * Return the styled text array associated with a particular resource ID.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return The styled text array associated with the resource.
- */
- public CharSequence[] getTextArray(int id) throws NotFoundException {
- CharSequence[] res = mAssets.getResourceTextArray(id);
- if (res != null) {
- return res;
- }
- throw new NotFoundException("Text array resource ID #0x"
- + Integer.toHexString(id));
- }
-
- /**
- * Return the string array associated with a particular resource ID.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return The string array associated with the resource.
- */
- public String[] getStringArray(int id) throws NotFoundException {
- String[] res = mAssets.getResourceStringArray(id);
- if (res != null) {
- return res;
- }
- throw new NotFoundException("String array resource ID #0x"
- + Integer.toHexString(id));
- }
-
- /**
- * Return the int array associated with a particular resource ID.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return The int array associated with the resource.
- */
- public int[] getIntArray(int id) throws NotFoundException {
- int[] res = mAssets.getArrayIntResource(id);
- if (res != null) {
- return res;
- }
- throw new NotFoundException("Int array resource ID #0x"
- + Integer.toHexString(id));
- }
-
- /**
- * Return an array of heterogeneous values.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return Returns a TypedArray holding an array of the array values.
- * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
- * when done with it.
- */
- public TypedArray obtainTypedArray(int id) throws NotFoundException {
- int len = mAssets.getArraySize(id);
- if (len < 0) {
- throw new NotFoundException("Array resource ID #0x"
- + Integer.toHexString(id));
- }
-
- TypedArray array = getCachedStyledAttributes(len);
- array.mLength = mAssets.retrieveArray(id, array.mData);
- array.mIndices[0] = 0;
-
- return array;
- }
-
- /**
- * Retrieve a dimensional for a particular resource ID. Unit
- * conversions are based on the current {@link DisplayMetrics} associated
- * with the resources.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @return Resource dimension value multiplied by the appropriate
- * metric.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @see #getDimensionPixelOffset
- * @see #getDimensionPixelSize
- */
- public float getDimension(int id) throws NotFoundException {
- synchronized (mTmpValue) {
- TypedValue value = mTmpValue;
- getValue(id, value, true);
- if (value.type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimension(value.data, mMetrics);
- }
- throw new NotFoundException(
- "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
- + Integer.toHexString(value.type) + " is not valid");
- }
- }
-
- /**
- * Retrieve a dimensional for a particular resource ID for use
- * as an offset in raw pixels. This is the same as
- * {@link #getDimension}, except the returned value is converted to
- * integer pixels for you. An offset conversion involves simply
- * truncating the base value to an integer.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @return Resource dimension value multiplied by the appropriate
- * metric and truncated to integer pixels.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @see #getDimension
- * @see #getDimensionPixelSize
- */
- public int getDimensionPixelOffset(int id) throws NotFoundException {
- synchronized (mTmpValue) {
- TypedValue value = mTmpValue;
- getValue(id, value, true);
- if (value.type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelOffset(
- value.data, mMetrics);
- }
- throw new NotFoundException(
- "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
- + Integer.toHexString(value.type) + " is not valid");
- }
- }
-
- /**
- * Retrieve a dimensional for a particular resource ID for use
- * as a size in raw pixels. This is the same as
- * {@link #getDimension}, except the returned value is converted to
- * integer pixels for use as a size. A size conversion involves
- * rounding the base value, and ensuring that a non-zero base value
- * is at least one pixel in size.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @return Resource dimension value multiplied by the appropriate
- * metric and truncated to integer pixels.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @see #getDimension
- * @see #getDimensionPixelOffset
- */
- public int getDimensionPixelSize(int id) throws NotFoundException {
- synchronized (mTmpValue) {
- TypedValue value = mTmpValue;
- getValue(id, value, true);
- if (value.type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelSize(
- value.data, mMetrics);
- }
- throw new NotFoundException(
- "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
- + Integer.toHexString(value.type) + " is not valid");
- }
- }
-
- /**
- * Retrieve a fractional unit for a particular resource ID.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- * @param base The base value of this fraction. In other words, a
- * standard fraction is multiplied by this value.
- * @param pbase The parent base value of this fraction. In other
- * words, a parent fraction (nn%p) is multiplied by this
- * value.
- *
- * @return Attribute fractional value multiplied by the appropriate
- * base value.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- */
- public float getFraction(int id, int base, int pbase) {
- synchronized (mTmpValue) {
- TypedValue value = mTmpValue;
- getValue(id, value, true);
- if (value.type == TypedValue.TYPE_FRACTION) {
- return TypedValue.complexToFraction(value.data, base, pbase);
- }
- throw new NotFoundException(
- "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
- + Integer.toHexString(value.type) + " is not valid");
- }
- }
-
- /**
- * Return a drawable object associated with a particular resource ID.
- * Various types of objects will be returned depending on the underlying
- * resource -- for example, a solid color, PNG image, scalable image, etc.
- * The Drawable API hides these implementation details.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return Drawable An object that can be used to draw this resource.
- */
- public Drawable getDrawable(int id) throws NotFoundException {
- synchronized (mTmpValue) {
- TypedValue value = mTmpValue;
- getValue(id, value, true);
- return loadDrawable(value, id);
- }
- }
-
- /**
- * Return a movie object associated with the particular resource ID.
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- */
- public Movie getMovie(int id) throws NotFoundException {
- InputStream is = openRawResource(id);
- Movie movie = Movie.decodeStream(is);
- try {
- is.close();
- }
- catch (java.io.IOException e) {
- // don't care, since the return value is valid
- }
- return movie;
- }
-
- /**
- * Return a color integer associated with a particular resource ID.
- * If the resource holds a complex
- * {@link android.content.res.ColorStateList}, then the default color from
- * the set is returned.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return Returns a single color value in the form 0xAARRGGBB.
- */
- public int getColor(int id) throws NotFoundException {
- synchronized (mTmpValue) {
- TypedValue value = mTmpValue;
- getValue(id, value, true);
- if (value.type >= TypedValue.TYPE_FIRST_INT
- && value.type <= TypedValue.TYPE_LAST_INT) {
- return value.data;
- } else if (value.type == TypedValue.TYPE_STRING) {
- ColorStateList csl = loadColorStateList(mTmpValue, id);
- return csl.getDefaultColor();
- }
- throw new NotFoundException(
- "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
- + Integer.toHexString(value.type) + " is not valid");
- }
- }
-
- /**
- * Return a color state list associated with a particular resource ID. The
- * resource may contain either a single raw color value, or a complex
- * {@link android.content.res.ColorStateList} holding multiple possible colors.
- *
- * @param id The desired resource identifier of a {@link ColorStateList},
- * as generated by the aapt tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return Returns a ColorStateList object containing either a single
- * solid color or multiple colors that can be selected based on a state.
- */
- public ColorStateList getColorStateList(int id) throws NotFoundException {
- synchronized (mTmpValue) {
- TypedValue value = mTmpValue;
- getValue(id, value, true);
- return loadColorStateList(value, id);
- }
- }
-
- /**
- * Return a boolean associated with a particular resource ID. This can be
- * used with any integral resource value, and will return true if it is
- * non-zero.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return Returns the boolean value contained in the resource.
- */
- public boolean getBoolean(int id) throws NotFoundException {
- synchronized (mTmpValue) {
- TypedValue value = mTmpValue;
- getValue(id, value, true);
- if (value.type >= TypedValue.TYPE_FIRST_INT
- && value.type <= TypedValue.TYPE_LAST_INT) {
- return value.data != 0;
- }
- throw new NotFoundException(
- "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
- + Integer.toHexString(value.type) + " is not valid");
- }
- }
-
- /**
- * Return an integer associated with a particular resource ID.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return Returns the integer value contained in the resource.
- */
- public int getInteger(int id) throws NotFoundException {
- synchronized (mTmpValue) {
- TypedValue value = mTmpValue;
- getValue(id, value, true);
- if (value.type >= TypedValue.TYPE_FIRST_INT
- && value.type <= TypedValue.TYPE_LAST_INT) {
- return value.data;
- }
- throw new NotFoundException(
- "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
- + Integer.toHexString(value.type) + " is not valid");
- }
- }
-
- /**
- * Return an XmlResourceParser through which you can read a view layout
- * description for the given resource ID. This parser has limited
- * functionality -- in particular, you can't change its input, and only
- * the high-level events are available.
- *
- * <p>This function is really a simple wrapper for calling
- * {@link #getXml} with a layout resource.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return A new parser object through which you can read
- * the XML data.
- *
- * @see #getXml
- */
- public XmlResourceParser getLayout(int id) throws NotFoundException {
- return loadXmlResourceParser(id, "layout");
- }
-
- /**
- * Return an XmlResourceParser through which you can read an animation
- * description for the given resource ID. This parser has limited
- * functionality -- in particular, you can't change its input, and only
- * the high-level events are available.
- *
- * <p>This function is really a simple wrapper for calling
- * {@link #getXml} with an animation resource.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return A new parser object through which you can read
- * the XML data.
- *
- * @see #getXml
- */
- public XmlResourceParser getAnimation(int id) throws NotFoundException {
- return loadXmlResourceParser(id, "anim");
- }
-
- /**
- * Return an XmlResourceParser through which you can read a generic XML
- * resource for the given resource ID.
- *
- * <p>The XmlPullParser implementation returned here has some limited
- * functionality. In particular, you can't change its input, and only
- * high-level parsing events are available (since the document was
- * pre-parsed for you at build time, which involved merging text and
- * stripping comments).
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return A new parser object through which you can read
- * the XML data.
- *
- * @see android.util.AttributeSet
- */
- public XmlResourceParser getXml(int id) throws NotFoundException {
- return loadXmlResourceParser(id, "xml");
- }
-
- /**
- * Open a data stream for reading a raw resource. This can only be used
- * with resources whose value is the name of an asset files -- that is, it can be
- * used to open drawable, sound, and raw resources; it will fail on string
- * and color resources.
- *
- * @param id The resource identifier to open, as generated by the appt
- * tool.
- *
- * @return InputStream Access to the resource data.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- */
- public InputStream openRawResource(int id) throws NotFoundException {
- synchronized (mTmpValue) {
- return openRawResource(id, mTmpValue);
- }
- }
-
- /**
- * Open a data stream for reading a raw resource. This can only be used
- * with resources whose value is the name of an asset files -- that is, it can be
- * used to open drawable, sound, and raw resources; it will fail on string
- * and color resources.
- *
- * @param id The resource identifier to open, as generated by the appt tool.
- * @param value The TypedValue object to hold the resource information.
- *
- * @return InputStream Access to the resource data.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @hide Pending API council approval
- */
- public InputStream openRawResource(int id, TypedValue value) throws NotFoundException {
- getValue(id, value, true);
-
- try {
- return mAssets.openNonAsset(value.assetCookie, value.string.toString(),
- AssetManager.ACCESS_STREAMING);
- } catch (Exception e) {
- NotFoundException rnf = new NotFoundException("File " + value.string.toString() +
- " from drawable resource ID #0x" + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
- }
-
- /**
- * Open a file descriptor for reading a raw resource. This can only be used
- * with resources whose value is the name of an asset files -- that is, it can be
- * used to open drawable, sound, and raw resources; it will fail on string
- * and color resources.
- *
- * <p>This function only works for resources that are stored in the package
- * as uncompressed data, which typically includes things like mp3 files
- * and png images.
- *
- * @param id The resource identifier to open, as generated by the appt
- * tool.
- *
- * @return AssetFileDescriptor A new file descriptor you can use to read
- * the resource. This includes the file descriptor itself, as well as the
- * offset and length of data where the resource appears in the file. A
- * null is returned if the file exists but is compressed.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- */
- public AssetFileDescriptor openRawResourceFd(int id) throws NotFoundException {
- synchronized (mTmpValue) {
- TypedValue value = mTmpValue;
- getValue(id, value, true);
-
- try {
- return mAssets.openNonAssetFd(
- value.assetCookie, value.string.toString());
- } catch (Exception e) {
- NotFoundException rnf = new NotFoundException(
- "File " + value.string.toString()
- + " from drawable resource ID #0x"
- + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
-
- }
- }
-
- /**
- * Return the raw data associated with a particular resource ID.
- *
- * @param id The desired resource identifier, as generated by the aapt
- * tool. This integer encodes the package, type, and resource
- * entry. The value 0 is an invalid identifier.
- * @param outValue Object in which to place the resource data.
- * @param resolveRefs If true, a resource that is a reference to another
- * resource will be followed so that you receive the
- * actual final resource data. If false, the TypedValue
- * will be filled in with the reference itself.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- */
- public void getValue(int id, TypedValue outValue, boolean resolveRefs)
- throws NotFoundException {
- boolean found = mAssets.getResourceValue(id, outValue, resolveRefs);
- if (found) {
- return;
- }
- throw new NotFoundException("Resource ID #0x"
- + Integer.toHexString(id));
- }
-
- /**
- * Return the raw data associated with a particular resource ID.
- * See getIdentifier() for information on how names are mapped to resource
- * IDs, and getString(int) for information on how string resources are
- * retrieved.
- *
- * <p>Note: use of this function is discouraged. It is much more
- * efficient to retrieve resources by identifier than by name.
- *
- * @param name The name of the desired resource. This is passed to
- * getIdentifier() with a default type of "string".
- * @param outValue Object in which to place the resource data.
- * @param resolveRefs If true, a resource that is a reference to another
- * resource will be followed so that you receive the
- * actual final resource data. If false, the TypedValue
- * will be filled in with the reference itself.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- */
- public void getValue(String name, TypedValue outValue, boolean resolveRefs)
- throws NotFoundException {
- int id = getIdentifier(name, "string", null);
- if (id != 0) {
- getValue(id, outValue, resolveRefs);
- return;
- }
- throw new NotFoundException("String resource name " + name);
- }
-
- /**
- * This class holds the current attribute values for a particular theme.
- * In other words, a Theme is a set of values for resource attributes;
- * these are used in conjunction with {@link TypedArray}
- * to resolve the final value for an attribute.
- *
- * <p>The Theme's attributes come into play in two ways: (1) a styled
- * attribute can explicit reference a value in the theme through the
- * "?themeAttribute" syntax; (2) if no value has been defined for a
- * particular styled attribute, as a last resort we will try to find that
- * attribute's value in the Theme.
- *
- * <p>You will normally use the {@link #obtainStyledAttributes} APIs to
- * retrieve XML attributes with style and theme information applied.
- */
- public final class Theme {
- /**
- * Place new attribute values into the theme. The style resource
- * specified by <var>resid</var> will be retrieved from this Theme's
- * resources, its values placed into the Theme object.
- *
- * <p>The semantics of this function depends on the <var>force</var>
- * argument: If false, only values that are not already defined in
- * the theme will be copied from the system resource; otherwise, if
- * any of the style's attributes are already defined in the theme, the
- * current values in the theme will be overwritten.
- *
- * @param resid The resource ID of a style resource from which to
- * obtain attribute values.
- * @param force If true, values in the style resource will always be
- * used in the theme; otherwise, they will only be used
- * if not already defined in the theme.
- */
- public void applyStyle(int resid, boolean force) {
- AssetManager.applyThemeStyle(mTheme, resid, force);
- }
-
- /**
- * Set this theme to hold the same contents as the theme
- * <var>other</var>. If both of these themes are from the same
- * Resources object, they will be identical after this function
- * returns. If they are from different Resources, only the resources
- * they have in common will be set in this theme.
- *
- * @param other The existing Theme to copy from.
- */
- public void setTo(Theme other) {
- AssetManager.copyTheme(mTheme, other.mTheme);
- }
-
- /**
- * Return a StyledAttributes holding the values defined by
- * <var>Theme</var> which are listed in <var>attrs</var>.
- *
- * <p>Be sure to call StyledAttributes.recycle() when you are done with
- * the array.
- *
- * @param attrs The desired attributes.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return Returns a TypedArray holding an array of the attribute values.
- * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
- * when done with it.
- *
- * @see Resources#obtainAttributes
- * @see #obtainStyledAttributes(int, int[])
- * @see #obtainStyledAttributes(AttributeSet, int[], int, int)
- */
- public TypedArray obtainStyledAttributes(int[] attrs) {
- int len = attrs.length;
- TypedArray array = getCachedStyledAttributes(len);
- array.mRsrcs = attrs;
- AssetManager.applyStyle(mTheme, 0, 0, 0, attrs,
- array.mData, array.mIndices);
- return array;
- }
-
- /**
- * Return a StyledAttributes holding the values defined by the style
- * resource <var>resid</var> which are listed in <var>attrs</var>.
- *
- * <p>Be sure to call StyledAttributes.recycle() when you are done with
- * the array.
- *
- * @param resid The desired style resource.
- * @param attrs The desired attributes in the style.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @return Returns a TypedArray holding an array of the attribute values.
- * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
- * when done with it.
- *
- * @see Resources#obtainAttributes
- * @see #obtainStyledAttributes(int[])
- * @see #obtainStyledAttributes(AttributeSet, int[], int, int)
- */
- public TypedArray obtainStyledAttributes(int resid, int[] attrs)
- throws NotFoundException {
- int len = attrs.length;
- TypedArray array = getCachedStyledAttributes(len);
- array.mRsrcs = attrs;
-
- AssetManager.applyStyle(mTheme, 0, resid, 0, attrs,
- array.mData, array.mIndices);
- if (false) {
- int[] data = array.mData;
-
- System.out.println("**********************************************************");
- System.out.println("**********************************************************");
- System.out.println("**********************************************************");
- System.out.println("Attributes:");
- String s = " Attrs:";
- int i;
- for (i=0; i<attrs.length; i++) {
- s = s + " 0x" + Integer.toHexString(attrs[i]);
- }
- System.out.println(s);
- s = " Found:";
- TypedValue value = new TypedValue();
- for (i=0; i<attrs.length; i++) {
- int d = i*AssetManager.STYLE_NUM_ENTRIES;
- value.type = data[d+AssetManager.STYLE_TYPE];
- value.data = data[d+AssetManager.STYLE_DATA];
- value.assetCookie = data[d+AssetManager.STYLE_ASSET_COOKIE];
- value.resourceId = data[d+AssetManager.STYLE_RESOURCE_ID];
- s = s + " 0x" + Integer.toHexString(attrs[i])
- + "=" + value;
- }
- System.out.println(s);
- }
- return array;
- }
-
- /**
- * Return a StyledAttributes holding the attribute values in
- * <var>set</var>
- * that are listed in <var>attrs</var>. In addition, if the given
- * AttributeSet specifies a style class (through the "style" attribute),
- * that style will be applied on top of the base attributes it defines.
- *
- * <p>Be sure to call StyledAttributes.recycle() when you are done with
- * the array.
- *
- * <p>When determining the final value of a particular attribute, there
- * are four inputs that come into play:</p>
- *
- * <ol>
- * <li> Any attribute values in the given AttributeSet.
- * <li> The style resource specified in the AttributeSet (named
- * "style").
- * <li> The default style specified by <var>defStyleAttr</var> and
- * <var>defStyleRes</var>
- * <li> The base values in this theme.
- * </ol>
- *
- * <p>Each of these inputs is considered in-order, with the first listed
- * taking precedence over the following ones. In other words, if in the
- * AttributeSet you have supplied <code>&lt;Button
- * textColor="#ff000000"&gt;</code>, then the button's text will
- * <em>always</em> be black, regardless of what is specified in any of
- * the styles.
- *
- * @param set The base set of attribute values. May be null.
- * @param attrs The desired attributes to be retrieved.
- * @param defStyleAttr An attribute in the current theme that contains a
- * reference to a style resource that supplies
- * defaults values for the StyledAttributes. Can be
- * 0 to not look for defaults.
- * @param defStyleRes A resource identifier of a style resource that
- * supplies default values for the StyledAttributes,
- * used only if defStyleAttr is 0 or can not be found
- * in the theme. Can be 0 to not look for defaults.
- *
- * @return Returns a TypedArray holding an array of the attribute values.
- * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
- * when done with it.
- *
- * @see Resources#obtainAttributes
- * @see #obtainStyledAttributes(int[])
- * @see #obtainStyledAttributes(int, int[])
- */
- public TypedArray obtainStyledAttributes(AttributeSet set,
- int[] attrs, int defStyleAttr, int defStyleRes) {
- int len = attrs.length;
- TypedArray array = getCachedStyledAttributes(len);
-
- // XXX note that for now we only work with compiled XML files.
- // To support generic XML files we will need to manually parse
- // out the attributes from the XML file (applying type information
- // contained in the resources and such).
- XmlBlock.Parser parser = (XmlBlock.Parser)set;
- AssetManager.applyStyle(
- mTheme, defStyleAttr, defStyleRes,
- parser != null ? parser.mParseState : 0, attrs,
- array.mData, array.mIndices);
-
- array.mRsrcs = attrs;
- array.mXml = parser;
-
- if (false) {
- int[] data = array.mData;
-
- System.out.println("Attributes:");
- String s = " Attrs:";
- int i;
- for (i=0; i<set.getAttributeCount(); i++) {
- s = s + " " + set.getAttributeName(i);
- int id = set.getAttributeNameResource(i);
- if (id != 0) {
- s = s + "(0x" + Integer.toHexString(id) + ")";
- }
- s = s + "=" + set.getAttributeValue(i);
- }
- System.out.println(s);
- s = " Found:";
- TypedValue value = new TypedValue();
- for (i=0; i<attrs.length; i++) {
- int d = i*AssetManager.STYLE_NUM_ENTRIES;
- value.type = data[d+AssetManager.STYLE_TYPE];
- value.data = data[d+AssetManager.STYLE_DATA];
- value.assetCookie = data[d+AssetManager.STYLE_ASSET_COOKIE];
- value.resourceId = data[d+AssetManager.STYLE_RESOURCE_ID];
- s = s + " 0x" + Integer.toHexString(attrs[i])
- + "=" + value;
- }
- System.out.println(s);
- }
-
- return array;
- }
-
- /**
- * Retrieve the value of an attribute in the Theme. The contents of
- * <var>outValue</var> are ultimately filled in by
- * {@link Resources#getValue}.
- *
- * @param resid The resource identifier of the desired theme
- * attribute.
- * @param outValue Filled in with the ultimate resource value supplied
- * by the attribute.
- * @param resolveRefs If true, resource references will be walked; if
- * false, <var>outValue</var> may be a
- * TYPE_REFERENCE. In either case, it will never
- * be a TYPE_ATTRIBUTE.
- *
- * @return boolean Returns true if the attribute was found and
- * <var>outValue</var> is valid, else false.
- */
- public boolean resolveAttribute(int resid, TypedValue outValue,
- boolean resolveRefs) {
- boolean got = mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs);
- if (false) {
- System.out.println(
- "resolveAttribute #" + Integer.toHexString(resid)
- + " got=" + got + ", type=0x" + Integer.toHexString(outValue.type)
- + ", data=0x" + Integer.toHexString(outValue.data));
- }
- return got;
- }
-
- /**
- * Print contents of this theme out to the log. For debugging only.
- *
- * @param priority The log priority to use.
- * @param tag The log tag to use.
- * @param prefix Text to prefix each line printed.
- */
- public void dump(int priority, String tag, String prefix) {
- AssetManager.dumpTheme(mTheme, priority, tag, prefix);
- }
-
- protected void finalize() throws Throwable {
- super.finalize();
- mAssets.releaseTheme(mTheme);
- }
-
- /*package*/ Theme() {
- mAssets = Resources.this.mAssets;
- mTheme = mAssets.createTheme();
- }
-
- private final AssetManager mAssets;
- private final int mTheme;
- }
-
- /**
- * Generate a new Theme object for this set of Resources. It initially
- * starts out empty.
- *
- * @return Theme The newly created Theme container.
- */
- public final Theme newTheme() {
- return new Theme();
- }
-
- /**
- * Retrieve a set of basic attribute values from an AttributeSet, not
- * performing styling of them using a theme and/or style resources.
- *
- * @param set The current attribute values to retrieve.
- * @param attrs The specific attributes to be retrieved.
- * @return Returns a TypedArray holding an array of the attribute values.
- * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
- * when done with it.
- *
- * @see Theme#obtainStyledAttributes(AttributeSet, int[], int, int)
- */
- public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
- int len = attrs.length;
- TypedArray array = getCachedStyledAttributes(len);
-
- // XXX note that for now we only work with compiled XML files.
- // To support generic XML files we will need to manually parse
- // out the attributes from the XML file (applying type information
- // contained in the resources and such).
- XmlBlock.Parser parser = (XmlBlock.Parser)set;
- mAssets.retrieveAttributes(parser.mParseState, attrs,
- array.mData, array.mIndices);
-
- array.mRsrcs = attrs;
- array.mXml = parser;
-
- return array;
- }
-
- /**
- * Store the newly updated configuration.
- */
- public void updateConfiguration(Configuration config,
- DisplayMetrics metrics) {
- synchronized (mTmpValue) {
- int configChanges = 0xfffffff;
- if (config != null) {
- configChanges = mConfiguration.updateFrom(config);
- }
- if (metrics != null) {
- mMetrics.setTo(metrics);
- }
- mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
- String locale = null;
- if (mConfiguration.locale != null) {
- locale = mConfiguration.locale.getLanguage();
- if (mConfiguration.locale.getCountry() != null) {
- locale += "-" + mConfiguration.locale.getCountry();
- }
- }
- int width, height;
- if (mMetrics.widthPixels >= mMetrics.heightPixels) {
- width = mMetrics.widthPixels;
- height = mMetrics.heightPixels;
- } else {
- width = mMetrics.heightPixels;
- height = mMetrics.widthPixels;
- }
- int keyboardHidden = mConfiguration.keyboardHidden;
- if (keyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO
- && mConfiguration.hardKeyboardHidden
- == Configuration.HARDKEYBOARDHIDDEN_YES) {
- keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT;
- }
- mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
- locale, mConfiguration.orientation,
- mConfiguration.touchscreen,
- (int)(mMetrics.density*160), mConfiguration.keyboard,
- keyboardHidden, mConfiguration.navigation, width, height,
- sSdkVersion);
- int N = mDrawableCache.size();
- if (DEBUG_CONFIG) {
- Log.d(TAG, "Cleaning up drawables config changes: 0x"
- + Integer.toHexString(configChanges));
- }
- for (int i=0; i<N; i++) {
- WeakReference<Drawable.ConstantState> ref = mDrawableCache.valueAt(i);
- if (ref != null) {
- Drawable.ConstantState cs = ref.get();
- if (cs != null) {
- if (Configuration.needNewResources(
- configChanges, cs.getChangingConfigurations())) {
- if (DEBUG_CONFIG) {
- Log.d(TAG, "FLUSHING #0x"
- + Integer.toHexString(mDrawableCache.keyAt(i))
- + " / " + cs + " with changes: 0x"
- + Integer.toHexString(cs.getChangingConfigurations()));
- }
- mDrawableCache.setValueAt(i, null);
- } else if (DEBUG_CONFIG) {
- Log.d(TAG, "(Keeping #0x"
- + Integer.toHexString(mDrawableCache.keyAt(i))
- + " / " + cs + " with changes: 0x"
- + Integer.toHexString(cs.getChangingConfigurations())
- + ")");
- }
- }
- }
- }
- mDrawableCache.clear();
- mColorStateListCache.clear();
- flushLayoutCache();
- }
- synchronized (mSync) {
- if (mPluralRule != null) {
- mPluralRule = PluralRules.ruleForLocale(config.locale);
- }
- }
- }
-
- /**
- * Update the system resources configuration if they have previously
- * been initialized.
- *
- * @hide
- */
- public static void updateSystemConfiguration(Configuration config, DisplayMetrics metrics) {
- if (mSystem != null) {
- mSystem.updateConfiguration(config, metrics);
- //Log.i(TAG, "Updated system resources " + mSystem
- // + ": " + mSystem.getConfiguration());
- }
- }
-
- /**
- * Return the current display metrics that are in effect for this resource
- * object. The returned object should be treated as read-only.
- *
- * @return The resource's current display metrics.
- */
- public DisplayMetrics getDisplayMetrics() {
- return mMetrics;
- }
-
- /**
- * Return the current configuration that is in effect for this resource
- * object. The returned object should be treated as read-only.
- *
- * @return The resource's current configuration.
- */
- public Configuration getConfiguration() {
- return mConfiguration;
- }
-
- /**
- * Return a resource identifier for the given resource name. A fully
- * qualified resource name is of the form "package:type/entry". The first
- * two components (package and type) are optional if defType and
- * defPackage, respectively, are specified here.
- *
- * <p>Note: use of this function is discouraged. It is much more
- * efficient to retrieve resources by identifier than by name.
- *
- * @param name The name of the desired resource.
- * @param defType Optional default resource type to find, if "type/" is
- * not included in the name. Can be null to require an
- * explicit type.
- * @param defPackage Optional default package to find, if "package:" is
- * not included in the name. Can be null to require an
- * explicit package.
- *
- * @return int The associated resource identifier. Returns 0 if no such
- * resource was found. (0 is not a valid resource ID.)
- */
- public int getIdentifier(String name, String defType, String defPackage) {
- try {
- return Integer.parseInt(name);
- } catch (Exception e) {
- }
- return mAssets.getResourceIdentifier(name, defType, defPackage);
- }
-
- /**
- * Return the full name for a given resource identifier. This name is
- * a single string of the form "package:type/entry".
- *
- * @param resid The resource identifier whose name is to be retrieved.
- *
- * @return A string holding the name of the resource.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @see #getResourcePackageName
- * @see #getResourceTypeName
- * @see #getResourceEntryName
- */
- public String getResourceName(int resid) throws NotFoundException {
- String str = mAssets.getResourceName(resid);
- if (str != null) return str;
- throw new NotFoundException("Unable to find resource ID #0x"
- + Integer.toHexString(resid));
- }
-
- /**
- * Return the package name for a given resource identifier.
- *
- * @param resid The resource identifier whose package name is to be
- * retrieved.
- *
- * @return A string holding the package name of the resource.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @see #getResourceName
- */
- public String getResourcePackageName(int resid) throws NotFoundException {
- String str = mAssets.getResourcePackageName(resid);
- if (str != null) return str;
- throw new NotFoundException("Unable to find resource ID #0x"
- + Integer.toHexString(resid));
- }
-
- /**
- * Return the type name for a given resource identifier.
- *
- * @param resid The resource identifier whose type name is to be
- * retrieved.
- *
- * @return A string holding the type name of the resource.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @see #getResourceName
- */
- public String getResourceTypeName(int resid) throws NotFoundException {
- String str = mAssets.getResourceTypeName(resid);
- if (str != null) return str;
- throw new NotFoundException("Unable to find resource ID #0x"
- + Integer.toHexString(resid));
- }
-
- /**
- * Return the entry name for a given resource identifier.
- *
- * @param resid The resource identifier whose entry name is to be
- * retrieved.
- *
- * @return A string holding the entry name of the resource.
- *
- * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
- *
- * @see #getResourceName
- */
- public String getResourceEntryName(int resid) throws NotFoundException {
- String str = mAssets.getResourceEntryName(resid);
- if (str != null) return str;
- throw new NotFoundException("Unable to find resource ID #0x"
- + Integer.toHexString(resid));
- }
-
- /**
- * Parse a series of {@link android.R.styleable#Extra &lt;extra&gt;} tags from
- * an XML file. You call this when you are at the parent tag of the
- * extra tags, and it return once all of the child tags have been parsed.
- * This will call {@link #parseBundleExtra} for each extra tag encountered.
- *
- * @param parser The parser from which to retrieve the extras.
- * @param outBundle A Bundle in which to place all parsed extras.
- * @throws XmlPullParserException
- * @throws IOException
- */
- public void parseBundleExtras(XmlResourceParser parser, Bundle outBundle)
- throws XmlPullParserException, IOException {
- int outerDepth = parser.getDepth();
- int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
-
- String nodeName = parser.getName();
- if (nodeName.equals("extra")) {
- parseBundleExtra("extra", parser, outBundle);
- XmlUtils.skipCurrentTag(parser);
-
- } else {
- XmlUtils.skipCurrentTag(parser);
- }
- }
- }
-
- /**
- * Parse a name/value pair out of an XML tag holding that data. The
- * AttributeSet must be holding the data defined by
- * {@link android.R.styleable#Extra}. The following value types are supported:
- * <ul>
- * <li> {@link TypedValue#TYPE_STRING}:
- * {@link Bundle#putCharSequence Bundle.putCharSequence()}
- * <li> {@link TypedValue#TYPE_INT_BOOLEAN}:
- * {@link Bundle#putCharSequence Bundle.putBoolean()}
- * <li> {@link TypedValue#TYPE_FIRST_INT}-{@link TypedValue#TYPE_LAST_INT}:
- * {@link Bundle#putCharSequence Bundle.putBoolean()}
- * <li> {@link TypedValue#TYPE_FLOAT}:
- * {@link Bundle#putCharSequence Bundle.putFloat()}
- * </ul>
- *
- * @param tagName The name of the tag these attributes come from; this is
- * only used for reporting error messages.
- * @param attrs The attributes from which to retrieve the name/value pair.
- * @param outBundle The Bundle in which to place the parsed value.
- * @throws XmlPullParserException If the attributes are not valid.
- */
- public void parseBundleExtra(String tagName, AttributeSet attrs,
- Bundle outBundle) throws XmlPullParserException {
- TypedArray sa = obtainAttributes(attrs,
- com.android.internal.R.styleable.Extra);
-
- String name = sa.getString(
- com.android.internal.R.styleable.Extra_name);
- if (name == null) {
- sa.recycle();
- throw new XmlPullParserException("<" + tagName
- + "> requires an android:name attribute at "
- + attrs.getPositionDescription());
- }
-
- TypedValue v = sa.peekValue(
- com.android.internal.R.styleable.Extra_value);
- if (v != null) {
- if (v.type == TypedValue.TYPE_STRING) {
- CharSequence cs = v.coerceToString();
- outBundle.putCharSequence(name, cs);
- } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
- outBundle.putBoolean(name, v.data != 0);
- } else if (v.type >= TypedValue.TYPE_FIRST_INT
- && v.type <= TypedValue.TYPE_LAST_INT) {
- outBundle.putInt(name, v.data);
- } else if (v.type == TypedValue.TYPE_FLOAT) {
- outBundle.putFloat(name, v.getFloat());
- } else {
- sa.recycle();
- throw new XmlPullParserException("<" + tagName
- + "> only supports string, integer, float, color, and boolean at "
- + attrs.getPositionDescription());
- }
- } else {
- sa.recycle();
- throw new XmlPullParserException("<" + tagName
- + "> requires an android:value or android:resource attribute at "
- + attrs.getPositionDescription());
- }
-
- sa.recycle();
- }
-
- /**
- * Retrieve underlying AssetManager storage for these resources.
- */
- public final AssetManager getAssets() {
- return mAssets;
- }
-
- /**
- * Call this to remove all cached loaded layout resources from the
- * Resources object. Only intended for use with performance testing
- * tools.
- */
- public final void flushLayoutCache() {
- synchronized (mCachedXmlBlockIds) {
- // First see if this block is in our cache.
- final int num = mCachedXmlBlockIds.length;
- for (int i=0; i<num; i++) {
- mCachedXmlBlockIds[i] = -0;
- XmlBlock oldBlock = mCachedXmlBlocks[i];
- if (oldBlock != null) {
- oldBlock.close();
- }
- mCachedXmlBlocks[i] = null;
- }
- }
- }
-
- /**
- * Start preloading of resource data using this Resources object. Only
- * for use by the zygote process for loading common system resources.
- * {@hide}
- */
- public final void startPreloading() {
- synchronized (mSync) {
- if (mPreloaded) {
- throw new IllegalStateException("Resources already preloaded");
- }
- mPreloaded = true;
- mPreloading = true;
- }
- }
-
- /**
- * Called by zygote when it is done preloading resources, to change back
- * to normal Resources operation.
- */
- public final void finishPreloading() {
- if (mPreloading) {
- mPreloading = false;
- flushLayoutCache();
- }
- }
-
- /*package*/ Drawable loadDrawable(TypedValue value, int id)
- throws NotFoundException {
- if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
- && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
- // Should we be caching these? If we use constant colors much
- // at all, most likely...
- //System.out.println("Creating drawable for color: #" +
- // Integer.toHexString(value.data));
- Drawable dr = new ColorDrawable(value.data);
- dr.setChangingConfigurations(value.changingConfigurations);
- return dr;
- }
-
- final int key = (value.assetCookie<<24)|value.data;
- Drawable dr = getCachedDrawable(key);
- //System.out.println("Cached drawable @ #" +
- // Integer.toHexString(key.intValue()) + ": " + dr);
- if (dr != null) {
- return dr;
- }
-
- Drawable.ConstantState cs = mPreloadedDrawables.get(key);
- if (cs != null) {
- dr = cs.newDrawable();
-
- } else {
- if (value.string == null) {
- throw new NotFoundException(
- "Resource is not a Drawable (color or path): " + value);
- }
-
- String file = value.string.toString();
-
- if (DEBUG_LOAD) Log.v(TAG, "Loading drawable for cookie "
- + value.assetCookie + ": " + file);
-
- if (file.endsWith(".xml")) {
- try {
- XmlResourceParser rp = loadXmlResourceParser(
- file, id, value.assetCookie, "drawable");
- dr = Drawable.createFromXml(this, rp);
- rp.close();
- } catch (Exception e) {
- NotFoundException rnf = new NotFoundException(
- "File " + file + " from drawable resource ID #0x"
- + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
-
- } else {
- try {
- InputStream is = mAssets.openNonAsset(
- value.assetCookie, file, AssetManager.ACCESS_BUFFER);
- // System.out.println("Opened file " + file + ": " + is);
- dr = Drawable.createFromResourceStream(this, value, is, file);
- is.close();
- // System.out.println("Created stream: " + dr);
- } catch (Exception e) {
- NotFoundException rnf = new NotFoundException(
- "File " + file + " from drawable resource ID #0x"
- + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
- }
- }
-
- if (dr != null) {
- dr.setChangingConfigurations(value.changingConfigurations);
- cs = dr.getConstantState();
- if (cs != null) {
- if (mPreloading) {
- mPreloadedDrawables.put(key, cs);
- }
- synchronized (mTmpValue) {
- //Log.i(TAG, "Saving cached drawable @ #" +
- // Integer.toHexString(key.intValue())
- // + " in " + this + ": " + cs);
- mDrawableCache.put(
- key, new WeakReference<Drawable.ConstantState>(cs));
- }
- }
- }
-
- return dr;
- }
-
- private final Drawable getCachedDrawable(int key) {
- synchronized (mTmpValue) {
- WeakReference<Drawable.ConstantState> wr = mDrawableCache.get(key);
- if (wr != null) { // we have the key
- Drawable.ConstantState entry = wr.get();
- if (entry != null) {
- //Log.i(TAG, "Returning cached drawable @ #" +
- // Integer.toHexString(((Integer)key).intValue())
- // + " in " + this + ": " + entry);
- return entry.newDrawable();
- }
- else { // our entry has been purged
- mDrawableCache.delete(key);
- }
- }
- }
- return null;
- }
-
- /*package*/ ColorStateList loadColorStateList(TypedValue value, int id)
- throws NotFoundException {
- if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
- && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
- return ColorStateList.valueOf(value.data);
- }
-
- final int key = (value.assetCookie<<24)|value.data;
- ColorStateList csl = getCachedColorStateList(key);
- if (csl != null) {
- return csl;
- }
-
- if (value.string == null) {
- throw new NotFoundException(
- "Resource is not a ColorStateList (color or path): " + value);
- }
-
- String file = value.string.toString();
-
- if (file.endsWith(".xml")) {
- try {
- XmlResourceParser rp = loadXmlResourceParser(
- file, id, value.assetCookie, "colorstatelist");
- csl = ColorStateList.createFromXml(this, rp);
- rp.close();
- } catch (Exception e) {
- NotFoundException rnf = new NotFoundException(
- "File " + file + " from color state list resource ID #0x"
- + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
- } else {
- throw new NotFoundException(
- "File " + file + " from drawable resource ID #0x"
- + Integer.toHexString(id) + ": .xml extension required");
- }
-
- if (csl != null) {
- synchronized (mTmpValue) {
- //Log.i(TAG, "Saving cached color state list @ #" +
- // Integer.toHexString(key.intValue())
- // + " in " + this + ": " + csl);
- mColorStateListCache.put(
- key, new WeakReference<ColorStateList>(csl));
- }
- }
-
- return csl;
- }
-
- private ColorStateList getCachedColorStateList(int key) {
- synchronized (mTmpValue) {
- WeakReference<ColorStateList> wr = mColorStateListCache.get(key);
- if (wr != null) { // we have the key
- ColorStateList entry = wr.get();
- if (entry != null) {
- //Log.i(TAG, "Returning cached color state list @ #" +
- // Integer.toHexString(((Integer)key).intValue())
- // + " in " + this + ": " + entry);
- return entry;
- }
- else { // our entry has been purged
- mColorStateListCache.delete(key);
- }
- }
- }
- return null;
- }
-
- /*package*/ XmlResourceParser loadXmlResourceParser(int id, String type)
- throws NotFoundException {
- synchronized (mTmpValue) {
- TypedValue value = mTmpValue;
- getValue(id, value, true);
- if (value.type == TypedValue.TYPE_STRING) {
- return loadXmlResourceParser(value.string.toString(), id,
- value.assetCookie, type);
- }
- throw new NotFoundException(
- "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
- + Integer.toHexString(value.type) + " is not valid");
- }
- }
-
- /*package*/ XmlResourceParser loadXmlResourceParser(String file, int id,
- int assetCookie, String type) throws NotFoundException {
- if (id != 0) {
- try {
- // These may be compiled...
- synchronized (mCachedXmlBlockIds) {
- // First see if this block is in our cache.
- final int num = mCachedXmlBlockIds.length;
- for (int i=0; i<num; i++) {
- if (mCachedXmlBlockIds[i] == id) {
- //System.out.println("**** REUSING XML BLOCK! id="
- // + id + ", index=" + i);
- return mCachedXmlBlocks[i].newParser();
- }
- }
-
- // Not in the cache, create a new block and put it at
- // the next slot in the cache.
- XmlBlock block = mAssets.openXmlBlockAsset(
- assetCookie, file);
- if (block != null) {
- int pos = mLastCachedXmlBlockIndex+1;
- if (pos >= num) pos = 0;
- mLastCachedXmlBlockIndex = pos;
- XmlBlock oldBlock = mCachedXmlBlocks[pos];
- if (oldBlock != null) {
- oldBlock.close();
- }
- mCachedXmlBlockIds[pos] = id;
- mCachedXmlBlocks[pos] = block;
- //System.out.println("**** CACHING NEW XML BLOCK! id="
- // + id + ", index=" + pos);
- return block.newParser();
- }
- }
- } catch (Exception e) {
- NotFoundException rnf = new NotFoundException(
- "File " + file + " from xml type " + type + " resource ID #0x"
- + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
- }
-
- throw new NotFoundException(
- "File " + file + " from xml type " + type + " resource ID #0x"
- + Integer.toHexString(id));
- }
-
- private TypedArray getCachedStyledAttributes(int len) {
- synchronized (mTmpValue) {
- TypedArray attrs = mCachedStyledAttributes;
- if (attrs != null) {
- mCachedStyledAttributes = null;
-
- attrs.mLength = len;
- int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;
- if (attrs.mData.length >= fullLen) {
- return attrs;
- }
- attrs.mData = new int[fullLen];
- attrs.mIndices = new int[1+len];
- return attrs;
- }
- return new TypedArray(this,
- new int[len*AssetManager.STYLE_NUM_ENTRIES],
- new int[1+len], len);
- }
- }
-
- private Resources() {
- mAssets = AssetManager.getSystem();
- // NOTE: Intentionally leaving this uninitialized (all values set
- // to zero), so that anyone who tries to do something that requires
- // metrics will get a very wrong value.
- mConfiguration.setToDefaults();
- mMetrics.setToDefaults();
- updateConfiguration(null, null);
- mAssets.ensureStringBlocks();
- }
-}
-
diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java
deleted file mode 100644
index 3df7708..0000000
--- a/core/java/android/content/res/StringBlock.java
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res;
-
-import android.text.*;
-import android.text.style.*;
-import android.util.Config;
-import android.util.Log;
-import android.util.SparseArray;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Typeface;
-import com.android.internal.util.XmlUtils;
-
-/**
- * Conveniences for retrieving data out of a compiled string resource.
- *
- * {@hide}
- */
-final class StringBlock {
- private static final String TAG = "AssetManager";
- private static final boolean localLOGV = Config.LOGV || false;
-
- private final int mNative;
- private final boolean mUseSparse;
- private final boolean mOwnsNative;
- private CharSequence[] mStrings;
- private SparseArray<CharSequence> mSparseStrings;
- StyleIDs mStyleIDs = null;
-
- public StringBlock(byte[] data, boolean useSparse) {
- mNative = nativeCreate(data, 0, data.length);
- mUseSparse = useSparse;
- mOwnsNative = true;
- if (localLOGV) Log.v(TAG, "Created string block " + this
- + ": " + nativeGetSize(mNative));
- }
-
- public StringBlock(byte[] data, int offset, int size, boolean useSparse) {
- mNative = nativeCreate(data, offset, size);
- mUseSparse = useSparse;
- mOwnsNative = true;
- if (localLOGV) Log.v(TAG, "Created string block " + this
- + ": " + nativeGetSize(mNative));
- }
-
- public CharSequence get(int idx) {
- synchronized (this) {
- if (mStrings != null) {
- CharSequence res = mStrings[idx];
- if (res != null) {
- return res;
- }
- } else if (mSparseStrings != null) {
- CharSequence res = mSparseStrings.get(idx);
- if (res != null) {
- return res;
- }
- } else {
- final int num = nativeGetSize(mNative);
- if (mUseSparse && num > 250) {
- mSparseStrings = new SparseArray<CharSequence>();
- } else {
- mStrings = new CharSequence[num];
- }
- }
- String str = nativeGetString(mNative, idx);
- CharSequence res = str;
- int[] style = nativeGetStyle(mNative, idx);
- if (localLOGV) Log.v(TAG, "Got string: " + str);
- if (localLOGV) Log.v(TAG, "Got styles: " + style);
- if (style != null) {
- if (mStyleIDs == null) {
- mStyleIDs = new StyleIDs();
- mStyleIDs.boldId = nativeIndexOfString(mNative, "b");
- mStyleIDs.italicId = nativeIndexOfString(mNative, "i");
- mStyleIDs.underlineId = nativeIndexOfString(mNative, "u");
- mStyleIDs.ttId = nativeIndexOfString(mNative, "tt");
- mStyleIDs.bigId = nativeIndexOfString(mNative, "big");
- mStyleIDs.smallId = nativeIndexOfString(mNative, "small");
- mStyleIDs.supId = nativeIndexOfString(mNative, "sup");
- mStyleIDs.subId = nativeIndexOfString(mNative, "sub");
- mStyleIDs.strikeId = nativeIndexOfString(mNative, "strike");
- mStyleIDs.listItemId = nativeIndexOfString(mNative, "li");
- mStyleIDs.marqueeId = nativeIndexOfString(mNative, "marquee");
-
- if (localLOGV) Log.v(TAG, "BoldId=" + mStyleIDs.boldId
- + ", ItalicId=" + mStyleIDs.italicId
- + ", UnderlineId=" + mStyleIDs.underlineId);
- }
-
- res = applyStyles(str, style, mStyleIDs);
- }
- if (mStrings != null) mStrings[idx] = res;
- else mSparseStrings.put(idx, res);
- return res;
- }
- }
-
- protected void finalize() throws Throwable {
- if (mOwnsNative) {
- nativeDestroy(mNative);
- }
- }
-
- static final class StyleIDs {
- private int boldId;
- private int italicId;
- private int underlineId;
- private int ttId;
- private int bigId;
- private int smallId;
- private int subId;
- private int supId;
- private int strikeId;
- private int listItemId;
- private int marqueeId;
- }
-
- private CharSequence applyStyles(String str, int[] style, StyleIDs ids) {
- if (style.length == 0)
- return str;
-
- SpannableString buffer = new SpannableString(str);
- int i=0;
- while (i < style.length) {
- int type = style[i];
- if (localLOGV) Log.v(TAG, "Applying style span id=" + type
- + ", start=" + style[i+1] + ", end=" + style[i+2]);
- if (type == ids.boldId) {
- buffer.setSpan(new StyleSpan(Typeface.BOLD),
- style[i+1], style[i+2]+1,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- } else if (type == ids.italicId) {
- buffer.setSpan(new StyleSpan(Typeface.ITALIC),
- style[i+1], style[i+2]+1,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- } else if (type == ids.underlineId) {
- buffer.setSpan(new UnderlineSpan(),
- style[i+1], style[i+2]+1,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- } else if (type == ids.ttId) {
- buffer.setSpan(new TypefaceSpan("monospace"),
- style[i+1], style[i+2]+1,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- } else if (type == ids.bigId) {
- buffer.setSpan(new RelativeSizeSpan(1.25f),
- style[i+1], style[i+2]+1,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- } else if (type == ids.smallId) {
- buffer.setSpan(new RelativeSizeSpan(0.8f),
- style[i+1], style[i+2]+1,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- } else if (type == ids.subId) {
- buffer.setSpan(new SubscriptSpan(),
- style[i+1], style[i+2]+1,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- } else if (type == ids.supId) {
- buffer.setSpan(new SuperscriptSpan(),
- style[i+1], style[i+2]+1,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- } else if (type == ids.strikeId) {
- buffer.setSpan(new StrikethroughSpan(),
- style[i+1], style[i+2]+1,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- } else if (type == ids.listItemId) {
- buffer.setSpan(new BulletSpan(10),
- style[i+1], style[i+2]+1,
- Spannable.SPAN_PARAGRAPH);
- } else if (type == ids.marqueeId) {
- buffer.setSpan(TextUtils.TruncateAt.MARQUEE,
- style[i+1], style[i+2]+1,
- Spannable.SPAN_INCLUSIVE_INCLUSIVE);
- } else {
- String tag = nativeGetString(mNative, type);
-
- if (tag.startsWith("font;")) {
- String sub;
-
- sub = subtag(tag, ";height=");
- if (sub != null) {
- int size = Integer.parseInt(sub);
- buffer.setSpan(new Height(size),
- style[i+1], style[i+2]+1,
- Spannable.SPAN_PARAGRAPH);
- }
-
- sub = subtag(tag, ";size=");
- if (sub != null) {
- int size = Integer.parseInt(sub);
- buffer.setSpan(new AbsoluteSizeSpan(size),
- style[i+1], style[i+2]+1,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
- sub = subtag(tag, ";fgcolor=");
- if (sub != null) {
- int color = XmlUtils.convertValueToUnsignedInt(sub, -1);
- buffer.setSpan(new ForegroundColorSpan(color),
- style[i+1], style[i+2]+1,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
- sub = subtag(tag, ";bgcolor=");
- if (sub != null) {
- int color = XmlUtils.convertValueToUnsignedInt(sub, -1);
- buffer.setSpan(new BackgroundColorSpan(color),
- style[i+1], style[i+2]+1,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- } else if (tag.startsWith("a;")) {
- String sub;
-
- sub = subtag(tag, ";href=");
- if (sub != null) {
- buffer.setSpan(new URLSpan(sub),
- style[i+1], style[i+2]+1,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- }
-
- i += 3;
- }
- return new SpannedString(buffer);
- }
-
- private static String subtag(String full, String attribute) {
- int start = full.indexOf(attribute);
- if (start < 0) {
- return null;
- }
-
- start += attribute.length();
- int end = full.indexOf(';', start);
-
- if (end < 0) {
- return full.substring(start);
- } else {
- return full.substring(start, end);
- }
- }
-
- /**
- * Forces the text line to be the specified height, shrinking/stretching
- * the ascent if possible, or the descent if shrinking the ascent further
- * will make the text unreadable.
- */
- private static class Height implements LineHeightSpan {
- private int mSize;
- private static float sProportion = 0;
-
- public Height(int size) {
- mSize = size;
- }
-
- public void chooseHeight(CharSequence text, int start, int end,
- int spanstartv, int v,
- Paint.FontMetricsInt fm) {
- if (fm.bottom - fm.top < mSize) {
- fm.top = fm.bottom - mSize;
- fm.ascent = fm.ascent - mSize;
- } else {
- if (sProportion == 0) {
- /*
- * Calculate what fraction of the nominal ascent
- * the height of a capital letter actually is,
- * so that we won't reduce the ascent to less than
- * that unless we absolutely have to.
- */
-
- Paint p = new Paint();
- p.setTextSize(100);
- Rect r = new Rect();
- p.getTextBounds("ABCDEFG", 0, 7, r);
-
- sProportion = (r.top) / p.ascent();
- }
-
- int need = (int) Math.ceil(-fm.top * sProportion);
-
- if (mSize - fm.descent >= need) {
- /*
- * It is safe to shrink the ascent this much.
- */
-
- fm.top = fm.bottom - mSize;
- fm.ascent = fm.descent - mSize;
- } else if (mSize >= need) {
- /*
- * We can't show all the descent, but we can at least
- * show all the ascent.
- */
-
- fm.top = fm.ascent = -need;
- fm.bottom = fm.descent = fm.top + mSize;
- } else {
- /*
- * Show as much of the ascent as we can, and no descent.
- */
-
- fm.top = fm.ascent = -mSize;
- fm.bottom = fm.descent = 0;
- }
- }
- }
- }
-
- /**
- * Create from an existing string block native object. This is
- * -extremely- dangerous -- only use it if you absolutely know what you
- * are doing! The given native object must exist for the entire lifetime
- * of this newly creating StringBlock.
- */
- StringBlock(int obj, boolean useSparse) {
- mNative = obj;
- mUseSparse = useSparse;
- mOwnsNative = false;
- if (localLOGV) Log.v(TAG, "Created string block " + this
- + ": " + nativeGetSize(mNative));
- }
-
- private static final native int nativeCreate(byte[] data,
- int offset,
- int size);
- private static final native int nativeGetSize(int obj);
- private static final native String nativeGetString(int obj, int idx);
- private static final native int[] nativeGetStyle(int obj, int idx);
- private static final native int nativeIndexOfString(int obj, String str);
- private static final native void nativeDestroy(int obj);
-}
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
deleted file mode 100644
index 82a57dd..0000000
--- a/core/java/android/content/res/TypedArray.java
+++ /dev/null
@@ -1,660 +0,0 @@
-package android.content.res;
-
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.TypedValue;
-import com.android.internal.util.XmlUtils;
-
-import java.util.Arrays;
-
-/**
- * Container for an array of values that were retrieved with
- * {@link Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)}
- * or {@link Resources#obtainAttributes}. Be
- * sure to call {@link #recycle} when done with them.
- *
- * The indices used to retrieve values from this structure correspond to
- * the positions of the attributes given to obtainStyledAttributes.
- */
-public class TypedArray {
- private final Resources mResources;
- /*package*/ XmlBlock.Parser mXml;
- /*package*/ int[] mRsrcs;
- /*package*/ int[] mData;
- /*package*/ int[] mIndices;
- /*package*/ int mLength;
- private TypedValue mValue = new TypedValue();
-
- /**
- * Return the number of values in this array.
- */
- public int length() {
- return mLength;
- }
-
- /**
- * Return the number of indices in the array that actually have data.
- */
- public int getIndexCount() {
- return mIndices[0];
- }
-
- /**
- * Return an index in the array that has data.
- *
- * @param at The index you would like to returned, ranging from 0 to
- * {@link #getIndexCount()}.
- *
- * @return The index at the given offset, which can be used with
- * {@link #getValue} and related APIs.
- */
- public int getIndex(int at) {
- return mIndices[1+at];
- }
-
- /**
- * Return the Resources object this array was loaded from.
- */
- public Resources getResources() {
- return mResources;
- }
-
- /**
- * Retrieve the styled string value for the attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return CharSequence holding string data. May be styled. Returns
- * null if the attribute is not defined.
- */
- public CharSequence getText(int index) {
- index *= AssetManager.STYLE_NUM_ENTRIES;
- final int[] data = mData;
- final int type = data[index+AssetManager.STYLE_TYPE];
- if (type == TypedValue.TYPE_NULL) {
- return null;
- } else if (type == TypedValue.TYPE_STRING) {
- return loadStringValueAt(index);
- }
-
- TypedValue v = mValue;
- if (getValueAt(index, v)) {
- Log.w(Resources.TAG, "Converting to string: " + v);
- return v.coerceToString();
- }
- Log.w(Resources.TAG, "getString of bad type: 0x"
- + Integer.toHexString(type));
- return null;
- }
-
- /**
- * Retrieve the string value for the attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return String holding string data. Any styling information is
- * removed. Returns null if the attribute is not defined.
- */
- public String getString(int index) {
- index *= AssetManager.STYLE_NUM_ENTRIES;
- final int[] data = mData;
- final int type = data[index+AssetManager.STYLE_TYPE];
- if (type == TypedValue.TYPE_NULL) {
- return null;
- } else if (type == TypedValue.TYPE_STRING) {
- return loadStringValueAt(index).toString();
- }
-
- TypedValue v = mValue;
- if (getValueAt(index, v)) {
- Log.w(Resources.TAG, "Converting to string: " + v);
- CharSequence cs = v.coerceToString();
- return cs != null ? cs.toString() : null;
- }
- Log.w(Resources.TAG, "getString of bad type: 0x"
- + Integer.toHexString(type));
- return null;
- }
-
- /**
- * Retrieve the string value for the attribute at <var>index</var>, but
- * only if that string comes from an immediate value in an XML file. That
- * is, this does not allow references to string resources, string
- * attributes, or conversions from other types. As such, this method
- * will only return strings for TypedArray objects that come from
- * attributes in an XML file.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return String holding string data. Any styling information is
- * removed. Returns null if the attribute is not defined or is not
- * an immediate string value.
- */
- public String getNonResourceString(int index) {
- index *= AssetManager.STYLE_NUM_ENTRIES;
- final int[] data = mData;
- final int type = data[index+AssetManager.STYLE_TYPE];
- if (type == TypedValue.TYPE_STRING) {
- final int cookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
- if (cookie < 0) {
- return mXml.getPooledString(
- data[index+AssetManager.STYLE_DATA]).toString();
- }
- }
- return null;
- }
-
- /**
- * Retrieve the boolean value for the attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined.
- *
- * @return Attribute boolean value, or defValue if not defined.
- */
- public boolean getBoolean(int index, boolean defValue) {
- index *= AssetManager.STYLE_NUM_ENTRIES;
- final int[] data = mData;
- final int type = data[index+AssetManager.STYLE_TYPE];
- if (type == TypedValue.TYPE_NULL) {
- return defValue;
- } else if (type >= TypedValue.TYPE_FIRST_INT
- && type <= TypedValue.TYPE_LAST_INT) {
- return data[index+AssetManager.STYLE_DATA] != 0;
- }
-
- TypedValue v = mValue;
- if (getValueAt(index, v)) {
- Log.w(Resources.TAG, "Converting to boolean: " + v);
- return XmlUtils.convertValueToBoolean(
- v.coerceToString(), defValue);
- }
- Log.w(Resources.TAG, "getBoolean of bad type: 0x"
- + Integer.toHexString(type));
- return defValue;
- }
-
- /**
- * Retrieve the integer value for the attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined.
- *
- * @return Attribute int value, or defValue if not defined.
- */
- public int getInt(int index, int defValue) {
- index *= AssetManager.STYLE_NUM_ENTRIES;
- final int[] data = mData;
- final int type = data[index+AssetManager.STYLE_TYPE];
- if (type == TypedValue.TYPE_NULL) {
- return defValue;
- } else if (type >= TypedValue.TYPE_FIRST_INT
- && type <= TypedValue.TYPE_LAST_INT) {
- return data[index+AssetManager.STYLE_DATA];
- }
-
- TypedValue v = mValue;
- if (getValueAt(index, v)) {
- Log.w(Resources.TAG, "Converting to int: " + v);
- return XmlUtils.convertValueToInt(
- v.coerceToString(), defValue);
- }
- Log.w(Resources.TAG, "getInt of bad type: 0x"
- + Integer.toHexString(type));
- return defValue;
- }
-
- /**
- * Retrieve the float value for the attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return Attribute float value, or defValue if not defined..
- */
- public float getFloat(int index, float defValue) {
- index *= AssetManager.STYLE_NUM_ENTRIES;
- final int[] data = mData;
- final int type = data[index+AssetManager.STYLE_TYPE];
- if (type == TypedValue.TYPE_NULL) {
- return defValue;
- } else if (type == TypedValue.TYPE_FLOAT) {
- return Float.intBitsToFloat(data[index+AssetManager.STYLE_DATA]);
- } else if (type >= TypedValue.TYPE_FIRST_INT
- && type <= TypedValue.TYPE_LAST_INT) {
- return data[index+AssetManager.STYLE_DATA];
- }
-
- TypedValue v = mValue;
- if (getValueAt(index, v)) {
- Log.w(Resources.TAG, "Converting to float: " + v);
- CharSequence str = v.coerceToString();
- if (str != null) {
- return Float.parseFloat(str.toString());
- }
- }
- Log.w(Resources.TAG, "getFloat of bad type: 0x"
- + Integer.toHexString(type));
- return defValue;
- }
-
- /**
- * Retrieve the color value for the attribute at <var>index</var>. If
- * the attribute references a color resource holding a complex
- * {@link android.content.res.ColorStateList}, then the default color from
- * the set is returned.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined or
- * not a resource.
- *
- * @return Attribute color value, or defValue if not defined.
- */
- public int getColor(int index, int defValue) {
- index *= AssetManager.STYLE_NUM_ENTRIES;
- final int[] data = mData;
- final int type = data[index+AssetManager.STYLE_TYPE];
- if (type == TypedValue.TYPE_NULL) {
- return defValue;
- } else if (type >= TypedValue.TYPE_FIRST_INT
- && type <= TypedValue.TYPE_LAST_INT) {
- return data[index+AssetManager.STYLE_DATA];
- } else if (type == TypedValue.TYPE_STRING) {
- final TypedValue value = mValue;
- if (getValueAt(index, value)) {
- ColorStateList csl = mResources.loadColorStateList(
- value, value.resourceId);
- return csl.getDefaultColor();
- }
- return defValue;
- }
-
- throw new UnsupportedOperationException("Can't convert to color: type=0x"
- + Integer.toHexString(type));
- }
-
- /**
- * Retrieve the ColorStateList for the attribute at <var>index</var>.
- * The value may be either a single solid color or a reference to
- * a color or complex {@link android.content.res.ColorStateList} description.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return ColorStateList for the attribute, or null if not defined.
- */
- public ColorStateList getColorStateList(int index) {
- final TypedValue value = mValue;
- if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
- return mResources.loadColorStateList(value, value.resourceId);
- }
- return null;
- }
-
- /**
- * Retrieve the integer value for the attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined or
- * not a resource.
- *
- * @return Attribute integer value, or defValue if not defined.
- */
- public int getInteger(int index, int defValue) {
- index *= AssetManager.STYLE_NUM_ENTRIES;
- final int[] data = mData;
- final int type = data[index+AssetManager.STYLE_TYPE];
- if (type == TypedValue.TYPE_NULL) {
- return defValue;
- } else if (type >= TypedValue.TYPE_FIRST_INT
- && type <= TypedValue.TYPE_LAST_INT) {
- return data[index+AssetManager.STYLE_DATA];
- }
-
- throw new UnsupportedOperationException("Can't convert to integer: type=0x"
- + Integer.toHexString(type));
- }
-
- /**
- * Retrieve a dimensional unit attribute at <var>index</var>. Unit
- * conversions are based on the current {@link DisplayMetrics}
- * associated with the resources this {@link TypedArray} object
- * came from.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined or
- * not a resource.
- *
- * @return Attribute dimension value multiplied by the appropriate
- * metric, or defValue if not defined.
- *
- * @see #getDimensionPixelOffset
- * @see #getDimensionPixelSize
- */
- public float getDimension(int index, float defValue) {
- index *= AssetManager.STYLE_NUM_ENTRIES;
- final int[] data = mData;
- final int type = data[index+AssetManager.STYLE_TYPE];
- if (type == TypedValue.TYPE_NULL) {
- return defValue;
- } else if (type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimension(
- data[index+AssetManager.STYLE_DATA], mResources.mMetrics);
- }
-
- throw new UnsupportedOperationException("Can't convert to dimension: type=0x"
- + Integer.toHexString(type));
- }
-
- /**
- * Retrieve a dimensional unit attribute at <var>index</var> for use
- * as an offset in raw pixels. This is the same as
- * {@link #getDimension}, except the returned value is converted to
- * integer pixels for you. An offset conversion involves simply
- * truncating the base value to an integer.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined or
- * not a resource.
- *
- * @return Attribute dimension value multiplied by the appropriate
- * metric and truncated to integer pixels, or defValue if not defined.
- *
- * @see #getDimension
- * @see #getDimensionPixelSize
- */
- public int getDimensionPixelOffset(int index, int defValue) {
- index *= AssetManager.STYLE_NUM_ENTRIES;
- final int[] data = mData;
- final int type = data[index+AssetManager.STYLE_TYPE];
- if (type == TypedValue.TYPE_NULL) {
- return defValue;
- } else if (type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelOffset(
- data[index+AssetManager.STYLE_DATA], mResources.mMetrics);
- }
-
- throw new UnsupportedOperationException("Can't convert to dimension: type=0x"
- + Integer.toHexString(type));
- }
-
- /**
- * Retrieve a dimensional unit attribute at <var>index</var> for use
- * as a size in raw pixels. This is the same as
- * {@link #getDimension}, except the returned value is converted to
- * integer pixels for use as a size. A size conversion involves
- * rounding the base value, and ensuring that a non-zero base value
- * is at least one pixel in size.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined or
- * not a resource.
- *
- * @return Attribute dimension value multiplied by the appropriate
- * metric and truncated to integer pixels, or defValue if not defined.
- *
- * @see #getDimension
- * @see #getDimensionPixelOffset
- */
- public int getDimensionPixelSize(int index, int defValue) {
- index *= AssetManager.STYLE_NUM_ENTRIES;
- final int[] data = mData;
- final int type = data[index+AssetManager.STYLE_TYPE];
- if (type == TypedValue.TYPE_NULL) {
- return defValue;
- } else if (type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelSize(
- data[index+AssetManager.STYLE_DATA], mResources.mMetrics);
- }
-
- throw new UnsupportedOperationException("Can't convert to dimension: type=0x"
- + Integer.toHexString(type));
- }
-
- /**
- * Special version of {@link #getDimensionPixelSize} for retrieving
- * {@link android.view.ViewGroup}'s layout_width and layout_height
- * attributes. This is only here for performance reasons; applications
- * should use {@link #getDimensionPixelSize}.
- *
- * @param index Index of the attribute to retrieve.
- * @param name Textual name of attribute for error reporting.
- *
- * @return Attribute dimension value multiplied by the appropriate
- * metric and truncated to integer pixels.
- */
- public int getLayoutDimension(int index, String name) {
- index *= AssetManager.STYLE_NUM_ENTRIES;
- final int[] data = mData;
- final int type = data[index+AssetManager.STYLE_TYPE];
- if (type >= TypedValue.TYPE_FIRST_INT
- && type <= TypedValue.TYPE_LAST_INT) {
- return data[index+AssetManager.STYLE_DATA];
- } else if (type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelSize(
- data[index+AssetManager.STYLE_DATA], mResources.mMetrics);
- }
-
- throw new RuntimeException(getPositionDescription()
- + ": You must supply a " + name + " attribute.");
- }
-
- /**
- * Retrieve a fractional unit attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- * @param base The base value of this fraction. In other words, a
- * standard fraction is multiplied by this value.
- * @param pbase The parent base value of this fraction. In other
- * words, a parent fraction (nn%p) is multiplied by this
- * value.
- * @param defValue Value to return if the attribute is not defined or
- * not a resource.
- *
- * @return Attribute fractional value multiplied by the appropriate
- * base value, or defValue if not defined.
- */
- public float getFraction(int index, int base, int pbase, float defValue) {
- index *= AssetManager.STYLE_NUM_ENTRIES;
- final int[] data = mData;
- final int type = data[index+AssetManager.STYLE_TYPE];
- if (type == TypedValue.TYPE_NULL) {
- return defValue;
- } else if (type == TypedValue.TYPE_FRACTION) {
- return TypedValue.complexToFraction(
- data[index+AssetManager.STYLE_DATA], base, pbase);
- }
-
- throw new UnsupportedOperationException("Can't convert to fraction: type=0x"
- + Integer.toHexString(type));
- }
-
- /**
- * Retrieve the resource identifier for the attribute at
- * <var>index</var>. Note that attribute resource as resolved when
- * the overall {@link TypedArray} object is retrieved. As a
- * result, this function will return the resource identifier of the
- * final resource value that was found, <em>not</em> necessarily the
- * original resource that was specified by the attribute.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined or
- * not a resource.
- *
- * @return Attribute resource identifier, or defValue if not defined.
- */
- public int getResourceId(int index, int defValue) {
- index *= AssetManager.STYLE_NUM_ENTRIES;
- final int[] data = mData;
- if (data[index+AssetManager.STYLE_TYPE] != TypedValue.TYPE_NULL) {
- final int resid = data[index+AssetManager.STYLE_RESOURCE_ID];
- if (resid != 0) {
- return resid;
- }
- }
- return defValue;
- }
-
- /**
- * Retrieve the Drawable for the attribute at <var>index</var>. This
- * gets the resource ID of the selected attribute, and uses
- * {@link Resources#getDrawable Resources.getDrawable} of the owning
- * Resources object to retrieve its Drawable.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return Drawable for the attribute, or null if not defined.
- */
- public Drawable getDrawable(int index) {
- final TypedValue value = mValue;
- if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
- if (false) {
- System.out.println("******************************************************************");
- System.out.println("Got drawable resource: type="
- + value.type
- + " str=" + value.string
- + " int=0x" + Integer.toHexString(value.data)
- + " cookie=" + value.assetCookie);
- System.out.println("******************************************************************");
- }
- return mResources.loadDrawable(value, value.resourceId);
- }
- return null;
- }
-
- /**
- * Retrieve the CharSequence[] for the attribute at <var>index</var>.
- * This gets the resource ID of the selected attribute, and uses
- * {@link Resources#getTextArray Resources.getTextArray} of the owning
- * Resources object to retrieve its String[].
- *
- * @param index Index of attribute to retrieve.
- *
- * @return CharSequence[] for the attribute, or null if not defined.
- */
- public CharSequence[] getTextArray(int index) {
- final TypedValue value = mValue;
- if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
- if (false) {
- System.out.println("******************************************************************");
- System.out.println("Got drawable resource: type="
- + value.type
- + " str=" + value.string
- + " int=0x" + Integer.toHexString(value.data)
- + " cookie=" + value.assetCookie);
- System.out.println("******************************************************************");
- }
- return mResources.getTextArray(value.resourceId);
- }
- return null;
- }
-
- /**
- * Retrieve the raw TypedValue for the attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- * @param outValue TypedValue object in which to place the attribute's
- * data.
- *
- * @return Returns true if the value was retrieved, else false.
- */
- public boolean getValue(int index, TypedValue outValue) {
- return getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, outValue);
- }
-
- /**
- * Determines whether there is an attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return True if the attribute has a value, false otherwise.
- */
- public boolean hasValue(int index) {
- index *= AssetManager.STYLE_NUM_ENTRIES;
- final int[] data = mData;
- final int type = data[index+AssetManager.STYLE_TYPE];
- return type != TypedValue.TYPE_NULL;
- }
-
- /**
- * Retrieve the raw TypedValue for the attribute at <var>index</var>
- * and return a temporary object holding its data. This object is only
- * valid until the next call on to {@link TypedArray}.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return Returns a TypedValue object if the attribute is defined,
- * containing its data; otherwise returns null. (You will not
- * receive a TypedValue whose type is TYPE_NULL.)
- */
- public TypedValue peekValue(int index) {
- final TypedValue value = mValue;
- if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
- return value;
- }
- return null;
- }
-
- /**
- * Returns a message about the parser state suitable for printing error messages.
- */
- public String getPositionDescription() {
- return mXml != null ? mXml.getPositionDescription() : "<internal>";
- }
-
- /**
- * Give back a previously retrieved StyledAttributes, for later re-use.
- */
- public void recycle() {
- synchronized (mResources.mTmpValue) {
- TypedArray cached = mResources.mCachedStyledAttributes;
- if (cached == null || cached.mData.length < mData.length) {
- mXml = null;
- mResources.mCachedStyledAttributes = this;
- }
- }
- }
-
- private boolean getValueAt(int index, TypedValue outValue) {
- final int[] data = mData;
- final int type = data[index+AssetManager.STYLE_TYPE];
- if (type == TypedValue.TYPE_NULL) {
- return false;
- }
- outValue.type = type;
- outValue.data = data[index+AssetManager.STYLE_DATA];
- outValue.assetCookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
- outValue.resourceId = data[index+AssetManager.STYLE_RESOURCE_ID];
- outValue.changingConfigurations = data[index+AssetManager.STYLE_CHANGING_CONFIGURATIONS];
- if (type == TypedValue.TYPE_STRING) {
- outValue.string = loadStringValueAt(index);
- }
- return true;
- }
-
- private CharSequence loadStringValueAt(int index) {
- final int[] data = mData;
- final int cookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
- if (cookie < 0) {
- if (mXml != null) {
- return mXml.getPooledString(
- data[index+AssetManager.STYLE_DATA]);
- }
- return null;
- }
- //System.out.println("Getting pooled from: " + v);
- return mResources.mAssets.getPooledString(
- cookie, data[index+AssetManager.STYLE_DATA]);
- }
-
- /*package*/ TypedArray(Resources resources, int[] data, int[] indices, int len) {
- mResources = resources;
- mData = data;
- mIndices = indices;
- mLength = len;
- }
-
- public String toString() {
- return Arrays.toString(mData);
- }
-} \ No newline at end of file
diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java
deleted file mode 100644
index 6336678..0000000
--- a/core/java/android/content/res/XmlBlock.java
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res;
-
-import android.util.TypedValue;
-import com.android.internal.util.XmlUtils;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-
-/**
- * Wrapper around a compiled XML file.
- *
- * {@hide}
- */
-final class XmlBlock {
- private static final boolean DEBUG=false;
-
- public XmlBlock(byte[] data) {
- mAssets = null;
- mNative = nativeCreate(data, 0, data.length);
- mStrings = new StringBlock(nativeGetStringBlock(mNative), false);
- }
-
- public XmlBlock(byte[] data, int offset, int size) {
- mAssets = null;
- mNative = nativeCreate(data, offset, size);
- mStrings = new StringBlock(nativeGetStringBlock(mNative), false);
- }
-
- public void close() {
- synchronized (this) {
- if (mOpen) {
- mOpen = false;
- decOpenCountLocked();
- }
- }
- }
-
- private void decOpenCountLocked() {
- mOpenCount--;
- if (mOpenCount == 0) {
- nativeDestroy(mNative);
- if (mAssets != null) {
- mAssets.xmlBlockGone();
- }
- }
- }
-
- public XmlResourceParser newParser() {
- synchronized (this) {
- if (mNative != 0) {
- return new Parser(nativeCreateParseState(mNative), this);
- }
- return null;
- }
- }
-
- /*package*/ final class Parser implements XmlResourceParser {
- Parser(int parseState, XmlBlock block) {
- mParseState = parseState;
- mBlock = block;
- block.mOpenCount++;
- }
-
- public void setFeature(String name, boolean state) throws XmlPullParserException {
- if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) {
- return;
- }
- if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) {
- return;
- }
- throw new XmlPullParserException("Unsupported feature: " + name);
- }
- public boolean getFeature(String name) {
- if (FEATURE_PROCESS_NAMESPACES.equals(name)) {
- return true;
- }
- if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
- return true;
- }
- return false;
- }
- public void setProperty(String name, Object value) throws XmlPullParserException {
- throw new XmlPullParserException("setProperty() not supported");
- }
- public Object getProperty(String name) {
- return null;
- }
- public void setInput(Reader in) throws XmlPullParserException {
- throw new XmlPullParserException("setInput() not supported");
- }
- public void setInput(InputStream inputStream, String inputEncoding) throws XmlPullParserException {
- throw new XmlPullParserException("setInput() not supported");
- }
- public void defineEntityReplacementText(String entityName, String replacementText) throws XmlPullParserException {
- throw new XmlPullParserException("defineEntityReplacementText() not supported");
- }
- public String getNamespacePrefix(int pos) throws XmlPullParserException {
- throw new XmlPullParserException("getNamespacePrefix() not supported");
- }
- public String getInputEncoding() {
- return null;
- }
- public String getNamespace(String prefix) {
- throw new RuntimeException("getNamespace() not supported");
- }
- public int getNamespaceCount(int depth) throws XmlPullParserException {
- throw new XmlPullParserException("getNamespaceCount() not supported");
- }
- public String getPositionDescription() {
- return "Binary XML file line #" + getLineNumber();
- }
- public String getNamespaceUri(int pos) throws XmlPullParserException {
- throw new XmlPullParserException("getNamespaceUri() not supported");
- }
- public int getColumnNumber() {
- return -1;
- }
- public int getDepth() {
- return mDepth;
- }
- public String getText() {
- int id = nativeGetText(mParseState);
- return id >= 0 ? mStrings.get(id).toString() : null;
- }
- public int getLineNumber() {
- return nativeGetLineNumber(mParseState);
- }
- public int getEventType() throws XmlPullParserException {
- return mEventType;
- }
- public boolean isWhitespace() throws XmlPullParserException {
- // whitespace was stripped by aapt.
- return false;
- }
- public String getPrefix() {
- throw new RuntimeException("getPrefix not supported");
- }
- public char[] getTextCharacters(int[] holderForStartAndLength) {
- String txt = getText();
- char[] chars = null;
- if (txt != null) {
- holderForStartAndLength[0] = 0;
- holderForStartAndLength[1] = txt.length();
- chars = new char[txt.length()];
- txt.getChars(0, txt.length(), chars, 0);
- }
- return chars;
- }
- public String getNamespace() {
- int id = nativeGetNamespace(mParseState);
- return id >= 0 ? mStrings.get(id).toString() : "";
- }
- public String getName() {
- int id = nativeGetName(mParseState);
- return id >= 0 ? mStrings.get(id).toString() : null;
- }
- public String getAttributeNamespace(int index) {
- int id = nativeGetAttributeNamespace(mParseState, index);
- if (DEBUG) System.out.println("getAttributeNamespace of " + index + " = " + id);
- if (id >= 0) return mStrings.get(id).toString();
- else if (id == -1) return "";
- throw new IndexOutOfBoundsException(String.valueOf(index));
- }
- public String getAttributeName(int index) {
- int id = nativeGetAttributeName(mParseState, index);
- if (DEBUG) System.out.println("getAttributeName of " + index + " = " + id);
- if (id >= 0) return mStrings.get(id).toString();
- throw new IndexOutOfBoundsException(String.valueOf(index));
- }
- public String getAttributePrefix(int index) {
- throw new RuntimeException("getAttributePrefix not supported");
- }
- public boolean isEmptyElementTag() throws XmlPullParserException {
- // XXX Need to detect this.
- return false;
- }
- public int getAttributeCount() {
- return mEventType == START_TAG ? nativeGetAttributeCount(mParseState) : -1;
- }
- public String getAttributeValue(int index) {
- int id = nativeGetAttributeStringValue(mParseState, index);
- if (DEBUG) System.out.println("getAttributeValue of " + index + " = " + id);
- if (id >= 0) return mStrings.get(id).toString();
-
- // May be some other type... check and try to convert if so.
- int t = nativeGetAttributeDataType(mParseState, index);
- if (t == TypedValue.TYPE_NULL) {
- throw new IndexOutOfBoundsException(String.valueOf(index));
- }
-
- int v = nativeGetAttributeData(mParseState, index);
- return TypedValue.coerceToString(t, v);
- }
- public String getAttributeType(int index) {
- return "CDATA";
- }
- public boolean isAttributeDefault(int index) {
- return false;
- }
- public int nextToken() throws XmlPullParserException,IOException {
- return next();
- }
- public String getAttributeValue(String namespace, String name) {
- int idx = nativeGetAttributeIndex(mParseState, namespace, name);
- if (idx >= 0) {
- if (DEBUG) System.out.println("getAttributeName of "
- + namespace + ":" + name + " index = " + idx);
- if (DEBUG) System.out.println(
- "Namespace=" + getAttributeNamespace(idx)
- + "Name=" + getAttributeName(idx)
- + ", Value=" + getAttributeValue(idx));
- return getAttributeValue(idx);
- }
- return null;
- }
- public int next() throws XmlPullParserException,IOException {
- if (!mStarted) {
- mStarted = true;
- return START_DOCUMENT;
- }
- if (mParseState == 0) {
- return END_DOCUMENT;
- }
- int ev = nativeNext(mParseState);
- if (mDecNextDepth) {
- mDepth--;
- mDecNextDepth = false;
- }
- switch (ev) {
- case START_TAG:
- mDepth++;
- break;
- case END_TAG:
- mDecNextDepth = true;
- break;
- }
- mEventType = ev;
- if (ev == END_DOCUMENT) {
- // Automatically close the parse when we reach the end of
- // a document, since the standard XmlPullParser interface
- // doesn't have such an API so most clients will leave us
- // dangling.
- close();
- }
- return ev;
- }
- public void require(int type, String namespace, String name) throws XmlPullParserException,IOException {
- if (type != getEventType()
- || (namespace != null && !namespace.equals( getNamespace () ) )
- || (name != null && !name.equals( getName() ) ) )
- throw new XmlPullParserException( "expected "+ TYPES[ type ]+getPositionDescription());
- }
- public String nextText() throws XmlPullParserException,IOException {
- if(getEventType() != START_TAG) {
- throw new XmlPullParserException(
- getPositionDescription()
- + ": parser must be on START_TAG to read next text", this, null);
- }
- int eventType = next();
- if(eventType == TEXT) {
- String result = getText();
- eventType = next();
- if(eventType != END_TAG) {
- throw new XmlPullParserException(
- getPositionDescription()
- + ": event TEXT it must be immediately followed by END_TAG", this, null);
- }
- return result;
- } else if(eventType == END_TAG) {
- return "";
- } else {
- throw new XmlPullParserException(
- getPositionDescription()
- + ": parser must be on START_TAG or TEXT to read text", this, null);
- }
- }
- public int nextTag() throws XmlPullParserException,IOException {
- int eventType = next();
- if(eventType == TEXT && isWhitespace()) { // skip whitespace
- eventType = next();
- }
- if (eventType != START_TAG && eventType != END_TAG) {
- throw new XmlPullParserException(
- getPositionDescription()
- + ": expected start or end tag", this, null);
- }
- return eventType;
- }
-
- public int getAttributeNameResource(int index) {
- return nativeGetAttributeResource(mParseState, index);
- }
-
- public int getAttributeListValue(String namespace, String attribute,
- String[] options, int defaultValue) {
- int idx = nativeGetAttributeIndex(mParseState, namespace, attribute);
- if (idx >= 0) {
- return getAttributeListValue(idx, options, defaultValue);
- }
- return defaultValue;
- }
- public boolean getAttributeBooleanValue(String namespace, String attribute,
- boolean defaultValue) {
- int idx = nativeGetAttributeIndex(mParseState, namespace, attribute);
- if (idx >= 0) {
- return getAttributeBooleanValue(idx, defaultValue);
- }
- return defaultValue;
- }
- public int getAttributeResourceValue(String namespace, String attribute,
- int defaultValue) {
- int idx = nativeGetAttributeIndex(mParseState, namespace, attribute);
- if (idx >= 0) {
- return getAttributeResourceValue(idx, defaultValue);
- }
- return defaultValue;
- }
- public int getAttributeIntValue(String namespace, String attribute,
- int defaultValue) {
- int idx = nativeGetAttributeIndex(mParseState, namespace, attribute);
- if (idx >= 0) {
- return getAttributeIntValue(idx, defaultValue);
- }
- return defaultValue;
- }
- public int getAttributeUnsignedIntValue(String namespace, String attribute,
- int defaultValue)
- {
- int idx = nativeGetAttributeIndex(mParseState, namespace, attribute);
- if (idx >= 0) {
- return getAttributeUnsignedIntValue(idx, defaultValue);
- }
- return defaultValue;
- }
- public float getAttributeFloatValue(String namespace, String attribute,
- float defaultValue) {
- int idx = nativeGetAttributeIndex(mParseState, namespace, attribute);
- if (idx >= 0) {
- return getAttributeFloatValue(idx, defaultValue);
- }
- return defaultValue;
- }
-
- public int getAttributeListValue(int idx,
- String[] options, int defaultValue) {
- int t = nativeGetAttributeDataType(mParseState, idx);
- int v = nativeGetAttributeData(mParseState, idx);
- if (t == TypedValue.TYPE_STRING) {
- return XmlUtils.convertValueToList(
- mStrings.get(v), options, defaultValue);
- }
- return v;
- }
- public boolean getAttributeBooleanValue(int idx,
- boolean defaultValue) {
- int t = nativeGetAttributeDataType(mParseState, idx);
- // Note: don't attempt to convert any other types, because
- // we want to count on appt doing the conversion for us.
- if (t >= TypedValue.TYPE_FIRST_INT &&
- t <= TypedValue.TYPE_LAST_INT) {
- return nativeGetAttributeData(mParseState, idx) != 0;
- }
- return defaultValue;
- }
- public int getAttributeResourceValue(int idx, int defaultValue) {
- int t = nativeGetAttributeDataType(mParseState, idx);
- // Note: don't attempt to convert any other types, because
- // we want to count on appt doing the conversion for us.
- if (t == TypedValue.TYPE_REFERENCE) {
- return nativeGetAttributeData(mParseState, idx);
- }
- return defaultValue;
- }
- public int getAttributeIntValue(int idx, int defaultValue) {
- int t = nativeGetAttributeDataType(mParseState, idx);
- // Note: don't attempt to convert any other types, because
- // we want to count on appt doing the conversion for us.
- if (t >= TypedValue.TYPE_FIRST_INT &&
- t <= TypedValue.TYPE_LAST_INT) {
- return nativeGetAttributeData(mParseState, idx);
- }
- return defaultValue;
- }
- public int getAttributeUnsignedIntValue(int idx, int defaultValue) {
- int t = nativeGetAttributeDataType(mParseState, idx);
- // Note: don't attempt to convert any other types, because
- // we want to count on appt doing the conversion for us.
- if (t >= TypedValue.TYPE_FIRST_INT &&
- t <= TypedValue.TYPE_LAST_INT) {
- return nativeGetAttributeData(mParseState, idx);
- }
- return defaultValue;
- }
- public float getAttributeFloatValue(int idx, float defaultValue) {
- int t = nativeGetAttributeDataType(mParseState, idx);
- // Note: don't attempt to convert any other types, because
- // we want to count on appt doing the conversion for us.
- if (t == TypedValue.TYPE_FLOAT) {
- return Float.intBitsToFloat(
- nativeGetAttributeData(mParseState, idx));
- }
- throw new RuntimeException("not a float!");
- }
-
- public String getIdAttribute() {
- int id = nativeGetIdAttribute(mParseState);
- return id >= 0 ? mStrings.get(id).toString() : null;
- }
- public String getClassAttribute() {
- int id = nativeGetClassAttribute(mParseState);
- return id >= 0 ? mStrings.get(id).toString() : null;
- }
-
- public int getIdAttributeResourceValue(int defaultValue) {
- //todo: create and use native method
- return getAttributeResourceValue(null, "id", defaultValue);
- }
-
- public int getStyleAttribute() {
- return nativeGetStyleAttribute(mParseState);
- }
-
- public void close() {
- synchronized (mBlock) {
- if (mParseState != 0) {
- nativeDestroyParseState(mParseState);
- mParseState = 0;
- mBlock.decOpenCountLocked();
- }
- }
- }
-
- protected void finalize() throws Throwable {
- close();
- }
-
- /*package*/ final CharSequence getPooledString(int id) {
- return mStrings.get(id);
- }
-
- /*package*/ int mParseState;
- private final XmlBlock mBlock;
- private boolean mStarted = false;
- private boolean mDecNextDepth = false;
- private int mDepth = 0;
- private int mEventType = START_DOCUMENT;
- }
-
- protected void finalize() throws Throwable {
- close();
- }
-
- /**
- * Create from an existing xml block native object. This is
- * -extremely- dangerous -- only use it if you absolutely know what you
- * are doing! The given native object must exist for the entire lifetime
- * of this newly creating XmlBlock.
- */
- XmlBlock(AssetManager assets, int xmlBlock) {
- mAssets = assets;
- mNative = xmlBlock;
- mStrings = new StringBlock(nativeGetStringBlock(xmlBlock), false);
- }
-
- private final AssetManager mAssets;
- private final int mNative;
- private final StringBlock mStrings;
- private boolean mOpen = true;
- private int mOpenCount = 1;
-
- private static final native int nativeCreate(byte[] data,
- int offset,
- int size);
- private static final native int nativeGetStringBlock(int obj);
-
- private static final native int nativeCreateParseState(int obj);
- private static final native int nativeNext(int state);
- private static final native int nativeGetNamespace(int state);
- private static final native int nativeGetName(int state);
- private static final native int nativeGetText(int state);
- private static final native int nativeGetLineNumber(int state);
- private static final native int nativeGetAttributeCount(int state);
- private static final native int nativeGetAttributeNamespace(int state, int idx);
- private static final native int nativeGetAttributeName(int state, int idx);
- private static final native int nativeGetAttributeResource(int state, int idx);
- private static final native int nativeGetAttributeDataType(int state, int idx);
- private static final native int nativeGetAttributeData(int state, int idx);
- private static final native int nativeGetAttributeStringValue(int state, int idx);
- private static final native int nativeGetIdAttribute(int state);
- private static final native int nativeGetClassAttribute(int state);
- private static final native int nativeGetStyleAttribute(int state);
- private static final native int nativeGetAttributeIndex(int state, String namespace, String name);
- private static final native void nativeDestroyParseState(int state);
-
- private static final native void nativeDestroy(int obj);
-}
diff --git a/core/java/android/content/res/XmlResourceParser.java b/core/java/android/content/res/XmlResourceParser.java
deleted file mode 100644
index c59e6d4..0000000
--- a/core/java/android/content/res/XmlResourceParser.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.util.AttributeSet;
-
-/**
- * The XML parsing interface returned for an XML resource. This is a standard
- * XmlPullParser interface, as well as an extended AttributeSet interface and
- * an additional close() method on this interface for the client to indicate
- * when it is done reading the resource.
- */
-public interface XmlResourceParser extends XmlPullParser, AttributeSet {
- /**
- * Close this interface to the resource. Calls on the interface are no
- * longer value after this call.
- */
- public void close();
-}
-
diff --git a/core/java/android/content/res/package.html b/core/java/android/content/res/package.html
deleted file mode 100644
index bb09dc7..0000000
--- a/core/java/android/content/res/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<HTML>
-<BODY>
-Contains classes for accessing application resources,
-such as raw asset files, colors, drawables, media or other other files
-in the package, plus important device configuration details
-(orientation, input types, etc.) that affect how the application may behave.
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java
deleted file mode 100644
index 76f0860..0000000
--- a/core/java/android/database/AbstractCursor.java
+++ /dev/null
@@ -1,636 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-import android.content.ContentResolver;
-import android.net.Uri;
-import android.util.Config;
-import android.util.Log;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-
-import java.lang.ref.WeakReference;
-import java.lang.UnsupportedOperationException;
-import java.util.HashMap;
-import java.util.Map;
-
-
-/**
- * This is an abstract cursor class that handles a lot of the common code
- * that all cursors need to deal with and is provided for convenience reasons.
- */
-public abstract class AbstractCursor implements CrossProcessCursor {
- private static final String TAG = "Cursor";
-
- DataSetObservable mDataSetObservable = new DataSetObservable();
- ContentObservable mContentObservable = new ContentObservable();
-
- /* -------------------------------------------------------- */
- /* These need to be implemented by subclasses */
- abstract public int getCount();
-
- abstract public String[] getColumnNames();
-
- abstract public String getString(int column);
- abstract public short getShort(int column);
- abstract public int getInt(int column);
- abstract public long getLong(int column);
- abstract public float getFloat(int column);
- abstract public double getDouble(int column);
- abstract public boolean isNull(int column);
-
- // TODO implement getBlob in all cursor types
- public byte[] getBlob(int column) {
- throw new UnsupportedOperationException("getBlob is not supported");
- }
- /* -------------------------------------------------------- */
- /* Methods that may optionally be implemented by subclasses */
-
- /**
- * returns a pre-filled window, return NULL if no such window
- */
- public CursorWindow getWindow() {
- return null;
- }
-
- public int getColumnCount() {
- return getColumnNames().length;
- }
-
- public void deactivate() {
- deactivateInternal();
- }
-
- /**
- * @hide
- */
- public void deactivateInternal() {
- if (mSelfObserver != null) {
- mContentResolver.unregisterContentObserver(mSelfObserver);
- mSelfObserverRegistered = false;
- }
- mDataSetObservable.notifyInvalidated();
- }
-
- public boolean requery() {
- if (mSelfObserver != null && mSelfObserverRegistered == false) {
- mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);
- mSelfObserverRegistered = true;
- }
- mDataSetObservable.notifyChanged();
- return true;
- }
-
- public boolean isClosed() {
- return mClosed;
- }
-
- public void close() {
- mClosed = true;
- mContentObservable.unregisterAll();
- deactivateInternal();
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean commitUpdates(Map<? extends Long,? extends Map<String,Object>> values) {
- return false;
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean deleteRow() {
- return false;
- }
-
- /**
- * This function is called every time the cursor is successfully scrolled
- * to a new position, giving the subclass a chance to update any state it
- * may have. If it returns false the move function will also do so and the
- * cursor will scroll to the beforeFirst position.
- *
- * @param oldPosition the position that we're moving from
- * @param newPosition the position that we're moving to
- * @return true if the move is successful, false otherwise
- */
- public boolean onMove(int oldPosition, int newPosition) {
- return true;
- }
-
-
- public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
- // Default implementation, uses getString
- String result = getString(columnIndex);
- if (result != null) {
- char[] data = buffer.data;
- if (data == null || data.length < result.length()) {
- buffer.data = result.toCharArray();
- } else {
- result.getChars(0, result.length(), data, 0);
- }
- buffer.sizeCopied = result.length();
- }
- }
-
- /* -------------------------------------------------------- */
- /* Implementation */
- public AbstractCursor() {
- mPos = -1;
- mRowIdColumnIndex = -1;
- mCurrentRowID = null;
- mUpdatedRows = new HashMap<Long, Map<String, Object>>();
- }
-
- public final int getPosition() {
- return mPos;
- }
-
- public final boolean moveToPosition(int position) {
- // Make sure position isn't past the end of the cursor
- final int count = getCount();
- if (position >= count) {
- mPos = count;
- return false;
- }
-
- // Make sure position isn't before the beginning of the cursor
- if (position < 0) {
- mPos = -1;
- return false;
- }
-
- // Check for no-op moves, and skip the rest of the work for them
- if (position == mPos) {
- return true;
- }
-
- boolean result = onMove(mPos, position);
- if (result == false) {
- mPos = -1;
- } else {
- mPos = position;
- if (mRowIdColumnIndex != -1) {
- mCurrentRowID = Long.valueOf(getLong(mRowIdColumnIndex));
- }
- }
-
- return result;
- }
-
- /**
- * Copy data from cursor to CursorWindow
- * @param position start position of data
- * @param window
- */
- public void fillWindow(int position, CursorWindow window) {
- if (position < 0 || position > getCount()) {
- return;
- }
- window.acquireReference();
- try {
- int oldpos = mPos;
- mPos = position - 1;
- window.clear();
- window.setStartPosition(position);
- int columnNum = getColumnCount();
- window.setNumColumns(columnNum);
- while (moveToNext() && window.allocRow()) {
- for (int i = 0; i < columnNum; i++) {
- String field = getString(i);
- if (field != null) {
- if (!window.putString(field, mPos, i)) {
- window.freeLastRow();
- break;
- }
- } else {
- if (!window.putNull(mPos, i)) {
- window.freeLastRow();
- break;
- }
- }
- }
- }
-
- mPos = oldpos;
- } catch (IllegalStateException e){
- // simply ignore it
- } finally {
- window.releaseReference();
- }
- }
-
- public final boolean move(int offset) {
- return moveToPosition(mPos + offset);
- }
-
- public final boolean moveToFirst() {
- return moveToPosition(0);
- }
-
- public final boolean moveToLast() {
- return moveToPosition(getCount() - 1);
- }
-
- public final boolean moveToNext() {
- return moveToPosition(mPos + 1);
- }
-
- public final boolean moveToPrevious() {
- return moveToPosition(mPos - 1);
- }
-
- public final boolean isFirst() {
- return mPos == 0 && getCount() != 0;
- }
-
- public final boolean isLast() {
- int cnt = getCount();
- return mPos == (cnt - 1) && cnt != 0;
- }
-
- public final boolean isBeforeFirst() {
- if (getCount() == 0) {
- return true;
- }
- return mPos == -1;
- }
-
- public final boolean isAfterLast() {
- if (getCount() == 0) {
- return true;
- }
- return mPos == getCount();
- }
-
- public int getColumnIndex(String columnName) {
- // Hack according to bug 903852
- final int periodIndex = columnName.lastIndexOf('.');
- if (periodIndex != -1) {
- Exception e = new Exception();
- Log.e(TAG, "requesting column name with table name -- " + columnName, e);
- columnName = columnName.substring(periodIndex + 1);
- }
-
- String columnNames[] = getColumnNames();
- int length = columnNames.length;
- for (int i = 0; i < length; i++) {
- if (columnNames[i].equalsIgnoreCase(columnName)) {
- return i;
- }
- }
-
- if (Config.LOGV) {
- if (getCount() > 0) {
- Log.w("AbstractCursor", "Unknown column " + columnName);
- }
- }
- return -1;
- }
-
- public int getColumnIndexOrThrow(String columnName) {
- final int index = getColumnIndex(columnName);
- if (index < 0) {
- throw new IllegalArgumentException("column '" + columnName + "' does not exist");
- }
- return index;
- }
-
- public String getColumnName(int columnIndex) {
- return getColumnNames()[columnIndex];
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateBlob(int columnIndex, byte[] value) {
- return update(columnIndex, value);
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateString(int columnIndex, String value) {
- return update(columnIndex, value);
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateShort(int columnIndex, short value) {
- return update(columnIndex, Short.valueOf(value));
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateInt(int columnIndex, int value) {
- return update(columnIndex, Integer.valueOf(value));
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateLong(int columnIndex, long value) {
- return update(columnIndex, Long.valueOf(value));
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateFloat(int columnIndex, float value) {
- return update(columnIndex, Float.valueOf(value));
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateDouble(int columnIndex, double value) {
- return update(columnIndex, Double.valueOf(value));
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateToNull(int columnIndex) {
- return update(columnIndex, null);
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean update(int columnIndex, Object obj) {
- if (!supportsUpdates()) {
- return false;
- }
-
- // Long.valueOf() returns null sometimes!
-// Long rowid = Long.valueOf(getLong(mRowIdColumnIndex));
- Long rowid = new Long(getLong(mRowIdColumnIndex));
- if (rowid == null) {
- throw new IllegalStateException("null rowid. mRowIdColumnIndex = " + mRowIdColumnIndex);
- }
-
- synchronized(mUpdatedRows) {
- Map<String, Object> row = mUpdatedRows.get(rowid);
- if (row == null) {
- row = new HashMap<String, Object>();
- mUpdatedRows.put(rowid, row);
- }
- row.put(getColumnNames()[columnIndex], obj);
- }
-
- return true;
- }
-
- /**
- * Returns <code>true</code> if there are pending updates that have not yet been committed.
- *
- * @return <code>true</code> if there are pending updates that have not yet been committed.
- * @hide
- * @deprecated
- */
- public boolean hasUpdates() {
- synchronized(mUpdatedRows) {
- return mUpdatedRows.size() > 0;
- }
- }
-
- /**
- * @hide
- * @deprecated
- */
- public void abortUpdates() {
- synchronized(mUpdatedRows) {
- mUpdatedRows.clear();
- }
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean commitUpdates() {
- return commitUpdates(null);
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean supportsUpdates() {
- return mRowIdColumnIndex != -1;
- }
-
- public void registerContentObserver(ContentObserver observer) {
- mContentObservable.registerObserver(observer);
- }
-
- public void unregisterContentObserver(ContentObserver observer) {
- // cursor will unregister all observers when it close
- if (!mClosed) {
- mContentObservable.unregisterObserver(observer);
- }
- }
-
- /**
- * @hide pending API council approval
- */
- protected void notifyDataSetChange() {
- mDataSetObservable.notifyChanged();
- }
-
- /**
- * @hide pending API council approval
- */
- protected DataSetObservable getDataSetObservable() {
- return mDataSetObservable;
-
- }
- public void registerDataSetObserver(DataSetObserver observer) {
- mDataSetObservable.registerObserver(observer);
-
- }
-
- public void unregisterDataSetObserver(DataSetObserver observer) {
- mDataSetObservable.unregisterObserver(observer);
- }
-
- /**
- * Subclasses must call this method when they finish committing updates to notify all
- * observers.
- *
- * @param selfChange
- */
- protected void onChange(boolean selfChange) {
- synchronized (mSelfObserverLock) {
- mContentObservable.dispatchChange(selfChange);
- if (mNotifyUri != null && selfChange) {
- mContentResolver.notifyChange(mNotifyUri, mSelfObserver);
- }
- }
- }
-
- /**
- * Specifies a content URI to watch for changes.
- *
- * @param cr The content resolver from the caller's context.
- * @param notifyUri The URI to watch for changes. This can be a
- * specific row URI, or a base URI for a whole class of content.
- */
- public void setNotificationUri(ContentResolver cr, Uri notifyUri) {
- synchronized (mSelfObserverLock) {
- mNotifyUri = notifyUri;
- mContentResolver = cr;
- if (mSelfObserver != null) {
- mContentResolver.unregisterContentObserver(mSelfObserver);
- }
- mSelfObserver = new SelfContentObserver(this);
- mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);
- mSelfObserverRegistered = true;
- }
- }
-
- public boolean getWantsAllOnMoveCalls() {
- return false;
- }
-
- public Bundle getExtras() {
- return Bundle.EMPTY;
- }
-
- public Bundle respond(Bundle extras) {
- return Bundle.EMPTY;
- }
-
- /**
- * This function returns true if the field has been updated and is
- * used in conjunction with {@link #getUpdatedField} to allow subclasses to
- * support reading uncommitted updates. NOTE: This function and
- * {@link #getUpdatedField} should be called together inside of a
- * block synchronized on mUpdatedRows.
- *
- * @param columnIndex the column index of the field to check
- * @return true if the field has been updated, false otherwise
- */
- protected boolean isFieldUpdated(int columnIndex) {
- if (mRowIdColumnIndex != -1 && mUpdatedRows.size() > 0) {
- Map<String, Object> updates = mUpdatedRows.get(mCurrentRowID);
- if (updates != null && updates.containsKey(getColumnNames()[columnIndex])) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * This function returns the uncommitted updated value for the field
- * at columnIndex. NOTE: This function and {@link #isFieldUpdated} should
- * be called together inside of a block synchronized on mUpdatedRows.
- *
- * @param columnIndex the column index of the field to retrieve
- * @return the updated value
- */
- protected Object getUpdatedField(int columnIndex) {
- Map<String, Object> updates = mUpdatedRows.get(mCurrentRowID);
- return updates.get(getColumnNames()[columnIndex]);
- }
-
- /**
- * This function throws CursorIndexOutOfBoundsException if
- * the cursor position is out of bounds. Subclass implementations of
- * the get functions should call this before attempting
- * to retrieve data.
- *
- * @throws CursorIndexOutOfBoundsException
- */
- protected void checkPosition() {
- if (-1 == mPos || getCount() == mPos) {
- throw new CursorIndexOutOfBoundsException(mPos, getCount());
- }
- }
-
- @Override
- protected void finalize() {
- if (mSelfObserver != null && mSelfObserverRegistered == true) {
- mContentResolver.unregisterContentObserver(mSelfObserver);
- }
- }
-
- /**
- * Cursors use this class to track changes others make to their URI.
- */
- protected static class SelfContentObserver extends ContentObserver {
- WeakReference<AbstractCursor> mCursor;
-
- public SelfContentObserver(AbstractCursor cursor) {
- super(null);
- mCursor = new WeakReference<AbstractCursor>(cursor);
- }
-
- @Override
- public boolean deliverSelfNotifications() {
- return false;
- }
-
- @Override
- public void onChange(boolean selfChange) {
- AbstractCursor cursor = mCursor.get();
- if (cursor != null) {
- cursor.onChange(false);
- }
- }
- }
-
- /**
- * This HashMap contains a mapping from Long rowIDs to another Map
- * that maps from String column names to new values. A NULL value means to
- * remove an existing value, and all numeric values are in their class
- * forms, i.e. Integer, Long, Float, etc.
- */
- protected HashMap<Long, Map<String, Object>> mUpdatedRows;
-
- /**
- * This must be set to the index of the row ID column by any
- * subclass that wishes to support updates.
- */
- protected int mRowIdColumnIndex;
-
- protected int mPos;
- protected Long mCurrentRowID;
- protected ContentResolver mContentResolver;
- protected boolean mClosed = false;
- private Uri mNotifyUri;
- private ContentObserver mSelfObserver;
- final private Object mSelfObserverLock = new Object();
- private boolean mSelfObserverRegistered;
-}
diff --git a/core/java/android/database/AbstractWindowedCursor.java b/core/java/android/database/AbstractWindowedCursor.java
deleted file mode 100644
index 4ac0aef..0000000
--- a/core/java/android/database/AbstractWindowedCursor.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-/**
- * A base class for Cursors that store their data in {@link CursorWindow}s.
- */
-public abstract class AbstractWindowedCursor extends AbstractCursor
-{
- @Override
- public byte[] getBlob(int columnIndex)
- {
- checkPosition();
-
- synchronized(mUpdatedRows) {
- if (isFieldUpdated(columnIndex)) {
- return (byte[])getUpdatedField(columnIndex);
- }
- }
-
- return mWindow.getBlob(mPos, columnIndex);
- }
-
- @Override
- public String getString(int columnIndex)
- {
- checkPosition();
-
- synchronized(mUpdatedRows) {
- if (isFieldUpdated(columnIndex)) {
- return (String)getUpdatedField(columnIndex);
- }
- }
-
- return mWindow.getString(mPos, columnIndex);
- }
-
- @Override
- public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer)
- {
- checkPosition();
-
- synchronized(mUpdatedRows) {
- if (isFieldUpdated(columnIndex)) {
- super.copyStringToBuffer(columnIndex, buffer);
- }
- }
-
- mWindow.copyStringToBuffer(mPos, columnIndex, buffer);
- }
-
- @Override
- public short getShort(int columnIndex)
- {
- checkPosition();
-
- synchronized(mUpdatedRows) {
- if (isFieldUpdated(columnIndex)) {
- Number value = (Number)getUpdatedField(columnIndex);
- return value.shortValue();
- }
- }
-
- return mWindow.getShort(mPos, columnIndex);
- }
-
- @Override
- public int getInt(int columnIndex)
- {
- checkPosition();
-
- synchronized(mUpdatedRows) {
- if (isFieldUpdated(columnIndex)) {
- Number value = (Number)getUpdatedField(columnIndex);
- return value.intValue();
- }
- }
-
- return mWindow.getInt(mPos, columnIndex);
- }
-
- @Override
- public long getLong(int columnIndex)
- {
- checkPosition();
-
- synchronized(mUpdatedRows) {
- if (isFieldUpdated(columnIndex)) {
- Number value = (Number)getUpdatedField(columnIndex);
- return value.longValue();
- }
- }
-
- return mWindow.getLong(mPos, columnIndex);
- }
-
- @Override
- public float getFloat(int columnIndex)
- {
- checkPosition();
-
- synchronized(mUpdatedRows) {
- if (isFieldUpdated(columnIndex)) {
- Number value = (Number)getUpdatedField(columnIndex);
- return value.floatValue();
- }
- }
-
- return mWindow.getFloat(mPos, columnIndex);
- }
-
- @Override
- public double getDouble(int columnIndex)
- {
- checkPosition();
-
- synchronized(mUpdatedRows) {
- if (isFieldUpdated(columnIndex)) {
- Number value = (Number)getUpdatedField(columnIndex);
- return value.doubleValue();
- }
- }
-
- return mWindow.getDouble(mPos, columnIndex);
- }
-
- @Override
- public boolean isNull(int columnIndex)
- {
- checkPosition();
-
- synchronized(mUpdatedRows) {
- if (isFieldUpdated(columnIndex)) {
- return getUpdatedField(columnIndex) == null;
- }
- }
-
- return mWindow.isNull(mPos, columnIndex);
- }
-
- public boolean isBlob(int columnIndex)
- {
- checkPosition();
-
- synchronized(mUpdatedRows) {
- if (isFieldUpdated(columnIndex)) {
- Object object = getUpdatedField(columnIndex);
- return object == null || object instanceof byte[];
- }
- }
-
- return mWindow.isBlob(mPos, columnIndex);
- }
-
- @Override
- protected void checkPosition()
- {
- super.checkPosition();
-
- if (mWindow == null) {
- throw new StaleDataException("Access closed cursor");
- }
- }
-
- @Override
- public CursorWindow getWindow() {
- return mWindow;
- }
-
- /**
- * Set a new cursor window to cursor, usually set a remote cursor window
- * @param window cursor window
- */
- public void setWindow(CursorWindow window) {
- if (mWindow != null) {
- mWindow.close();
- }
- mWindow = window;
- }
-
- public boolean hasWindow() {
- return mWindow != null;
- }
-
- /**
- * This needs be updated in {@link #onMove} by subclasses, and
- * needs to be set to NULL when the contents of the cursor change.
- */
- protected CursorWindow mWindow;
-}
diff --git a/core/java/android/database/BulkCursorNative.java b/core/java/android/database/BulkCursorNative.java
deleted file mode 100644
index baa94d8..0000000
--- a/core/java/android/database/BulkCursorNative.java
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-import android.os.Binder;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Bundle;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Native implementation of the bulk cursor. This is only for use in implementing
- * IPC, application code should use the Cursor interface.
- *
- * {@hide}
- */
-public abstract class BulkCursorNative extends Binder implements IBulkCursor
-{
- public BulkCursorNative()
- {
- attachInterface(this, descriptor);
- }
-
- /**
- * Cast a Binder object into a content resolver interface, generating
- * a proxy if needed.
- */
- static public IBulkCursor asInterface(IBinder obj)
- {
- if (obj == null) {
- return null;
- }
- IBulkCursor in = (IBulkCursor)obj.queryLocalInterface(descriptor);
- if (in != null) {
- return in;
- }
-
- return new BulkCursorProxy(obj);
- }
-
- @Override
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
- throws RemoteException {
- try {
- switch (code) {
- case GET_CURSOR_WINDOW_TRANSACTION: {
- data.enforceInterface(IBulkCursor.descriptor);
- int startPos = data.readInt();
- CursorWindow window = getWindow(startPos);
- if (window == null) {
- reply.writeInt(0);
- return true;
- }
- reply.writeNoException();
- reply.writeInt(1);
- window.writeToParcel(reply, 0);
- return true;
- }
-
- case COUNT_TRANSACTION: {
- data.enforceInterface(IBulkCursor.descriptor);
- int count = count();
- reply.writeNoException();
- reply.writeInt(count);
- return true;
- }
-
- case GET_COLUMN_NAMES_TRANSACTION: {
- data.enforceInterface(IBulkCursor.descriptor);
- String[] columnNames = getColumnNames();
- reply.writeNoException();
- reply.writeInt(columnNames.length);
- int length = columnNames.length;
- for (int i = 0; i < length; i++) {
- reply.writeString(columnNames[i]);
- }
- return true;
- }
-
- case DEACTIVATE_TRANSACTION: {
- data.enforceInterface(IBulkCursor.descriptor);
- deactivate();
- reply.writeNoException();
- return true;
- }
-
- case CLOSE_TRANSACTION: {
- data.enforceInterface(IBulkCursor.descriptor);
- close();
- reply.writeNoException();
- return true;
- }
-
- case REQUERY_TRANSACTION: {
- data.enforceInterface(IBulkCursor.descriptor);
- IContentObserver observer =
- IContentObserver.Stub.asInterface(data.readStrongBinder());
- CursorWindow window = CursorWindow.CREATOR.createFromParcel(data);
- int count = requery(observer, window);
- reply.writeNoException();
- reply.writeInt(count);
- reply.writeBundle(getExtras());
- return true;
- }
-
- case UPDATE_ROWS_TRANSACTION: {
- data.enforceInterface(IBulkCursor.descriptor);
- // TODO - what ClassLoader should be passed to readHashMap?
- // TODO - switch to Bundle
- HashMap<Long, Map<String, Object>> values = data.readHashMap(null);
- boolean result = updateRows(values);
- reply.writeNoException();
- reply.writeInt((result == true ? 1 : 0));
- return true;
- }
-
- case DELETE_ROW_TRANSACTION: {
- data.enforceInterface(IBulkCursor.descriptor);
- int position = data.readInt();
- boolean result = deleteRow(position);
- reply.writeNoException();
- reply.writeInt((result == true ? 1 : 0));
- return true;
- }
-
- case ON_MOVE_TRANSACTION: {
- data.enforceInterface(IBulkCursor.descriptor);
- int position = data.readInt();
- onMove(position);
- reply.writeNoException();
- return true;
- }
-
- case WANTS_ON_MOVE_TRANSACTION: {
- data.enforceInterface(IBulkCursor.descriptor);
- boolean result = getWantsAllOnMoveCalls();
- reply.writeNoException();
- reply.writeInt(result ? 1 : 0);
- return true;
- }
-
- case GET_EXTRAS_TRANSACTION: {
- data.enforceInterface(IBulkCursor.descriptor);
- Bundle extras = getExtras();
- reply.writeNoException();
- reply.writeBundle(extras);
- return true;
- }
-
- case RESPOND_TRANSACTION: {
- data.enforceInterface(IBulkCursor.descriptor);
- Bundle extras = data.readBundle();
- Bundle returnExtras = respond(extras);
- reply.writeNoException();
- reply.writeBundle(returnExtras);
- return true;
- }
- }
- } catch (Exception e) {
- DatabaseUtils.writeExceptionToParcel(reply, e);
- return true;
- }
-
- return super.onTransact(code, data, reply, flags);
- }
-
- public IBinder asBinder()
- {
- return this;
- }
-}
-
-
-final class BulkCursorProxy implements IBulkCursor {
- private IBinder mRemote;
- private Bundle mExtras;
-
- public BulkCursorProxy(IBinder remote)
- {
- mRemote = remote;
- mExtras = null;
- }
-
- public IBinder asBinder()
- {
- return mRemote;
- }
-
- public CursorWindow getWindow(int startPos) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IBulkCursor.descriptor);
-
- data.writeInt(startPos);
-
- mRemote.transact(GET_CURSOR_WINDOW_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
-
- CursorWindow window = null;
- if (reply.readInt() == 1) {
- window = CursorWindow.newFromParcel(reply);
- }
-
- data.recycle();
- reply.recycle();
-
- return window;
- }
-
- public void onMove(int position) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IBulkCursor.descriptor);
-
- data.writeInt(position);
-
- mRemote.transact(ON_MOVE_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
-
- data.recycle();
- reply.recycle();
- }
-
- public int count() throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IBulkCursor.descriptor);
-
- boolean result = mRemote.transact(COUNT_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
-
- int count;
- if (result == false) {
- count = -1;
- } else {
- count = reply.readInt();
- }
- data.recycle();
- reply.recycle();
- return count;
- }
-
- public String[] getColumnNames() throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IBulkCursor.descriptor);
-
- mRemote.transact(GET_COLUMN_NAMES_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
-
- String[] columnNames = null;
- int numColumns = reply.readInt();
- columnNames = new String[numColumns];
- for (int i = 0; i < numColumns; i++) {
- columnNames[i] = reply.readString();
- }
-
- data.recycle();
- reply.recycle();
- return columnNames;
- }
-
- public void deactivate() throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IBulkCursor.descriptor);
-
- mRemote.transact(DEACTIVATE_TRANSACTION, data, reply, 0);
- DatabaseUtils.readExceptionFromParcel(reply);
-
- data.recycle();
- reply.recycle();
- }
-
- public void close() throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IBulkCursor.descriptor);
-
- mRemote.transact(CLOSE_TRANSACTION, data, reply, 0);
- DatabaseUtils.readExceptionFromParcel(reply);
-
- data.recycle();
- reply.recycle();
- }
-
- public int requery(IContentObserver observer, CursorWindow window) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IBulkCursor.descriptor);
-
- data.writeStrongInterface(observer);
- window.writeToParcel(data, 0);
-
- boolean result = mRemote.transact(REQUERY_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
-
- int count;
- if (!result) {
- count = -1;
- } else {
- count = reply.readInt();
- mExtras = reply.readBundle();
- }
-
- data.recycle();
- reply.recycle();
-
- return count;
- }
-
- public boolean updateRows(Map values) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IBulkCursor.descriptor);
-
- data.writeMap(values);
-
- mRemote.transact(UPDATE_ROWS_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
-
- boolean result = (reply.readInt() == 1 ? true : false);
-
- data.recycle();
- reply.recycle();
-
- return result;
- }
-
- public boolean deleteRow(int position) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IBulkCursor.descriptor);
-
- data.writeInt(position);
-
- mRemote.transact(DELETE_ROW_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
-
- boolean result = (reply.readInt() == 1 ? true : false);
-
- data.recycle();
- reply.recycle();
-
- return result;
- }
-
- public boolean getWantsAllOnMoveCalls() throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IBulkCursor.descriptor);
-
- mRemote.transact(WANTS_ON_MOVE_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
-
- int result = reply.readInt();
- data.recycle();
- reply.recycle();
- return result != 0;
- }
-
- public Bundle getExtras() throws RemoteException {
- if (mExtras == null) {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IBulkCursor.descriptor);
-
- mRemote.transact(GET_EXTRAS_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
-
- mExtras = reply.readBundle();
- data.recycle();
- reply.recycle();
- }
- return mExtras;
- }
-
- public Bundle respond(Bundle extras) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
-
- data.writeInterfaceToken(IBulkCursor.descriptor);
-
- data.writeBundle(extras);
-
- mRemote.transact(RESPOND_TRANSACTION, data, reply, 0);
-
- DatabaseUtils.readExceptionFromParcel(reply);
-
- Bundle returnExtras = reply.readBundle();
- data.recycle();
- reply.recycle();
- return returnExtras;
- }
-}
-
diff --git a/core/java/android/database/BulkCursorToCursorAdaptor.java b/core/java/android/database/BulkCursorToCursorAdaptor.java
deleted file mode 100644
index c26810a..0000000
--- a/core/java/android/database/BulkCursorToCursorAdaptor.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-import android.os.RemoteException;
-import android.os.Bundle;
-import android.util.Log;
-
-import java.util.Map;
-
-/**
- * Adapts an {@link IBulkCursor} to a {@link Cursor} for use in the local
- * process.
- *
- * {@hide}
- */
-public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor {
- private static final String TAG = "BulkCursor";
-
- private SelfContentObserver mObserverBridge;
- private IBulkCursor mBulkCursor;
- private int mCount;
- private String[] mColumns;
- private boolean mWantsAllOnMoveCalls;
-
- public void set(IBulkCursor bulkCursor) {
- mBulkCursor = bulkCursor;
-
- try {
- mCount = mBulkCursor.count();
- mWantsAllOnMoveCalls = mBulkCursor.getWantsAllOnMoveCalls();
-
- // Search for the rowID column index and set it for our parent
- mColumns = mBulkCursor.getColumnNames();
- int length = mColumns.length;
- for (int i = 0; i < length; i++) {
- if (mColumns[i].equals("_id")) {
- mRowIdColumnIndex = i;
- break;
- }
- }
- } catch (RemoteException ex) {
- Log.e(TAG, "Setup failed because the remote process is dead");
- }
- }
-
- /**
- * Gets a SelfDataChangeOberserver that can be sent to a remote
- * process to receive change notifications over IPC.
- *
- * @return A SelfContentObserver hooked up to this Cursor
- */
- public synchronized IContentObserver getObserver() {
- if (mObserverBridge == null) {
- mObserverBridge = new SelfContentObserver(this);
- }
- return mObserverBridge.getContentObserver();
- }
-
- @Override
- public int getCount() {
- return mCount;
- }
-
- @Override
- public boolean onMove(int oldPosition, int newPosition) {
- try {
- // Make sure we have the proper window
- if (mWindow != null) {
- if (newPosition < mWindow.getStartPosition() ||
- newPosition >= (mWindow.getStartPosition() + mWindow.getNumRows())) {
- mWindow = mBulkCursor.getWindow(newPosition);
- } else if (mWantsAllOnMoveCalls) {
- mBulkCursor.onMove(newPosition);
- }
- } else {
- mWindow = mBulkCursor.getWindow(newPosition);
- }
- } catch (RemoteException ex) {
- // We tried to get a window and failed
- Log.e(TAG, "Unable to get window because the remote process is dead");
- return false;
- }
-
- // Couldn't obtain a window, something is wrong
- if (mWindow == null) {
- return false;
- }
-
- return true;
- }
-
- @Override
- public void deactivate() {
- // This will call onInvalidated(), so make sure to do it before calling release,
- // which is what actually makes the data set invalid.
- super.deactivate();
-
- try {
- mBulkCursor.deactivate();
- } catch (RemoteException ex) {
- Log.w(TAG, "Remote process exception when deactivating");
- }
- mWindow = null;
- }
-
- @Override
- public void close() {
- super.close();
- try {
- mBulkCursor.close();
- } catch (RemoteException ex) {
- Log.w(TAG, "Remote process exception when closing");
- }
- mWindow = null;
- }
-
- @Override
- public boolean requery() {
- try {
- int oldCount = mCount;
- //TODO get the window from a pool somewhere to avoid creating the memory dealer
- mCount = mBulkCursor.requery(getObserver(), new CursorWindow(
- false /* the window will be accessed across processes */));
- if (mCount != -1) {
- mPos = -1;
- mWindow = null;
-
- // super.requery() will call onChanged. Do it here instead of relying on the
- // observer from the far side so that observers can see a correct value for mCount
- // when responding to onChanged.
- super.requery();
- return true;
- } else {
- deactivate();
- return false;
- }
- } catch (Exception ex) {
- Log.e(TAG, "Unable to requery because the remote process exception " + ex.getMessage());
- deactivate();
- return false;
- }
- }
-
- /**
- * @hide
- * @deprecated
- */
- @Override
- public boolean deleteRow() {
- try {
- boolean result = mBulkCursor.deleteRow(mPos);
- if (result != false) {
- // The window contains the old value, discard it
- mWindow = null;
-
- // Fix up the position
- mCount = mBulkCursor.count();
- if (mPos < mCount) {
- int oldPos = mPos;
- mPos = -1;
- moveToPosition(oldPos);
- } else {
- mPos = mCount;
- }
-
- // Send the change notification
- onChange(true);
- }
- return result;
- } catch (RemoteException ex) {
- Log.e(TAG, "Unable to delete row because the remote process is dead");
- return false;
- }
- }
-
- @Override
- public String[] getColumnNames() {
- return mColumns;
- }
-
- /**
- * @hide
- * @deprecated
- */
- @Override
- public boolean commitUpdates(Map<? extends Long,
- ? extends Map<String,Object>> additionalValues) {
- if (!supportsUpdates()) {
- Log.e(TAG, "commitUpdates not supported on this cursor, did you include the _id column?");
- return false;
- }
-
- synchronized(mUpdatedRows) {
- if (additionalValues != null) {
- mUpdatedRows.putAll(additionalValues);
- }
-
- if (mUpdatedRows.size() <= 0) {
- return false;
- }
-
- try {
- boolean result = mBulkCursor.updateRows(mUpdatedRows);
-
- if (result == true) {
- mUpdatedRows.clear();
-
- // Send the change notification
- onChange(true);
- }
- return result;
- } catch (RemoteException ex) {
- Log.e(TAG, "Unable to commit updates because the remote process is dead");
- return false;
- }
- }
- }
-
- @Override
- public Bundle getExtras() {
- try {
- return mBulkCursor.getExtras();
- } catch (RemoteException e) {
- // This should never happen because the system kills processes that are using remote
- // cursors when the provider process is killed.
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public Bundle respond(Bundle extras) {
- try {
- return mBulkCursor.respond(extras);
- } catch (RemoteException e) {
- // This should never happen because the system kills processes that are using remote
- // cursors when the provider process is killed.
- throw new RuntimeException(e);
- }
- }
-}
-
diff --git a/core/java/android/database/CharArrayBuffer.java b/core/java/android/database/CharArrayBuffer.java
deleted file mode 100644
index 73781b7..0000000
--- a/core/java/android/database/CharArrayBuffer.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-/**
- * This is used for {@link Cursor#copyStringToBuffer}
- */
-public final class CharArrayBuffer {
- public CharArrayBuffer(int size) {
- data = new char[size];
- }
-
- public CharArrayBuffer(char[] buf) {
- data = buf;
- }
-
- public char[] data; // In and out parameter
- public int sizeCopied; // Out parameter
-}
diff --git a/core/java/android/database/ContentObservable.java b/core/java/android/database/ContentObservable.java
deleted file mode 100644
index 8d7b7c5..0000000
--- a/core/java/android/database/ContentObservable.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-/**
- * A specialization of Observable for ContentObserver that provides methods for
- * invoking the various callback methods of ContentObserver.
- */
-public class ContentObservable extends Observable<ContentObserver> {
-
- @Override
- public void registerObserver(ContentObserver observer) {
- super.registerObserver(observer);
- }
-
- /**
- * invokes dispatchUpdate on each observer, unless the observer doesn't want
- * self-notifications and the update is from a self-notification
- * @param selfChange
- */
- public void dispatchChange(boolean selfChange) {
- synchronized(mObservers) {
- for (ContentObserver observer : mObservers) {
- if (!selfChange || observer.deliverSelfNotifications()) {
- observer.dispatchChange(selfChange);
- }
- }
- }
- }
-
- /**
- * invokes onChange on each observer
- * @param selfChange
- */
- public void notifyChange(boolean selfChange) {
- synchronized(mObservers) {
- for (ContentObserver observer : mObservers) {
- observer.onChange(selfChange);
- }
- }
- }
-}
diff --git a/core/java/android/database/ContentObserver.java b/core/java/android/database/ContentObserver.java
deleted file mode 100644
index 3b829a3..0000000
--- a/core/java/android/database/ContentObserver.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-import android.os.Handler;
-
-/**
- * Receives call backs for changes to content. Must be implemented by objects which are added
- * to a {@link ContentObservable}.
- */
-public abstract class ContentObserver {
-
- private Transport mTransport;
-
- // Protects mTransport
- private Object lock = new Object();
-
- /* package */ Handler mHandler;
-
- private final class NotificationRunnable implements Runnable {
-
- private boolean mSelf;
-
- public NotificationRunnable(boolean self) {
- mSelf = self;
- }
-
- public void run() {
- ContentObserver.this.onChange(mSelf);
- }
- }
-
- private static final class Transport extends IContentObserver.Stub {
- ContentObserver mContentObserver;
-
- public Transport(ContentObserver contentObserver) {
- mContentObserver = contentObserver;
- }
-
- public boolean deliverSelfNotifications() {
- ContentObserver contentObserver = mContentObserver;
- if (contentObserver != null) {
- return contentObserver.deliverSelfNotifications();
- }
- return false;
- }
-
- public void onChange(boolean selfChange) {
- ContentObserver contentObserver = mContentObserver;
- if (contentObserver != null) {
- contentObserver.dispatchChange(selfChange);
- }
- }
-
- public void releaseContentObserver() {
- mContentObserver = null;
- }
- }
-
- /**
- * onChange() will happen on the provider Handler.
- *
- * @param handler The handler to run {@link #onChange} on.
- */
- public ContentObserver(Handler handler) {
- mHandler = handler;
- }
-
- /**
- * Gets access to the binder transport object. Not for public consumption.
- *
- * {@hide}
- */
- public IContentObserver getContentObserver() {
- synchronized(lock) {
- if (mTransport == null) {
- mTransport = new Transport(this);
- }
- return mTransport;
- }
- }
-
- /**
- * Gets access to the binder transport object, and unlinks the transport object
- * from the ContentObserver. Not for public consumption.
- *
- * {@hide}
- */
- public IContentObserver releaseContentObserver() {
- synchronized(lock) {
- Transport oldTransport = mTransport;
- if (oldTransport != null) {
- oldTransport.releaseContentObserver();
- mTransport = null;
- }
- return oldTransport;
- }
- }
-
- /**
- * Returns true if this observer is interested in notifications for changes
- * made through the cursor the observer is registered with.
- */
- public boolean deliverSelfNotifications() {
- return false;
- }
-
- /**
- * This method is called when a change occurs to the cursor that
- * is being observed.
- *
- * @param selfChange true if the update was caused by a call to <code>commit</code> on the
- * cursor that is being observed.
- */
- public void onChange(boolean selfChange) {}
-
- public final void dispatchChange(boolean selfChange) {
- if (mHandler == null) {
- onChange(selfChange);
- } else {
- mHandler.post(new NotificationRunnable(selfChange));
- }
- }
-}
diff --git a/core/java/android/database/CrossProcessCursor.java b/core/java/android/database/CrossProcessCursor.java
deleted file mode 100644
index 77ba3a5..0000000
--- a/core/java/android/database/CrossProcessCursor.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-public interface CrossProcessCursor extends Cursor{
- /**
- * returns a pre-filled window, return NULL if no such window
- */
- CursorWindow getWindow();
-
- /**
- * copies cursor data into the window start at pos
- */
- void fillWindow(int pos, CursorWindow winow);
-
- /**
- * This function is called every time the cursor is successfully scrolled
- * to a new position, giving the subclass a chance to update any state it
- * may have. If it returns false the move function will also do so and the
- * cursor will scroll to the beforeFirst position.
- *
- * @param oldPosition the position that we're moving from
- * @param newPosition the position that we're moving to
- * @return true if the move is successful, false otherwise
- */
- boolean onMove(int oldPosition, int newPosition);
-
-}
diff --git a/core/java/android/database/Cursor.java b/core/java/android/database/Cursor.java
deleted file mode 100644
index 79178f4..0000000
--- a/core/java/android/database/Cursor.java
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-import android.content.ContentResolver;
-import android.net.Uri;
-import android.os.Bundle;
-
-import java.util.Map;
-
-/**
- * This interface provides random read-write access to the result set returned
- * by a database query.
- */
-public interface Cursor {
- /**
- * Returns the numbers of rows in the cursor.
- *
- * @return the number of rows in the cursor.
- */
- int getCount();
-
- /**
- * Returns the current position of the cursor in the row set.
- * The value is zero-based. When the row set is first returned the cursor
- * will be at positon -1, which is before the first row. After the
- * last row is returned another call to next() will leave the cursor past
- * the last entry, at a position of count().
- *
- * @return the current cursor position.
- */
- int getPosition();
-
- /**
- * Move the cursor by a relative amount, forward or backward, from the
- * current position. Positive offsets move forwards, negative offsets move
- * backwards. If the final position is outside of the bounds of the result
- * set then the resultant position will be pinned to -1 or count() depending
- * on whether the value is off the front or end of the set, respectively.
- *
- * <p>This method will return true if the requested destination was
- * reachable, otherwise, it returns false. For example, if the cursor is at
- * currently on the second entry in the result set and move(-5) is called,
- * the position will be pinned at -1, and false will be returned.
- *
- * @param offset the offset to be applied from the current position.
- * @return whether the requested move fully succeeded.
- */
- boolean move(int offset);
-
- /**
- * Move the cursor to an absolute position. The valid
- * range of values is -1 &lt;= position &lt;= count.
- *
- * <p>This method will return true if the request destination was reachable,
- * otherwise, it returns false.
- *
- * @param position the zero-based position to move to.
- * @return whether the requested move fully succeeded.
- */
- boolean moveToPosition(int position);
-
- /**
- * Move the cursor to the first row.
- *
- * <p>This method will return false if the cursor is empty.
- *
- * @return whether the move succeeded.
- */
- boolean moveToFirst();
-
- /**
- * Move the cursor to the last row.
- *
- * <p>This method will return false if the cursor is empty.
- *
- * @return whether the move succeeded.
- */
- boolean moveToLast();
-
- /**
- * Move the cursor to the next row.
- *
- * <p>This method will return false if the cursor is already past the
- * last entry in the result set.
- *
- * @return whether the move succeeded.
- */
- boolean moveToNext();
-
- /**
- * Move the cursor to the previous row.
- *
- * <p>This method will return false if the cursor is already before the
- * first entry in the result set.
- *
- * @return whether the move succeeded.
- */
- boolean moveToPrevious();
-
- /**
- * Returns whether the cursor is pointing to the first row.
- *
- * @return whether the cursor is pointing at the first entry.
- */
- boolean isFirst();
-
- /**
- * Returns whether the cursor is pointing to the last row.
- *
- * @return whether the cursor is pointing at the last entry.
- */
- boolean isLast();
-
- /**
- * Returns whether the cursor is pointing to the position before the first
- * row.
- *
- * @return whether the cursor is before the first result.
- */
- boolean isBeforeFirst();
-
- /**
- * Returns whether the cursor is pointing to the position after the last
- * row.
- *
- * @return whether the cursor is after the last result.
- */
- boolean isAfterLast();
-
- /**
- * Removes the row at the current cursor position from the underlying data
- * store. After this method returns the cursor will be pointing to the row
- * after the row that is deleted. This has the side effect of decrementing
- * the result of count() by one.
- * <p>
- * The query must have the row ID column in its selection, otherwise this
- * call will fail.
- *
- * @hide
- * @return whether the record was successfully deleted.
- * @deprecated use {@link ContentResolver#delete(Uri, String, String[])}
- */
- @Deprecated
- boolean deleteRow();
-
- /**
- * Returns the zero-based index for the given column name, or -1 if the column doesn't exist.
- * If you expect the column to exist use {@link #getColumnIndexOrThrow(String)} instead, which
- * will make the error more clear.
- *
- * @param columnName the name of the target column.
- * @return the zero-based column index for the given column name, or -1 if
- * the column name does not exist.
- * @see #getColumnIndexOrThrow(String)
- */
- int getColumnIndex(String columnName);
-
- /**
- * Returns the zero-based index for the given column name, or throws
- * {@link IllegalArgumentException} if the column doesn't exist. If you're not sure if
- * a column will exist or not use {@link #getColumnIndex(String)} and check for -1, which
- * is more efficient than catching the exceptions.
- *
- * @param columnName the name of the target column.
- * @return the zero-based column index for the given column name
- * @see #getColumnIndex(String)
- * @throws IllegalArgumentException if the column does not exist
- */
- int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException;
-
- /**
- * Returns the column name at the given zero-based column index.
- *
- * @param columnIndex the zero-based index of the target column.
- * @return the column name for the given column index.
- */
- String getColumnName(int columnIndex);
-
- /**
- * Returns a string array holding the names of all of the columns in the
- * result set in the order in which they were listed in the result.
- *
- * @return the names of the columns returned in this query.
- */
- String[] getColumnNames();
-
- /**
- * Return total number of columns
- * @return number of columns
- */
- int getColumnCount();
-
- /**
- * Returns the value of the requested column as a byte array.
- *
- * <p>If the native content of that column is not blob exception may throw
- *
- * @param columnIndex the zero-based index of the target column.
- * @return the value of that column as a byte array.
- */
- byte[] getBlob(int columnIndex);
-
- /**
- * Returns the value of the requested column as a String.
- *
- * <p>If the native content of that column is not text the result will be
- * the result of passing the column value to String.valueOf(x).
- *
- * @param columnIndex the zero-based index of the target column.
- * @return the value of that column as a String.
- */
- String getString(int columnIndex);
-
- /**
- * Retrieves the requested column text and stores it in the buffer provided.
- * If the buffer size is not sufficient, a new char buffer will be allocated
- * and assigned to CharArrayBuffer.data
- * @param columnIndex the zero-based index of the target column.
- * if the target column is null, return buffer
- * @param buffer the buffer to copy the text into.
- */
- void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer);
-
- /**
- * Returns the value of the requested column as a short.
- *
- * <p>If the native content of that column is not numeric the result will be
- * the result of passing the column value to Short.valueOf(x).
- *
- * @param columnIndex the zero-based index of the target column.
- * @return the value of that column as a short.
- */
- short getShort(int columnIndex);
-
- /**
- * Returns the value of the requested column as an int.
- *
- * <p>If the native content of that column is not numeric the result will be
- * the result of passing the column value to Integer.valueOf(x).
- *
- * @param columnIndex the zero-based index of the target column.
- * @return the value of that column as an int.
- */
- int getInt(int columnIndex);
-
- /**
- * Returns the value of the requested column as a long.
- *
- * <p>If the native content of that column is not numeric the result will be
- * the result of passing the column value to Long.valueOf(x).
- *
- * @param columnIndex the zero-based index of the target column.
- * @return the value of that column as a long.
- */
- long getLong(int columnIndex);
-
- /**
- * Returns the value of the requested column as a float.
- *
- * <p>If the native content of that column is not numeric the result will be
- * the result of passing the column value to Float.valueOf(x).
- *
- * @param columnIndex the zero-based index of the target column.
- * @return the value of that column as a float.
- */
- float getFloat(int columnIndex);
-
- /**
- * Returns the value of the requested column as a double.
- *
- * <p>If the native content of that column is not numeric the result will be
- * the result of passing the column value to Double.valueOf(x).
- *
- * @param columnIndex the zero-based index of the target column.
- * @return the value of that column as a double.
- */
- double getDouble(int columnIndex);
-
- /**
- * Returns <code>true</code> if the value in the indicated column is null.
- *
- * @param columnIndex the zero-based index of the target column.
- * @return whether the column value is null.
- */
- boolean isNull(int columnIndex);
-
- /**
- * Returns <code>true</code> if the cursor supports updates.
- *
- * @return whether the cursor supports updates.
- * @hide
- * @deprecated use the {@link ContentResolver} update methods instead of the Cursor
- * update methods
- */
- @Deprecated
- boolean supportsUpdates();
-
- /**
- * Returns <code>true</code> if there are pending updates that have not yet been committed.
- *
- * @return <code>true</code> if there are pending updates that have not yet been committed.
- * @hide
- * @deprecated use the {@link ContentResolver} update methods instead of the Cursor
- * update methods
- */
- @Deprecated
- boolean hasUpdates();
-
- /**
- * Updates the value for the given column in the row the cursor is
- * currently pointing at. Updates are not committed to the backing store
- * until {@link #commitUpdates()} is called.
- *
- * @param columnIndex the zero-based index of the target column.
- * @param value the new value.
- * @return whether the operation succeeded.
- * @hide
- * @deprecated use the {@link ContentResolver} update methods instead of the Cursor
- * update methods
- */
- @Deprecated
- boolean updateBlob(int columnIndex, byte[] value);
-
- /**
- * Updates the value for the given column in the row the cursor is
- * currently pointing at. Updates are not committed to the backing store
- * until {@link #commitUpdates()} is called.
- *
- * @param columnIndex the zero-based index of the target column.
- * @param value the new value.
- * @return whether the operation succeeded.
- * @hide
- * @deprecated use the {@link ContentResolver} update methods instead of the Cursor
- * update methods
- */
- @Deprecated
- boolean updateString(int columnIndex, String value);
-
- /**
- * Updates the value for the given column in the row the cursor is
- * currently pointing at. Updates are not committed to the backing store
- * until {@link #commitUpdates()} is called.
- *
- * @param columnIndex the zero-based index of the target column.
- * @param value the new value.
- * @return whether the operation succeeded.
- * @hide
- * @deprecated use the {@link ContentResolver} update methods instead of the Cursor
- * update methods
- */
- @Deprecated
- boolean updateShort(int columnIndex, short value);
-
- /**
- * Updates the value for the given column in the row the cursor is
- * currently pointing at. Updates are not committed to the backing store
- * until {@link #commitUpdates()} is called.
- *
- * @param columnIndex the zero-based index of the target column.
- * @param value the new value.
- * @return whether the operation succeeded.
- * @hide
- * @deprecated use the {@link ContentResolver} update methods instead of the Cursor
- * update methods
- */
- @Deprecated
- boolean updateInt(int columnIndex, int value);
-
- /**
- * Updates the value for the given column in the row the cursor is
- * currently pointing at. Updates are not committed to the backing store
- * until {@link #commitUpdates()} is called.
- *
- * @param columnIndex the zero-based index of the target column.
- * @param value the new value.
- * @return whether the operation succeeded.
- * @hide
- * @deprecated use the {@link ContentResolver} update methods instead of the Cursor
- * update methods
- */
- @Deprecated
- boolean updateLong(int columnIndex, long value);
-
- /**
- * Updates the value for the given column in the row the cursor is
- * currently pointing at. Updates are not committed to the backing store
- * until {@link #commitUpdates()} is called.
- *
- * @param columnIndex the zero-based index of the target column.
- * @param value the new value.
- * @return whether the operation succeeded.
- * @hide
- * @deprecated use the {@link ContentResolver} update methods instead of the Cursor
- * update methods
- */
- @Deprecated
- boolean updateFloat(int columnIndex, float value);
-
- /**
- * Updates the value for the given column in the row the cursor is
- * currently pointing at. Updates are not committed to the backing store
- * until {@link #commitUpdates()} is called.
- *
- * @param columnIndex the zero-based index of the target column.
- * @param value the new value.
- * @return whether the operation succeeded.
- * @hide
- * @deprecated use the {@link ContentResolver} update methods instead of the Cursor
- * update methods
- */
- @Deprecated
- boolean updateDouble(int columnIndex, double value);
-
- /**
- * Removes the value for the given column in the row the cursor is
- * currently pointing at. Updates are not committed to the backing store
- * until {@link #commitUpdates()} is called.
- *
- * @param columnIndex the zero-based index of the target column.
- * @return whether the operation succeeded.
- * @hide
- * @deprecated use the {@link ContentResolver} update methods instead of the Cursor
- * update methods
- */
- @Deprecated
- boolean updateToNull(int columnIndex);
-
- /**
- * Atomically commits all updates to the backing store. After completion,
- * this method leaves the data in an inconsistent state and you should call
- * {@link #requery} before reading data from the cursor again.
- *
- * @return whether the operation succeeded.
- * @hide
- * @deprecated use the {@link ContentResolver} update methods instead of the Cursor
- * update methods
- */
- @Deprecated
- boolean commitUpdates();
-
- /**
- * Atomically commits all updates to the backing store, as well as the
- * updates included in values. After completion,
- * this method leaves the data in an inconsistent state and you should call
- * {@link #requery} before reading data from the cursor again.
- *
- * @param values A map from row IDs to Maps associating column names with
- * updated values. A null value indicates the field should be
- removed.
- * @return whether the operation succeeded.
- * @hide
- * @deprecated use the {@link ContentResolver} update methods instead of the Cursor
- * update methods
- */
- @Deprecated
- boolean commitUpdates(Map<? extends Long,
- ? extends Map<String,Object>> values);
-
- /**
- * Reverts all updates made to the cursor since the last call to
- * commitUpdates.
- * @hide
- * @deprecated use the {@link ContentResolver} update methods instead of the Cursor
- * update methods
- */
- @Deprecated
- void abortUpdates();
-
- /**
- * Deactivates the Cursor, making all calls on it fail until {@link #requery} is called.
- * Inactive Cursors use fewer resources than active Cursors.
- * Calling {@link #requery} will make the cursor active again.
- */
- void deactivate();
-
- /**
- * Performs the query that created the cursor again, refreshing its
- * contents. This may be done at any time, including after a call to {@link
- * #deactivate}.
- *
- * @return true if the requery succeeded, false if not, in which case the
- * cursor becomes invalid.
- */
- boolean requery();
-
- /**
- * Closes the Cursor, releasing all of its resources and making it completely invalid.
- * Unlike {@link #deactivate()} a call to {@link #requery()} will not make the Cursor valid
- * again.
- */
- void close();
-
- /**
- * return true if the cursor is closed
- * @return true if the cursor is closed.
- */
- boolean isClosed();
-
- /**
- * Register an observer that is called when changes happen to the content backing this cursor.
- * Typically the data set won't change until {@link #requery()} is called.
- *
- * @param observer the object that gets notified when the content backing the cursor changes.
- * @see #unregisterContentObserver(ContentObserver)
- */
- void registerContentObserver(ContentObserver observer);
-
- /**
- * Unregister an observer that has previously been registered with this
- * cursor via {@link #registerContentObserver}.
- *
- * @param observer the object to unregister.
- * @see #registerContentObserver(ContentObserver)
- */
- void unregisterContentObserver(ContentObserver observer);
-
- /**
- * Register an observer that is called when changes happen to the contents
- * of the this cursors data set, for example, when the data set is changed via
- * {@link #requery()}, {@link #deactivate()}, or {@link #close()}.
- *
- * @param observer the object that gets notified when the cursors data set changes.
- * @see #unregisterDataSetObserver(DataSetObserver)
- */
- void registerDataSetObserver(DataSetObserver observer);
-
- /**
- * Unregister an observer that has previously been registered with this
- * cursor via {@link #registerContentObserver}.
- *
- * @param observer the object to unregister.
- * @see #registerDataSetObserver(DataSetObserver)
- */
- void unregisterDataSetObserver(DataSetObserver observer);
-
- /**
- * Register to watch a content URI for changes. This can be the URI of a specific data row (for
- * example, "content://my_provider_type/23"), or a a generic URI for a content type.
- *
- * @param cr The content resolver from the caller's context. The listener attached to
- * this resolver will be notified.
- * @param uri The content URI to watch.
- */
- void setNotificationUri(ContentResolver cr, Uri uri);
-
- /**
- * onMove() will only be called across processes if this method returns true.
- * @return whether all cursor movement should result in a call to onMove().
- */
- boolean getWantsAllOnMoveCalls();
-
- /**
- * Returns a bundle of extra values. This is an optional way for cursors to provide out-of-band
- * metadata to their users. One use of this is for reporting on the progress of network requests
- * that are required to fetch data for the cursor.
- *
- * <p>These values may only change when requery is called.
- * @return cursor-defined values, or Bundle.EMTPY if there are no values. Never null.
- */
- Bundle getExtras();
-
- /**
- * This is an out-of-band way for the the user of a cursor to communicate with the cursor. The
- * structure of each bundle is entirely defined by the cursor.
- *
- * <p>One use of this is to tell a cursor that it should retry its network request after it
- * reported an error.
- * @param extras extra values, or Bundle.EMTPY. Never null.
- * @return extra values, or Bundle.EMTPY. Never null.
- */
- Bundle respond(Bundle extras);
-}
diff --git a/core/java/android/database/CursorIndexOutOfBoundsException.java b/core/java/android/database/CursorIndexOutOfBoundsException.java
deleted file mode 100644
index 1f77d00..0000000
--- a/core/java/android/database/CursorIndexOutOfBoundsException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-/**
- * An exception indicating that a cursor is out of bounds.
- */
-public class CursorIndexOutOfBoundsException extends IndexOutOfBoundsException {
-
- public CursorIndexOutOfBoundsException(int index, int size) {
- super("Index " + index + " requested, with a size of " + size);
- }
-
- public CursorIndexOutOfBoundsException(String message) {
- super(message);
- }
-}
diff --git a/core/java/android/database/CursorJoiner.java b/core/java/android/database/CursorJoiner.java
deleted file mode 100644
index e3c2988..0000000
--- a/core/java/android/database/CursorJoiner.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-import java.util.Iterator;
-
-/**
- * Does a join on two cursors using the specified columns. The cursors must already
- * be sorted on each of the specified columns in ascending order. This joiner only
- * supports the case where the tuple of key column values is unique.
- * <p>
- * Typical usage:
- *
- * <pre>
- * CursorJoiner joiner = new CursorJoiner(cursorA, keyColumnsofA, cursorB, keyColumnsofB);
- * for (CursorJointer.Result joinerResult : joiner) {
- * switch (joinerResult) {
- * case LEFT:
- * // handle case where a row in cursorA is unique
- * break;
- * case RIGHT:
- * // handle case where a row in cursorB is unique
- * break;
- * case BOTH:
- * // handle case where a row with the same key is in both cursors
- * break;
- * }
- * }
- * </pre>
- */
-public final class CursorJoiner
- implements Iterator<CursorJoiner.Result>, Iterable<CursorJoiner.Result> {
- private Cursor mCursorLeft;
- private Cursor mCursorRight;
- private boolean mCompareResultIsValid;
- private Result mCompareResult;
- private int[] mColumnsLeft;
- private int[] mColumnsRight;
- private String[] mValues;
-
- /**
- * The result of a call to next().
- */
- public enum Result {
- /** The row currently pointed to by the left cursor is unique */
- RIGHT,
- /** The row currently pointed to by the right cursor is unique */
- LEFT,
- /** The rows pointed to by both cursors are the same */
- BOTH
- }
-
- /**
- * Initializes the CursorJoiner and resets the cursors to the first row. The left and right
- * column name arrays must have the same number of columns.
- * @param cursorLeft The left cursor to compare
- * @param columnNamesLeft The column names to compare from the left cursor
- * @param cursorRight The right cursor to compare
- * @param columnNamesRight The column names to compare from the right cursor
- */
- public CursorJoiner(
- Cursor cursorLeft, String[] columnNamesLeft,
- Cursor cursorRight, String[] columnNamesRight) {
- if (columnNamesLeft.length != columnNamesRight.length) {
- throw new IllegalArgumentException(
- "you must have the same number of columns on the left and right, "
- + columnNamesLeft.length + " != " + columnNamesRight.length);
- }
-
- mCursorLeft = cursorLeft;
- mCursorRight = cursorRight;
-
- mCursorLeft.moveToFirst();
- mCursorRight.moveToFirst();
-
- mCompareResultIsValid = false;
-
- mColumnsLeft = buildColumnIndiciesArray(cursorLeft, columnNamesLeft);
- mColumnsRight = buildColumnIndiciesArray(cursorRight, columnNamesRight);
-
- mValues = new String[mColumnsLeft.length * 2];
- }
-
- public Iterator<Result> iterator() {
- return this;
- }
-
- /**
- * Lookup the indicies of the each column name and return them in an array.
- * @param cursor the cursor that contains the columns
- * @param columnNames the array of names to lookup
- * @return an array of column indices
- */
- private int[] buildColumnIndiciesArray(Cursor cursor, String[] columnNames) {
- int[] columns = new int[columnNames.length];
- for (int i = 0; i < columnNames.length; i++) {
- columns[i] = cursor.getColumnIndexOrThrow(columnNames[i]);
- }
- return columns;
- }
-
- /**
- * Returns whether or not there are more rows to compare using next().
- * @return true if there are more rows to compare
- */
- public boolean hasNext() {
- if (mCompareResultIsValid) {
- switch (mCompareResult) {
- case BOTH:
- return !mCursorLeft.isLast() || !mCursorRight.isLast();
-
- case LEFT:
- return !mCursorLeft.isLast() || !mCursorRight.isAfterLast();
-
- case RIGHT:
- return !mCursorLeft.isAfterLast() || !mCursorRight.isLast();
-
- default:
- throw new IllegalStateException("bad value for mCompareResult, "
- + mCompareResult);
- }
- } else {
- return !mCursorLeft.isAfterLast() || !mCursorRight.isAfterLast();
- }
- }
-
- /**
- * Returns the comparison result of the next row from each cursor. If one cursor
- * has no more rows but the other does then subsequent calls to this will indicate that
- * the remaining rows are unique.
- * <p>
- * The caller must check that hasNext() returns true before calling this.
- * <p>
- * Once next() has been called the cursors specified in the result of the call to
- * next() are guaranteed to point to the row that was indicated. Reading values
- * from the cursor that was not indicated in the call to next() will result in
- * undefined behavior.
- * @return LEFT, if the row pointed to by the left cursor is unique, RIGHT
- * if the row pointed to by the right cursor is unique, BOTH if the rows in both
- * cursors are the same.
- */
- public Result next() {
- if (!hasNext()) {
- throw new IllegalStateException("you must only call next() when hasNext() is true");
- }
- incrementCursors();
- assert hasNext();
-
- boolean hasLeft = !mCursorLeft.isAfterLast();
- boolean hasRight = !mCursorRight.isAfterLast();
-
- if (hasLeft && hasRight) {
- populateValues(mValues, mCursorLeft, mColumnsLeft, 0 /* start filling at index 0 */);
- populateValues(mValues, mCursorRight, mColumnsRight, 1 /* start filling at index 1 */);
- switch (compareStrings(mValues)) {
- case -1:
- mCompareResult = Result.LEFT;
- break;
- case 0:
- mCompareResult = Result.BOTH;
- break;
- case 1:
- mCompareResult = Result.RIGHT;
- break;
- }
- } else if (hasLeft) {
- mCompareResult = Result.LEFT;
- } else {
- assert hasRight;
- mCompareResult = Result.RIGHT;
- }
- mCompareResultIsValid = true;
- return mCompareResult;
- }
-
- public void remove() {
- throw new UnsupportedOperationException("not implemented");
- }
-
- /**
- * Reads the strings from the cursor that are specifed in the columnIndicies
- * array and saves them in values beginning at startingIndex, skipping a slot
- * for each value. If columnIndicies has length 3 and startingIndex is 1, the
- * values will be stored in slots 1, 3, and 5.
- * @param values the String[] to populate
- * @param cursor the cursor from which to read
- * @param columnIndicies the indicies of the values to read from the cursor
- * @param startingIndex the slot in which to start storing values, and must be either 0 or 1.
- */
- private static void populateValues(String[] values, Cursor cursor, int[] columnIndicies,
- int startingIndex) {
- assert startingIndex == 0 || startingIndex == 1;
- for (int i = 0; i < columnIndicies.length; i++) {
- values[startingIndex + i*2] = cursor.getString(columnIndicies[i]);
- }
- }
-
- /**
- * Increment the cursors past the rows indicated in the most recent call to next().
- * This will only have an affect once per call to next().
- */
- private void incrementCursors() {
- if (mCompareResultIsValid) {
- switch (mCompareResult) {
- case LEFT:
- mCursorLeft.moveToNext();
- break;
- case RIGHT:
- mCursorRight.moveToNext();
- break;
- case BOTH:
- mCursorLeft.moveToNext();
- mCursorRight.moveToNext();
- break;
- }
- mCompareResultIsValid = false;
- }
- }
-
- /**
- * Compare the values. Values contains n pairs of strings. If all the pairs of strings match
- * then returns 0. Otherwise returns the comparison result of the first non-matching pair
- * of values, -1 if the first of the pair is less than the second of the pair or 1 if it
- * is greater.
- * @param values the n pairs of values to compare
- * @return -1, 0, or 1 as described above.
- */
- private static int compareStrings(String... values) {
- if ((values.length % 2) != 0) {
- throw new IllegalArgumentException("you must specify an even number of values");
- }
-
- for (int index = 0; index < values.length; index+=2) {
- if (values[index] == null) {
- if (values[index+1] == null) continue;
- return -1;
- }
-
- if (values[index+1] == null) {
- return 1;
- }
-
- int comp = values[index].compareTo(values[index+1]);
- if (comp != 0) {
- return comp < 0 ? -1 : 1;
- }
- }
-
- return 0;
- }
-}
diff --git a/core/java/android/database/CursorToBulkCursorAdaptor.java b/core/java/android/database/CursorToBulkCursorAdaptor.java
deleted file mode 100644
index 19ad946..0000000
--- a/core/java/android/database/CursorToBulkCursorAdaptor.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-import android.database.sqlite.SQLiteMisuseException;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Config;
-import android.util.Log;
-
-import java.util.Map;
-
-
-/**
- * Wraps a BulkCursor around an existing Cursor making it remotable.
- *
- * {@hide}
- */
-public final class CursorToBulkCursorAdaptor extends BulkCursorNative
- implements IBinder.DeathRecipient {
- private static final String TAG = "Cursor";
- private final CrossProcessCursor mCursor;
- private CursorWindow mWindow;
- private final String mProviderName;
- private final boolean mReadOnly;
- private ContentObserverProxy mObserver;
-
- private static final class ContentObserverProxy extends ContentObserver
- {
- protected IContentObserver mRemote;
-
- public ContentObserverProxy(IContentObserver remoteObserver, DeathRecipient recipient) {
- super(null);
- mRemote = remoteObserver;
- try {
- remoteObserver.asBinder().linkToDeath(recipient, 0);
- } catch (RemoteException e) {
- // Do nothing, the far side is dead
- }
- }
-
- public boolean unlinkToDeath(DeathRecipient recipient) {
- return mRemote.asBinder().unlinkToDeath(recipient, 0);
- }
-
- @Override
- public boolean deliverSelfNotifications() {
- // The far side handles the self notifications.
- return false;
- }
-
- @Override
- public void onChange(boolean selfChange) {
- try {
- mRemote.onChange(selfChange);
- } catch (RemoteException ex) {
- // Do nothing, the far side is dead
- }
- }
- }
-
- public CursorToBulkCursorAdaptor(Cursor cursor, IContentObserver observer, String providerName,
- boolean allowWrite, CursorWindow window) {
- try {
- mCursor = (CrossProcessCursor) cursor;
- if (mCursor instanceof AbstractWindowedCursor) {
- AbstractWindowedCursor windowedCursor = (AbstractWindowedCursor) cursor;
- if (windowedCursor.hasWindow()) {
- if (Log.isLoggable(TAG, Log.VERBOSE) || Config.LOGV) {
- Log.v(TAG, "Cross process cursor has a local window before setWindow in "
- + providerName, new RuntimeException());
- }
- }
- windowedCursor.setWindow(window);
- } else {
- mWindow = window;
- mCursor.fillWindow(0, window);
- }
- } catch (ClassCastException e) {
- // TODO Implement this case.
- throw new UnsupportedOperationException(
- "Only CrossProcessCursor cursors are supported across process for now", e);
- }
- mProviderName = providerName;
- mReadOnly = !allowWrite;
-
- createAndRegisterObserverProxy(observer);
- }
-
- public void binderDied() {
- mCursor.close();
- if (mWindow != null) {
- mWindow.close();
- }
- }
-
- public CursorWindow getWindow(int startPos) {
- mCursor.moveToPosition(startPos);
-
- if (mWindow != null) {
- if (startPos < mWindow.getStartPosition() ||
- startPos >= (mWindow.getStartPosition() + mWindow.getNumRows())) {
- mCursor.fillWindow(startPos, mWindow);
- }
- return mWindow;
- } else {
- return ((AbstractWindowedCursor)mCursor).getWindow();
- }
- }
-
- public void onMove(int position) {
- mCursor.onMove(mCursor.getPosition(), position);
- }
-
- public int count() {
- return mCursor.getCount();
- }
-
- public String[] getColumnNames() {
- return mCursor.getColumnNames();
- }
-
- public void deactivate() {
- maybeUnregisterObserverProxy();
- mCursor.deactivate();
- }
-
- public void close() {
- maybeUnregisterObserverProxy();
- mCursor.deactivate();
-
- }
-
- public int requery(IContentObserver observer, CursorWindow window) {
- if (mWindow == null) {
- ((AbstractWindowedCursor)mCursor).setWindow(window);
- }
- try {
- if (!mCursor.requery()) {
- return -1;
- }
- } catch (IllegalStateException e) {
- IllegalStateException leakProgram = new IllegalStateException(
- mProviderName + " Requery misuse db, mCursor isClosed:" +
- mCursor.isClosed(), e);
- throw leakProgram;
- }
-
- if (mWindow != null) {
- mCursor.fillWindow(0, window);
- mWindow = window;
- }
- maybeUnregisterObserverProxy();
- createAndRegisterObserverProxy(observer);
- return mCursor.getCount();
- }
-
- public boolean getWantsAllOnMoveCalls() {
- return mCursor.getWantsAllOnMoveCalls();
- }
-
- /**
- * Create a ContentObserver from the observer and register it as an observer on the
- * underlying cursor.
- * @param observer the IContentObserver that wants to monitor the cursor
- * @throws IllegalStateException if an observer is already registered
- */
- private void createAndRegisterObserverProxy(IContentObserver observer) {
- if (mObserver != null) {
- throw new IllegalStateException("an observer is already registered");
- }
- mObserver = new ContentObserverProxy(observer, this);
- mCursor.registerContentObserver(mObserver);
- }
-
- /** Unregister the observer if it is already registered. */
- private void maybeUnregisterObserverProxy() {
- if (mObserver != null) {
- mCursor.unregisterContentObserver(mObserver);
- mObserver.unlinkToDeath(this);
- mObserver = null;
- }
- }
-
- public boolean updateRows(Map<? extends Long, ? extends Map<String, Object>> values) {
- if (mReadOnly) {
- Log.w("ContentProvider", "Permission Denial: modifying "
- + mProviderName
- + " from pid=" + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return false;
- }
- return mCursor.commitUpdates(values);
- }
-
- public boolean deleteRow(int position) {
- if (mReadOnly) {
- Log.w("ContentProvider", "Permission Denial: modifying "
- + mProviderName
- + " from pid=" + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return false;
- }
- if (mCursor.moveToPosition(position) == false) {
- return false;
- }
- return mCursor.deleteRow();
- }
-
- public Bundle getExtras() {
- return mCursor.getExtras();
- }
-
- public Bundle respond(Bundle extras) {
- return mCursor.respond(extras);
- }
-}
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
deleted file mode 100644
index 8e26730..0000000
--- a/core/java/android/database/CursorWindow.java
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-import android.database.sqlite.SQLiteClosable;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * A buffer containing multiple cursor rows.
- */
-public class CursorWindow extends SQLiteClosable implements Parcelable {
- /** The pointer to the native window class */
- @SuppressWarnings("unused")
- private int nWindow;
-
- private int mStartPos;
-
- /**
- * Creates a new empty window.
- *
- * @param localWindow true if this window will be used in this process only
- */
- public CursorWindow(boolean localWindow) {
- mStartPos = 0;
- native_init(localWindow);
- }
-
- /**
- * Returns the starting position of this window within the entire
- * Cursor's result set.
- *
- * @return the starting position of this window within the entire
- * Cursor's result set.
- */
- public int getStartPosition() {
- return mStartPos;
- }
-
- /**
- * Set the start position of cursor window
- * @param pos
- */
- public void setStartPosition(int pos) {
- mStartPos = pos;
- }
-
- /**
- * Returns the number of rows in this window.
- *
- * @return the number of rows in this window.
- */
- public int getNumRows() {
- acquireReference();
- try {
- return getNumRows_native();
- } finally {
- releaseReference();
- }
- }
-
- private native int getNumRows_native();
- /**
- * Set number of Columns
- * @param columnNum
- * @return true if success
- */
- public boolean setNumColumns(int columnNum) {
- acquireReference();
- try {
- return setNumColumns_native(columnNum);
- } finally {
- releaseReference();
- }
- }
-
- private native boolean setNumColumns_native(int columnNum);
-
- /**
- * Allocate a row in cursor window
- * @return false if cursor window is out of memory
- */
- public boolean allocRow(){
- acquireReference();
- try {
- return allocRow_native();
- } finally {
- releaseReference();
- }
- }
-
- private native boolean allocRow_native();
-
- /**
- * Free the last row
- */
- public void freeLastRow(){
- acquireReference();
- try {
- freeLastRow_native();
- } finally {
- releaseReference();
- }
- }
-
- private native void freeLastRow_native();
-
- /**
- * copy byte array to cursor window
- * @param value
- * @param row
- * @param col
- * @return false if fail to copy
- */
- public boolean putBlob(byte[] value, int row, int col) {
- acquireReference();
- try {
- return putBlob_native(value, row - mStartPos, col);
- } finally {
- releaseReference();
- }
- }
-
- private native boolean putBlob_native(byte[] value, int row, int col);
-
- /**
- * Copy String to cursor window
- * @param value
- * @param row
- * @param col
- * @return false if fail to copy
- */
- public boolean putString(String value, int row, int col) {
- acquireReference();
- try {
- return putString_native(value, row - mStartPos, col);
- } finally {
- releaseReference();
- }
- }
-
- private native boolean putString_native(String value, int row, int col);
-
- /**
- * Copy integer to cursor window
- * @param value
- * @param row
- * @param col
- * @return false if fail to copy
- */
- public boolean putLong(long value, int row, int col) {
- acquireReference();
- try {
- return putLong_native(value, row - mStartPos, col);
- } finally {
- releaseReference();
- }
- }
-
- private native boolean putLong_native(long value, int row, int col);
-
-
- /**
- * Copy double to cursor window
- * @param value
- * @param row
- * @param col
- * @return false if fail to copy
- */
- public boolean putDouble(double value, int row, int col) {
- acquireReference();
- try {
- return putDouble_native(value, row - mStartPos, col);
- } finally {
- releaseReference();
- }
- }
-
- private native boolean putDouble_native(double value, int row, int col);
-
- /**
- * Set the [row, col] value to NULL
- * @param row
- * @param col
- * @return false if fail to copy
- */
- public boolean putNull(int row, int col) {
- acquireReference();
- try {
- return putNull_native(row - mStartPos, col);
- } finally {
- releaseReference();
- }
- }
-
- private native boolean putNull_native(int row, int col);
-
-
- /**
- * Returns {@code true} if given field is {@code NULL}.
- *
- * @param row the row to read from, row - getStartPosition() being the actual row in the window
- * @param col the column to read from
- * @return {@code true} if given field is {@code NULL}
- */
- public boolean isNull(int row, int col) {
- acquireReference();
- try {
- return isNull_native(row - mStartPos, col);
- } finally {
- releaseReference();
- }
- }
-
- private native boolean isNull_native(int row, int col);
-
- /**
- * Returns a byte array for the given field.
- *
- * @param row the row to read from, row - getStartPosition() being the actual row in the window
- * @param col the column to read from
- * @return a String value for the given field
- */
- public byte[] getBlob(int row, int col) {
- acquireReference();
- try {
- return getBlob_native(row - mStartPos, col);
- } finally {
- releaseReference();
- }
- }
-
- private native byte[] getBlob_native(int row, int col);
-
- /**
- * Checks if a field contains either a blob or is null.
- *
- * @param row the row to read from, row - getStartPosition() being the actual row in the window
- * @param col the column to read from
- * @return {@code true} if given field is {@code NULL} or a blob
- */
- public boolean isBlob(int row, int col) {
- acquireReference();
- try {
- return isBlob_native(row - mStartPos, col);
- } finally {
- releaseReference();
- }
- }
-
- private native boolean isBlob_native(int row, int col);
-
- /**
- * Returns a String for the given field.
- *
- * @param row the row to read from, row - getStartPosition() being the actual row in the window
- * @param col the column to read from
- * @return a String value for the given field
- */
- public String getString(int row, int col) {
- acquireReference();
- try {
- return getString_native(row - mStartPos, col);
- } finally {
- releaseReference();
- }
- }
-
- private native String getString_native(int row, int col);
-
- /**
- * copy the text for the given field in the provided char array.
- *
- * @param row the row to read from, row - getStartPosition() being the actual row in the window
- * @param col the column to read from
- * @param buffer the CharArrayBuffer to copy the text into,
- * If the requested string is larger than the buffer
- * a new char buffer will be created to hold the string. and assigne to
- * CharArrayBuffer.data
- */
- public void copyStringToBuffer(int row, int col, CharArrayBuffer buffer) {
- if (buffer == null) {
- throw new IllegalArgumentException("CharArrayBuffer should not be null");
- }
- if (buffer.data == null) {
- buffer.data = new char[64];
- }
- acquireReference();
- try {
- char[] newbuf = copyStringToBuffer_native(
- row - mStartPos, col, buffer.data.length, buffer);
- if (newbuf != null) {
- buffer.data = newbuf;
- }
- } finally {
- releaseReference();
- }
- }
-
- private native char[] copyStringToBuffer_native(
- int row, int col, int bufferSize, CharArrayBuffer buffer);
-
- /**
- * Returns a long for the given field.
- * row is 0 based
- *
- * @param row the row to read from, row - getStartPosition() being the actual row in the window
- * @param col the column to read from
- * @return a long value for the given field
- */
- public long getLong(int row, int col) {
- acquireReference();
- try {
- return getLong_native(row - mStartPos, col);
- } finally {
- releaseReference();
- }
- }
-
- private native long getLong_native(int row, int col);
-
- /**
- * Returns a double for the given field.
- * row is 0 based
- *
- * @param row the row to read from, row - getStartPosition() being the actual row in the window
- * @param col the column to read from
- * @return a double value for the given field
- */
- public double getDouble(int row, int col) {
- acquireReference();
- try {
- return getDouble_native(row - mStartPos, col);
- } finally {
- releaseReference();
- }
- }
-
- private native double getDouble_native(int row, int col);
-
- /**
- * Returns a short for the given field.
- * row is 0 based
- *
- * @param row the row to read from, row - getStartPosition() being the actual row in the window
- * @param col the column to read from
- * @return a short value for the given field
- */
- public short getShort(int row, int col) {
- acquireReference();
- try {
- return (short) getLong_native(row - mStartPos, col);
- } finally {
- releaseReference();
- }
- }
-
- /**
- * Returns an int for the given field.
- *
- * @param row the row to read from, row - getStartPosition() being the actual row in the window
- * @param col the column to read from
- * @return an int value for the given field
- */
- public int getInt(int row, int col) {
- acquireReference();
- try {
- return (int) getLong_native(row - mStartPos, col);
- } finally {
- releaseReference();
- }
- }
-
- /**
- * Returns a float for the given field.
- * row is 0 based
- *
- * @param row the row to read from, row - getStartPosition() being the actual row in the window
- * @param col the column to read from
- * @return a float value for the given field
- */
- public float getFloat(int row, int col) {
- acquireReference();
- try {
- return (float) getDouble_native(row - mStartPos, col);
- } finally {
- releaseReference();
- }
- }
-
- /**
- * Clears out the existing contents of the window, making it safe to reuse
- * for new data. Note that the number of columns in the window may NOT
- * change across a call to clear().
- */
- public void clear() {
- acquireReference();
- try {
- mStartPos = 0;
- native_clear();
- } finally {
- releaseReference();
- }
- }
-
- /** Clears out the native side of things */
- private native void native_clear();
-
- /**
- * Cleans up the native resources associated with the window.
- */
- public void close() {
- releaseReference();
- }
-
- private native void close_native();
-
- @Override
- protected void finalize() {
- // Just in case someone forgot to call close...
- close_native();
- }
-
- public static final Parcelable.Creator<CursorWindow> CREATOR
- = new Parcelable.Creator<CursorWindow>() {
- public CursorWindow createFromParcel(Parcel source) {
- return new CursorWindow(source);
- }
-
- public CursorWindow[] newArray(int size) {
- return new CursorWindow[size];
- }
- };
-
- public static CursorWindow newFromParcel(Parcel p) {
- return CREATOR.createFromParcel(p);
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeStrongBinder(native_getBinder());
- dest.writeInt(mStartPos);
- }
-
- private CursorWindow(Parcel source) {
- IBinder nativeBinder = source.readStrongBinder();
- mStartPos = source.readInt();
-
- native_init(nativeBinder);
- }
-
- /** Get the binder for the native side of the window */
- private native IBinder native_getBinder();
-
- /** Does the native side initialization for an empty window */
- private native void native_init(boolean localOnly);
-
- /** Does the native side initialization with an existing binder from another process */
- private native void native_init(IBinder nativeBinder);
-
- @Override
- protected void onAllReferencesReleased() {
- close_native();
- }
-}
diff --git a/core/java/android/database/CursorWrapper.java b/core/java/android/database/CursorWrapper.java
deleted file mode 100644
index f0aa7d7..0000000
--- a/core/java/android/database/CursorWrapper.java
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-import android.content.ContentResolver;
-import android.database.CharArrayBuffer;
-import android.net.Uri;
-import android.os.Bundle;
-
-import java.util.Map;
-
-/**
- * Wrapper class for Cursor that delegates all calls to the actual cursor object
- */
-
-public class CursorWrapper implements Cursor {
-
- public CursorWrapper(Cursor cursor) {
- mCursor = cursor;
- }
-
- /**
- * @hide
- * @deprecated
- */
- public void abortUpdates() {
- mCursor.abortUpdates();
- }
-
- public void close() {
- mCursor.close();
- }
-
- public boolean isClosed() {
- return mCursor.isClosed();
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean commitUpdates() {
- return mCursor.commitUpdates();
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean commitUpdates(
- Map<? extends Long, ? extends Map<String, Object>> values) {
- return mCursor.commitUpdates(values);
- }
-
- public int getCount() {
- return mCursor.getCount();
- }
-
- public void deactivate() {
- mCursor.deactivate();
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean deleteRow() {
- return mCursor.deleteRow();
- }
-
- public boolean moveToFirst() {
- return mCursor.moveToFirst();
- }
-
- public int getColumnCount() {
- return mCursor.getColumnCount();
- }
-
- public int getColumnIndex(String columnName) {
- return mCursor.getColumnIndex(columnName);
- }
-
- public int getColumnIndexOrThrow(String columnName)
- throws IllegalArgumentException {
- return mCursor.getColumnIndexOrThrow(columnName);
- }
-
- public String getColumnName(int columnIndex) {
- return mCursor.getColumnName(columnIndex);
- }
-
- public String[] getColumnNames() {
- return mCursor.getColumnNames();
- }
-
- public double getDouble(int columnIndex) {
- return mCursor.getDouble(columnIndex);
- }
-
- public Bundle getExtras() {
- return mCursor.getExtras();
- }
-
- public float getFloat(int columnIndex) {
- return mCursor.getFloat(columnIndex);
- }
-
- public int getInt(int columnIndex) {
- return mCursor.getInt(columnIndex);
- }
-
- public long getLong(int columnIndex) {
- return mCursor.getLong(columnIndex);
- }
-
- public short getShort(int columnIndex) {
- return mCursor.getShort(columnIndex);
- }
-
- public String getString(int columnIndex) {
- return mCursor.getString(columnIndex);
- }
-
- public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
- mCursor.copyStringToBuffer(columnIndex, buffer);
- }
-
- public byte[] getBlob(int columnIndex) {
- return mCursor.getBlob(columnIndex);
- }
-
- public boolean getWantsAllOnMoveCalls() {
- return mCursor.getWantsAllOnMoveCalls();
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean hasUpdates() {
- return mCursor.hasUpdates();
- }
-
- public boolean isAfterLast() {
- return mCursor.isAfterLast();
- }
-
- public boolean isBeforeFirst() {
- return mCursor.isBeforeFirst();
- }
-
- public boolean isFirst() {
- return mCursor.isFirst();
- }
-
- public boolean isLast() {
- return mCursor.isLast();
- }
-
- public boolean isNull(int columnIndex) {
- return mCursor.isNull(columnIndex);
- }
-
- public boolean moveToLast() {
- return mCursor.moveToLast();
- }
-
- public boolean move(int offset) {
- return mCursor.move(offset);
- }
-
- public boolean moveToPosition(int position) {
- return mCursor.moveToPosition(position);
- }
-
- public boolean moveToNext() {
- return mCursor.moveToNext();
- }
-
- public int getPosition() {
- return mCursor.getPosition();
- }
-
- public boolean moveToPrevious() {
- return mCursor.moveToPrevious();
- }
-
- public void registerContentObserver(ContentObserver observer) {
- mCursor.registerContentObserver(observer);
- }
-
- public void registerDataSetObserver(DataSetObserver observer) {
- mCursor.registerDataSetObserver(observer);
- }
-
- public boolean requery() {
- return mCursor.requery();
- }
-
- public Bundle respond(Bundle extras) {
- return mCursor.respond(extras);
- }
-
- public void setNotificationUri(ContentResolver cr, Uri uri) {
- mCursor.setNotificationUri(cr, uri);
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean supportsUpdates() {
- return mCursor.supportsUpdates();
- }
-
- public void unregisterContentObserver(ContentObserver observer) {
- mCursor.unregisterContentObserver(observer);
- }
-
- public void unregisterDataSetObserver(DataSetObserver observer) {
- mCursor.unregisterDataSetObserver(observer);
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateDouble(int columnIndex, double value) {
- return mCursor.updateDouble(columnIndex, value);
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateFloat(int columnIndex, float value) {
- return mCursor.updateFloat(columnIndex, value);
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateInt(int columnIndex, int value) {
- return mCursor.updateInt(columnIndex, value);
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateLong(int columnIndex, long value) {
- return mCursor.updateLong(columnIndex, value);
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateShort(int columnIndex, short value) {
- return mCursor.updateShort(columnIndex, value);
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateString(int columnIndex, String value) {
- return mCursor.updateString(columnIndex, value);
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateBlob(int columnIndex, byte[] value) {
- return mCursor.updateBlob(columnIndex, value);
- }
-
- /**
- * @hide
- * @deprecated
- */
- public boolean updateToNull(int columnIndex) {
- return mCursor.updateToNull(columnIndex);
- }
-
- private Cursor mCursor;
-
-}
-
diff --git a/core/java/android/database/DataSetObservable.java b/core/java/android/database/DataSetObservable.java
deleted file mode 100644
index 9200e81..0000000
--- a/core/java/android/database/DataSetObservable.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-/**
- * A specialization of Observable for DataSetObserver that provides methods for
- * invoking the various callback methods of DataSetObserver.
- */
-public class DataSetObservable extends Observable<DataSetObserver> {
- /**
- * Invokes onChanged on each observer. Called when the data set being observed has
- * changed, and which when read contains the new state of the data.
- */
- public void notifyChanged() {
- synchronized(mObservers) {
- for (DataSetObserver observer : mObservers) {
- observer.onChanged();
- }
- }
- }
-
- /**
- * Invokes onInvalidated on each observer. Called when the data set being monitored
- * has changed such that it is no longer valid.
- */
- public void notifyInvalidated() {
- synchronized (mObservers) {
- for (DataSetObserver observer : mObservers) {
- observer.onInvalidated();
- }
- }
- }
-}
diff --git a/core/java/android/database/DataSetObserver.java b/core/java/android/database/DataSetObserver.java
deleted file mode 100644
index 28616c8..0000000
--- a/core/java/android/database/DataSetObserver.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-/**
- * Receives call backs when a data set has been changed, or made invalid. The typically data sets
- * that are observed are {@link Cursor}s or {@link android.widget.Adapter}s.
- * DataSetObserver must be implemented by objects which are added to a DataSetObservable.
- */
-public abstract class DataSetObserver {
- /**
- * This method is called when the entire data set has changed,
- * most likely through a call to {@link Cursor#requery()} on a {@link Cursor}.
- */
- public void onChanged() {
- // Do nothing
- }
-
- /**
- * This method is called when the entire data becomes invalid,
- * most likely through a call to {@link Cursor#deactivate()} or {@link Cursor#close()} on a
- * {@link Cursor}.
- */
- public void onInvalidated() {
- // Do nothing
- }
-}
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
deleted file mode 100644
index 10f3806..0000000
--- a/core/java/android/database/DatabaseUtils.java
+++ /dev/null
@@ -1,1018 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-import org.apache.commons.codec.binary.Hex;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.sqlite.SQLiteAbortException;
-import android.database.sqlite.SQLiteConstraintException;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteDatabaseCorruptException;
-import android.database.sqlite.SQLiteDiskIOException;
-import android.database.sqlite.SQLiteException;
-import android.database.sqlite.SQLiteFullException;
-import android.database.sqlite.SQLiteProgram;
-import android.database.sqlite.SQLiteStatement;
-import android.os.Parcel;
-import android.text.TextUtils;
-import android.util.Config;
-import android.util.Log;
-
-import java.io.FileNotFoundException;
-import java.io.PrintStream;
-import java.text.Collator;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Static utility methods for dealing with databases and {@link Cursor}s.
- */
-public class DatabaseUtils {
- private static final String TAG = "DatabaseUtils";
-
- private static final boolean DEBUG = false;
- private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
-
- private static final String[] countProjection = new String[]{"count(*)"};
-
- /**
- * Special function for writing an exception result at the header of
- * a parcel, to be used when returning an exception from a transaction.
- * exception will be re-thrown by the function in another process
- * @param reply Parcel to write to
- * @param e The Exception to be written.
- * @see Parcel#writeNoException
- * @see Parcel#writeException
- */
- public static final void writeExceptionToParcel(Parcel reply, Exception e) {
- int code = 0;
- boolean logException = true;
- if (e instanceof FileNotFoundException) {
- code = 1;
- logException = false;
- } else if (e instanceof IllegalArgumentException) {
- code = 2;
- } else if (e instanceof UnsupportedOperationException) {
- code = 3;
- } else if (e instanceof SQLiteAbortException) {
- code = 4;
- } else if (e instanceof SQLiteConstraintException) {
- code = 5;
- } else if (e instanceof SQLiteDatabaseCorruptException) {
- code = 6;
- } else if (e instanceof SQLiteFullException) {
- code = 7;
- } else if (e instanceof SQLiteDiskIOException) {
- code = 8;
- } else if (e instanceof SQLiteException) {
- code = 9;
- } else {
- reply.writeException(e);
- Log.e(TAG, "Writing exception to parcel", e);
- return;
- }
- reply.writeInt(code);
- reply.writeString(e.getMessage());
-
- if (logException) {
- Log.e(TAG, "Writing exception to parcel", e);
- }
- }
-
- /**
- * Special function for reading an exception result from the header of
- * a parcel, to be used after receiving the result of a transaction. This
- * will throw the exception for you if it had been written to the Parcel,
- * otherwise return and let you read the normal result data from the Parcel.
- * @param reply Parcel to read from
- * @see Parcel#writeNoException
- * @see Parcel#readException
- */
- public static final void readExceptionFromParcel(Parcel reply) {
- int code = reply.readInt();
- if (code == 0) return;
- String msg = reply.readString();
- DatabaseUtils.readExceptionFromParcel(reply, msg, code);
- }
-
- public static void readExceptionWithFileNotFoundExceptionFromParcel(
- Parcel reply) throws FileNotFoundException {
- int code = reply.readInt();
- if (code == 0) return;
- String msg = reply.readString();
- if (code == 1) {
- throw new FileNotFoundException(msg);
- } else {
- DatabaseUtils.readExceptionFromParcel(reply, msg, code);
- }
- }
-
- private static final void readExceptionFromParcel(Parcel reply, String msg, int code) {
- switch (code) {
- case 2:
- throw new IllegalArgumentException(msg);
- case 3:
- throw new UnsupportedOperationException(msg);
- case 4:
- throw new SQLiteAbortException(msg);
- case 5:
- throw new SQLiteConstraintException(msg);
- case 6:
- throw new SQLiteDatabaseCorruptException(msg);
- case 7:
- throw new SQLiteFullException(msg);
- case 8:
- throw new SQLiteDiskIOException(msg);
- case 9:
- throw new SQLiteException(msg);
- default:
- reply.readException(code, msg);
- }
- }
-
- /**
- * Binds the given Object to the given SQLiteProgram using the proper
- * typing. For example, bind numbers as longs/doubles, and everything else
- * as a string by call toString() on it.
- *
- * @param prog the program to bind the object to
- * @param index the 1-based index to bind at
- * @param value the value to bind
- */
- public static void bindObjectToProgram(SQLiteProgram prog, int index,
- Object value) {
- if (value == null) {
- prog.bindNull(index);
- } else if (value instanceof Double || value instanceof Float) {
- prog.bindDouble(index, ((Number)value).doubleValue());
- } else if (value instanceof Number) {
- prog.bindLong(index, ((Number)value).longValue());
- } else if (value instanceof Boolean) {
- Boolean bool = (Boolean)value;
- if (bool) {
- prog.bindLong(index, 1);
- } else {
- prog.bindLong(index, 0);
- }
- } else if (value instanceof byte[]){
- prog.bindBlob(index, (byte[]) value);
- } else {
- prog.bindString(index, value.toString());
- }
- }
-
- /**
- * Appends an SQL string to the given StringBuilder, including the opening
- * and closing single quotes. Any single quotes internal to sqlString will
- * be escaped.
- *
- * This method is deprecated because we want to encourage everyone
- * to use the "?" binding form. However, when implementing a
- * ContentProvider, one may want to add WHERE clauses that were
- * not provided by the caller. Since "?" is a positional form,
- * using it in this case could break the caller because the
- * indexes would be shifted to accomodate the ContentProvider's
- * internal bindings. In that case, it may be necessary to
- * construct a WHERE clause manually. This method is useful for
- * those cases.
- *
- * @param sb the StringBuilder that the SQL string will be appended to
- * @param sqlString the raw string to be appended, which may contain single
- * quotes
- */
- public static void appendEscapedSQLString(StringBuilder sb, String sqlString) {
- sb.append('\'');
- if (sqlString.indexOf('\'') != -1) {
- int length = sqlString.length();
- for (int i = 0; i < length; i++) {
- char c = sqlString.charAt(i);
- if (c == '\'') {
- sb.append('\'');
- }
- sb.append(c);
- }
- } else
- sb.append(sqlString);
- sb.append('\'');
- }
-
- /**
- * SQL-escape a string.
- */
- public static String sqlEscapeString(String value) {
- StringBuilder escaper = new StringBuilder();
-
- DatabaseUtils.appendEscapedSQLString(escaper, value);
-
- return escaper.toString();
- }
-
- /**
- * Appends an Object to an SQL string with the proper escaping, etc.
- */
- public static final void appendValueToSql(StringBuilder sql, Object value) {
- if (value == null) {
- sql.append("NULL");
- } else if (value instanceof Boolean) {
- Boolean bool = (Boolean)value;
- if (bool) {
- sql.append('1');
- } else {
- sql.append('0');
- }
- } else {
- appendEscapedSQLString(sql, value.toString());
- }
- }
-
- /**
- * Concatenates two SQL WHERE clauses, handling empty or null values.
- * @hide
- */
- public static String concatenateWhere(String a, String b) {
- if (TextUtils.isEmpty(a)) {
- return b;
- }
- if (TextUtils.isEmpty(b)) {
- return a;
- }
-
- return "(" + a + ") AND (" + b + ")";
- }
-
- /**
- * return the collation key
- * @param name
- * @return the collation key
- */
- public static String getCollationKey(String name) {
- byte [] arr = getCollationKeyInBytes(name);
- try {
- return new String(arr, 0, getKeyLen(arr), "ISO8859_1");
- } catch (Exception ex) {
- return "";
- }
- }
-
- /**
- * return the collation key in hex format
- * @param name
- * @return the collation key in hex format
- */
- public static String getHexCollationKey(String name) {
- byte [] arr = getCollationKeyInBytes(name);
- char[] keys = Hex.encodeHex(arr);
- return new String(keys, 0, getKeyLen(arr) * 2);
- }
-
- private static int getKeyLen(byte[] arr) {
- if (arr[arr.length - 1] != 0) {
- return arr.length;
- } else {
- // remove zero "termination"
- return arr.length-1;
- }
- }
-
- private static byte[] getCollationKeyInBytes(String name) {
- if (mColl == null) {
- mColl = Collator.getInstance();
- mColl.setStrength(Collator.PRIMARY);
- }
- return mColl.getCollationKey(name).toByteArray();
- }
-
- private static Collator mColl = null;
- /**
- * Prints the contents of a Cursor to System.out. The position is restored
- * after printing.
- *
- * @param cursor the cursor to print
- */
- public static void dumpCursor(Cursor cursor) {
- dumpCursor(cursor, System.out);
- }
-
- /**
- * Prints the contents of a Cursor to a PrintSteam. The position is restored
- * after printing.
- *
- * @param cursor the cursor to print
- * @param stream the stream to print to
- */
- public static void dumpCursor(Cursor cursor, PrintStream stream) {
- stream.println(">>>>> Dumping cursor " + cursor);
- if (cursor != null) {
- int startPos = cursor.getPosition();
-
- cursor.moveToPosition(-1);
- while (cursor.moveToNext()) {
- dumpCurrentRow(cursor, stream);
- }
- cursor.moveToPosition(startPos);
- }
- stream.println("<<<<<");
- }
-
- /**
- * Prints the contents of a Cursor to a StringBuilder. The position
- * is restored after printing.
- *
- * @param cursor the cursor to print
- * @param sb the StringBuilder to print to
- */
- public static void dumpCursor(Cursor cursor, StringBuilder sb) {
- sb.append(">>>>> Dumping cursor " + cursor + "\n");
- if (cursor != null) {
- int startPos = cursor.getPosition();
-
- cursor.moveToPosition(-1);
- while (cursor.moveToNext()) {
- dumpCurrentRow(cursor, sb);
- }
- cursor.moveToPosition(startPos);
- }
- sb.append("<<<<<\n");
- }
-
- /**
- * Prints the contents of a Cursor to a String. The position is restored
- * after printing.
- *
- * @param cursor the cursor to print
- * @return a String that contains the dumped cursor
- */
- public static String dumpCursorToString(Cursor cursor) {
- StringBuilder sb = new StringBuilder();
- dumpCursor(cursor, sb);
- return sb.toString();
- }
-
- /**
- * Prints the contents of a Cursor's current row to System.out.
- *
- * @param cursor the cursor to print from
- */
- public static void dumpCurrentRow(Cursor cursor) {
- dumpCurrentRow(cursor, System.out);
- }
-
- /**
- * Prints the contents of a Cursor's current row to a PrintSteam.
- *
- * @param cursor the cursor to print
- * @param stream the stream to print to
- */
- public static void dumpCurrentRow(Cursor cursor, PrintStream stream) {
- String[] cols = cursor.getColumnNames();
- stream.println("" + cursor.getPosition() + " {");
- int length = cols.length;
- for (int i = 0; i< length; i++) {
- String value;
- try {
- value = cursor.getString(i);
- } catch (SQLiteException e) {
- // assume that if the getString threw this exception then the column is not
- // representable by a string, e.g. it is a BLOB.
- value = "<unprintable>";
- }
- stream.println(" " + cols[i] + '=' + value);
- }
- stream.println("}");
- }
-
- /**
- * Prints the contents of a Cursor's current row to a StringBuilder.
- *
- * @param cursor the cursor to print
- * @param sb the StringBuilder to print to
- */
- public static void dumpCurrentRow(Cursor cursor, StringBuilder sb) {
- String[] cols = cursor.getColumnNames();
- sb.append("" + cursor.getPosition() + " {\n");
- int length = cols.length;
- for (int i = 0; i < length; i++) {
- String value;
- try {
- value = cursor.getString(i);
- } catch (SQLiteException e) {
- // assume that if the getString threw this exception then the column is not
- // representable by a string, e.g. it is a BLOB.
- value = "<unprintable>";
- }
- sb.append(" " + cols[i] + '=' + value + "\n");
- }
- sb.append("}\n");
- }
-
- /**
- * Dump the contents of a Cursor's current row to a String.
- *
- * @param cursor the cursor to print
- * @return a String that contains the dumped cursor row
- */
- public static String dumpCurrentRowToString(Cursor cursor) {
- StringBuilder sb = new StringBuilder();
- dumpCurrentRow(cursor, sb);
- return sb.toString();
- }
-
- /**
- * Reads a String out of a field in a Cursor and writes it to a Map.
- *
- * @param cursor The cursor to read from
- * @param field The TEXT field to read
- * @param values The {@link ContentValues} to put the value into, with the field as the key
- */
- public static void cursorStringToContentValues(Cursor cursor, String field,
- ContentValues values) {
- cursorStringToContentValues(cursor, field, values, field);
- }
-
- /**
- * Reads a String out of a field in a Cursor and writes it to an InsertHelper.
- *
- * @param cursor The cursor to read from
- * @param field The TEXT field to read
- * @param inserter The InsertHelper to bind into
- * @param index the index of the bind entry in the InsertHelper
- */
- public static void cursorStringToInsertHelper(Cursor cursor, String field,
- InsertHelper inserter, int index) {
- inserter.bind(index, cursor.getString(cursor.getColumnIndexOrThrow(field)));
- }
-
- /**
- * Reads a String out of a field in a Cursor and writes it to a Map.
- *
- * @param cursor The cursor to read from
- * @param field The TEXT field to read
- * @param values The {@link ContentValues} to put the value into, with the field as the key
- * @param key The key to store the value with in the map
- */
- public static void cursorStringToContentValues(Cursor cursor, String field,
- ContentValues values, String key) {
- values.put(key, cursor.getString(cursor.getColumnIndexOrThrow(field)));
- }
-
- /**
- * Reads an Integer out of a field in a Cursor and writes it to a Map.
- *
- * @param cursor The cursor to read from
- * @param field The INTEGER field to read
- * @param values The {@link ContentValues} to put the value into, with the field as the key
- */
- public static void cursorIntToContentValues(Cursor cursor, String field, ContentValues values) {
- cursorIntToContentValues(cursor, field, values, field);
- }
-
- /**
- * Reads a Integer out of a field in a Cursor and writes it to a Map.
- *
- * @param cursor The cursor to read from
- * @param field The INTEGER field to read
- * @param values The {@link ContentValues} to put the value into, with the field as the key
- * @param key The key to store the value with in the map
- */
- public static void cursorIntToContentValues(Cursor cursor, String field, ContentValues values,
- String key) {
- int colIndex = cursor.getColumnIndex(field);
- if (!cursor.isNull(colIndex)) {
- values.put(key, cursor.getInt(colIndex));
- } else {
- values.put(key, (Integer) null);
- }
- }
-
- /**
- * Reads a Long out of a field in a Cursor and writes it to a Map.
- *
- * @param cursor The cursor to read from
- * @param field The INTEGER field to read
- * @param values The {@link ContentValues} to put the value into, with the field as the key
- */
- public static void cursorLongToContentValues(Cursor cursor, String field, ContentValues values)
- {
- cursorLongToContentValues(cursor, field, values, field);
- }
-
- /**
- * Reads a Long out of a field in a Cursor and writes it to a Map.
- *
- * @param cursor The cursor to read from
- * @param field The INTEGER field to read
- * @param values The {@link ContentValues} to put the value into
- * @param key The key to store the value with in the map
- */
- public static void cursorLongToContentValues(Cursor cursor, String field, ContentValues values,
- String key) {
- int colIndex = cursor.getColumnIndex(field);
- if (!cursor.isNull(colIndex)) {
- Long value = Long.valueOf(cursor.getLong(colIndex));
- values.put(key, value);
- } else {
- values.put(key, (Long) null);
- }
- }
-
- /**
- * Reads a Double out of a field in a Cursor and writes it to a Map.
- *
- * @param cursor The cursor to read from
- * @param field The REAL field to read
- * @param values The {@link ContentValues} to put the value into
- */
- public static void cursorDoubleToCursorValues(Cursor cursor, String field, ContentValues values)
- {
- cursorDoubleToContentValues(cursor, field, values, field);
- }
-
- /**
- * Reads a Double out of a field in a Cursor and writes it to a Map.
- *
- * @param cursor The cursor to read from
- * @param field The REAL field to read
- * @param values The {@link ContentValues} to put the value into
- * @param key The key to store the value with in the map
- */
- public static void cursorDoubleToContentValues(Cursor cursor, String field,
- ContentValues values, String key) {
- int colIndex = cursor.getColumnIndex(field);
- if (!cursor.isNull(colIndex)) {
- values.put(key, cursor.getDouble(colIndex));
- } else {
- values.put(key, (Double) null);
- }
- }
-
- /**
- * Read the entire contents of a cursor row and store them in a ContentValues.
- *
- * @param cursor the cursor to read from.
- * @param values the {@link ContentValues} to put the row into.
- */
- public static void cursorRowToContentValues(Cursor cursor, ContentValues values) {
- AbstractWindowedCursor awc =
- (cursor instanceof AbstractWindowedCursor) ? (AbstractWindowedCursor) cursor : null;
-
- String[] columns = cursor.getColumnNames();
- int length = columns.length;
- for (int i = 0; i < length; i++) {
- if (awc != null && awc.isBlob(i)) {
- values.put(columns[i], cursor.getBlob(i));
- } else {
- values.put(columns[i], cursor.getString(i));
- }
- }
- }
-
- /**
- * Query the table for the number of rows in the table.
- * @param db the database the table is in
- * @param table the name of the table to query
- * @return the number of rows in the table
- */
- public static long queryNumEntries(SQLiteDatabase db, String table) {
- Cursor cursor = db.query(table, countProjection,
- null, null, null, null, null);
- cursor.moveToFirst();
- long count = cursor.getLong(0);
- cursor.deactivate();
- return count;
- }
-
- /**
- * Utility method to run the query on the db and return the value in the
- * first column of the first row.
- */
- public static long longForQuery(SQLiteDatabase db, String query, String[] selectionArgs) {
- SQLiteStatement prog = db.compileStatement(query);
- try {
- return longForQuery(prog, selectionArgs);
- } finally {
- prog.close();
- }
- }
-
- /**
- * Utility method to run the pre-compiled query and return the value in the
- * first column of the first row.
- */
- public static long longForQuery(SQLiteStatement prog, String[] selectionArgs) {
- if (selectionArgs != null) {
- int size = selectionArgs.length;
- for (int i = 0; i < size; i++) {
- bindObjectToProgram(prog, i + 1, selectionArgs[i]);
- }
- }
- long value = prog.simpleQueryForLong();
- return value;
- }
-
- /**
- * Utility method to run the query on the db and return the value in the
- * first column of the first row.
- */
- public static String stringForQuery(SQLiteDatabase db, String query, String[] selectionArgs) {
- SQLiteStatement prog = db.compileStatement(query);
- try {
- return stringForQuery(prog, selectionArgs);
- } finally {
- prog.close();
- }
- }
-
- /**
- * Utility method to run the pre-compiled query and return the value in the
- * first column of the first row.
- */
- public static String stringForQuery(SQLiteStatement prog, String[] selectionArgs) {
- if (selectionArgs != null) {
- int size = selectionArgs.length;
- for (int i = 0; i < size; i++) {
- bindObjectToProgram(prog, i + 1, selectionArgs[i]);
- }
- }
- String value = prog.simpleQueryForString();
- return value;
- }
-
- /**
- * This class allows users to do multiple inserts into a table but
- * compile the SQL insert statement only once, which may increase
- * performance.
- */
- public static class InsertHelper {
- private final SQLiteDatabase mDb;
- private final String mTableName;
- private HashMap<String, Integer> mColumns;
- private String mInsertSQL = null;
- private SQLiteStatement mInsertStatement = null;
- private SQLiteStatement mReplaceStatement = null;
- private SQLiteStatement mPreparedStatement = null;
-
- /**
- * {@hide}
- *
- * These are the columns returned by sqlite's "PRAGMA
- * table_info(...)" command that we depend on.
- */
- public static final int TABLE_INFO_PRAGMA_COLUMNNAME_INDEX = 1;
- public static final int TABLE_INFO_PRAGMA_DEFAULT_INDEX = 4;
-
- /**
- * @param db the SQLiteDatabase to insert into
- * @param tableName the name of the table to insert into
- */
- public InsertHelper(SQLiteDatabase db, String tableName) {
- mDb = db;
- mTableName = tableName;
- }
-
- private void buildSQL() throws SQLException {
- StringBuilder sb = new StringBuilder(128);
- sb.append("INSERT INTO ");
- sb.append(mTableName);
- sb.append(" (");
-
- StringBuilder sbv = new StringBuilder(128);
- sbv.append("VALUES (");
-
- int i = 1;
- Cursor cur = null;
- try {
- cur = mDb.rawQuery("PRAGMA table_info(" + mTableName + ")", null);
- mColumns = new HashMap<String, Integer>(cur.getCount());
- while (cur.moveToNext()) {
- String columnName = cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX);
- String defaultValue = cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX);
-
- mColumns.put(columnName, i);
- sb.append("'");
- sb.append(columnName);
- sb.append("'");
-
- if (defaultValue == null) {
- sbv.append("?");
- } else {
- sbv.append("COALESCE(?, ");
- sbv.append(defaultValue);
- sbv.append(")");
- }
-
- sb.append(i == cur.getCount() ? ") " : ", ");
- sbv.append(i == cur.getCount() ? ");" : ", ");
- ++i;
- }
- } finally {
- if (cur != null) cur.close();
- }
-
- sb.append(sbv);
-
- mInsertSQL = sb.toString();
- if (LOCAL_LOGV) Log.v(TAG, "insert statement is " + mInsertSQL);
- }
-
- private SQLiteStatement getStatement(boolean allowReplace) throws SQLException {
- if (allowReplace) {
- if (mReplaceStatement == null) {
- if (mInsertSQL == null) buildSQL();
- // chop "INSERT" off the front and prepend "INSERT OR REPLACE" instead.
- String replaceSQL = "INSERT OR REPLACE" + mInsertSQL.substring(6);
- mReplaceStatement = mDb.compileStatement(replaceSQL);
- }
- return mReplaceStatement;
- } else {
- if (mInsertStatement == null) {
- if (mInsertSQL == null) buildSQL();
- mInsertStatement = mDb.compileStatement(mInsertSQL);
- }
- return mInsertStatement;
- }
- }
-
- /**
- * Performs an insert, adding a new row with the given values.
- *
- * @param values the set of values with which to populate the
- * new row
- * @param allowReplace if true, the statement does "INSERT OR
- * REPLACE" instead of "INSERT", silently deleting any
- * previously existing rows that would cause a conflict
- *
- * @return the row ID of the newly inserted row, or -1 if an
- * error occurred
- */
- private synchronized long insertInternal(ContentValues values, boolean allowReplace) {
- try {
- SQLiteStatement stmt = getStatement(allowReplace);
- stmt.clearBindings();
- if (LOCAL_LOGV) Log.v(TAG, "--- inserting in table " + mTableName);
- for (Map.Entry<String, Object> e: values.valueSet()) {
- final String key = e.getKey();
- int i = getColumnIndex(key);
- DatabaseUtils.bindObjectToProgram(stmt, i, e.getValue());
- if (LOCAL_LOGV) {
- Log.v(TAG, "binding " + e.getValue() + " to column " +
- i + " (" + key + ")");
- }
- }
- return stmt.executeInsert();
- } catch (SQLException e) {
- Log.e(TAG, "Error inserting " + values + " into table " + mTableName, e);
- return -1;
- }
- }
-
- /**
- * Returns the index of the specified column. This is index is suitagble for use
- * in calls to bind().
- * @param key the column name
- * @return the index of the column
- */
- public int getColumnIndex(String key) {
- getStatement(false);
- final Integer index = mColumns.get(key);
- if (index == null) {
- throw new IllegalArgumentException("column '" + key + "' is invalid");
- }
- return index;
- }
-
- /**
- * Bind the value to an index. A prepareForInsert() or prepareForReplace()
- * without a matching execute() must have already have been called.
- * @param index the index of the slot to which to bind
- * @param value the value to bind
- */
- public void bind(int index, double value) {
- mPreparedStatement.bindDouble(index, value);
- }
-
- /**
- * Bind the value to an index. A prepareForInsert() or prepareForReplace()
- * without a matching execute() must have already have been called.
- * @param index the index of the slot to which to bind
- * @param value the value to bind
- */
- public void bind(int index, float value) {
- mPreparedStatement.bindDouble(index, value);
- }
-
- /**
- * Bind the value to an index. A prepareForInsert() or prepareForReplace()
- * without a matching execute() must have already have been called.
- * @param index the index of the slot to which to bind
- * @param value the value to bind
- */
- public void bind(int index, long value) {
- mPreparedStatement.bindLong(index, value);
- }
-
- /**
- * Bind the value to an index. A prepareForInsert() or prepareForReplace()
- * without a matching execute() must have already have been called.
- * @param index the index of the slot to which to bind
- * @param value the value to bind
- */
- public void bind(int index, int value) {
- mPreparedStatement.bindLong(index, value);
- }
-
- /**
- * Bind the value to an index. A prepareForInsert() or prepareForReplace()
- * without a matching execute() must have already have been called.
- * @param index the index of the slot to which to bind
- * @param value the value to bind
- */
- public void bind(int index, boolean value) {
- mPreparedStatement.bindLong(index, value ? 1 : 0);
- }
-
- /**
- * Bind null to an index. A prepareForInsert() or prepareForReplace()
- * without a matching execute() must have already have been called.
- * @param index the index of the slot to which to bind
- */
- public void bindNull(int index) {
- mPreparedStatement.bindNull(index);
- }
-
- /**
- * Bind the value to an index. A prepareForInsert() or prepareForReplace()
- * without a matching execute() must have already have been called.
- * @param index the index of the slot to which to bind
- * @param value the value to bind
- */
- public void bind(int index, byte[] value) {
- if (value == null) {
- mPreparedStatement.bindNull(index);
- } else {
- mPreparedStatement.bindBlob(index, value);
- }
- }
-
- /**
- * Bind the value to an index. A prepareForInsert() or prepareForReplace()
- * without a matching execute() must have already have been called.
- * @param index the index of the slot to which to bind
- * @param value the value to bind
- */
- public void bind(int index, String value) {
- if (value == null) {
- mPreparedStatement.bindNull(index);
- } else {
- mPreparedStatement.bindString(index, value);
- }
- }
-
- /**
- * Performs an insert, adding a new row with the given values.
- * If the table contains conflicting rows, an error is
- * returned.
- *
- * @param values the set of values with which to populate the
- * new row
- *
- * @return the row ID of the newly inserted row, or -1 if an
- * error occurred
- */
- public long insert(ContentValues values) {
- return insertInternal(values, false);
- }
-
- /**
- * Execute the previously prepared insert or replace using the bound values
- * since the last call to prepareForInsert or prepareForReplace.
- *
- * <p>Note that calling bind() and then execute() is not thread-safe. The only thread-safe
- * way to use this class is to call insert() or replace().
- *
- * @return the row ID of the newly inserted row, or -1 if an
- * error occurred
- */
- public long execute() {
- if (mPreparedStatement == null) {
- throw new IllegalStateException("you must prepare this inserter before calling "
- + "execute");
- }
- try {
- if (LOCAL_LOGV) Log.v(TAG, "--- doing insert or replace in table " + mTableName);
- return mPreparedStatement.executeInsert();
- } catch (SQLException e) {
- Log.e(TAG, "Error executing InsertHelper with table " + mTableName, e);
- return -1;
- } finally {
- // you can only call this once per prepare
- mPreparedStatement = null;
- }
- }
-
- /**
- * Prepare the InsertHelper for an insert. The pattern for this is:
- * <ul>
- * <li>prepareForInsert()
- * <li>bind(index, value);
- * <li>bind(index, value);
- * <li>...
- * <li>bind(index, value);
- * <li>execute();
- * </ul>
- */
- public void prepareForInsert() {
- mPreparedStatement = getStatement(false);
- mPreparedStatement.clearBindings();
- }
-
- /**
- * Prepare the InsertHelper for a replace. The pattern for this is:
- * <ul>
- * <li>prepareForReplace()
- * <li>bind(index, value);
- * <li>bind(index, value);
- * <li>...
- * <li>bind(index, value);
- * <li>execute();
- * </ul>
- */
- public void prepareForReplace() {
- mPreparedStatement = getStatement(true);
- mPreparedStatement.clearBindings();
- }
-
- /**
- * Performs an insert, adding a new row with the given values.
- * If the table contains conflicting rows, they are deleted
- * and replaced with the new row.
- *
- * @param values the set of values with which to populate the
- * new row
- *
- * @return the row ID of the newly inserted row, or -1 if an
- * error occurred
- */
- public long replace(ContentValues values) {
- return insertInternal(values, true);
- }
-
- /**
- * Close this object and release any resources associated with
- * it. The behavior of calling <code>insert()</code> after
- * calling this method is undefined.
- */
- public void close() {
- if (mInsertStatement != null) {
- mInsertStatement.close();
- mInsertStatement = null;
- }
- if (mReplaceStatement != null) {
- mReplaceStatement.close();
- mReplaceStatement = null;
- }
- mInsertSQL = null;
- mColumns = null;
- }
- }
-
- /**
- * Creates a db and populates it with the sql statements in sqlStatements.
- *
- * @param context the context to use to create the db
- * @param dbName the name of the db to create
- * @param dbVersion the version to set on the db
- * @param sqlStatements the statements to use to populate the db. This should be a single string
- * of the form returned by sqlite3's <tt>.dump</tt> command (statements separated by
- * semicolons)
- */
- static public void createDbFromSqlStatements(
- Context context, String dbName, int dbVersion, String sqlStatements) {
- SQLiteDatabase db = context.openOrCreateDatabase(dbName, 0, null);
- // TODO: this is not quite safe since it assumes that all semicolons at the end of a line
- // terminate statements. It is possible that a text field contains ;\n. We will have to fix
- // this if that turns out to be a problem.
- String[] statements = TextUtils.split(sqlStatements, ";\n");
- for (String statement : statements) {
- if (TextUtils.isEmpty(statement)) continue;
- db.execSQL(statement);
- }
- db.setVersion(dbVersion);
- db.close();
- }
-}
diff --git a/core/java/android/database/IBulkCursor.java b/core/java/android/database/IBulkCursor.java
deleted file mode 100644
index 24354fd..0000000
--- a/core/java/android/database/IBulkCursor.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.Bundle;
-
-import java.util.Map;
-
-/**
- * This interface provides a low-level way to pass bulk cursor data across
- * both process and language boundries. Application code should use the Cursor
- * interface directly.
- *
- * {@hide}
- */
-public interface IBulkCursor extends IInterface
-{
- /**
- * Returns a BulkCursorWindow, which either has a reference to a shared
- * memory segment with the rows, or an array of JSON strings.
- */
- public CursorWindow getWindow(int startPos) throws RemoteException;
-
- public void onMove(int position) throws RemoteException;
-
- /**
- * Returns the number of rows in the cursor.
- *
- * @return the number of rows in the cursor.
- */
- public int count() throws RemoteException;
-
- /**
- * Returns a string array holding the names of all of the columns in the
- * cursor in the order in which they were listed in the result.
- *
- * @return the names of the columns returned in this query.
- */
- public String[] getColumnNames() throws RemoteException;
-
- public boolean updateRows(Map<? extends Long, ? extends Map<String, Object>> values) throws RemoteException;
-
- public boolean deleteRow(int position) throws RemoteException;
-
- public void deactivate() throws RemoteException;
-
- public void close() throws RemoteException;
-
- public int requery(IContentObserver observer, CursorWindow window) throws RemoteException;
-
- boolean getWantsAllOnMoveCalls() throws RemoteException;
-
- Bundle getExtras() throws RemoteException;
-
- Bundle respond(Bundle extras) throws RemoteException;
-
- /* IPC constants */
- static final String descriptor = "android.content.IBulkCursor";
-
- static final int GET_CURSOR_WINDOW_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
- static final int COUNT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1;
- static final int GET_COLUMN_NAMES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 2;
- static final int UPDATE_ROWS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 3;
- static final int DELETE_ROW_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 4;
- static final int DEACTIVATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 5;
- static final int REQUERY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 6;
- static final int ON_MOVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 7;
- static final int WANTS_ON_MOVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 8;
- static final int GET_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 9;
- static final int RESPOND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 10;
- static final int CLOSE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 11;
-}
-
diff --git a/core/java/android/database/IContentObserver.aidl b/core/java/android/database/IContentObserver.aidl
deleted file mode 100755
index ac2f975..0000000
--- a/core/java/android/database/IContentObserver.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.database;
-
-/**
- * @hide
- */
-interface IContentObserver
-{
- /**
- * This method is called when an update occurs to the cursor that is being
- * observed. selfUpdate is true if the update was caused by a call to
- * commit on the cursor that is being observed.
- */
- oneway void onChange(boolean selfUpdate);
-}
diff --git a/core/java/android/database/MatrixCursor.java b/core/java/android/database/MatrixCursor.java
deleted file mode 100644
index cf5a573..0000000
--- a/core/java/android/database/MatrixCursor.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-import java.util.ArrayList;
-
-/**
- * A mutable cursor implementation backed by an array of {@code Object}s. Use
- * {@link #newRow()} to add rows. Automatically expands internal capacity
- * as needed.
- */
-public class MatrixCursor extends AbstractCursor {
-
- private final String[] columnNames;
- private Object[] data;
- private int rowCount = 0;
- private final int columnCount;
-
- /**
- * Constructs a new cursor with the given initial capacity.
- *
- * @param columnNames names of the columns, the ordering of which
- * determines column ordering elsewhere in this cursor
- * @param initialCapacity in rows
- */
- public MatrixCursor(String[] columnNames, int initialCapacity) {
- this.columnNames = columnNames;
- this.columnCount = columnNames.length;
-
- if (initialCapacity < 1) {
- initialCapacity = 1;
- }
-
- this.data = new Object[columnCount * initialCapacity];
- }
-
- /**
- * Constructs a new cursor.
- *
- * @param columnNames names of the columns, the ordering of which
- * determines column ordering elsewhere in this cursor
- */
- public MatrixCursor(String[] columnNames) {
- this(columnNames, 16);
- }
-
- /**
- * Gets value at the given column for the current row.
- */
- private Object get(int column) {
- if (column < 0 || column >= columnCount) {
- throw new CursorIndexOutOfBoundsException("Requested column: "
- + column + ", # of columns: " + columnCount);
- }
- if (mPos < 0) {
- throw new CursorIndexOutOfBoundsException("Before first row.");
- }
- if (mPos >= rowCount) {
- throw new CursorIndexOutOfBoundsException("After last row.");
- }
- return data[mPos * columnCount + column];
- }
-
- /**
- * Adds a new row to the end and returns a builder for that row. Not safe
- * for concurrent use.
- *
- * @return builder which can be used to set the column values for the new
- * row
- */
- public RowBuilder newRow() {
- rowCount++;
- int endIndex = rowCount * columnCount;
- ensureCapacity(endIndex);
- int start = endIndex - columnCount;
- return new RowBuilder(start, endIndex);
- }
-
- /**
- * Adds a new row to the end with the given column values. Not safe
- * for concurrent use.
- *
- * @throws IllegalArgumentException if {@code columnValues.length !=
- * columnNames.length}
- * @param columnValues in the same order as the the column names specified
- * at cursor construction time
- */
- public void addRow(Object[] columnValues) {
- if (columnValues.length != columnCount) {
- throw new IllegalArgumentException("columnNames.length = "
- + columnCount + ", columnValues.length = "
- + columnValues.length);
- }
-
- int start = rowCount++ * columnCount;
- ensureCapacity(start + columnCount);
- System.arraycopy(columnValues, 0, data, start, columnCount);
- }
-
- /**
- * Adds a new row to the end with the given column values. Not safe
- * for concurrent use.
- *
- * @throws IllegalArgumentException if {@code columnValues.size() !=
- * columnNames.length}
- * @param columnValues in the same order as the the column names specified
- * at cursor construction time
- */
- public void addRow(Iterable<?> columnValues) {
- int start = rowCount * columnCount;
- int end = start + columnCount;
- ensureCapacity(end);
-
- if (columnValues instanceof ArrayList<?>) {
- addRow((ArrayList<?>) columnValues, start);
- return;
- }
-
- int current = start;
- Object[] localData = data;
- for (Object columnValue : columnValues) {
- if (current == end) {
- // TODO: null out row?
- throw new IllegalArgumentException(
- "columnValues.size() > columnNames.length");
- }
- localData[current++] = columnValue;
- }
-
- if (current != end) {
- // TODO: null out row?
- throw new IllegalArgumentException(
- "columnValues.size() < columnNames.length");
- }
-
- // Increase row count here in case we encounter an exception.
- rowCount++;
- }
-
- /** Optimization for {@link ArrayList}. */
- private void addRow(ArrayList<?> columnValues, int start) {
- int size = columnValues.size();
- if (size != columnCount) {
- throw new IllegalArgumentException("columnNames.length = "
- + columnCount + ", columnValues.size() = " + size);
- }
-
- rowCount++;
- Object[] localData = data;
- for (int i = 0; i < size; i++) {
- localData[start + i] = columnValues.get(i);
- }
- }
-
- /** Ensures that this cursor has enough capacity. */
- private void ensureCapacity(int size) {
- if (size > data.length) {
- Object[] oldData = this.data;
- int newSize = data.length * 2;
- if (newSize < size) {
- newSize = size;
- }
- this.data = new Object[newSize];
- System.arraycopy(oldData, 0, this.data, 0, oldData.length);
- }
- }
-
- /**
- * Builds a row, starting from the left-most column and adding one column
- * value at a time. Follows the same ordering as the column names specified
- * at cursor construction time.
- */
- public class RowBuilder {
-
- private int index;
- private final int endIndex;
-
- RowBuilder(int index, int endIndex) {
- this.index = index;
- this.endIndex = endIndex;
- }
-
- /**
- * Sets the next column value in this row.
- *
- * @throws CursorIndexOutOfBoundsException if you try to add too many
- * values
- * @return this builder to support chaining
- */
- public RowBuilder add(Object columnValue) {
- if (index == endIndex) {
- throw new CursorIndexOutOfBoundsException(
- "No more columns left.");
- }
-
- data[index++] = columnValue;
- return this;
- }
- }
-
- // AbstractCursor implementation.
-
- public int getCount() {
- return rowCount;
- }
-
- public String[] getColumnNames() {
- return columnNames;
- }
-
- public String getString(int column) {
- return String.valueOf(get(column));
- }
-
- public short getShort(int column) {
- Object value = get(column);
- return (value instanceof String)
- ? Short.valueOf((String) value)
- : ((Number) value).shortValue();
- }
-
- public int getInt(int column) {
- Object value = get(column);
- return (value instanceof String)
- ? Integer.valueOf((String) value)
- : ((Number) value).intValue();
- }
-
- public long getLong(int column) {
- Object value = get(column);
- return (value instanceof String)
- ? Long.valueOf((String) value)
- : ((Number) value).longValue();
- }
-
- public float getFloat(int column) {
- Object value = get(column);
- return (value instanceof String)
- ? Float.valueOf((String) value)
- : ((Number) value).floatValue();
- }
-
- public double getDouble(int column) {
- Object value = get(column);
- return (value instanceof String)
- ? Double.valueOf((String) value)
- : ((Number) value).doubleValue();
- }
-
- public boolean isNull(int column) {
- return get(column) == null;
- }
-}
diff --git a/core/java/android/database/MergeCursor.java b/core/java/android/database/MergeCursor.java
deleted file mode 100644
index 7e91159..0000000
--- a/core/java/android/database/MergeCursor.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-/**
- * A convience class that lets you present an array of Cursors as a single linear Cursor.
- * The schema of the cursors presented is entirely up to the creator of the MergeCursor, and
- * may be different if that is desired. Calls to getColumns, getColumnIndex, etc will return the
- * value for the row that the MergeCursor is currently pointing at.
- */
-public class MergeCursor extends AbstractCursor
-{
- private DataSetObserver mObserver = new DataSetObserver() {
-
- @Override
- public void onChanged() {
- // Reset our position so the optimizations in move-related code
- // don't screw us over
- mPos = -1;
- }
-
- @Override
- public void onInvalidated() {
- mPos = -1;
- }
- };
-
- public MergeCursor(Cursor[] cursors)
- {
- mCursors = cursors;
- mCursor = cursors[0];
-
- for (int i = 0; i < mCursors.length; i++) {
- if (mCursors[i] == null) continue;
-
- mCursors[i].registerDataSetObserver(mObserver);
- }
- }
-
- @Override
- public int getCount()
- {
- int count = 0;
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] != null) {
- count += mCursors[i].getCount();
- }
- }
- return count;
- }
-
- @Override
- public boolean onMove(int oldPosition, int newPosition)
- {
- /* Find the right cursor */
- mCursor = null;
- int cursorStartPos = 0;
- int length = mCursors.length;
- for (int i = 0 ; i < length; i++) {
- if (mCursors[i] == null) {
- continue;
- }
-
- if (newPosition < (cursorStartPos + mCursors[i].getCount())) {
- mCursor = mCursors[i];
- break;
- }
-
- cursorStartPos += mCursors[i].getCount();
- }
-
- /* Move it to the right position */
- if (mCursor != null) {
- boolean ret = mCursor.moveToPosition(newPosition - cursorStartPos);
- return ret;
- }
- return false;
- }
-
- /**
- * @hide
- * @deprecated
- */
- @Override
- public boolean deleteRow()
- {
- return mCursor.deleteRow();
- }
-
- /**
- * @hide
- * @deprecated
- */
- @Override
- public boolean commitUpdates() {
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] != null) {
- mCursors[i].commitUpdates();
- }
- }
- onChange(true);
- return true;
- }
-
- @Override
- public String getString(int column)
- {
- return mCursor.getString(column);
- }
-
- @Override
- public short getShort(int column)
- {
- return mCursor.getShort(column);
- }
-
- @Override
- public int getInt(int column)
- {
- return mCursor.getInt(column);
- }
-
- @Override
- public long getLong(int column)
- {
- return mCursor.getLong(column);
- }
-
- @Override
- public float getFloat(int column)
- {
- return mCursor.getFloat(column);
- }
-
- @Override
- public double getDouble(int column)
- {
- return mCursor.getDouble(column);
- }
-
- @Override
- public boolean isNull(int column)
- {
- return mCursor.isNull(column);
- }
-
- @Override
- public byte[] getBlob(int column)
- {
- return mCursor.getBlob(column);
- }
-
- @Override
- public String[] getColumnNames()
- {
- if (mCursor != null) {
- return mCursor.getColumnNames();
- } else {
- return new String[0];
- }
- }
-
- @Override
- public void deactivate()
- {
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] != null) {
- mCursors[i].deactivate();
- }
- }
- }
-
- @Override
- public void close() {
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] == null) continue;
- mCursors[i].close();
- }
- }
-
- @Override
- public void registerContentObserver(ContentObserver observer) {
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] != null) {
- mCursors[i].registerContentObserver(observer);
- }
- }
- }
- @Override
- public void unregisterContentObserver(ContentObserver observer) {
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] != null) {
- mCursors[i].unregisterContentObserver(observer);
- }
- }
- }
-
- @Override
- public void registerDataSetObserver(DataSetObserver observer) {
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] != null) {
- mCursors[i].registerDataSetObserver(observer);
- }
- }
- }
-
- @Override
- public void unregisterDataSetObserver(DataSetObserver observer) {
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] != null) {
- mCursors[i].unregisterDataSetObserver(observer);
- }
- }
- }
-
- @Override
- public boolean requery()
- {
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] == null) {
- continue;
- }
-
- if (mCursors[i].requery() == false) {
- return false;
- }
- }
-
- return true;
- }
-
- private Cursor mCursor; // updated in onMove
- private Cursor[] mCursors;
-}
diff --git a/core/java/android/database/Observable.java b/core/java/android/database/Observable.java
deleted file mode 100644
index b6fecab..0000000
--- a/core/java/android/database/Observable.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-import java.util.ArrayList;
-
-/**
- * Provides methods for (un)registering arbitrary observers in an ArrayList.
- */
-public abstract class Observable<T> {
- /**
- * The list of observers. An observer can be in the list at most
- * once and will never be null.
- */
- protected final ArrayList<T> mObservers = new ArrayList<T>();
-
- /**
- * Adds an observer to the list. The observer cannot be null and it must not already
- * be registered.
- * @param observer the observer to register
- * @throws IllegalArgumentException the observer is null
- * @throws IllegalStateException the observer is already registered
- */
- public void registerObserver(T observer) {
- if (observer == null) {
- throw new IllegalArgumentException("The observer is null.");
- }
- synchronized(mObservers) {
- if (mObservers.contains(observer)) {
- throw new IllegalStateException("Observer " + observer + " is already registered.");
- }
- mObservers.add(observer);
- }
- }
-
- /**
- * Removes a previously registered observer. The observer must not be null and it
- * must already have been registered.
- * @param observer the observer to unregister
- * @throws IllegalArgumentException the observer is null
- * @throws IllegalStateException the observer is not yet registered
- */
- public void unregisterObserver(T observer) {
- if (observer == null) {
- throw new IllegalArgumentException("The observer is null.");
- }
- synchronized(mObservers) {
- int index = mObservers.indexOf(observer);
- if (index == -1) {
- throw new IllegalStateException("Observer " + observer + " was not registered.");
- }
- mObservers.remove(index);
- }
- }
-
- /**
- * Remove all registered observer
- */
- public void unregisterAll() {
- synchronized(mObservers) {
- mObservers.clear();
- }
- }
-}
diff --git a/core/java/android/database/SQLException.java b/core/java/android/database/SQLException.java
deleted file mode 100644
index 0386af0..0000000
--- a/core/java/android/database/SQLException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-/**
- * An exception that indicates there was an error with SQL parsing or execution.
- */
-public class SQLException extends RuntimeException
-{
- public SQLException() {}
-
- public SQLException(String error)
- {
- super(error);
- }
-}
diff --git a/core/java/android/database/StaleDataException.java b/core/java/android/database/StaleDataException.java
deleted file mode 100644
index ee70beb..0000000
--- a/core/java/android/database/StaleDataException.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-/**
- * This exception is thrown when a Cursor contains stale data and must be
- * requeried before being used again.
- */
-public class StaleDataException extends java.lang.RuntimeException
-{
- public StaleDataException()
- {
- super();
- }
-
- public StaleDataException(String description)
- {
- super(description);
- }
-}
diff --git a/core/java/android/database/package.html b/core/java/android/database/package.html
deleted file mode 100644
index 1f76d9f..0000000
--- a/core/java/android/database/package.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<HTML>
-<BODY>
-Contains classes to explore data returned through a content provider.
-<p>
-If you need to manage data in a private database, use the {@link
-android.database.sqlite} classes. These classes are used to manage the {@link
-android.database.Cursor} object returned from a content provider query. Databases
-are usually created and opened with {@link android.content.Context#openOrCreateDatabase}
-To make requests through
-content providers, you can use the {@link android.content.ContentResolver
-content.ContentResolver} class.
-<p>All databases are stored on the device in <code>/data/data/&lt;package_name&gt;/databases</code>
-</BODY>
-</HTML>
diff --git a/core/java/android/database/sqlite/SQLiteAbortException.java b/core/java/android/database/sqlite/SQLiteAbortException.java
deleted file mode 100644
index 64dc4b7..0000000
--- a/core/java/android/database/sqlite/SQLiteAbortException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-/**
- * An exception that indicates that the SQLite program was aborted.
- * This can happen either through a call to ABORT in a trigger,
- * or as the result of using the ABORT conflict clause.
- */
-public class SQLiteAbortException extends SQLiteException {
- public SQLiteAbortException() {}
-
- public SQLiteAbortException(String error) {
- super(error);
- }
-}
diff --git a/core/java/android/database/sqlite/SQLiteClosable.java b/core/java/android/database/sqlite/SQLiteClosable.java
deleted file mode 100644
index f64261c..0000000
--- a/core/java/android/database/sqlite/SQLiteClosable.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-/**
- * An object create from a SQLiteDatabase that can be closed.
- */
-public abstract class SQLiteClosable {
- private int mReferenceCount = 1;
- private Object mLock = new Object();
- protected abstract void onAllReferencesReleased();
- protected void onAllReferencesReleasedFromContainer(){}
-
- public void acquireReference() {
- synchronized(mLock) {
- if (mReferenceCount <= 0) {
- throw new IllegalStateException(
- "attempt to acquire a reference on a close SQLiteClosable");
- }
- mReferenceCount++;
- }
- }
-
- public void releaseReference() {
- synchronized(mLock) {
- mReferenceCount--;
- if (mReferenceCount == 0) {
- onAllReferencesReleased();
- }
- }
- }
-
- public void releaseReferenceFromContainer() {
- synchronized(mLock) {
- mReferenceCount--;
- if (mReferenceCount == 0) {
- onAllReferencesReleasedFromContainer();
- }
- }
- }
-}
diff --git a/core/java/android/database/sqlite/SQLiteConstraintException.java b/core/java/android/database/sqlite/SQLiteConstraintException.java
deleted file mode 100644
index e3119eb..0000000
--- a/core/java/android/database/sqlite/SQLiteConstraintException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-/**
- * An exception that indicates that an integrity constraint was violated.
- */
-public class SQLiteConstraintException extends SQLiteException {
- public SQLiteConstraintException() {}
-
- public SQLiteConstraintException(String error) {
- super(error);
- }
-}
diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java
deleted file mode 100644
index 70b9b83..0000000
--- a/core/java/android/database/sqlite/SQLiteCursor.java
+++ /dev/null
@@ -1,606 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-import android.database.AbstractWindowedCursor;
-import android.database.CursorWindow;
-import android.database.DataSetObserver;
-import android.database.SQLException;
-
-import android.os.Handler;
-import android.os.Message;
-import android.os.Process;
-import android.text.TextUtils;
-import android.util.Config;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * A Cursor implementation that exposes results from a query on a
- * {@link SQLiteDatabase}.
- */
-public class SQLiteCursor extends AbstractWindowedCursor {
- static final String TAG = "Cursor";
- static final int NO_COUNT = -1;
-
- /** The name of the table to edit */
- private String mEditTable;
-
- /** The names of the columns in the rows */
- private String[] mColumns;
-
- /** The query object for the cursor */
- private SQLiteQuery mQuery;
-
- /** The database the cursor was created from */
- private SQLiteDatabase mDatabase;
-
- /** The compiled query this cursor came from */
- private SQLiteCursorDriver mDriver;
-
- /** The number of rows in the cursor */
- private int mCount = NO_COUNT;
-
- /** A mapping of column names to column indices, to speed up lookups */
- private Map<String, Integer> mColumnNameMap;
-
- /** Used to find out where a cursor was allocated in case it never got
- * released. */
- private StackTraceElement[] mStackTraceElements;
-
- /**
- * mMaxRead is the max items that each cursor window reads
- * default to a very high value
- */
- private int mMaxRead = Integer.MAX_VALUE;
- private int mInitialRead = Integer.MAX_VALUE;
- private int mCursorState = 0;
- private ReentrantLock mLock = null;
- private boolean mPendingData = false;
-
- /**
- * support for a cursor variant that doesn't always read all results
- * initialRead is the initial number of items that cursor window reads
- * if query contains more than this number of items, a thread will be
- * created and handle the left over items so that caller can show
- * results as soon as possible
- * @param initialRead initial number of items that cursor read
- * @param maxRead leftover items read at maxRead items per time
- * @hide
- */
- public void setLoadStyle(int initialRead, int maxRead) {
- mMaxRead = maxRead;
- mInitialRead = initialRead;
- mLock = new ReentrantLock(true);
- }
-
- private void queryThreadLock() {
- if (mLock != null) {
- mLock.lock();
- }
- }
-
- private void queryThreadUnlock() {
- if (mLock != null) {
- mLock.unlock();
- }
- }
-
-
- /**
- * @hide
- */
- final private class QueryThread implements Runnable {
- private final int mThreadState;
- QueryThread(int version) {
- mThreadState = version;
- }
- private void sendMessage() {
- if (mNotificationHandler != null) {
- mNotificationHandler.sendEmptyMessage(1);
- mPendingData = false;
- } else {
- mPendingData = true;
- }
-
- }
- public void run() {
- // use cached mWindow, to avoid get null mWindow
- CursorWindow cw = mWindow;
- Process.setThreadPriority(Process.myTid(), Process.THREAD_PRIORITY_BACKGROUND);
- // the cursor's state doesn't change
- while (true) {
- mLock.lock();
- if (mCursorState != mThreadState) {
- mLock.unlock();
- break;
- }
- try {
- int count = mQuery.fillWindow(cw, mMaxRead, mCount);
- // return -1 means not finished
- if (count != 0) {
- if (count == NO_COUNT){
- mCount += mMaxRead;
- sendMessage();
- } else {
- mCount = count;
- sendMessage();
- break;
- }
- } else {
- break;
- }
- } catch (Exception e) {
- // end the tread when the cursor is close
- break;
- } finally {
- mLock.unlock();
- }
- }
- }
- }
-
- /**
- * @hide
- */
- protected class MainThreadNotificationHandler extends Handler {
- public void handleMessage(Message msg) {
- notifyDataSetChange();
- }
- }
-
- /**
- * @hide
- */
- protected MainThreadNotificationHandler mNotificationHandler;
-
- public void registerDataSetObserver(DataSetObserver observer) {
- super.registerDataSetObserver(observer);
- if ((Integer.MAX_VALUE != mMaxRead || Integer.MAX_VALUE != mInitialRead) &&
- mNotificationHandler == null) {
- queryThreadLock();
- try {
- mNotificationHandler = new MainThreadNotificationHandler();
- if (mPendingData) {
- notifyDataSetChange();
- mPendingData = false;
- }
- } finally {
- queryThreadUnlock();
- }
- }
-
- }
-
- /**
- * Execute a query and provide access to its result set through a Cursor
- * interface. For a query such as: {@code SELECT name, birth, phone FROM
- * myTable WHERE ... LIMIT 1,20 ORDER BY...} the column names (name, birth,
- * phone) would be in the projection argument and everything from
- * {@code FROM} onward would be in the params argument. This constructor
- * has package scope.
- *
- * @param db a reference to a Database object that is already constructed
- * and opened
- * @param editTable the name of the table used for this query
- * @param query the rest of the query terms
- * cursor is finalized
- */
- public SQLiteCursor(SQLiteDatabase db, SQLiteCursorDriver driver,
- String editTable, SQLiteQuery query) {
- // The AbstractCursor constructor needs to do some setup.
- super();
-
- if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) {
- mStackTraceElements = new Exception().getStackTrace();
- }
-
- mDatabase = db;
- mDriver = driver;
- mEditTable = editTable;
- mColumnNameMap = null;
- mQuery = query;
-
- try {
- db.lock();
-
- // Setup the list of columns
- int columnCount = mQuery.columnCountLocked();
- mColumns = new String[columnCount];
-
- // Read in all column names
- for (int i = 0; i < columnCount; i++) {
- String columnName = mQuery.columnNameLocked(i);
- mColumns[i] = columnName;
- if (Config.LOGV) {
- Log.v("DatabaseWindow", "mColumns[" + i + "] is "
- + mColumns[i]);
- }
-
- // Make note of the row ID column index for quick access to it
- if ("_id".equals(columnName)) {
- mRowIdColumnIndex = i;
- }
- }
- } finally {
- db.unlock();
- }
- }
-
- /**
- * @return the SQLiteDatabase that this cursor is associated with.
- */
- public SQLiteDatabase getDatabase() {
- return mDatabase;
- }
-
- @Override
- public boolean onMove(int oldPosition, int newPosition) {
- // Make sure the row at newPosition is present in the window
- if (mWindow == null || newPosition < mWindow.getStartPosition() ||
- newPosition >= (mWindow.getStartPosition() + mWindow.getNumRows())) {
- fillWindow(newPosition);
- }
-
- return true;
- }
-
- @Override
- public int getCount() {
- if (mCount == NO_COUNT) {
- fillWindow(0);
- }
- return mCount;
- }
-
- private void fillWindow (int startPos) {
- if (mWindow == null) {
- // If there isn't a window set already it will only be accessed locally
- mWindow = new CursorWindow(true /* the window is local only */);
- } else {
- mCursorState++;
- queryThreadLock();
- try {
- mWindow.clear();
- } finally {
- queryThreadUnlock();
- }
- }
- mWindow.setStartPosition(startPos);
- mCount = mQuery.fillWindow(mWindow, mInitialRead, 0);
- // return -1 means not finished
- if (mCount == NO_COUNT){
- mCount = startPos + mInitialRead;
- Thread t = new Thread(new QueryThread(mCursorState), "query thread");
- t.start();
- }
- }
-
- @Override
- public int getColumnIndex(String columnName) {
- // Create mColumnNameMap on demand
- if (mColumnNameMap == null) {
- String[] columns = mColumns;
- int columnCount = columns.length;
- HashMap<String, Integer> map = new HashMap<String, Integer>(columnCount, 1);
- for (int i = 0; i < columnCount; i++) {
- map.put(columns[i], i);
- }
- mColumnNameMap = map;
- }
-
- // Hack according to bug 903852
- final int periodIndex = columnName.lastIndexOf('.');
- if (periodIndex != -1) {
- Exception e = new Exception();
- Log.e(TAG, "requesting column name with table name -- " + columnName, e);
- columnName = columnName.substring(periodIndex + 1);
- }
-
- Integer i = mColumnNameMap.get(columnName);
- if (i != null) {
- return i.intValue();
- } else {
- return -1;
- }
- }
-
- /**
- * @hide
- * @deprecated
- */
- @Override
- public boolean deleteRow() {
- checkPosition();
-
- // Only allow deletes if there is an ID column, and the ID has been read from it
- if (mRowIdColumnIndex == -1 || mCurrentRowID == null) {
- Log.e(TAG,
- "Could not delete row because either the row ID column is not available or it" +
- "has not been read.");
- return false;
- }
-
- boolean success;
-
- /*
- * Ensure we don't change the state of the database when another
- * thread is holding the database lock. requery() and moveTo() are also
- * synchronized here to make sure they get the state of the database
- * immediately following the DELETE.
- */
- mDatabase.lock();
- try {
- try {
- mDatabase.delete(mEditTable, mColumns[mRowIdColumnIndex] + "=?",
- new String[] {mCurrentRowID.toString()});
- success = true;
- } catch (SQLException e) {
- success = false;
- }
-
- int pos = mPos;
- requery();
-
- /*
- * Ensure proper cursor state. Note that mCurrentRowID changes
- * in this call.
- */
- moveToPosition(pos);
- } finally {
- mDatabase.unlock();
- }
-
- if (success) {
- onChange(true);
- return true;
- } else {
- return false;
- }
- }
-
- @Override
- public String[] getColumnNames() {
- return mColumns;
- }
-
- /**
- * @hide
- * @deprecated
- */
- @Override
- public boolean supportsUpdates() {
- return super.supportsUpdates() && !TextUtils.isEmpty(mEditTable);
- }
-
- /**
- * @hide
- * @deprecated
- */
- @Override
- public boolean commitUpdates(Map<? extends Long,
- ? extends Map<String, Object>> additionalValues) {
- if (!supportsUpdates()) {
- Log.e(TAG, "commitUpdates not supported on this cursor, did you "
- + "include the _id column?");
- return false;
- }
-
- /*
- * Prevent other threads from changing the updated rows while they're
- * being processed here.
- */
- synchronized (mUpdatedRows) {
- if (additionalValues != null) {
- mUpdatedRows.putAll(additionalValues);
- }
-
- if (mUpdatedRows.size() == 0) {
- return true;
- }
-
- /*
- * Prevent other threads from changing the database state while
- * we process the updated rows, and prevents us from changing the
- * database behind the back of another thread.
- */
- mDatabase.beginTransaction();
- try {
- StringBuilder sql = new StringBuilder(128);
-
- // For each row that has been updated
- for (Map.Entry<Long, Map<String, Object>> rowEntry :
- mUpdatedRows.entrySet()) {
- Map<String, Object> values = rowEntry.getValue();
- Long rowIdObj = rowEntry.getKey();
-
- if (rowIdObj == null || values == null) {
- throw new IllegalStateException("null rowId or values found! rowId = "
- + rowIdObj + ", values = " + values);
- }
-
- if (values.size() == 0) {
- continue;
- }
-
- long rowId = rowIdObj.longValue();
-
- Iterator<Map.Entry<String, Object>> valuesIter =
- values.entrySet().iterator();
-
- sql.setLength(0);
- sql.append("UPDATE " + mEditTable + " SET ");
-
- // For each column value that has been updated
- Object[] bindings = new Object[values.size()];
- int i = 0;
- while (valuesIter.hasNext()) {
- Map.Entry<String, Object> entry = valuesIter.next();
- sql.append(entry.getKey());
- sql.append("=?");
- bindings[i] = entry.getValue();
- if (valuesIter.hasNext()) {
- sql.append(", ");
- }
- i++;
- }
-
- sql.append(" WHERE " + mColumns[mRowIdColumnIndex]
- + '=' + rowId);
- sql.append(';');
- mDatabase.execSQL(sql.toString(), bindings);
- mDatabase.rowUpdated(mEditTable, rowId);
- }
- mDatabase.setTransactionSuccessful();
- } finally {
- mDatabase.endTransaction();
- }
-
- mUpdatedRows.clear();
- }
-
- // Let any change observers know about the update
- onChange(true);
-
- return true;
- }
-
- private void deactivateCommon() {
- if (Config.LOGV) Log.v(TAG, "<<< Releasing cursor " + this);
- mCursorState = 0;
- if (mWindow != null) {
- mWindow.close();
- mWindow = null;
- }
- if (Config.LOGV) Log.v("DatabaseWindow", "closing window in release()");
- }
-
- @Override
- public void deactivate() {
- super.deactivate();
- deactivateCommon();
- mDriver.cursorDeactivated();
- }
-
- @Override
- public void close() {
- super.close();
- deactivateCommon();
- mQuery.close();
- mDriver.cursorClosed();
- }
-
- @Override
- public boolean requery() {
- if (isClosed()) {
- return false;
- }
- long timeStart = 0;
- if (Config.LOGV) {
- timeStart = System.currentTimeMillis();
- }
- /*
- * Synchronize on the database lock to ensure that mCount matches the
- * results of mQuery.requery().
- */
- mDatabase.lock();
- try {
- if (mWindow != null) {
- mWindow.clear();
- }
- mPos = -1;
- // This one will recreate the temp table, and get its count
- mDriver.cursorRequeried(this);
- mCount = NO_COUNT;
- mCursorState++;
- queryThreadLock();
- try {
- mQuery.requery();
- } finally {
- queryThreadUnlock();
- }
- } finally {
- mDatabase.unlock();
- }
-
- if (Config.LOGV) {
- Log.v("DatabaseWindow", "closing window in requery()");
- Log.v(TAG, "--- Requery()ed cursor " + this + ": " + mQuery);
- }
-
- boolean result = super.requery();
- if (Config.LOGV) {
- long timeEnd = System.currentTimeMillis();
- Log.v(TAG, "requery (" + (timeEnd - timeStart) + " ms): " + mDriver.toString());
- }
- return result;
- }
-
- @Override
- public void setWindow(CursorWindow window) {
- if (mWindow != null) {
- mCursorState++;
- queryThreadLock();
- try {
- mWindow.close();
- } finally {
- queryThreadUnlock();
- }
- mCount = NO_COUNT;
- }
- mWindow = window;
- }
-
- /**
- * Changes the selection arguments. The new values take effect after a call to requery().
- */
- public void setSelectionArguments(String[] selectionArgs) {
- mDriver.setBindArguments(selectionArgs);
- }
-
- /**
- * Release the native resources, if they haven't been released yet.
- */
- @Override
- protected void finalize() {
- try {
- if (mWindow != null) {
- close();
- String message = "Finalizing cursor " + this + " on " + mEditTable
- + " that has not been deactivated or closed";
- if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) {
- Log.d(TAG, message + "\nThis cursor was created in:");
- for (StackTraceElement ste : mStackTraceElements) {
- Log.d(TAG, " " + ste);
- }
- }
- SQLiteDebug.notifyActiveCursorFinalized();
- throw new IllegalStateException(message);
- } else {
- if (Config.LOGV) {
- Log.v(TAG, "Finalizing cursor " + this + " on " + mEditTable);
- }
- }
- } finally {
- super.finalize();
- }
- }
-}
diff --git a/core/java/android/database/sqlite/SQLiteCursorDriver.java b/core/java/android/database/sqlite/SQLiteCursorDriver.java
deleted file mode 100644
index eda1b78..0000000
--- a/core/java/android/database/sqlite/SQLiteCursorDriver.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase.CursorFactory;
-
-/**
- * A driver for SQLiteCursors that is used to create them and gets notified
- * by the cursors it creates on significant events in their lifetimes.
- */
-public interface SQLiteCursorDriver {
- /**
- * Executes the query returning a Cursor over the result set.
- *
- * @param factory The CursorFactory to use when creating the Cursors, or
- * null if standard SQLiteCursors should be returned.
- * @return a Cursor over the result set
- */
- Cursor query(CursorFactory factory, String[] bindArgs);
-
- /**
- * Called by a SQLiteCursor when it is released.
- */
- void cursorDeactivated();
-
- /**
- * Called by a SQLiteCursor when it is requeryed.
- *
- * @return The new count value.
- */
- void cursorRequeried(Cursor cursor);
-
- /**
- * Called by a SQLiteCursor when it it closed to destroy this object as well.
- */
- void cursorClosed();
-
- /**
- * Set new bind arguments. These will take effect in cursorRequeried().
- * @param bindArgs the new arguments
- */
- public void setBindArguments(String[] bindArgs);
-}
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
deleted file mode 100644
index 87bb277..0000000
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ /dev/null
@@ -1,1675 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.SQLException;
-import android.os.Debug;
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.Config;
-import android.util.Log;
-import android.util.EventLog;
-
-import java.io.File;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.WeakHashMap;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Exposes methods to manage a SQLite database.
- * <p>SQLiteDatabase has methods to create, delete, execute SQL commands, and
- * perform other common database management tasks.
- * <p>See the Notepad sample application in the SDK for an example of creating
- * and managing a database.
- * <p> Database names must be unique within an application, not across all
- * applications.
- *
- * <h3>Localized Collation - ORDER BY</h3>
- * <p>In addition to SQLite's default <code>BINARY</code> collator, Android supplies
- * two more, <code>LOCALIZED</code>, which changes with the system's current locale
- * if you wire it up correctly (XXX a link needed!), and <code>UNICODE</code>, which
- * is the Unicode Collation Algorithm and not tailored to the current locale.
- */
-public class SQLiteDatabase extends SQLiteClosable {
- private static final String TAG = "Database";
- private static final int DB_OPERATION_EVENT = 52000;
-
- /**
- * Algorithms used in ON CONFLICT clause
- * http://www.sqlite.org/lang_conflict.html
- * @hide
- */
- public enum ConflictAlgorithm {
- /**
- * When a constraint violation occurs, an immediate ROLLBACK occurs,
- * thus ending the current transaction, and the command aborts with a
- * return code of SQLITE_CONSTRAINT. If no transaction is active
- * (other than the implied transaction that is created on every command)
- * then this algorithm works the same as ABORT.
- */
- ROLLBACK("ROLLBACK"),
-
- /**
- * When a constraint violation occurs,no ROLLBACK is executed
- * so changes from prior commands within the same transaction
- * are preserved. This is the default behavior.
- */
- ABORT("ABORT"),
-
- /**
- * When a constraint violation occurs, the command aborts with a return
- * code SQLITE_CONSTRAINT. But any changes to the database that
- * the command made prior to encountering the constraint violation
- * are preserved and are not backed out.
- */
- FAIL("FAIL"),
-
- /**
- * When a constraint violation occurs, the one row that contains
- * the constraint violation is not inserted or changed.
- * But the command continues executing normally. Other rows before and
- * after the row that contained the constraint violation continue to be
- * inserted or updated normally. No error is returned.
- */
- IGNORE("IGNORE"),
-
- /**
- * When a UNIQUE constraint violation occurs, the pre-existing rows that
- * are causing the constraint violation are removed prior to inserting
- * or updating the current row. Thus the insert or update always occurs.
- * The command continues executing normally. No error is returned.
- * If a NOT NULL constraint violation occurs, the NULL value is replaced
- * by the default value for that column. If the column has no default
- * value, then the ABORT algorithm is used. If a CHECK constraint
- * violation occurs then the IGNORE algorithm is used. When this conflict
- * resolution strategy deletes rows in order to satisfy a constraint,
- * it does not invoke delete triggers on those rows.
- * This behavior might change in a future release.
- */
- REPLACE("REPLACE");
-
- private final String mValue;
- ConflictAlgorithm(String value) {
- mValue = value;
- }
- public String value() {
- return mValue;
- }
- }
-
- /**
- * Maximum Length Of A LIKE Or GLOB Pattern
- * The pattern matching algorithm used in the default LIKE and GLOB implementation
- * of SQLite can exhibit O(N^2) performance (where N is the number of characters in
- * the pattern) for certain pathological cases. To avoid denial-of-service attacks
- * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes.
- * The default value of this limit is 50000. A modern workstation can evaluate
- * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly.
- * The denial of service problem only comes into play when the pattern length gets
- * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns
- * are at most a few dozen bytes in length, paranoid application developers may
- * want to reduce this parameter to something in the range of a few hundred
- * if they know that external users are able to generate arbitrary patterns.
- */
- public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000;
-
- /**
- * Flag for {@link #openDatabase} to open the database for reading and writing.
- * If the disk is full, this may fail even before you actually write anything.
- *
- * {@more} Note that the value of this flag is 0, so it is the default.
- */
- public static final int OPEN_READWRITE = 0x00000000; // update native code if changing
-
- /**
- * Flag for {@link #openDatabase} to open the database for reading only.
- * This is the only reliable way to open a database if the disk may be full.
- */
- public static final int OPEN_READONLY = 0x00000001; // update native code if changing
-
- private static final int OPEN_READ_MASK = 0x00000001; // update native code if changing
-
- /**
- * Flag for {@link #openDatabase} to open the database without support for localized collators.
- *
- * {@more} This causes the collator <code>LOCALIZED</code> not to be created.
- * You must be consistent when using this flag to use the setting the database was
- * created with. If this is set, {@link #setLocale} will do nothing.
- */
- public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing
-
- /**
- * Flag for {@link #openDatabase} to create the database file if it does not already exist.
- */
- public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing
-
- /**
- * Indicates whether the most-recently started transaction has been marked as successful.
- */
- private boolean mInnerTransactionIsSuccessful;
-
- /**
- * Valid during the life of a transaction, and indicates whether the entire transaction (the
- * outer one and all of the inner ones) so far has been successful.
- */
- private boolean mTransactionIsSuccessful;
-
- /** Synchronize on this when accessing the database */
- private final ReentrantLock mLock = new ReentrantLock(true);
-
- private long mLockAcquiredWallTime = 0L;
- private long mLockAcquiredThreadTime = 0L;
-
- // limit the frequency of complaints about each database to one within 20 sec
- // unless run command adb shell setprop log.tag.Database VERBOSE
- private static final int LOCK_WARNING_WINDOW_IN_MS = 20000;
- /** If the lock is held this long then a warning will be printed when it is released. */
- private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS = 300;
- private static final int LOCK_ACQUIRED_WARNING_THREAD_TIME_IN_MS = 100;
- private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT = 2000;
-
- private long mLastLockMessageTime = 0L;
-
- /** Used by native code, do not rename */
- /* package */ int mNativeHandle = 0;
-
- /** Used to make temp table names unique */
- /* package */ int mTempTableSequence = 0;
-
- /** The path for the database file */
- private String mPath;
-
- /** The flags passed to open/create */
- private int mFlags;
-
- /** The optional factory to use when creating new Cursors */
- private CursorFactory mFactory;
-
- private WeakHashMap<SQLiteClosable, Object> mPrograms;
-
- private final RuntimeException mLeakedException;
-
- // package visible, since callers will access directly to minimize overhead in the case
- // that logging is not enabled.
- /* package */ final boolean mLogStats;
-
- /**
- * @param closable
- */
- void addSQLiteClosable(SQLiteClosable closable) {
- lock();
- try {
- mPrograms.put(closable, null);
- } finally {
- unlock();
- }
- }
-
- void removeSQLiteClosable(SQLiteClosable closable) {
- lock();
- try {
- mPrograms.remove(closable);
- } finally {
- unlock();
- }
- }
-
- @Override
- protected void onAllReferencesReleased() {
- if (isOpen()) {
- dbclose();
- }
- }
-
- /**
- * Attempts to release memory that SQLite holds but does not require to
- * operate properly. Typically this memory will come from the page cache.
- *
- * @return the number of bytes actually released
- */
- static public native int releaseMemory();
-
- /**
- * Control whether or not the SQLiteDatabase is made thread-safe by using locks
- * around critical sections. This is pretty expensive, so if you know that your
- * DB will only be used by a single thread then you should set this to false.
- * The default is true.
- * @param lockingEnabled set to true to enable locks, false otherwise
- */
- public void setLockingEnabled(boolean lockingEnabled) {
- mLockingEnabled = lockingEnabled;
- }
-
- /**
- * If set then the SQLiteDatabase is made thread-safe by using locks
- * around critical sections
- */
- private boolean mLockingEnabled = true;
-
- /* package */ void onCorruption() {
- try {
- // Close the database (if we can), which will cause subsequent operations to fail.
- close();
- } finally {
- Log.e(TAG, "Removing corrupt database: " + mPath);
- // Delete the corrupt file. Don't re-create it now -- that would just confuse people
- // -- but the next time someone tries to open it, they can set it up from scratch.
- new File(mPath).delete();
- }
- }
-
- /**
- * Locks the database for exclusive access. The database lock must be held when
- * touch the native sqlite3* object since it is single threaded and uses
- * a polling lock contention algorithm. The lock is recursive, and may be acquired
- * multiple times by the same thread. This is a no-op if mLockingEnabled is false.
- *
- * @see #unlock()
- */
- /* package */ void lock() {
- if (!mLockingEnabled) return;
- mLock.lock();
- if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) {
- if (mLock.getHoldCount() == 1) {
- // Use elapsed real-time since the CPU may sleep when waiting for IO
- mLockAcquiredWallTime = SystemClock.elapsedRealtime();
- mLockAcquiredThreadTime = Debug.threadCpuTimeNanos();
- }
- }
- }
-
- /**
- * Locks the database for exclusive access. The database lock must be held when
- * touch the native sqlite3* object since it is single threaded and uses
- * a polling lock contention algorithm. The lock is recursive, and may be acquired
- * multiple times by the same thread.
- *
- * @see #unlockForced()
- */
- private void lockForced() {
- mLock.lock();
- if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) {
- if (mLock.getHoldCount() == 1) {
- // Use elapsed real-time since the CPU may sleep when waiting for IO
- mLockAcquiredWallTime = SystemClock.elapsedRealtime();
- mLockAcquiredThreadTime = Debug.threadCpuTimeNanos();
- }
- }
- }
-
- /**
- * Releases the database lock. This is a no-op if mLockingEnabled is false.
- *
- * @see #unlock()
- */
- /* package */ void unlock() {
- if (!mLockingEnabled) return;
- if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) {
- if (mLock.getHoldCount() == 1) {
- checkLockHoldTime();
- }
- }
- mLock.unlock();
- }
-
- /**
- * Releases the database lock.
- *
- * @see #unlockForced()
- */
- private void unlockForced() {
- if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING) {
- if (mLock.getHoldCount() == 1) {
- checkLockHoldTime();
- }
- }
- mLock.unlock();
- }
-
- private void checkLockHoldTime() {
- // Use elapsed real-time since the CPU may sleep when waiting for IO
- long elapsedTime = SystemClock.elapsedRealtime();
- long lockedTime = elapsedTime - mLockAcquiredWallTime;
- if (lockedTime < LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT &&
- !Log.isLoggable(TAG, Log.VERBOSE) &&
- (elapsedTime - mLastLockMessageTime) < LOCK_WARNING_WINDOW_IN_MS) {
- return;
- }
- if (lockedTime > LOCK_ACQUIRED_WARNING_TIME_IN_MS) {
- int threadTime = (int)
- ((Debug.threadCpuTimeNanos() - mLockAcquiredThreadTime) / 1000000);
- if (threadTime > LOCK_ACQUIRED_WARNING_THREAD_TIME_IN_MS ||
- lockedTime > LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT) {
- mLastLockMessageTime = elapsedTime;
- String msg = "lock held on " + mPath + " for " + lockedTime + "ms. Thread time was "
- + threadTime + "ms";
- if (SQLiteDebug.DEBUG_LOCK_TIME_TRACKING_STACK_TRACE) {
- Log.d(TAG, msg, new Exception());
- } else {
- Log.d(TAG, msg);
- }
- }
- }
- }
-
- /**
- * Begins a transaction. Transactions can be nested. When the outer transaction is ended all of
- * the work done in that transaction and all of the nested transactions will be committed or
- * rolled back. The changes will be rolled back if any transaction is ended without being
- * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
- *
- * <p>Here is the standard idiom for transactions:
- *
- * <pre>
- * db.beginTransaction();
- * try {
- * ...
- * db.setTransactionSuccessful();
- * } finally {
- * db.endTransaction();
- * }
- * </pre>
- */
- public void beginTransaction() {
- lockForced();
- boolean ok = false;
- try {
- // If this thread already had the lock then get out
- if (mLock.getHoldCount() > 1) {
- if (mInnerTransactionIsSuccessful) {
- String msg = "Cannot call beginTransaction between "
- + "calling setTransactionSuccessful and endTransaction";
- IllegalStateException e = new IllegalStateException(msg);
- Log.e(TAG, "beginTransaction() failed", e);
- throw e;
- }
- ok = true;
- return;
- }
-
- // This thread didn't already have the lock, so begin a database
- // transaction now.
- execSQL("BEGIN EXCLUSIVE;");
- mTransactionIsSuccessful = true;
- mInnerTransactionIsSuccessful = false;
- ok = true;
- } finally {
- if (!ok) {
- // beginTransaction is called before the try block so we must release the lock in
- // the case of failure.
- unlockForced();
- }
- }
- }
-
- /**
- * End a transaction. See beginTransaction for notes about how to use this and when transactions
- * are committed and rolled back.
- */
- public void endTransaction() {
- if (!mLock.isHeldByCurrentThread()) {
- throw new IllegalStateException("no transaction pending");
- }
- try {
- if (mInnerTransactionIsSuccessful) {
- mInnerTransactionIsSuccessful = false;
- } else {
- mTransactionIsSuccessful = false;
- }
- if (mLock.getHoldCount() != 1) {
- return;
- }
- if (mTransactionIsSuccessful) {
- execSQL("COMMIT;");
- } else {
- try {
- execSQL("ROLLBACK;");
- } catch (SQLException e) {
- if (Config.LOGD) {
- Log.d(TAG, "exception during rollback, maybe the DB previously "
- + "performed an auto-rollback");
- }
- }
- }
- } finally {
- unlockForced();
- if (Config.LOGV) {
- Log.v(TAG, "unlocked " + Thread.currentThread()
- + ", holdCount is " + mLock.getHoldCount());
- }
- }
- }
-
- /**
- * Marks the current transaction as successful. Do not do any more database work between
- * calling this and calling endTransaction. Do as little non-database work as possible in that
- * situation too. If any errors are encountered between this and endTransaction the transaction
- * will still be committed.
- *
- * @throws IllegalStateException if the current thread is not in a transaction or the
- * transaction is already marked as successful.
- */
- public void setTransactionSuccessful() {
- if (!mLock.isHeldByCurrentThread()) {
- throw new IllegalStateException("no transaction pending");
- }
- if (mInnerTransactionIsSuccessful) {
- throw new IllegalStateException(
- "setTransactionSuccessful may only be called once per call to beginTransaction");
- }
- mInnerTransactionIsSuccessful = true;
- }
-
- /**
- * return true if there is a transaction pending
- */
- public boolean inTransaction() {
- return mLock.getHoldCount() > 0;
- }
-
- /**
- * Checks if the database lock is held by this thread.
- *
- * @return true, if this thread is holding the database lock.
- */
- public boolean isDbLockedByCurrentThread() {
- return mLock.isHeldByCurrentThread();
- }
-
- /**
- * Checks if the database is locked by another thread. This is
- * just an estimate, since this status can change at any time,
- * including after the call is made but before the result has
- * been acted upon.
- *
- * @return true, if the database is locked by another thread
- */
- public boolean isDbLockedByOtherThreads() {
- return !mLock.isHeldByCurrentThread() && mLock.isLocked();
- }
-
- /**
- * Temporarily end the transaction to let other threads run. The transaction is assumed to be
- * successful so far. Do not call setTransactionSuccessful before calling this. When this
- * returns a new transaction will have been created but not marked as successful.
- * @return true if the transaction was yielded
- * @deprecated if the db is locked more than once (becuase of nested transactions) then the lock
- * will not be yielded. Use yieldIfContendedSafely instead.
- */
- public boolean yieldIfContended() {
- return yieldIfContendedHelper(false /* do not check yielding */);
- }
-
- /**
- * Temporarily end the transaction to let other threads run. The transaction is assumed to be
- * successful so far. Do not call setTransactionSuccessful before calling this. When this
- * returns a new transaction will have been created but not marked as successful. This assumes
- * that there are no nested transactions (beginTransaction has only been called once) and will
- * through an exception if that is not the case.
- * @return true if the transaction was yielded
- */
- public boolean yieldIfContendedSafely() {
- return yieldIfContendedHelper(true /* check yielding */);
- }
-
- private boolean yieldIfContendedHelper(boolean checkFullyYielded) {
- if (mLock.getQueueLength() == 0) {
- // Reset the lock acquire time since we know that the thread was willing to yield
- // the lock at this time.
- mLockAcquiredWallTime = SystemClock.elapsedRealtime();
- mLockAcquiredThreadTime = Debug.threadCpuTimeNanos();
- return false;
- }
- setTransactionSuccessful();
- endTransaction();
- if (checkFullyYielded) {
- if (this.isDbLockedByCurrentThread()) {
- throw new IllegalStateException(
- "Db locked more than once. yielfIfContended cannot yield");
- }
- }
- beginTransaction();
- return true;
- }
-
- /** Maps table names to info about what to which _sync_time column to set
- * to NULL on an update. This is used to support syncing. */
- private final Map<String, SyncUpdateInfo> mSyncUpdateInfo =
- new HashMap<String, SyncUpdateInfo>();
-
- public Map<String, String> getSyncedTables() {
- synchronized(mSyncUpdateInfo) {
- HashMap<String, String> tables = new HashMap<String, String>();
- for (String table : mSyncUpdateInfo.keySet()) {
- SyncUpdateInfo info = mSyncUpdateInfo.get(table);
- if (info.deletedTable != null) {
- tables.put(table, info.deletedTable);
- }
- }
- return tables;
- }
- }
-
- /**
- * Internal class used to keep track what needs to be marked as changed
- * when an update occurs. This is used for syncing, so the sync engine
- * knows what data has been updated locally.
- */
- static private class SyncUpdateInfo {
- /**
- * Creates the SyncUpdateInfo class.
- *
- * @param masterTable The table to set _sync_time to NULL in
- * @param deletedTable The deleted table that corresponds to the
- * master table
- * @param foreignKey The key that refers to the primary key in table
- */
- SyncUpdateInfo(String masterTable, String deletedTable,
- String foreignKey) {
- this.masterTable = masterTable;
- this.deletedTable = deletedTable;
- this.foreignKey = foreignKey;
- }
-
- /** The table containing the _sync_time column */
- String masterTable;
-
- /** The deleted table that corresponds to the master table */
- String deletedTable;
-
- /** The key in the local table the row in table. It may be _id, if table
- * is the local table. */
- String foreignKey;
- }
-
- /**
- * Used to allow returning sub-classes of {@link Cursor} when calling query.
- */
- public interface CursorFactory {
- /**
- * See
- * {@link SQLiteCursor#SQLiteCursor(SQLiteDatabase, SQLiteCursorDriver,
- * String, SQLiteQuery)}.
- */
- public Cursor newCursor(SQLiteDatabase db,
- SQLiteCursorDriver masterQuery, String editTable,
- SQLiteQuery query);
- }
-
- /**
- * Open the database according to the flags {@link #OPEN_READWRITE}
- * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
- *
- * <p>Sets the locale of the database to the the system's current locale.
- * Call {@link #setLocale} if you would like something else.</p>
- *
- * @param path to database file to open and/or create
- * @param factory an optional factory class that is called to instantiate a
- * cursor when query is called, or null for default
- * @param flags to control database access mode
- * @return the newly opened database
- * @throws SQLiteException if the database cannot be opened
- */
- public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags) {
- SQLiteDatabase db = null;
- try {
- // Open the database.
- return new SQLiteDatabase(path, factory, flags);
- } catch (SQLiteDatabaseCorruptException e) {
- // Try to recover from this, if we can.
- // TODO: should we do this for other open failures?
- Log.e(TAG, "Deleting and re-creating corrupt database " + path, e);
- new File(path).delete();
- return new SQLiteDatabase(path, factory, flags);
- }
- }
-
- /**
- * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY).
- */
- public static SQLiteDatabase openOrCreateDatabase(File file, CursorFactory factory) {
- return openOrCreateDatabase(file.getPath(), factory);
- }
-
- /**
- * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
- */
- public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory) {
- return openDatabase(path, factory, CREATE_IF_NECESSARY);
- }
-
- /**
- * Create a memory backed SQLite database. Its contents will be destroyed
- * when the database is closed.
- *
- * <p>Sets the locale of the database to the the system's current locale.
- * Call {@link #setLocale} if you would like something else.</p>
- *
- * @param factory an optional factory class that is called to instantiate a
- * cursor when query is called
- * @return a SQLiteDatabase object, or null if the database can't be created
- */
- public static SQLiteDatabase create(CursorFactory factory) {
- // This is a magic string with special meaning for SQLite.
- return openDatabase(":memory:", factory, CREATE_IF_NECESSARY);
- }
-
- /**
- * Close the database.
- */
- public void close() {
- lock();
- try {
- closeClosable();
- releaseReference();
- } finally {
- unlock();
- }
- }
-
- private void closeClosable() {
- Iterator<Map.Entry<SQLiteClosable, Object>> iter = mPrograms.entrySet().iterator();
- while (iter.hasNext()) {
- Map.Entry<SQLiteClosable, Object> entry = iter.next();
- SQLiteClosable program = entry.getKey();
- if (program != null) {
- program.onAllReferencesReleasedFromContainer();
- }
- }
- }
-
- /**
- * Native call to close the database.
- */
- private native void dbclose();
-
- /**
- * Gets the database version.
- *
- * @return the database version
- */
- public int getVersion() {
- SQLiteStatement prog = null;
- lock();
- try {
- prog = new SQLiteStatement(this, "PRAGMA user_version;");
- long version = prog.simpleQueryForLong();
- return (int) version;
- } finally {
- if (prog != null) prog.close();
- unlock();
- }
- }
-
- /**
- * Sets the database version.
- *
- * @param version the new database version
- */
- public void setVersion(int version) {
- execSQL("PRAGMA user_version = " + version);
- }
-
- /**
- * Returns the maximum size the database may grow to.
- *
- * @return the new maximum database size
- */
- public long getMaximumSize() {
- SQLiteStatement prog = null;
- lock();
- try {
- prog = new SQLiteStatement(this,
- "PRAGMA max_page_count;");
- long pageCount = prog.simpleQueryForLong();
- return pageCount * getPageSize();
- } finally {
- if (prog != null) prog.close();
- unlock();
- }
- }
-
- /**
- * Sets the maximum size the database will grow to. The maximum size cannot
- * be set below the current size.
- *
- * @param numBytes the maximum database size, in bytes
- * @return the new maximum database size
- */
- public long setMaximumSize(long numBytes) {
- SQLiteStatement prog = null;
- lock();
- try {
- long pageSize = getPageSize();
- long numPages = numBytes / pageSize;
- // If numBytes isn't a multiple of pageSize, bump up a page
- if ((numBytes % pageSize) != 0) {
- numPages++;
- }
- prog = new SQLiteStatement(this,
- "PRAGMA max_page_count = " + numPages);
- long newPageCount = prog.simpleQueryForLong();
- return newPageCount * pageSize;
- } finally {
- if (prog != null) prog.close();
- unlock();
- }
- }
-
- /**
- * Returns the maximum size the database may grow to.
- *
- * @return the new maximum database size
- */
- public long getPageSize() {
- SQLiteStatement prog = null;
- lock();
- try {
- prog = new SQLiteStatement(this,
- "PRAGMA page_size;");
- long size = prog.simpleQueryForLong();
- return size;
- } finally {
- if (prog != null) prog.close();
- unlock();
- }
- }
-
- /**
- * Sets the database page size. The page size must be a power of two. This
- * method does not work if any data has been written to the database file,
- * and must be called right after the database has been created.
- *
- * @param numBytes the database page size, in bytes
- */
- public void setPageSize(long numBytes) {
- execSQL("PRAGMA page_size = " + numBytes);
- }
-
- /**
- * Mark this table as syncable. When an update occurs in this table the
- * _sync_dirty field will be set to ensure proper syncing operation.
- *
- * @param table the table to mark as syncable
- * @param deletedTable The deleted table that corresponds to the
- * syncable table
- */
- public void markTableSyncable(String table, String deletedTable) {
- markTableSyncable(table, "_id", table, deletedTable);
- }
-
- /**
- * Mark this table as syncable, with the _sync_dirty residing in another
- * table. When an update occurs in this table the _sync_dirty field of the
- * row in updateTable with the _id in foreignKey will be set to
- * ensure proper syncing operation.
- *
- * @param table an update on this table will trigger a sync time removal
- * @param foreignKey this is the column in table whose value is an _id in
- * updateTable
- * @param updateTable this is the table that will have its _sync_dirty
- */
- public void markTableSyncable(String table, String foreignKey,
- String updateTable) {
- markTableSyncable(table, foreignKey, updateTable, null);
- }
-
- /**
- * Mark this table as syncable, with the _sync_dirty residing in another
- * table. When an update occurs in this table the _sync_dirty field of the
- * row in updateTable with the _id in foreignKey will be set to
- * ensure proper syncing operation.
- *
- * @param table an update on this table will trigger a sync time removal
- * @param foreignKey this is the column in table whose value is an _id in
- * updateTable
- * @param updateTable this is the table that will have its _sync_dirty
- * @param deletedTable The deleted table that corresponds to the
- * updateTable
- */
- private void markTableSyncable(String table, String foreignKey,
- String updateTable, String deletedTable) {
- lock();
- try {
- native_execSQL("SELECT _sync_dirty FROM " + updateTable
- + " LIMIT 0");
- native_execSQL("SELECT " + foreignKey + " FROM " + table
- + " LIMIT 0");
- } finally {
- unlock();
- }
-
- SyncUpdateInfo info = new SyncUpdateInfo(updateTable, deletedTable,
- foreignKey);
- synchronized (mSyncUpdateInfo) {
- mSyncUpdateInfo.put(table, info);
- }
- }
-
- /**
- * Call for each row that is updated in a cursor.
- *
- * @param table the table the row is in
- * @param rowId the row ID of the updated row
- */
- /* package */ void rowUpdated(String table, long rowId) {
- SyncUpdateInfo info;
- synchronized (mSyncUpdateInfo) {
- info = mSyncUpdateInfo.get(table);
- }
- if (info != null) {
- execSQL("UPDATE " + info.masterTable
- + " SET _sync_dirty=1 WHERE _id=(SELECT " + info.foreignKey
- + " FROM " + table + " WHERE _id=" + rowId + ")");
- }
- }
-
- /**
- * Finds the name of the first table, which is editable.
- *
- * @param tables a list of tables
- * @return the first table listed
- */
- public static String findEditTable(String tables) {
- if (!TextUtils.isEmpty(tables)) {
- // find the first word terminated by either a space or a comma
- int spacepos = tables.indexOf(' ');
- int commapos = tables.indexOf(',');
-
- if (spacepos > 0 && (spacepos < commapos || commapos < 0)) {
- return tables.substring(0, spacepos);
- } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) {
- return tables.substring(0, commapos);
- }
- return tables;
- } else {
- throw new IllegalStateException("Invalid tables");
- }
- }
-
- /**
- * Compiles an SQL statement into a reusable pre-compiled statement object.
- * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the
- * statement and fill in those values with {@link SQLiteProgram#bindString}
- * and {@link SQLiteProgram#bindLong} each time you want to run the
- * statement. Statements may not return result sets larger than 1x1.
- *
- * @param sql The raw SQL statement, may contain ? for unknown values to be
- * bound later.
- * @return a pre-compiled statement object.
- */
- public SQLiteStatement compileStatement(String sql) throws SQLException {
- lock();
- try {
- return new SQLiteStatement(this, sql);
- } finally {
- unlock();
- }
- }
-
- /**
- * Query the given URL, returning a {@link Cursor} over the result set.
- *
- * @param distinct true if you want each row to be unique, false otherwise.
- * @param table The table name to compile the query against.
- * @param columns A list of which columns to return. Passing null will
- * return all columns, which is discouraged to prevent reading
- * data from storage that isn't going to be used.
- * @param selection A filter declaring which rows to return, formatted as an
- * SQL WHERE clause (excluding the WHERE itself). Passing null
- * will return all rows for the given table.
- * @param selectionArgs You may include ?s in selection, which will be
- * replaced by the values from selectionArgs, in order that they
- * appear in the selection. The values will be bound as Strings.
- * @param groupBy A filter declaring how to group rows, formatted as an SQL
- * GROUP BY clause (excluding the GROUP BY itself). Passing null
- * will cause the rows to not be grouped.
- * @param having A filter declare which row groups to include in the cursor,
- * if row grouping is being used, formatted as an SQL HAVING
- * clause (excluding the HAVING itself). Passing null will cause
- * all row groups to be included, and is required when row
- * grouping is not being used.
- * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
- * (excluding the ORDER BY itself). Passing null will use the
- * default sort order, which may be unordered.
- * @param limit Limits the number of rows returned by the query,
- * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
- * @return A Cursor object, which is positioned before the first entry
- * @see Cursor
- */
- public Cursor query(boolean distinct, String table, String[] columns,
- String selection, String[] selectionArgs, String groupBy,
- String having, String orderBy, String limit) {
- return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
- groupBy, having, orderBy, limit);
- }
-
- /**
- * Query the given URL, returning a {@link Cursor} over the result set.
- *
- * @param cursorFactory the cursor factory to use, or null for the default factory
- * @param distinct true if you want each row to be unique, false otherwise.
- * @param table The table name to compile the query against.
- * @param columns A list of which columns to return. Passing null will
- * return all columns, which is discouraged to prevent reading
- * data from storage that isn't going to be used.
- * @param selection A filter declaring which rows to return, formatted as an
- * SQL WHERE clause (excluding the WHERE itself). Passing null
- * will return all rows for the given table.
- * @param selectionArgs You may include ?s in selection, which will be
- * replaced by the values from selectionArgs, in order that they
- * appear in the selection. The values will be bound as Strings.
- * @param groupBy A filter declaring how to group rows, formatted as an SQL
- * GROUP BY clause (excluding the GROUP BY itself). Passing null
- * will cause the rows to not be grouped.
- * @param having A filter declare which row groups to include in the cursor,
- * if row grouping is being used, formatted as an SQL HAVING
- * clause (excluding the HAVING itself). Passing null will cause
- * all row groups to be included, and is required when row
- * grouping is not being used.
- * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
- * (excluding the ORDER BY itself). Passing null will use the
- * default sort order, which may be unordered.
- * @param limit Limits the number of rows returned by the query,
- * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
- * @return A Cursor object, which is positioned before the first entry
- * @see Cursor
- */
- public Cursor queryWithFactory(CursorFactory cursorFactory,
- boolean distinct, String table, String[] columns,
- String selection, String[] selectionArgs, String groupBy,
- String having, String orderBy, String limit) {
- String sql = SQLiteQueryBuilder.buildQueryString(
- distinct, table, columns, selection, groupBy, having, orderBy, limit);
-
- return rawQueryWithFactory(
- cursorFactory, sql, selectionArgs, findEditTable(table));
- }
-
- /**
- * Query the given table, returning a {@link Cursor} over the result set.
- *
- * @param table The table name to compile the query against.
- * @param columns A list of which columns to return. Passing null will
- * return all columns, which is discouraged to prevent reading
- * data from storage that isn't going to be used.
- * @param selection A filter declaring which rows to return, formatted as an
- * SQL WHERE clause (excluding the WHERE itself). Passing null
- * will return all rows for the given table.
- * @param selectionArgs You may include ?s in selection, which will be
- * replaced by the values from selectionArgs, in order that they
- * appear in the selection. The values will be bound as Strings.
- * @param groupBy A filter declaring how to group rows, formatted as an SQL
- * GROUP BY clause (excluding the GROUP BY itself). Passing null
- * will cause the rows to not be grouped.
- * @param having A filter declare which row groups to include in the cursor,
- * if row grouping is being used, formatted as an SQL HAVING
- * clause (excluding the HAVING itself). Passing null will cause
- * all row groups to be included, and is required when row
- * grouping is not being used.
- * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
- * (excluding the ORDER BY itself). Passing null will use the
- * default sort order, which may be unordered.
- * @return A {@link Cursor} object, which is positioned before the first entry
- * @see Cursor
- */
- public Cursor query(String table, String[] columns, String selection,
- String[] selectionArgs, String groupBy, String having,
- String orderBy) {
-
- return query(false, table, columns, selection, selectionArgs, groupBy,
- having, orderBy, null /* limit */);
- }
-
- /**
- * Query the given table, returning a {@link Cursor} over the result set.
- *
- * @param table The table name to compile the query against.
- * @param columns A list of which columns to return. Passing null will
- * return all columns, which is discouraged to prevent reading
- * data from storage that isn't going to be used.
- * @param selection A filter declaring which rows to return, formatted as an
- * SQL WHERE clause (excluding the WHERE itself). Passing null
- * will return all rows for the given table.
- * @param selectionArgs You may include ?s in selection, which will be
- * replaced by the values from selectionArgs, in order that they
- * appear in the selection. The values will be bound as Strings.
- * @param groupBy A filter declaring how to group rows, formatted as an SQL
- * GROUP BY clause (excluding the GROUP BY itself). Passing null
- * will cause the rows to not be grouped.
- * @param having A filter declare which row groups to include in the cursor,
- * if row grouping is being used, formatted as an SQL HAVING
- * clause (excluding the HAVING itself). Passing null will cause
- * all row groups to be included, and is required when row
- * grouping is not being used.
- * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
- * (excluding the ORDER BY itself). Passing null will use the
- * default sort order, which may be unordered.
- * @param limit Limits the number of rows returned by the query,
- * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
- * @return A {@link Cursor} object, which is positioned before the first entry
- * @see Cursor
- */
- public Cursor query(String table, String[] columns, String selection,
- String[] selectionArgs, String groupBy, String having,
- String orderBy, String limit) {
-
- return query(false, table, columns, selection, selectionArgs, groupBy,
- having, orderBy, limit);
- }
-
- /**
- * Runs the provided SQL and returns a {@link Cursor} over the result set.
- *
- * @param sql the SQL query. The SQL string must not be ; terminated
- * @param selectionArgs You may include ?s in where clause in the query,
- * which will be replaced by the values from selectionArgs. The
- * values will be bound as Strings.
- * @return A {@link Cursor} object, which is positioned before the first entry
- */
- public Cursor rawQuery(String sql, String[] selectionArgs) {
- return rawQueryWithFactory(null, sql, selectionArgs, null);
- }
-
- /**
- * Runs the provided SQL and returns a cursor over the result set.
- *
- * @param cursorFactory the cursor factory to use, or null for the default factory
- * @param sql the SQL query. The SQL string must not be ; terminated
- * @param selectionArgs You may include ?s in where clause in the query,
- * which will be replaced by the values from selectionArgs. The
- * values will be bound as Strings.
- * @param editTable the name of the first table, which is editable
- * @return A {@link Cursor} object, which is positioned before the first entry
- */
- public Cursor rawQueryWithFactory(
- CursorFactory cursorFactory, String sql, String[] selectionArgs,
- String editTable) {
- long timeStart = 0;
-
- if (Config.LOGV) {
- timeStart = System.currentTimeMillis();
- }
-
- SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable);
-
- try {
- return driver.query(
- cursorFactory != null ? cursorFactory : mFactory,
- selectionArgs);
- } finally {
- if (Config.LOGV) {
- long duration = System.currentTimeMillis() - timeStart;
-
- Log.v(SQLiteCursor.TAG,
- "query (" + duration + " ms): " + driver.toString() + ", args are "
- + (selectionArgs != null
- ? TextUtils.join(",", selectionArgs)
- : "<null>"));
- }
- }
- }
-
- /**
- * Runs the provided SQL and returns a cursor over the result set.
- * The cursor will read an initial set of rows and the return to the caller.
- * It will continue to read in batches and send data changed notifications
- * when the later batches are ready.
- * @param sql the SQL query. The SQL string must not be ; terminated
- * @param selectionArgs You may include ?s in where clause in the query,
- * which will be replaced by the values from selectionArgs. The
- * values will be bound as Strings.
- * @param initialRead set the initial count of items to read from the cursor
- * @param maxRead set the count of items to read on each iteration after the first
- * @return A {@link Cursor} object, which is positioned before the first entry
- * @hide pending API council approval
- */
- public Cursor rawQuery(String sql, String[] selectionArgs,
- int initialRead, int maxRead) {
- SQLiteCursor c = (SQLiteCursor)rawQueryWithFactory(
- null, sql, selectionArgs, null);
- c.setLoadStyle(initialRead, maxRead);
- return c;
- }
-
- /**
- * Convenience method for inserting a row into the database.
- *
- * @param table the table to insert the row into
- * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
- * so if initialValues is empty this column will explicitly be
- * assigned a NULL value
- * @param values this map contains the initial column values for the
- * row. The keys should be the column names and the values the
- * column values
- * @return the row ID of the newly inserted row, or -1 if an error occurred
- */
- public long insert(String table, String nullColumnHack, ContentValues values) {
- try {
- return insertWithOnConflict(table, nullColumnHack, values, null);
- } catch (SQLException e) {
- Log.e(TAG, "Error inserting " + values, e);
- return -1;
- }
- }
-
- /**
- * Convenience method for inserting a row into the database.
- *
- * @param table the table to insert the row into
- * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
- * so if initialValues is empty this column will explicitly be
- * assigned a NULL value
- * @param values this map contains the initial column values for the
- * row. The keys should be the column names and the values the
- * column values
- * @throws SQLException
- * @return the row ID of the newly inserted row, or -1 if an error occurred
- */
- public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
- throws SQLException {
- return insertWithOnConflict(table, nullColumnHack, values, null);
- }
-
- /**
- * Convenience method for replacing a row in the database.
- *
- * @param table the table in which to replace the row
- * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
- * so if initialValues is empty this row will explicitly be
- * assigned a NULL value
- * @param initialValues this map contains the initial column values for
- * the row. The key
- * @return the row ID of the newly inserted row, or -1 if an error occurred
- */
- public long replace(String table, String nullColumnHack, ContentValues initialValues) {
- try {
- return insertWithOnConflict(table, nullColumnHack, initialValues,
- ConflictAlgorithm.REPLACE);
- } catch (SQLException e) {
- Log.e(TAG, "Error inserting " + initialValues, e);
- return -1;
- }
- }
-
- /**
- * Convenience method for replacing a row in the database.
- *
- * @param table the table in which to replace the row
- * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
- * so if initialValues is empty this row will explicitly be
- * assigned a NULL value
- * @param initialValues this map contains the initial column values for
- * the row. The key
- * @throws SQLException
- * @return the row ID of the newly inserted row, or -1 if an error occurred
- */
- public long replaceOrThrow(String table, String nullColumnHack,
- ContentValues initialValues) throws SQLException {
- return insertWithOnConflict(table, nullColumnHack, initialValues,
- ConflictAlgorithm.REPLACE);
- }
-
- /**
- * General method for inserting a row into the database.
- *
- * @param table the table to insert the row into
- * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
- * so if initialValues is empty this column will explicitly be
- * assigned a NULL value
- * @param initialValues this map contains the initial column values for the
- * row. The keys should be the column names and the values the
- * column values
- * @param algorithm {@link ConflictAlgorithm} for insert conflict resolver
- * @return the row ID of the newly inserted row, or -1 if an error occurred
- * @hide
- */
- public long insertWithOnConflict(String table, String nullColumnHack,
- ContentValues initialValues, ConflictAlgorithm algorithm) {
- if (!isOpen()) {
- throw new IllegalStateException("database not open");
- }
-
- // Measurements show most sql lengths <= 152
- StringBuilder sql = new StringBuilder(152);
- sql.append("INSERT");
- if (algorithm != null) {
- sql.append(" OR ");
- sql.append(algorithm.value());
- }
- sql.append(" INTO ");
- sql.append(table);
- // Measurements show most values lengths < 40
- StringBuilder values = new StringBuilder(40);
-
- Set<Map.Entry<String, Object>> entrySet = null;
- if (initialValues != null && initialValues.size() > 0) {
- entrySet = initialValues.valueSet();
- Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator();
- sql.append('(');
-
- boolean needSeparator = false;
- while (entriesIter.hasNext()) {
- if (needSeparator) {
- sql.append(", ");
- values.append(", ");
- }
- needSeparator = true;
- Map.Entry<String, Object> entry = entriesIter.next();
- sql.append(entry.getKey());
- values.append('?');
- }
-
- sql.append(')');
- } else {
- sql.append("(" + nullColumnHack + ") ");
- values.append("NULL");
- }
-
- sql.append(" VALUES(");
- sql.append(values);
- sql.append(");");
-
- lock();
- SQLiteStatement statement = null;
- try {
- statement = compileStatement(sql.toString());
-
- // Bind the values
- if (entrySet != null) {
- int size = entrySet.size();
- Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator();
- for (int i = 0; i < size; i++) {
- Map.Entry<String, Object> entry = entriesIter.next();
- DatabaseUtils.bindObjectToProgram(statement, i + 1, entry.getValue());
- }
- }
-
- // Run the program and then cleanup
- statement.execute();
-
- long insertedRowId = lastInsertRow();
- if (insertedRowId == -1) {
- Log.e(TAG, "Error inserting " + initialValues + " using " + sql);
- } else {
- if (Config.LOGD && Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Inserting row " + insertedRowId + " from "
- + initialValues + " using " + sql);
- }
- }
- return insertedRowId;
- } catch (SQLiteDatabaseCorruptException e) {
- onCorruption();
- throw e;
- } finally {
- if (statement != null) {
- statement.close();
- }
- unlock();
- }
- }
-
- /**
- * Convenience method for deleting rows in the database.
- *
- * @param table the table to delete from
- * @param whereClause the optional WHERE clause to apply when deleting.
- * Passing null will delete all rows.
- * @return the number of rows affected if a whereClause is passed in, 0
- * otherwise. To remove all rows and get a count pass "1" as the
- * whereClause.
- */
- public int delete(String table, String whereClause, String[] whereArgs) {
- if (!isOpen()) {
- throw new IllegalStateException("database not open");
- }
- lock();
- SQLiteStatement statement = null;
- try {
- statement = compileStatement("DELETE FROM " + table
- + (!TextUtils.isEmpty(whereClause)
- ? " WHERE " + whereClause : ""));
- if (whereArgs != null) {
- int numArgs = whereArgs.length;
- for (int i = 0; i < numArgs; i++) {
- DatabaseUtils.bindObjectToProgram(statement, i + 1, whereArgs[i]);
- }
- }
- statement.execute();
- statement.close();
- return lastChangeCount();
- } catch (SQLiteDatabaseCorruptException e) {
- onCorruption();
- throw e;
- } finally {
- if (statement != null) {
- statement.close();
- }
- unlock();
- }
- }
-
- /**
- * Convenience method for updating rows in the database.
- *
- * @param table the table to update in
- * @param values a map from column names to new column values. null is a
- * valid value that will be translated to NULL.
- * @param whereClause the optional WHERE clause to apply when updating.
- * Passing null will update all rows.
- * @return the number of rows affected
- */
- public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
- return updateWithOnConflict(table, values, whereClause, whereArgs, null);
- }
-
- /**
- * Convenience method for updating rows in the database.
- *
- * @param table the table to update in
- * @param values a map from column names to new column values. null is a
- * valid value that will be translated to NULL.
- * @param whereClause the optional WHERE clause to apply when updating.
- * Passing null will update all rows.
- * @param algorithm {@link ConflictAlgorithm} for update conflict resolver
- * @return the number of rows affected
- * @hide
- */
- public int updateWithOnConflict(String table, ContentValues values,
- String whereClause, String[] whereArgs, ConflictAlgorithm algorithm) {
- if (!isOpen()) {
- throw new IllegalStateException("database not open");
- }
-
- if (values == null || values.size() == 0) {
- throw new IllegalArgumentException("Empty values");
- }
-
- StringBuilder sql = new StringBuilder(120);
- sql.append("UPDATE ");
- if (algorithm != null) {
- sql.append(" OR ");
- sql.append(algorithm.value());
- }
-
- sql.append(table);
- sql.append(" SET ");
-
- Set<Map.Entry<String, Object>> entrySet = values.valueSet();
- Iterator<Map.Entry<String, Object>> entriesIter = entrySet.iterator();
-
- while (entriesIter.hasNext()) {
- Map.Entry<String, Object> entry = entriesIter.next();
- sql.append(entry.getKey());
- sql.append("=?");
- if (entriesIter.hasNext()) {
- sql.append(", ");
- }
- }
-
- if (!TextUtils.isEmpty(whereClause)) {
- sql.append(" WHERE ");
- sql.append(whereClause);
- }
-
- lock();
- SQLiteStatement statement = null;
- try {
- statement = compileStatement(sql.toString());
-
- // Bind the values
- int size = entrySet.size();
- entriesIter = entrySet.iterator();
- int bindArg = 1;
- for (int i = 0; i < size; i++) {
- Map.Entry<String, Object> entry = entriesIter.next();
- DatabaseUtils.bindObjectToProgram(statement, bindArg, entry.getValue());
- bindArg++;
- }
-
- if (whereArgs != null) {
- size = whereArgs.length;
- for (int i = 0; i < size; i++) {
- statement.bindString(bindArg, whereArgs[i]);
- bindArg++;
- }
- }
-
- // Run the program and then cleanup
- statement.execute();
- statement.close();
- int numChangedRows = lastChangeCount();
- if (Config.LOGD && Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Updated " + numChangedRows + " using " + values + " and " + sql);
- }
- return numChangedRows;
- } catch (SQLiteDatabaseCorruptException e) {
- onCorruption();
- throw e;
- } catch (SQLException e) {
- Log.e(TAG, "Error updating " + values + " using " + sql);
- throw e;
- } finally {
- if (statement != null) {
- statement.close();
- }
- unlock();
- }
- }
-
- /**
- * Execute a single SQL statement that is not a query. For example, CREATE
- * TABLE, DELETE, INSERT, etc. Multiple statements separated by ;s are not
- * supported. it takes a write lock
- *
- * @throws SQLException If the SQL string is invalid for some reason
- */
- public void execSQL(String sql) throws SQLException {
- boolean logStats = mLogStats;
- long timeStart = logStats ? SystemClock.elapsedRealtime() : 0;
- lock();
- try {
- native_execSQL(sql);
- } catch (SQLiteDatabaseCorruptException e) {
- onCorruption();
- throw e;
- } finally {
- unlock();
- }
- if (logStats) {
- logTimeStat(false /* not a read */, timeStart, SystemClock.elapsedRealtime());
- }
- }
-
- /**
- * Execute a single SQL statement that is not a query. For example, CREATE
- * TABLE, DELETE, INSERT, etc. Multiple statements separated by ;s are not
- * supported. it takes a write lock,
- *
- * @param sql
- * @param bindArgs only byte[], String, Long and Double are supported in bindArgs.
- * @throws SQLException If the SQL string is invalid for some reason
- */
- public void execSQL(String sql, Object[] bindArgs) throws SQLException {
- if (bindArgs == null) {
- throw new IllegalArgumentException("Empty bindArgs");
- }
-
- boolean logStats = mLogStats;
- long timeStart = logStats ? SystemClock.elapsedRealtime() : 0;
- lock();
- SQLiteStatement statement = null;
- try {
- statement = compileStatement(sql);
- if (bindArgs != null) {
- int numArgs = bindArgs.length;
- for (int i = 0; i < numArgs; i++) {
- DatabaseUtils.bindObjectToProgram(statement, i + 1, bindArgs[i]);
- }
- }
- statement.execute();
- } catch (SQLiteDatabaseCorruptException e) {
- onCorruption();
- throw e;
- } finally {
- if (statement != null) {
- statement.close();
- }
- unlock();
- }
- if (logStats) {
- logTimeStat(false /* not a read */, timeStart, SystemClock.elapsedRealtime());
- }
- }
-
- @Override
- protected void finalize() {
- if (isOpen()) {
- if (mPrograms.isEmpty()) {
- Log.e(TAG, "Leak found", mLeakedException);
- } else {
- IllegalStateException leakProgram = new IllegalStateException(
- "mPrograms size " + mPrograms.size(), mLeakedException);
- Log.e(TAG, "Leak found", leakProgram);
- }
- closeClosable();
- onAllReferencesReleased();
- }
- }
-
- /**
- * Private constructor. See {@link #create} and {@link #openDatabase}.
- *
- * @param path The full path to the database
- * @param factory The factory to use when creating cursors, may be NULL.
- * @param flags 0 or {@link #NO_LOCALIZED_COLLATORS}. If the database file already
- * exists, mFlags will be updated appropriately.
- */
- private SQLiteDatabase(String path, CursorFactory factory, int flags) {
- if (path == null) {
- throw new IllegalArgumentException("path should not be null");
- }
- mFlags = flags;
- mPath = path;
- mLogStats = "1".equals(android.os.SystemProperties.get("db.logstats"));
-
- mLeakedException = new IllegalStateException(path +
- " SQLiteDatabase created and never closed");
- mFactory = factory;
- dbopen(mPath, mFlags);
- mPrograms = new WeakHashMap<SQLiteClosable,Object>();
- try {
- setLocale(Locale.getDefault());
- } catch (RuntimeException e) {
- Log.e(TAG, "Failed to setLocale() when constructing, closing the database", e);
- dbclose();
- throw e;
- }
- }
-
- /**
- * return whether the DB is opened as read only.
- * @return true if DB is opened as read only
- */
- public boolean isReadOnly() {
- return (mFlags & OPEN_READ_MASK) == OPEN_READONLY;
- }
-
- /**
- * @return true if the DB is currently open (has not been closed)
- */
- public boolean isOpen() {
- return mNativeHandle != 0;
- }
-
- public boolean needUpgrade(int newVersion) {
- return newVersion > getVersion();
- }
-
- /**
- * Getter for the path to the database file.
- *
- * @return the path to our database file.
- */
- public final String getPath() {
- return mPath;
- }
-
- /* package */ void logTimeStat(boolean read, long begin, long end) {
- EventLog.writeEvent(DB_OPERATION_EVENT, mPath, read ? 0 : 1, end - begin);
- }
-
- /**
- * Sets the locale for this database. Does nothing if this database has
- * the NO_LOCALIZED_COLLATORS flag set or was opened read only.
- * @throws SQLException if the locale could not be set. The most common reason
- * for this is that there is no collator available for the locale you requested.
- * In this case the database remains unchanged.
- */
- public void setLocale(Locale locale) {
- lock();
- try {
- native_setLocale(locale.toString(), mFlags);
- } finally {
- unlock();
- }
- }
-
- /**
- * Native call to open the database.
- *
- * @param path The full path to the database
- */
- private native void dbopen(String path, int flags);
-
- /**
- * Native call to execute a raw SQL statement. {@link #lock} must be held
- * when calling this method.
- *
- * @param sql The raw SQL string
- * @throws SQLException
- */
- /* package */ native void native_execSQL(String sql) throws SQLException;
-
- /**
- * Native call to set the locale. {@link #lock} must be held when calling
- * this method.
- * @throws SQLException
- */
- /* package */ native void native_setLocale(String loc, int flags);
-
- /**
- * Returns the row ID of the last row inserted into the database.
- *
- * @return the row ID of the last row inserted into the database.
- */
- /* package */ native long lastInsertRow();
-
- /**
- * Returns the number of changes made in the last statement executed.
- *
- * @return the number of changes made in the last statement executed.
- */
- /* package */ native int lastChangeCount();
-}
diff --git a/core/java/android/database/sqlite/SQLiteDatabaseCorruptException.java b/core/java/android/database/sqlite/SQLiteDatabaseCorruptException.java
deleted file mode 100644
index 73b6c0c..0000000
--- a/core/java/android/database/sqlite/SQLiteDatabaseCorruptException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-/**
- * An exception that indicates that the SQLite database file is corrupt.
- */
-public class SQLiteDatabaseCorruptException extends SQLiteException {
- public SQLiteDatabaseCorruptException() {}
-
- public SQLiteDatabaseCorruptException(String error) {
- super(error);
- }
-}
diff --git a/core/java/android/database/sqlite/SQLiteDebug.java b/core/java/android/database/sqlite/SQLiteDebug.java
deleted file mode 100644
index d04afb0..0000000
--- a/core/java/android/database/sqlite/SQLiteDebug.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-import android.util.Config;
-
-/**
- * Provides debugging info about all SQLite databases running in the current process.
- *
- * {@hide}
- */
-public final class SQLiteDebug {
- /**
- * Controls the printing of SQL statements as they are executed.
- */
- public static final boolean DEBUG_SQL_STATEMENTS = Config.LOGV;
-
- /**
- * Controls the stack trace reporting of active cursors being
- * finalized.
- */
- public static final boolean DEBUG_ACTIVE_CURSOR_FINALIZATION = Config.LOGV;
-
- /**
- * Controls the tracking of time spent holding the database lock.
- */
- public static final boolean DEBUG_LOCK_TIME_TRACKING = false;
-
- /**
- * Controls the printing of stack traces when tracking the time spent holding the database lock.
- */
- public static final boolean DEBUG_LOCK_TIME_TRACKING_STACK_TRACE = false;
-
- /**
- * Contains statistics about the active pagers in the current process.
- *
- * @see #getPagerStats(PagerStats)
- */
- public static class PagerStats {
- /** The total number of bytes in all pagers in the current process */
- public long totalBytes;
- /** The number of bytes in referenced pages in all pagers in the current process */
- public long referencedBytes;
- /** The number of bytes in all database files opened in the current process */
- public long databaseBytes;
- /** The number of pagers opened in the current process */
- public int numPagers;
- }
-
- /**
- * Gathers statistics about all pagers in the current process.
- */
- public static native void getPagerStats(PagerStats stats);
-
- /**
- * Returns the size of the SQLite heap.
- * @return The size of the SQLite heap in bytes.
- */
- public static native long getHeapSize();
-
- /**
- * Returns the amount of allocated memory in the SQLite heap.
- * @return The allocated size in bytes.
- */
- public static native long getHeapAllocatedSize();
-
- /**
- * Returns the amount of free memory in the SQLite heap.
- * @return The freed size in bytes.
- */
- public static native long getHeapFreeSize();
-
- /**
- * Determines the number of dirty belonging to the SQLite
- * heap segments of this process. pages[0] returns the number of
- * shared pages, pages[1] returns the number of private pages
- */
- public static native void getHeapDirtyPages(int[] pages);
-
- private static int sNumActiveCursorsFinalized = 0;
-
- /**
- * Returns the number of active cursors that have been finalized. This depends on the GC having
- * run but is still useful for tests.
- */
- public static int getNumActiveCursorsFinalized() {
- return sNumActiveCursorsFinalized;
- }
-
- static synchronized void notifyActiveCursorFinalized() {
- sNumActiveCursorsFinalized++;
- }
-}
diff --git a/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java b/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java
deleted file mode 100644
index ca64aca..0000000
--- a/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase.CursorFactory;
-import android.util.Log;
-
-/**
- * A cursor driver that uses the given query directly.
- *
- * @hide
- */
-public class SQLiteDirectCursorDriver implements SQLiteCursorDriver {
- private static String TAG = "SQLiteDirectCursorDriver";
- private String mEditTable;
- private SQLiteDatabase mDatabase;
- private Cursor mCursor;
- private String mSql;
- private SQLiteQuery mQuery;
-
- public SQLiteDirectCursorDriver(SQLiteDatabase db, String sql, String editTable) {
- mDatabase = db;
- mEditTable = editTable;
- //TODO remove all callers that end in ; and remove this check
- if (sql.charAt(sql.length() - 1) == ';') {
- Log.w(TAG, "Found SQL string that ends in ; -- " + sql);
- sql = sql.substring(0, sql.length() - 1);
- }
- mSql = sql;
- }
-
- public Cursor query(CursorFactory factory, String[] selectionArgs) {
- // Compile the query
- SQLiteQuery query = new SQLiteQuery(mDatabase, mSql, 0, selectionArgs);
-
- try {
- // Arg binding
- int numArgs = selectionArgs == null ? 0 : selectionArgs.length;
- for (int i = 0; i < numArgs; i++) {
- query.bindString(i + 1, selectionArgs[i]);
- }
-
- // Create the cursor
- if (factory == null) {
- mCursor = new SQLiteCursor(mDatabase, this, mEditTable, query);
- } else {
- mCursor = factory.newCursor(mDatabase, this, mEditTable, query);
- }
-
- mQuery = query;
- query = null;
- return mCursor;
- } finally {
- // Make sure this object is cleaned up if something happens
- if (query != null) query.close();
- }
- }
-
- public void cursorClosed() {
- mCursor = null;
- }
-
- public void setBindArguments(String[] bindArgs) {
- final int numArgs = bindArgs.length;
- for (int i = 0; i < numArgs; i++) {
- mQuery.bindString(i + 1, bindArgs[i]);
- }
- }
-
- public void cursorDeactivated() {
- // Do nothing
- }
-
- public void cursorRequeried(Cursor cursor) {
- // Do nothing
- }
-
- @Override
- public String toString() {
- return "SQLiteDirectCursorDriver: " + mSql;
- }
-}
diff --git a/core/java/android/database/sqlite/SQLiteDiskIOException.java b/core/java/android/database/sqlite/SQLiteDiskIOException.java
deleted file mode 100644
index 01b2069..0000000
--- a/core/java/android/database/sqlite/SQLiteDiskIOException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-/**
- * An exception that indicates that an IO error occured while accessing the
- * SQLite database file.
- */
-public class SQLiteDiskIOException extends SQLiteException {
- public SQLiteDiskIOException() {}
-
- public SQLiteDiskIOException(String error) {
- super(error);
- }
-}
diff --git a/core/java/android/database/sqlite/SQLiteDoneException.java b/core/java/android/database/sqlite/SQLiteDoneException.java
deleted file mode 100644
index d6d3f66..0000000
--- a/core/java/android/database/sqlite/SQLiteDoneException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-/**
- * An exception that indicates that the SQLite program is done.
- * Thrown when an operation that expects a row (such as {@link
- * SQLiteStatement#simpleQueryForString} or {@link
- * SQLiteStatement#simpleQueryForLong}) does not get one.
- */
-public class SQLiteDoneException extends SQLiteException {
- public SQLiteDoneException() {}
-
- public SQLiteDoneException(String error) {
- super(error);
- }
-}
diff --git a/core/java/android/database/sqlite/SQLiteException.java b/core/java/android/database/sqlite/SQLiteException.java
deleted file mode 100644
index 3a97bfb..0000000
--- a/core/java/android/database/sqlite/SQLiteException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-import android.database.SQLException;
-
-/**
- * A SQLite exception that indicates there was an error with SQL parsing or execution.
- */
-public class SQLiteException extends SQLException {
- public SQLiteException() {}
-
- public SQLiteException(String error) {
- super(error);
- }
-}
diff --git a/core/java/android/database/sqlite/SQLiteFullException.java b/core/java/android/database/sqlite/SQLiteFullException.java
deleted file mode 100644
index 582d930..0000000
--- a/core/java/android/database/sqlite/SQLiteFullException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-/**
- * An exception that indicates that the SQLite database is full.
- */
-public class SQLiteFullException extends SQLiteException {
- public SQLiteFullException() {}
-
- public SQLiteFullException(String error) {
- super(error);
- }
-}
diff --git a/core/java/android/database/sqlite/SQLiteMisuseException.java b/core/java/android/database/sqlite/SQLiteMisuseException.java
deleted file mode 100644
index 685f3ea..0000000
--- a/core/java/android/database/sqlite/SQLiteMisuseException.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-public class SQLiteMisuseException extends SQLiteException {
- public SQLiteMisuseException() {}
-
- public SQLiteMisuseException(String error) {
- super(error);
- }
-}
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
deleted file mode 100644
index 52aac3a..0000000
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-import android.content.Context;
-import android.database.sqlite.SQLiteDatabase.CursorFactory;
-import android.util.Log;
-
-/**
- * A helper class to manage database creation and version management.
- * You create a subclass implementing {@link #onCreate}, {@link #onUpgrade} and
- * optionally {@link #onOpen}, and this class takes care of opening the database
- * if it exists, creating it if it does not, and upgrading it as necessary.
- * Transactions are used to make sure the database is always in a sensible state.
- * <p>For an example, see the NotePadProvider class in the NotePad sample application,
- * in the <em>samples/</em> directory of the SDK.</p>
- */
-public abstract class SQLiteOpenHelper {
- private static final String TAG = SQLiteOpenHelper.class.getSimpleName();
-
- private final Context mContext;
- private final String mName;
- private final CursorFactory mFactory;
- private final int mNewVersion;
-
- private SQLiteDatabase mDatabase = null;
- private boolean mIsInitializing = false;
-
- /**
- * Create a helper object to create, open, and/or manage a database.
- * The database is not actually created or opened until one of
- * {@link #getWritableDatabase} or {@link #getReadableDatabase} is called.
- *
- * @param context to use to open or create the database
- * @param name of the database file, or null for an in-memory database
- * @param factory to use for creating cursor objects, or null for the default
- * @param version number of the database (starting at 1); if the database is older,
- * {@link #onUpgrade} will be used to upgrade the database
- */
- public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {
- if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);
-
- mContext = context;
- mName = name;
- mFactory = factory;
- mNewVersion = version;
- }
-
- /**
- * Create and/or open a database that will be used for reading and writing.
- * Once opened successfully, the database is cached, so you can call this
- * method every time you need to write to the database. Make sure to call
- * {@link #close} when you no longer need it.
- *
- * <p>Errors such as bad permissions or a full disk may cause this operation
- * to fail, but future attempts may succeed if the problem is fixed.</p>
- *
- * @throws SQLiteException if the database cannot be opened for writing
- * @return a read/write database object valid until {@link #close} is called
- */
- public synchronized SQLiteDatabase getWritableDatabase() {
- if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {
- return mDatabase; // The database is already open for business
- }
-
- if (mIsInitializing) {
- throw new IllegalStateException("getWritableDatabase called recursively");
- }
-
- // If we have a read-only database open, someone could be using it
- // (though they shouldn't), which would cause a lock to be held on
- // the file, and our attempts to open the database read-write would
- // fail waiting for the file lock. To prevent that, we acquire the
- // lock on the read-only database, which shuts out other users.
-
- boolean success = false;
- SQLiteDatabase db = null;
- if (mDatabase != null) mDatabase.lock();
- try {
- mIsInitializing = true;
- if (mName == null) {
- db = SQLiteDatabase.create(null);
- } else {
- db = mContext.openOrCreateDatabase(mName, 0, mFactory);
- }
-
- int version = db.getVersion();
- if (version != mNewVersion) {
- db.beginTransaction();
- try {
- if (version == 0) {
- onCreate(db);
- } else {
- onUpgrade(db, version, mNewVersion);
- }
- db.setVersion(mNewVersion);
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- }
- }
-
- onOpen(db);
- success = true;
- return db;
- } finally {
- mIsInitializing = false;
- if (success) {
- if (mDatabase != null) {
- try { mDatabase.close(); } catch (Exception e) { }
- mDatabase.unlock();
- }
- mDatabase = db;
- } else {
- if (mDatabase != null) mDatabase.unlock();
- if (db != null) db.close();
- }
- }
- }
-
- /**
- * Create and/or open a database. This will be the same object returned by
- * {@link #getWritableDatabase} unless some problem, such as a full disk,
- * requires the database to be opened read-only. In that case, a read-only
- * database object will be returned. If the problem is fixed, a future call
- * to {@link #getWritableDatabase} may succeed, in which case the read-only
- * database object will be closed and the read/write object will be returned
- * in the future.
- *
- * @throws SQLiteException if the database cannot be opened
- * @return a database object valid until {@link #getWritableDatabase}
- * or {@link #close} is called.
- */
- public synchronized SQLiteDatabase getReadableDatabase() {
- if (mDatabase != null && mDatabase.isOpen()) {
- return mDatabase; // The database is already open for business
- }
-
- if (mIsInitializing) {
- throw new IllegalStateException("getReadableDatabase called recursively");
- }
-
- try {
- return getWritableDatabase();
- } catch (SQLiteException e) {
- if (mName == null) throw e; // Can't open a temp database read-only!
- Log.e(TAG, "Couldn't open " + mName + " for writing (will try read-only):", e);
- }
-
- SQLiteDatabase db = null;
- try {
- mIsInitializing = true;
- String path = mContext.getDatabasePath(mName).getPath();
- db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY);
- if (db.getVersion() != mNewVersion) {
- throw new SQLiteException("Can't upgrade read-only database from version " +
- db.getVersion() + " to " + mNewVersion + ": " + path);
- }
-
- onOpen(db);
- Log.w(TAG, "Opened " + mName + " in read-only mode");
- mDatabase = db;
- return mDatabase;
- } finally {
- mIsInitializing = false;
- if (db != null && db != mDatabase) db.close();
- }
- }
-
- /**
- * Close any open database object.
- */
- public synchronized void close() {
- if (mIsInitializing) throw new IllegalStateException("Closed during initialization");
-
- if (mDatabase != null && mDatabase.isOpen()) {
- mDatabase.close();
- mDatabase = null;
- }
- }
-
- /**
- * Called when the database is created for the first time. This is where the
- * creation of tables and the initial population of the tables should happen.
- *
- * @param db The database.
- */
- public abstract void onCreate(SQLiteDatabase db);
-
- /**
- * Called when the database needs to be upgraded. The implementation
- * should use this method to drop tables, add tables, or do anything else it
- * needs to upgrade to the new schema version.
- *
- * <p>The SQLite ALTER TABLE documentation can be found
- * <a href="http://sqlite.org/lang_altertable.html">here</a>. If you add new columns
- * you can use ALTER TABLE to insert them into a live table. If you rename or remove columns
- * you can use ALTER TABLE to rename the old table, then create the new table and then
- * populate the new table with the contents of the old table.
- *
- * @param db The database.
- * @param oldVersion The old database version.
- * @param newVersion The new database version.
- */
- public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);
-
- /**
- * Called when the database has been opened.
- * Override method should check {@link SQLiteDatabase#isReadOnly} before
- * updating the database.
- *
- * @param db The database.
- */
- public void onOpen(SQLiteDatabase db) {}
-}
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
deleted file mode 100644
index f89c87d..0000000
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-import android.util.Log;
-
-/**
- * A base class for compiled SQLite programs.
- */
-public abstract class SQLiteProgram extends SQLiteClosable {
- static final String TAG = "SQLiteProgram";
-
- /** The database this program is compiled against. */
- protected SQLiteDatabase mDatabase;
-
- /**
- * Native linkage, do not modify. This comes from the database and should not be modified
- * in here or in the native code.
- */
- protected int nHandle = 0;
-
- /**
- * Native linkage, do not modify. When non-0 this holds a reference to a valid
- * sqlite3_statement object. It is only updated by the native code, but may be
- * checked in this class when the database lock is held to determine if there
- * is a valid native-side program or not.
- */
- protected int nStatement = 0;
-
- /**
- * Used to find out where a cursor was allocated in case it never got
- * released.
- */
- private StackTraceElement[] mStackTraceElements;
-
- /* package */ SQLiteProgram(SQLiteDatabase db, String sql) {
- if (SQLiteDebug.DEBUG_SQL_STATEMENTS) {
- mStackTraceElements = new Exception().getStackTrace();
- }
-
- mDatabase = db;
- db.acquireReference();
- db.addSQLiteClosable(this);
- this.nHandle = db.mNativeHandle;
- compile(sql, false);
- }
-
- @Override
- protected void onAllReferencesReleased() {
- // Note that native_finalize() checks to make sure that nStatement is
- // non-null before destroying it.
- native_finalize();
- mDatabase.releaseReference();
- mDatabase.removeSQLiteClosable(this);
- }
-
- @Override
- protected void onAllReferencesReleasedFromContainer(){
- // Note that native_finalize() checks to make sure that nStatement is
- // non-null before destroying it.
- native_finalize();
- mDatabase.releaseReference();
- }
-
- /**
- * Returns a unique identifier for this program.
- *
- * @return a unique identifier for this program
- */
- public final int getUniqueId() {
- return nStatement;
- }
-
- /**
- * Compiles the given SQL into a SQLite byte code program using sqlite3_prepare_v2(). If
- * this method has been called previously without a call to close and forCompilation is set
- * to false the previous compilation will be used. Setting forceCompilation to true will
- * always re-compile the program and should be done if you pass differing SQL strings to this
- * method.
- *
- * <P>Note: this method acquires the database lock.</P>
- *
- * @param sql the SQL string to compile
- * @param forceCompilation forces the SQL to be recompiled in the event that there is an
- * existing compiled SQL program already around
- */
- protected void compile(String sql, boolean forceCompilation) {
- // Only compile if we don't have a valid statement already or the caller has
- // explicitly requested a recompile.
- if (nStatement == 0 || forceCompilation) {
- mDatabase.lock();
- try {
- // Note that the native_compile() takes care of destroying any previously
- // existing programs before it compiles.
- acquireReference();
- native_compile(sql);
- } finally {
- releaseReference();
- mDatabase.unlock();
- }
- }
- }
-
- /**
- * Bind a NULL value to this statement. The value remains bound until
- * {@link #clearBindings} is called.
- *
- * @param index The 1-based index to the parameter to bind null to
- */
- public void bindNull(int index) {
- acquireReference();
- try {
- native_bind_null(index);
- } finally {
- releaseReference();
- }
- }
-
- /**
- * Bind a long value to this statement. The value remains bound until
- * {@link #clearBindings} is called.
- *
- * @param index The 1-based index to the parameter to bind
- * @param value The value to bind
- */
- public void bindLong(int index, long value) {
- acquireReference();
- try {
- native_bind_long(index, value);
- } finally {
- releaseReference();
- }
- }
-
- /**
- * Bind a double value to this statement. The value remains bound until
- * {@link #clearBindings} is called.
- *
- * @param index The 1-based index to the parameter to bind
- * @param value The value to bind
- */
- public void bindDouble(int index, double value) {
- acquireReference();
- try {
- native_bind_double(index, value);
- } finally {
- releaseReference();
- }
- }
-
- /**
- * Bind a String value to this statement. The value remains bound until
- * {@link #clearBindings} is called.
- *
- * @param index The 1-based index to the parameter to bind
- * @param value The value to bind
- */
- public void bindString(int index, String value) {
- if (value == null) {
- throw new IllegalArgumentException("the bind value at index " + index + " is null");
- }
- acquireReference();
- try {
- native_bind_string(index, value);
- } finally {
- releaseReference();
- }
- }
-
- /**
- * Bind a byte array value to this statement. The value remains bound until
- * {@link #clearBindings} is called.
- *
- * @param index The 1-based index to the parameter to bind
- * @param value The value to bind
- */
- public void bindBlob(int index, byte[] value) {
- if (value == null) {
- throw new IllegalArgumentException("the bind value at index " + index + " is null");
- }
- acquireReference();
- try {
- native_bind_blob(index, value);
- } finally {
- releaseReference();
- }
- }
-
- /**
- * Clears all existing bindings. Unset bindings are treated as NULL.
- */
- public void clearBindings() {
- acquireReference();
- try {
- native_clear_bindings();
- } finally {
- releaseReference();
- }
- }
-
- /**
- * Release this program's resources, making it invalid.
- */
- public void close() {
- mDatabase.lock();
- try {
- releaseReference();
- } finally {
- mDatabase.unlock();
- }
- }
-
- /**
- * Make sure that the native resource is cleaned up.
- */
- @Override
- protected void finalize() {
- if (nStatement != 0) {
- if (SQLiteDebug.DEBUG_SQL_STATEMENTS) {
- String message = "Finalizing " + this +
- " that has not been closed";
-
- Log.d(TAG, message + "\nThis cursor was created in:");
- for (StackTraceElement ste : mStackTraceElements) {
- Log.d(TAG, " " + ste);
- }
- }
- // when in finalize() it is already removed from weakhashmap
- // so it is safe to not removed itself from db
- onAllReferencesReleasedFromContainer();
- }
- }
-
- /**
- * Compiles SQL into a SQLite program.
- *
- * <P>The database lock must be held when calling this method.
- * @param sql The SQL to compile.
- */
- protected final native void native_compile(String sql);
- protected final native void native_finalize();
-
- protected final native void native_bind_null(int index);
- protected final native void native_bind_long(int index, long value);
- protected final native void native_bind_double(int index, double value);
- protected final native void native_bind_string(int index, String value);
- protected final native void native_bind_blob(int index, byte[] value);
- private final native void native_clear_bindings();
-}
-
diff --git a/core/java/android/database/sqlite/SQLiteQuery.java b/core/java/android/database/sqlite/SQLiteQuery.java
deleted file mode 100644
index 5bfa0e8..0000000
--- a/core/java/android/database/sqlite/SQLiteQuery.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-import android.database.CursorWindow;
-import android.os.SystemClock;
-
-/**
- * A SQLite program that represents a query that reads the resulting rows into a CursorWindow.
- * This class is used by SQLiteCursor and isn't useful itself.
- */
-public class SQLiteQuery extends SQLiteProgram {
- //private static final String TAG = "Cursor";
-
- /** The index of the unbound OFFSET parameter */
- private int mOffsetIndex;
-
- /** The SQL used to create this query */
- private String mQuery;
-
- /** Args to bind on requery */
- private String[] mBindArgs;
-
- private boolean mClosed = false;
-
- /**
- * Create a persistent query object.
- *
- * @param db The database that this query object is associated with
- * @param query The SQL string for this query.
- * @param offsetIndex The 1-based index to the OFFSET parameter,
- */
- /* package */ SQLiteQuery(SQLiteDatabase db, String query, int offsetIndex, String[] bindArgs) {
- super(db, query);
-
- mOffsetIndex = offsetIndex;
- mQuery = query;
- mBindArgs = bindArgs;
- }
-
- /**
- * Reads rows into a buffer. This method acquires the database lock.
- *
- * @param window The window to fill into
- * @return number of total rows in the query
- */
- /* package */ int fillWindow(CursorWindow window,
- int maxRead, int lastPos) {
- mDatabase.lock();
-
- boolean logStats = mDatabase.mLogStats;
- long startTime = logStats ? SystemClock.elapsedRealtime() : 0;
- try {
- acquireReference();
- try {
- window.acquireReference();
- // if the start pos is not equal to 0, then most likely window is
- // too small for the data set, loading by another thread
- // is not safe in this situation. the native code will ignore maxRead
- int numRows = native_fill_window(window, window.getStartPosition(), mOffsetIndex,
- maxRead, lastPos);
- if (logStats) {
- mDatabase.logTimeStat(true /* read */, startTime,
- SystemClock.elapsedRealtime());
- }
- return numRows;
- } catch (IllegalStateException e){
- // simply ignore it
- return 0;
- } catch (SQLiteDatabaseCorruptException e) {
- mDatabase.onCorruption();
- throw e;
- } finally {
- window.releaseReference();
- }
- } finally {
- releaseReference();
- mDatabase.unlock();
- }
- }
-
- /**
- * Get the column count for the statement. Only valid on query based
- * statements. The database must be locked
- * when calling this method.
- *
- * @return The number of column in the statement's result set.
- */
- /* package */ int columnCountLocked() {
- acquireReference();
- try {
- return native_column_count();
- } finally {
- releaseReference();
- }
- }
-
- /**
- * Retrieves the column name for the given column index. The database must be locked
- * when calling this method.
- *
- * @param columnIndex the index of the column to get the name for
- * @return The requested column's name
- */
- /* package */ String columnNameLocked(int columnIndex) {
- acquireReference();
- try {
- return native_column_name(columnIndex);
- } finally {
- releaseReference();
- }
- }
-
- /** {@hide pending API Council approval} */
- @Override
- public String toString() {
- return "SQLiteQuery: " + mQuery;
- }
-
- @Override
- public void close() {
- super.close();
- mClosed = true;
- }
-
- /**
- * Called by SQLiteCursor when it is requeried.
- */
- /* package */ void requery() {
- if (mBindArgs != null) {
- int len = mBindArgs.length;
- try {
- for (int i = 0; i < len; i++) {
- super.bindString(i + 1, mBindArgs[i]);
- }
- } catch (SQLiteMisuseException e) {
- StringBuilder errMsg = new StringBuilder("mQuery " + mQuery);
- for (int i = 0; i < len; i++) {
- errMsg.append(" ");
- errMsg.append(mBindArgs[i]);
- }
- errMsg.append(" ");
- IllegalStateException leakProgram = new IllegalStateException(
- errMsg.toString(), e);
- throw leakProgram;
- }
- }
- }
-
- @Override
- public void bindNull(int index) {
- mBindArgs[index - 1] = null;
- if (!mClosed) super.bindNull(index);
- }
-
- @Override
- public void bindLong(int index, long value) {
- mBindArgs[index - 1] = Long.toString(value);
- if (!mClosed) super.bindLong(index, value);
- }
-
- @Override
- public void bindDouble(int index, double value) {
- mBindArgs[index - 1] = Double.toString(value);
- if (!mClosed) super.bindDouble(index, value);
- }
-
- @Override
- public void bindString(int index, String value) {
- mBindArgs[index - 1] = value;
- if (!mClosed) super.bindString(index, value);
- }
-
- private final native int native_fill_window(CursorWindow window,
- int startPos, int offsetParam, int maxRead, int lastPos);
-
- private final native int native_column_count();
-
- private final native String native_column_name(int columnIndex);
-}
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
deleted file mode 100644
index 519a81c..0000000
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.sqlite.SQLiteDatabase;
-import android.provider.BaseColumns;
-import android.text.TextUtils;
-import android.util.Config;
-import android.util.Log;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
-
-/**
- * This is a convience class that helps build SQL queries to be sent to
- * {@link SQLiteDatabase} objects.
- */
-public class SQLiteQueryBuilder
-{
- private static final String TAG = "SQLiteQueryBuilder";
-
- private Map<String, String> mProjectionMap = null;
- private String mTables = "";
- private StringBuilder mWhereClause = new StringBuilder(64);
- private boolean mDistinct;
- private SQLiteDatabase.CursorFactory mFactory;
-
- public SQLiteQueryBuilder() {
- mDistinct = false;
- mFactory = null;
- }
-
- /**
- * Mark the query as DISTINCT.
- *
- * @param distinct if true the query is DISTINCT, otherwise it isn't
- */
- public void setDistinct(boolean distinct) {
- mDistinct = distinct;
- }
-
- /**
- * Returns the list of tables being queried
- *
- * @return the list of tables being queried
- */
- public String getTables() {
- return mTables;
- }
-
- /**
- * Sets the list of tables to query. Multiple tables can be specified to perform a join.
- * For example:
- * setTables("foo, bar")
- * setTables("foo LEFT OUTER JOIN bar ON (foo.id = bar.foo_id)")
- *
- * @param inTables the list of tables to query on
- */
- public void setTables(String inTables) {
- mTables = inTables;
- }
-
- /**
- * Append a chunk to the WHERE clause of the query. All chunks appended are surrounded
- * by parenthesis and ANDed with the selection passed to {@link #query}. The final
- * WHERE clause looks like:
- *
- * WHERE (&lt;append chunk 1>&lt;append chunk2>) AND (&lt;query() selection parameter>)
- *
- * @param inWhere the chunk of text to append to the WHERE clause.
- */
- public void appendWhere(CharSequence inWhere) {
- if (mWhereClause.length() == 0) {
- mWhereClause.append('(');
- }
- mWhereClause.append(inWhere);
- }
-
- /**
- * Append a chunk to the WHERE clause of the query. All chunks appended are surrounded
- * by parenthesis and ANDed with the selection passed to {@link #query}. The final
- * WHERE clause looks like:
- *
- * WHERE (&lt;append chunk 1>&lt;append chunk2>) AND (&lt;query() selection parameter>)
- *
- * @param inWhere the chunk of text to append to the WHERE clause. it will be escaped
- * to avoid SQL injection attacks
- */
- public void appendWhereEscapeString(String inWhere) {
- if (mWhereClause.length() == 0) {
- mWhereClause.append('(');
- }
- DatabaseUtils.appendEscapedSQLString(mWhereClause, inWhere);
- }
-
- /**
- * Sets the projection map for the query. The projection map maps
- * from column names that the caller passes into query to database
- * column names. This is useful for renaming columns as well as
- * disambiguating column names when doing joins. For example you
- * could map "name" to "people.name". If a projection map is set
- * it must contain all column names the user may request, even if
- * the key and value are the same.
- *
- * @param columnMap maps from the user column names to the database column names
- */
- public void setProjectionMap(Map<String, String> columnMap) {
- mProjectionMap = columnMap;
- }
-
- /**
- * Sets the cursor factory to be used for the query. You can use
- * one factory for all queries on a database but it is normally
- * easier to specify the factory when doing this query. @param
- * factory the factor to use
- */
- public void setCursorFactory(SQLiteDatabase.CursorFactory factory) {
- mFactory = factory;
- }
-
- /**
- * Build an SQL query string from the given clauses.
- *
- * @param distinct true if you want each row to be unique, false otherwise.
- * @param tables The table names to compile the query against.
- * @param columns A list of which columns to return. Passing null will
- * return all columns, which is discouraged to prevent reading
- * data from storage that isn't going to be used.
- * @param where A filter declaring which rows to return, formatted as an SQL
- * WHERE clause (excluding the WHERE itself). Passing null will
- * return all rows for the given URL.
- * @param groupBy A filter declaring how to group rows, formatted as an SQL
- * GROUP BY clause (excluding the GROUP BY itself). Passing null
- * will cause the rows to not be grouped.
- * @param having A filter declare which row groups to include in the cursor,
- * if row grouping is being used, formatted as an SQL HAVING
- * clause (excluding the HAVING itself). Passing null will cause
- * all row groups to be included, and is required when row
- * grouping is not being used.
- * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
- * (excluding the ORDER BY itself). Passing null will use the
- * default sort order, which may be unordered.
- * @param limit Limits the number of rows returned by the query,
- * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
- * @return the SQL query string
- */
- public static String buildQueryString(
- boolean distinct, String tables, String[] columns, String where,
- String groupBy, String having, String orderBy, String limit) {
- if (TextUtils.isEmpty(groupBy) && !TextUtils.isEmpty(having)) {
- throw new IllegalArgumentException(
- "HAVING clauses are only permitted when using a groupBy clause");
- }
-
- StringBuilder query = new StringBuilder(120);
-
- query.append("SELECT ");
- if (distinct) {
- query.append("DISTINCT ");
- }
- if (columns != null && columns.length != 0) {
- appendColumns(query, columns);
- } else {
- query.append("* ");
- }
- query.append("FROM ");
- query.append(tables);
- appendClause(query, " WHERE ", where);
- appendClause(query, " GROUP BY ", groupBy);
- appendClause(query, " HAVING ", having);
- appendClause(query, " ORDER BY ", orderBy);
- appendClauseEscapeClause(query, " LIMIT ", limit);
-
- return query.toString();
- }
-
- private static void appendClause(StringBuilder s, String name, String clause) {
- if (!TextUtils.isEmpty(clause)) {
- s.append(name);
- s.append(clause);
- }
- }
-
- private static void appendClauseEscapeClause(StringBuilder s, String name, String clause) {
- if (!TextUtils.isEmpty(clause)) {
- s.append(name);
- DatabaseUtils.appendEscapedSQLString(s, clause);
- }
- }
-
- /**
- * Add the names that are non-null in columns to s, separating
- * them with commas.
- */
- public static void appendColumns(StringBuilder s, String[] columns) {
- int n = columns.length;
-
- for (int i = 0; i < n; i++) {
- String column = columns[i];
-
- if (column != null) {
- if (i > 0) {
- s.append(", ");
- }
- s.append(column);
- }
- }
- s.append(' ');
- }
-
- /**
- * Perform a query by combining all current settings and the
- * information passed into this method.
- *
- * @param db the database to query on
- * @param projectionIn A list of which columns to return. Passing
- * null will return all columns, which is discouraged to prevent
- * reading data from storage that isn't going to be used.
- * @param selection A filter declaring which rows to return,
- * formatted as an SQL WHERE clause (excluding the WHERE
- * itself). Passing null will return all rows for the given URL.
- * @param selectionArgs You may include ?s in selection, which
- * will be replaced by the values from selectionArgs, in order
- * that they appear in the selection. The values will be bound
- * as Strings.
- * @param groupBy A filter declaring how to group rows, formatted
- * as an SQL GROUP BY clause (excluding the GROUP BY
- * itself). Passing null will cause the rows to not be grouped.
- * @param having A filter declare which row groups to include in
- * the cursor, if row grouping is being used, formatted as an
- * SQL HAVING clause (excluding the HAVING itself). Passing
- * null will cause all row groups to be included, and is
- * required when row grouping is not being used.
- * @param sortOrder How to order the rows, formatted as an SQL
- * ORDER BY clause (excluding the ORDER BY itself). Passing null
- * will use the default sort order, which may be unordered.
- * @return a cursor over the result set
- * @see android.content.ContentResolver#query(android.net.Uri, String[],
- * String, String[], String)
- */
- public Cursor query(SQLiteDatabase db, String[] projectionIn,
- String selection, String[] selectionArgs, String groupBy,
- String having, String sortOrder) {
- return query(db, projectionIn, selection, selectionArgs, groupBy, having, sortOrder,
- null /* limit */);
- }
-
- /**
- * Perform a query by combining all current settings and the
- * information passed into this method.
- *
- * @param db the database to query on
- * @param projectionIn A list of which columns to return. Passing
- * null will return all columns, which is discouraged to prevent
- * reading data from storage that isn't going to be used.
- * @param selection A filter declaring which rows to return,
- * formatted as an SQL WHERE clause (excluding the WHERE
- * itself). Passing null will return all rows for the given URL.
- * @param selectionArgs You may include ?s in selection, which
- * will be replaced by the values from selectionArgs, in order
- * that they appear in the selection. The values will be bound
- * as Strings.
- * @param groupBy A filter declaring how to group rows, formatted
- * as an SQL GROUP BY clause (excluding the GROUP BY
- * itself). Passing null will cause the rows to not be grouped.
- * @param having A filter declare which row groups to include in
- * the cursor, if row grouping is being used, formatted as an
- * SQL HAVING clause (excluding the HAVING itself). Passing
- * null will cause all row groups to be included, and is
- * required when row grouping is not being used.
- * @param sortOrder How to order the rows, formatted as an SQL
- * ORDER BY clause (excluding the ORDER BY itself). Passing null
- * will use the default sort order, which may be unordered.
- * @param limit Limits the number of rows returned by the query,
- * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
- * @return a cursor over the result set
- * @see android.content.ContentResolver#query(android.net.Uri, String[],
- * String, String[], String)
- */
- public Cursor query(SQLiteDatabase db, String[] projectionIn,
- String selection, String[] selectionArgs, String groupBy,
- String having, String sortOrder, String limit) {
- if (mTables == null) {
- return null;
- }
-
- String sql = buildQuery(
- projectionIn, selection, selectionArgs, groupBy, having,
- sortOrder, limit);
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Performing query: " + sql);
- }
- return db.rawQueryWithFactory(
- mFactory, sql, selectionArgs,
- SQLiteDatabase.findEditTable(mTables));
- }
-
- /**
- * Construct a SELECT statement suitable for use in a group of
- * SELECT statements that will be joined through UNION operators
- * in buildUnionQuery.
- *
- * @param projectionIn A list of which columns to return. Passing
- * null will return all columns, which is discouraged to
- * prevent reading data from storage that isn't going to be
- * used.
- * @param selection A filter declaring which rows to return,
- * formatted as an SQL WHERE clause (excluding the WHERE
- * itself). Passing null will return all rows for the given
- * URL.
- * @param selectionArgs You may include ?s in selection, which
- * will be replaced by the values from selectionArgs, in order
- * that they appear in the selection. The values will be bound
- * as Strings.
- * @param groupBy A filter declaring how to group rows, formatted
- * as an SQL GROUP BY clause (excluding the GROUP BY itself).
- * Passing null will cause the rows to not be grouped.
- * @param having A filter declare which row groups to include in
- * the cursor, if row grouping is being used, formatted as an
- * SQL HAVING clause (excluding the HAVING itself). Passing
- * null will cause all row groups to be included, and is
- * required when row grouping is not being used.
- * @param sortOrder How to order the rows, formatted as an SQL
- * ORDER BY clause (excluding the ORDER BY itself). Passing null
- * will use the default sort order, which may be unordered.
- * @param limit Limits the number of rows returned by the query,
- * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
- * @return the resulting SQL SELECT statement
- */
- public String buildQuery(
- String[] projectionIn, String selection, String[] selectionArgs,
- String groupBy, String having, String sortOrder, String limit) {
- String[] projection = computeProjection(projectionIn);
-
- if (mWhereClause.length() > 0) {
- mWhereClause.append(')');
- }
-
- // Tack on the user's selection, if present.
- if (selection != null && selection.length() > 0) {
- if (mWhereClause.length() > 0) {
- mWhereClause.append(" AND ");
- }
-
- mWhereClause.append('(');
- mWhereClause.append(selection);
- mWhereClause.append(')');
- }
-
- return buildQueryString(
- mDistinct, mTables, projection, mWhereClause.toString(),
- groupBy, having, sortOrder, limit);
- }
-
- /**
- * Construct a SELECT statement suitable for use in a group of
- * SELECT statements that will be joined through UNION operators
- * in buildUnionQuery.
- *
- * @param typeDiscriminatorColumn the name of the result column
- * whose cells will contain the name of the table from which
- * each row was drawn.
- * @param unionColumns the names of the columns to appear in the
- * result. This may include columns that do not appear in the
- * table this SELECT is querying (i.e. mTables), but that do
- * appear in one of the other tables in the UNION query that we
- * are constructing.
- * @param columnsPresentInTable a Set of the names of the columns
- * that appear in this table (i.e. in the table whose name is
- * mTables). Since columns in unionColumns include columns that
- * appear only in other tables, we use this array to distinguish
- * which ones actually are present. Other columns will have
- * NULL values for results from this subquery.
- * @param computedColumnsOffset all columns in unionColumns before
- * this index are included under the assumption that they're
- * computed and therefore won't appear in columnsPresentInTable,
- * e.g. "date * 1000 as normalized_date"
- * @param typeDiscriminatorValue the value used for the
- * type-discriminator column in this subquery
- * @param selection A filter declaring which rows to return,
- * formatted as an SQL WHERE clause (excluding the WHERE
- * itself). Passing null will return all rows for the given
- * URL.
- * @param selectionArgs You may include ?s in selection, which
- * will be replaced by the values from selectionArgs, in order
- * that they appear in the selection. The values will be bound
- * as Strings.
- * @param groupBy A filter declaring how to group rows, formatted
- * as an SQL GROUP BY clause (excluding the GROUP BY itself).
- * Passing null will cause the rows to not be grouped.
- * @param having A filter declare which row groups to include in
- * the cursor, if row grouping is being used, formatted as an
- * SQL HAVING clause (excluding the HAVING itself). Passing
- * null will cause all row groups to be included, and is
- * required when row grouping is not being used.
- * @return the resulting SQL SELECT statement
- */
- public String buildUnionSubQuery(
- String typeDiscriminatorColumn,
- String[] unionColumns,
- Set<String> columnsPresentInTable,
- int computedColumnsOffset,
- String typeDiscriminatorValue,
- String selection,
- String[] selectionArgs,
- String groupBy,
- String having) {
- int unionColumnsCount = unionColumns.length;
- String[] projectionIn = new String[unionColumnsCount];
-
- for (int i = 0; i < unionColumnsCount; i++) {
- String unionColumn = unionColumns[i];
-
- if (unionColumn.equals(typeDiscriminatorColumn)) {
- projectionIn[i] = "'" + typeDiscriminatorValue + "' AS "
- + typeDiscriminatorColumn;
- } else if (i <= computedColumnsOffset
- || columnsPresentInTable.contains(unionColumn)) {
- projectionIn[i] = unionColumn;
- } else {
- projectionIn[i] = "NULL AS " + unionColumn;
- }
- }
- return buildQuery(
- projectionIn, selection, selectionArgs, groupBy, having,
- null /* sortOrder */,
- null /* limit */);
- }
-
- /**
- * Given a set of subqueries, all of which are SELECT statements,
- * construct a query that returns the union of what those
- * subqueries return.
- * @param subQueries an array of SQL SELECT statements, all of
- * which must have the same columns as the same positions in
- * their results
- * @param sortOrder How to order the rows, formatted as an SQL
- * ORDER BY clause (excluding the ORDER BY itself). Passing
- * null will use the default sort order, which may be unordered.
- * @param limit The limit clause, which applies to the entire union result set
- *
- * @return the resulting SQL SELECT statement
- */
- public String buildUnionQuery(String[] subQueries, String sortOrder, String limit) {
- StringBuilder query = new StringBuilder(128);
- int subQueryCount = subQueries.length;
- String unionOperator = mDistinct ? " UNION " : " UNION ALL ";
-
- for (int i = 0; i < subQueryCount; i++) {
- if (i > 0) {
- query.append(unionOperator);
- }
- query.append(subQueries[i]);
- }
- appendClause(query, " ORDER BY ", sortOrder);
- appendClause(query, " LIMIT ", limit);
- return query.toString();
- }
-
- private String[] computeProjection(String[] projectionIn) {
- if (projectionIn != null && projectionIn.length > 0) {
- if (mProjectionMap != null) {
- String[] projection = new String[projectionIn.length];
- int length = projectionIn.length;
-
- for (int i = 0; i < length; i++) {
- String userColumn = projectionIn[i];
- String column = mProjectionMap.get(userColumn);
-
- if (column == null) {
- throw new IllegalArgumentException(
- "Invalid column " + projectionIn[i]);
- } else {
- projection[i] = column;
- }
- }
- return projection;
- } else {
- return projectionIn;
- }
- } else if (mProjectionMap != null) {
- // Return all columns in projection map.
- Set<Entry<String, String>> entrySet = mProjectionMap.entrySet();
- String[] projection = new String[entrySet.size()];
- Iterator<Entry<String, String>> entryIter = entrySet.iterator();
- int i = 0;
-
- while (entryIter.hasNext()) {
- Entry<String, String> entry = entryIter.next();
-
- // Don't include the _count column when people ask for no projection.
- if (entry.getKey().equals(BaseColumns._COUNT)) {
- continue;
- }
- projection[i++] = entry.getValue();
- }
- return projection;
- }
- return null;
- }
-}
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
deleted file mode 100644
index d169259..0000000
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database.sqlite;
-
-import android.os.SystemClock;
-
-/**
- * A pre-compiled statement against a {@link SQLiteDatabase} that can be reused.
- * The statement cannot return multiple rows, but 1x1 result sets are allowed.
- * Don't use SQLiteStatement constructor directly, please use
- * {@link SQLiteDatabase#compileStatement(String)}
- */
-public class SQLiteStatement extends SQLiteProgram
-{
- /**
- * Don't use SQLiteStatement constructor directly, please use
- * {@link SQLiteDatabase#compileStatement(String)}
- * @param db
- * @param sql
- */
- /* package */ SQLiteStatement(SQLiteDatabase db, String sql) {
- super(db, sql);
- }
-
- /**
- * Execute this SQL statement, if it is not a query. For example,
- * CREATE TABLE, DELTE, INSERT, etc.
- *
- * @throws android.database.SQLException If the SQL string is invalid for
- * some reason
- */
- public void execute() {
- mDatabase.lock();
- boolean logStats = mDatabase.mLogStats;
- long startTime = logStats ? SystemClock.elapsedRealtime() : 0;
-
- acquireReference();
- try {
- native_execute();
- if (logStats) {
- mDatabase.logTimeStat(false /* write */, startTime, SystemClock.elapsedRealtime());
- }
- } finally {
- releaseReference();
- mDatabase.unlock();
- }
- }
-
- /**
- * Execute this SQL statement and return the ID of the most
- * recently inserted row. The SQL statement should probably be an
- * INSERT for this to be a useful call.
- *
- * @return the row ID of the last row inserted.
- *
- * @throws android.database.SQLException If the SQL string is invalid for
- * some reason
- */
- public long executeInsert() {
- mDatabase.lock();
- boolean logStats = mDatabase.mLogStats;
- long startTime = logStats ? SystemClock.elapsedRealtime() : 0;
-
- acquireReference();
- try {
- native_execute();
- if (logStats) {
- mDatabase.logTimeStat(false /* write */, startTime, SystemClock.elapsedRealtime());
- }
- return mDatabase.lastInsertRow();
- } finally {
- releaseReference();
- mDatabase.unlock();
- }
- }
-
- /**
- * Execute a statement that returns a 1 by 1 table with a numeric value.
- * For example, SELECT COUNT(*) FROM table;
- *
- * @return The result of the query.
- *
- * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
- */
- public long simpleQueryForLong() {
- mDatabase.lock();
- boolean logStats = mDatabase.mLogStats;
- long startTime = logStats ? SystemClock.elapsedRealtime() : 0;
-
- acquireReference();
- try {
- long retValue = native_1x1_long();
- if (logStats) {
- mDatabase.logTimeStat(false /* write */, startTime, SystemClock.elapsedRealtime());
- }
- return retValue;
- } finally {
- releaseReference();
- mDatabase.unlock();
- }
- }
-
- /**
- * Execute a statement that returns a 1 by 1 table with a text value.
- * For example, SELECT COUNT(*) FROM table;
- *
- * @return The result of the query.
- *
- * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
- */
- public String simpleQueryForString() {
- mDatabase.lock();
- boolean logStats = mDatabase.mLogStats;
- long startTime = logStats ? SystemClock.elapsedRealtime() : 0;
-
- acquireReference();
- try {
- String retValue = native_1x1_string();
- if (logStats) {
- mDatabase.logTimeStat(false /* write */, startTime, SystemClock.elapsedRealtime());
- }
- return retValue;
- } finally {
- releaseReference();
- mDatabase.unlock();
- }
- }
-
- private final native void native_execute();
- private final native long native_1x1_long();
- private final native String native_1x1_string();
-}
diff --git a/core/java/android/database/sqlite/package.html b/core/java/android/database/sqlite/package.html
deleted file mode 100644
index ff0f9f5..0000000
--- a/core/java/android/database/sqlite/package.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<HTML>
-<BODY>
-Contains the SQLite database management
-classes that an application would use to manage its own private database.
-<p>
-Applications use these classes to maange private databases. If creating a
-content provider, you will probably have to use these classes to create and
-manage your own database to store content. See <a
-href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> to learn
-the conventions for implementing a content provider. See the
-NotePadProvider class in the NotePad sample application in the SDK for an
-example of a content provider. Android ships with SQLite version 3.4.0
-<p>If you are working with data sent to you by a provider, you will not use
-these SQLite classes, but instead use the generic {@link android.database}
-classes.
-<p>Android ships with the sqlite3 database tool in the <code>tools/</code>
-folder. You can use this tool to browse or run SQL commands on the device. Run by
-typing <code>sqlite3</code> in a shell window.
-</BODY>
-</HTML>
diff --git a/core/java/android/ddm/DdmHandleAppName.java b/core/java/android/ddm/DdmHandleAppName.java
deleted file mode 100644
index 4a57d12..0000000
--- a/core/java/android/ddm/DdmHandleAppName.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.ddm;
-
-import org.apache.harmony.dalvik.ddmc.Chunk;
-import org.apache.harmony.dalvik.ddmc.ChunkHandler;
-import org.apache.harmony.dalvik.ddmc.DdmServer;
-import android.util.Config;
-import android.util.Log;
-import java.nio.ByteBuffer;
-
-
-/**
- * Track our app name. We don't (currently) handle any inbound packets.
- */
-public class DdmHandleAppName extends ChunkHandler {
-
- public static final int CHUNK_APNM = type("APNM");
-
- private volatile static String mAppName = "";
-
- private static DdmHandleAppName mInstance = new DdmHandleAppName();
-
-
- /* singleton, do not instantiate */
- private DdmHandleAppName() {}
-
- /**
- * Register for the messages we're interested in.
- */
- public static void register() {}
-
- /**
- * Called when the DDM server connects. The handler is allowed to
- * send messages to the server.
- */
- public void connected() {}
-
- /**
- * Called when the DDM server disconnects. Can be used to disable
- * periodic transmissions or clean up saved state.
- */
- public void disconnected() {}
-
- /**
- * Handle a chunk of data.
- */
- public Chunk handleChunk(Chunk request) {
- return null;
- }
-
-
-
- /**
- * Set the application name. Called when we get named, which may be
- * before or after DDMS connects. For the latter we need to send up
- * an APNM message.
- */
- public static void setAppName(String name) {
- if (name == null || name.length() == 0)
- return;
-
- mAppName = name;
-
- // if DDMS is already connected, send the app name up
- sendAPNM(name);
- }
-
- public static String getAppName() {
- return mAppName;
- }
-
- /*
- * Send an APNM (APplication NaMe) chunk.
- */
- private static void sendAPNM(String appName) {
- if (Config.LOGV)
- Log.v("ddm", "Sending app name");
-
- ByteBuffer out = ByteBuffer.allocate(4 + appName.length()*2);
- out.order(ChunkHandler.CHUNK_ORDER);
- out.putInt(appName.length());
- putString(out, appName);
-
- Chunk chunk = new Chunk(CHUNK_APNM, out);
- DdmServer.sendChunk(chunk);
- }
-
-}
-
diff --git a/core/java/android/ddm/DdmHandleExit.java b/core/java/android/ddm/DdmHandleExit.java
deleted file mode 100644
index 8a0b9a4..0000000
--- a/core/java/android/ddm/DdmHandleExit.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.ddm;
-
-import org.apache.harmony.dalvik.ddmc.Chunk;
-import org.apache.harmony.dalvik.ddmc.ChunkHandler;
-import org.apache.harmony.dalvik.ddmc.DdmServer;
-import android.util.Config;
-import android.util.Log;
-import java.nio.ByteBuffer;
-
-/**
- * Handle an EXIT chunk.
- */
-public class DdmHandleExit extends ChunkHandler {
-
- public static final int CHUNK_EXIT = type("EXIT");
-
- private static DdmHandleExit mInstance = new DdmHandleExit();
-
-
- /* singleton, do not instantiate */
- private DdmHandleExit() {}
-
- /**
- * Register for the messages we're interested in.
- */
- public static void register() {
- DdmServer.registerHandler(CHUNK_EXIT, mInstance);
- }
-
- /**
- * Called when the DDM server connects. The handler is allowed to
- * send messages to the server.
- */
- public void connected() {}
-
- /**
- * Called when the DDM server disconnects. Can be used to disable
- * periodic transmissions or clean up saved state.
- */
- public void disconnected() {}
-
- /**
- * Handle a chunk of data. We're only registered for "EXIT".
- */
- public Chunk handleChunk(Chunk request) {
- if (Config.LOGV)
- Log.v("ddm-exit", "Handling " + name(request.type) + " chunk");
-
- /*
- * Process the request.
- */
- ByteBuffer in = wrapChunk(request);
-
- int statusCode = in.getInt();
-
- Runtime.getRuntime().halt(statusCode);
-
- // if that doesn't work, return an empty message
- return null;
- }
-}
-
diff --git a/core/java/android/ddm/DdmHandleHeap.java b/core/java/android/ddm/DdmHandleHeap.java
deleted file mode 100644
index 54457c2..0000000
--- a/core/java/android/ddm/DdmHandleHeap.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.ddm;
-
-import org.apache.harmony.dalvik.ddmc.Chunk;
-import org.apache.harmony.dalvik.ddmc.ChunkHandler;
-import org.apache.harmony.dalvik.ddmc.DdmServer;
-import org.apache.harmony.dalvik.ddmc.DdmVmInternal;
-import android.util.Config;
-import android.util.Log;
-import java.nio.ByteBuffer;
-
-/**
- * Handle thread-related traffic.
- */
-public class DdmHandleHeap extends ChunkHandler {
-
- public static final int CHUNK_HPIF = type("HPIF");
- public static final int CHUNK_HPSG = type("HPSG");
- public static final int CHUNK_NHSG = type("NHSG");
- public static final int CHUNK_HPGC = type("HPGC");
- public static final int CHUNK_REAE = type("REAE");
- public static final int CHUNK_REAQ = type("REAQ");
- public static final int CHUNK_REAL = type("REAL");
-
- private static DdmHandleHeap mInstance = new DdmHandleHeap();
-
-
- /* singleton, do not instantiate */
- private DdmHandleHeap() {}
-
- /**
- * Register for the messages we're interested in.
- */
- public static void register() {
- DdmServer.registerHandler(CHUNK_HPIF, mInstance);
- DdmServer.registerHandler(CHUNK_HPSG, mInstance);
- DdmServer.registerHandler(CHUNK_NHSG, mInstance);
- DdmServer.registerHandler(CHUNK_HPGC, mInstance);
- DdmServer.registerHandler(CHUNK_REAE, mInstance);
- DdmServer.registerHandler(CHUNK_REAQ, mInstance);
- DdmServer.registerHandler(CHUNK_REAL, mInstance);
- }
-
- /**
- * Called when the DDM server connects. The handler is allowed to
- * send messages to the server.
- */
- public void connected() {}
-
- /**
- * Called when the DDM server disconnects. Can be used to disable
- * periodic transmissions or clean up saved state.
- */
- public void disconnected() {}
-
- /**
- * Handle a chunk of data.
- */
- public Chunk handleChunk(Chunk request) {
- if (Config.LOGV)
- Log.v("ddm-heap", "Handling " + name(request.type) + " chunk");
- int type = request.type;
-
- if (type == CHUNK_HPIF) {
- return handleHPIF(request);
- } else if (type == CHUNK_HPSG) {
- return handleHPSGNHSG(request, false);
- } else if (type == CHUNK_NHSG) {
- return handleHPSGNHSG(request, true);
- } else if (type == CHUNK_HPGC) {
- return handleHPGC(request);
- } else if (type == CHUNK_REAE) {
- return handleREAE(request);
- } else if (type == CHUNK_REAQ) {
- return handleREAQ(request);
- } else if (type == CHUNK_REAL) {
- return handleREAL(request);
- } else {
- throw new RuntimeException("Unknown packet "
- + ChunkHandler.name(type));
- }
- }
-
- /*
- * Handle a "HeaP InFo request".
- */
- private Chunk handleHPIF(Chunk request) {
- ByteBuffer in = wrapChunk(request);
-
- int when = in.get();
- if (Config.LOGV)
- Log.v("ddm-heap", "Heap segment enable: when=" + when);
-
- boolean ok = DdmVmInternal.heapInfoNotify(when);
- if (!ok) {
- return createFailChunk(1, "Unsupported HPIF what");
- } else {
- return null; // empty response
- }
- }
-
- /*
- * Handle a "HeaP SeGment" or "Native Heap SeGment" request.
- */
- private Chunk handleHPSGNHSG(Chunk request, boolean isNative) {
- ByteBuffer in = wrapChunk(request);
-
- int when = in.get();
- int what = in.get();
- if (Config.LOGV)
- Log.v("ddm-heap", "Heap segment enable: when=" + when
- + ", what=" + what + ", isNative=" + isNative);
-
- boolean ok = DdmVmInternal.heapSegmentNotify(when, what, isNative);
- if (!ok) {
- return createFailChunk(1, "Unsupported HPSG what/when");
- } else {
- // TODO: if "when" is non-zero and we want to see a dump
- // right away, initiate a GC.
- return null; // empty response
- }
- }
-
- /*
- * Handle a "HeaP Garbage Collection" request.
- */
- private Chunk handleHPGC(Chunk request) {
- //ByteBuffer in = wrapChunk(request);
-
- if (Config.LOGD)
- Log.d("ddm-heap", "Heap GC request");
- System.gc();
-
- return null; // empty response
- }
-
- /*
- * Handle a "REcent Allocation Enable" request.
- */
- private Chunk handleREAE(Chunk request) {
- ByteBuffer in = wrapChunk(request);
- boolean enable;
-
- enable = (in.get() != 0);
-
- if (Config.LOGD)
- Log.d("ddm-heap", "Recent allocation enable request: " + enable);
-
- DdmVmInternal.enableRecentAllocations(enable);
-
- return null; // empty response
- }
-
- /*
- * Handle a "REcent Allocation Query" request.
- */
- private Chunk handleREAQ(Chunk request) {
- //ByteBuffer in = wrapChunk(request);
-
- byte[] reply = new byte[1];
- reply[0] = DdmVmInternal.getRecentAllocationStatus() ? (byte)1 :(byte)0;
- return new Chunk(CHUNK_REAQ, reply, 0, reply.length);
- }
-
- /*
- * Handle a "REcent ALlocations" request.
- */
- private Chunk handleREAL(Chunk request) {
- //ByteBuffer in = wrapChunk(request);
-
- if (Config.LOGD)
- Log.d("ddm-heap", "Recent allocations request");
-
- /* generate the reply in a ready-to-go format */
- byte[] reply = DdmVmInternal.getRecentAllocations();
- return new Chunk(CHUNK_REAL, reply, 0, reply.length);
- }
-}
-
diff --git a/core/java/android/ddm/DdmHandleHello.java b/core/java/android/ddm/DdmHandleHello.java
deleted file mode 100644
index e4d630e..0000000
--- a/core/java/android/ddm/DdmHandleHello.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.ddm;
-
-import org.apache.harmony.dalvik.ddmc.Chunk;
-import org.apache.harmony.dalvik.ddmc.ChunkHandler;
-import org.apache.harmony.dalvik.ddmc.DdmServer;
-import android.util.Config;
-import android.util.Log;
-import android.os.Debug;
-
-import java.nio.ByteBuffer;
-
-/**
- * Handle a HELO chunk.
- */
-public class DdmHandleHello extends ChunkHandler {
-
- public static final int CHUNK_HELO = type("HELO");
- public static final int CHUNK_WAIT = type("WAIT");
-
- private static DdmHandleHello mInstance = new DdmHandleHello();
-
-
- /* singleton, do not instantiate */
- private DdmHandleHello() {}
-
- /**
- * Register for the messages we're interested in.
- */
- public static void register() {
- DdmServer.registerHandler(CHUNK_HELO, mInstance);
- }
-
- /**
- * Called when the DDM server connects. The handler is allowed to
- * send messages to the server.
- */
- public void connected() {
- if (Config.LOGV)
- Log.v("ddm-hello", "Connected!");
-
- if (true) {
- /* test spontaneous transmission */
- byte[] data = new byte[] { 0, 1, 2, 3, 4, -4, -3, -2, -1, 127 };
- Chunk testChunk =
- new Chunk(ChunkHandler.type("TEST"), data, 1, data.length-2);
- DdmServer.sendChunk(testChunk);
- }
- }
-
- /**
- * Called when the DDM server disconnects. Can be used to disable
- * periodic transmissions or clean up saved state.
- */
- public void disconnected() {
- if (Config.LOGV)
- Log.v("ddm-hello", "Disconnected!");
- }
-
- /**
- * Handle a chunk of data. We're only registered for "HELO".
- */
- public Chunk handleChunk(Chunk request) {
- if (Config.LOGV)
- Log.v("ddm-hello", "Handling " + name(request.type) + " chunk");
-
- if (false)
- return createFailChunk(123, "This is a test");
-
- /*
- * Process the request.
- */
- ByteBuffer in = wrapChunk(request);
-
- int serverProtoVers = in.getInt();
- if (Config.LOGV)
- Log.v("ddm-hello", "Server version is " + serverProtoVers);
-
- /*
- * Create a response.
- */
- String vmName = System.getProperty("java.vm.name", "?");
- String vmVersion = System.getProperty("java.vm.version", "?");
- String vmIdent = vmName + " v" + vmVersion;
-
- //String appName = android.app.ActivityThread.currentPackageName();
- //if (appName == null)
- // appName = "unknown";
- String appName = DdmHandleAppName.getAppName();
-
- ByteBuffer out = ByteBuffer.allocate(16
- + vmIdent.length()*2 + appName.length()*2);
- out.order(ChunkHandler.CHUNK_ORDER);
- out.putInt(DdmServer.CLIENT_PROTOCOL_VERSION);
- out.putInt(android.os.Process.myPid());
- out.putInt(vmIdent.length());
- out.putInt(appName.length());
- putString(out, vmIdent);
- putString(out, appName);
-
- Chunk reply = new Chunk(CHUNK_HELO, out);
-
- /*
- * Take the opportunity to inform DDMS if we are waiting for a
- * debugger to attach.
- */
- if (Debug.waitingForDebugger())
- sendWAIT(0);
-
- return reply;
- }
-
- /**
- * Send up a WAIT chunk. The only currently defined value for "reason"
- * is zero, which means "waiting for a debugger".
- */
- public static void sendWAIT(int reason) {
- byte[] data = new byte[] { (byte) reason };
- Chunk waitChunk = new Chunk(CHUNK_WAIT, data, 0, 1);
- DdmServer.sendChunk(waitChunk);
- }
-}
-
diff --git a/core/java/android/ddm/DdmHandleNativeHeap.java b/core/java/android/ddm/DdmHandleNativeHeap.java
deleted file mode 100644
index 6bd65aa..0000000
--- a/core/java/android/ddm/DdmHandleNativeHeap.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.ddm;
-
-import org.apache.harmony.dalvik.ddmc.Chunk;
-import org.apache.harmony.dalvik.ddmc.ChunkHandler;
-import org.apache.harmony.dalvik.ddmc.DdmServer;
-import android.util.Log;
-import java.nio.ByteBuffer;
-
-/**
- * Handle thread-related traffic.
- */
-public class DdmHandleNativeHeap extends ChunkHandler {
-
- public static final int CHUNK_NHGT = type("NHGT");
-
- private static DdmHandleNativeHeap mInstance = new DdmHandleNativeHeap();
-
-
- /* singleton, do not instantiate */
- private DdmHandleNativeHeap() {}
-
- /**
- * Register for the messages we're interested in.
- */
- public static void register() {
- DdmServer.registerHandler(CHUNK_NHGT, mInstance);
- }
-
- /**
- * Called when the DDM server connects. The handler is allowed to
- * send messages to the server.
- */
- public void connected() {}
-
- /**
- * Called when the DDM server disconnects. Can be used to disable
- * periodic transmissions or clean up saved state.
- */
- public void disconnected() {}
-
- /**
- * Handle a chunk of data.
- */
- public Chunk handleChunk(Chunk request) {
- Log.i("ddm-nativeheap", "Handling " + name(request.type) + " chunk");
- int type = request.type;
-
- if (type == CHUNK_NHGT) {
- return handleNHGT(request);
- } else {
- throw new RuntimeException("Unknown packet "
- + ChunkHandler.name(type));
- }
- }
-
- /*
- * Handle a "Native Heap GeT" request.
- */
- private Chunk handleNHGT(Chunk request) {
- //ByteBuffer in = wrapChunk(request);
-
- byte[] data = getLeakInfo();
-
- if (data != null) {
- // wrap & return
- Log.i("ddm-nativeheap", "Sending " + data.length + " bytes");
- return new Chunk(ChunkHandler.type("NHGT"), data, 0, data.length);
- } else {
- // failed, return a failure error code and message
- return createFailChunk(1, "Something went wrong");
- }
- }
-
- private native byte[] getLeakInfo();
-}
-
diff --git a/core/java/android/ddm/DdmHandleThread.java b/core/java/android/ddm/DdmHandleThread.java
deleted file mode 100644
index c307988..0000000
--- a/core/java/android/ddm/DdmHandleThread.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.ddm;
-
-import org.apache.harmony.dalvik.ddmc.Chunk;
-import org.apache.harmony.dalvik.ddmc.ChunkHandler;
-import org.apache.harmony.dalvik.ddmc.DdmServer;
-import org.apache.harmony.dalvik.ddmc.DdmVmInternal;
-import android.util.Config;
-import android.util.Log;
-import java.nio.ByteBuffer;
-
-/**
- * Handle thread-related traffic.
- */
-public class DdmHandleThread extends ChunkHandler {
-
- public static final int CHUNK_THEN = type("THEN");
- public static final int CHUNK_THCR = type("THCR");
- public static final int CHUNK_THDE = type("THDE");
- public static final int CHUNK_THST = type("THST");
- public static final int CHUNK_STKL = type("STKL");
-
- private static DdmHandleThread mInstance = new DdmHandleThread();
-
-
- /* singleton, do not instantiate */
- private DdmHandleThread() {}
-
- /**
- * Register for the messages we're interested in.
- */
- public static void register() {
- DdmServer.registerHandler(CHUNK_THEN, mInstance);
- DdmServer.registerHandler(CHUNK_THST, mInstance);
- DdmServer.registerHandler(CHUNK_STKL, mInstance);
- }
-
- /**
- * Called when the DDM server connects. The handler is allowed to
- * send messages to the server.
- */
- public void connected() {}
-
- /**
- * Called when the DDM server disconnects. Can be used to disable
- * periodic transmissions or clean up saved state.
- */
- public void disconnected() {}
-
- /**
- * Handle a chunk of data.
- */
- public Chunk handleChunk(Chunk request) {
- if (Config.LOGV)
- Log.v("ddm-thread", "Handling " + name(request.type) + " chunk");
- int type = request.type;
-
- if (type == CHUNK_THEN) {
- return handleTHEN(request);
- } else if (type == CHUNK_THST) {
- return handleTHST(request);
- } else if (type == CHUNK_STKL) {
- return handleSTKL(request);
- } else {
- throw new RuntimeException("Unknown packet "
- + ChunkHandler.name(type));
- }
- }
-
- /*
- * Handle a "THread notification ENable" request.
- */
- private Chunk handleTHEN(Chunk request) {
- ByteBuffer in = wrapChunk(request);
-
- boolean enable = (in.get() != 0);
- //Log.i("ddm-thread", "Thread notify enable: " + enable);
-
- DdmVmInternal.threadNotify(enable);
- return null; // empty response
- }
-
- /*
- * Handle a "THread STatus" request. This is constructed by the VM.
- */
- private Chunk handleTHST(Chunk request) {
- ByteBuffer in = wrapChunk(request);
- // currently nothing to read from "in"
-
- //Log.d("ddm-thread", "Thread status request");
-
- byte[] status = DdmVmInternal.getThreadStats();
- if (status != null)
- return new Chunk(CHUNK_THST, status, 0, status.length);
- else
- return createFailChunk(1, "Can't build THST chunk");
- }
-
- /*
- * Handle a STacK List request.
- *
- * This is done by threadId, which isn't great since those are
- * recycled. We need a thread serial ID. The Linux tid is an okay
- * answer as it's unlikely to recycle at the exact wrong moment.
- * However, we're using the short threadId in THST messages, so we
- * use them here for consistency. (One thought is to keep the current
- * thread ID in the low 16 bits and somehow serialize the top 16 bits.)
- */
- private Chunk handleSTKL(Chunk request) {
- ByteBuffer in = wrapChunk(request);
- int threadId;
-
- threadId = in.getInt();
-
- //Log.d("ddm-thread", "Stack list request " + threadId);
-
- StackTraceElement[] trace = DdmVmInternal.getStackTraceById(threadId);
- if (trace == null) {
- return createFailChunk(1, "Stack trace unavailable");
- } else {
- return createStackChunk(trace, threadId);
- }
- }
-
- /*
- * Serialize a StackTraceElement[] into an STKL chunk.
- *
- * We include the threadId in the response so the other side doesn't have
- * to match up requests and responses as carefully.
- */
- private Chunk createStackChunk(StackTraceElement[] trace, int threadId) {
- int bufferSize = 0;
-
- bufferSize += 4; // version, flags, whatever
- bufferSize += 4; // thread ID
- bufferSize += 4; // frame count
- for (StackTraceElement elem : trace) {
- bufferSize += 4 + elem.getClassName().length() * 2;
- bufferSize += 4 + elem.getMethodName().length() * 2;
- bufferSize += 4;
- if (elem.getFileName() != null)
- bufferSize += elem.getFileName().length() * 2;
- bufferSize += 4; // line number
- }
-
- ByteBuffer out = ByteBuffer.allocate(bufferSize);
- out.putInt(0);
- out.putInt(threadId);
- out.putInt(trace.length);
- for (StackTraceElement elem : trace) {
- out.putInt(elem.getClassName().length());
- putString(out, elem.getClassName());
- out.putInt(elem.getMethodName().length());
- putString(out, elem.getMethodName());
- if (elem.getFileName() != null) {
- out.putInt(elem.getFileName().length());
- putString(out, elem.getFileName());
- } else {
- out.putInt(0);
- }
- out.putInt(elem.getLineNumber());
- }
-
- return new Chunk(CHUNK_STKL, out);
- }
-}
-
diff --git a/core/java/android/ddm/DdmRegister.java b/core/java/android/ddm/DdmRegister.java
deleted file mode 100644
index b7f1ab8..0000000
--- a/core/java/android/ddm/DdmRegister.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.ddm;
-
-import org.apache.harmony.dalvik.ddmc.DdmServer;
-import android.util.Config;
-import android.util.Log;
-
-/**
- * Just a place to stick handler registrations, instead of scattering
- * them around.
- */
-public class DdmRegister {
-
- private DdmRegister() {}
-
- /**
- * Register handlers for all known chunk types.
- *
- * If you write a handler, add a registration call here.
- *
- * Note that this is invoked by the application (usually through a
- * static initializer in the main class), not the VM. It's done this
- * way so that the handlers can use Android classes with native calls
- * that aren't registered until after the VM is initialized (e.g.
- * logging). It also allows debugging of DDM handler initialization.
- *
- * The chunk dispatcher will pause until we call registrationComplete(),
- * so that we don't have a race that causes us to drop packets before
- * we finish here.
- */
- public static void registerHandlers() {
- if (Config.LOGV)
- Log.v("ddm", "Registering DDM message handlers");
- DdmHandleHello.register();
- DdmHandleThread.register();
- DdmHandleHeap.register();
- DdmHandleNativeHeap.register();
- DdmHandleExit.register();
-
- DdmServer.registrationComplete();
- }
-}
-
diff --git a/core/java/android/ddm/README.txt b/core/java/android/ddm/README.txt
deleted file mode 100644
index a8e645d..0000000
--- a/core/java/android/ddm/README.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Some classes that handle DDM traffic.
-
-It's not necessary to put all DDM-related code in this package; this just
-has the essentials. Subclass org.apache.harmony.dalvik.ddmc.ChunkHandler and add a new
-registration call in DdmRegister.java.
-
diff --git a/core/java/android/ddm/package.html b/core/java/android/ddm/package.html
deleted file mode 100755
index 1c9bf9d..0000000
--- a/core/java/android/ddm/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body>
- {@hide}
-</body>
-</html>
diff --git a/core/java/android/debug/JNITest.java b/core/java/android/debug/JNITest.java
deleted file mode 100644
index 2ce374a..0000000
--- a/core/java/android/debug/JNITest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.debug;
-
-/**
- * Simple JNI verification test.
- */
-public class JNITest {
-
- public JNITest() {
- }
-
- public int test(int intArg, double doubleArg, String stringArg) {
- int[] intArray = { 42, 53, 65, 127 };
-
- return part1(intArg, doubleArg, stringArg, intArray);
- }
-
- private native int part1(int intArg, double doubleArg, String stringArg,
- int[] arrayArg);
-
- private int part2(double doubleArg, int fromArray, String stringArg) {
- int result;
-
- System.out.println(stringArg + " : " + (float) doubleArg + " : " +
- fromArray);
- result = part3(stringArg);
-
- return result + 6;
- }
-
- private static native int part3(String stringArg);
-}
-
diff --git a/core/java/android/debug/package.html b/core/java/android/debug/package.html
deleted file mode 100755
index c9f96a6..0000000
--- a/core/java/android/debug/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>
diff --git a/core/java/android/gadget/GadgetHost.java b/core/java/android/gadget/GadgetHost.java
deleted file mode 100644
index 31aed32..0000000
--- a/core/java/android/gadget/GadgetHost.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.gadget;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.widget.RemoteViews;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-import com.android.internal.gadget.IGadgetHost;
-import com.android.internal.gadget.IGadgetService;
-
-/**
- * GadgetHost provides the interaction with the Gadget Service for apps,
- * like the home screen, that want to embed gadgets in their UI.
- */
-public class GadgetHost {
-
- static final int HANDLE_UPDATE = 1;
- static final int HANDLE_PROVIDER_CHANGED = 2;
-
- static Object sServiceLock = new Object();
- static IGadgetService sService;
-
- Context mContext;
- String mPackageName;
-
- class Callbacks extends IGadgetHost.Stub {
- public void updateGadget(int gadgetId, RemoteViews views) {
- Message msg = mHandler.obtainMessage(HANDLE_UPDATE);
- msg.arg1 = gadgetId;
- msg.obj = views;
- msg.sendToTarget();
- }
-
- public void providerChanged(int gadgetId, GadgetProviderInfo info) {
- Message msg = mHandler.obtainMessage(HANDLE_PROVIDER_CHANGED);
- msg.arg1 = gadgetId;
- msg.obj = info;
- msg.sendToTarget();
- }
- }
-
- Handler mHandler = new Handler() {
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case HANDLE_UPDATE: {
- updateGadgetView(msg.arg1, (RemoteViews)msg.obj);
- break;
- }
- case HANDLE_PROVIDER_CHANGED: {
- onProviderChanged(msg.arg1, (GadgetProviderInfo)msg.obj);
- break;
- }
- }
- }
- };
-
- int mHostId;
- Callbacks mCallbacks = new Callbacks();
- HashMap<Integer,GadgetHostView> mViews = new HashMap();
-
- public GadgetHost(Context context, int hostId) {
- mContext = context;
- mHostId = hostId;
- synchronized (sServiceLock) {
- if (sService == null) {
- IBinder b = ServiceManager.getService(Context.GADGET_SERVICE);
- sService = IGadgetService.Stub.asInterface(b);
- }
- }
- }
-
- /**
- * Start receiving onGadgetChanged calls for your gadgets. Call this when your activity
- * becomes visible, i.e. from onStart() in your Activity.
- */
- public void startListening() {
- int[] updatedIds = null;
- ArrayList<RemoteViews> updatedViews = new ArrayList();
-
- try {
- if (mPackageName == null) {
- mPackageName = mContext.getPackageName();
- }
- updatedIds = sService.startListening(mCallbacks, mPackageName, mHostId, updatedViews);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
- }
-
- final int N = updatedIds.length;
- for (int i=0; i<N; i++) {
- updateGadgetView(updatedIds[i], updatedViews.get(i));
- }
- }
-
- /**
- * Stop receiving onGadgetChanged calls for your gadgets. Call this when your activity is
- * no longer visible, i.e. from onStop() in your Activity.
- */
- public void stopListening() {
- try {
- sService.stopListening(mHostId);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
- }
- }
-
- /**
- * Get a gadgetId for a host in the calling process.
- *
- * @return a gadgetId
- */
- public int allocateGadgetId() {
- try {
- if (mPackageName == null) {
- mPackageName = mContext.getPackageName();
- }
- return sService.allocateGadgetId(mPackageName, mHostId);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
- }
- }
-
- /**
- * Stop listening to changes for this gadget.
- */
- public void deleteGadgetId(int gadgetId) {
- synchronized (mViews) {
- mViews.remove(gadgetId);
- try {
- sService.deleteGadgetId(gadgetId);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
- }
- }
- }
-
- /**
- * Remove all records about this host from the gadget manager.
- * <ul>
- * <li>Call this when initializing your database, as it might be because of a data wipe.</li>
- * <li>Call this to have the gadget manager release all resources associated with your
- * host. Any future calls about this host will cause the records to be re-allocated.</li>
- * </ul>
- */
- public void deleteHost() {
- try {
- sService.deleteHost(mHostId);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
- }
- }
-
- /**
- * Remove all records about all hosts for your package.
- * <ul>
- * <li>Call this when initializing your database, as it might be because of a data wipe.</li>
- * <li>Call this to have the gadget manager release all resources associated with your
- * host. Any future calls about this host will cause the records to be re-allocated.</li>
- * </ul>
- */
- public static void deleteAllHosts() {
- try {
- sService.deleteAllHosts();
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
- }
- }
-
- public final GadgetHostView createView(Context context, int gadgetId,
- GadgetProviderInfo gadget) {
- GadgetHostView view = onCreateView(context, gadgetId, gadget);
- view.setGadget(gadgetId, gadget);
- synchronized (mViews) {
- mViews.put(gadgetId, view);
- }
- RemoteViews views = null;
- try {
- views = sService.getGadgetViews(gadgetId);
- } catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
- }
- view.updateGadget(views);
- return view;
- }
-
- /**
- * Called to create the GadgetHostView. Override to return a custom subclass if you
- * need it. {@more}
- */
- protected GadgetHostView onCreateView(Context context, int gadgetId,
- GadgetProviderInfo gadget) {
- return new GadgetHostView(context);
- }
-
- /**
- * Called when the gadget provider for a gadget has been upgraded to a new apk.
- */
- protected void onProviderChanged(int gadgetId, GadgetProviderInfo gadget) {
- }
-
- void updateGadgetView(int gadgetId, RemoteViews views) {
- GadgetHostView v;
- synchronized (mViews) {
- v = mViews.get(gadgetId);
- }
- if (v != null) {
- v.updateGadget(views);
- }
- }
-}
-
-
diff --git a/core/java/android/gadget/GadgetHostView.java b/core/java/android/gadget/GadgetHostView.java
deleted file mode 100644
index a985bd4..0000000
--- a/core/java/android/gadget/GadgetHostView.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.gadget;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.graphics.Color;
-import android.util.Config;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.Animation;
-import android.widget.FrameLayout;
-import android.widget.RemoteViews;
-import android.widget.TextView;
-import android.widget.ViewAnimator;
-
-/**
- * Provides the glue to show gadget views. This class offers automatic animation
- * between updates, and will try recycling old views for each incoming
- * {@link RemoteViews}.
- */
-public class GadgetHostView extends ViewAnimator implements Animation.AnimationListener {
- static final String TAG = "GadgetHostView";
- static final boolean LOGD = Config.LOGD || true;
-
- // When we're inflating the initialLayout for a gadget, we only allow
- // views that are allowed in RemoteViews.
- static final LayoutInflater.Filter sInflaterFilter = new LayoutInflater.Filter() {
- public boolean onLoadClass(Class clazz) {
- return clazz.isAnnotationPresent(RemoteViews.RemoteView.class);
- }
- };
-
- Context mLocalContext;
-
- int mGadgetId;
- GadgetProviderInfo mInfo;
-
- View mActiveView = null;
- View mStaleView = null;
-
- int mActiveLayoutId = -1;
- int mStaleLayoutId = -1;
-
- /**
- * Last set of {@link RemoteViews} applied to {@link #mActiveView}
- */
- RemoteViews mActiveActions = null;
-
- /**
- * Flag indicating that {@link #mActiveActions} has been applied to
- * {@link #mStaleView}, meaning it's readyto recycle.
- */
- boolean mStalePrepared = false;
-
- /**
- * Create a host view. Uses default fade animations.
- */
- public GadgetHostView(Context context) {
- this(context, android.R.anim.fade_in, android.R.anim.fade_out);
- }
-
- /**
- * Create a host view. Uses specified animations when pushing
- * {@link #updateGadget(RemoteViews)}.
- *
- * @param animationIn Resource ID of in animation to use
- * @param animationOut Resource ID of out animation to use
- */
- public GadgetHostView(Context context, int animationIn, int animationOut) {
- super(context);
- mLocalContext = context;
-
- // Prepare our default transition animations
- setAnimateFirstView(true);
- setInAnimation(context, animationIn);
- setOutAnimation(context, animationOut);
-
- // Watch for animation events to prepare recycling
- Animation inAnimation = getInAnimation();
- if (inAnimation != null) {
- inAnimation.setAnimationListener(this);
- }
- }
-
- /**
- * Set the gadget that will be displayed by this view.
- */
- public void setGadget(int gadgetId, GadgetProviderInfo info) {
- if (mInfo != null) {
- // TODO: remove the old view, or whatever
- }
- mGadgetId = gadgetId;
- mInfo = info;
- }
-
- public int getGadgetId() {
- return mGadgetId;
- }
-
- public GadgetProviderInfo getGadgetInfo() {
- return mInfo;
- }
-
- public void onAnimationEnd(Animation animation) {
- // When our transition animation finishes, we should try bringing our
- // newly-stale view up to the current view.
- if (mActiveActions != null &&
- mStaleLayoutId == mActiveActions.getLayoutId()) {
- if (LOGD) Log.d(TAG, "after animation, layoutId matched so we're recycling old view");
- mActiveActions.reapply(mLocalContext, mStaleView);
- mStalePrepared = true;
- }
- }
-
- public void onAnimationRepeat(Animation animation) {
- }
-
- public void onAnimationStart(Animation animation) {
- }
-
- /**
- * Process a set of {@link RemoteViews} coming in as an update from the
- * gadget provider. Will animate into these new views as needed.
- */
- public void updateGadget(RemoteViews remoteViews) {
- if (LOGD) Log.d(TAG, "updateGadget called");
-
- boolean recycled = false;
- View newContent = null;
- Exception exception = null;
-
- if (remoteViews == null) {
- newContent = getDefaultView();
- }
-
- // If our stale view has been prepared to match active, and the new
- // layout matches, try recycling it
- if (newContent == null && mStalePrepared &&
- remoteViews.getLayoutId() == mStaleLayoutId) {
- try {
- remoteViews.reapply(mLocalContext, mStaleView);
- newContent = mStaleView;
- recycled = true;
- if (LOGD) Log.d(TAG, "was able to recycled existing layout");
- } catch (RuntimeException e) {
- exception = e;
- }
- }
-
- // Try normal RemoteView inflation
- if (newContent == null) {
- try {
- newContent = remoteViews.apply(mLocalContext, this);
- if (LOGD) Log.d(TAG, "had to inflate new layout");
- } catch (RuntimeException e) {
- exception = e;
- }
- }
-
- if (exception != null && LOGD) {
- Log.w(TAG, "Error inflating gadget " + getGadgetInfo(), exception);
- }
-
- if (newContent == null) {
- // TODO: Should we throw an exception here for the host activity to catch?
- // Maybe we should show a generic error widget.
- if (LOGD) Log.d(TAG, "updateGadget couldn't find any view, so inflating error");
- newContent = getErrorView();
- }
-
- if (!recycled) {
- prepareView(newContent);
- addView(newContent);
- }
-
- showNext();
-
- if (!recycled) {
- removeView(mStaleView);
- }
-
- mStalePrepared = false;
- mActiveActions = remoteViews;
-
- mStaleView = mActiveView;
- mActiveView = newContent;
-
- mStaleLayoutId = mActiveLayoutId;
- mActiveLayoutId = (remoteViews == null) ? -1 : remoteViews.getLayoutId();
- }
-
- /**
- * Prepare the given view to be shown. This might include adjusting
- * {@link FrameLayout.LayoutParams} before inserting.
- */
- protected void prepareView(View view) {
- // Take requested dimensions from parent, but apply default gravity.
- ViewGroup.LayoutParams requested = view.getLayoutParams();
- if (requested == null) {
- requested = new FrameLayout.LayoutParams(LayoutParams.FILL_PARENT,
- LayoutParams.FILL_PARENT);
- }
-
- FrameLayout.LayoutParams params =
- new FrameLayout.LayoutParams(requested.width, requested.height);
- params.gravity = Gravity.CENTER;
- view.setLayoutParams(params);
- }
-
- /**
- * Inflate and return the default layout requested by gadget provider.
- */
- protected View getDefaultView() {
- View defaultView = null;
- Exception exception = null;
-
- try {
- if (mInfo != null) {
- Context theirContext = mLocalContext.createPackageContext(
- mInfo.provider.getPackageName(), 0 /* no flags */);
- LayoutInflater inflater = (LayoutInflater)
- theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater = inflater.cloneInContext(theirContext);
- inflater.setFilter(sInflaterFilter);
- defaultView = inflater.inflate(mInfo.initialLayout, this, false);
- } else {
- Log.w(TAG, "can't inflate defaultView because mInfo is missing");
- }
- } catch (PackageManager.NameNotFoundException e) {
- exception = e;
- } catch (RuntimeException e) {
- exception = e;
- }
-
- if (exception != null && LOGD) {
- Log.w(TAG, "Error inflating gadget " + mInfo, exception);
- }
-
- if (defaultView == null) {
- if (LOGD) Log.d(TAG, "getDefaultView couldn't find any view, so inflating error");
- defaultView = getErrorView();
- }
-
- return defaultView;
- }
-
- /**
- * Inflate and return a view that represents an error state.
- */
- protected View getErrorView() {
- TextView tv = new TextView(mLocalContext);
- // TODO: move this error string and background color into resources
- tv.setText("Error inflating gadget");
- tv.setBackgroundColor(Color.argb(127, 0, 0, 0));
- return tv;
- }
-}
diff --git a/core/java/android/gadget/GadgetManager.java b/core/java/android/gadget/GadgetManager.java
deleted file mode 100644
index a9a2c80..0000000
--- a/core/java/android/gadget/GadgetManager.java
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.gadget;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.Log;
-import android.widget.RemoteViews;
-
-import com.android.internal.gadget.IGadgetService;
-
-import java.lang.ref.WeakReference;
-import java.util.List;
-import java.util.WeakHashMap;
-
-/**
- * Updates gadget state; gets information about installed gadget providers and other
- * gadget related state.
- */
-public class GadgetManager {
- static final String TAG = "GadgetManager";
-
- /**
- * Send this from your gadget host activity when you want to pick a gadget to display.
- * The gadget picker activity will be launched.
- * <p>
- * You must supply the following extras:
- * <table>
- * <tr>
- * <td>{@link #EXTRA_GADGET_ID}</td>
- * <td>A newly allocated gadgetId, which will be bound to the gadget provider
- * once the user has selected one.</td>
- * </tr>
- * </table>
- *
- * <p>
- * The system will respond with an onActivityResult call with the following extras in
- * the intent:
- * <table>
- * <tr>
- * <td>{@link #EXTRA_GADGET_ID}</td>
- * <td>The gadgetId that you supplied in the original intent.</td>
- * </tr>
- * </table>
- * <p>
- * When you receive the result from the gadget pick activity, if the resultCode is
- * {@link android.app.Activity#RESULT_OK}, a gadget has been selected. You should then
- * check the GadgetProviderInfo for the returned gadget, and if it has one, launch its configuration
- * activity. If {@link android.app.Activity#RESULT_CANCELED} is returned, you should delete
- * the gadgetId.
- *
- * @see #ACTION_GADGET_CONFIGURE
- */
- public static final String ACTION_GADGET_PICK = "android.gadget.action.GADGET_PICK";
-
- /**
- * Sent when it is time to configure your gadget while it is being added to a host.
- * This action is not sent as a broadcast to the gadget provider, but as a startActivity
- * to the activity specified in the {@link GadgetProviderInfo GadgetProviderInfo meta-data}.
- *
- * <p>
- * The intent will contain the following extras:
- * <table>
- * <tr>
- * <td>{@link #EXTRA_GADGET_ID}</td>
- * <td>The gadgetId to configure.</td>
- * </tr>
- * </table>
- *
- * <p>If you return {@link android.app.Activity#RESULT_OK} using
- * {@link android.app.Activity#setResult Activity.setResult()}, the gadget will be added,
- * and you will receive an {@link #ACTION_GADGET_UPDATE} broadcast for this gadget.
- * If you return {@link android.app.Activity#RESULT_CANCELED}, the host will cancel the add
- * and not display this gadget, and you will receive a {@link #ACTION_GADGET_DELETED} broadcast.
- */
- public static final String ACTION_GADGET_CONFIGURE = "android.gadget.action.GADGET_CONFIGURE";
-
- /**
- * An intent extra that contains one gadgetId.
- * <p>
- * The value will be an int that can be retrieved like this:
- * {@sample frameworks/base/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/GadgetHostActivity.java getExtra_EXTRA_GADGET_ID}
- */
- public static final String EXTRA_GADGET_ID = "gadgetId";
-
- /**
- * An intent extra that contains multiple gadgetIds.
- * <p>
- * The value will be an int array that can be retrieved like this:
- * {@sample frameworks/base/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/TestGadgetProvider.java getExtra_EXTRA_GADGET_IDS}
- */
- public static final String EXTRA_GADGET_IDS = "gadgetIds";
-
- /**
- * A sentiel value that the gadget manager will never return as a gadgetId.
- */
- public static final int INVALID_GADGET_ID = 0;
-
- /**
- * Sent when it is time to update your gadget.
- *
- * <p>This may be sent in response to a new instance for this gadget provider having
- * been instantiated, the requested {@link GadgetProviderInfo#updatePeriodMillis update interval}
- * having lapsed, or the system booting.
- *
- * <p>
- * The intent will contain the following extras:
- * <table>
- * <tr>
- * <td>{@link #EXTRA_GADGET_IDS}</td>
- * <td>The gadgetIds to update. This may be all of the gadgets created for this
- * provider, or just a subset. The system tries to send updates for as few gadget
- * instances as possible.</td>
- * </tr>
- * </table>
- *
- * @see GadgetProvider#onUpdate GadgetProvider.onUpdate(Context context, GadgetManager gadgetManager, int[] gadgetIds)
- */
- public static final String ACTION_GADGET_UPDATE = "android.gadget.action.GADGET_UPDATE";
-
- /**
- * Sent when an instance of a gadget is deleted from its host.
- *
- * @see GadgetProvider#onDeleted GadgetProvider.onDeleted(Context context, int[] gadgetIds)
- */
- public static final String ACTION_GADGET_DELETED = "android.gadget.action.GADGET_DELETED";
-
- /**
- * Sent when an instance of a gadget is removed from the last host.
- *
- * @see GadgetProvider#onEnabled GadgetProvider.onEnabled(Context context)
- */
- public static final String ACTION_GADGET_DISABLED = "android.gadget.action.GADGET_DISABLED";
-
- /**
- * Sent when an instance of a gadget is added to a host for the first time.
- * This broadcast is sent at boot time if there is a gadget host installed with
- * an instance for this provider.
- *
- * @see GadgetProvider#onEnabled GadgetProvider.onEnabled(Context context)
- */
- public static final String ACTION_GADGET_ENABLED = "android.gadget.action.GADGET_ENABLED";
-
- /**
- * Field for the manifest meta-data tag.
- *
- * @see GadgetProviderInfo
- */
- public static final String META_DATA_GADGET_PROVIDER = "android.gadget.provider";
-
- static WeakHashMap<Context, WeakReference<GadgetManager>> sManagerCache = new WeakHashMap();
- static IGadgetService sService;
-
- Context mContext;
-
- /**
- * Get the GadgetManager instance to use for the supplied {@link android.content.Context
- * Context} object.
- */
- public static GadgetManager getInstance(Context context) {
- synchronized (sManagerCache) {
- if (sService == null) {
- IBinder b = ServiceManager.getService(Context.GADGET_SERVICE);
- sService = IGadgetService.Stub.asInterface(b);
- }
-
- WeakReference<GadgetManager> ref = sManagerCache.get(context);
- GadgetManager result = null;
- if (ref != null) {
- result = ref.get();
- }
- if (result == null) {
- result = new GadgetManager(context);
- sManagerCache.put(context, new WeakReference(result));
- }
- return result;
- }
- }
-
- private GadgetManager(Context context) {
- mContext = context;
- }
-
- /**
- * Set the RemoteViews to use for the specified gadgetIds.
- *
- * <p>
- * It is okay to call this method both inside an {@link #ACTION_GADGET_UPDATE} broadcast,
- * and outside of the handler.
- * This method will only work when called from the uid that owns the gadget provider.
- *
- * @param gadgetIds The gadget instances for which to set the RemoteViews.
- * @param views The RemoteViews object to show.
- */
- public void updateGadget(int[] gadgetIds, RemoteViews views) {
- try {
- sService.updateGadgetIds(gadgetIds, views);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
- }
- }
-
- /**
- * Set the RemoteViews to use for the specified gadgetId.
- *
- * <p>
- * It is okay to call this method both inside an {@link #ACTION_GADGET_UPDATE} broadcast,
- * and outside of the handler.
- * This method will only work when called from the uid that owns the gadget provider.
- *
- * @param gadgetId The gadget instance for which to set the RemoteViews.
- * @param views The RemoteViews object to show.
- */
- public void updateGadget(int gadgetId, RemoteViews views) {
- updateGadget(new int[] { gadgetId }, views);
- }
-
- /**
- * Set the RemoteViews to use for all gadget instances for the supplied gadget provider.
- *
- * <p>
- * It is okay to call this method both inside an {@link #ACTION_GADGET_UPDATE} broadcast,
- * and outside of the handler.
- * This method will only work when called from the uid that owns the gadget provider.
- *
- * @param provider The {@link ComponentName} for the {@link
- * android.content.BroadcastReceiver BroadcastReceiver} provider
- * for your gadget.
- * @param views The RemoteViews object to show.
- */
- public void updateGadget(ComponentName provider, RemoteViews views) {
- try {
- sService.updateGadgetProvider(provider, views);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
- }
- }
-
- /**
- * Return a list of the gadget providers that are currently installed.
- */
- public List<GadgetProviderInfo> getInstalledProviders() {
- try {
- return sService.getInstalledProviders();
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
- }
- }
-
- /**
- * Get the available info about the gadget.
- *
- * @return A gadgetId. If the gadgetId has not been bound to a provider yet, or
- * you don't have access to that gadgetId, null is returned.
- */
- public GadgetProviderInfo getGadgetInfo(int gadgetId) {
- try {
- return sService.getGadgetInfo(gadgetId);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
- }
- }
-
- /**
- * Set the component for a given gadgetId.
- *
- * <p class="note">You need the GADGET_LIST permission. This method is to be used by the
- * gadget picker.
- *
- * @param gadgetId The gadget instance for which to set the RemoteViews.
- * @param provider The {@link android.content.BroadcastReceiver} that will be the gadget
- * provider for this gadget.
- */
- public void bindGadgetId(int gadgetId, ComponentName provider) {
- try {
- sService.bindGadgetId(gadgetId, provider);
- }
- catch (RemoteException e) {
- throw new RuntimeException("system server dead?", e);
- }
- }
-}
-
diff --git a/core/java/android/gadget/GadgetProvider.java b/core/java/android/gadget/GadgetProvider.java
deleted file mode 100755
index 7e10e78..0000000
--- a/core/java/android/gadget/GadgetProvider.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.gadget;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-
-/**
- * A conveience class to aid in implementing a gadget provider.
- * Everything you can do with GadgetProvider, you can do with a regular {@link BroadcastReceiver}.
- * GadgetProvider merely parses the relevant fields out of the Intent that is received in
- * {@link #onReceive(Context,Intent) onReceive(Context,Intent)}, and calls hook methods
- * with the received extras.
- *
- * <p>Extend this class and override one or more of the {@link #onUpdate}, {@link #onDeleted},
- * {@link #onEnabled} or {@link #onDisabled} methods to implement your own gadget functionality.
- *
- * <h3>Sample Code</h3>
- * For an example of how to write a gadget provider, see the
- * <a href="{@toroot}reference/android/gadget/package-descr.html#providers">android.gadget
- * package overview</a>.
- */
-public class GadgetProvider extends BroadcastReceiver {
- /**
- * Constructor to initialize GadgetProvider.
- */
- public GadgetProvider() {
- }
-
- /**
- * Implements {@link BroadcastReceiver#onReceive} to dispatch calls to the various
- * other methods on GadgetProvider.
- *
- * @param context The Context in which the receiver is running.
- * @param intent The Intent being received.
- */
- // BEGIN_INCLUDE(onReceive)
- public void onReceive(Context context, Intent intent) {
- // Protect against rogue update broadcasts (not really a security issue,
- // just filter bad broacasts out so subclasses are less likely to crash).
- String action = intent.getAction();
- if (GadgetManager.ACTION_GADGET_UPDATE.equals(action)) {
- Bundle extras = intent.getExtras();
- if (extras != null) {
- int[] gadgetIds = extras.getIntArray(GadgetManager.EXTRA_GADGET_IDS);
- if (gadgetIds != null && gadgetIds.length > 0) {
- this.onUpdate(context, GadgetManager.getInstance(context), gadgetIds);
- }
- }
- }
- else if (GadgetManager.ACTION_GADGET_DELETED.equals(action)) {
- Bundle extras = intent.getExtras();
- if (extras != null) {
- int[] gadgetIds = extras.getIntArray(GadgetManager.EXTRA_GADGET_IDS);
- if (gadgetIds != null && gadgetIds.length > 0) {
- this.onDeleted(context, gadgetIds);
- }
- }
- }
- else if (GadgetManager.ACTION_GADGET_ENABLED.equals(action)) {
- this.onEnabled(context);
- }
- else if (GadgetManager.ACTION_GADGET_DISABLED.equals(action)) {
- this.onDisabled(context);
- }
- }
- // END_INCLUDE(onReceive)
-
- /**
- * Called in response to the {@link GadgetManager#ACTION_GADGET_UPDATE} broadcast when
- * this gadget provider is being asked to provide {@link android.widget.RemoteViews RemoteViews}
- * for a set of gadgets. Override this method to implement your own gadget functionality.
- *
- * {@more}
- *
- * @param context The {@link android.content.Context Context} in which this receiver is
- * running.
- * @param gadgetManager A {@link GadgetManager} object you can call {@link
- * GadgetManager#updateGadget} on.
- * @param gadgetIds The gadgetsIds for which an update is needed. Note that this
- * may be all of the gadget instances for this provider, or just
- * a subset of them.
- *
- * @see GadgetManager#ACTION_GADGET_UPDATE
- */
- public void onUpdate(Context context, GadgetManager gadgetManager, int[] gadgetIds) {
- }
-
- /**
- * Called in response to the {@link GadgetManager#ACTION_GADGET_DELETED} broadcast when
- * one or more gadget instances have been deleted. Override this method to implement
- * your own gadget functionality.
- *
- * {@more}
- *
- * @param context The {@link android.content.Context Context} in which this receiver is
- * running.
- * @param gadgetIds The gadgetsIds that have been deleted from their host.
- *
- * @see GadgetManager#ACTION_GADGET_DELETED
- */
- public void onDeleted(Context context, int[] gadgetIds) {
- }
-
- /**
- * Called in response to the {@link GadgetManager#ACTION_GADGET_ENABLED} broadcast when
- * the a gadget for this provider is instantiated. Override this method to implement your
- * own gadget functionality.
- *
- * {@more}
- * When the last gadget for this provider is deleted,
- * {@link GadgetManager#ACTION_GADGET_DISABLED} is sent by the gadget manager, and
- * {@link #onDisabled} is called. If after that, a gadget for this provider is created
- * again, onEnabled() will be called again.
- *
- * @param context The {@link android.content.Context Context} in which this receiver is
- * running.
- *
- * @see GadgetManager#ACTION_GADGET_ENABLED
- */
- public void onEnabled(Context context) {
- }
-
- /**
- * Called in response to the {@link GadgetManager#ACTION_GADGET_DISABLED} broadcast, which
- * is sent when the last gadget instance for this provider is deleted. Override this method
- * to implement your own gadget functionality.
- *
- * {@more}
- *
- * @param context The {@link android.content.Context Context} in which this receiver is
- * running.
- *
- * @see GadgetManager#ACTION_GADGET_DISABLED
- */
- public void onDisabled(Context context) {
- }
-}
diff --git a/core/java/android/gadget/GadgetProviderInfo.aidl b/core/java/android/gadget/GadgetProviderInfo.aidl
deleted file mode 100644
index 589f886..0000000
--- a/core/java/android/gadget/GadgetProviderInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2007, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.gadget;
-
-parcelable GadgetProviderInfo;
diff --git a/core/java/android/gadget/GadgetProviderInfo.java b/core/java/android/gadget/GadgetProviderInfo.java
deleted file mode 100644
index 95c0432..0000000
--- a/core/java/android/gadget/GadgetProviderInfo.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.gadget;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.content.ComponentName;
-
-/**
- * Describes the meta data for an installed gadget provider. The fields in this class
- * correspond to the fields in the <code>&lt;gadget-provider&gt;</code> xml tag.
- */
-public class GadgetProviderInfo implements Parcelable {
- /**
- * Identity of this gadget component. This component should be a {@link
- * android.content.BroadcastReceiver}, and it will be sent the Gadget intents
- * {@link android.gadget as described in the gadget package documentation}.
- *
- * <p>This field corresponds to the <code>android:name</code> attribute in
- * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
- */
- public ComponentName provider;
-
- /**
- * Minimum width of the gadget, in dp.
- *
- * <p>This field corresponds to the <code>android:minWidth</code> attribute in
- * the gadget meta-data file.
- */
- public int minWidth;
-
- /**
- * Minimum height of the gadget, in dp.
- *
- * <p>This field corresponds to the <code>android:minHeight</code> attribute in
- * the gadget meta-data file.
- */
- public int minHeight;
-
- /**
- * How often, in milliseconds, that this gadget wants to be updated.
- * The gadget manager may place a limit on how often a gadget is updated.
- *
- * <p>This field corresponds to the <code>android:updatePeriodMillis</code> attribute in
- * the gadget meta-data file.
- */
- public int updatePeriodMillis;
-
- /**
- * The resource id of the initial layout for this gadget. This should be
- * displayed until the RemoteViews for the gadget is available.
- *
- * <p>This field corresponds to the <code>android:initialLayout</code> attribute in
- * the gadget meta-data file.
- */
- public int initialLayout;
-
- /**
- * The activity to launch that will configure the gadget.
- *
- * <p>This class name of field corresponds to the <code>android:configure</code> attribute in
- * the gadget meta-data file. The package name always corresponds to the package containing
- * the gadget provider.
- */
- public ComponentName configure;
-
- /**
- * The label to display to the user in the gadget picker. If not supplied in the
- * xml, the application label will be used.
- *
- * <p>This field corresponds to the <code>android:label</code> attribute in
- * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
- */
- public String label;
-
- /**
- * The icon to display for this gadget in the gadget picker. If not supplied in the
- * xml, the application icon will be used.
- *
- * <p>This field corresponds to the <code>android:icon</code> attribute in
- * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
- */
- public int icon;
-
- public GadgetProviderInfo() {
- }
-
- /**
- * Unflatten the GadgetProviderInfo from a parcel.
- */
- public GadgetProviderInfo(Parcel in) {
- if (0 != in.readInt()) {
- this.provider = new ComponentName(in);
- }
- this.minWidth = in.readInt();
- this.minHeight = in.readInt();
- this.updatePeriodMillis = in.readInt();
- this.initialLayout = in.readInt();
- if (0 != in.readInt()) {
- this.configure = new ComponentName(in);
- }
- this.label = in.readString();
- this.icon = in.readInt();
- }
-
-
- public void writeToParcel(android.os.Parcel out, int flags) {
- if (this.provider != null) {
- out.writeInt(1);
- this.provider.writeToParcel(out, flags);
- } else {
- out.writeInt(0);
- }
- out.writeInt(this.minWidth);
- out.writeInt(this.minHeight);
- out.writeInt(this.updatePeriodMillis);
- out.writeInt(this.initialLayout);
- if (this.configure != null) {
- out.writeInt(1);
- this.configure.writeToParcel(out, flags);
- } else {
- out.writeInt(0);
- }
- out.writeString(this.label);
- out.writeInt(this.icon);
- }
-
- public int describeContents() {
- return 0;
- }
-
- /**
- * Parcelable.Creator that instantiates GadgetProviderInfo objects
- */
- public static final Parcelable.Creator<GadgetProviderInfo> CREATOR
- = new Parcelable.Creator<GadgetProviderInfo>()
- {
- public GadgetProviderInfo createFromParcel(Parcel parcel)
- {
- return new GadgetProviderInfo(parcel);
- }
-
- public GadgetProviderInfo[] newArray(int size)
- {
- return new GadgetProviderInfo[size];
- }
- };
-
- public String toString() {
- return "GadgetProviderInfo(provider=" + this.provider + ")";
- }
-}
-
-
diff --git a/core/java/android/gadget/package.html b/core/java/android/gadget/package.html
deleted file mode 100644
index 4c04396..0000000
--- a/core/java/android/gadget/package.html
+++ /dev/null
@@ -1,136 +0,0 @@
-<body>
-<p>Android allows applications to publish views to be embedded in other applications. These
-views are called gadgets, and are published by "gadget providers." The component that can
-contain gadgets is called a "gadget host."
-</p>
-<h3><a href="package-descr.html#providers">Gadget Providers</a></h3>
-<ul>
- <li><a href="package-descr.html#provider_manifest">Declaring a gadget in the AndroidManifest</a></li>
- <li><a href="package-descr.html#provider_meta_data">Adding the GadgetProviderInfo meta-data</a></li>
- <li><a href="package-descr.html#provider_GadgetProvider">Using the GadgetProvider class</a></li>
- <li><a href="package-descr.html#provider_configuration">Gadget Configuration UI</a></li>
- <li><a href="package-descr.html#provider_broadcasts">Gadget Broadcast Intents</a></li>
-</ul>
-<h3><a href="package-descr.html#">Gadget Hosts</a></h3>
-
-
-{@more}
-
-
-<h2><a name="providers"></a>Gadget Providers</h2>
-<p>
-Any application can publish gadgets. All an application needs to do to publish a gadget is
-to have a {@link android.content.BroadcastReceiver} that receives the {@link
-android.gadget.GadgetManager#ACTION_GADGET_UPDATE GadgetManager.ACTION_GADGET_UPDATE} intent,
-and provide some meta-data about the gadget. Android provides the
-{@link android.gadget.GadgetProvider} class, which extends BroadcastReceiver, as a convenience
-class to aid in handling the broadcasts.
-
-<h3><a name="provider_manifest"></a>Declaring a gadget in the AndroidManifest</h3>
-
-<p>
-First, declare the {@link android.content.BroadcastReceiver} in your application's
-<code>AndroidManifest.xml</code> file.
-
-{@sample frameworks/base/tests/gadgets/GadgetHostTest/AndroidManifest.xml GadgetProvider}
-
-<p>
-The <b><code>&lt;receiver&gt;</b> element has the following attributes:
-<ul>
- <li><b><code>android:name</code> -</b> which specifies the
- {@link android.content.BroadcastReceiver} or {@link android.gadget.GadgetProvider}
- class.</li>
- <li><b><code>android:label</code> -</b> which specifies the string resource that
- will be shown by the gadget picker as the label.</li>
- <li><b><code>android:icon</code> -</b> which specifies the drawable resource that
- will be shown by the gadget picker as the icon.</li>
-</ul>
-
-<p>
-The <b><code>&lt;intent-filter&gt;</b> element tells the {@link android.content.pm.PackageManager}
-that this {@link android.content.BroadcastReceiver} receives the {@link
-android.gadget.GadgetManager#ACTION_GADGET_UPDATE GadgetManager.ACTION_GADGET_UPDATE} broadcast.
-The gadget manager will send other broadcasts directly to your gadget provider as required.
-It is only necessary to explicitly declare that you accept the {@link
-android.gadget.GadgetManager#ACTION_GADGET_UPDATE GadgetManager.ACTION_GADGET_UPDATE} broadcast.
-
-<p>
-The <b><code>&lt;meta-data&gt;</code></b> element tells the gadget manager which xml resource to
-read to find the {@link android.gadget.GadgetProviderInfo} for your gadget provider. It has the following
-attributes:
-<ul>
- <li><b><code>android:name="android.gadget.provider"</code> -</b> identifies this meta-data
- as the {@link android.gadget.GadgetProviderInfo} descriptor.</li>
- <li><b><code>android:resource</code> -</b> is the xml resource to use as that descriptor.</li>
-</ul>
-
-
-<h3><a name="provider_meta_data"></a>Adding the {@link android.gadget.GadgetProviderInfo GadgetProviderInfo} meta-data</h3>
-
-<p>
-For a gadget, the values in the {@link android.gadget.GadgetProviderInfo} structure are supplied
-in an XML resource. In the example above, the xml resource is referenced with
-<code>android:resource="@xml/gadget_info"</code>. That XML file would go in your application's
-directory at <code>res/xml/gadget_info.xml</code>. Here is a simple example.
-
-{@sample frameworks/base/tests/gadgets/GadgetHostTest/res/xml/gadget_info.xml GadgetProviderInfo}
-
-<p>
-The attributes are as documented in the {@link android.gadget.GadgetProviderInfo GagetInfo} class. (86400000 milliseconds means once per day)
-
-
-<h3><a name="provider_GadgetProvider"></a>Using the {@link android.gadget.GadgetProvider GadgetProvider} class</h3>
-
-<p>The GadgetProvider class is the easiest way to handle the gadget provider intent broadcasts.
-See the <code>src/com/example/android/apis/gadget/ExampleGadgetProvider.java</code>
-sample class in ApiDemos for an example.
-
-<p class="note">Keep in mind that since the the GadgetProvider is a BroadcastReceiver,
-your process is not guaranteed to keep running after the callback methods return. See
-<a href="../../../guide/topics/fundamentals.html#broadlife">Application Fundamentals &gt;
-Broadcast Receiver Lifecycle</a> for more information.
-
-
-
-<h3><a name="provider_configuration"></a>Gadget Configuration UI</h3>
-
-<p>
-Gadget hosts have the ability to start a configuration activity when a gadget is instantiated.
-The activity should be declared as normal in AndroidManifest.xml, and it should be listed in
-the GadgetProviderInfo XML file in the <code>android:configure</code> attribute.
-
-<p>The activity you specified will be launched with the {@link
-android.gadget.GadgetManager#ACTION_GADGET_CONFIGURE} action. See the documentation for that
-action for more info.
-
-<p>See the <code>src/com/example/android/apis/gadget/ExampleGadgetConfigure.java</code>
-sample class in ApiDemos for an example.
-
-
-
-<h3><a name="providers_broadcasts"></a>Gadget Broadcast Intents</h3>
-
-<p>{@link android.gadget.GadgetProvider} is just a convenience class. If you would like
-to receive the gadget broadcasts directly, you can. The four intents you need to care about are:
-<ul>
- <li>{@link android.gadget.GadgetManager#ACTION_GADGET_UPDATE}</li>
- <li>{@link android.gadget.GadgetManager#ACTION_GADGET_DELETED}</li>
- <li>{@link android.gadget.GadgetManager#ACTION_GADGET_ENABLED}</li>
- <li>{@link android.gadget.GadgetManager#ACTION_GADGET_DISABLED}</li>
-</ul>
-
-<p>By way of example, the implementation of
-{@link android.gadget.GadgetProvider#onReceive} is quite simple:</p>
-
-{@sample frameworks/base/core/java/android/gadget/GadgetProvider.java onReceive}
-
-
-<h2>Gadget Hosts</h3>
-<p>Gadget hosts are the containers in which gadgets can be placed. Most of the look and feel
-details are left up to the gadget hosts. For example, the home screen has one way of viewing
-gadgets, but the lock screen could also contain gadgets, and it would have a different way of
-adding, removing and otherwise managing gadgets.</p>
-<p>For more information on implementing your own gadget host, see the
-{@link android.gadget.GadgetHost GadgetHost} class.</p>
-</body>
-
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
deleted file mode 100644
index 40a5b47..0000000
--- a/core/java/android/hardware/Camera.java
+++ /dev/null
@@ -1,782 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware;
-
-import java.lang.ref.WeakReference;
-import java.util.HashMap;
-import java.util.StringTokenizer;
-import java.io.IOException;
-
-import android.util.Log;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import android.graphics.PixelFormat;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-
-/**
- * The Camera class is used to connect/disconnect with the camera service,
- * set capture settings, start/stop preview, snap a picture, and retrieve
- * frames for encoding for video.
- * <p>There is no default constructor for this class. Use {@link #open()} to
- * get a Camera object.</p>
- */
-public class Camera {
- private static final String TAG = "Camera";
-
- // These match the enum in libs/android_runtime/android_hardware_Camera.cpp
- private static final int SHUTTER_CALLBACK = 0;
- private static final int RAW_PICTURE_CALLBACK = 1;
- private static final int JPEG_PICTURE_CALLBACK = 2;
- private static final int PREVIEW_CALLBACK = 3;
- private static final int AUTOFOCUS_CALLBACK = 4;
- private static final int ERROR_CALLBACK = 5;
-
- private int mNativeContext; // accessed by native methods
- private int mListenerContext;
- private EventHandler mEventHandler;
- private ShutterCallback mShutterCallback;
- private PictureCallback mRawImageCallback;
- private PictureCallback mJpegCallback;
- private PreviewCallback mPreviewCallback;
- private AutoFocusCallback mAutoFocusCallback;
- private ErrorCallback mErrorCallback;
- private boolean mOneShot;
-
- /**
- * Returns a new Camera object.
- */
- public static Camera open() {
- return new Camera();
- }
-
- Camera() {
- mShutterCallback = null;
- mRawImageCallback = null;
- mJpegCallback = null;
- mPreviewCallback = null;
-
- Looper looper;
- if ((looper = Looper.myLooper()) != null) {
- mEventHandler = new EventHandler(this, looper);
- } else if ((looper = Looper.getMainLooper()) != null) {
- mEventHandler = new EventHandler(this, looper);
- } else {
- mEventHandler = null;
- }
-
- native_setup(new WeakReference<Camera>(this));
- }
-
- protected void finalize() {
- native_release();
- }
-
- private native final void native_setup(Object camera_this);
- private native final void native_release();
-
-
- /**
- * Disconnects and releases the Camera object resources.
- * <p>It is recommended that you call this as soon as you're done with the
- * Camera object.</p>
- */
- public final void release() {
- native_release();
- }
-
- /**
- * Reconnect to the camera after passing it to MediaRecorder. To save
- * setup/teardown time, a client of Camera can pass an initialized Camera
- * object to a MediaRecorder to use for video recording. Once the
- * MediaRecorder is done with the Camera, this method can be used to
- * re-establish a connection with the camera hardware. NOTE: The Camera
- * object must first be unlocked by the process that owns it before it
- * can be connected to another proces.
- *
- * @throws IOException if the method fails.
- *
- * FIXME: Unhide after approval
- * @hide
- */
- public native final void reconnect() throws IOException;
-
- /**
- * Lock the camera to prevent other processes from accessing it. To save
- * setup/teardown time, a client of Camera can pass an initialized Camera
- * object to another process. This method is used to re-lock the Camera
- * object prevent other processes from accessing it. By default, the
- * Camera object is locked. Locking it again from the same process will
- * have no effect. Attempting to lock it from another process if it has
- * not been unlocked will fail.
- * Returns 0 if lock was successful.
- *
- * FIXME: Unhide after approval
- * @hide
- */
- public native final int lock();
-
- /**
- * Unlock the camera to allow aother process to access it. To save
- * setup/teardown time, a client of Camera can pass an initialized Camera
- * object to another process. This method is used to unlock the Camera
- * object before handing off the Camera object to the other process.
-
- * Returns 0 if unlock was successful.
- *
- * FIXME: Unhide after approval
- * @hide
- */
- public native final int unlock();
-
- /**
- * Sets the SurfaceHolder to be used for a picture preview. If the surface
- * changed since the last call, the screen will blank. Nothing happens
- * if the same surface is re-set.
- *
- * @param holder the SurfaceHolder upon which to place the picture preview
- * @throws IOException if the method fails.
- */
- public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {
- setPreviewDisplay(holder.getSurface());
- }
-
- private native final void setPreviewDisplay(Surface surface);
-
- /**
- * Used to get a copy of each preview frame.
- */
- public interface PreviewCallback
- {
- /**
- * The callback that delivers the preview frames.
- *
- * @param data The contents of the preview frame in getPreviewFormat()
- * format.
- * @param camera The Camera service object.
- */
- void onPreviewFrame(byte[] data, Camera camera);
- };
-
- /**
- * Start drawing preview frames to the surface.
- */
- public native final void startPreview();
-
- /**
- * Stop drawing preview frames to the surface.
- */
- public native final void stopPreview();
-
- /**
- * Return current preview state.
- *
- * FIXME: Unhide before release
- * @hide
- */
- public native final boolean previewEnabled();
-
- /**
- * Can be called at any time to instruct the camera to use a callback for
- * each preview frame in addition to displaying it.
- *
- * @param cb A callback object that receives a copy of each preview frame.
- * Pass null to stop receiving callbacks at any time.
- */
- public final void setPreviewCallback(PreviewCallback cb) {
- mPreviewCallback = cb;
- mOneShot = false;
- setHasPreviewCallback(cb != null, false);
- }
-
- /**
- * Installs a callback to retrieve a single preview frame, after which the
- * callback is cleared.
- *
- * @param cb A callback object that receives a copy of the preview frame.
- */
- public final void setOneShotPreviewCallback(PreviewCallback cb) {
- if (cb != null) {
- mPreviewCallback = cb;
- mOneShot = true;
- setHasPreviewCallback(true, true);
- }
- }
-
- private native final void setHasPreviewCallback(boolean installed, boolean oneshot);
-
- private class EventHandler extends Handler
- {
- private Camera mCamera;
-
- public EventHandler(Camera c, Looper looper) {
- super(looper);
- mCamera = c;
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch(msg.what) {
- case SHUTTER_CALLBACK:
- if (mShutterCallback != null) {
- mShutterCallback.onShutter();
- }
- return;
- case RAW_PICTURE_CALLBACK:
- if (mRawImageCallback != null)
- mRawImageCallback.onPictureTaken((byte[])msg.obj, mCamera);
- return;
-
- case JPEG_PICTURE_CALLBACK:
- if (mJpegCallback != null)
- mJpegCallback.onPictureTaken((byte[])msg.obj, mCamera);
- return;
-
- case PREVIEW_CALLBACK:
- if (mPreviewCallback != null) {
- mPreviewCallback.onPreviewFrame((byte[])msg.obj, mCamera);
- if (mOneShot) {
- mPreviewCallback = null;
- }
- }
- return;
-
- case AUTOFOCUS_CALLBACK:
- if (mAutoFocusCallback != null)
- mAutoFocusCallback.onAutoFocus(msg.arg1 == 0 ? false : true, mCamera);
- return;
-
- case ERROR_CALLBACK:
- Log.e(TAG, "Error " + msg.arg1);
- if (mErrorCallback != null)
- mErrorCallback.onError(msg.arg1, mCamera);
- return;
-
- default:
- Log.e(TAG, "Unknown message type " + msg.what);
- return;
- }
- }
- }
-
- private static void postEventFromNative(Object camera_ref,
- int what, int arg1, int arg2, Object obj)
- {
- Camera c = (Camera)((WeakReference)camera_ref).get();
- if (c == null)
- return;
-
- if (c.mEventHandler != null) {
- Message m = c.mEventHandler.obtainMessage(what, arg1, arg2, obj);
- c.mEventHandler.sendMessage(m);
- }
- }
-
- /**
- * Handles the callback for the camera auto focus.
- */
- public interface AutoFocusCallback
- {
- /**
- * Callback for the camera auto focus.
- *
- * @param success true if focus was successful, false if otherwise
- * @param camera the Camera service object
- */
- void onAutoFocus(boolean success, Camera camera);
- };
-
- /**
- * Starts auto-focus function and registers a callback function to
- * run when camera is focused. Only valid after startPreview() has
- * been called.
- *
- * @param cb the callback to run
- */
- public final void autoFocus(AutoFocusCallback cb)
- {
- mAutoFocusCallback = cb;
- native_autoFocus();
- }
- private native final void native_autoFocus();
-
- /**
- * An interface which contains a callback for the shutter closing after taking a picture.
- */
- public interface ShutterCallback
- {
- /**
- * Can be used to play a shutter sound as soon as the image has been captured, but before
- * the data is available.
- */
- void onShutter();
- }
-
- /**
- * Handles the callback for when a picture is taken.
- */
- public interface PictureCallback {
- /**
- * Callback for when a picture is taken.
- *
- * @param data a byte array of the picture data
- * @param camera the Camera service object
- */
- void onPictureTaken(byte[] data, Camera camera);
- };
-
- /**
- * Triggers an asynchronous image capture. The camera service
- * will initiate a series of callbacks to the application as the
- * image capture progresses. The shutter callback occurs after
- * the image is captured. This can be used to trigger a sound
- * to let the user know that image has been captured. The raw
- * callback occurs when the raw image data is available. The jpeg
- * callback occurs when the compressed image is available. If the
- * application does not need a particular callback, a null can be
- * passed instead of a callback method.
- *
- * @param shutter callback after the image is captured, may be null
- * @param raw callback with raw image data, may be null
- * @param jpeg callback with jpeg image data, may be null
- */
- public final void takePicture(ShutterCallback shutter, PictureCallback raw,
- PictureCallback jpeg) {
- mShutterCallback = shutter;
- mRawImageCallback = raw;
- mJpegCallback = jpeg;
- native_takePicture();
- }
- private native final void native_takePicture();
-
- // These match the enum in libs/android_runtime/android_hardware_Camera.cpp
- /** Unspecified camerar error. @see #ErrorCallback */
- public static final int CAMERA_ERROR_UNKNOWN = 1;
- /** Media server died. In this case, the application must release the
- * Camera object and instantiate a new one. @see #ErrorCallback */
- public static final int CAMERA_ERROR_SERVER_DIED = 100;
-
- /**
- * Handles the camera error callback.
- */
- public interface ErrorCallback
- {
- /**
- * Callback for camera errors.
- * @param error error code:
- * <ul>
- * <li>{@link #CAMERA_ERROR_UNKNOWN}
- * <li>{@link #CAMERA_ERROR_SERVER_DIED}
- * </ul>
- * @param camera the Camera service object
- */
- void onError(int error, Camera camera);
- };
-
- /**
- * Registers a callback to be invoked when an error occurs.
- * @param cb the callback to run
- */
- public final void setErrorCallback(ErrorCallback cb)
- {
- mErrorCallback = cb;
- }
-
- private native final void native_setParameters(String params);
- private native final String native_getParameters();
-
- /**
- * Sets the Parameters for pictures from this Camera service.
- *
- * @param params the Parameters to use for this Camera service
- */
- public void setParameters(Parameters params) {
- Log.e(TAG, "setParameters()");
- //params.dump();
- native_setParameters(params.flatten());
- }
-
- /**
- * Returns the picture Parameters for this Camera service.
- */
- public Parameters getParameters() {
- Parameters p = new Parameters();
- String s = native_getParameters();
- Log.e(TAG, "_getParameters: " + s);
- p.unflatten(s);
- return p;
- }
-
- /**
- * Handles the picture size (dimensions).
- */
- public class Size {
- /**
- * Sets the dimensions for pictures.
- *
- * @param w the photo width (pixels)
- * @param h the photo height (pixels)
- */
- public Size(int w, int h) {
- width = w;
- height = h;
- }
- /** width of the picture */
- public int width;
- /** height of the picture */
- public int height;
- };
-
- /**
- * Handles the parameters for pictures created by a Camera service.
- */
- public class Parameters {
- private HashMap<String, String> mMap;
-
- private Parameters() {
- mMap = new HashMap<String, String>();
- }
-
- /**
- * Writes the current Parameters to the log.
- * @hide
- * @deprecated
- */
- public void dump() {
- Log.e(TAG, "dump: size=" + mMap.size());
- for (String k : mMap.keySet()) {
- Log.e(TAG, "dump: " + k + "=" + mMap.get(k));
- }
- }
-
- /**
- * Creates a single string with all the parameters set in
- * this Parameters object.
- * <p>The {@link #unflatten(String)} method does the reverse.</p>
- *
- * @return a String with all values from this Parameters object, in
- * semi-colon delimited key-value pairs
- */
- public String flatten() {
- StringBuilder flattened = new StringBuilder();
- for (String k : mMap.keySet()) {
- flattened.append(k);
- flattened.append("=");
- flattened.append(mMap.get(k));
- flattened.append(";");
- }
- // chop off the extra semicolon at the end
- flattened.deleteCharAt(flattened.length()-1);
- return flattened.toString();
- }
-
- /**
- * Takes a flattened string of parameters and adds each one to
- * this Parameters object.
- * <p>The {@link #flatten()} method does the reverse.</p>
- *
- * @param flattened a String of parameters (key-value paired) that
- * are semi-colon delimited
- */
- public void unflatten(String flattened) {
- mMap.clear();
-
- StringTokenizer tokenizer = new StringTokenizer(flattened, ";");
- while (tokenizer.hasMoreElements()) {
- String kv = tokenizer.nextToken();
- int pos = kv.indexOf('=');
- if (pos == -1) {
- continue;
- }
- String k = kv.substring(0, pos);
- String v = kv.substring(pos + 1);
- mMap.put(k, v);
- }
- }
-
- public void remove(String key) {
- mMap.remove(key);
- }
-
- /**
- * Sets a String parameter.
- *
- * @param key the key name for the parameter
- * @param value the String value of the parameter
- */
- public void set(String key, String value) {
- if (key.indexOf('=') != -1 || key.indexOf(';') != -1) {
- Log.e(TAG, "Key \"" + key + "\" contains invalid character (= or ;)");
- return;
- }
- if (value.indexOf('=') != -1 || value.indexOf(';') != -1) {
- Log.e(TAG, "Value \"" + value + "\" contains invalid character (= or ;)");
- return;
- }
-
- mMap.put(key, value);
- }
-
- /**
- * Sets an integer parameter.
- *
- * @param key the key name for the parameter
- * @param value the int value of the parameter
- */
- public void set(String key, int value) {
- mMap.put(key, Integer.toString(value));
- }
-
- /**
- * Returns the value of a String parameter.
- *
- * @param key the key name for the parameter
- * @return the String value of the parameter
- */
- public String get(String key) {
- return mMap.get(key);
- }
-
- /**
- * Returns the value of an integer parameter.
- *
- * @param key the key name for the parameter
- * @return the int value of the parameter
- */
- public int getInt(String key) {
- return Integer.parseInt(mMap.get(key));
- }
-
- /**
- * Sets the dimensions for preview pictures.
- *
- * @param width the width of the pictures, in pixels
- * @param height the height of the pictures, in pixels
- */
- public void setPreviewSize(int width, int height) {
- String v = Integer.toString(width) + "x" + Integer.toString(height);
- set("preview-size", v);
- }
-
- /**
- * Returns the dimensions setting for preview pictures.
- *
- * @return a Size object with the height and width setting
- * for the preview picture
- */
- public Size getPreviewSize() {
- String pair = get("preview-size");
- if (pair == null)
- return null;
- String[] dims = pair.split("x");
- if (dims.length != 2)
- return null;
-
- return new Size(Integer.parseInt(dims[0]),
- Integer.parseInt(dims[1]));
-
- }
-
- /**
- * Sets the dimensions for EXIF thumbnails.
- *
- * @param width the width of the thumbnail, in pixels
- * @param height the height of the thumbnail, in pixels
- *
- * FIXME: unhide before release
- * @hide
- */
- public void setThumbnailSize(int width, int height) {
- set("jpeg-thumbnail-width", width);
- set("jpeg-thumbnail-height", height);
- }
-
- /**
- * Returns the dimensions for EXIF thumbnail
- *
- * @return a Size object with the height and width setting
- * for the EXIF thumbnails
- *
- * FIXME: unhide before release
- * @hide
- */
- public Size getThumbnailSize() {
- return new Size(getInt("jpeg-thumbnail-width"),
- getInt("jpeg-thumbnail-height"));
- }
-
- /**
- * Sets the quality of the EXIF thumbnail
- *
- * @param quality the JPEG quality of the EXIT thumbnail
- *
- * FIXME: unhide before release
- * @hide
- */
- public void setThumbnailQuality(int quality) {
- set("jpeg-thumbnail-quality", quality);
- }
-
- /**
- * Returns the quality setting for the EXIF thumbnail
- *
- * @return the JPEG quality setting of the EXIF thumbnail
- *
- * FIXME: unhide before release
- * @hide
- */
- public int getThumbnailQuality() {
- return getInt("jpeg-thumbnail-quality");
- }
-
- /**
- * Sets the rate at which preview frames are received.
- *
- * @param fps the frame rate (frames per second)
- */
- public void setPreviewFrameRate(int fps) {
- set("preview-frame-rate", fps);
- }
-
- /**
- * Returns the setting for the rate at which preview frames
- * are received.
- *
- * @return the frame rate setting (frames per second)
- */
- public int getPreviewFrameRate() {
- return getInt("preview-frame-rate");
- }
-
- /**
- * Sets the image format for preview pictures.
- *
- * @param pixel_format the desired preview picture format
- * (<var>PixelFormat.YCbCr_420_SP</var>,
- * <var>PixelFormat.RGB_565</var>, or
- * <var>PixelFormat.JPEG</var>)
- * @see android.graphics.PixelFormat
- */
- public void setPreviewFormat(int pixel_format) {
- String s = cameraFormatForPixelFormat(pixel_format);
- if (s == null) {
- throw new IllegalArgumentException();
- }
-
- set("preview-format", s);
- }
-
- /**
- * Returns the image format for preview pictures.
- *
- * @return the PixelFormat int representing the preview picture format
- */
- public int getPreviewFormat() {
- return pixelFormatForCameraFormat(get("preview-format"));
- }
-
- /**
- * Sets the dimensions for pictures.
- *
- * @param width the width for pictures, in pixels
- * @param height the height for pictures, in pixels
- */
- public void setPictureSize(int width, int height) {
- String v = Integer.toString(width) + "x" + Integer.toString(height);
- set("picture-size", v);
- }
-
- /**
- * Returns the dimension setting for pictures.
- *
- * @return a Size object with the height and width setting
- * for pictures
- */
- public Size getPictureSize() {
- String pair = get("picture-size");
- if (pair == null)
- return null;
- String[] dims = pair.split("x");
- if (dims.length != 2)
- return null;
-
- return new Size(Integer.parseInt(dims[0]),
- Integer.parseInt(dims[1]));
-
- }
-
- /**
- * Sets the image format for pictures.
- *
- * @param pixel_format the desired picture format
- * (<var>PixelFormat.YCbCr_420_SP</var>,
- * <var>PixelFormat.RGB_565</var>, or
- * <var>PixelFormat.JPEG</var>)
- * @see android.graphics.PixelFormat
- */
- public void setPictureFormat(int pixel_format) {
- String s = cameraFormatForPixelFormat(pixel_format);
- if (s == null) {
- throw new IllegalArgumentException();
- }
-
- set("picture-format", s);
- }
-
- /**
- * Returns the image format for pictures.
- *
- * @return the PixelFormat int representing the picture format
- */
- public int getPictureFormat() {
- return pixelFormatForCameraFormat(get("picture-format"));
- }
-
- private String cameraFormatForPixelFormat(int pixel_format) {
- switch(pixel_format) {
- case PixelFormat.YCbCr_422_SP: return "yuv422sp";
- case PixelFormat.YCbCr_420_SP: return "yuv420sp";
- case PixelFormat.RGB_565: return "rgb565";
- case PixelFormat.JPEG: return "jpeg";
- default: return null;
- }
- }
-
- private int pixelFormatForCameraFormat(String format) {
- if (format == null)
- return PixelFormat.UNKNOWN;
-
- if (format.equals("yuv422sp"))
- return PixelFormat.YCbCr_422_SP;
-
- if (format.equals("yuv420sp"))
- return PixelFormat.YCbCr_420_SP;
-
- if (format.equals("rgb565"))
- return PixelFormat.RGB_565;
-
- if (format.equals("jpeg"))
- return PixelFormat.JPEG;
-
- return PixelFormat.UNKNOWN;
- }
-
- };
-}
-
-
diff --git a/core/java/android/hardware/GeomagneticField.java b/core/java/android/hardware/GeomagneticField.java
deleted file mode 100644
index b4c04b1..0000000
--- a/core/java/android/hardware/GeomagneticField.java
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware;
-
-import java.util.GregorianCalendar;
-
-/**
- * This class is used to estimated estimate magnetic field at a given point on
- * Earth, and in particular, to compute the magnetic declination from true
- * north.
- *
- * <p>This uses the World Magnetic Model produced by the United States National
- * Geospatial-Intelligence Agency. More details about the model can be found at
- * <a href="http://www.ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml">http://www.ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml</a>.
- * This class currently uses WMM-2005 which is valid until 2010, but should
- * produce acceptable results for several years after that.
- */
-public class GeomagneticField {
- // The magnetic field at a given point, in nonoteslas in geodetic
- // coordinates.
- private float mX;
- private float mY;
- private float mZ;
-
- // Geocentric coordinates -- set by computeGeocentricCoordinates.
- private float mGcLatitudeRad;
- private float mGcLongitudeRad;
- private float mGcRadiusKm;
-
- // Constants from WGS84 (the coordinate system used by GPS)
- static private final float EARTH_SEMI_MAJOR_AXIS_KM = 6378.137f;
- static private final float EARTH_SEMI_MINOR_AXIS_KM = 6356.7523f;
- static private final float EARTH_REFERENCE_RADIUS_KM = 6371.2f;
-
- // These coefficients and the formulae used below are from:
- // NOAA Technical Report: The US/UK World Magnetic Model for 2005-2010
- static private final float[][] G_COEFF = new float[][] {
- { 0f },
- { -29556.8f, -1671.7f },
- { -2340.6f, 3046.9f, 1657.0f },
- { 1335.4f, -2305.1f, 1246.7f, 674.0f },
- { 919.8f, 798.1f, 211.3f, -379.4f, 100.0f },
- { -227.4f, 354.6f, 208.7f, -136.5f, -168.3f, -14.1f },
- { 73.2f, 69.7f, 76.7f, -151.2f, -14.9f, 14.6f, -86.3f },
- { 80.1f, -74.5f, -1.4f, 38.5f, 12.4f, 9.5f, 5.7f, 1.8f },
- { 24.9f, 7.7f, -11.6f, -6.9f, -18.2f, 10.0f, 9.2f, -11.6f, -5.2f },
- { 5.6f, 9.9f, 3.5f, -7.0f, 5.1f, -10.8f, -1.3f, 8.8f, -6.7f, -9.1f },
- { -2.3f, -6.3f, 1.6f, -2.6f, 0.0f, 3.1f, 0.4f, 2.1f, 3.9f, -0.1f, -2.3f },
- { 2.8f, -1.6f, -1.7f, 1.7f, -0.1f, 0.1f, -0.7f, 0.7f, 1.8f, 0.0f, 1.1f, 4.1f },
- { -2.4f, -0.4f, 0.2f, 0.8f, -0.3f, 1.1f, -0.5f, 0.4f, -0.3f, -0.3f, -0.1f,
- -0.3f, -0.1f } };
-
- static private final float[][] H_COEFF = new float[][] {
- { 0f },
- { 0.0f, 5079.8f },
- { 0.0f, -2594.7f, -516.7f },
- { 0.0f, -199.9f, 269.3f, -524.2f },
- { 0.0f, 281.5f, -226.0f, 145.8f, -304.7f },
- { 0.0f, 42.4f, 179.8f, -123.0f, -19.5f, 103.6f },
- { 0.0f, -20.3f, 54.7f, 63.6f, -63.4f, -0.1f, 50.4f },
- { 0.0f, -61.5f, -22.4f, 7.2f, 25.4f, 11.0f, -26.4f, -5.1f },
- { 0.0f, 11.2f, -21.0f, 9.6f, -19.8f, 16.1f, 7.7f, -12.9f, -0.2f },
- { 0.0f, -20.1f, 12.9f, 12.6f, -6.7f, -8.1f, 8.0f, 2.9f, -7.9f, 6.0f },
- { 0.0f, 2.4f, 0.2f, 4.4f, 4.8f, -6.5f, -1.1f, -3.4f, -0.8f, -2.3f, -7.9f },
- { 0.0f, 0.3f, 1.2f, -0.8f, -2.5f, 0.9f, -0.6f, -2.7f, -0.9f, -1.3f, -2.0f, -1.2f },
- { 0.0f, -0.4f, 0.3f, 2.4f, -2.6f, 0.6f, 0.3f, 0.0f, 0.0f, 0.3f, -0.9f, -0.4f,
- 0.8f } };
-
- static private final float[][] DELTA_G = new float[][] {
- { 0f },
- { 8.0f, 10.6f },
- { -15.1f, -7.8f, -0.8f },
- { 0.4f, -2.6f, -1.2f, -6.5f },
- { -2.5f, 2.8f, -7.0f, 6.2f, -3.8f },
- { -2.8f, 0.7f, -3.2f, -1.1f, 0.1f, -0.8f },
- { -0.7f, 0.4f, -0.3f, 2.3f, -2.1f, -0.6f, 1.4f },
- { 0.2f, -0.1f, -0.3f, 1.1f, 0.6f, 0.5f, -0.4f, 0.6f },
- { 0.1f, 0.3f, -0.4f, 0.3f, -0.3f, 0.2f, 0.4f, -0.7f, 0.4f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } };
-
- static private final float[][] DELTA_H = new float[][] {
- { 0f },
- { 0.0f, -20.9f },
- { 0.0f, -23.2f, -14.6f },
- { 0.0f, 5.0f, -7.0f, -0.6f },
- { 0.0f, 2.2f, 1.6f, 5.8f, 0.1f },
- { 0.0f, 0.0f, 1.7f, 2.1f, 4.8f, -1.1f },
- { 0.0f, -0.6f, -1.9f, -0.4f, -0.5f, -0.3f, 0.7f },
- { 0.0f, 0.6f, 0.4f, 0.2f, 0.3f, -0.8f, -0.2f, 0.1f },
- { 0.0f, -0.2f, 0.1f, 0.3f, 0.4f, 0.1f, -0.2f, 0.4f, 0.4f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } };
-
- static private final long BASE_TIME =
- new GregorianCalendar(2005, 1, 1).getTimeInMillis();
-
- // The ratio between the Gauss-normalized associated Legendre functions and
- // the Schmid quasi-normalized ones. Compute these once staticly since they
- // don't depend on input variables at all.
- static private final float[][] SCHMIDT_QUASI_NORM_FACTORS =
- computeSchmidtQuasiNormFactors(G_COEFF.length);
-
- /**
- * Estimate the magnetic field at a given point and time.
- *
- * @param gdLatitudeDeg
- * Latitude in WGS84 geodetic coordinates -- positive is east.
- * @param gdLongitudeDeg
- * Longitude in WGS84 geodetic coordinates -- positive is north.
- * @param altitudeMeters
- * Altitude in WGS84 geodetic coordinates, in meters.
- * @param timeMillis
- * Time at which to evaluate the declination, in milliseconds
- * since January 1, 1970. (approximate is fine -- the declination
- * changes very slowly).
- */
- public GeomagneticField(float gdLatitudeDeg,
- float gdLongitudeDeg,
- float altitudeMeters,
- long timeMillis) {
- final int MAX_N = G_COEFF.length; // Maximum degree of the coefficients.
-
- // We don't handle the north and south poles correctly -- pretend that
- // we're not quite at them to avoid crashing.
- gdLatitudeDeg = Math.min(90.0f - 1e-5f,
- Math.max(-90.0f + 1e-5f, gdLatitudeDeg));
- computeGeocentricCoordinates(gdLatitudeDeg,
- gdLongitudeDeg,
- altitudeMeters);
-
- assert G_COEFF.length == H_COEFF.length;
-
- // Note: LegendreTable computes associated Legendre functions for
- // cos(theta). We want the associated Legendre functions for
- // sin(latitude), which is the same as cos(PI/2 - latitude), except the
- // derivate will be negated.
- LegendreTable legendre =
- new LegendreTable(MAX_N - 1,
- (float) (Math.PI / 2.0 - mGcLatitudeRad));
-
- // Compute a table of (EARTH_REFERENCE_RADIUS_KM / radius)^n for i in
- // 0..MAX_N-2 (this is much faster than calling Math.pow MAX_N+1 times).
- float[] relativeRadiusPower = new float[MAX_N + 2];
- relativeRadiusPower[0] = 1.0f;
- relativeRadiusPower[1] = EARTH_REFERENCE_RADIUS_KM / mGcRadiusKm;
- for (int i = 2; i < relativeRadiusPower.length; ++i) {
- relativeRadiusPower[i] = relativeRadiusPower[i - 1] *
- relativeRadiusPower[1];
- }
-
- // Compute tables of sin(lon * m) and cos(lon * m) for m = 0..MAX_N --
- // this is much faster than calling Math.sin and Math.com MAX_N+1 times.
- float[] sinMLon = new float[MAX_N];
- float[] cosMLon = new float[MAX_N];
- sinMLon[0] = 0.0f;
- cosMLon[0] = 1.0f;
- sinMLon[1] = (float) Math.sin(mGcLongitudeRad);
- cosMLon[1] = (float) Math.cos(mGcLongitudeRad);
-
- for (int m = 2; m < MAX_N; ++m) {
- // Standard expansions for sin((m-x)*theta + x*theta) and
- // cos((m-x)*theta + x*theta).
- int x = m >> 1;
- sinMLon[m] = sinMLon[m-x] * cosMLon[x] + cosMLon[m-x] * sinMLon[x];
- cosMLon[m] = cosMLon[m-x] * cosMLon[x] - sinMLon[m-x] * sinMLon[x];
- }
-
- float inverseCosLatitude = 1.0f / (float) Math.cos(mGcLatitudeRad);
- float yearsSinceBase =
- (timeMillis - BASE_TIME) / (365f * 24f * 60f * 60f * 1000f);
-
- // We now compute the magnetic field strength given the geocentric
- // location. The magnetic field is the derivative of the potential
- // function defined by the model. See NOAA Technical Report: The US/UK
- // World Magnetic Model for 2005-2010 for the derivation.
- float gcX = 0.0f; // Geocentric northwards component.
- float gcY = 0.0f; // Geocentric eastwards component.
- float gcZ = 0.0f; // Geocentric downwards component.
-
- for (int n = 1; n < MAX_N; n++) {
- for (int m = 0; m <= n; m++) {
- // Adjust the coefficients for the current date.
- float g = G_COEFF[n][m] + yearsSinceBase * DELTA_G[n][m];
- float h = H_COEFF[n][m] + yearsSinceBase * DELTA_H[n][m];
-
- // Negative derivative with respect to latitude, divided by
- // radius. This looks like the negation of the version in the
- // NOAA Techincal report because that report used
- // P_n^m(sin(theta)) and we use P_n^m(cos(90 - theta)), so the
- // derivative with respect to theta is negated.
- gcX += relativeRadiusPower[n+2]
- * (g * cosMLon[m] + h * sinMLon[m])
- * legendre.mPDeriv[n][m]
- * SCHMIDT_QUASI_NORM_FACTORS[n][m];
-
- // Negative derivative with respect to longitude, divided by
- // radius.
- gcY += relativeRadiusPower[n+2] * m
- * (g * sinMLon[m] - h * cosMLon[m])
- * legendre.mP[n][m]
- * SCHMIDT_QUASI_NORM_FACTORS[n][m]
- * inverseCosLatitude;
-
- // Negative derivative with respect to radius.
- gcZ -= (n + 1) * relativeRadiusPower[n+2]
- * (g * cosMLon[m] + h * sinMLon[m])
- * legendre.mP[n][m]
- * SCHMIDT_QUASI_NORM_FACTORS[n][m];
- }
- }
-
- // Convert back to geodetic coordinates. This is basically just a
- // rotation around the Y-axis by the difference in latitudes between the
- // geocentric frame and the geodetic frame.
- double latDiffRad = Math.toRadians(gdLatitudeDeg) - mGcLatitudeRad;
- mX = (float) (gcX * Math.cos(latDiffRad)
- + gcZ * Math.sin(latDiffRad));
- mY = gcY;
- mZ = (float) (- gcX * Math.sin(latDiffRad)
- + gcZ * Math.cos(latDiffRad));
- }
-
- /**
- * @return The X (northward) component of the magnetic field in nanoteslas.
- */
- public float getX() {
- return mX;
- }
-
- /**
- * @return The Y (eastward) component of the magnetic field in nanoteslas.
- */
- public float getY() {
- return mY;
- }
-
- /**
- * @return The Z (downward) component of the magnetic field in nanoteslas.
- */
- public float getZ() {
- return mZ;
- }
-
- /**
- * @return The declination of the horizontal component of the magnetic
- * field from true north, in degrees (i.e. positive means the
- * magnetic field is rotated east that much from true north).
- */
- public float getDeclination() {
- return (float) Math.toDegrees(Math.atan2(mY, mX));
- }
-
- /**
- * @return The inclination of the magnetic field in degrees -- positive
- * means the magnetic field is rotated downwards.
- */
- public float getInclination() {
- return (float) Math.toDegrees(Math.atan2(mZ,
- getHorizontalStrength()));
- }
-
- /**
- * @return Horizontal component of the field strength in nonoteslas.
- */
- public float getHorizontalStrength() {
- return (float) Math.sqrt(mX * mX + mY * mY);
- }
-
- /**
- * @return Total field strength in nanoteslas.
- */
- public float getFieldStrength() {
- return (float) Math.sqrt(mX * mX + mY * mY + mZ * mZ);
- }
-
- /**
- * @param gdLatitudeDeg
- * Latitude in WGS84 geodetic coordinates.
- * @param gdLongitudeDeg
- * Longitude in WGS84 geodetic coordinates.
- * @param altitudeMeters
- * Altitude above sea level in WGS84 geodetic coordinates.
- * @return Geocentric latitude (i.e. angle between closest point on the
- * equator and this point, at the center of the earth.
- */
- private void computeGeocentricCoordinates(float gdLatitudeDeg,
- float gdLongitudeDeg,
- float altitudeMeters) {
- float altitudeKm = altitudeMeters / 1000.0f;
- float a2 = EARTH_SEMI_MAJOR_AXIS_KM * EARTH_SEMI_MAJOR_AXIS_KM;
- float b2 = EARTH_SEMI_MINOR_AXIS_KM * EARTH_SEMI_MINOR_AXIS_KM;
- double gdLatRad = Math.toRadians(gdLatitudeDeg);
- float clat = (float) Math.cos(gdLatRad);
- float slat = (float) Math.sin(gdLatRad);
- float tlat = slat / clat;
- float latRad =
- (float) Math.sqrt(a2 * clat * clat + b2 * slat * slat);
-
- mGcLatitudeRad = (float) Math.atan(tlat * (latRad * altitudeKm + b2)
- / (latRad * altitudeKm + a2));
-
- mGcLongitudeRad = (float) Math.toRadians(gdLongitudeDeg);
-
- float radSq = altitudeKm * altitudeKm
- + 2 * altitudeKm * (float) Math.sqrt(a2 * clat * clat +
- b2 * slat * slat)
- + (a2 * a2 * clat * clat + b2 * b2 * slat * slat)
- / (a2 * clat * clat + b2 * slat * slat);
- mGcRadiusKm = (float) Math.sqrt(radSq);
- }
-
-
- /**
- * Utility class to compute a table of Gauss-normalized associated Legendre
- * functions P_n^m(cos(theta))
- */
- static private class LegendreTable {
- // These are the Gauss-normalized associated Legendre functions -- that
- // is, they are normal Legendre functions multiplied by
- // (n-m)!/(2n-1)!! (where (2n-1)!! = 1*3*5*...*2n-1)
- public final float[][] mP;
-
- // Derivative of mP, with respect to theta.
- public final float[][] mPDeriv;
-
- /**
- * @param maxN
- * The maximum n- and m-values to support
- * @param thetaRad
- * Returned functions will be Gauss-normalized
- * P_n^m(cos(thetaRad)), with thetaRad in radians.
- */
- public LegendreTable(int maxN, float thetaRad) {
- // Compute the table of Gauss-normalized associated Legendre
- // functions using standard recursion relations. Also compute the
- // table of derivatives using the derivative of the recursion
- // relations.
- float cos = (float) Math.cos(thetaRad);
- float sin = (float) Math.sin(thetaRad);
-
- mP = new float[maxN + 1][];
- mPDeriv = new float[maxN + 1][];
- mP[0] = new float[] { 1.0f };
- mPDeriv[0] = new float[] { 0.0f };
- for (int n = 1; n <= maxN; n++) {
- mP[n] = new float[n + 1];
- mPDeriv[n] = new float[n + 1];
- for (int m = 0; m <= n; m++) {
- if (n == m) {
- mP[n][m] = sin * mP[n - 1][m - 1];
- mPDeriv[n][m] = cos * mP[n - 1][m - 1]
- + sin * mPDeriv[n - 1][m - 1];
- } else if (n == 1 || m == n - 1) {
- mP[n][m] = cos * mP[n - 1][m];
- mPDeriv[n][m] = -sin * mP[n - 1][m]
- + cos * mPDeriv[n - 1][m];
- } else {
- assert n > 1 && m < n - 1;
- float k = ((n - 1) * (n - 1) - m * m)
- / (float) ((2 * n - 1) * (2 * n - 3));
- mP[n][m] = cos * mP[n - 1][m] - k * mP[n - 2][m];
- mPDeriv[n][m] = -sin * mP[n - 1][m]
- + cos * mPDeriv[n - 1][m] - k * mPDeriv[n - 2][m];
- }
- }
- }
- }
- }
-
- /**
- * Compute the ration between the Gauss-normalized associated Legendre
- * functions and the Schmidt quasi-normalized version. This is equivalent to
- * sqrt((m==0?1:2)*(n-m)!/(n+m!))*(2n-1)!!/(n-m)!
- */
- private static float[][] computeSchmidtQuasiNormFactors(int maxN) {
- float[][] schmidtQuasiNorm = new float[maxN + 1][];
- schmidtQuasiNorm[0] = new float[] { 1.0f };
- for (int n = 1; n <= maxN; n++) {
- schmidtQuasiNorm[n] = new float[n + 1];
- schmidtQuasiNorm[n][0] =
- schmidtQuasiNorm[n - 1][0] * (2 * n - 1) / (float) n;
- for (int m = 1; m <= n; m++) {
- schmidtQuasiNorm[n][m] = schmidtQuasiNorm[n][m - 1]
- * (float) Math.sqrt((n - m + 1) * (m == 1 ? 2 : 1)
- / (float) (n + m));
- }
- }
- return schmidtQuasiNorm;
- }
-} \ No newline at end of file
diff --git a/core/java/android/hardware/ISensorService.aidl b/core/java/android/hardware/ISensorService.aidl
deleted file mode 100644
index 04af2ae..0000000
--- a/core/java/android/hardware/ISensorService.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/* //device/java/android/android/hardware/ISensorService.aidl
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.hardware;
-
-import android.os.ParcelFileDescriptor;
-
-/**
- * {@hide}
- */
-interface ISensorService
-{
- ParcelFileDescriptor getDataChanel();
- boolean enableSensor(IBinder listener, String name, int sensor, int enable);
-}
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
deleted file mode 100644
index 0ce2f7b..0000000
--- a/core/java/android/hardware/Sensor.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package android.hardware;
-
-/**
- * Class representing a sensor. Use {@link SensorManager#getSensorList}
- * to get the list of available Sensors.
- */
-public class Sensor {
-
- /**
- * A constant describing an accelerometer sensor type.
- * See {@link android.hardware.SensorEvent SensorEvent}
- * for more details.
- */
- public static final int TYPE_ACCELEROMETER = 1;
-
- /**
- * A constant describing a magnetic field sensor type.
- * See {@link android.hardware.SensorEvent SensorEvent}
- * for more details.
- */
- public static final int TYPE_MAGNETIC_FIELD = 2;
-
- /**
- * A constant describing an orientation sensor type.
- * See {@link android.hardware.SensorEvent SensorEvent}
- * for more details.
- */
- public static final int TYPE_ORIENTATION = 3;
-
- /** A constant describing a gyroscope sensor type */
- public static final int TYPE_GYROSCOPE = 4;
- /** A constant describing a light sensor type */
- public static final int TYPE_LIGHT = 5;
- /** A constant describing a pressure sensor type */
- public static final int TYPE_PRESSURE = 6;
- /** A constant describing a temperature sensor type */
- public static final int TYPE_TEMPERATURE = 7;
- /** A constant describing a proximity sensor type */
- public static final int TYPE_PROXIMITY = 8;
-
-
- /**
- * A constant describing all sensor types.
- */
- public static final int TYPE_ALL = -1;
-
- /* Some of these fields are set only by the native bindings in
- * SensorManager.
- */
- private String mName;
- private String mVendor;
- private int mVersion;
- private int mHandle;
- private int mType;
- private float mMaxRange;
- private float mResolution;
- private float mPower;
- private int mLegacyType;
-
-
- Sensor() {
- }
-
- /**
- * @return name string of the sensor.
- */
- public String getName() {
- return mName;
- }
-
- /**
- * @return vendor string of this sensor.
- */
- public String getVendor() {
- return mVendor;
- }
-
- /**
- * @return generic type of this sensor.
- */
- public int getType() {
- return mType;
- }
-
- /**
- * @return version of the sensor's module.
- */
- public int getVersion() {
- return mVersion;
- }
-
- /**
- * @return maximum range of the sensor in the sensor's unit.
- */
- public float getMaximumRange() {
- return mMaxRange;
- }
-
- /**
- * @return resolution of the sensor in the sensor's unit.
- */
- public float getResolution() {
- return mResolution;
- }
-
- /**
- * @return the power in mA used by this sensor while in use
- */
- public float getPower() {
- return mPower;
- }
-
- int getHandle() {
- return mHandle;
- }
-
- void setRange(float max, float res) {
- mMaxRange = max;
- mResolution = res;
- }
-
- void setLegacyType(int legacyType) {
- mLegacyType = legacyType;
- }
-
- int getLegacyType() {
- return mLegacyType;
- }
-}
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
deleted file mode 100644
index cf939c5..0000000
--- a/core/java/android/hardware/SensorEvent.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware;
-
-/**
- * This class represents a sensor event and holds informations such as the
- * sensor type (eg: accelerometer, orientation, etc...), the time-stamp,
- * accuracy and of course the sensor's {@link SensorEvent#values data}.
- *
- * <p><u>Definition of the coordinate system used by the SensorEvent API.</u><p>
- *
- * <pre>
- * The coordinate space is defined relative to the screen of the phone
- * in its default orientation. The axes are not swapped when the device's
- * screen orientation changes.
- *
- * The OpenGL ES coordinate system is used. The origin is in the
- * lower-left corner with respect to the screen, with the X axis horizontal
- * and pointing right, the Y axis vertical and pointing up and the Z axis
- * pointing outside the front face of the screen. In this system, coordinates
- * behind the screen have negative Z values.
- *
- * <b>Note:</b> This coordinate system is different from the one used in the
- * Android 2D APIs where the origin is in the top-left corner.
- *
- * x<0 x>0
- * ^
- * |
- * +-----------+--> y>0
- * | |
- * | |
- * | |
- * | | / z<0
- * | | /
- * | | /
- * O-----------+/
- * |[] [ ] []/
- * +----------/+ y<0
- * /
- * /
- * |/ z>0 (toward the sky)
- *
- * O: Origin (x=0,y=0,z=0)
- * </pre>
- */
-
-public class SensorEvent {
- /**
- * The length and contents of the values array vary depending on which
- * sensor type is being monitored (see also {@link SensorEvent} for a
- * definition of the coordinate system used):
- *
- * <p>{@link android.hardware.Sensor#TYPE_ORIENTATION Sensor.TYPE_ORIENTATION}:<p>
- * All values are angles in degrees.
- *
- * <p>values[0]: Azimuth, angle between the magnetic north direction and
- * the Y axis, around the Z axis (0 to 359).
- * 0=North, 90=East, 180=South, 270=West
- *
- * <p>values[1]: Pitch, rotation around X axis (-180 to 180),
- * with positive values when the z-axis moves <b>toward</b> the y-axis.
- *
- * <p>values[2]: Roll, rotation around Y axis (-90 to 90), with
- * positive values when the x-axis moves <b>away</b> from the z-axis.
- *
- * <p><b>Note:</b> This definition is different from <b>yaw, pitch and
- * roll</b> used in aviation where the X axis is along the long side of
- * the plane (tail to nose).
- *
- * <p><b>Note:</b> It is preferable to use
- * {@link android.hardware.SensorManager#getRotationMatrix
- * getRotationMatrix()} in conjunction with
- * {@link android.hardware.SensorManager#remapCoordinateSystem
- * remapCoordinateSystem()} and
- * {@link android.hardware.SensorManager#getOrientation getOrientation()}
- * to compute these values; while it may be more expensive, it is usually
- * more accurate.
- *
- * <p>{@link android.hardware.Sensor#TYPE_ACCELEROMETER Sensor.TYPE_ACCELEROMETER}:<p>
- * All values are in SI units (m/s^2) and measure the acceleration applied
- * to the phone minus the force of gravity.
- *
- * <p>values[0]: Acceleration minus Gx on the x-axis
- * <p>values[1]: Acceleration minus Gy on the y-axis
- * <p>values[2]: Acceleration minus Gz on the z-axis
- *
- * <p><u>Examples</u>:
- * <li>When the device lies flat on a table and is pushed on its left
- * side toward the right, the x acceleration value is positive.</li>
- *
- * <li>When the device lies flat on a table, the acceleration value is
- * +9.81, which correspond to the acceleration of the device (0 m/s^2)
- * minus the force of gravity (-9.81 m/s^2).</li>
- *
- * <li>When the device lies flat on a table and is pushed toward the sky
- * with an acceleration of A m/s^2, the acceleration value is equal to
- * A+9.81 which correspond to the acceleration of the
- * device (+A m/s^2) minus the force of gravity (-9.81 m/s^2).</li>
- *
- *
- * <p>{@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD Sensor.TYPE_MAGNETIC_FIELD}:<p>
- * All values are in micro-Tesla (uT) and measure the ambient magnetic
- * field in the X, Y and Z axis.
- *
- */
- public final float[] values;
-
- /**
- * The sensor that generated this event.
- * See {@link android.hardware.SensorManager SensorManager}
- * for details.
- */
- public Sensor sensor;
-
- /**
- * The accuracy of this event.
- * See {@link android.hardware.SensorManager SensorManager}
- * for details.
- */
- public int accuracy;
-
-
- /**
- * The time in nanosecond at which the event happened
- */
- public long timestamp;
-
-
- SensorEvent(int size) {
- values = new float[size];
- }
-}
diff --git a/core/java/android/hardware/SensorEventListener.java b/core/java/android/hardware/SensorEventListener.java
deleted file mode 100644
index 716d0d4..0000000
--- a/core/java/android/hardware/SensorEventListener.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware;
-
-/**
- * Used for receiving notifications from the SensorManager when
- * sensor values have changed.
- */
-public interface SensorEventListener {
-
- /**
- * Called when sensor values have changed.
- * <p>See {@link android.hardware.SensorManager SensorManager}
- * for details on possible sensor types.
- * <p>See also {@link android.hardware.SensorEvent SensorEvent}.
- *
- * <p><b>NOTE:</b> The application doesn't own the
- * {@link android.hardware.SensorEvent event}
- * object passed as a parameter and therefore cannot hold on o it.
- * The object may be part of an internal pool and may be reused by
- * the framework.
- *
- * @param event the {@link android.hardware.SensorEvent SensorEvent}.
- */
- public void onSensorChanged(SensorEvent event);
-
- /**
- * Called when the accuracy of a sensor has changed.
- * <p>See {@link android.hardware.SensorManager SensorManager}
- * for details.
- *
- * @param accuracy The new accuracy of this sensor
- */
- public void onAccuracyChanged(Sensor sensor, int accuracy);
-}
diff --git a/core/java/android/hardware/SensorListener.java b/core/java/android/hardware/SensorListener.java
deleted file mode 100644
index cfa184b..0000000
--- a/core/java/android/hardware/SensorListener.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware;
-
-/**
- * Used for receiving notifications from the SensorManager when
- * sensor values have changed.
- *
- * This interface is deprecated, use
- * {@link android.hardware.SensorEventListener SensorEventListener} instead.
- *
- */
-@Deprecated
-public interface SensorListener {
-
- /**
- * <p>Called when sensor values have changed.
- * The length and contents of the values array vary
- * depending on which sensor is being monitored.
- * See {@link android.hardware.SensorManager SensorManager}
- * for details on possible sensor types.
- *
- * <p><u>Definition of the coordinate system used below.</u><p>
- * <p>The X axis refers to the screen's horizontal axis
- * (the small edge in portrait mode, the long edge in landscape mode) and
- * points to the right.
- * <p>The Y axis refers to the screen's vertical axis and points towards
- * the top of the screen (the origin is in the lower-left corner).
- * <p>The Z axis points toward the sky when the device is lying on its back
- * on a table.
- * <p> <b>IMPORTANT NOTE:</b> The axis <b><u>are swapped</u></b> when the
- * device's screen orientation changes. To access the unswapped values,
- * use indices 3, 4 and 5 in values[].
- *
- * <p>{@link android.hardware.SensorManager#SENSOR_ORIENTATION SENSOR_ORIENTATION},
- * {@link android.hardware.SensorManager#SENSOR_ORIENTATION_RAW SENSOR_ORIENTATION_RAW}:<p>
- * All values are angles in degrees.
- *
- * <p>values[0]: Azimuth, rotation around the Z axis (0<=azimuth<360).
- * 0 = North, 90 = East, 180 = South, 270 = West
- *
- * <p>values[1]: Pitch, rotation around X axis (-180<=pitch<=180), with positive
- * values when the z-axis moves toward the y-axis.
- *
- * <p>values[2]: Roll, rotation around Y axis (-90<=roll<=90), with positive values
- * when the z-axis moves toward the x-axis.
- *
- * <p>Note that this definition of yaw, pitch and roll is different from the
- * traditional definition used in aviation where the X axis is along the long
- * side of the plane (tail to nose).
- *
- * <p>{@link android.hardware.SensorManager#SENSOR_ACCELEROMETER SENSOR_ACCELEROMETER}:<p>
- * All values are in SI units (m/s^2) and measure contact forces.
- *
- * <p>values[0]: force applied by the device on the x-axis
- * <p>values[1]: force applied by the device on the y-axis
- * <p>values[2]: force applied by the device on the z-axis
- *
- * <p><u>Examples</u>:
- * <li>When the device is pushed on its left side toward the right, the
- * x acceleration value is negative (the device applies a reaction force
- * to the push toward the left)</li>
- *
- * <li>When the device lies flat on a table, the acceleration value is
- * {@link android.hardware.SensorManager#STANDARD_GRAVITY -STANDARD_GRAVITY},
- * which correspond to the force the device applies on the table in reaction
- * to gravity.</li>
- *
- * <p>{@link android.hardware.SensorManager#SENSOR_MAGNETIC_FIELD SENSOR_MAGNETIC_FIELD}:<p>
- * All values are in micro-Tesla (uT) and measure the ambient magnetic
- * field in the X, Y and -Z axis.
- * <p><b><u>Note:</u></b> the magnetic field's Z axis is inverted.
- *
- * @param sensor The ID of the sensor being monitored
- * @param values The new values for the sensor.
- */
- public void onSensorChanged(int sensor, float[] values);
-
- /**
- * Called when the accuracy of a sensor has changed.
- * See {@link android.hardware.SensorManager SensorManager}
- * for details.
- *
- * @param sensor The ID of the sensor being monitored
- * @param accuracy The new accuracy of this sensor.
- */
- public void onAccuracyChanged(int sensor, int accuracy);
-}
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
deleted file mode 100644
index e232c2c..0000000
--- a/core/java/android/hardware/SensorManager.java
+++ /dev/null
@@ -1,1462 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware;
-
-import android.content.Context;
-import android.os.Binder;
-import android.os.Looper;
-import android.os.ParcelFileDescriptor;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.Handler;
-import android.os.Message;
-import android.os.ServiceManager;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.IRotationWatcher;
-import android.view.IWindowManager;
-import android.view.Surface;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Class that lets you access the device's sensors. Get an instance of this
- * class by calling {@link android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with an argument of {@link android.content.Context#SENSOR_SERVICE}.
- */
-public class SensorManager extends IRotationWatcher.Stub
-{
- private static final String TAG = "SensorManager";
- private static final float[] mTempMatrix = new float[16];
-
- /* NOTE: sensor IDs must be a power of 2 */
-
- /**
- * A constant describing an orientation sensor.
- * See {@link android.hardware.SensorListener SensorListener} for more details.
- * @deprecated use {@link android.hardware.Sensor Sensor} instead.
- */
- @Deprecated
- public static final int SENSOR_ORIENTATION = 1 << 0;
-
- /**
- * A constant describing an accelerometer.
- * See {@link android.hardware.SensorListener SensorListener} for more details.
- * @deprecated use {@link android.hardware.Sensor Sensor} instead.
- */
- @Deprecated
- public static final int SENSOR_ACCELEROMETER = 1 << 1;
-
- /**
- * A constant describing a temperature sensor
- * See {@link android.hardware.SensorListener SensorListener} for more details.
- * @deprecated use {@link android.hardware.Sensor Sensor} instead.
- */
- @Deprecated
- public static final int SENSOR_TEMPERATURE = 1 << 2;
-
- /**
- * A constant describing a magnetic sensor
- * See {@link android.hardware.SensorListener SensorListener} for more details.
- * @deprecated use {@link android.hardware.Sensor Sensor} instead.
- */
- @Deprecated
- public static final int SENSOR_MAGNETIC_FIELD = 1 << 3;
-
- /**
- * A constant describing an ambient light sensor
- * See {@link android.hardware.SensorListener SensorListener} for more details.
- * @deprecated use {@link android.hardware.Sensor Sensor} instead.
- */
- @Deprecated
- public static final int SENSOR_LIGHT = 1 << 4;
-
- /**
- * A constant describing a proximity sensor
- * See {@link android.hardware.SensorListener SensorListener} for more details.
- * @deprecated use {@link android.hardware.Sensor Sensor} instead.
- */
- @Deprecated
- public static final int SENSOR_PROXIMITY = 1 << 5;
-
- /**
- * A constant describing a Tricorder
- * See {@link android.hardware.SensorListener SensorListener} for more details.
- * @deprecated use {@link android.hardware.Sensor Sensor} instead.
- */
- @Deprecated
- public static final int SENSOR_TRICORDER = 1 << 6;
-
- /**
- * A constant describing an orientation sensor.
- * See {@link android.hardware.SensorListener SensorListener} for more details.
- * @deprecated use {@link android.hardware.Sensor Sensor} instead.
- */
- @Deprecated
- public static final int SENSOR_ORIENTATION_RAW = 1 << 7;
-
- /** A constant that includes all sensors */
- @Deprecated
- public static final int SENSOR_ALL = 0x7F;
-
- /** Smallest sensor ID */
- @Deprecated
- public static final int SENSOR_MIN = SENSOR_ORIENTATION;
-
- /** Largest sensor ID */
- @Deprecated
- public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1);
-
-
- /** Index of the X value in the array returned by
- * {@link android.hardware.SensorListener#onSensorChanged} */
- @Deprecated
- public static final int DATA_X = 0;
- /** Index of the Y value in the array returned by
- * {@link android.hardware.SensorListener#onSensorChanged} */
- @Deprecated
- public static final int DATA_Y = 1;
- /** Index of the Z value in the array returned by
- * {@link android.hardware.SensorListener#onSensorChanged} */
- @Deprecated
- public static final int DATA_Z = 2;
-
- /** Offset to the untransformed values in the array returned by
- * {@link android.hardware.SensorListener#onSensorChanged} */
- @Deprecated
- public static final int RAW_DATA_INDEX = 3;
-
- /** Index of the untransformed X value in the array returned by
- * {@link android.hardware.SensorListener#onSensorChanged} */
- @Deprecated
- public static final int RAW_DATA_X = 3;
- /** Index of the untransformed Y value in the array returned by
- * {@link android.hardware.SensorListener#onSensorChanged} */
- @Deprecated
- public static final int RAW_DATA_Y = 4;
- /** Index of the untransformed Z value in the array returned by
- * {@link android.hardware.SensorListener#onSensorChanged} */
- @Deprecated
- public static final int RAW_DATA_Z = 5;
-
-
- /** Standard gravity (g) on Earth. This value is equivalent to 1G */
- public static final float STANDARD_GRAVITY = 9.80665f;
-
- /** values returned by the accelerometer in various locations in the universe.
- * all values are in SI units (m/s^2) */
- public static final float GRAVITY_SUN = 275.0f;
- public static final float GRAVITY_MERCURY = 3.70f;
- public static final float GRAVITY_VENUS = 8.87f;
- public static final float GRAVITY_EARTH = 9.80665f;
- public static final float GRAVITY_MOON = 1.6f;
- public static final float GRAVITY_MARS = 3.71f;
- public static final float GRAVITY_JUPITER = 23.12f;
- public static final float GRAVITY_SATURN = 8.96f;
- public static final float GRAVITY_URANUS = 8.69f;
- public static final float GRAVITY_NEPTUNE = 11.0f;
- public static final float GRAVITY_PLUTO = 0.6f;
- public static final float GRAVITY_DEATH_STAR_I = 0.000000353036145f;
- public static final float GRAVITY_THE_ISLAND = 4.815162342f;
-
-
- /** Maximum magnetic field on Earth's surface */
- public static final float MAGNETIC_FIELD_EARTH_MAX = 60.0f;
-
- /** Minimum magnetic field on Earth's surface */
- public static final float MAGNETIC_FIELD_EARTH_MIN = 30.0f;
-
-
- /** Various luminance values during the day (lux) */
- public static final float LIGHT_SUNLIGHT_MAX = 120000.0f;
- public static final float LIGHT_SUNLIGHT = 110000.0f;
- public static final float LIGHT_SHADE = 20000.0f;
- public static final float LIGHT_OVERCAST = 10000.0f;
- public static final float LIGHT_SUNRISE = 400.0f;
- public static final float LIGHT_CLOUDY = 100.0f;
- /** Various luminance values during the night (lux) */
- public static final float LIGHT_FULLMOON = 0.25f;
- public static final float LIGHT_NO_MOON = 0.001f;
-
- /** get sensor data as fast as possible */
- public static final int SENSOR_DELAY_FASTEST = 0;
- /** rate suitable for games */
- public static final int SENSOR_DELAY_GAME = 1;
- /** rate suitable for the user interface */
- public static final int SENSOR_DELAY_UI = 2;
- /** rate (default) suitable for screen orientation changes */
- public static final int SENSOR_DELAY_NORMAL = 3;
-
-
- /** The values returned by this sensor cannot be trusted, calibration
- * is needed or the environment doesn't allow readings */
- public static final int SENSOR_STATUS_UNRELIABLE = 0;
-
- /** This sensor is reporting data with low accuracy, calibration with the
- * environment is needed */
- public static final int SENSOR_STATUS_ACCURACY_LOW = 1;
-
- /** This sensor is reporting data with an average level of accuracy,
- * calibration with the environment may improve the readings */
- public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2;
-
- /** This sensor is reporting data with maximum accuracy */
- public static final int SENSOR_STATUS_ACCURACY_HIGH = 3;
-
- /** see {@link #remapCoordinateSystem} */
- public static final int AXIS_X = 1;
- /** see {@link #remapCoordinateSystem} */
- public static final int AXIS_Y = 2;
- /** see {@link #remapCoordinateSystem} */
- public static final int AXIS_Z = 3;
- /** see {@link #remapCoordinateSystem} */
- public static final int AXIS_MINUS_X = AXIS_X | 0x80;
- /** see {@link #remapCoordinateSystem} */
- public static final int AXIS_MINUS_Y = AXIS_Y | 0x80;
- /** see {@link #remapCoordinateSystem} */
- public static final int AXIS_MINUS_Z = AXIS_Z | 0x80;
-
- /*-----------------------------------------------------------------------*/
-
- private ISensorService mSensorService;
- Looper mMainLooper;
- @SuppressWarnings("deprecation")
- private HashMap<SensorListener, LegacyListener> mLegacyListenersMap =
- new HashMap<SensorListener, LegacyListener>();
-
- /*-----------------------------------------------------------------------*/
-
- private static final int SENSOR_DISABLE = -1;
- private static boolean sSensorModuleInitialized = false;
- private static ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
- private static SparseArray<List<Sensor>> sSensorListByType = new SparseArray<List<Sensor>>();
- private static IWindowManager sWindowManager;
- private static int sRotation = Surface.ROTATION_0;
- /* The thread and the sensor list are global to the process
- * but the actual thread is spawned on demand */
- private static SensorThread sSensorThread;
-
- // Used within this module from outside SensorManager, don't make private
- static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
- static final ArrayList<ListenerDelegate> sListeners =
- new ArrayList<ListenerDelegate>();
-
- /*-----------------------------------------------------------------------*/
-
- static private class SensorThread {
-
- Thread mThread;
-
- SensorThread() {
- // this gets to the sensor module. We can have only one per process.
- sensors_data_init();
- }
-
- @Override
- protected void finalize() {
- sensors_data_uninit();
- }
-
- // must be called with sListeners lock
- void startLocked(ISensorService service) {
- try {
- if (mThread == null) {
- ParcelFileDescriptor fd = service.getDataChanel();
- mThread = new Thread(new SensorThreadRunnable(fd),
- SensorThread.class.getName());
- mThread.start();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in startLocked: ", e);
- }
- }
-
- private class SensorThreadRunnable implements Runnable {
- private ParcelFileDescriptor mSensorDataFd;
- SensorThreadRunnable(ParcelFileDescriptor fd) {
- mSensorDataFd = fd;
- }
- public void run() {
- //Log.d(TAG, "entering main sensor thread");
- final float[] values = new float[3];
- final int[] status = new int[1];
- final long timestamp[] = new long[1];
- Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
-
- if (mSensorDataFd == null) {
- Log.e(TAG, "mSensorDataFd == NULL, exiting");
- return;
- }
- // this thread is guaranteed to be unique
- sensors_data_open(mSensorDataFd.getFileDescriptor());
- try {
- mSensorDataFd.close();
- } catch (IOException e) {
- // *shrug*
- Log.e(TAG, "IOException: ", e);
- }
- mSensorDataFd = null;
-
-
- while (true) {
- // wait for an event
- final int sensor = sensors_data_poll(values, status, timestamp);
-
- if (sensor == -1) {
- // we lost the connection to the event stream. this happens
- // when the last listener is removed.
- Log.d(TAG, "_sensors_data_poll() failed, we bail out.");
- break;
- }
-
- int accuracy = status[0];
- synchronized (sListeners) {
- if (sListeners.isEmpty()) {
- // we have no more listeners, terminate the thread
- sensors_data_close();
- mThread = null;
- break;
- }
- final Sensor sensorObject = sHandleToSensor.get(sensor);
- if (sensorObject != null) {
- // report the sensor event to all listeners that
- // care about it.
- final int size = sListeners.size();
- for (int i=0 ; i<size ; i++) {
- ListenerDelegate listener = sListeners.get(i);
- if (listener.hasSensor(sensorObject)) {
- // this is asynchronous (okay to call
- // with sListeners lock held).
- listener.onSensorChangedLocked(sensorObject,
- values, timestamp, accuracy);
- }
- }
- }
- }
- }
- //Log.d(TAG, "exiting main sensor thread");
- }
- }
- }
-
- /*-----------------------------------------------------------------------*/
-
- private class ListenerDelegate extends Binder {
- final SensorEventListener mSensorEventListener;
- private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>();
- private final Handler mHandler;
- private SensorEvent mValuesPool;
- public int mSensors;
-
- ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) {
- mSensorEventListener = listener;
- Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
- // currently we create one Handler instance per listener, but we could
- // have one per looper (we'd need to pass the ListenerDelegate
- // instance to handleMessage and keep track of them separately).
- mHandler = new Handler(looper) {
- @Override
- public void handleMessage(Message msg) {
- SensorEvent t = (SensorEvent)msg.obj;
- if (t.accuracy >= 0) {
- mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy);
- }
- mSensorEventListener.onSensorChanged(t);
- returnToPool(t);
- }
- };
- addSensor(sensor);
- }
-
- protected SensorEvent createSensorEvent() {
- // maximal size for all legacy events is 3
- return new SensorEvent(3);
- }
-
- protected SensorEvent getFromPool() {
- SensorEvent t = null;
- synchronized (this) {
- // remove the array from the pool
- t = mValuesPool;
- mValuesPool = null;
- }
- if (t == null) {
- // the pool was empty, we need a new one
- t = createSensorEvent();
- }
- return t;
- }
-
- protected void returnToPool(SensorEvent t) {
- synchronized (this) {
- // put back the array into the pool
- if (mValuesPool == null) {
- mValuesPool = t;
- }
- }
- }
-
- Object getListener() {
- return mSensorEventListener;
- }
-
- int addSensor(Sensor sensor) {
- mSensors |= 1<<sensor.getHandle();
- mSensorList.add(sensor);
- return mSensors;
- }
- int removeSensor(Sensor sensor) {
- mSensors &= ~(1<<sensor.getHandle());
- mSensorList.remove(sensor);
- return mSensors;
- }
- boolean hasSensor(Sensor sensor) {
- return ((mSensors & (1<<sensor.getHandle())) != 0);
- }
- List<Sensor> getSensors() {
- return mSensorList;
- }
-
- void onSensorChangedLocked(Sensor sensor, float[] values, long[] timestamp, int accuracy) {
- SensorEvent t = getFromPool();
- final float[] v = t.values;
- v[0] = values[0];
- v[1] = values[1];
- v[2] = values[2];
- t.timestamp = timestamp[0];
- t.accuracy = accuracy;
- t.sensor = sensor;
- Message msg = Message.obtain();
- msg.what = 0;
- msg.obj = t;
- mHandler.sendMessage(msg);
- }
- }
-
- /**
- * {@hide}
- */
- public SensorManager(Looper mainLooper) {
- mSensorService = ISensorService.Stub.asInterface(
- ServiceManager.getService(Context.SENSOR_SERVICE));
- mMainLooper = mainLooper;
-
-
- synchronized(sListeners) {
- if (!sSensorModuleInitialized) {
- sSensorModuleInitialized = true;
-
- nativeClassInit();
-
- sWindowManager = IWindowManager.Stub.asInterface(
- ServiceManager.getService("window"));
- if (sWindowManager != null) {
- // if it's null we're running in the system process
- // which won't get the rotated values
- try {
- sRotation = sWindowManager.watchRotation(this);
- } catch (RemoteException e) {
- }
- }
-
- // initialize the sensor list
- sensors_module_init();
- final ArrayList<Sensor> fullList = sFullSensorsList;
- int i = 0;
- do {
- Sensor sensor = new Sensor();
- i = sensors_module_get_next_sensor(sensor, i);
-
- if (i>=0) {
- Log.d(TAG, "found sensor: " + sensor.getName() +
- ", handle=" + sensor.getHandle());
- sensor.setLegacyType(getLegacySensorType(sensor.getType()));
- fullList.add(sensor);
- sHandleToSensor.append(sensor.getHandle(), sensor);
- }
- } while (i>0);
-
- sSensorThread = new SensorThread();
- }
- }
- }
-
- private int getLegacySensorType(int type) {
- switch (type) {
- case Sensor.TYPE_ACCELEROMETER:
- return SENSOR_ACCELEROMETER;
- case Sensor.TYPE_MAGNETIC_FIELD:
- return SENSOR_MAGNETIC_FIELD;
- case Sensor.TYPE_ORIENTATION:
- return SENSOR_ORIENTATION_RAW;
- case Sensor.TYPE_TEMPERATURE:
- return SENSOR_TEMPERATURE;
- }
- return 0;
- }
-
- /** @return available sensors.
- * @deprecated This method is deprecated, use
- * {@link SensorManager#getSensorList(int)} instead
- */
- @Deprecated
- public int getSensors() {
- int result = 0;
- final ArrayList<Sensor> fullList = sFullSensorsList;
- for (Sensor i : fullList) {
- switch (i.getType()) {
- case Sensor.TYPE_ACCELEROMETER:
- result |= SensorManager.SENSOR_ACCELEROMETER;
- break;
- case Sensor.TYPE_MAGNETIC_FIELD:
- result |= SensorManager.SENSOR_MAGNETIC_FIELD;
- break;
- case Sensor.TYPE_ORIENTATION:
- result |= SensorManager.SENSOR_ORIENTATION |
- SensorManager.SENSOR_ORIENTATION_RAW;
- break;
- }
- }
- return result;
- }
-
- /**
- * Use this method to get the list of available sensors of a certain
- * type. Make multiple calls to get sensors of different types or use
- * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all
- * the sensors.
- *
- * @param type of sensors requested
- * @return a list of sensors matching the asked type.
- */
- public List<Sensor> getSensorList(int type) {
- // cache the returned lists the first time
- List<Sensor> list;
- final ArrayList<Sensor> fullList = sFullSensorsList;
- synchronized(fullList) {
- list = sSensorListByType.get(type);
- if (list == null) {
- if (type == Sensor.TYPE_ALL) {
- list = fullList;
- } else {
- list = new ArrayList<Sensor>();
- for (Sensor i : fullList) {
- if (i.getType() == type)
- list.add(i);
- }
- }
- list = Collections.unmodifiableList(list);
- sSensorListByType.append(type, list);
- }
- }
- return list;
- }
-
- /**
- * Use this method to get the default sensor for a given type. Note that
- * the returned sensor could be a composite sensor, and its data could be
- * averaged or filtered. If you need to access the raw sensors use
- * {@link SensorManager#getSensorList(int) getSensorList}.
- *
- *
- * @param type of sensors requested
- * @return the default sensors matching the asked type.
- */
- public Sensor getDefaultSensor(int type) {
- // TODO: need to be smarter, for now, just return the 1st sensor
- List<Sensor> l = getSensorList(type);
- return l.isEmpty() ? null : l.get(0);
- }
-
-
- /**
- * Registers a listener for given sensors.
- * @deprecated This method is deprecated, use
- * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
- * instead.
- *
- * @param listener sensor listener object
- * @param sensors a bit masks of the sensors to register to
- *
- * @return true if the sensor is supported and successfully enabled
- */
- @Deprecated
- public boolean registerListener(SensorListener listener, int sensors) {
- return registerListener(listener, sensors, SENSOR_DELAY_NORMAL);
- }
-
- /**
- * Registers a SensorListener for given sensors.
- * @deprecated This method is deprecated, use
- * {@link SensorManager#registerListener(SensorEventListener, Sensor, int)}
- * instead.
- *
- * @param listener sensor listener object
- * @param sensors a bit masks of the sensors to register to
- * @param rate rate of events. This is only a hint to the system. events
- * may be received faster or slower than the specified rate. Usually events
- * are received faster.
- *
- * @return true if the sensor is supported and successfully enabled
- */
- @Deprecated
- public boolean registerListener(SensorListener listener, int sensors, int rate) {
- if (listener == null) {
- return false;
- }
- boolean result = false;
- result = registerLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
- listener, sensors, rate) || result;
- result = registerLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
- listener, sensors, rate) || result;
- result = registerLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
- listener, sensors, rate) || result;
- result = registerLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
- listener, sensors, rate) || result;
- result = registerLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
- listener, sensors, rate) || result;
- return result;
- }
-
- @SuppressWarnings("deprecation")
- private boolean registerLegacyListener(int legacyType, int type,
- SensorListener listener, int sensors, int rate)
- {
- if (listener == null) {
- return false;
- }
- boolean result = false;
- // Are we activating this legacy sensor?
- if ((sensors & legacyType) != 0) {
- // if so, find a suitable Sensor
- Sensor sensor = getDefaultSensor(type);
- if (sensor != null) {
- // If we don't already have one, create a LegacyListener
- // to wrap this listener and process the events as
- // they are expected by legacy apps.
- LegacyListener legacyListener = null;
- synchronized (mLegacyListenersMap) {
- legacyListener = mLegacyListenersMap.get(listener);
- if (legacyListener == null) {
- // we didn't find a LegacyListener for this client,
- // create one, and put it in our list.
- legacyListener = new LegacyListener(listener);
- mLegacyListenersMap.put(listener, legacyListener);
- }
- }
- // register this legacy sensor with this legacy listener
- legacyListener.registerSensor(legacyType);
- // and finally, register the legacy listener with the new apis
- result = registerListener(legacyListener, sensor, rate);
- }
- }
- return result;
- }
-
- /**
- * Unregisters a listener for the sensors with which it is registered.
- * @deprecated This method is deprecated, use
- * {@link SensorManager#unregisterListener(SensorEventListener, Sensor)}
- * instead.
- *
- * @param listener a SensorListener object
- * @param sensors a bit masks of the sensors to unregister from
- */
- @Deprecated
- public void unregisterListener(SensorListener listener, int sensors) {
- unregisterLegacyListener(SENSOR_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER,
- listener, sensors);
- unregisterLegacyListener(SENSOR_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD,
- listener, sensors);
- unregisterLegacyListener(SENSOR_ORIENTATION_RAW, Sensor.TYPE_ORIENTATION,
- listener, sensors);
- unregisterLegacyListener(SENSOR_ORIENTATION, Sensor.TYPE_ORIENTATION,
- listener, sensors);
- unregisterLegacyListener(SENSOR_TEMPERATURE, Sensor.TYPE_TEMPERATURE,
- listener, sensors);
- }
-
- @SuppressWarnings("deprecation")
- private void unregisterLegacyListener(int legacyType, int type,
- SensorListener listener, int sensors)
- {
- if (listener == null) {
- return;
- }
- // do we know about this listener?
- LegacyListener legacyListener = null;
- synchronized (mLegacyListenersMap) {
- legacyListener = mLegacyListenersMap.get(listener);
- }
- if (legacyListener != null) {
- // Are we deactivating this legacy sensor?
- if ((sensors & legacyType) != 0) {
- // if so, find the corresponding Sensor
- Sensor sensor = getDefaultSensor(type);
- if (sensor != null) {
- // unregister this legacy sensor and if we don't
- // need the corresponding Sensor, unregister it too
- if (legacyListener.unregisterSensor(legacyType)) {
- // corresponding sensor not needed, unregister
- unregisterListener(legacyListener, sensor);
- // finally check if we still need the legacyListener
- // in our mapping, if not, get rid of it too.
- synchronized(sListeners) {
- boolean found = false;
- for (ListenerDelegate i : sListeners) {
- if (i.getListener() == legacyListener) {
- found = true;
- break;
- }
- }
- if (!found) {
- synchronized (mLegacyListenersMap) {
- mLegacyListenersMap.remove(listener);
- }
- }
- }
- }
- }
- }
- }
- }
-
- /**
- * Unregisters a listener for all sensors.
- * @deprecated This method is deprecated, use
- * {@link SensorManager#unregisterListener(SensorEventListener)}
- * instead.
- *
- * @param listener a SensorListener object
- */
- @Deprecated
- public void unregisterListener(SensorListener listener) {
- unregisterListener(listener, SENSOR_ALL | SENSOR_ORIENTATION_RAW);
- }
-
- /**
- * Unregisters a listener for the sensors with which it is registered.
- *
- * @param listener a SensorEventListener object
- * @param sensor the sensor to unregister from
- *
- */
- public void unregisterListener(SensorEventListener listener, Sensor sensor) {
- unregisterListener((Object)listener, sensor);
- }
-
- /**
- * Unregisters a listener for all sensors.
- *
- * @param listener a SensorListener object
- *
- */
- public void unregisterListener(SensorEventListener listener) {
- unregisterListener((Object)listener);
- }
-
-
- /**
- * Registers a {@link android.hardware.SensorEventListener SensorEventListener}
- * for the given sensor.
- *
- * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object.
- * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
- * @param rate The rate {@link android.hardware.SensorEvent sensor events} are delivered at.
- * This is only a hint to the system. Events may be received faster or
- * slower than the specified rate. Usually events are received faster.
- *
- * @return true if the sensor is supported and successfully enabled.
- *
- */
- public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) {
- return registerListener(listener, sensor, rate, null);
- }
-
- /**
- * Registers a {@link android.hardware.SensorEventListener SensorEventListener}
- * for the given sensor.
- *
- * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object.
- * @param sensor The {@link android.hardware.Sensor Sensor} to register to.
- * @param rate The rate {@link android.hardware.SensorEvent sensor events} are delivered at.
- * This is only a hint to the system. Events may be received faster or
- * slower than the specified rate. Usually events are received faster.
- * @param handler The {@link android.os.Handler Handler} the
- * {@link android.hardware.SensorEvent sensor events} will be delivered to.
- *
- * @return true if the sensor is supported and successfully enabled.
- *
- */
- public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,
- Handler handler) {
- if (listener == null || sensor == null) {
- return false;
- }
- boolean result;
- int delay = -1;
- switch (rate) {
- case SENSOR_DELAY_FASTEST:
- delay = 0;
- break;
- case SENSOR_DELAY_GAME:
- delay = 20;
- break;
- case SENSOR_DELAY_UI:
- delay = 60;
- break;
- case SENSOR_DELAY_NORMAL:
- delay = 200;
- break;
- default:
- return false;
- }
-
- try {
- synchronized (sListeners) {
- ListenerDelegate l = null;
- for (ListenerDelegate i : sListeners) {
- if (i.getListener() == listener) {
- l = i;
- break;
- }
- }
-
- String name = sensor.getName();
- int handle = sensor.getHandle();
- if (l == null) {
- l = new ListenerDelegate(listener, sensor, handler);
- result = mSensorService.enableSensor(l, name, handle, delay);
- if (result) {
- sListeners.add(l);
- sListeners.notify();
- }
- if (!sListeners.isEmpty()) {
- sSensorThread.startLocked(mSensorService);
- }
- } else {
- result = mSensorService.enableSensor(l, name, handle, delay);
- if (result) {
- l.addSensor(sensor);
- }
- }
- }
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in registerListener: ", e);
- result = false;
- }
- return result;
- }
-
- private void unregisterListener(Object listener, Sensor sensor) {
- if (listener == null || sensor == null) {
- return;
- }
- try {
- synchronized (sListeners) {
- final int size = sListeners.size();
- for (int i=0 ; i<size ; i++) {
- ListenerDelegate l = sListeners.get(i);
- if (l.getListener() == listener) {
- // disable these sensors
- String name = sensor.getName();
- int handle = sensor.getHandle();
- mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);
- // if we have no more sensors enabled on this listener,
- // take it off the list.
- if (l.removeSensor(sensor) == 0) {
- sListeners.remove(i);
- }
- break;
- }
- }
- }
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in unregisterListener: ", e);
- }
- }
-
- private void unregisterListener(Object listener) {
- if (listener == null) {
- return;
- }
- try {
- synchronized (sListeners) {
- final int size = sListeners.size();
- for (int i=0 ; i<size ; i++) {
- ListenerDelegate l = sListeners.get(i);
- if (l.getListener() == listener) {
- // disable all sensors for this listener
- for (Sensor sensor : l.getSensors()) {
- String name = sensor.getName();
- int handle = sensor.getHandle();
- mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);
- }
- sListeners.remove(i);
- break;
- }
- }
- }
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in unregisterListener: ", e);
- }
- }
-
- /**
- * Computes the inclination matrix <b>I</b> as well as the rotation
- * matrix <b>R</b> transforming a vector from the
- * device coordinate system to the world's coordinate system which is
- * defined as a direct orthonormal basis, where:
- *
- * <li>X is defined as the vector product <b>Y.Z</b> (It is tangential to
- * the ground at the device's current location and roughly points East).</li>
- * <li>Y is tangential to the ground at the device's current location and
- * points towards the magnetic North Pole.</li>
- * <li>Z points towards the sky and is perpendicular to the ground.</li>
- * <p>
- * <hr>
- * <p>By definition:
- * <p>[0 0 g] = <b>R</b> * <b>gravity</b> (g = magnitude of gravity)
- * <p>[0 m 0] = <b>I</b> * <b>R</b> * <b>geomagnetic</b>
- * (m = magnitude of geomagnetic field)
- * <p><b>R</b> is the identity matrix when the device is aligned with the
- * world's coordinate system, that is, when the device's X axis points
- * toward East, the Y axis points to the North Pole and the device is facing
- * the sky.
- *
- * <p><b>I</b> is a rotation matrix transforming the geomagnetic
- * vector into the same coordinate space as gravity (the world's coordinate
- * space). <b>I</b> is a simple rotation around the X axis.
- * The inclination angle in radians can be computed with
- * {@link #getInclination}.
- * <hr>
- *
- * <p> Each matrix is returned either as a 3x3 or 4x4 row-major matrix
- * depending on the length of the passed array:
- * <p><u>If the array length is 16:</u>
- * <pre>
- * / M[ 0] M[ 1] M[ 2] M[ 3] \
- * | M[ 4] M[ 5] M[ 6] M[ 7] |
- * | M[ 8] M[ 9] M[10] M[11] |
- * \ M[12] M[13] M[14] M[15] /
- *</pre>
- * This matrix is ready to be used by OpenGL ES's
- * {@link javax.microedition.khronos.opengles.GL10#glLoadMatrixf(float[], int)
- * glLoadMatrixf(float[], int)}.
- * <p>Note that because OpenGL matrices are column-major matrices you must
- * transpose the matrix before using it. However, since the matrix is a
- * rotation matrix, its transpose is also its inverse, conveniently, it is
- * often the inverse of the rotation that is needed for rendering; it can
- * therefore be used with OpenGL ES directly.
- * <p>
- * Also note that the returned matrices always have this form:
- * <pre>
- * / M[ 0] M[ 1] M[ 2] 0 \
- * | M[ 4] M[ 5] M[ 6] 0 |
- * | M[ 8] M[ 9] M[10] 0 |
- * \ 0 0 0 1 /
- *</pre>
- * <p><u>If the array length is 9:</u>
- * <pre>
- * / M[ 0] M[ 1] M[ 2] \
- * | M[ 3] M[ 4] M[ 5] |
- * \ M[ 6] M[ 7] M[ 8] /
- *</pre>
- *
- * <hr>
- * <p>The inverse of each matrix can be computed easily by taking its
- * transpose.
- *
- * <p>The matrices returned by this function are meaningful only when the
- * device is not free-falling and it is not close to the magnetic north.
- * If the device is accelerating, or placed into a strong magnetic field,
- * the returned matrices may be inaccurate.
- *
- * @param R is an array of 9 floats holding the rotation matrix <b>R</b>
- * when this function returns. R can be null.<p>
- * @param I is an array of 9 floats holding the rotation matrix <b>I</b>
- * when this function returns. I can be null.<p>
- * @param gravity is an array of 3 floats containing the gravity vector
- * expressed in the device's coordinate. You can simply use the
- * {@link android.hardware.SensorEvent#values values}
- * returned by a {@link android.hardware.SensorEvent SensorEvent} of a
- * {@link android.hardware.Sensor Sensor} of type
- * {@link android.hardware.Sensor#TYPE_ACCELEROMETER TYPE_ACCELEROMETER}.<p>
- * @param geomagnetic is an array of 3 floats containing the geomagnetic
- * vector expressed in the device's coordinate. You can simply use the
- * {@link android.hardware.SensorEvent#values values}
- * returned by a {@link android.hardware.SensorEvent SensorEvent} of a
- * {@link android.hardware.Sensor Sensor} of type
- * {@link android.hardware.Sensor#TYPE_MAGNETIC_FIELD TYPE_MAGNETIC_FIELD}.
- * @return
- * true on success<p>
- * false on failure (for instance, if the device is in free fall).
- * On failure the output matrices are not modified.
- */
-
- public static boolean getRotationMatrix(float[] R, float[] I,
- float[] gravity, float[] geomagnetic) {
- // TODO: move this to native code for efficiency
- float Ax = gravity[0];
- float Ay = gravity[1];
- float Az = gravity[2];
- final float Ex = geomagnetic[0];
- final float Ey = geomagnetic[1];
- final float Ez = geomagnetic[2];
- float Hx = Ey*Az - Ez*Ay;
- float Hy = Ez*Ax - Ex*Az;
- float Hz = Ex*Ay - Ey*Ax;
- final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
- if (normH < 0.1f) {
- // device is close to free fall (or in space?), or close to
- // magnetic north pole. Typical values are > 100.
- return false;
- }
- final float invH = 1.0f / normH;
- Hx *= invH;
- Hy *= invH;
- Hz *= invH;
- final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az);
- Ax *= invA;
- Ay *= invA;
- Az *= invA;
- final float Mx = Ay*Hz - Az*Hy;
- final float My = Az*Hx - Ax*Hz;
- final float Mz = Ax*Hy - Ay*Hx;
- if (R != null) {
- if (R.length == 9) {
- R[0] = Hx; R[1] = Hy; R[2] = Hz;
- R[3] = Mx; R[4] = My; R[5] = Mz;
- R[6] = Ax; R[7] = Ay; R[8] = Az;
- } else if (R.length == 16) {
- R[0] = Hx; R[1] = Hy; R[2] = Hz; R[3] = 0;
- R[4] = Mx; R[5] = My; R[6] = Mz; R[7] = 0;
- R[8] = Ax; R[9] = Ay; R[10] = Az; R[11] = 0;
- R[12] = 0; R[13] = 0; R[14] = 0; R[15] = 1;
- }
- }
- if (I != null) {
- // compute the inclination matrix by projecting the geomagnetic
- // vector onto the Z (gravity) and X (horizontal component
- // of geomagnetic vector) axes.
- final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez);
- final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE;
- final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE;
- if (I.length == 9) {
- I[0] = 1; I[1] = 0; I[2] = 0;
- I[3] = 0; I[4] = c; I[5] = s;
- I[6] = 0; I[7] =-s; I[8] = c;
- } else if (I.length == 16) {
- I[0] = 1; I[1] = 0; I[2] = 0;
- I[4] = 0; I[5] = c; I[6] = s;
- I[8] = 0; I[9] =-s; I[10]= c;
- I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;
- I[15] = 1;
- }
- }
- return true;
- }
-
- /**
- * Computes the geomagnetic inclination angle in radians from the
- * inclination matrix <b>I</b> returned by {@link #getRotationMatrix}.
- * @param I inclination matrix see {@link #getRotationMatrix}.
- * @return The geomagnetic inclination angle in radians.
- */
- public static float getInclination(float[] I) {
- if (I.length == 9) {
- return (float)Math.atan2(I[5], I[4]);
- } else {
- return (float)Math.atan2(I[6], I[5]);
- }
- }
-
- /**
- * Rotates the supplied rotation matrix so it is expressed in a
- * different coordinate system. This is typically used when an application
- * needs to compute the three orientation angles of the device (see
- * {@link #getOrientation}) in a different coordinate system.
- *
- * <p>When the rotation matrix is used for drawing (for instance with
- * OpenGL ES), it usually <b>doesn't need</b> to be transformed by this
- * function, unless the screen is physically rotated, such as when used
- * in landscape mode.
- *
- * <p><u>Examples:</u><p>
- *
- * <li>Using the camera (Y axis along the camera's axis) for an augmented
- * reality application where the rotation angles are needed :</li><p>
- *
- * <code>remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);</code><p>
- *
- * <li>Using the device as a mechanical compass in landscape mode:</li><p>
- *
- * <code>remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);</code><p>
- *
- * Beware of the above example. This call is needed only if the device is
- * physically used in landscape mode to calculate the rotation angles (see
- * {@link #getOrientation}).
- * If the rotation matrix is also used for rendering, it may not need to
- * be transformed, for instance if your {@link android.app.Activity
- * Activity} is running in landscape mode.
- *
- * <p>Since the resulting coordinate system is orthonormal, only two axes
- * need to be specified.
- *
- * @param inR the rotation matrix to be transformed. Usually it is the
- * matrix returned by {@link #getRotationMatrix}.
- * @param X defines on which world axis and direction the X axis of the
- * device is mapped.
- * @param Y defines on which world axis and direction the Y axis of the
- * device is mapped.
- * @param outR the transformed rotation matrix. inR and outR can be the same
- * array, but it is not recommended for performance reason.
- * @return true on success. false if the input parameters are incorrect, for
- * instance if X and Y define the same axis. Or if inR and outR don't have
- * the same length.
- */
-
- public static boolean remapCoordinateSystem(float[] inR, int X, int Y,
- float[] outR)
- {
- if (inR == outR) {
- final float[] temp = mTempMatrix;
- synchronized(temp) {
- // we don't expect to have a lot of contention
- if (remapCoordinateSystemImpl(inR, X, Y, temp)) {
- final int size = outR.length;
- for (int i=0 ; i<size ; i++)
- outR[i] = temp[i];
- return true;
- }
- }
- }
- return remapCoordinateSystemImpl(inR, X, Y, outR);
- }
-
- private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y,
- float[] outR)
- {
- /*
- * X and Y define a rotation matrix 'r':
- *
- * (X==1)?((X&0x80)?-1:1):0 (X==2)?((X&0x80)?-1:1):0 (X==3)?((X&0x80)?-1:1):0
- * (Y==1)?((Y&0x80)?-1:1):0 (Y==2)?((Y&0x80)?-1:1):0 (Y==3)?((X&0x80)?-1:1):0
- * r[0] ^ r[1]
- *
- * where the 3rd line is the vector product of the first 2 lines
- *
- */
-
- final int length = outR.length;
- if (inR.length != length)
- return false; // invalid parameter
- if ((X & 0x7C)!=0 || (Y & 0x7C)!=0)
- return false; // invalid parameter
- if (((X & 0x3)==0) || ((Y & 0x3)==0))
- return false; // no axis specified
- if ((X & 0x3) == (Y & 0x3))
- return false; // same axis specified
-
- // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y)
- // this can be calculated by exclusive-or'ing X and Y; except for
- // the sign inversion (+/-) which is calculated below.
- int Z = X ^ Y;
-
- // extract the axis (remove the sign), offset in the range 0 to 2.
- final int x = (X & 0x3)-1;
- final int y = (Y & 0x3)-1;
- final int z = (Z & 0x3)-1;
-
- // compute the sign of Z (whether it needs to be inverted)
- final int axis_y = (z+1)%3;
- final int axis_z = (z+2)%3;
- if (((x^axis_y)|(y^axis_z)) != 0)
- Z ^= 0x80;
-
- final boolean sx = (X>=0x80);
- final boolean sy = (Y>=0x80);
- final boolean sz = (Z>=0x80);
-
- // Perform R * r, in avoiding actual muls and adds.
- final int rowLength = ((length==16)?4:3);
- for (int j=0 ; j<3 ; j++) {
- final int offset = j*rowLength;
- for (int i=0 ; i<3 ; i++) {
- if (x==i) outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0];
- if (y==i) outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1];
- if (z==i) outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2];
- }
- }
- if (length == 16) {
- outR[3] = outR[7] = outR[11] = outR[12] = outR[13] = outR[14] = 0;
- outR[15] = 1;
- }
- return true;
- }
-
- /**
- * Computes the device's orientation based on the rotation matrix.
- * <p> When it returns, the array values is filled with the result:
- * <li>values[0]: <i>azimuth</i>, rotation around the Z axis.</li>
- * <li>values[1]: <i>pitch</i>, rotation around the X axis.</li>
- * <li>values[2]: <i>roll</i>, rotation around the Y axis.</li>
- * <p>
- *
- * @param R rotation matrix see {@link #getRotationMatrix}.
- * @param values an array of 3 floats to hold the result.
- * @return The array values passed as argument.
- */
- public static float[] getOrientation(float[] R, float values[]) {
- /*
- * 4x4 (length=16) case:
- * / R[ 0] R[ 1] R[ 2] 0 \
- * | R[ 4] R[ 5] R[ 6] 0 |
- * | R[ 8] R[ 9] R[10] 0 |
- * \ 0 0 0 1 /
- *
- * 3x3 (length=9) case:
- * / R[ 0] R[ 1] R[ 2] \
- * | R[ 3] R[ 4] R[ 5] |
- * \ R[ 6] R[ 7] R[ 8] /
- *
- */
- if (R.length == 9) {
- values[0] = (float)Math.atan2(R[1], R[4]);
- values[1] = (float)Math.asin(-R[7]);
- values[2] = (float)Math.atan2(-R[6], R[8]);
- } else {
- values[0] = (float)Math.atan2(R[1], R[5]);
- values[1] = (float)Math.asin(-R[9]);
- values[2] = (float)Math.atan2(-R[8], R[10]);
- }
- return values;
- }
-
-
- /**
- * {@hide}
- */
- public void onRotationChanged(int rotation) {
- synchronized(sListeners) {
- sRotation = rotation;
- }
- }
-
- static int getRotation() {
- synchronized(sListeners) {
- return sRotation;
- }
- }
-
- private class LegacyListener implements SensorEventListener {
- private float mValues[] = new float[6];
- @SuppressWarnings("deprecation")
- private SensorListener mTarget;
- private int mSensors;
- private final LmsFilter mYawfilter = new LmsFilter();
-
- @SuppressWarnings("deprecation")
- LegacyListener(SensorListener target) {
- mTarget = target;
- mSensors = 0;
- }
-
- void registerSensor(int legacyType) {
- mSensors |= legacyType;
- }
-
- boolean unregisterSensor(int legacyType) {
- mSensors &= ~legacyType;
- int mask = SENSOR_ORIENTATION|SENSOR_ORIENTATION_RAW;
- if (((legacyType&mask)!=0) && ((mSensors&mask)!=0)) {
- return false;
- }
- return true;
- }
-
- @SuppressWarnings("deprecation")
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- try {
- mTarget.onAccuracyChanged(sensor.getLegacyType(), accuracy);
- } catch (AbstractMethodError e) {
- // old app that doesn't implement this method
- // just ignore it.
- }
- }
-
- @SuppressWarnings("deprecation")
- public void onSensorChanged(SensorEvent event) {
- final float v[] = mValues;
- v[0] = event.values[0];
- v[1] = event.values[1];
- v[2] = event.values[2];
- int legacyType = event.sensor.getLegacyType();
- mapSensorDataToWindow(legacyType, v, SensorManager.getRotation());
- if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
- if ((mSensors & SENSOR_ORIENTATION_RAW)!=0) {
- mTarget.onSensorChanged(SENSOR_ORIENTATION_RAW, v);
- }
- if ((mSensors & SENSOR_ORIENTATION)!=0) {
- v[0] = mYawfilter.filter(event.timestamp, v[0]);
- mTarget.onSensorChanged(SENSOR_ORIENTATION, v);
- }
- } else {
- mTarget.onSensorChanged(legacyType, v);
- }
- }
-
- /*
- * Helper function to convert the specified sensor's data to the windows's
- * coordinate space from the device's coordinate space.
- *
- * output: 3,4,5: values in the old API format
- * 0,1,2: transformed values in the old API format
- *
- */
- private void mapSensorDataToWindow(int sensor,
- float[] values, int orientation) {
- float x = values[0];
- float y = values[1];
- float z = values[2];
-
- switch (sensor) {
- case SensorManager.SENSOR_ORIENTATION:
- case SensorManager.SENSOR_ORIENTATION_RAW:
- z = -z;
- break;
- case SensorManager.SENSOR_ACCELEROMETER:
- x = -x;
- y = -y;
- z = -z;
- break;
- case SensorManager.SENSOR_MAGNETIC_FIELD:
- x = -x;
- y = -y;
- break;
- }
- values[0] = x;
- values[1] = y;
- values[2] = z;
- values[3] = x;
- values[4] = y;
- values[5] = z;
- // TODO: add support for 180 and 270 orientations
- if (orientation == Surface.ROTATION_90) {
- switch (sensor) {
- case SENSOR_ACCELEROMETER:
- case SENSOR_MAGNETIC_FIELD:
- values[0] =-y;
- values[1] = x;
- values[2] = z;
- break;
- case SENSOR_ORIENTATION:
- case SENSOR_ORIENTATION_RAW:
- values[0] = x + ((x < 270) ? 90 : -270);
- values[1] = z;
- values[2] = y;
- break;
- }
- }
- }
- }
-
- class LmsFilter {
- private static final int SENSORS_RATE_MS = 20;
- private static final int COUNT = 12;
- private static final float PREDICTION_RATIO = 1.0f/3.0f;
- private static final float PREDICTION_TIME = (SENSORS_RATE_MS*COUNT/1000.0f)*PREDICTION_RATIO;
- private float mV[] = new float[COUNT*2];
- private float mT[] = new float[COUNT*2];
- private int mIndex;
-
- public LmsFilter() {
- mIndex = COUNT;
- }
-
- public float filter(long time, float in) {
- float v = in;
- final float ns = 1.0f / 1000000000.0f;
- final float t = time*ns;
- float v1 = mV[mIndex];
- if ((v-v1) > 180) {
- v -= 360;
- } else if ((v1-v) > 180) {
- v += 360;
- }
- /* Manage the circular buffer, we write the data twice spaced
- * by COUNT values, so that we don't have to copy the array
- * when it's full
- */
- mIndex++;
- if (mIndex >= COUNT*2)
- mIndex = COUNT;
- mV[mIndex] = v;
- mT[mIndex] = t;
- mV[mIndex-COUNT] = v;
- mT[mIndex-COUNT] = t;
-
- float A, B, C, D, E;
- float a, b;
- int i;
-
- A = B = C = D = E = 0;
- for (i=0 ; i<COUNT-1 ; i++) {
- final int j = mIndex - 1 - i;
- final float Z = mV[j];
- final float T = 0.5f*(mT[j] + mT[j+1]) - t;
- float dT = mT[j] - mT[j+1];
- dT *= dT;
- A += Z*dT;
- B += T*(T*dT);
- C += (T*dT);
- D += Z*(T*dT);
- E += dT;
- }
- b = (A*B + C*D) / (E*B + C*C);
- a = (E*b - A) / C;
- float f = b + PREDICTION_TIME*a;
-
- // Normalize
- f *= (1.0f / 360.0f);
- if (((f>=0)?f:-f) >= 0.5f)
- f = f - (float)Math.ceil(f + 0.5f) + 1.0f;
- if (f < 0)
- f += 1.0f;
- f *= 360.0f;
- return f;
- }
- }
-
-
- private static native void nativeClassInit();
-
- private static native int sensors_module_init();
- private static native int sensors_module_get_next_sensor(Sensor sensor, int next);
-
- // Used within this module from outside SensorManager, don't make private
- static native int sensors_data_init();
- static native int sensors_data_uninit();
- static native int sensors_data_open(FileDescriptor fd);
- static native int sensors_data_close();
- static native int sensors_data_poll(float[] values, int[] status, long[] timestamp);
-}
diff --git a/core/java/android/hardware/package.html b/core/java/android/hardware/package.html
deleted file mode 100644
index 06788a6..0000000
--- a/core/java/android/hardware/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<HTML>
-<BODY>
-Provides support for hardware devices that may not be present on every Android device.
-</BODY>
-</HTML>
diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java
deleted file mode 100644
index eedcc35..0000000
--- a/core/java/android/inputmethodservice/AbstractInputMethodService.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.inputmethodservice;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.inputmethod.InputMethod;
-import android.view.inputmethod.InputMethodSession;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * AbstractInputMethodService provides a abstract base class for input methods.
- * Normal input method implementations will not derive from this directly,
- * instead building on top of {@link InputMethodService} or another more
- * complete base class. Be sure to read {@link InputMethod} for more
- * information on the basics of writing input methods.
- *
- * <p>This class combines a Service (representing the input method component
- * to the system with the InputMethod interface that input methods must
- * implement. This base class takes care of reporting your InputMethod from
- * the service when clients bind to it, but provides no standard implementation
- * of the InputMethod interface itself. Derived classes must implement that
- * interface.
- */
-public abstract class AbstractInputMethodService extends Service
- implements KeyEvent.Callback {
- private InputMethod mInputMethod;
-
- /**
- * Base class for derived classes to implement their {@link InputMethod}
- * interface. This takes care of basic maintenance of the input method,
- * but most behavior must be implemented in a derived class.
- */
- public abstract class AbstractInputMethodImpl implements InputMethod {
- /**
- * Instantiate a new client session for the input method, by calling
- * back to {@link AbstractInputMethodService#onCreateInputMethodSessionInterface()
- * AbstractInputMethodService.onCreateInputMethodSessionInterface()}.
- */
- public void createSession(SessionCallback callback) {
- callback.sessionCreated(onCreateInputMethodSessionInterface());
- }
-
- /**
- * Take care of enabling or disabling an existing session by calling its
- * {@link AbstractInputMethodSessionImpl#revokeSelf()
- * AbstractInputMethodSessionImpl.setEnabled()} method.
- */
- public void setSessionEnabled(InputMethodSession session, boolean enabled) {
- ((AbstractInputMethodSessionImpl)session).setEnabled(enabled);
- }
-
- /**
- * Take care of killing an existing session by calling its
- * {@link AbstractInputMethodSessionImpl#revokeSelf()
- * AbstractInputMethodSessionImpl.revokeSelf()} method.
- */
- public void revokeSession(InputMethodSession session) {
- ((AbstractInputMethodSessionImpl)session).revokeSelf();
- }
- }
-
- /**
- * Base class for derived classes to implement their {@link InputMethodSession}
- * interface. This takes care of basic maintenance of the session,
- * but most behavior must be implemented in a derived class.
- */
- public abstract class AbstractInputMethodSessionImpl implements InputMethodSession {
- boolean mEnabled = true;
- boolean mRevoked;
-
- /**
- * Check whether this session has been enabled by the system. If not
- * enabled, you should not execute any calls on to it.
- */
- public boolean isEnabled() {
- return mEnabled;
- }
-
- /**
- * Check whether this session has been revoked by the system. Revoked
- * session is also always disabled, so there is generally no need to
- * explicitly check for this.
- */
- public boolean isRevoked() {
- return mRevoked;
- }
-
- /**
- * Change the enabled state of the session. This only works if the
- * session has not been revoked.
- */
- public void setEnabled(boolean enabled) {
- if (!mRevoked) {
- mEnabled = enabled;
- }
- }
-
- /**
- * Revoke the session from the client. This disabled the session, and
- * prevents it from ever being enabled again.
- */
- public void revokeSelf() {
- mRevoked = true;
- mEnabled = false;
- }
-
- /**
- * Take care of dispatching incoming key events to the appropriate
- * callbacks on the service, and tell the client when this is done.
- */
- public void dispatchKeyEvent(int seq, KeyEvent event, EventCallback callback) {
- boolean handled = event.dispatch(AbstractInputMethodService.this);
- if (callback != null) {
- callback.finishedEvent(seq, handled);
- }
- }
-
- /**
- * Take care of dispatching incoming trackball events to the appropriate
- * callbacks on the service, and tell the client when this is done.
- */
- public void dispatchTrackballEvent(int seq, MotionEvent event, EventCallback callback) {
- boolean handled = onTrackballEvent(event);
- if (callback != null) {
- callback.finishedEvent(seq, handled);
- }
- }
- }
-
- /**
- * Called by the framework during initialization, when the InputMethod
- * interface for this service needs to be created.
- */
- public abstract AbstractInputMethodImpl onCreateInputMethodInterface();
-
- /**
- * Called by the framework when a new InputMethodSession interface is
- * needed for a new client of the input method.
- */
- public abstract AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface();
-
- /**
- * Implement this to handle {@link android.os.Binder#dump Binder.dump()}
- * calls on your input method.
- */
- protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
- }
-
- @Override
- final public IBinder onBind(Intent intent) {
- if (mInputMethod == null) {
- mInputMethod = onCreateInputMethodInterface();
- }
- return new IInputMethodWrapper(this, mInputMethod);
- }
-
- public boolean onTrackballEvent(MotionEvent event) {
- return false;
- }
-}
diff --git a/core/java/android/inputmethodservice/ExtractEditText.java b/core/java/android/inputmethodservice/ExtractEditText.java
deleted file mode 100644
index 52f8209..0000000
--- a/core/java/android/inputmethodservice/ExtractEditText.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package android.inputmethodservice;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.inputmethod.ExtractedText;
-import android.widget.EditText;
-
-/***
- * Specialization of {@link EditText} for showing and interacting with the
- * extracted text in a full-screen input method.
- */
-public class ExtractEditText extends EditText {
- private InputMethodService mIME;
- private int mSettingExtractedText;
-
- public ExtractEditText(Context context) {
- super(context, null);
- }
-
- public ExtractEditText(Context context, AttributeSet attrs) {
- super(context, attrs, com.android.internal.R.attr.editTextStyle);
- }
-
- public ExtractEditText(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- void setIME(InputMethodService ime) {
- mIME = ime;
- }
-
- /**
- * Start making changes that will not be reported to the client. That
- * is, {@link #onSelectionChanged(int, int)} will not result in sending
- * the new selection to the client
- */
- public void startInternalChanges() {
- mSettingExtractedText += 1;
- }
-
- /**
- * Finish making changes that will not be reported to the client. That
- * is, {@link #onSelectionChanged(int, int)} will not result in sending
- * the new selection to the client
- */
- public void finishInternalChanges() {
- mSettingExtractedText -= 1;
- }
-
- /**
- * Implement just to keep track of when we are setting text from the
- * client (vs. seeing changes in ourself from the user).
- */
- @Override public void setExtractedText(ExtractedText text) {
- try {
- mSettingExtractedText++;
- super.setExtractedText(text);
- } finally {
- mSettingExtractedText--;
- }
- }
-
- /**
- * Report to the underlying text editor about selection changes.
- */
- @Override protected void onSelectionChanged(int selStart, int selEnd) {
- if (mSettingExtractedText == 0 && mIME != null && selStart >= 0 && selEnd >= 0) {
- mIME.onExtractedSelectionChanged(selStart, selEnd);
- }
- }
-
- /**
- * Redirect clicks to the IME for handling there. First allows any
- * on click handler to run, though.
- */
- @Override public boolean performClick() {
- if (!super.performClick() && mIME != null) {
- mIME.onExtractedTextClicked();
- return true;
- }
- return false;
- }
-
- @Override public boolean onTextContextMenuItem(int id) {
- if (mIME != null) {
- if (mIME.onExtractTextContextMenuItem(id)) {
- return true;
- }
- }
- return super.onTextContextMenuItem(id);
- }
-
- /**
- * We are always considered to be an input method target.
- */
- public boolean isInputMethodTarget() {
- return true;
- }
-
- /**
- * Pretend like the window this view is in always has focus, so its
- * highlight and cursor will be displayed.
- */
- @Override public boolean hasWindowFocus() {
- return this.isEnabled() ? true : false;
- }
-
- /**
- * Pretend like this view always has focus, so its
- * highlight and cursor will be displayed.
- */
- @Override public boolean isFocused() {
- return this.isEnabled() ? true : false;
- }
-
- /**
- * Pretend like this view always has focus, so its
- * highlight and cursor will be displayed.
- */
- @Override public boolean hasFocus() {
- return this.isEnabled() ? true : false;
- }
-}
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
deleted file mode 100644
index 5a85c66..0000000
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package android.inputmethodservice;
-
-import com.android.internal.os.HandlerCaller;
-import com.android.internal.view.IInputMethodCallback;
-import com.android.internal.view.IInputMethodSession;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.ExtractedText;
-import android.view.inputmethod.InputMethodSession;
-import android.view.inputmethod.EditorInfo;
-
-class IInputMethodSessionWrapper extends IInputMethodSession.Stub
- implements HandlerCaller.Callback {
- private static final String TAG = "InputMethodWrapper";
- private static final boolean DEBUG = false;
-
- private static final int DO_FINISH_INPUT = 60;
- private static final int DO_DISPLAY_COMPLETIONS = 65;
- private static final int DO_UPDATE_EXTRACTED_TEXT = 67;
- private static final int DO_DISPATCH_KEY_EVENT = 70;
- private static final int DO_DISPATCH_TRACKBALL_EVENT = 80;
- private static final int DO_UPDATE_SELECTION = 90;
- private static final int DO_UPDATE_CURSOR = 95;
- private static final int DO_APP_PRIVATE_COMMAND = 100;
-
- final HandlerCaller mCaller;
- final InputMethodSession mInputMethodSession;
-
- // NOTE: we should have a cache of these.
- static class InputMethodEventCallbackWrapper implements InputMethodSession.EventCallback {
- final IInputMethodCallback mCb;
- InputMethodEventCallbackWrapper(IInputMethodCallback cb) {
- mCb = cb;
- }
- public void finishedEvent(int seq, boolean handled) {
- try {
- mCb.finishedEvent(seq, handled);
- } catch (RemoteException e) {
- }
- }
- }
-
- public IInputMethodSessionWrapper(Context context,
- InputMethodSession inputMethodSession) {
- mCaller = new HandlerCaller(context, this);
- mInputMethodSession = inputMethodSession;
- }
-
- public InputMethodSession getInternalInputMethodSession() {
- return mInputMethodSession;
- }
-
- public void executeMessage(Message msg) {
- switch (msg.what) {
- case DO_FINISH_INPUT:
- mInputMethodSession.finishInput();
- return;
- case DO_DISPLAY_COMPLETIONS:
- mInputMethodSession.displayCompletions((CompletionInfo[])msg.obj);
- return;
- case DO_UPDATE_EXTRACTED_TEXT:
- mInputMethodSession.updateExtractedText(msg.arg1,
- (ExtractedText)msg.obj);
- return;
- case DO_DISPATCH_KEY_EVENT: {
- HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
- mInputMethodSession.dispatchKeyEvent(msg.arg1,
- (KeyEvent)args.arg1,
- new InputMethodEventCallbackWrapper(
- (IInputMethodCallback)args.arg2));
- mCaller.recycleArgs(args);
- return;
- }
- case DO_DISPATCH_TRACKBALL_EVENT: {
- HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
- mInputMethodSession.dispatchTrackballEvent(msg.arg1,
- (MotionEvent)args.arg1,
- new InputMethodEventCallbackWrapper(
- (IInputMethodCallback)args.arg2));
- mCaller.recycleArgs(args);
- return;
- }
- case DO_UPDATE_SELECTION: {
- HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
- mInputMethodSession.updateSelection(args.argi1, args.argi2,
- args.argi3, args.argi4, args.argi5, args.argi6);
- mCaller.recycleArgs(args);
- return;
- }
- case DO_UPDATE_CURSOR: {
- mInputMethodSession.updateCursor((Rect)msg.obj);
- return;
- }
- case DO_APP_PRIVATE_COMMAND: {
- HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
- mInputMethodSession.appPrivateCommand((String)args.arg1,
- (Bundle)args.arg2);
- mCaller.recycleArgs(args);
- return;
- }
- }
- Log.w(TAG, "Unhandled message code: " + msg.what);
- }
-
- public void finishInput() {
- mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_INPUT));
- }
-
- public void displayCompletions(CompletionInfo[] completions) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageO(
- DO_DISPLAY_COMPLETIONS, completions));
- }
-
- public void updateExtractedText(int token, ExtractedText text) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageIO(
- DO_UPDATE_EXTRACTED_TEXT, token, text));
- }
-
- public void dispatchKeyEvent(int seq, KeyEvent event, IInputMethodCallback callback) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_DISPATCH_KEY_EVENT, seq,
- event, callback));
- }
-
- public void dispatchTrackballEvent(int seq, MotionEvent event, IInputMethodCallback callback) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_DISPATCH_TRACKBALL_EVENT, seq,
- event, callback));
- }
-
- public void updateSelection(int oldSelStart, int oldSelEnd,
- int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageIIIIII(DO_UPDATE_SELECTION,
- oldSelStart, oldSelEnd, newSelStart, newSelEnd,
- candidatesStart, candidatesEnd));
- }
-
- public void updateCursor(Rect newCursor) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_UPDATE_CURSOR,
- newCursor));
- }
-
- public void appPrivateCommand(String action, Bundle data) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_APP_PRIVATE_COMMAND, action, data));
- }
-}
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
deleted file mode 100644
index a2c75b5..0000000
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ /dev/null
@@ -1,236 +0,0 @@
-package android.inputmethodservice;
-
-import com.android.internal.os.HandlerCaller;
-import com.android.internal.view.IInputContext;
-import com.android.internal.view.IInputMethod;
-import com.android.internal.view.IInputMethodCallback;
-import com.android.internal.view.IInputMethodSession;
-import com.android.internal.view.InputConnectionWrapper;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputBinding;
-import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputMethod;
-import android.view.inputmethod.InputMethodSession;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Implements the internal IInputMethod interface to convert incoming calls
- * on to it back to calls on the public InputMethod interface, scheduling
- * them on the main thread of the process.
- */
-class IInputMethodWrapper extends IInputMethod.Stub
- implements HandlerCaller.Callback {
- private static final String TAG = "InputMethodWrapper";
- private static final boolean DEBUG = false;
-
- private static final int DO_DUMP = 1;
- private static final int DO_ATTACH_TOKEN = 10;
- private static final int DO_SET_INPUT_CONTEXT = 20;
- private static final int DO_UNSET_INPUT_CONTEXT = 30;
- private static final int DO_START_INPUT = 32;
- private static final int DO_RESTART_INPUT = 34;
- private static final int DO_CREATE_SESSION = 40;
- private static final int DO_SET_SESSION_ENABLED = 45;
- private static final int DO_REVOKE_SESSION = 50;
- private static final int DO_SHOW_SOFT_INPUT = 60;
- private static final int DO_HIDE_SOFT_INPUT = 70;
-
- final AbstractInputMethodService mTarget;
- final HandlerCaller mCaller;
- final InputMethod mInputMethod;
-
- static class Notifier {
- boolean notified;
- }
-
- // NOTE: we should have a cache of these.
- static class InputMethodSessionCallbackWrapper implements InputMethod.SessionCallback {
- final Context mContext;
- final IInputMethodCallback mCb;
- InputMethodSessionCallbackWrapper(Context context, IInputMethodCallback cb) {
- mContext = context;
- mCb = cb;
- }
- public void sessionCreated(InputMethodSession session) {
- try {
- if (session != null) {
- IInputMethodSessionWrapper wrap =
- new IInputMethodSessionWrapper(mContext, session);
- mCb.sessionCreated(wrap);
- } else {
- mCb.sessionCreated(null);
- }
- } catch (RemoteException e) {
- }
- }
- }
-
- public IInputMethodWrapper(AbstractInputMethodService context,
- InputMethod inputMethod) {
- mTarget = context;
- mCaller = new HandlerCaller(context, this);
- mInputMethod = inputMethod;
- }
-
- public InputMethod getInternalInputMethod() {
- return mInputMethod;
- }
-
- public void executeMessage(Message msg) {
- switch (msg.what) {
- case DO_DUMP: {
- HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
- try {
- mTarget.dump((FileDescriptor)args.arg1,
- (PrintWriter)args.arg2, (String[])args.arg3);
- } catch (RuntimeException e) {
- ((PrintWriter)args.arg2).println("Exception: " + e);
- }
- synchronized (args.arg4) {
- ((CountDownLatch)args.arg4).countDown();
- }
- return;
- }
-
- case DO_ATTACH_TOKEN: {
- mInputMethod.attachToken((IBinder)msg.obj);
- return;
- }
- case DO_SET_INPUT_CONTEXT: {
- mInputMethod.bindInput((InputBinding)msg.obj);
- return;
- }
- case DO_UNSET_INPUT_CONTEXT:
- mInputMethod.unbindInput();
- return;
- case DO_START_INPUT: {
- HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
- IInputContext inputContext = (IInputContext)args.arg1;
- InputConnection ic = inputContext != null
- ? new InputConnectionWrapper(inputContext) : null;
- mInputMethod.startInput(ic, (EditorInfo)args.arg2);
- return;
- }
- case DO_RESTART_INPUT: {
- HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
- IInputContext inputContext = (IInputContext)args.arg1;
- InputConnection ic = inputContext != null
- ? new InputConnectionWrapper(inputContext) : null;
- mInputMethod.restartInput(ic, (EditorInfo)args.arg2);
- return;
- }
- case DO_CREATE_SESSION: {
- mInputMethod.createSession(new InputMethodSessionCallbackWrapper(
- mCaller.mContext, (IInputMethodCallback)msg.obj));
- return;
- }
- case DO_SET_SESSION_ENABLED:
- mInputMethod.setSessionEnabled((InputMethodSession)msg.obj,
- msg.arg1 != 0);
- return;
- case DO_REVOKE_SESSION:
- mInputMethod.revokeSession((InputMethodSession)msg.obj);
- return;
- case DO_SHOW_SOFT_INPUT:
- mInputMethod.showSoftInput(msg.arg1);
- return;
- case DO_HIDE_SOFT_INPUT:
- mInputMethod.hideSoftInput();
- return;
- }
- Log.w(TAG, "Unhandled message code: " + msg.what);
- }
-
- @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
- if (mTarget.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
-
- fout.println("Permission Denial: can't dump InputMethodManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
- CountDownLatch latch = new CountDownLatch(1);
- mCaller.executeOrSendMessage(mCaller.obtainMessageOOOO(DO_DUMP,
- fd, fout, args, latch));
- try {
- if (!latch.await(5, TimeUnit.SECONDS)) {
- fout.println("Timeout waiting for dump");
- }
- } catch (InterruptedException e) {
- fout.println("Interrupted waiting for dump");
- }
- }
-
- public void attachToken(IBinder token) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_ATTACH_TOKEN, token));
- }
-
- public void bindInput(InputBinding binding) {
- InputConnection ic = new InputConnectionWrapper(
- IInputContext.Stub.asInterface(binding.getConnectionToken()));
- InputBinding nu = new InputBinding(ic, binding);
- mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_INPUT_CONTEXT, nu));
- }
-
- public void unbindInput() {
- mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_UNSET_INPUT_CONTEXT));
- }
-
- public void startInput(IInputContext inputContext, EditorInfo attribute) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_START_INPUT,
- inputContext, attribute));
- }
-
- public void restartInput(IInputContext inputContext, EditorInfo attribute) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_RESTART_INPUT,
- inputContext, attribute));
- }
-
- public void createSession(IInputMethodCallback callback) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_CREATE_SESSION, callback));
- }
-
- public void setSessionEnabled(IInputMethodSession session, boolean enabled) {
- try {
- InputMethodSession ls = ((IInputMethodSessionWrapper)
- session).getInternalInputMethodSession();
- mCaller.executeOrSendMessage(mCaller.obtainMessageIO(
- DO_SET_SESSION_ENABLED, enabled ? 1 : 0, ls));
- } catch (ClassCastException e) {
- Log.w(TAG, "Incoming session not of correct type: " + session, e);
- }
- }
-
- public void revokeSession(IInputMethodSession session) {
- try {
- InputMethodSession ls = ((IInputMethodSessionWrapper)
- session).getInternalInputMethodSession();
- mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_REVOKE_SESSION, ls));
- } catch (ClassCastException e) {
- Log.w(TAG, "Incoming session not of correct type: " + session, e);
- }
- }
-
- public void showSoftInput(int flags) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageI(DO_SHOW_SOFT_INPUT,
- flags));
- }
-
- public void hideSoftInput() {
- mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_HIDE_SOFT_INPUT));
- }
-}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
deleted file mode 100644
index 4be1fc7..0000000
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ /dev/null
@@ -1,1636 +0,0 @@
-/*
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.inputmethodservice;
-
-import static android.view.ViewGroup.LayoutParams.FILL_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.provider.Settings;
-import android.text.Layout;
-import android.text.Spannable;
-import android.text.method.MovementMethod;
-import android.util.Log;
-import android.util.PrintWriterPrinter;
-import android.util.Printer;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.ExtractedText;
-import android.view.inputmethod.ExtractedTextRequest;
-import android.view.inputmethod.InputBinding;
-import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputMethod;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.EditorInfo;
-import android.widget.FrameLayout;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * InputMethodService provides a standard implementation of an InputMethod,
- * which final implementations can derive from and customize. See the
- * base class {@link AbstractInputMethodService} and the {@link InputMethod}
- * interface for more information on the basics of writing input methods.
- *
- * <p>In addition to the normal Service lifecycle methods, this class
- * introduces some new specific callbacks that most subclasses will want
- * to make use of:</p>
- * <ul>
- * <li> {@link #onInitializeInterface()} for user-interface initialization,
- * in particular to deal with configuration changes while the service is
- * running.
- * <li> {@link #onBindInput} to find out about switching to a new client.
- * <li> {@link #onStartInput} to deal with an input session starting with
- * the client.
- * <li> {@link #onCreateInputView()}, {@link #onCreateCandidatesView()},
- * and {@link #onCreateExtractTextView()} for non-demand generation of the UI.
- * <li> {@link #onStartInputView(EditorInfo, boolean)} to deal with input
- * starting within the input area of the IME.
- * </ul>
- *
- * <p>An input method has significant discretion in how it goes about its
- * work: the {@link android.inputmethodservice.InputMethodService} provides
- * a basic framework for standard UI elements (input view, candidates view,
- * and running in fullscreen mode), but it is up to a particular implementor
- * to decide how to use them. For example, one input method could implement
- * an input area with a keyboard, another could allow the user to draw text,
- * while a third could have no input area (and thus not be visible to the
- * user) but instead listen to audio and perform text to speech conversion.</p>
- *
- * <p>In the implementation provided here, all of these elements are placed
- * together in a single window managed by the InputMethodService. It will
- * execute callbacks as it needs information about them, and provides APIs for
- * programmatic control over them. They layout of these elements is explicitly
- * defined:</p>
- *
- * <ul>
- * <li>The soft input view, if available, is placed at the bottom of the
- * screen.
- * <li>The candidates view, if currently shown, is placed above the soft
- * input view.
- * <li>If not running fullscreen, the application is moved or resized to be
- * above these views; if running fullscreen, the window will completely cover
- * the application and its top part will contain the extract text of what is
- * currently being edited by the application.
- * </ul>
- *
- *
- * <a name="SoftInputView"></a>
- * <h3>Soft Input View</h3>
- *
- * <p>Central to most input methods is the soft input view. This is where most
- * user interaction occurs: pressing on soft keys, drawing characters, or
- * however else your input method wants to generate text. Most implementations
- * will simply have their own view doing all of this work, and return a new
- * instance of it when {@link #onCreateInputView()} is called. At that point,
- * as long as the input view is visible, you will see user interaction in
- * that view and can call back on the InputMethodService to interact with the
- * application as appropriate.</p>
- *
- * <p>There are some situations where you want to decide whether or not your
- * soft input view should be shown to the user. This is done by implementing
- * the {@link #onEvaluateInputViewShown()} to return true or false based on
- * whether it should be shown in the current environment. If any of your
- * state has changed that may impact this, call
- * {@link #updateInputViewShown()} to have it re-evaluated. The default
- * implementation always shows the input view unless there is a hard
- * keyboard available, which is the appropriate behavior for most input
- * methods.</p>
- *
- *
- * <a name="CandidatesView"></a>
- * <h3>Candidates View</h3>
- *
- * <p>Often while the user is generating raw text, an input method wants to
- * provide them with a list of possible interpretations of that text that can
- * be selected for use. This is accomplished with the candidates view, and
- * like the soft input view you implement {@link #onCreateCandidatesView()}
- * to instantiate your own view implementing your candidates UI.</p>
- *
- * <p>Management of the candidates view is a little different than the input
- * view, because the candidates view tends to be more transient, being shown
- * only when there are possible candidates for the current text being entered
- * by the user. To control whether the candidates view is shown, you use
- * {@link #setCandidatesViewShown(boolean)}. Note that because the candidate
- * view tends to be shown and hidden a lot, it does not impact the application
- * UI in the same way as the soft input view: it will never cause application
- * windows to resize, only cause them to be panned if needed for the user to
- * see the current focus.</p>
- *
- *
- * <a name="FullscreenMode"></a>
- * <h3>Fullscreen Mode</h3>
- *
- * <p>Sometimes your input method UI is too large to integrate with the
- * application UI, so you just want to take over the screen. This is
- * accomplished by switching to full-screen mode, causing the input method
- * window to fill the entire screen and add its own "extracted text" editor
- * showing the user the text that is being typed. Unlike the other UI elements,
- * there is a standard implementation for the extract editor that you should
- * not need to change. The editor is placed at the top of the IME, above the
- * input and candidates views.</p>
- *
- * <p>Similar to the input view, you control whether the IME is running in
- * fullscreen mode by implementing {@link #onEvaluateFullscreenMode()}
- * to return true or false based on
- * whether it should be fullscreen in the current environment. If any of your
- * state has changed that may impact this, call
- * {@link #updateFullscreenMode()} to have it re-evaluated. The default
- * implementation selects fullscreen mode when the screen is in a landscape
- * orientation, which is appropriate behavior for most input methods that have
- * a significant input area.</p>
- *
- * <p>When in fullscreen mode, you have some special requirements because the
- * user can not see the application UI. In particular, you should implement
- * {@link #onDisplayCompletions(CompletionInfo[])} to show completions
- * generated by your application, typically in your candidates view like you
- * would normally show candidates.
- *
- *
- * <a name="GeneratingText"></a>
- * <h3>Generating Text</h3>
- *
- * <p>The key part of an IME is of course generating text for the application.
- * This is done through calls to the
- * {@link android.view.inputmethod.InputConnection} interface to the
- * application, which can be retrieved from {@link #getCurrentInputConnection()}.
- * This interface allows you to generate raw key events or, if the target
- * supports it, directly edit in strings of candidates and committed text.</p>
- *
- * <p>Information about what the target is expected and supports can be found
- * through the {@link android.view.inputmethod.EditorInfo} class, which is
- * retrieved with {@link #getCurrentInputEditorInfo()} method. The most
- * important part of this is {@link android.view.inputmethod.EditorInfo#inputType
- * EditorInfo.inputType}; in particular, if this is
- * {@link android.view.inputmethod.EditorInfo#TYPE_NULL EditorInfo.TYPE_NULL},
- * then the target does not support complex edits and you need to only deliver
- * raw key events to it. An input method will also want to look at other
- * values here, to for example detect password mode, auto complete text views,
- * phone number entry, etc.</p>
- *
- * <p>When the user switches between input targets, you will receive calls to
- * {@link #onFinishInput()} and {@link #onStartInput(EditorInfo, boolean)}.
- * You can use these to reset and initialize your input state for the current
- * target. For example, you will often want to clear any input state, and
- * update a soft keyboard to be appropriate for the new inputType.</p>
- */
-public class InputMethodService extends AbstractInputMethodService {
- static final String TAG = "InputMethodService";
- static final boolean DEBUG = false;
-
- InputMethodManager mImm;
-
- LayoutInflater mInflater;
- View mRootView;
- SoftInputWindow mWindow;
- boolean mInitialized;
- boolean mWindowCreated;
- boolean mWindowAdded;
- boolean mWindowVisible;
- FrameLayout mExtractFrame;
- FrameLayout mCandidatesFrame;
- FrameLayout mInputFrame;
-
- IBinder mToken;
-
- InputBinding mInputBinding;
- InputConnection mInputConnection;
- boolean mInputStarted;
- boolean mInputViewStarted;
- boolean mCandidatesViewStarted;
- InputConnection mStartedInputConnection;
- EditorInfo mInputEditorInfo;
-
- int mShowInputFlags;
- boolean mShowInputRequested;
- boolean mLastShowInputRequested;
- int mCandidatesVisibility;
- CompletionInfo[] mCurCompletions;
-
- boolean mShowInputForced;
-
- boolean mFullscreenApplied;
- boolean mIsFullscreen;
- View mExtractView;
- ExtractEditText mExtractEditText;
- ExtractedText mExtractedText;
- int mExtractedToken;
-
- View mInputView;
- boolean mIsInputViewShown;
-
- int mStatusIcon;
-
- final Insets mTmpInsets = new Insets();
- final int[] mTmpLocation = new int[2];
-
- final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer =
- new ViewTreeObserver.OnComputeInternalInsetsListener() {
- public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
- if (isFullscreenMode()) {
- // In fullscreen mode, we just say the window isn't covering
- // any content so we don't impact whatever is behind.
- View decor = getWindow().getWindow().getDecorView();
- info.contentInsets.top = info.visibleInsets.top
- = decor.getHeight();
- info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
- } else {
- onComputeInsets(mTmpInsets);
- info.contentInsets.top = mTmpInsets.contentTopInsets;
- info.visibleInsets.top = mTmpInsets.visibleTopInsets;
- info.setTouchableInsets(mTmpInsets.touchableInsets);
- }
- }
- };
-
- /**
- * Concrete implementation of
- * {@link AbstractInputMethodService.AbstractInputMethodImpl} that provides
- * all of the standard behavior for an input method.
- */
- public class InputMethodImpl extends AbstractInputMethodImpl {
- /**
- * Take care of attaching the given window token provided by the system.
- */
- public void attachToken(IBinder token) {
- if (mToken == null) {
- mToken = token;
- mWindow.setToken(token);
- }
- }
-
- /**
- * Handle a new input binding, calling
- * {@link InputMethodService#onBindInput InputMethodService.onBindInput()}
- * when done.
- */
- public void bindInput(InputBinding binding) {
- mInputBinding = binding;
- mInputConnection = binding.getConnection();
- if (DEBUG) Log.v(TAG, "bindInput(): binding=" + binding
- + " ic=" + mInputConnection);
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) ic.reportFullscreenMode(mIsFullscreen);
- initialize();
- onBindInput();
- }
-
- /**
- * Clear the current input binding.
- */
- public void unbindInput() {
- if (DEBUG) Log.v(TAG, "unbindInput(): binding=" + mInputBinding
- + " ic=" + mInputConnection);
- onUnbindInput();
- mInputStarted = false;
- mInputBinding = null;
- mInputConnection = null;
- }
-
- public void startInput(InputConnection ic, EditorInfo attribute) {
- if (DEBUG) Log.v(TAG, "startInput(): editor=" + attribute);
- doStartInput(ic, attribute, false);
- }
-
- public void restartInput(InputConnection ic, EditorInfo attribute) {
- if (DEBUG) Log.v(TAG, "restartInput(): editor=" + attribute);
- doStartInput(ic, attribute, true);
- }
-
- /**
- * Handle a request by the system to hide the soft input area.
- */
- public void hideSoftInput() {
- if (DEBUG) Log.v(TAG, "hideSoftInput()");
- mShowInputFlags = 0;
- mShowInputRequested = false;
- mShowInputForced = false;
- hideWindow();
- }
-
- /**
- * Handle a request by the system to show the soft input area.
- */
- public void showSoftInput(int flags) {
- if (DEBUG) Log.v(TAG, "showSoftInput()");
- mShowInputFlags = 0;
- if (onShowInputRequested(flags, false)) {
- showWindow(true);
- }
- }
- }
-
- /**
- * Concrete implementation of
- * {@link AbstractInputMethodService.AbstractInputMethodSessionImpl} that provides
- * all of the standard behavior for an input method session.
- */
- public class InputMethodSessionImpl extends AbstractInputMethodSessionImpl {
- public void finishInput() {
- if (!isEnabled()) {
- return;
- }
- if (DEBUG) Log.v(TAG, "finishInput() in " + this);
- doFinishInput();
- }
-
- /**
- * Call {@link InputMethodService#onDisplayCompletions
- * InputMethodService.onDisplayCompletions()}.
- */
- public void displayCompletions(CompletionInfo[] completions) {
- if (!isEnabled()) {
- return;
- }
- mCurCompletions = completions;
- onDisplayCompletions(completions);
- }
-
- /**
- * Call {@link InputMethodService#onUpdateExtractedText
- * InputMethodService.onUpdateExtractedText()}.
- */
- public void updateExtractedText(int token, ExtractedText text) {
- if (!isEnabled()) {
- return;
- }
- onUpdateExtractedText(token, text);
- }
-
- /**
- * Call {@link InputMethodService#onUpdateSelection
- * InputMethodService.onUpdateSelection()}.
- */
- public void updateSelection(int oldSelStart, int oldSelEnd,
- int newSelStart, int newSelEnd,
- int candidatesStart, int candidatesEnd) {
- if (!isEnabled()) {
- return;
- }
- InputMethodService.this.onUpdateSelection(oldSelStart, oldSelEnd,
- newSelStart, newSelEnd, candidatesStart, candidatesEnd);
- }
-
- /**
- * Call {@link InputMethodService#onUpdateCursor
- * InputMethodService.onUpdateCursor()}.
- */
- public void updateCursor(Rect newCursor) {
- if (!isEnabled()) {
- return;
- }
- InputMethodService.this.onUpdateCursor(newCursor);
- }
-
- /**
- * Call {@link InputMethodService#onAppPrivateCommand
- * InputMethodService.onAppPrivateCommand()}.
- */
- public void appPrivateCommand(String action, Bundle data) {
- if (!isEnabled()) {
- return;
- }
- InputMethodService.this.onAppPrivateCommand(action, data);
- }
- }
-
- /**
- * Information about where interesting parts of the input method UI appear.
- */
- public static final class Insets {
- /**
- * This is the top part of the UI that is the main content. It is
- * used to determine the basic space needed, to resize/pan the
- * application behind. It is assumed that this inset does not
- * change very much, since any change will cause a full resize/pan
- * of the application behind. This value is relative to the top edge
- * of the input method window.
- */
- public int contentTopInsets;
-
- /**
- * This is the top part of the UI that is visibly covering the
- * application behind it. This provides finer-grained control over
- * visibility, allowing you to change it relatively frequently (such
- * as hiding or showing candidates) without disrupting the underlying
- * UI too much. For example, this will never resize the application
- * UI, will only pan if needed to make the current focus visible, and
- * will not aggressively move the pan position when this changes unless
- * needed to make the focus visible. This value is relative to the top edge
- * of the input method window.
- */
- public int visibleTopInsets;
-
- /**
- * Option for {@link #touchableInsets}: the entire window frame
- * can be touched.
- */
- public static final int TOUCHABLE_INSETS_FRAME
- = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
-
- /**
- * Option for {@link #touchableInsets}: the area inside of
- * the content insets can be touched.
- */
- public static final int TOUCHABLE_INSETS_CONTENT
- = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
-
- /**
- * Option for {@link #touchableInsets}: the area inside of
- * the visible insets can be touched.
- */
- public static final int TOUCHABLE_INSETS_VISIBLE
- = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE;
-
- /**
- * Determine which area of the window is touchable by the user. May
- * be one of: {@link #TOUCHABLE_INSETS_FRAME},
- * {@link #TOUCHABLE_INSETS_CONTENT}, or {@link #TOUCHABLE_INSETS_VISIBLE}.
- */
- public int touchableInsets;
- }
-
- @Override public void onCreate() {
- super.onCreate();
- mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
- mInflater = (LayoutInflater)getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- mWindow = new SoftInputWindow(this);
- initViews();
- mWindow.getWindow().setLayout(FILL_PARENT, WRAP_CONTENT);
- }
-
- /**
- * This is a hook that subclasses can use to perform initialization of
- * their interface. It is called for you prior to any of your UI objects
- * being created, both after the service is first created and after a
- * configuration change happens.
- */
- public void onInitializeInterface() {
- }
-
- void initialize() {
- if (!mInitialized) {
- mInitialized = true;
- onInitializeInterface();
- }
- }
-
- void initViews() {
- mInitialized = false;
- mWindowCreated = false;
- mShowInputRequested = false;
- mShowInputForced = false;
-
- mRootView = mInflater.inflate(
- com.android.internal.R.layout.input_method, null);
- mWindow.setContentView(mRootView);
- mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
- if (Settings.System.getInt(getContentResolver(),
- Settings.System.FANCY_IME_ANIMATIONS, 0) != 0) {
- mWindow.getWindow().setWindowAnimations(
- com.android.internal.R.style.Animation_InputMethodFancy);
- }
- mExtractFrame = (FrameLayout)mRootView.findViewById(android.R.id.extractArea);
- mExtractView = null;
- mExtractEditText = null;
- mFullscreenApplied = false;
-
- mCandidatesFrame = (FrameLayout)mRootView.findViewById(android.R.id.candidatesArea);
- mInputFrame = (FrameLayout)mRootView.findViewById(android.R.id.inputArea);
- mInputView = null;
- mIsInputViewShown = false;
-
- mExtractFrame.setVisibility(View.GONE);
- mCandidatesVisibility = getCandidatesHiddenVisibility();
- mCandidatesFrame.setVisibility(mCandidatesVisibility);
- mInputFrame.setVisibility(View.GONE);
- }
-
- @Override public void onDestroy() {
- super.onDestroy();
- mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
- mInsetsComputer);
- if (mWindowAdded) {
- mWindow.dismiss();
- }
- }
-
- /**
- * Take care of handling configuration changes. Subclasses of
- * InputMethodService generally don't need to deal directly with
- * this on their own; the standard implementation here takes care of
- * regenerating the input method UI as a result of the configuration
- * change, so you can rely on your {@link #onCreateInputView} and
- * other methods being called as appropriate due to a configuration change.
- *
- * <p>When a configuration change does happen,
- * {@link #onInitializeInterface()} is guaranteed to be called the next
- * time prior to any of the other input or UI creation callbacks. The
- * following will be called immediately depending if appropriate for current
- * state: {@link #onStartInput} if input is active, and
- * {@link #onCreateInputView} and {@link #onStartInputView} and related
- * appropriate functions if the UI is displayed.
- */
- @Override public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
-
- boolean visible = mWindowVisible;
- int showFlags = mShowInputFlags;
- boolean showingInput = mShowInputRequested;
- CompletionInfo[] completions = mCurCompletions;
- initViews();
- mInputViewStarted = false;
- mCandidatesViewStarted = false;
- if (mInputStarted) {
- doStartInput(getCurrentInputConnection(),
- getCurrentInputEditorInfo(), true);
- }
- if (visible) {
- if (showingInput) {
- // If we were last showing the soft keyboard, try to do so again.
- if (onShowInputRequested(showFlags, true)) {
- showWindow(true);
- if (completions != null) {
- mCurCompletions = completions;
- onDisplayCompletions(completions);
- }
- } else {
- hideWindow();
- }
- } else if (mCandidatesVisibility == View.VISIBLE) {
- // If the candidates are currently visible, make sure the
- // window is shown for them.
- showWindow(false);
- } else {
- // Otherwise hide the window.
- hideWindow();
- }
- }
- }
-
- /**
- * Implement to return our standard {@link InputMethodImpl}. Subclasses
- * can override to provide their own customized version.
- */
- public AbstractInputMethodImpl onCreateInputMethodInterface() {
- return new InputMethodImpl();
- }
-
- /**
- * Implement to return our standard {@link InputMethodSessionImpl}. Subclasses
- * can override to provide their own customized version.
- */
- public AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface() {
- return new InputMethodSessionImpl();
- }
-
- public LayoutInflater getLayoutInflater() {
- return mInflater;
- }
-
- public Dialog getWindow() {
- return mWindow;
- }
-
- /**
- * Return the maximum width, in pixels, available the input method.
- * Input methods are positioned at the bottom of the screen and, unless
- * running in fullscreen, will generally want to be as short as possible
- * so should compute their height based on their contents. However, they
- * can stretch as much as needed horizontally. The function returns to
- * you the maximum amount of space available horizontally, which you can
- * use if needed for UI placement.
- *
- * <p>In many cases this is not needed, you can just rely on the normal
- * view layout mechanisms to position your views within the full horizontal
- * space given to the input method.
- *
- * <p>Note that this value can change dynamically, in particular when the
- * screen orientation changes.
- */
- public int getMaxWidth() {
- WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
- return wm.getDefaultDisplay().getWidth();
- }
-
- /**
- * Return the currently active InputBinding for the input method, or
- * null if there is none.
- */
- public InputBinding getCurrentInputBinding() {
- return mInputBinding;
- }
-
- /**
- * Retrieve the currently active InputConnection that is bound to
- * the input method, or null if there is none.
- */
- public InputConnection getCurrentInputConnection() {
- InputConnection ic = mStartedInputConnection;
- if (ic != null) {
- return ic;
- }
- return mInputConnection;
- }
-
- public boolean getCurrentInputStarted() {
- return mInputStarted;
- }
-
- public EditorInfo getCurrentInputEditorInfo() {
- return mInputEditorInfo;
- }
-
- /**
- * Re-evaluate whether the input method should be running in fullscreen
- * mode, and update its UI if this has changed since the last time it
- * was evaluated. This will call {@link #onEvaluateFullscreenMode()} to
- * determine whether it should currently run in fullscreen mode. You
- * can use {@link #isFullscreenMode()} to determine if the input method
- * is currently running in fullscreen mode.
- */
- public void updateFullscreenMode() {
- boolean isFullscreen = mShowInputRequested && onEvaluateFullscreenMode();
- boolean changed = mLastShowInputRequested != mShowInputRequested;
- if (mIsFullscreen != isFullscreen || !mFullscreenApplied) {
- changed = true;
- mIsFullscreen = isFullscreen;
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) ic.reportFullscreenMode(isFullscreen);
- mFullscreenApplied = true;
- initialize();
- Drawable bg = onCreateBackgroundDrawable();
- if (bg == null) {
- // We need to give the window a real drawable, so that it
- // correctly sets its mode.
- bg = getResources().getDrawable(android.R.color.transparent);
- }
- mWindow.getWindow().setBackgroundDrawable(bg);
- mExtractFrame.setVisibility(isFullscreen ? View.VISIBLE : View.GONE);
- if (isFullscreen) {
- if (mExtractView == null) {
- View v = onCreateExtractTextView();
- if (v != null) {
- setExtractView(v);
- }
- }
- startExtractingText();
- }
- }
-
- if (changed) {
- onConfigureWindow(mWindow.getWindow(), isFullscreen,
- !mShowInputRequested);
- mLastShowInputRequested = mShowInputRequested;
- }
- }
-
- /**
- * Update the given window's parameters for the given mode. This is called
- * when the window is first displayed and each time the fullscreen or
- * candidates only mode changes.
- *
- * <p>The default implementation makes the layout for the window
- * FILL_PARENT x FILL_PARENT when in fullscreen mode, and
- * FILL_PARENT x WRAP_CONTENT when in non-fullscreen mode.
- *
- * @param win The input method's window.
- * @param isFullscreen If true, the window is running in fullscreen mode
- * and intended to cover the entire application display.
- * @param isCandidatesOnly If true, the window is only showing the
- * candidates view and none of the rest of its UI. This is mutually
- * exclusive with fullscreen mode.
- */
- public void onConfigureWindow(Window win, boolean isFullscreen,
- boolean isCandidatesOnly) {
- if (isFullscreen) {
- mWindow.getWindow().setLayout(FILL_PARENT, FILL_PARENT);
- } else {
- mWindow.getWindow().setLayout(FILL_PARENT, WRAP_CONTENT);
- }
- }
-
- /**
- * Return whether the input method is <em>currently</em> running in
- * fullscreen mode. This is the mode that was last determined and
- * applied by {@link #updateFullscreenMode()}.
- */
- public boolean isFullscreenMode() {
- return mIsFullscreen;
- }
-
- /**
- * Override this to control when the input method should run in
- * fullscreen mode. The default implementation runs in fullsceen only
- * when the screen is in landscape mode. If you change what
- * this returns, you will need to call {@link #updateFullscreenMode()}
- * yourself whenever the returned value may have changed to have it
- * re-evaluated and applied.
- */
- public boolean onEvaluateFullscreenMode() {
- Configuration config = getResources().getConfiguration();
- return config.orientation == Configuration.ORIENTATION_LANDSCAPE;
- }
-
- /**
- * Compute the interesting insets into your UI. The default implementation
- * uses the top of the candidates frame for the visible insets, and the
- * top of the input frame for the content insets. The default touchable
- * insets are {@link Insets#TOUCHABLE_INSETS_VISIBLE}.
- *
- * <p>Note that this method is not called when in fullscreen mode, since
- * in that case the application is left as-is behind the input method and
- * not impacted by anything in its UI.
- *
- * @param outInsets Fill in with the current UI insets.
- */
- public void onComputeInsets(Insets outInsets) {
- int[] loc = mTmpLocation;
- if (mInputFrame.getVisibility() == View.VISIBLE) {
- mInputFrame.getLocationInWindow(loc);
- } else {
- loc[1] = 0;
- }
- outInsets.contentTopInsets = loc[1];
- if (mCandidatesFrame.getVisibility() == View.VISIBLE) {
- mCandidatesFrame.getLocationInWindow(loc);
- }
- outInsets.visibleTopInsets = loc[1];
- outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_VISIBLE;
- }
-
- /**
- * Re-evaluate whether the soft input area should currently be shown, and
- * update its UI if this has changed since the last time it
- * was evaluated. This will call {@link #onEvaluateInputViewShown()} to
- * determine whether the input view should currently be shown. You
- * can use {@link #isInputViewShown()} to determine if the input view
- * is currently shown.
- */
- public void updateInputViewShown() {
- boolean isShown = mShowInputRequested && onEvaluateInputViewShown();
- if (mIsInputViewShown != isShown && mWindowVisible) {
- mIsInputViewShown = isShown;
- mInputFrame.setVisibility(isShown ? View.VISIBLE : View.GONE);
- if (mInputView == null) {
- initialize();
- View v = onCreateInputView();
- if (v != null) {
- setInputView(v);
- }
- }
- }
- }
-
- /**
- * Returns true if we have been asked to show our input view.
- */
- public boolean isShowInputRequested() {
- return mShowInputRequested;
- }
-
- /**
- * Return whether the soft input view is <em>currently</em> shown to the
- * user. This is the state that was last determined and
- * applied by {@link #updateInputViewShown()}.
- */
- public boolean isInputViewShown() {
- return mIsInputViewShown && mWindowVisible;
- }
-
- /**
- * Override this to control when the soft input area should be shown to
- * the user. The default implementation only shows the input view when
- * there is no hard keyboard or the keyboard is hidden. If you change what
- * this returns, you will need to call {@link #updateInputViewShown()}
- * yourself whenever the returned value may have changed to have it
- * re-evalauted and applied.
- */
- public boolean onEvaluateInputViewShown() {
- Configuration config = getResources().getConfiguration();
- return config.keyboard == Configuration.KEYBOARD_NOKEYS
- || config.hardKeyboardHidden == Configuration.KEYBOARDHIDDEN_YES;
- }
-
- /**
- * Controls the visibility of the candidates display area. By default
- * it is hidden.
- */
- public void setCandidatesViewShown(boolean shown) {
- int vis = shown ? View.VISIBLE : getCandidatesHiddenVisibility();
- if (mCandidatesVisibility != vis) {
- mCandidatesFrame.setVisibility(vis);
- mCandidatesVisibility = vis;
- }
- if (!mShowInputRequested && mWindowVisible != shown) {
- // If we are being asked to show the candidates view while the app
- // has not asked for the input view to be shown, then we need
- // to update whether the window is shown.
- if (shown) {
- showWindow(false);
- } else {
- hideWindow();
- }
- }
- }
-
- /**
- * Returns the visibility mode (either {@link View#INVISIBLE View.INVISIBLE}
- * or {@link View#GONE View.GONE}) of the candidates view when it is not
- * shown. The default implementation returns GONE when in fullscreen mode,
- * otherwise VISIBLE. Be careful if you change this to return GONE in
- * other situations -- if showing or hiding the candidates view causes
- * your window to resize, this can cause temporary drawing artifacts as
- * the resize takes place.
- */
- public int getCandidatesHiddenVisibility() {
- return isFullscreenMode() ? View.GONE : View.INVISIBLE;
- }
-
- public void showStatusIcon(int iconResId) {
- mStatusIcon = iconResId;
- mImm.showStatusIcon(mToken, getPackageName(), iconResId);
- }
-
- public void hideStatusIcon() {
- mStatusIcon = 0;
- mImm.hideStatusIcon(mToken);
- }
-
- /**
- * Force switch to a new input method, as identified by <var>id</var>. This
- * input method will be destroyed, and the requested one started on the
- * current input field.
- *
- * @param id Unique identifier of the new input method ot start.
- */
- public void switchInputMethod(String id) {
- mImm.setInputMethod(mToken, id);
- }
-
- public void setExtractView(View view) {
- mExtractFrame.removeAllViews();
- mExtractFrame.addView(view, new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.FILL_PARENT));
- mExtractView = view;
- if (view != null) {
- mExtractEditText = (ExtractEditText)view.findViewById(
- com.android.internal.R.id.inputExtractEditText);
- mExtractEditText.setIME(this);
- startExtractingText();
- } else {
- mExtractEditText = null;
- }
- }
-
- /**
- * Replaces the current candidates view with a new one. You only need to
- * call this when dynamically changing the view; normally, you should
- * implement {@link #onCreateCandidatesView()} and create your view when
- * first needed by the input method.
- */
- public void setCandidatesView(View view) {
- mCandidatesFrame.removeAllViews();
- mCandidatesFrame.addView(view, new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
- }
-
- /**
- * Replaces the current input view with a new one. You only need to
- * call this when dynamically changing the view; normally, you should
- * implement {@link #onCreateInputView()} and create your view when
- * first needed by the input method.
- */
- public void setInputView(View view) {
- mInputFrame.removeAllViews();
- mInputFrame.addView(view, new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
- mInputView = view;
- }
-
- /**
- * Called by the framework to create a Drawable for the background of
- * the input method window. May return null for no background. The default
- * implementation returns a non-null standard background only when in
- * fullscreen mode. This is called each time the fullscreen mode changes.
- */
- public Drawable onCreateBackgroundDrawable() {
- if (isFullscreenMode()) {
- return getResources().getDrawable(
- com.android.internal.R.drawable.input_method_fullscreen_background);
- }
- return null;
- }
-
- /**
- * Called by the framework to create the layout for showing extacted text.
- * Only called when in fullscreen mode. The returned view hierarchy must
- * have an {@link ExtractEditText} whose ID is
- * {@link android.R.id#inputExtractEditText}.
- */
- public View onCreateExtractTextView() {
- return mInflater.inflate(
- com.android.internal.R.layout.input_method_extract_view, null);
- }
-
- /**
- * Create and return the view hierarchy used to show candidates. This will
- * be called once, when the candidates are first displayed. You can return
- * null to have no candidates view; the default implementation returns null.
- *
- * <p>To control when the candidates view is displayed, use
- * {@link #setCandidatesViewShown(boolean)}.
- * To change the candidates view after the first one is created by this
- * function, use {@link #setCandidatesView(View)}.
- */
- public View onCreateCandidatesView() {
- return null;
- }
-
- /**
- * Create and return the view hierarchy used for the input area (such as
- * a soft keyboard). This will be called once, when the input area is
- * first displayed. You can return null to have no input area; the default
- * implementation returns null.
- *
- * <p>To control when the input view is displayed, implement
- * {@link #onEvaluateInputViewShown()}.
- * To change the input view after the first one is created by this
- * function, use {@link #setInputView(View)}.
- */
- public View onCreateInputView() {
- return null;
- }
-
- /**
- * Called when the input view is being shown and input has started on
- * a new editor. This will always be called after {@link #onStartInput},
- * allowing you to do your general setup there and just view-specific
- * setup here. You are guaranteed that {@link #onCreateInputView()} will
- * have been called some time before this function is called.
- *
- * @param info Description of the type of text being edited.
- * @param restarting Set to true if we are restarting input on the
- * same text field as before.
- */
- public void onStartInputView(EditorInfo info, boolean restarting) {
- }
-
- /**
- * Called when the input view is being hidden from the user. This will
- * be called either prior to hiding the window, or prior to switching to
- * another target for editing.
- *
- * <p>The default
- * implementation uses the InputConnection to clear any active composing
- * text; you can override this (not calling the base class implementation)
- * to perform whatever behavior you would like.
- *
- * @boolean finishingInput If true, {@link #onFinishInput} will be
- * called immediately after.
- */
- public void onFinishInputView(boolean finishingInput) {
- if (!finishingInput) {
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- ic.finishComposingText();
- }
- }
- }
-
- /**
- * Called when only the candidates view has been shown for showing
- * processing as the user enters text through a hard keyboard.
- * This will always be called after {@link #onStartInput},
- * allowing you to do your general setup there and just view-specific
- * setup here. You are guaranteed that {@link #onCreateCandidatesView()}
- * will have been called some time before this function is called.
- *
- * <p>Note that this will <em>not</em> be called when the input method
- * is running in full editing mode, and thus receiving
- * {@link #onStartInputView} to initiate that operation. This is only
- * for the case when candidates are being shown while the input method
- * editor is hidden but wants to show its candidates UI as text is
- * entered through some other mechanism.
- *
- * @param info Description of the type of text being edited.
- * @param restarting Set to true if we are restarting input on the
- * same text field as before.
- */
- public void onStartCandidatesView(EditorInfo info, boolean restarting) {
- }
-
- /**
- * Called when the candidates view is being hidden from the user. This will
- * be called either prior to hiding the window, or prior to switching to
- * another target for editing.
- *
- * <p>The default
- * implementation uses the InputConnection to clear any active composing
- * text; you can override this (not calling the base class implementation)
- * to perform whatever behavior you would like.
- *
- * @boolean finishingInput If true, {@link #onFinishInput} will be
- * called immediately after.
- */
- public void onFinishCandidatesView(boolean finishingInput) {
- if (!finishingInput) {
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- ic.finishComposingText();
- }
- }
- }
-
- /**
- * The system has decided that it may be time to show your input method.
- * This is called due to a corresponding call to your
- * {@link InputMethod#showSoftInput(int) InputMethod.showSoftInput(int)}
- * method. The default implementation uses
- * {@link #onEvaluateInputViewShown()}, {@link #onEvaluateFullscreenMode()},
- * and the current configuration to decide whether the input view should
- * be shown at this point.
- *
- * @param flags Provides additional information about the show request,
- * as per {@link InputMethod#showSoftInput(int) InputMethod.showSoftInput(int)}.
- * @param configChange This is true if we are re-showing due to a
- * configuration change.
- * @return Returns true to indicate that the window should be shown.
- */
- public boolean onShowInputRequested(int flags, boolean configChange) {
- if (!onEvaluateInputViewShown()) {
- return false;
- }
- if ((flags&InputMethod.SHOW_EXPLICIT) == 0) {
- if (!configChange && onEvaluateFullscreenMode()) {
- // Don't show if this is not explicitly requested by the user and
- // the input method is fullscreen. That would be too disruptive.
- // However, we skip this change for a config change, since if
- // the IME is already shown we do want to go into fullscreen
- // mode at this point.
- return false;
- }
- Configuration config = getResources().getConfiguration();
- if (config.keyboard != Configuration.KEYBOARD_NOKEYS) {
- // And if the device has a hard keyboard, even if it is
- // currently hidden, don't show the input method implicitly.
- // These kinds of devices don't need it that much.
- return false;
- }
- }
- if ((flags&InputMethod.SHOW_FORCED) != 0) {
- mShowInputForced = true;
- }
- return true;
- }
-
- public void showWindow(boolean showInput) {
- if (DEBUG) Log.v(TAG, "Showing window: showInput=" + showInput
- + " mShowInputRequested=" + mShowInputRequested
- + " mWindowAdded=" + mWindowAdded
- + " mWindowCreated=" + mWindowCreated
- + " mWindowVisible=" + mWindowVisible
- + " mInputStarted=" + mInputStarted);
- boolean doShowInput = false;
- boolean wasVisible = mWindowVisible;
- mWindowVisible = true;
- if (!mShowInputRequested) {
- if (mInputStarted) {
- if (showInput) {
- doShowInput = true;
- mShowInputRequested = true;
- }
- }
- } else {
- showInput = true;
- }
-
- if (DEBUG) Log.v(TAG, "showWindow: updating UI");
- initialize();
- updateFullscreenMode();
- updateInputViewShown();
-
- if (!mWindowAdded || !mWindowCreated) {
- mWindowAdded = true;
- mWindowCreated = true;
- initialize();
- if (DEBUG) Log.v(TAG, "CALL: onCreateCandidatesView");
- View v = onCreateCandidatesView();
- if (DEBUG) Log.v(TAG, "showWindow: candidates=" + v);
- if (v != null) {
- setCandidatesView(v);
- }
- }
- if (mShowInputRequested) {
- if (!mInputViewStarted) {
- if (DEBUG) Log.v(TAG, "CALL: onStartInputView");
- mInputViewStarted = true;
- onStartInputView(mInputEditorInfo, false);
- }
- } else if (!mCandidatesViewStarted) {
- if (DEBUG) Log.v(TAG, "CALL: onStartCandidatesView");
- mCandidatesViewStarted = true;
- onStartCandidatesView(mInputEditorInfo, false);
- }
-
- if (doShowInput) {
- startExtractingText();
- }
-
- if (!wasVisible) {
- if (DEBUG) Log.v(TAG, "showWindow: showing!");
- onWindowShown();
- mWindow.show();
- }
- }
-
- public void hideWindow() {
- if (mInputViewStarted) {
- if (DEBUG) Log.v(TAG, "CALL: onFinishInputView");
- onFinishInputView(false);
- } else if (mCandidatesViewStarted) {
- if (DEBUG) Log.v(TAG, "CALL: onFinishCandidatesView");
- onFinishCandidatesView(false);
- }
- mInputViewStarted = false;
- mCandidatesViewStarted = false;
- if (mWindowVisible) {
- mWindow.hide();
- mWindowVisible = false;
- onWindowHidden();
- }
- }
-
- /**
- * Called when the input method window has been shown to the user, after
- * previously not being visible. This is done after all of the UI setup
- * for the window has occurred (creating its views etc).
- */
- public void onWindowShown() {
- }
-
- /**
- * Called when the input method window has been hidden from the user,
- * after previously being visible.
- */
- public void onWindowHidden() {
- }
-
- /**
- * Called when a new client has bound to the input method. This
- * may be followed by a series of {@link #onStartInput(EditorInfo, boolean)}
- * and {@link #onFinishInput()} calls as the user navigates through its
- * UI. Upon this call you know that {@link #getCurrentInputBinding}
- * and {@link #getCurrentInputConnection} return valid objects.
- */
- public void onBindInput() {
- }
-
- /**
- * Called when the previous bound client is no longer associated
- * with the input method. After returning {@link #getCurrentInputBinding}
- * and {@link #getCurrentInputConnection} will no longer return
- * valid objects.
- */
- public void onUnbindInput() {
- }
-
- /**
- * Called to inform the input method that text input has started in an
- * editor. You should use this callback to initialize the state of your
- * input to match the state of the editor given to it.
- *
- * @param attribute The attributes of the editor that input is starting
- * in.
- * @param restarting Set to true if input is restarting in the same
- * editor such as because the application has changed the text in
- * the editor. Otherwise will be false, indicating this is a new
- * session with the editor.
- */
- public void onStartInput(EditorInfo attribute, boolean restarting) {
- }
-
- void doFinishInput() {
- if (mInputViewStarted) {
- if (DEBUG) Log.v(TAG, "CALL: onFinishInputView");
- onFinishInputView(true);
- } else if (mCandidatesViewStarted) {
- if (DEBUG) Log.v(TAG, "CALL: onFinishCandidatesView");
- onFinishCandidatesView(true);
- }
- mInputViewStarted = false;
- mCandidatesViewStarted = false;
- if (mInputStarted) {
- if (DEBUG) Log.v(TAG, "CALL: onFinishInput");
- onFinishInput();
- }
- mInputStarted = false;
- mStartedInputConnection = null;
- mCurCompletions = null;
- }
-
- void doStartInput(InputConnection ic, EditorInfo attribute, boolean restarting) {
- if (!restarting) {
- doFinishInput();
- }
- mInputStarted = true;
- mStartedInputConnection = ic;
- mInputEditorInfo = attribute;
- initialize();
- if (DEBUG) Log.v(TAG, "CALL: onStartInput");
- onStartInput(attribute, restarting);
- if (mWindowVisible) {
- if (mShowInputRequested) {
- if (DEBUG) Log.v(TAG, "CALL: onStartInputView");
- mInputViewStarted = true;
- onStartInputView(mInputEditorInfo, restarting);
- startExtractingText();
- } else if (mCandidatesVisibility == View.VISIBLE) {
- if (DEBUG) Log.v(TAG, "CALL: onStartCandidatesView");
- mCandidatesViewStarted = true;
- onStartCandidatesView(mInputEditorInfo, restarting);
- }
- }
- }
-
- /**
- * Called to inform the input method that text input has finished in
- * the last editor. At this point there may be a call to
- * {@link #onStartInput(EditorInfo, boolean)} to perform input in a
- * new editor, or the input method may be left idle. This method is
- * <em>not</em> called when input restarts in the same editor.
- *
- * <p>The default
- * implementation uses the InputConnection to clear any active composing
- * text; you can override this (not calling the base class implementation)
- * to perform whatever behavior you would like.
- */
- public void onFinishInput() {
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- ic.finishComposingText();
- }
- }
-
- /**
- * Called when the application has reported auto-completion candidates that
- * it would like to have the input method displayed. Typically these are
- * only used when an input method is running in full-screen mode, since
- * otherwise the user can see and interact with the pop-up window of
- * completions shown by the application.
- *
- * <p>The default implementation here does nothing.
- */
- public void onDisplayCompletions(CompletionInfo[] completions) {
- }
-
- /**
- * Called when the application has reported new extracted text to be shown
- * due to changes in its current text state. The default implementation
- * here places the new text in the extract edit text, when the input
- * method is running in fullscreen mode.
- */
- public void onUpdateExtractedText(int token, ExtractedText text) {
- if (mExtractedToken != token) {
- return;
- }
- if (mExtractEditText != null && text != null) {
- mExtractedText = text;
- mExtractEditText.setExtractedText(text);
- }
- }
-
- /**
- * Called when the application has reported a new selection region of
- * the text. This is called whether or not the input method has requested
- * extracted text updates, although if so it will not receive this call
- * if the extracted text has changed as well.
- *
- * <p>The default implementation takes care of updating the cursor in
- * the extract text, if it is being shown.
- */
- public void onUpdateSelection(int oldSelStart, int oldSelEnd,
- int newSelStart, int newSelEnd,
- int candidatesStart, int candidatesEnd) {
- final ExtractEditText eet = mExtractEditText;
- if (eet != null && mExtractedText != null) {
- final int off = mExtractedText.startOffset;
- eet.startInternalChanges();
- eet.setSelection(newSelStart-off, newSelEnd-off);
- eet.finishInternalChanges();
- }
- }
-
- /**
- * Called when the application has reported a new location of its text
- * cursor. This is only called if explicitly requested by the input method.
- * The default implementation does nothing.
- */
- public void onUpdateCursor(Rect newCursor) {
- }
-
- /**
- * Close this input method's soft input area, removing it from the display.
- * The input method will continue running, but the user can no longer use
- * it to generate input by touching the screen.
- * @param flags Provides additional operating flags. Currently may be
- * 0 or have the {@link InputMethodManager#HIDE_IMPLICIT_ONLY
- * InputMethodManager.HIDE_IMPLICIT_ONLY} bit set.
- */
- public void dismissSoftInput(int flags) {
- mImm.hideSoftInputFromInputMethod(mToken, flags);
- }
-
- /**
- * Override this to intercept key down events before they are processed by the
- * application. If you return true, the application will not itself
- * process the event. If you return true, the normal application processing
- * will occur as if the IME had not seen the event at all.
- *
- * <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK
- * KeyEvent.KEYCODE_BACK} to hide the current IME UI if it is shown. In
- * additional, in fullscreen mode only, it will consume DPAD movement
- * events to move the cursor in the extracted text view, not allowing
- * them to perform navigation in the underlying application.
- */
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
- && event.getRepeatCount() == 0) {
- if (mShowInputRequested) {
- // If the soft input area is shown, back closes it and we
- // consume the back key.
- dismissSoftInput(0);
- return true;
- } else if (mWindowVisible) {
- if (mCandidatesVisibility == View.VISIBLE) {
- // If we are showing candidates even if no input area, then
- // hide them.
- setCandidatesViewShown(false);
- return true;
- } else {
- // If we have the window visible for some other reason --
- // most likely to show candidates -- then just get rid
- // of it. This really shouldn't happen, but just in case...
- hideWindow();
- return true;
- }
- }
- }
-
- return doMovementKey(keyCode, event, MOVEMENT_DOWN);
- }
-
- /**
- * Override this to intercept special key multiple events before they are
- * processed by the
- * application. If you return true, the application will not itself
- * process the event. If you return true, the normal application processing
- * will occur as if the IME had not seen the event at all.
- *
- * <p>The default implementation always returns false, except when
- * in fullscreen mode, where it will consume DPAD movement
- * events to move the cursor in the extracted text view, not allowing
- * them to perform navigation in the underlying application.
- */
- public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
- return doMovementKey(keyCode, event, count);
- }
-
- /**
- * Override this to intercept key up events before they are processed by the
- * application. If you return true, the application will not itself
- * process the event. If you return true, the normal application processing
- * will occur as if the IME had not seen the event at all.
- *
- * <p>The default implementation always returns false, except when
- * in fullscreen mode, where it will consume DPAD movement
- * events to move the cursor in the extracted text view, not allowing
- * them to perform navigation in the underlying application.
- */
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- return doMovementKey(keyCode, event, MOVEMENT_UP);
- }
-
- public boolean onTrackballEvent(MotionEvent event) {
- return false;
- }
-
- public void onAppPrivateCommand(String action, Bundle data) {
- }
-
- static final int MOVEMENT_DOWN = -1;
- static final int MOVEMENT_UP = -2;
-
- boolean doMovementKey(int keyCode, KeyEvent event, int count) {
- final ExtractEditText eet = mExtractEditText;
- if (isFullscreenMode() && isInputViewShown() && eet != null) {
- // If we are in fullscreen mode, the cursor will move around
- // the extract edit text, but should NOT cause focus to move
- // to other fields.
- MovementMethod movement = eet.getMovementMethod();
- Layout layout = eet.getLayout();
- if (movement != null && layout != null) {
- // We want our own movement method to handle the key, so the
- // cursor will properly move in our own word wrapping.
- if (count == MOVEMENT_DOWN) {
- if (movement.onKeyDown(eet,
- (Spannable)eet.getText(), keyCode, event)) {
- return true;
- }
- } else if (count == MOVEMENT_UP) {
- if (movement.onKeyUp(eet,
- (Spannable)eet.getText(), keyCode, event)) {
- return true;
- }
- } else {
- if (!movement.onKeyOther(eet, (Spannable)eet.getText(), event)) {
- KeyEvent down = new KeyEvent(event, KeyEvent.ACTION_DOWN);
- if (movement.onKeyDown(eet,
- (Spannable)eet.getText(), keyCode, down)) {
- KeyEvent up = new KeyEvent(event, KeyEvent.ACTION_UP);
- movement.onKeyUp(eet,
- (Spannable)eet.getText(), keyCode, up);
- while (--count > 0) {
- movement.onKeyDown(eet,
- (Spannable)eet.getText(), keyCode, down);
- movement.onKeyUp(eet,
- (Spannable)eet.getText(), keyCode, up);
- }
- }
- }
- }
- }
- // Regardless of whether the movement method handled the key,
- // we never allow DPAD navigation to the application.
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * This is called when the user has moved the cursor in the extracted
- * text view, when running in fullsreen mode. The default implementation
- * performs the corresponding selection change on the underlying text
- * editor.
- */
- public void onExtractedSelectionChanged(int start, int end) {
- InputConnection conn = getCurrentInputConnection();
- if (conn != null) {
- conn.setSelection(start, end);
- }
- }
-
- /**
- * This is called when the user has clicked on the extracted text view,
- * when running in fullscreen mode. The default implementation hides
- * the candidates view when this happens. Re-implement this to provide
- * whatever behavior you want.
- */
- public void onExtractedTextClicked() {
- setCandidatesViewShown(false);
- }
-
- /**
- * This is called when the user has selected a context menu item from the
- * extracted text view, when running in fullscreen mode. The default
- * implementation sends this action to the current InputConnection's
- * {@link InputConnection#performContextMenuAction(int)}, for it
- * to be processed in underlying "real" editor. Re-implement this to
- * provide whatever behavior you want.
- */
- public boolean onExtractTextContextMenuItem(int id) {
- InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- ic.performContextMenuAction(id);
- }
- return true;
- }
-
- void startExtractingText() {
- final ExtractEditText eet = mExtractEditText;
- if (eet != null && getCurrentInputStarted()
- && isFullscreenMode()) {
- mExtractedToken++;
- ExtractedTextRequest req = new ExtractedTextRequest();
- req.token = mExtractedToken;
- req.flags = InputConnection.GET_TEXT_WITH_STYLES;
- req.hintMaxLines = 10;
- req.hintMaxChars = 10000;
- mExtractedText = getCurrentInputConnection().getExtractedText(req,
- InputConnection.GET_EXTRACTED_TEXT_MONITOR);
- try {
- eet.startInternalChanges();
- int inputType = getCurrentInputEditorInfo().inputType;
- if ((inputType&EditorInfo.TYPE_MASK_CLASS)
- == EditorInfo.TYPE_CLASS_TEXT) {
- if ((inputType&EditorInfo.TYPE_TEXT_FLAG_IME_MULTI_LINE) != 0) {
- inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
- }
- }
- eet.setInputType(inputType);
- eet.setHint(mInputEditorInfo.hintText);
- if (mExtractedText != null) {
- eet.setEnabled(true);
- eet.setExtractedText(mExtractedText);
- } else {
- eet.setEnabled(false);
- eet.setText("");
- }
- } finally {
- eet.finishInternalChanges();
- }
- }
- }
-
- /**
- * Performs a dump of the InputMethodService's internal state. Override
- * to add your own information to the dump.
- */
- @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
- final Printer p = new PrintWriterPrinter(fout);
- p.println("Input method service state for " + this + ":");
- p.println(" mWindowCreated=" + mWindowCreated
- + " mWindowAdded=" + mWindowAdded
- + " mWindowVisible=" + mWindowVisible);
- p.println(" Configuration=" + getResources().getConfiguration());
- p.println(" mToken=" + mToken);
- p.println(" mInputBinding=" + mInputBinding);
- p.println(" mInputConnection=" + mInputConnection);
- p.println(" mStartedInputConnection=" + mStartedInputConnection);
- p.println(" mInputStarted=" + mInputStarted
- + " mInputViewStarted=" + mInputViewStarted
- + " mCandidatesViewStarted=" + mCandidatesViewStarted);
-
- if (mInputEditorInfo != null) {
- p.println(" mInputEditorInfo:");
- mInputEditorInfo.dump(p, " ");
- } else {
- p.println(" mInputEditorInfo: null");
- }
-
- p.println(" mShowInputRequested=" + mShowInputRequested
- + " mLastShowInputRequested=" + mLastShowInputRequested
- + " mShowInputForced=" + mShowInputForced
- + " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags));
- p.println(" mCandidatesVisibility=" + mCandidatesVisibility
- + " mFullscreenApplied=" + mFullscreenApplied
- + " mIsFullscreen=" + mIsFullscreen);
-
- if (mExtractedText != null) {
- p.println(" mExtractedText:");
- p.println(" text=" + mExtractedText.text.length() + " chars"
- + " startOffset=" + mExtractedText.startOffset);
- p.println(" selectionStart=" + mExtractedText.selectionStart
- + " selectionEnd=" + mExtractedText.selectionEnd
- + " flags=0x" + Integer.toHexString(mExtractedText.flags));
- } else {
- p.println(" mExtractedText: null");
- }
- p.println(" mExtractedToken=" + mExtractedToken);
- p.println(" mIsInputViewShown=" + mIsInputViewShown
- + " mStatusIcon=" + mStatusIcon);
- p.println("Last computed insets:");
- p.println(" contentTopInsets=" + mTmpInsets.contentTopInsets
- + " visibleTopInsets=" + mTmpInsets.visibleTopInsets
- + " touchableInsets=" + mTmpInsets.touchableInsets);
- }
-}
diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java
deleted file mode 100755
index 6a560ce..0000000
--- a/core/java/android/inputmethodservice/Keyboard.java
+++ /dev/null
@@ -1,815 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.inputmethodservice;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.TypedValue;
-import android.util.Xml;
-import android.view.Display;
-import android.view.WindowManager;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.StringTokenizer;
-
-
-/**
- * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard
- * consists of rows of keys.
- * <p>The layout file for a keyboard contains XML that looks like the following snippet:</p>
- * <pre>
- * &lt;Keyboard
- * android:keyWidth="%10p"
- * android:keyHeight="50px"
- * android:horizontalGap="2px"
- * android:verticalGap="2px" &gt;
- * &lt;Row android:keyWidth="32px" &gt;
- * &lt;Key android:keyLabel="A" /&gt;
- * ...
- * &lt;/Row&gt;
- * ...
- * &lt;/Keyboard&gt;
- * </pre>
- * @attr ref android.R.styleable#Keyboard_keyWidth
- * @attr ref android.R.styleable#Keyboard_keyHeight
- * @attr ref android.R.styleable#Keyboard_horizontalGap
- * @attr ref android.R.styleable#Keyboard_verticalGap
- */
-public class Keyboard {
-
- static final String TAG = "Keyboard";
-
- // Keyboard XML Tags
- private static final String TAG_KEYBOARD = "Keyboard";
- private static final String TAG_ROW = "Row";
- private static final String TAG_KEY = "Key";
-
- public static final int EDGE_LEFT = 0x01;
- public static final int EDGE_RIGHT = 0x02;
- public static final int EDGE_TOP = 0x04;
- public static final int EDGE_BOTTOM = 0x08;
-
- public static final int KEYCODE_SHIFT = -1;
- public static final int KEYCODE_MODE_CHANGE = -2;
- public static final int KEYCODE_CANCEL = -3;
- public static final int KEYCODE_DONE = -4;
- public static final int KEYCODE_DELETE = -5;
- public static final int KEYCODE_ALT = -6;
-
- /** Keyboard label **/
- private CharSequence mLabel;
-
- /** Horizontal gap default for all rows */
- private int mDefaultHorizontalGap;
-
- /** Default key width */
- private int mDefaultWidth;
-
- /** Default key height */
- private int mDefaultHeight;
-
- /** Default gap between rows */
- private int mDefaultVerticalGap;
-
- /** Is the keyboard in the shifted state */
- private boolean mShifted;
-
- /** Key instance for the shift key, if present */
- private Key mShiftKey;
-
- /** Key index for the shift key, if present */
- private int mShiftKeyIndex = -1;
-
- /** Current key width, while loading the keyboard */
- private int mKeyWidth;
-
- /** Current key height, while loading the keyboard */
- private int mKeyHeight;
-
- /** Total height of the keyboard, including the padding and keys */
- private int mTotalHeight;
-
- /**
- * Total width of the keyboard, including left side gaps and keys, but not any gaps on the
- * right side.
- */
- private int mTotalWidth;
-
- /** List of keys in this keyboard */
- private List<Key> mKeys;
-
- /** List of modifier keys such as Shift & Alt, if any */
- private List<Key> mModifierKeys;
-
- /** Width of the screen available to fit the keyboard */
- private int mDisplayWidth;
-
- /** Height of the screen */
- private int mDisplayHeight;
-
- /** Keyboard mode, or zero, if none. */
- private int mKeyboardMode;
-
- // Variables for pre-computing nearest keys.
-
- private static final int GRID_WIDTH = 10;
- private static final int GRID_HEIGHT = 5;
- private static final int GRID_SIZE = GRID_WIDTH * GRID_HEIGHT;
- private int mCellWidth;
- private int mCellHeight;
- private int[][] mGridNeighbors;
- private int mProximityThreshold;
- /** Number of key widths from current touch point to search for nearest keys. */
- private static float SEARCH_DISTANCE = 1.4f;
-
- /**
- * Container for keys in the keyboard. All keys in a row are at the same Y-coordinate.
- * Some of the key size defaults can be overridden per row from what the {@link Keyboard}
- * defines.
- * @attr ref android.R.styleable#Keyboard_keyWidth
- * @attr ref android.R.styleable#Keyboard_keyHeight
- * @attr ref android.R.styleable#Keyboard_horizontalGap
- * @attr ref android.R.styleable#Keyboard_verticalGap
- * @attr ref android.R.styleable#Keyboard_Row_rowEdgeFlags
- * @attr ref android.R.styleable#Keyboard_Row_keyboardMode
- */
- public static class Row {
- /** Default width of a key in this row. */
- public int defaultWidth;
- /** Default height of a key in this row. */
- public int defaultHeight;
- /** Default horizontal gap between keys in this row. */
- public int defaultHorizontalGap;
- /** Vertical gap following this row. */
- public int verticalGap;
- /**
- * Edge flags for this row of keys. Possible values that can be assigned are
- * {@link Keyboard#EDGE_TOP EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM EDGE_BOTTOM}
- */
- public int rowEdgeFlags;
-
- /** The keyboard mode for this row */
- public int mode;
-
- private Keyboard parent;
-
- public Row(Keyboard parent) {
- this.parent = parent;
- }
-
- public Row(Resources res, Keyboard parent, XmlResourceParser parser) {
- this.parent = parent;
- TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
- com.android.internal.R.styleable.Keyboard);
- defaultWidth = getDimensionOrFraction(a,
- com.android.internal.R.styleable.Keyboard_keyWidth,
- parent.mDisplayWidth, parent.mDefaultWidth);
- defaultHeight = getDimensionOrFraction(a,
- com.android.internal.R.styleable.Keyboard_keyHeight,
- parent.mDisplayHeight, parent.mDefaultHeight);
- defaultHorizontalGap = getDimensionOrFraction(a,
- com.android.internal.R.styleable.Keyboard_horizontalGap,
- parent.mDisplayWidth, parent.mDefaultHorizontalGap);
- verticalGap = getDimensionOrFraction(a,
- com.android.internal.R.styleable.Keyboard_verticalGap,
- parent.mDisplayHeight, parent.mDefaultVerticalGap);
- a.recycle();
- a = res.obtainAttributes(Xml.asAttributeSet(parser),
- com.android.internal.R.styleable.Keyboard_Row);
- rowEdgeFlags = a.getInt(com.android.internal.R.styleable.Keyboard_Row_rowEdgeFlags, 0);
- mode = a.getResourceId(com.android.internal.R.styleable.Keyboard_Row_keyboardMode,
- 0);
- }
- }
-
- /**
- * Class for describing the position and characteristics of a single key in the keyboard.
- *
- * @attr ref android.R.styleable#Keyboard_keyWidth
- * @attr ref android.R.styleable#Keyboard_keyHeight
- * @attr ref android.R.styleable#Keyboard_horizontalGap
- * @attr ref android.R.styleable#Keyboard_Key_codes
- * @attr ref android.R.styleable#Keyboard_Key_keyIcon
- * @attr ref android.R.styleable#Keyboard_Key_keyLabel
- * @attr ref android.R.styleable#Keyboard_Key_iconPreview
- * @attr ref android.R.styleable#Keyboard_Key_isSticky
- * @attr ref android.R.styleable#Keyboard_Key_isRepeatable
- * @attr ref android.R.styleable#Keyboard_Key_isModifier
- * @attr ref android.R.styleable#Keyboard_Key_popupKeyboard
- * @attr ref android.R.styleable#Keyboard_Key_popupCharacters
- * @attr ref android.R.styleable#Keyboard_Key_keyOutputText
- * @attr ref android.R.styleable#Keyboard_Key_keyEdgeFlags
- */
- public static class Key {
- /**
- * All the key codes (unicode or custom code) that this key could generate, zero'th
- * being the most important.
- */
- public int[] codes;
-
- /** Label to display */
- public CharSequence label;
-
- /** Icon to display instead of a label. Icon takes precedence over a label */
- public Drawable icon;
- /** Preview version of the icon, for the preview popup */
- public Drawable iconPreview;
- /** Width of the key, not including the gap */
- public int width;
- /** Height of the key, not including the gap */
- public int height;
- /** The horizontal gap before this key */
- public int gap;
- /** Whether this key is sticky, i.e., a toggle key */
- public boolean sticky;
- /** X coordinate of the key in the keyboard layout */
- public int x;
- /** Y coordinate of the key in the keyboard layout */
- public int y;
- /** The current pressed state of this key */
- public boolean pressed;
- /** If this is a sticky key, is it on? */
- public boolean on;
- /** Text to output when pressed. This can be multiple characters, like ".com" */
- public CharSequence text;
- /** Popup characters */
- public CharSequence popupCharacters;
-
- /**
- * Flags that specify the anchoring to edges of the keyboard for detecting touch events
- * that are just out of the boundary of the key. This is a bit mask of
- * {@link Keyboard#EDGE_LEFT}, {@link Keyboard#EDGE_RIGHT}, {@link Keyboard#EDGE_TOP} and
- * {@link Keyboard#EDGE_BOTTOM}.
- */
- public int edgeFlags;
- /** Whether this is a modifier key, such as Shift or Alt */
- public boolean modifier;
- /** The keyboard that this key belongs to */
- private Keyboard keyboard;
- /**
- * If this key pops up a mini keyboard, this is the resource id for the XML layout for that
- * keyboard.
- */
- public int popupResId;
- /** Whether this key repeats itself when held down */
- public boolean repeatable;
-
-
- private final static int[] KEY_STATE_NORMAL_ON = {
- android.R.attr.state_checkable,
- android.R.attr.state_checked
- };
-
- private final static int[] KEY_STATE_PRESSED_ON = {
- android.R.attr.state_pressed,
- android.R.attr.state_checkable,
- android.R.attr.state_checked
- };
-
- private final static int[] KEY_STATE_NORMAL_OFF = {
- android.R.attr.state_checkable
- };
-
- private final static int[] KEY_STATE_PRESSED_OFF = {
- android.R.attr.state_pressed,
- android.R.attr.state_checkable
- };
-
- private final static int[] KEY_STATE_NORMAL = {
- };
-
- private final static int[] KEY_STATE_PRESSED = {
- android.R.attr.state_pressed
- };
-
- /** Create an empty key with no attributes. */
- public Key(Row parent) {
- keyboard = parent.parent;
- }
-
- /** Create a key with the given top-left coordinate and extract its attributes from
- * the XML parser.
- * @param res resources associated with the caller's context
- * @param parent the row that this key belongs to. The row must already be attached to
- * a {@link Keyboard}.
- * @param x the x coordinate of the top-left
- * @param y the y coordinate of the top-left
- * @param parser the XML parser containing the attributes for this key
- */
- public Key(Resources res, Row parent, int x, int y, XmlResourceParser parser) {
- this(parent);
-
- this.x = x;
- this.y = y;
-
- TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
- com.android.internal.R.styleable.Keyboard);
-
- width = getDimensionOrFraction(a,
- com.android.internal.R.styleable.Keyboard_keyWidth,
- keyboard.mDisplayWidth, parent.defaultWidth);
- height = getDimensionOrFraction(a,
- com.android.internal.R.styleable.Keyboard_keyHeight,
- keyboard.mDisplayHeight, parent.defaultHeight);
- gap = getDimensionOrFraction(a,
- com.android.internal.R.styleable.Keyboard_horizontalGap,
- keyboard.mDisplayWidth, parent.defaultHorizontalGap);
- a.recycle();
- a = res.obtainAttributes(Xml.asAttributeSet(parser),
- com.android.internal.R.styleable.Keyboard_Key);
- this.x += gap;
- TypedValue codesValue = new TypedValue();
- a.getValue(com.android.internal.R.styleable.Keyboard_Key_codes,
- codesValue);
- if (codesValue.type == TypedValue.TYPE_INT_DEC
- || codesValue.type == TypedValue.TYPE_INT_HEX) {
- codes = new int[] { codesValue.data };
- } else if (codesValue.type == TypedValue.TYPE_STRING) {
- codes = parseCSV(codesValue.string.toString());
- }
-
- iconPreview = a.getDrawable(com.android.internal.R.styleable.Keyboard_Key_iconPreview);
- if (iconPreview != null) {
- iconPreview.setBounds(0, 0, iconPreview.getIntrinsicWidth(),
- iconPreview.getIntrinsicHeight());
- }
- popupCharacters = a.getText(
- com.android.internal.R.styleable.Keyboard_Key_popupCharacters);
- popupResId = a.getResourceId(
- com.android.internal.R.styleable.Keyboard_Key_popupKeyboard, 0);
- repeatable = a.getBoolean(
- com.android.internal.R.styleable.Keyboard_Key_isRepeatable, false);
- modifier = a.getBoolean(
- com.android.internal.R.styleable.Keyboard_Key_isModifier, false);
- sticky = a.getBoolean(
- com.android.internal.R.styleable.Keyboard_Key_isSticky, false);
- edgeFlags = a.getInt(com.android.internal.R.styleable.Keyboard_Key_keyEdgeFlags, 0);
- edgeFlags |= parent.rowEdgeFlags;
-
- icon = a.getDrawable(
- com.android.internal.R.styleable.Keyboard_Key_keyIcon);
- if (icon != null) {
- icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
- }
- label = a.getText(com.android.internal.R.styleable.Keyboard_Key_keyLabel);
- text = a.getText(com.android.internal.R.styleable.Keyboard_Key_keyOutputText);
-
- if (codes == null && !TextUtils.isEmpty(label)) {
- codes = new int[] { label.charAt(0) };
- }
- a.recycle();
- }
-
- /**
- * Informs the key that it has been pressed, in case it needs to change its appearance or
- * state.
- * @see #onReleased(boolean)
- */
- public void onPressed() {
- pressed = !pressed;
- }
-
- /**
- * Changes the pressed state of the key. If it is a sticky key, it will also change the
- * toggled state of the key if the finger was release inside.
- * @param inside whether the finger was released inside the key
- * @see #onPressed()
- */
- public void onReleased(boolean inside) {
- pressed = !pressed;
- if (sticky) {
- on = !on;
- }
- }
-
- int[] parseCSV(String value) {
- int count = 0;
- int lastIndex = 0;
- if (value.length() > 0) {
- count++;
- while ((lastIndex = value.indexOf(",", lastIndex + 1)) > 0) {
- count++;
- }
- }
- int[] values = new int[count];
- count = 0;
- StringTokenizer st = new StringTokenizer(value, ",");
- while (st.hasMoreTokens()) {
- try {
- values[count++] = Integer.parseInt(st.nextToken());
- } catch (NumberFormatException nfe) {
- Log.e(TAG, "Error parsing keycodes " + value);
- }
- }
- return values;
- }
-
- /**
- * Detects if a point falls inside this key.
- * @param x the x-coordinate of the point
- * @param y the y-coordinate of the point
- * @return whether or not the point falls inside the key. If the key is attached to an edge,
- * it will assume that all points between the key and the edge are considered to be inside
- * the key.
- */
- public boolean isInside(int x, int y) {
- boolean leftEdge = (edgeFlags & EDGE_LEFT) > 0;
- boolean rightEdge = (edgeFlags & EDGE_RIGHT) > 0;
- boolean topEdge = (edgeFlags & EDGE_TOP) > 0;
- boolean bottomEdge = (edgeFlags & EDGE_BOTTOM) > 0;
- if ((x >= this.x || (leftEdge && x <= this.x + this.width))
- && (x < this.x + this.width || (rightEdge && x >= this.x))
- && (y >= this.y || (topEdge && y <= this.y + this.height))
- && (y < this.y + this.height || (bottomEdge && y >= this.y))) {
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Returns the square of the distance between the center of the key and the given point.
- * @param x the x-coordinate of the point
- * @param y the y-coordinate of the point
- * @return the square of the distance of the point from the center of the key
- */
- public int squaredDistanceFrom(int x, int y) {
- int xDist = this.x + width / 2 - x;
- int yDist = this.y + height / 2 - y;
- return xDist * xDist + yDist * yDist;
- }
-
- /**
- * Returns the drawable state for the key, based on the current state and type of the key.
- * @return the drawable state of the key.
- * @see android.graphics.drawable.StateListDrawable#setState(int[])
- */
- public int[] getCurrentDrawableState() {
- int[] states = KEY_STATE_NORMAL;
-
- if (on) {
- if (pressed) {
- states = KEY_STATE_PRESSED_ON;
- } else {
- states = KEY_STATE_NORMAL_ON;
- }
- } else {
- if (sticky) {
- if (pressed) {
- states = KEY_STATE_PRESSED_OFF;
- } else {
- states = KEY_STATE_NORMAL_OFF;
- }
- } else {
- if (pressed) {
- states = KEY_STATE_PRESSED;
- }
- }
- }
- return states;
- }
- }
-
- /**
- * Creates a keyboard from the given xml key layout file.
- * @param context the application or service context
- * @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
- */
- public Keyboard(Context context, int xmlLayoutResId) {
- this(context, xmlLayoutResId, 0);
- }
-
- /**
- * Creates a keyboard from the given xml key layout file. Weeds out rows
- * that have a keyboard mode defined but don't match the specified mode.
- * @param context the application or service context
- * @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
- * @param modeId keyboard mode identifier
- */
- public Keyboard(Context context, int xmlLayoutResId, int modeId) {
- WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- final Display display = wm.getDefaultDisplay();
- mDisplayWidth = display.getWidth();
- mDisplayHeight = display.getHeight();
- mDefaultHorizontalGap = 0;
- mDefaultWidth = mDisplayWidth / 10;
- mDefaultVerticalGap = 0;
- mDefaultHeight = mDefaultWidth;
- mKeys = new ArrayList<Key>();
- mModifierKeys = new ArrayList<Key>();
- mKeyboardMode = modeId;
- loadKeyboard(context, context.getResources().getXml(xmlLayoutResId));
- }
-
- /**
- * <p>Creates a blank keyboard from the given resource file and populates it with the specified
- * characters in left-to-right, top-to-bottom fashion, using the specified number of columns.
- * </p>
- * <p>If the specified number of columns is -1, then the keyboard will fit as many keys as
- * possible in each row.</p>
- * @param context the application or service context
- * @param layoutTemplateResId the layout template file, containing no keys.
- * @param characters the list of characters to display on the keyboard. One key will be created
- * for each character.
- * @param columns the number of columns of keys to display. If this number is greater than the
- * number of keys that can fit in a row, it will be ignored. If this number is -1, the
- * keyboard will fit as many keys as possible in each row.
- */
- public Keyboard(Context context, int layoutTemplateResId,
- CharSequence characters, int columns, int horizontalPadding) {
- this(context, layoutTemplateResId);
- int x = 0;
- int y = 0;
- int column = 0;
- mTotalWidth = 0;
-
- Row row = new Row(this);
- row.defaultHeight = mDefaultHeight;
- row.defaultWidth = mDefaultWidth;
- row.defaultHorizontalGap = mDefaultHorizontalGap;
- row.verticalGap = mDefaultVerticalGap;
- row.rowEdgeFlags = EDGE_TOP | EDGE_BOTTOM;
- final int maxColumns = columns == -1 ? Integer.MAX_VALUE : columns;
- for (int i = 0; i < characters.length(); i++) {
- char c = characters.charAt(i);
- if (column >= maxColumns
- || x + mDefaultWidth + horizontalPadding > mDisplayWidth) {
- x = 0;
- y += mDefaultVerticalGap + mDefaultHeight;
- column = 0;
- }
- final Key key = new Key(row);
- key.x = x;
- key.y = y;
- key.width = mDefaultWidth;
- key.height = mDefaultHeight;
- key.gap = mDefaultHorizontalGap;
- key.label = String.valueOf(c);
- key.codes = new int[] { c };
- column++;
- x += key.width + key.gap;
- mKeys.add(key);
- if (x > mTotalWidth) {
- mTotalWidth = x;
- }
- }
- mTotalHeight = y + mDefaultHeight;
- }
-
- public List<Key> getKeys() {
- return mKeys;
- }
-
- public List<Key> getModifierKeys() {
- return mModifierKeys;
- }
-
- protected int getHorizontalGap() {
- return mDefaultHorizontalGap;
- }
-
- protected void setHorizontalGap(int gap) {
- mDefaultHorizontalGap = gap;
- }
-
- protected int getVerticalGap() {
- return mDefaultVerticalGap;
- }
-
- protected void setVerticalGap(int gap) {
- mDefaultVerticalGap = gap;
- }
-
- protected int getKeyHeight() {
- return mDefaultHeight;
- }
-
- protected void setKeyHeight(int height) {
- mDefaultHeight = height;
- }
-
- protected int getKeyWidth() {
- return mDefaultWidth;
- }
-
- protected void setKeyWidth(int width) {
- mDefaultWidth = width;
- }
-
- /**
- * Returns the total height of the keyboard
- * @return the total height of the keyboard
- */
- public int getHeight() {
- return mTotalHeight;
- }
-
- public int getMinWidth() {
- return mTotalWidth;
- }
-
- public boolean setShifted(boolean shiftState) {
- if (mShiftKey != null) {
- mShiftKey.on = shiftState;
- }
- if (mShifted != shiftState) {
- mShifted = shiftState;
- return true;
- }
- return false;
- }
-
- public boolean isShifted() {
- return mShifted;
- }
-
- public int getShiftKeyIndex() {
- return mShiftKeyIndex;
- }
-
- private void computeNearestNeighbors() {
- // Round-up so we don't have any pixels outside the grid
- mCellWidth = (getMinWidth() + GRID_WIDTH - 1) / GRID_WIDTH;
- mCellHeight = (getHeight() + GRID_HEIGHT - 1) / GRID_HEIGHT;
- mGridNeighbors = new int[GRID_SIZE][];
- int[] indices = new int[mKeys.size()];
- final int gridWidth = GRID_WIDTH * mCellWidth;
- final int gridHeight = GRID_HEIGHT * mCellHeight;
- for (int x = 0; x < gridWidth; x += mCellWidth) {
- for (int y = 0; y < gridHeight; y += mCellHeight) {
- int count = 0;
- for (int i = 0; i < mKeys.size(); i++) {
- final Key key = mKeys.get(i);
- if (key.squaredDistanceFrom(x, y) < mProximityThreshold ||
- key.squaredDistanceFrom(x + mCellWidth - 1, y) < mProximityThreshold ||
- key.squaredDistanceFrom(x + mCellWidth - 1, y + mCellHeight - 1)
- < mProximityThreshold ||
- key.squaredDistanceFrom(x, y + mCellHeight - 1) < mProximityThreshold) {
- indices[count++] = i;
- }
- }
- int [] cell = new int[count];
- System.arraycopy(indices, 0, cell, 0, count);
- mGridNeighbors[(y / mCellHeight) * GRID_WIDTH + (x / mCellWidth)] = cell;
- }
- }
- }
-
- /**
- * Returns the indices of the keys that are closest to the given point.
- * @param x the x-coordinate of the point
- * @param y the y-coordinate of the point
- * @return the array of integer indices for the nearest keys to the given point. If the given
- * point is out of range, then an array of size zero is returned.
- */
- public int[] getNearestKeys(int x, int y) {
- if (mGridNeighbors == null) computeNearestNeighbors();
- if (x >= 0 && x < getMinWidth() && y >= 0 && y < getHeight()) {
- int index = (y / mCellHeight) * GRID_WIDTH + (x / mCellWidth);
- if (index < GRID_SIZE) {
- return mGridNeighbors[index];
- }
- }
- return new int[0];
- }
-
- protected Row createRowFromXml(Resources res, XmlResourceParser parser) {
- return new Row(res, this, parser);
- }
-
- protected Key createKeyFromXml(Resources res, Row parent, int x, int y,
- XmlResourceParser parser) {
- return new Key(res, parent, x, y, parser);
- }
-
- private void loadKeyboard(Context context, XmlResourceParser parser) {
- boolean inKey = false;
- boolean inRow = false;
- boolean leftMostKey = false;
- int row = 0;
- int x = 0;
- int y = 0;
- Key key = null;
- Row currentRow = null;
- Resources res = context.getResources();
- boolean skipRow = false;
-
- try {
- int event;
- while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
- if (event == XmlResourceParser.START_TAG) {
- String tag = parser.getName();
- if (TAG_ROW.equals(tag)) {
- inRow = true;
- x = 0;
- currentRow = createRowFromXml(res, parser);
- skipRow = currentRow.mode != 0 && currentRow.mode != mKeyboardMode;
- if (skipRow) {
- skipToEndOfRow(parser);
- inRow = false;
- }
- } else if (TAG_KEY.equals(tag)) {
- inKey = true;
- key = createKeyFromXml(res, currentRow, x, y, parser);
- mKeys.add(key);
- if (key.codes[0] == KEYCODE_SHIFT) {
- mShiftKey = key;
- mShiftKeyIndex = mKeys.size()-1;
- mModifierKeys.add(key);
- } else if (key.codes[0] == KEYCODE_ALT) {
- mModifierKeys.add(key);
- }
- } else if (TAG_KEYBOARD.equals(tag)) {
- parseKeyboardAttributes(res, parser);
- }
- } else if (event == XmlResourceParser.END_TAG) {
- if (inKey) {
- inKey = false;
- x += key.gap + key.width;
- if (x > mTotalWidth) {
- mTotalWidth = x;
- }
- } else if (inRow) {
- inRow = false;
- y += currentRow.verticalGap;
- y += currentRow.defaultHeight;
- row++;
- } else {
- // TODO: error or extend?
- }
- }
- }
- } catch (Exception e) {
- Log.e(TAG, "Parse error:" + e);
- e.printStackTrace();
- }
- mTotalHeight = y - mDefaultVerticalGap;
- }
-
- private void skipToEndOfRow(XmlResourceParser parser)
- throws XmlPullParserException, IOException {
- int event;
- while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
- if (event == XmlResourceParser.END_TAG
- && parser.getName().equals(TAG_ROW)) {
- break;
- }
- }
- }
-
- private void parseKeyboardAttributes(Resources res, XmlResourceParser parser) {
- TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
- com.android.internal.R.styleable.Keyboard);
-
- mDefaultWidth = getDimensionOrFraction(a,
- com.android.internal.R.styleable.Keyboard_keyWidth,
- mDisplayWidth, mDisplayWidth / 10);
- mDefaultHeight = getDimensionOrFraction(a,
- com.android.internal.R.styleable.Keyboard_keyHeight,
- mDisplayHeight, 50);
- mDefaultHorizontalGap = getDimensionOrFraction(a,
- com.android.internal.R.styleable.Keyboard_horizontalGap,
- mDisplayWidth, 0);
- mDefaultVerticalGap = getDimensionOrFraction(a,
- com.android.internal.R.styleable.Keyboard_verticalGap,
- mDisplayHeight, 0);
- mProximityThreshold = (int) (mDefaultWidth * SEARCH_DISTANCE);
- mProximityThreshold = mProximityThreshold * mProximityThreshold; // Square it for comparison
- a.recycle();
- }
-
- static int getDimensionOrFraction(TypedArray a, int index, int base, int defValue) {
- TypedValue value = a.peekValue(index);
- if (value == null) return defValue;
- if (value.type == TypedValue.TYPE_DIMENSION) {
- return a.getDimensionPixelOffset(index, defValue);
- } else if (value.type == TypedValue.TYPE_FRACTION) {
- // Round it to avoid values like 47.9999 from getting truncated
- return Math.round(a.getFraction(index, base, base, defValue));
- }
- return defValue;
- }
-}
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
deleted file mode 100755
index 886e688..0000000
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ /dev/null
@@ -1,1154 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.inputmethodservice;
-
-import com.android.internal.R;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Typeface;
-import android.graphics.Paint.Align;
-import android.graphics.drawable.Drawable;
-import android.inputmethodservice.Keyboard.Key;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Vibrator;
-import android.preference.PreferenceManager;
-import android.util.AttributeSet;
-import android.view.GestureDetector;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.Button;
-import android.widget.PopupWindow;
-import android.widget.TextView;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A view that renders a virtual {@link Keyboard}. It handles rendering of keys and
- * detecting key presses and touch movements.
- *
- * @attr ref android.R.styleable#KeyboardView_keyBackground
- * @attr ref android.R.styleable#KeyboardView_keyPreviewLayout
- * @attr ref android.R.styleable#KeyboardView_keyPreviewOffset
- * @attr ref android.R.styleable#KeyboardView_labelTextSize
- * @attr ref android.R.styleable#KeyboardView_keyTextSize
- * @attr ref android.R.styleable#KeyboardView_keyTextColor
- * @attr ref android.R.styleable#KeyboardView_verticalCorrection
- * @attr ref android.R.styleable#KeyboardView_popupLayout
- */
-public class KeyboardView extends View implements View.OnClickListener {
-
- /**
- * Listener for virtual keyboard events.
- */
- public interface OnKeyboardActionListener {
-
- /**
- * Called when the user presses a key. This is sent before the {@link #onKey} is called.
- * For keys that repeat, this is only called once.
- * @param primaryCode the unicode of the key being pressed. If the touch is not on a valid
- * key, the value will be zero.
- * @hide Pending API Council approval
- */
- void onPress(int primaryCode);
-
- /**
- * Called when the user releases a key. This is sent after the {@link #onKey} is called.
- * For keys that repeat, this is only called once.
- * @param primaryCode the code of the key that was released
- * @hide Pending API Council approval
- */
- void onRelease(int primaryCode);
-
- /**
- * Send a key press to the listener.
- * @param primaryCode this is the key that was pressed
- * @param keyCodes the codes for all the possible alternative keys
- * with the primary code being the first. If the primary key code is
- * a single character such as an alphabet or number or symbol, the alternatives
- * will include other characters that may be on the same key or adjacent keys.
- * These codes are useful to correct for accidental presses of a key adjacent to
- * the intended key.
- */
- void onKey(int primaryCode, int[] keyCodes);
-
- /**
- * Called when the user quickly moves the finger from right to left.
- */
- void swipeLeft();
-
- /**
- * Called when the user quickly moves the finger from left to right.
- */
- void swipeRight();
-
- /**
- * Called when the user quickly moves the finger from up to down.
- */
- void swipeDown();
-
- /**
- * Called when the user quickly moves the finger from down to up.
- */
- void swipeUp();
- }
-
- private static final boolean DEBUG = false;
- private static final int NOT_A_KEY = -1;
- private static final int[] KEY_DELETE = { Keyboard.KEYCODE_DELETE };
- private static final int[] LONG_PRESSABLE_STATE_SET = { R.attr.state_long_pressable };
-
- private Keyboard mKeyboard;
- private int mCurrentKeyIndex = NOT_A_KEY;
- private int mLabelTextSize;
- private int mKeyTextSize;
- private int mKeyTextColor;
- private float mShadowRadius;
- private int mShadowColor;
- private float mBackgroundDimAmount;
-
- private TextView mPreviewText;
- private PopupWindow mPreviewPopup;
- private int mPreviewTextSizeLarge;
- private int mPreviewOffset;
- private int mPreviewHeight;
- private int[] mOffsetInWindow;
-
- private PopupWindow mPopupKeyboard;
- private View mMiniKeyboardContainer;
- private KeyboardView mMiniKeyboard;
- private boolean mMiniKeyboardOnScreen;
- private View mPopupParent;
- private int mMiniKeyboardOffsetX;
- private int mMiniKeyboardOffsetY;
- private Map<Key,View> mMiniKeyboardCache;
- private int[] mWindowOffset;
- private Key[] mKeys;
-
- /** Listener for {@link OnKeyboardActionListener}. */
- private OnKeyboardActionListener mKeyboardActionListener;
-
- private static final int MSG_SHOW_PREVIEW = 1;
- private static final int MSG_REMOVE_PREVIEW = 2;
- private static final int MSG_REPEAT = 3;
- private static final int MSG_LONGPRESS = 4;
-
- private static final int DELAY_BEFORE_PREVIEW = 70;
- private static final int DELAY_AFTER_PREVIEW = 60;
-
- private int mVerticalCorrection;
- private int mProximityThreshold;
-
- private boolean mPreviewCentered = false;
- private boolean mShowPreview = true;
- private boolean mShowTouchPoints = true;
- private int mPopupPreviewX;
- private int mPopupPreviewY;
-
- private int mLastX;
- private int mLastY;
- private int mStartX;
- private int mStartY;
-
- private boolean mProximityCorrectOn;
-
- private Paint mPaint;
- private Rect mPadding;
-
- private long mDownTime;
- private long mLastMoveTime;
- private int mLastKey;
- private int mLastCodeX;
- private int mLastCodeY;
- private int mCurrentKey = NOT_A_KEY;
- private long mLastKeyTime;
- private long mCurrentKeyTime;
- private int[] mKeyIndices = new int[12];
- private GestureDetector mGestureDetector;
- private int mPopupX;
- private int mPopupY;
- private int mRepeatKeyIndex = NOT_A_KEY;
- private int mPopupLayout;
- private boolean mAbortKey;
- private Key mInvalidatedKey;
- private Rect mClipRegion = new Rect(0, 0, 0, 0);
-
- private Drawable mKeyBackground;
-
- private static final int REPEAT_INTERVAL = 50; // ~20 keys per second
- private static final int REPEAT_START_DELAY = 400;
- private static final int LONGPRESS_TIMEOUT = 800;
- // Deemed to be too short : ViewConfiguration.getLongPressTimeout();
-
- private static int MAX_NEARBY_KEYS = 12;
- private int[] mDistances = new int[MAX_NEARBY_KEYS];
-
- // For multi-tap
- private int mLastSentIndex;
- private int mTapCount;
- private long mLastTapTime;
- private boolean mInMultiTap;
- private static final int MULTITAP_INTERVAL = 800; // milliseconds
- private StringBuilder mPreviewLabel = new StringBuilder(1);
-
- Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_SHOW_PREVIEW:
- showKey(msg.arg1);
- break;
- case MSG_REMOVE_PREVIEW:
- mPreviewText.setVisibility(INVISIBLE);
- break;
- case MSG_REPEAT:
- if (repeatKey()) {
- Message repeat = Message.obtain(this, MSG_REPEAT);
- sendMessageDelayed(repeat, REPEAT_INTERVAL);
- }
- break;
- case MSG_LONGPRESS:
- openPopupIfRequired((MotionEvent) msg.obj);
- break;
- }
- }
- };
-
- public KeyboardView(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.keyboardViewStyle);
- }
-
- public KeyboardView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a =
- context.obtainStyledAttributes(
- attrs, android.R.styleable.KeyboardView, defStyle, 0);
-
- LayoutInflater inflate =
- (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- int previewLayout = 0;
- int keyTextSize = 0;
-
- int n = a.getIndexCount();
-
- for (int i = 0; i < n; i++) {
- int attr = a.getIndex(i);
-
- switch (attr) {
- case com.android.internal.R.styleable.KeyboardView_keyBackground:
- mKeyBackground = a.getDrawable(attr);
- break;
- case com.android.internal.R.styleable.KeyboardView_verticalCorrection:
- mVerticalCorrection = a.getDimensionPixelOffset(attr, 0);
- break;
- case com.android.internal.R.styleable.KeyboardView_keyPreviewLayout:
- previewLayout = a.getResourceId(attr, 0);
- break;
- case com.android.internal.R.styleable.KeyboardView_keyPreviewOffset:
- mPreviewOffset = a.getDimensionPixelOffset(attr, 0);
- break;
- case com.android.internal.R.styleable.KeyboardView_keyPreviewHeight:
- mPreviewHeight = a.getDimensionPixelSize(attr, 80);
- break;
- case com.android.internal.R.styleable.KeyboardView_keyTextSize:
- mKeyTextSize = a.getDimensionPixelSize(attr, 18);
- break;
- case com.android.internal.R.styleable.KeyboardView_keyTextColor:
- mKeyTextColor = a.getColor(attr, 0xFF000000);
- break;
- case com.android.internal.R.styleable.KeyboardView_labelTextSize:
- mLabelTextSize = a.getDimensionPixelSize(attr, 14);
- break;
- case com.android.internal.R.styleable.KeyboardView_popupLayout:
- mPopupLayout = a.getResourceId(attr, 0);
- break;
- case com.android.internal.R.styleable.KeyboardView_shadowColor:
- mShadowColor = a.getColor(attr, 0);
- break;
- case com.android.internal.R.styleable.KeyboardView_shadowRadius:
- mShadowRadius = a.getFloat(attr, 0f);
- break;
- }
- }
-
- a = mContext.obtainStyledAttributes(
- com.android.internal.R.styleable.Theme);
- mBackgroundDimAmount = a.getFloat(android.R.styleable.Theme_backgroundDimAmount, 0.5f);
-
- mPreviewPopup = new PopupWindow(context);
- if (previewLayout != 0) {
- mPreviewText = (TextView) inflate.inflate(previewLayout, null);
- mPreviewTextSizeLarge = (int) mPreviewText.getTextSize();
- mPreviewPopup.setContentView(mPreviewText);
- mPreviewPopup.setBackgroundDrawable(null);
- } else {
- mShowPreview = false;
- }
-
- mPreviewPopup.setTouchable(false);
-
- mPopupKeyboard = new PopupWindow(context);
- mPopupKeyboard.setBackgroundDrawable(null);
- //mPopupKeyboard.setClippingEnabled(false);
-
- mPopupParent = this;
- //mPredicting = true;
-
- mPaint = new Paint();
- mPaint.setAntiAlias(true);
- mPaint.setTextSize(keyTextSize);
- mPaint.setTextAlign(Align.CENTER);
-
- mPadding = new Rect(0, 0, 0, 0);
- mMiniKeyboardCache = new HashMap<Key,View>();
- mKeyBackground.getPadding(mPadding);
-
- resetMultiTap();
- initGestureDetector();
- }
-
- private void initGestureDetector() {
- mGestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
- @Override
- public boolean onFling(MotionEvent me1, MotionEvent me2,
- float velocityX, float velocityY) {
- final float absX = Math.abs(velocityX);
- final float absY = Math.abs(velocityY);
- if (velocityX > 500 && absY < absX) {
- swipeRight();
- return true;
- } else if (velocityX < -500 && absY < absX) {
- swipeLeft();
- return true;
- } else if (velocityY < -500 && absX < absY) {
- swipeUp();
- return true;
- } else if (velocityY > 500 && absX < 200) {
- swipeDown();
- return true;
- } else if (absX > 800 || absY > 800) {
- return true;
- }
- return false;
- }
- });
-
- mGestureDetector.setIsLongpressEnabled(false);
- }
-
- public void setOnKeyboardActionListener(OnKeyboardActionListener listener) {
- mKeyboardActionListener = listener;
- }
-
- /**
- * Returns the {@link OnKeyboardActionListener} object.
- * @return the listener attached to this keyboard
- */
- protected OnKeyboardActionListener getOnKeyboardActionListener() {
- return mKeyboardActionListener;
- }
-
- /**
- * Attaches a keyboard to this view. The keyboard can be switched at any time and the
- * view will re-layout itself to accommodate the keyboard.
- * @see Keyboard
- * @see #getKeyboard()
- * @param keyboard the keyboard to display in this view
- */
- public void setKeyboard(Keyboard keyboard) {
- if (mKeyboard != null) {
- showPreview(NOT_A_KEY);
- }
- mKeyboard = keyboard;
- List<Key> keys = mKeyboard.getKeys();
- mKeys = keys.toArray(new Key[keys.size()]);
- requestLayout();
- invalidate();
- computeProximityThreshold(keyboard);
- }
-
- /**
- * Returns the current keyboard being displayed by this view.
- * @return the currently attached keyboard
- * @see #setKeyboard(Keyboard)
- */
- public Keyboard getKeyboard() {
- return mKeyboard;
- }
-
- /**
- * Sets the state of the shift key of the keyboard, if any.
- * @param shifted whether or not to enable the state of the shift key
- * @return true if the shift key state changed, false if there was no change
- * @see KeyboardView#isShifted()
- */
- public boolean setShifted(boolean shifted) {
- if (mKeyboard != null) {
- if (mKeyboard.setShifted(shifted)) {
- // The whole keyboard probably needs to be redrawn
- invalidate();
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns the state of the shift key of the keyboard, if any.
- * @return true if the shift is in a pressed state, false otherwise. If there is
- * no shift key on the keyboard or there is no keyboard attached, it returns false.
- * @see KeyboardView#setShifted(boolean)
- */
- public boolean isShifted() {
- if (mKeyboard != null) {
- return mKeyboard.isShifted();
- }
- return false;
- }
-
- /**
- * Enables or disables the key feedback popup. This is a popup that shows a magnified
- * version of the depressed key. By default the preview is enabled.
- * @param previewEnabled whether or not to enable the key feedback popup
- * @see #isPreviewEnabled()
- */
- public void setPreviewEnabled(boolean previewEnabled) {
- mShowPreview = previewEnabled;
- }
-
- /**
- * Returns the enabled state of the key feedback popup.
- * @return whether or not the key feedback popup is enabled
- * @see #setPreviewEnabled(boolean)
- */
- public boolean isPreviewEnabled() {
- return mShowPreview;
- }
-
- public void setVerticalCorrection(int verticalOffset) {
-
- }
- public void setPopupParent(View v) {
- mPopupParent = v;
- }
-
- public void setPopupOffset(int x, int y) {
- mMiniKeyboardOffsetX = x;
- mMiniKeyboardOffsetY = y;
- if (mPreviewPopup.isShowing()) {
- mPreviewPopup.dismiss();
- }
- }
-
- /**
- * Enables or disables proximity correction. When enabled, {@link OnKeyboardActionListener#onKey}
- * gets called with key codes for adjacent keys. Otherwise only the primary code is returned.
- * @param enabled whether or not the proximity correction is enabled
- * @hide Pending API Council approval
- */
- public void setProximityCorrectionEnabled(boolean enabled) {
- mProximityCorrectOn = enabled;
- }
-
- /**
- * Returns the enabled state of the proximity correction.
- * @return true if proximity correction is enabled, false otherwise
- * @hide Pending API Council approval
- */
- public boolean isProximityCorrectionEnabled() {
- return mProximityCorrectOn;
- }
-
- /**
- * Popup keyboard close button clicked.
- * @hide
- */
- public void onClick(View v) {
- dismissPopupKeyboard();
- }
-
- private CharSequence adjustCase(CharSequence label) {
- if (mKeyboard.isShifted() && label != null && label.length() == 1
- && Character.isLowerCase(label.charAt(0))) {
- label = label.toString().toUpperCase();
- }
- return label;
- }
-
- @Override
- public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // Round up a little
- if (mKeyboard == null) {
- setMeasuredDimension(mPaddingLeft + mPaddingRight, mPaddingTop + mPaddingBottom);
- } else {
- int width = mKeyboard.getMinWidth() + mPaddingLeft + mPaddingRight;
- if (MeasureSpec.getSize(widthMeasureSpec) < width + 10) {
- width = MeasureSpec.getSize(widthMeasureSpec);
- }
- setMeasuredDimension(width, mKeyboard.getHeight() + mPaddingTop + mPaddingBottom);
- }
- }
-
- /**
- * Compute the average distance between adjacent keys (horizontally and vertically)
- * and square it to get the proximity threshold. We use a square here and in computing
- * the touch distance from a key's center to avoid taking a square root.
- * @param keyboard
- */
- private void computeProximityThreshold(Keyboard keyboard) {
- if (keyboard == null) return;
- final Key[] keys = mKeys;
- if (keys == null) return;
- int length = keys.length;
- int dimensionSum = 0;
- for (int i = 0; i < length; i++) {
- Key key = keys[i];
- dimensionSum += Math.min(key.width, key.height) + key.gap;
- }
- if (dimensionSum < 0 || length == 0) return;
- mProximityThreshold = (int) (dimensionSum * 1.4f / length);
- mProximityThreshold *= mProximityThreshold; // Square it
- }
-
- @Override
- public void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (mKeyboard == null) return;
-
- final Paint paint = mPaint;
- final Drawable keyBackground = mKeyBackground;
- final Rect clipRegion = mClipRegion;
- final Rect padding = mPadding;
- final int kbdPaddingLeft = mPaddingLeft;
- final int kbdPaddingTop = mPaddingTop;
- final Key[] keys = mKeys;
- final Key invalidKey = mInvalidatedKey;
- //canvas.translate(0, mKeyboardPaddingTop);
- paint.setAlpha(255);
- paint.setColor(mKeyTextColor);
- boolean drawSingleKey = false;
- if (invalidKey != null && canvas.getClipBounds(clipRegion)) {
-// System.out.println("Key bounds = " + (invalidKey.x + mPaddingLeft) + ","
-// + (invalidKey.y + mPaddingTop) + ","
-// + (invalidKey.x + invalidKey.width + mPaddingLeft) + ","
-// + (invalidKey.y + invalidKey.height + mPaddingTop));
-// System.out.println("Clip bounds =" + clipRegion.toShortString());
- // Is clipRegion completely contained within the invalidated key?
- if (invalidKey.x + kbdPaddingLeft - 1 <= clipRegion.left &&
- invalidKey.y + kbdPaddingTop - 1 <= clipRegion.top &&
- invalidKey.x + invalidKey.width + kbdPaddingLeft + 1 >= clipRegion.right &&
- invalidKey.y + invalidKey.height + kbdPaddingTop + 1 >= clipRegion.bottom) {
- drawSingleKey = true;
- }
- }
- final int keyCount = keys.length;
- for (int i = 0; i < keyCount; i++) {
- final Key key = keys[i];
- if (drawSingleKey && invalidKey != key) {
- continue;
- }
- int[] drawableState = key.getCurrentDrawableState();
- keyBackground.setState(drawableState);
-
- // Switch the character to uppercase if shift is pressed
- String label = key.label == null? null : adjustCase(key.label).toString();
-
- final Rect bounds = keyBackground.getBounds();
- if (key.width != bounds.right ||
- key.height != bounds.bottom) {
- keyBackground.setBounds(0, 0, key.width, key.height);
- }
- canvas.translate(key.x + kbdPaddingLeft, key.y + kbdPaddingTop);
- keyBackground.draw(canvas);
-
- if (label != null) {
- // For characters, use large font. For labels like "Done", use small font.
- if (label.length() > 1 && key.codes.length < 2) {
- paint.setTextSize(mLabelTextSize);
- paint.setTypeface(Typeface.DEFAULT_BOLD);
- } else {
- paint.setTextSize(mKeyTextSize);
- paint.setTypeface(Typeface.DEFAULT);
- }
- // Draw a drop shadow for the text
- paint.setShadowLayer(mShadowRadius, 0, 0, mShadowColor);
- // Draw the text
- canvas.drawText(label,
- (key.width - padding.left - padding.right) / 2
- + padding.left,
- (key.height - padding.top - padding.bottom) / 2
- + (paint.getTextSize() - paint.descent()) / 2 + padding.top,
- paint);
- // Turn off drop shadow
- paint.setShadowLayer(0, 0, 0, 0);
- } else if (key.icon != null) {
- final int drawableX = (key.width - padding.left - padding.right
- - key.icon.getIntrinsicWidth()) / 2 + padding.left;
- final int drawableY = (key.height - padding.top - padding.bottom
- - key.icon.getIntrinsicHeight()) / 2 + padding.top;
- canvas.translate(drawableX, drawableY);
- key.icon.setBounds(0, 0,
- key.icon.getIntrinsicWidth(), key.icon.getIntrinsicHeight());
- key.icon.draw(canvas);
- canvas.translate(-drawableX, -drawableY);
- }
- canvas.translate(-key.x - kbdPaddingLeft, -key.y - kbdPaddingTop);
- }
- mInvalidatedKey = null;
- // Overlay a dark rectangle to dim the keyboard
- if (mMiniKeyboardOnScreen) {
- paint.setColor((int) (mBackgroundDimAmount * 0xFF) << 24);
- canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
- }
-
- if (DEBUG && mShowTouchPoints) {
- paint.setAlpha(128);
- paint.setColor(0xFFFF0000);
- canvas.drawCircle(mStartX, mStartY, 3, paint);
- canvas.drawLine(mStartX, mStartY, mLastX, mLastY, paint);
- paint.setColor(0xFF0000FF);
- canvas.drawCircle(mLastX, mLastY, 3, paint);
- paint.setColor(0xFF00FF00);
- canvas.drawCircle((mStartX + mLastX) / 2, (mStartY + mLastY) / 2, 2, paint);
- }
- }
-
- private int getKeyIndices(int x, int y, int[] allKeys) {
- final Key[] keys = mKeys;
- final boolean shifted = mKeyboard.isShifted();
- int primaryIndex = NOT_A_KEY;
- int closestKey = NOT_A_KEY;
- int closestKeyDist = mProximityThreshold + 1;
- java.util.Arrays.fill(mDistances, Integer.MAX_VALUE);
- int [] nearestKeyIndices = mKeyboard.getNearestKeys(x, y);
- final int keyCount = nearestKeyIndices.length;
- for (int i = 0; i < keyCount; i++) {
- final Key key = keys[nearestKeyIndices[i]];
- int dist = 0;
- boolean isInside = key.isInside(x,y);
- if (((mProximityCorrectOn
- && (dist = key.squaredDistanceFrom(x, y)) < mProximityThreshold)
- || isInside)
- && key.codes[0] > 32) {
- // Find insertion point
- final int nCodes = key.codes.length;
- if (dist < closestKeyDist) {
- closestKeyDist = dist;
- closestKey = nearestKeyIndices[i];
- }
-
- if (allKeys == null) continue;
-
- for (int j = 0; j < mDistances.length; j++) {
- if (mDistances[j] > dist) {
- // Make space for nCodes codes
- System.arraycopy(mDistances, j, mDistances, j + nCodes,
- mDistances.length - j - nCodes);
- System.arraycopy(allKeys, j, allKeys, j + nCodes,
- allKeys.length - j - nCodes);
- for (int c = 0; c < nCodes; c++) {
- allKeys[j + c] = key.codes[c];
- mDistances[j + c] = dist;
- }
- break;
- }
- }
- }
-
- if (isInside) {
- primaryIndex = nearestKeyIndices[i];
- }
- }
- if (primaryIndex == NOT_A_KEY) {
- primaryIndex = closestKey;
- }
- return primaryIndex;
- }
-
- private void detectAndSendKey(int x, int y, long eventTime) {
- int index = mCurrentKey;
- if (index != NOT_A_KEY && index < mKeys.length) {
- final Key key = mKeys[index];
- if (key.text != null) {
- for (int i = 0; i < key.text.length(); i++) {
- mKeyboardActionListener.onKey(key.text.charAt(i), key.codes);
- }
- mKeyboardActionListener.onRelease(NOT_A_KEY);
- } else {
- int code = key.codes[0];
- //TextEntryState.keyPressedAt(key, x, y);
- int[] codes = new int[MAX_NEARBY_KEYS];
- Arrays.fill(codes, NOT_A_KEY);
- getKeyIndices(x, y, codes);
- // Multi-tap
- if (mInMultiTap) {
- if (mTapCount != -1) {
- mKeyboardActionListener.onKey(Keyboard.KEYCODE_DELETE, KEY_DELETE);
- } else {
- mTapCount = 0;
- }
- code = key.codes[mTapCount];
- }
- mKeyboardActionListener.onKey(code, codes);
- mKeyboardActionListener.onRelease(code);
- }
- mLastSentIndex = index;
- mLastTapTime = eventTime;
- }
- }
-
- /**
- * Handle multi-tap keys by producing the key label for the current multi-tap state.
- */
- private CharSequence getPreviewText(Key key) {
- if (mInMultiTap) {
- // Multi-tap
- mPreviewLabel.setLength(0);
- mPreviewLabel.append((char) key.codes[mTapCount < 0 ? 0 : mTapCount]);
- return adjustCase(mPreviewLabel);
- } else {
- return adjustCase(key.label);
- }
- }
-
- private void showPreview(int keyIndex) {
- int oldKeyIndex = mCurrentKeyIndex;
- final PopupWindow previewPopup = mPreviewPopup;
-
- mCurrentKeyIndex = keyIndex;
- // Release the old key and press the new key
- final Key[] keys = mKeys;
- if (oldKeyIndex != mCurrentKeyIndex) {
- if (oldKeyIndex != NOT_A_KEY && keys.length > oldKeyIndex) {
- keys[oldKeyIndex].onReleased(mCurrentKeyIndex == NOT_A_KEY);
- invalidateKey(oldKeyIndex);
- }
- if (mCurrentKeyIndex != NOT_A_KEY && keys.length > mCurrentKeyIndex) {
- keys[mCurrentKeyIndex].onPressed();
- invalidateKey(mCurrentKeyIndex);
- }
- }
- // If key changed and preview is on ...
- if (oldKeyIndex != mCurrentKeyIndex && mShowPreview) {
- mHandler.removeMessages(MSG_SHOW_PREVIEW);
- if (previewPopup.isShowing()) {
- if (keyIndex == NOT_A_KEY) {
- mHandler.sendMessageDelayed(mHandler
- .obtainMessage(MSG_REMOVE_PREVIEW),
- DELAY_AFTER_PREVIEW);
- }
- }
- if (keyIndex != NOT_A_KEY) {
- if (previewPopup.isShowing() && mPreviewText.getVisibility() == VISIBLE) {
- // Show right away, if it's already visible and finger is moving around
- showKey(keyIndex);
- } else {
- mHandler.sendMessageDelayed(
- mHandler.obtainMessage(MSG_SHOW_PREVIEW, keyIndex, 0),
- DELAY_BEFORE_PREVIEW);
- }
- }
- }
- }
-
- private void showKey(final int keyIndex) {
- final PopupWindow previewPopup = mPreviewPopup;
- final Key[] keys = mKeys;
- Key key = keys[keyIndex];
- if (key.icon != null) {
- mPreviewText.setCompoundDrawables(null, null, null,
- key.iconPreview != null ? key.iconPreview : key.icon);
- mPreviewText.setText(null);
- } else {
- mPreviewText.setCompoundDrawables(null, null, null, null);
- mPreviewText.setText(getPreviewText(key));
- if (key.label.length() > 1 && key.codes.length < 2) {
- mPreviewText.setTextSize(mLabelTextSize);
- mPreviewText.setTypeface(Typeface.DEFAULT_BOLD);
- } else {
- mPreviewText.setTextSize(mPreviewTextSizeLarge);
- mPreviewText.setTypeface(Typeface.DEFAULT);
- }
- }
- mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- int popupWidth = Math.max(mPreviewText.getMeasuredWidth(), key.width
- + mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight());
- final int popupHeight = mPreviewHeight;
- LayoutParams lp = mPreviewText.getLayoutParams();
- if (lp != null) {
- lp.width = popupWidth;
- lp.height = popupHeight;
- }
- if (!mPreviewCentered) {
- mPopupPreviewX = key.x - mPreviewText.getPaddingLeft() + mPaddingLeft;
- mPopupPreviewY = key.y - popupHeight + mPreviewOffset;
- } else {
- // TODO: Fix this if centering is brought back
- mPopupPreviewX = 160 - mPreviewText.getMeasuredWidth() / 2;
- mPopupPreviewY = - mPreviewText.getMeasuredHeight();
- }
- mHandler.removeMessages(MSG_REMOVE_PREVIEW);
- if (mOffsetInWindow == null) {
- mOffsetInWindow = new int[2];
- getLocationInWindow(mOffsetInWindow);
- mOffsetInWindow[0] += mMiniKeyboardOffsetX; // Offset may be zero
- mOffsetInWindow[1] += mMiniKeyboardOffsetY; // Offset may be zero
- }
- // Set the preview background state
- mPreviewText.getBackground().setState(
- key.popupResId != 0 ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET);
- if (previewPopup.isShowing()) {
- previewPopup.update(mPopupPreviewX + mOffsetInWindow[0],
- mPopupPreviewY + mOffsetInWindow[1],
- popupWidth, popupHeight);
- } else {
- previewPopup.setWidth(popupWidth);
- previewPopup.setHeight(popupHeight);
- previewPopup.showAtLocation(mPopupParent, Gravity.NO_GRAVITY,
- mPopupPreviewX + mOffsetInWindow[0],
- mPopupPreviewY + mOffsetInWindow[1]);
- }
- mPreviewText.setVisibility(VISIBLE);
- }
-
- private void invalidateKey(int keyIndex) {
- if (keyIndex < 0 || keyIndex >= mKeys.length) {
- return;
- }
- final Key key = mKeys[keyIndex];
- mInvalidatedKey = key;
- invalidate(key.x + mPaddingLeft, key.y + mPaddingTop,
- key.x + key.width + mPaddingLeft, key.y + key.height + mPaddingTop);
- }
-
- private boolean openPopupIfRequired(MotionEvent me) {
- // Check if we have a popup layout specified first.
- if (mPopupLayout == 0) {
- return false;
- }
- if (mCurrentKey < 0 || mCurrentKey >= mKeys.length) {
- return false;
- }
-
- Key popupKey = mKeys[mCurrentKey];
- boolean result = onLongPress(popupKey);
- if (result) {
- mAbortKey = true;
- showPreview(NOT_A_KEY);
- }
- return result;
- }
-
- /**
- * Called when a key is long pressed. By default this will open any popup keyboard associated
- * with this key through the attributes popupLayout and popupCharacters.
- * @param popupKey the key that was long pressed
- * @return true if the long press is handled, false otherwise. Subclasses should call the
- * method on the base class if the subclass doesn't wish to handle the call.
- */
- protected boolean onLongPress(Key popupKey) {
- int popupKeyboardId = popupKey.popupResId;
-
- if (popupKeyboardId != 0) {
- mMiniKeyboardContainer = mMiniKeyboardCache.get(popupKey);
- if (mMiniKeyboardContainer == null) {
- LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- mMiniKeyboardContainer = inflater.inflate(mPopupLayout, null);
- mMiniKeyboard = (KeyboardView) mMiniKeyboardContainer.findViewById(
- com.android.internal.R.id.keyboardView);
- View closeButton = mMiniKeyboardContainer.findViewById(
- com.android.internal.R.id.button_close);
- if (closeButton != null) closeButton.setOnClickListener(this);
- mMiniKeyboard.setOnKeyboardActionListener(new OnKeyboardActionListener() {
- public void onKey(int primaryCode, int[] keyCodes) {
- mKeyboardActionListener.onKey(primaryCode, keyCodes);
- dismissPopupKeyboard();
- }
-
- public void swipeLeft() { }
- public void swipeRight() { }
- public void swipeUp() { }
- public void swipeDown() { }
- public void onPress(int primaryCode) {
- mKeyboardActionListener.onPress(primaryCode);
- }
- public void onRelease(int primaryCode) {
- mKeyboardActionListener.onRelease(primaryCode);
- }
- });
- //mInputView.setSuggest(mSuggest);
- Keyboard keyboard;
- if (popupKey.popupCharacters != null) {
- keyboard = new Keyboard(getContext(), popupKeyboardId,
- popupKey.popupCharacters, -1, getPaddingLeft() + getPaddingRight());
- } else {
- keyboard = new Keyboard(getContext(), popupKeyboardId);
- }
- mMiniKeyboard.setKeyboard(keyboard);
- mMiniKeyboard.setPopupParent(this);
- mMiniKeyboardContainer.measure(
- MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),
- MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));
-
- mMiniKeyboardCache.put(popupKey, mMiniKeyboardContainer);
- } else {
- mMiniKeyboard = (KeyboardView) mMiniKeyboardContainer.findViewById(
- com.android.internal.R.id.keyboardView);
- }
- if (mWindowOffset == null) {
- mWindowOffset = new int[2];
- getLocationInWindow(mWindowOffset);
- }
- mPopupX = popupKey.x + mPaddingLeft;
- mPopupY = popupKey.y + mPaddingTop;
- mPopupX = mPopupX + popupKey.width - mMiniKeyboardContainer.getMeasuredWidth();
- mPopupY = mPopupY - mMiniKeyboardContainer.getMeasuredHeight();
- final int x = mPopupX + mMiniKeyboardContainer.getPaddingRight() + mWindowOffset[0];
- final int y = mPopupY + mMiniKeyboardContainer.getPaddingBottom() + mWindowOffset[1];
- mMiniKeyboard.setPopupOffset(x < 0 ? 0 : x, y);
- mMiniKeyboard.setShifted(isShifted());
- mPopupKeyboard.setContentView(mMiniKeyboardContainer);
- mPopupKeyboard.setWidth(mMiniKeyboardContainer.getMeasuredWidth());
- mPopupKeyboard.setHeight(mMiniKeyboardContainer.getMeasuredHeight());
- mPopupKeyboard.showAtLocation(this, Gravity.NO_GRAVITY, x, y);
- mMiniKeyboardOnScreen = true;
- //mMiniKeyboard.onTouchEvent(getTranslatedEvent(me));
- invalidate();
- return true;
- }
- return false;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent me) {
- int touchX = (int) me.getX() - mPaddingLeft;
- int touchY = (int) me.getY() + mVerticalCorrection - mPaddingTop;
- int action = me.getAction();
- long eventTime = me.getEventTime();
- int keyIndex = getKeyIndices(touchX, touchY, null);
-
- if (mGestureDetector.onTouchEvent(me)) {
- showPreview(NOT_A_KEY);
- mHandler.removeMessages(MSG_REPEAT);
- mHandler.removeMessages(MSG_LONGPRESS);
- return true;
- }
-
- // Needs to be called after the gesture detector gets a turn, as it may have
- // displayed the mini keyboard
- if (mMiniKeyboardOnScreen) {
- return true;
- }
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- mAbortKey = false;
- mStartX = touchX;
- mStartY = touchY;
- mLastCodeX = touchX;
- mLastCodeY = touchY;
- mLastKeyTime = 0;
- mCurrentKeyTime = 0;
- mLastKey = NOT_A_KEY;
- mCurrentKey = keyIndex;
- mDownTime = me.getEventTime();
- mLastMoveTime = mDownTime;
- checkMultiTap(eventTime, keyIndex);
- mKeyboardActionListener.onPress(keyIndex != NOT_A_KEY ?
- mKeys[keyIndex].codes[0] : 0);
- if (mCurrentKey >= 0 && mKeys[mCurrentKey].repeatable) {
- mRepeatKeyIndex = mCurrentKey;
- repeatKey();
- Message msg = mHandler.obtainMessage(MSG_REPEAT);
- mHandler.sendMessageDelayed(msg, REPEAT_START_DELAY);
- }
- if (mCurrentKey != NOT_A_KEY) {
- Message msg = mHandler.obtainMessage(MSG_LONGPRESS, me);
- mHandler.sendMessageDelayed(msg, LONGPRESS_TIMEOUT);
- }
- showPreview(keyIndex);
- break;
-
- case MotionEvent.ACTION_MOVE:
- boolean continueLongPress = false;
- if (keyIndex != NOT_A_KEY) {
- if (mCurrentKey == NOT_A_KEY) {
- mCurrentKey = keyIndex;
- mCurrentKeyTime = eventTime - mDownTime;
- } else {
- if (keyIndex == mCurrentKey) {
- mCurrentKeyTime += eventTime - mLastMoveTime;
- continueLongPress = true;
- } else {
- resetMultiTap();
- mLastKey = mCurrentKey;
- mLastCodeX = mLastX;
- mLastCodeY = mLastY;
- mLastKeyTime =
- mCurrentKeyTime + eventTime - mLastMoveTime;
- mCurrentKey = keyIndex;
- mCurrentKeyTime = 0;
- }
- }
- if (keyIndex != mRepeatKeyIndex) {
- mHandler.removeMessages(MSG_REPEAT);
- mRepeatKeyIndex = NOT_A_KEY;
- }
- }
- if (!continueLongPress) {
- // Cancel old longpress
- mHandler.removeMessages(MSG_LONGPRESS);
- // Start new longpress if key has changed
- if (keyIndex != NOT_A_KEY) {
- Message msg = mHandler.obtainMessage(MSG_LONGPRESS, me);
- mHandler.sendMessageDelayed(msg, LONGPRESS_TIMEOUT);
- }
- }
- showPreview(keyIndex);
- break;
-
- case MotionEvent.ACTION_UP:
- mHandler.removeMessages(MSG_SHOW_PREVIEW);
- mHandler.removeMessages(MSG_REPEAT);
- mHandler.removeMessages(MSG_LONGPRESS);
- if (keyIndex == mCurrentKey) {
- mCurrentKeyTime += eventTime - mLastMoveTime;
- } else {
- resetMultiTap();
- mLastKey = mCurrentKey;
- mLastKeyTime = mCurrentKeyTime + eventTime - mLastMoveTime;
- mCurrentKey = keyIndex;
- mCurrentKeyTime = 0;
- }
- if (mCurrentKeyTime < mLastKeyTime && mLastKey != NOT_A_KEY) {
- mCurrentKey = mLastKey;
- touchX = mLastCodeX;
- touchY = mLastCodeY;
- }
- showPreview(NOT_A_KEY);
- Arrays.fill(mKeyIndices, NOT_A_KEY);
- invalidateKey(keyIndex);
- // If we're not on a repeating key (which sends on a DOWN event)
- if (mRepeatKeyIndex == NOT_A_KEY && !mMiniKeyboardOnScreen && !mAbortKey) {
- detectAndSendKey(touchX, touchY, eventTime);
- }
- mRepeatKeyIndex = NOT_A_KEY;
- break;
- }
- mLastX = touchX;
- mLastY = touchY;
- return true;
- }
-
- private boolean repeatKey() {
- Key key = mKeys[mRepeatKeyIndex];
- detectAndSendKey(key.x, key.y, mLastTapTime);
- return true;
- }
-
- protected void swipeRight() {
- mKeyboardActionListener.swipeRight();
- }
-
- protected void swipeLeft() {
- mKeyboardActionListener.swipeLeft();
- }
-
- protected void swipeUp() {
- mKeyboardActionListener.swipeUp();
- }
-
- protected void swipeDown() {
- mKeyboardActionListener.swipeDown();
- }
-
- public void closing() {
- if (mPreviewPopup.isShowing()) {
- mPreviewPopup.dismiss();
- }
- mHandler.removeMessages(MSG_REPEAT);
- mHandler.removeMessages(MSG_LONGPRESS);
- mHandler.removeMessages(MSG_SHOW_PREVIEW);
-
- dismissPopupKeyboard();
- }
-
- @Override
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- closing();
- }
-
- private void dismissPopupKeyboard() {
- if (mPopupKeyboard.isShowing()) {
- mPopupKeyboard.dismiss();
- mMiniKeyboardOnScreen = false;
- invalidate();
- }
- }
-
- public boolean handleBack() {
- if (mPopupKeyboard.isShowing()) {
- dismissPopupKeyboard();
- return true;
- }
- return false;
- }
-
- private void resetMultiTap() {
- mLastSentIndex = NOT_A_KEY;
- mTapCount = 0;
- mLastTapTime = -1;
- mInMultiTap = false;
- }
-
- private void checkMultiTap(long eventTime, int keyIndex) {
- if (keyIndex == NOT_A_KEY) return;
- Key key = mKeys[keyIndex];
- if (key.codes.length > 1) {
- mInMultiTap = true;
- if (eventTime < mLastTapTime + MULTITAP_INTERVAL
- && keyIndex == mLastSentIndex) {
- mTapCount = (mTapCount + 1) % key.codes.length;
- return;
- } else {
- mTapCount = -1;
- return;
- }
- }
- if (eventTime > mLastTapTime + MULTITAP_INTERVAL || keyIndex != mLastSentIndex) {
- resetMultiTap();
- }
- }
-}
diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java
deleted file mode 100644
index c37845f..0000000
--- a/core/java/android/inputmethodservice/SoftInputWindow.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.inputmethodservice;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.os.IBinder;
-import android.view.Gravity;
-import android.view.WindowManager;
-
-/**
- * A SoftInputWindow is a Dialog that is intended to be used for a top-level input
- * method window. It will be displayed along the edge of the screen, moving
- * the application user interface away from it so that the focused item is
- * always visible.
- */
-class SoftInputWindow extends Dialog {
-
- /**
- * Create a DockWindow that uses the default style.
- *
- * @param context The Context the DockWindow is to run it. In particular, it
- * uses the window manager and theme in this context to present its
- * UI.
- */
- public SoftInputWindow(Context context) {
- super(context, com.android.internal.R.style.Theme_InputMethod);
- initDockWindow();
- }
-
- public void setToken(IBinder token) {
- WindowManager.LayoutParams lp = getWindow().getAttributes();
- lp.token = token;
- getWindow().setAttributes(lp);
- }
-
- /**
- * Create a DockWindow that uses a custom style.
- *
- * @param context The Context in which the DockWindow should run. In
- * particular, it uses the window manager and theme from this context
- * to present its UI.
- * @param theme A style resource describing the theme to use for the window.
- * See <a href="{@docRoot}reference/available-resources.html#stylesandthemes">Style
- * and Theme Resources</a> for more information about defining and
- * using styles. This theme is applied on top of the current theme in
- * <var>context</var>. If 0, the default dialog theme will be used.
- */
- public SoftInputWindow(Context context, int theme) {
- super(context, theme);
- initDockWindow();
- }
-
- /**
- * Get the size of the DockWindow.
- *
- * @return If the DockWindow sticks to the top or bottom of the screen, the
- * return value is the height of the DockWindow, and its width is
- * equal to the width of the screen; If the DockWindow sticks to the
- * left or right of the screen, the return value is the width of the
- * DockWindow, and its height is equal to the height of the screen.
- */
- public int getSize() {
- WindowManager.LayoutParams lp = getWindow().getAttributes();
-
- if (lp.gravity == Gravity.TOP || lp.gravity == Gravity.BOTTOM) {
- return lp.height;
- } else {
- return lp.width;
- }
- }
-
- /**
- * Set the size of the DockWindow.
- *
- * @param size If the DockWindow sticks to the top or bottom of the screen,
- * <var>size</var> is the height of the DockWindow, and its width is
- * equal to the width of the screen; If the DockWindow sticks to the
- * left or right of the screen, <var>size</var> is the width of the
- * DockWindow, and its height is equal to the height of the screen.
- */
- public void setSize(int size) {
- WindowManager.LayoutParams lp = getWindow().getAttributes();
-
- if (lp.gravity == Gravity.TOP || lp.gravity == Gravity.BOTTOM) {
- lp.width = -1;
- lp.height = size;
- } else {
- lp.width = size;
- lp.height = -1;
- }
- getWindow().setAttributes(lp);
- }
-
- /**
- * Set which boundary of the screen the DockWindow sticks to.
- *
- * @param gravity The boundary of the screen to stick. See {#link
- * android.view.Gravity.LEFT}, {#link android.view.Gravity.TOP},
- * {#link android.view.Gravity.BOTTOM}, {#link
- * android.view.Gravity.RIGHT}.
- */
- public void setGravity(int gravity) {
- WindowManager.LayoutParams lp = getWindow().getAttributes();
-
- boolean oldIsVertical = (lp.gravity == Gravity.TOP || lp.gravity == Gravity.BOTTOM);
-
- lp.gravity = gravity;
-
- boolean newIsVertical = (lp.gravity == Gravity.TOP || lp.gravity == Gravity.BOTTOM);
-
- if (oldIsVertical != newIsVertical) {
- int tmp = lp.width;
- lp.width = lp.height;
- lp.height = tmp;
- getWindow().setAttributes(lp);
- }
- }
-
- private void initDockWindow() {
- WindowManager.LayoutParams lp = getWindow().getAttributes();
-
- lp.type = WindowManager.LayoutParams.TYPE_INPUT_METHOD;
- lp.setTitle("InputMethod");
-
- lp.gravity = Gravity.BOTTOM;
- lp.width = -1;
- // Let the input method window's orientation follow sensor based rotation
- // Turn this off for now, it is very problematic.
- //lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
-
- getWindow().setAttributes(lp);
- getWindow().setFlags(
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
- WindowManager.LayoutParams.FLAG_DIM_BEHIND);
- }
-}
diff --git a/core/java/android/inputmethodservice/package.html b/core/java/android/inputmethodservice/package.html
deleted file mode 100644
index 164349b..0000000
--- a/core/java/android/inputmethodservice/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<html>
-<body>
-Base classes for writing input methods. These APIs are not for use by
-normal applications, they are a framework specifically for writing input
-method components. Implementations will typically derive from
-{@link android.inputmethodservice.InputMethodService}.
-</body>
-</html>
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
deleted file mode 100644
index 1429bc1..0000000
--- a/core/java/android/net/ConnectivityManager.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.os.RemoteException;
-
-/**
- * Class that answers queries about the state of network connectivity. It also
- * notifies applications when network connectivity changes. Get an instance
- * of this class by calling
- * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.CONNECTIVITY_SERVICE)}.
- * <p>
- * The primary responsibilities of this class are to:
- * <ol>
- * <li>Monitor network connections (Wi-Fi, GPRS, UMTS, etc.)</li>
- * <li>Send broadcast intents when network connectivity changes</li>
- * <li>Attempt to "fail over" to another network when connectivity to a network
- * is lost</li>
- * <li>Provide an API that allows applications to query the coarse-grained or fine-grained
- * state of the available networks</li>
- * </ol>
- */
-public class ConnectivityManager
-{
- /**
- * A change in network connectivity has occurred. A connection has either
- * been established or lost. The NetworkInfo for the affected network is
- * sent as an extra; it should be consulted to see what kind of
- * connectivity event occurred.
- * <p/>
- * If this is a connection that was the result of failing over from a
- * disconnected network, then the FAILOVER_CONNECTION boolean extra is
- * set to true.
- * <p/>
- * For a loss of connectivity, if the connectivity manager is attempting
- * to connect (or has already connected) to another network, the
- * NetworkInfo for the new network is also passed as an extra. This lets
- * any receivers of the broadcast know that they should not necessarily
- * tell the user that no data traffic will be possible. Instead, the
- * reciever should expect another broadcast soon, indicating either that
- * the failover attempt succeeded (and so there is still overall data
- * connectivity), or that the failover attempt failed, meaning that all
- * connectivity has been lost.
- * <p/>
- * For a disconnect event, the boolean extra EXTRA_NO_CONNECTIVITY
- * is set to {@code true} if there are no connected networks at all.
- */
- public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
- /**
- * The lookup key for a {@link NetworkInfo} object. Retrieve with
- * {@link android.content.Intent#getParcelableExtra(String)}.
- */
- public static final String EXTRA_NETWORK_INFO = "networkInfo";
- /**
- * The lookup key for a boolean that indicates whether a connect event
- * is for a network to which the connectivity manager was failing over
- * following a disconnect on another network.
- * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}.
- */
- public static final String EXTRA_IS_FAILOVER = "isFailover";
- /**
- * The lookup key for a {@link NetworkInfo} object. This is supplied when
- * there is another network that it may be possible to connect to. Retrieve with
- * {@link android.content.Intent#getParcelableExtra(String)}.
- */
- public static final String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
- /**
- * The lookup key for a boolean that indicates whether there is a
- * complete lack of connectivity, i.e., no network is available.
- * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}.
- */
- public static final String EXTRA_NO_CONNECTIVITY = "noConnectivity";
- /**
- * The lookup key for a string that indicates why an attempt to connect
- * to a network failed. The string has no particular structure. It is
- * intended to be used in notifications presented to users. Retrieve
- * it with {@link android.content.Intent#getStringExtra(String)}.
- */
- public static final String EXTRA_REASON = "reason";
- /**
- * The lookup key for a string that provides optionally supplied
- * extra information about the network state. The information
- * may be passed up from the lower networking layers, and its
- * meaning may be specific to a particular network type. Retrieve
- * it with {@link android.content.Intent#getStringExtra(String)}.
- */
- public static final String EXTRA_EXTRA_INFO = "extraInfo";
-
- /**
- * Broadcast Action: The setting for background data usage has changed
- * values. Use {@link #getBackgroundDataSetting()} to get the current value.
- * <p>
- * If an application uses the network in the background, it should listen
- * for this broadcast and stop using the background data if the value is
- * false.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_BACKGROUND_DATA_SETTING_CHANGED =
- "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
-
- public static final int TYPE_MOBILE = 0;
- public static final int TYPE_WIFI = 1;
-
- public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
-
- private IConnectivityManager mService;
-
- static public boolean isNetworkTypeValid(int networkType) {
- return networkType == TYPE_WIFI || networkType == TYPE_MOBILE;
- }
-
- public void setNetworkPreference(int preference) {
- try {
- mService.setNetworkPreference(preference);
- } catch (RemoteException e) {
- }
- }
-
- public int getNetworkPreference() {
- try {
- return mService.getNetworkPreference();
- } catch (RemoteException e) {
- return -1;
- }
- }
-
- public NetworkInfo getActiveNetworkInfo() {
- try {
- return mService.getActiveNetworkInfo();
- } catch (RemoteException e) {
- return null;
- }
- }
-
- public NetworkInfo getNetworkInfo(int networkType) {
- try {
- return mService.getNetworkInfo(networkType);
- } catch (RemoteException e) {
- return null;
- }
- }
-
- public NetworkInfo[] getAllNetworkInfo() {
- try {
- return mService.getAllNetworkInfo();
- } catch (RemoteException e) {
- return null;
- }
- }
-
- /** {@hide} */
- public boolean setRadios(boolean turnOn) {
- try {
- return mService.setRadios(turnOn);
- } catch (RemoteException e) {
- return false;
- }
- }
-
- /** {@hide} */
- public boolean setRadio(int networkType, boolean turnOn) {
- try {
- return mService.setRadio(networkType, turnOn);
- } catch (RemoteException e) {
- return false;
- }
- }
-
- /**
- * Tells the underlying networking system that the caller wants to
- * begin using the named feature. The interpretation of {@code feature}
- * is completely up to each networking implementation.
- * @param networkType specifies which network the request pertains to
- * @param feature the name of the feature to be used
- * @return an integer value representing the outcome of the request.
- * The interpretation of this value is specific to each networking
- * implementation+feature combination, except that the value {@code -1}
- * always indicates failure.
- */
- public int startUsingNetworkFeature(int networkType, String feature) {
- try {
- return mService.startUsingNetworkFeature(networkType, feature);
- } catch (RemoteException e) {
- return -1;
- }
- }
-
- /**
- * Tells the underlying networking system that the caller is finished
- * using the named feature. The interpretation of {@code feature}
- * is completely up to each networking implementation.
- * @param networkType specifies which network the request pertains to
- * @param feature the name of the feature that is no longer needed
- * @return an integer value representing the outcome of the request.
- * The interpretation of this value is specific to each networking
- * implementation+feature combination, except that the value {@code -1}
- * always indicates failure.
- */
- public int stopUsingNetworkFeature(int networkType, String feature) {
- try {
- return mService.stopUsingNetworkFeature(networkType, feature);
- } catch (RemoteException e) {
- return -1;
- }
- }
-
- /**
- * Ensure that a network route exists to deliver traffic to the specified
- * host via the specified network interface. An attempt to add a route that
- * already exists is ignored, but treated as successful.
- * @param networkType the type of the network over which traffic to the specified
- * host is to be routed
- * @param hostAddress the IP address of the host to which the route is desired
- * @return {@code true} on success, {@code false} on failure
- */
- public boolean requestRouteToHost(int networkType, int hostAddress) {
- try {
- return mService.requestRouteToHost(networkType, hostAddress);
- } catch (RemoteException e) {
- return false;
- }
- }
-
- /**
- * Returns the value of the setting for background data usage. If false,
- * applications should not use the network if the application is not in the
- * foreground. Developers should respect this setting, and check the value
- * of this before performing any background data operations.
- * <p>
- * All applications that have background services that use the network
- * should listen to {@link #ACTION_BACKGROUND_DATA_SETTING_CHANGED}.
- *
- * @return Whether background data usage is allowed.
- */
- public boolean getBackgroundDataSetting() {
- try {
- return mService.getBackgroundDataSetting();
- } catch (RemoteException e) {
- // Err on the side of safety
- return false;
- }
- }
-
- /**
- * Sets the value of the setting for background data usage.
- *
- * @param allowBackgroundData Whether an application should use data while
- * it is in the background.
- *
- * @attr ref android.Manifest.permission#CHANGE_BACKGROUND_DATA_SETTING
- * @see #getBackgroundDataSetting()
- * @hide
- */
- public void setBackgroundDataSetting(boolean allowBackgroundData) {
- try {
- mService.setBackgroundDataSetting(allowBackgroundData);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Don't allow use of default constructor.
- */
- @SuppressWarnings({"UnusedDeclaration"})
- private ConnectivityManager() {
- }
-
- /**
- * {@hide}
- */
- public ConnectivityManager(IConnectivityManager service) {
- if (service == null) {
- throw new IllegalArgumentException(
- "ConnectivityManager() cannot be constructed with null service");
- }
- mService = service;
- }
-}
diff --git a/core/java/android/net/Credentials.java b/core/java/android/net/Credentials.java
deleted file mode 100644
index 7f6cf9d..0000000
--- a/core/java/android/net/Credentials.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-/**
- * A class for representing UNIX credentials passed via ancillary data
- * on UNIX domain sockets. See "man 7 unix" on a desktop linux distro.
- */
-public class Credentials {
- /** pid of process. root peers may lie. */
- private final int pid;
- /** uid of process. root peers may lie. */
- private final int uid;
- /** gid of process. root peers may lie. */
- private final int gid;
-
- public Credentials (int pid, int uid, int gid) {
- this.pid = pid;
- this.uid = uid;
- this.gid = gid;
- }
-
- public int getPid() {
- return pid;
- }
-
- public int getUid() {
- return uid;
- }
-
- public int getGid() {
- return gid;
- }
-}
diff --git a/core/java/android/net/DhcpInfo.aidl b/core/java/android/net/DhcpInfo.aidl
deleted file mode 100644
index 29cd21f..0000000
--- a/core/java/android/net/DhcpInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2008, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-parcelable DhcpInfo;
diff --git a/core/java/android/net/DhcpInfo.java b/core/java/android/net/DhcpInfo.java
deleted file mode 100644
index 1178bec..0000000
--- a/core/java/android/net/DhcpInfo.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-/**
- * A simple object for retrieving the results of a DHCP request.
- */
-public class DhcpInfo implements Parcelable {
- public int ipAddress;
- public int gateway;
- public int netmask;
-
- public int dns1;
- public int dns2;
-
- public int serverAddress;
- public int leaseDuration;
-
- public DhcpInfo() {
- super();
- }
-
- public String toString() {
- StringBuffer str = new StringBuffer();
-
- str.append("ipaddr "); putAddress(str, ipAddress);
- str.append(" gateway "); putAddress(str, gateway);
- str.append(" netmask "); putAddress(str, netmask);
- str.append(" dns1 "); putAddress(str, dns1);
- str.append(" dns2 "); putAddress(str, dns2);
- str.append(" DHCP server "); putAddress(str, serverAddress);
- str.append(" lease ").append(leaseDuration).append(" seconds");
-
- return str.toString();
- }
-
- private static void putAddress(StringBuffer buf, int addr) {
- buf.append(addr & 0xff).append('.').
- append((addr >>>= 8) & 0xff).append('.').
- append((addr >>>= 8) & 0xff).append('.').
- append((addr >>>= 8) & 0xff);
- }
-
- /** Implement the Parcelable interface {@hide} */
- public int describeContents() {
- return 0;
- }
-
- /** Implement the Parcelable interface {@hide} */
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(ipAddress);
- dest.writeInt(gateway);
- dest.writeInt(netmask);
- dest.writeInt(dns1);
- dest.writeInt(dns2);
- dest.writeInt(serverAddress);
- dest.writeInt(leaseDuration);
- }
-
- /** Implement the Parcelable interface {@hide} */
- public static final Creator<DhcpInfo> CREATOR =
- new Creator<DhcpInfo>() {
- public DhcpInfo createFromParcel(Parcel in) {
- DhcpInfo info = new DhcpInfo();
- info.ipAddress = in.readInt();
- info.gateway = in.readInt();
- info.netmask = in.readInt();
- info.dns1 = in.readInt();
- info.dns2 = in.readInt();
- info.serverAddress = in.readInt();
- info.leaseDuration = in.readInt();
- return info;
- }
-
- public DhcpInfo[] newArray(int size) {
- return new DhcpInfo[size];
- }
- };
-}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
deleted file mode 100644
index de68598..0000000
--- a/core/java/android/net/IConnectivityManager.aidl
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * Copyright (c) 2008, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.net.NetworkInfo;
-
-/**
- * Interface that answers queries about, and allows changing, the
- * state of network connectivity.
- */
-/** {@hide} */
-interface IConnectivityManager
-{
- void setNetworkPreference(int pref);
-
- int getNetworkPreference();
-
- NetworkInfo getActiveNetworkInfo();
-
- NetworkInfo getNetworkInfo(int networkType);
-
- NetworkInfo[] getAllNetworkInfo();
-
- boolean setRadios(boolean onOff);
-
- boolean setRadio(int networkType, boolean turnOn);
-
- int startUsingNetworkFeature(int networkType, in String feature);
-
- int stopUsingNetworkFeature(int networkType, in String feature);
-
- boolean requestRouteToHost(int networkType, int hostAddress);
-
- boolean getBackgroundDataSetting();
-
- void setBackgroundDataSetting(boolean allowBackgroundData);
-}
diff --git a/core/java/android/net/LocalServerSocket.java b/core/java/android/net/LocalServerSocket.java
deleted file mode 100644
index 2b93fc2..0000000
--- a/core/java/android/net/LocalServerSocket.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import java.io.IOException;
-import java.io.FileDescriptor;
-
-/**
- * non-standard class for creating inbound UNIX-domain socket
- * on the Android platform, this is created in the Linux non-filesystem
- * namespace.
- *
- * On simulator platforms, this may be created in a temporary directory on
- * the filesystem
- */
-public class LocalServerSocket {
- private final LocalSocketImpl impl;
- private final LocalSocketAddress localAddress;
-
- /** 50 seems a bit much, but it's what was here */
- private static final int LISTEN_BACKLOG = 50;
-
- /**
- * Crewates a new server socket listening at specified name.
- * On the Android platform, the name is created in the Linux
- * abstract namespace (instead of on the filesystem).
- *
- * @param name address for socket
- * @throws IOException
- */
- public LocalServerSocket(String name) throws IOException
- {
- impl = new LocalSocketImpl();
-
- impl.create(true);
-
- localAddress = new LocalSocketAddress(name);
- impl.bind(localAddress);
-
- impl.listen(LISTEN_BACKLOG);
- }
-
- /**
- * Create a LocalServerSocket from a file descriptor that's already
- * been created and bound. listen() will be called immediately on it.
- * Used for cases where file descriptors are passed in via environment
- * variables
- *
- * @param fd bound file descriptor
- * @throws IOException
- */
- public LocalServerSocket(FileDescriptor fd) throws IOException
- {
- impl = new LocalSocketImpl(fd);
- impl.listen(LISTEN_BACKLOG);
- localAddress = impl.getSockAddress();
- }
-
- /**
- * Obtains the socket's local address
- *
- * @return local address
- */
- public LocalSocketAddress getLocalSocketAddress()
- {
- return localAddress;
- }
-
- /**
- * Accepts a new connection to the socket. Blocks until a new
- * connection arrives.
- *
- * @return a socket representing the new connection.
- * @throws IOException
- */
- public LocalSocket accept() throws IOException
- {
- LocalSocketImpl acceptedImpl = new LocalSocketImpl();
-
- impl.accept (acceptedImpl);
-
- return new LocalSocket(acceptedImpl);
- }
-
- /**
- * Returns file descriptor or null if not yet open/already closed
- *
- * @return fd or null
- */
- public FileDescriptor getFileDescriptor() {
- return impl.getFileDescriptor();
- }
-
- /**
- * Closes server socket.
- *
- * @throws IOException
- */
- public void close() throws IOException
- {
- impl.close();
- }
-}
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
deleted file mode 100644
index 4039a69..0000000
--- a/core/java/android/net/LocalSocket.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.SocketOptions;
-
-/**
- * Creates a (non-server) socket in the UNIX-domain namespace. The interface
- * here is not entirely unlike that of java.net.Socket
- */
-public class LocalSocket {
-
- private LocalSocketImpl impl;
- private volatile boolean implCreated;
- private LocalSocketAddress localAddress;
- private boolean isBound;
- private boolean isConnected;
-
- /**
- * Creates a AF_LOCAL/UNIX domain stream socket.
- */
- public LocalSocket() {
- this(new LocalSocketImpl());
- isBound = false;
- isConnected = false;
- }
-
- /**
- * for use with AndroidServerSocket
- * @param impl a SocketImpl
- */
- /*package*/ LocalSocket(LocalSocketImpl impl) {
- this.impl = impl;
- this.isConnected = false;
- this.isBound = false;
- }
-
- /** {@inheritDoc} */
- @Override
- public String toString() {
- return super.toString() + " impl:" + impl;
- }
-
- /**
- * It's difficult to discern from the spec when impl.create() should be
- * called, but it seems like a reasonable rule is "as soon as possible,
- * but not in a context where IOException cannot be thrown"
- *
- * @throws IOException from SocketImpl.create()
- */
- private void implCreateIfNeeded() throws IOException {
- if (!implCreated) {
- synchronized (this) {
- if (!implCreated) {
- implCreated = true;
- impl.create(true);
- }
- }
- }
- }
-
- /**
- * Connects this socket to an endpoint. May only be called on an instance
- * that has not yet been connected.
- *
- * @param endpoint endpoint address
- * @throws IOException if socket is in invalid state or the address does
- * not exist.
- */
- public void connect(LocalSocketAddress endpoint) throws IOException {
- synchronized (this) {
- if (isConnected) {
- throw new IOException("already connected");
- }
-
- implCreateIfNeeded();
- impl.connect(endpoint, 0);
- isConnected = true;
- isBound = true;
- }
- }
-
- /**
- * Binds this socket to an endpoint name. May only be called on an instance
- * that has not yet been bound.
- *
- * @param bindpoint endpoint address
- * @throws IOException
- */
- public void bind(LocalSocketAddress bindpoint) throws IOException {
- implCreateIfNeeded();
-
- synchronized (this) {
- if (isBound) {
- throw new IOException("already bound");
- }
-
- localAddress = bindpoint;
- impl.bind(localAddress);
- isBound = true;
- }
- }
-
- /**
- * Retrieves the name that this socket is bound to, if any.
- *
- * @return Local address or null if anonymous
- */
- public LocalSocketAddress getLocalSocketAddress() {
- return localAddress;
- }
-
- /**
- * Retrieves the input stream for this instance.
- *
- * @return input stream
- * @throws IOException if socket has been closed or cannot be created.
- */
- public InputStream getInputStream() throws IOException {
- implCreateIfNeeded();
- return impl.getInputStream();
- }
-
- /**
- * Retrieves the output stream for this instance.
- *
- * @return output stream
- * @throws IOException if socket has been closed or cannot be created.
- */
- public OutputStream getOutputStream() throws IOException {
- implCreateIfNeeded();
- return impl.getOutputStream();
- }
-
- /**
- * Closes the socket.
- *
- * @throws IOException
- */
- public void close() throws IOException {
- implCreateIfNeeded();
- impl.close();
- }
-
- /**
- * Shuts down the input side of the socket.
- *
- * @throws IOException
- */
- public void shutdownInput() throws IOException {
- implCreateIfNeeded();
- impl.shutdownInput();
- }
-
- /**
- * Shuts down the output side of the socket.
- *
- * @throws IOException
- */
- public void shutdownOutput() throws IOException {
- implCreateIfNeeded();
- impl.shutdownOutput();
- }
-
- public void setReceiveBufferSize(int size) throws IOException {
- impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
- }
-
- public int getReceiveBufferSize() throws IOException {
- return ((Integer) impl.getOption(SocketOptions.SO_RCVBUF)).intValue();
- }
-
- public void setSoTimeout(int n) throws IOException {
- impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(n));
- }
-
- public int getSoTimeout() throws IOException {
- return ((Integer) impl.getOption(SocketOptions.SO_TIMEOUT)).intValue();
- }
-
- public void setSendBufferSize(int n) throws IOException {
- impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(n));
- }
-
- public int getSendBufferSize() throws IOException {
- return ((Integer) impl.getOption(SocketOptions.SO_SNDBUF)).intValue();
- }
-
- //???SEC
- public LocalSocketAddress getRemoteSocketAddress() {
- throw new UnsupportedOperationException();
- }
-
- //???SEC
- public synchronized boolean isConnected() {
- return isConnected;
- }
-
- //???SEC
- public boolean isClosed() {
- throw new UnsupportedOperationException();
- }
-
- //???SEC
- public synchronized boolean isBound() {
- return isBound;
- }
-
- //???SEC
- public boolean isOutputShutdown() {
- throw new UnsupportedOperationException();
- }
-
- //???SEC
- public boolean isInputShutdown() {
- throw new UnsupportedOperationException();
- }
-
- //???SEC
- public void connect(LocalSocketAddress endpoint, int timeout)
- throws IOException {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Enqueues a set of file descriptors to send to the peer. The queue
- * is one deep. The file descriptors will be sent with the next write
- * of normal data, and will be delivered in a single ancillary message.
- * See "man 7 unix" SCM_RIGHTS on a desktop Linux machine.
- *
- * @param fds non-null; file descriptors to send.
- */
- public void setFileDescriptorsForSend(FileDescriptor[] fds) {
- impl.setFileDescriptorsForSend(fds);
- }
-
- /**
- * Retrieves a set of file descriptors that a peer has sent through
- * an ancillary message. This method retrieves the most recent set sent,
- * and then returns null until a new set arrives.
- * File descriptors may only be passed along with regular data, so this
- * method can only return a non-null after a read operation.
- *
- * @return null or file descriptor array
- * @throws IOException
- */
- public FileDescriptor[] getAncillaryFileDescriptors() throws IOException {
- return impl.getAncillaryFileDescriptors();
- }
-
- /**
- * Retrieves the credentials of this socket's peer. Only valid on
- * connected sockets.
- *
- * @return non-null; peer credentials
- * @throws IOException
- */
- public Credentials getPeerCredentials() throws IOException {
- return impl.getPeerCredentials();
- }
-
- /**
- * Returns file descriptor or null if not yet open/already closed
- *
- * @return fd or null
- */
- public FileDescriptor getFileDescriptor() {
- return impl.getFileDescriptor();
- }
-}
diff --git a/core/java/android/net/LocalSocketAddress.java b/core/java/android/net/LocalSocketAddress.java
deleted file mode 100644
index 8265b85..0000000
--- a/core/java/android/net/LocalSocketAddress.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-/**
- * A UNIX-domain (AF_LOCAL) socket address. For use with
- * android.net.LocalSocket and android.net.LocalServerSocket.
- *
- * On the Android system, these names refer to names in the Linux
- * abstract (non-filesystem) UNIX domain namespace.
- */
-public class LocalSocketAddress
-{
- /**
- * The namespace that this address exists in. See also
- * include/cutils/sockets.h ANDROID_SOCKET_NAMESPACE_*
- */
- public enum Namespace {
- /** A socket in the Linux abstract namespace */
- ABSTRACT(0),
- /**
- * A socket in the Android reserved namespace in /dev/socket.
- * Only the init process may create a socket here.
- */
- RESERVED(1),
- /**
- * A socket named with a normal filesystem path.
- */
- FILESYSTEM(2);
-
- /** The id matches with a #define in include/cutils/sockets.h */
- private int id;
- Namespace (int id) {
- this.id = id;
- }
-
- /**
- * @return int constant shared with native code
- */
- /*package*/ int getId() {
- return id;
- }
- }
-
- private final String name;
- private final Namespace namespace;
-
- /**
- * Creates an instance with a given name.
- *
- * @param name non-null name
- * @param namespace namespace the name should be created in.
- */
- public LocalSocketAddress(String name, Namespace namespace) {
- this.name = name;
- this.namespace = namespace;
- }
-
- /**
- * Creates an instance with a given name in the {@link Namespace#ABSTRACT}
- * namespace
- *
- * @param name non-null name
- */
- public LocalSocketAddress(String name) {
- this(name,Namespace.ABSTRACT);
- }
-
- /**
- * Retrieves the string name of this address
- * @return string name
- */
- public String getName()
- {
- return name;
- }
-
- /**
- * Returns the namespace used by this address.
- *
- * @return non-null a namespace
- */
- public Namespace getNamespace() {
- return namespace;
- }
-}
diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java
deleted file mode 100644
index 6c36a7d..0000000
--- a/core/java/android/net/LocalSocketImpl.java
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.InputStream;
-import java.io.FileDescriptor;
-import java.net.SocketOptions;
-
-/**
- * Socket implementation used for android.net.LocalSocket and
- * android.net.LocalServerSocket. Supports only AF_LOCAL sockets.
- */
-class LocalSocketImpl
-{
- private SocketInputStream fis;
- private SocketOutputStream fos;
- private Object readMonitor = new Object();
- private Object writeMonitor = new Object();
-
- /** null if closed or not yet created */
- private FileDescriptor fd;
-
- // These fields are accessed by native code;
- /** file descriptor array received during a previous read */
- FileDescriptor[] inboundFileDescriptors;
- /** file descriptor array that should be written during next write */
- FileDescriptor[] outboundFileDescriptors;
-
- /**
- * An input stream for local sockets. Needed because we may
- * need to read ancillary data.
- */
- class SocketInputStream extends InputStream {
- /** {@inheritDoc} */
- @Override
- public int available() throws IOException {
- return available_native(fd);
- }
-
- /** {@inheritDoc} */
- @Override
- public void close() throws IOException {
- LocalSocketImpl.this.close();
- }
-
- /** {@inheritDoc} */
- @Override
- public int read() throws IOException {
- int ret;
- synchronized (readMonitor) {
- FileDescriptor myFd = fd;
- if (myFd == null) throw new IOException("socket closed");
-
- ret = read_native(myFd);
- return ret;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public int read(byte[] b) throws IOException {
- return read(b, 0, b.length);
- }
-
- /** {@inheritDoc} */
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- synchronized (readMonitor) {
- FileDescriptor myFd = fd;
- if (myFd == null) throw new IOException("socket closed");
-
- if (off < 0 || len < 0 || (off + len) > b.length ) {
- throw new ArrayIndexOutOfBoundsException();
- }
-
- int ret = readba_native(b, off, len, myFd);
-
- return ret;
- }
- }
- }
-
- /**
- * An output stream for local sockets. Needed because we may
- * need to read ancillary data.
- */
- class SocketOutputStream extends OutputStream {
- /** {@inheritDoc} */
- @Override
- public void close() throws IOException {
- LocalSocketImpl.this.close();
- }
-
- /** {@inheritDoc} */
- @Override
- public void write (byte[] b) throws IOException {
- write(b, 0, b.length);
- }
-
- /** {@inheritDoc} */
- @Override
- public void write (byte[] b, int off, int len) throws IOException {
- synchronized (writeMonitor) {
- FileDescriptor myFd = fd;
- if (myFd == null) throw new IOException("socket closed");
-
- if (off < 0 || len < 0 || (off + len) > b.length ) {
- throw new ArrayIndexOutOfBoundsException();
- }
- writeba_native(b, off, len, myFd);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public void write (int b) throws IOException {
- synchronized (writeMonitor) {
- FileDescriptor myFd = fd;
- if (myFd == null) throw new IOException("socket closed");
- write_native(b, myFd);
- }
- }
- }
-
- private native int available_native(FileDescriptor fd) throws IOException;
- private native void close_native(FileDescriptor fd) throws IOException;
- private native int read_native(FileDescriptor fd) throws IOException;
- private native int readba_native(byte[] b, int off, int len,
- FileDescriptor fd) throws IOException;
- private native void writeba_native(byte[] b, int off, int len,
- FileDescriptor fd) throws IOException;
- private native void write_native(int b, FileDescriptor fd)
- throws IOException;
- private native void connectLocal(FileDescriptor fd, String name,
- int namespace) throws IOException;
- private native void bindLocal(FileDescriptor fd, String name, int namespace)
- throws IOException;
- private native FileDescriptor create_native(boolean stream)
- throws IOException;
- private native void listen_native(FileDescriptor fd, int backlog)
- throws IOException;
- private native void shutdown(FileDescriptor fd, boolean shutdownInput);
- private native Credentials getPeerCredentials_native(
- FileDescriptor fd) throws IOException;
- private native int getOption_native(FileDescriptor fd, int optID)
- throws IOException;
- private native void setOption_native(FileDescriptor fd, int optID,
- int b, int value) throws IOException;
-
-// private native LocalSocketAddress getSockName_native
-// (FileDescriptor fd) throws IOException;
-
- /**
- * Accepts a connection on a server socket.
- *
- * @param fd file descriptor of server socket
- * @param s socket implementation that will become the new socket
- * @return file descriptor of new socket
- */
- private native FileDescriptor accept
- (FileDescriptor fd, LocalSocketImpl s) throws IOException;
-
- /**
- * Create a new instance.
- */
- /*package*/ LocalSocketImpl()
- {
- }
-
- /**
- * Create a new instance from a file descriptor representing
- * a bound socket. The state of the file descriptor is not checked here
- * but the caller can verify socket state by calling listen().
- *
- * @param fd non-null; bound file descriptor
- */
- /*package*/ LocalSocketImpl(FileDescriptor fd) throws IOException
- {
- this.fd = fd;
- }
-
- public String toString() {
- return super.toString() + " fd:" + fd;
- }
-
- /**
- * Creates a socket in the underlying OS.
- *
- * @param stream true if this should be a stream socket, false for
- * datagram.
- * @throws IOException
- */
- public void create (boolean stream) throws IOException {
- // no error if socket already created
- // need this for LocalServerSocket.accept()
- if (fd == null) {
- fd = create_native(stream);
- }
- }
-
- /**
- * Closes the socket.
- *
- * @throws IOException
- */
- public void close() throws IOException {
- synchronized (LocalSocketImpl.this) {
- if (fd == null) return;
- close_native(fd);
- fd = null;
- }
- }
-
- /** note timeout presently ignored */
- protected void connect(LocalSocketAddress address, int timeout)
- throws IOException
- {
- if (fd == null) {
- throw new IOException("socket not created");
- }
-
- connectLocal(fd, address.getName(), address.getNamespace().getId());
- }
-
- /**
- * Binds this socket to an endpoint name. May only be called on an instance
- * that has not yet been bound.
- *
- * @param endpoint endpoint address
- * @throws IOException
- */
- public void bind(LocalSocketAddress endpoint) throws IOException
- {
- if (fd == null) {
- throw new IOException("socket not created");
- }
-
- bindLocal(fd, endpoint.getName(), endpoint.getNamespace().getId());
- }
-
- protected void listen(int backlog) throws IOException
- {
- if (fd == null) {
- throw new IOException("socket not created");
- }
-
- listen_native(fd, backlog);
- }
-
- /**
- * Accepts a new connection to the socket. Blocks until a new
- * connection arrives.
- *
- * @param s a socket that will be used to represent the new connection.
- * @throws IOException
- */
- protected void accept(LocalSocketImpl s) throws IOException
- {
- if (fd == null) {
- throw new IOException("socket not created");
- }
-
- s.fd = accept(fd, s);
- }
-
- /**
- * Retrieves the input stream for this instance.
- *
- * @return input stream
- * @throws IOException if socket has been closed or cannot be created.
- */
- protected InputStream getInputStream() throws IOException
- {
- if (fd == null) {
- throw new IOException("socket not created");
- }
-
- synchronized (this) {
- if (fis == null) {
- fis = new SocketInputStream();
- }
-
- return fis;
- }
- }
-
- /**
- * Retrieves the output stream for this instance.
- *
- * @return output stream
- * @throws IOException if socket has been closed or cannot be created.
- */
- protected OutputStream getOutputStream() throws IOException
- {
- if (fd == null) {
- throw new IOException("socket not created");
- }
-
- synchronized (this) {
- if (fos == null) {
- fos = new SocketOutputStream();
- }
-
- return fos;
- }
- }
-
- /**
- * Returns the number of bytes available for reading without blocking.
- *
- * @return >= 0 count bytes available
- * @throws IOException
- */
- protected int available() throws IOException
- {
- return getInputStream().available();
- }
-
- /**
- * Shuts down the input side of the socket.
- *
- * @throws IOException
- */
- protected void shutdownInput() throws IOException
- {
- if (fd == null) {
- throw new IOException("socket not created");
- }
-
- shutdown(fd, true);
- }
-
- /**
- * Shuts down the output side of the socket.
- *
- * @throws IOException
- */
- protected void shutdownOutput() throws IOException
- {
- if (fd == null) {
- throw new IOException("socket not created");
- }
-
- shutdown(fd, false);
- }
-
- protected FileDescriptor getFileDescriptor()
- {
- return fd;
- }
-
- protected boolean supportsUrgentData()
- {
- return false;
- }
-
- protected void sendUrgentData(int data) throws IOException
- {
- throw new RuntimeException ("not impled");
- }
-
- public Object getOption(int optID) throws IOException
- {
- if (fd == null) {
- throw new IOException("socket not created");
- }
-
- if (optID == SocketOptions.SO_TIMEOUT) {
- return 0;
- }
-
- int value = getOption_native(fd, optID);
- switch (optID)
- {
- case SocketOptions.SO_RCVBUF:
- case SocketOptions.SO_SNDBUF:
- return value;
- case SocketOptions.SO_REUSEADDR:
- default:
- return value;
- }
- }
-
- public void setOption(int optID, Object value)
- throws IOException {
- /*
- * Boolean.FALSE is used to disable some options, so it
- * is important to distinguish between FALSE and unset.
- * We define it here that -1 is unset, 0 is FALSE, and 1
- * is TRUE.
- */
- int boolValue = -1;
- int intValue = 0;
-
- if (fd == null) {
- throw new IOException("socket not created");
- }
-
- if (value instanceof Integer) {
- intValue = (Integer)value;
- } else if (value instanceof Boolean) {
- boolValue = ((Boolean) value)? 1 : 0;
- } else {
- throw new IOException("bad value: " + value);
- }
-
- setOption_native(fd, optID, boolValue, intValue);
- }
-
- /**
- * Enqueues a set of file descriptors to send to the peer. The queue
- * is one deep. The file descriptors will be sent with the next write
- * of normal data, and will be delivered in a single ancillary message.
- * See "man 7 unix" SCM_RIGHTS on a desktop Linux machine.
- *
- * @param fds non-null; file descriptors to send.
- * @throws IOException
- */
- public void setFileDescriptorsForSend(FileDescriptor[] fds) {
- synchronized(writeMonitor) {
- outboundFileDescriptors = fds;
- }
- }
-
- /**
- * Retrieves a set of file descriptors that a peer has sent through
- * an ancillary message. This method retrieves the most recent set sent,
- * and then returns null until a new set arrives.
- * File descriptors may only be passed along with regular data, so this
- * method can only return a non-null after a read operation.
- *
- * @return null or file descriptor array
- * @throws IOException
- */
- public FileDescriptor[] getAncillaryFileDescriptors() throws IOException {
- synchronized(readMonitor) {
- FileDescriptor[] result = inboundFileDescriptors;
-
- inboundFileDescriptors = null;
- return result;
- }
- }
-
- /**
- * Retrieves the credentials of this socket's peer. Only valid on
- * connected sockets.
- *
- * @return non-null; peer credentials
- * @throws IOException
- */
- public Credentials getPeerCredentials() throws IOException
- {
- return getPeerCredentials_native(fd);
- }
-
- /**
- * Retrieves the socket name from the OS.
- *
- * @return non-null; socket name
- * @throws IOException on failure
- */
- public LocalSocketAddress getSockAddress() throws IOException
- {
- return null;
- //TODO implement this
- //return getSockName_native(fd);
- }
-
- @Override
- protected void finalize() throws IOException {
- close();
- }
-}
-
diff --git a/core/java/android/net/MailTo.java b/core/java/android/net/MailTo.java
deleted file mode 100644
index ca28f86..0000000
--- a/core/java/android/net/MailTo.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- *
- * MailTo URL parser
- *
- * This class parses a mailto scheme URL and then can be queried for
- * the parsed parameters. This implements RFC 2368.
- *
- */
-public class MailTo {
-
- static public final String MAILTO_SCHEME = "mailto:";
-
- // All the parsed content is added to the headers.
- private HashMap<String, String> mHeaders;
-
- // Well known headers
- static private final String TO = "to";
- static private final String BODY = "body";
- static private final String CC = "cc";
- static private final String SUBJECT = "subject";
-
-
- /**
- * Test to see if the given string is a mailto URL
- * @param url string to be tested
- * @return true if the string is a mailto URL
- */
- public static boolean isMailTo(String url) {
- if (url != null && url.startsWith(MAILTO_SCHEME)) {
- return true;
- }
- return false;
- }
-
- /**
- * Parse and decode a mailto scheme string. This parser implements
- * RFC 2368. The returned object can be queried for the parsed parameters.
- * @param url String containing a mailto URL
- * @return MailTo object
- * @exception ParseException if the scheme is not a mailto URL
- */
- public static MailTo parse(String url) throws ParseException {
- if (url == null) {
- throw new NullPointerException();
- }
- if (!isMailTo(url)) {
- throw new ParseException("Not a mailto scheme");
- }
- // Strip the scheme as the Uri parser can't cope with it.
- String noScheme = url.substring(MAILTO_SCHEME.length());
- Uri email = Uri.parse(noScheme);
- MailTo m = new MailTo();
-
- // Parse out the query parameters
- String query = email.getQuery();
- if (query != null ) {
- String[] queries = query.split("&");
- for (String q : queries) {
- String[] nameval = q.split("=");
- if (nameval.length == 0) {
- continue;
- }
- // insert the headers with the name in lowercase so that
- // we can easily find common headers
- m.mHeaders.put(Uri.decode(nameval[0]).toLowerCase(),
- nameval.length > 1 ? Uri.decode(nameval[1]) : null);
- }
- }
-
- // Address can be specified in both the headers and just after the
- // mailto line. Join the two together.
- String address = email.getPath();
- if (address != null) {
- String addr = m.getTo();
- if (addr != null) {
- address += ", " + addr;
- }
- m.mHeaders.put(TO, address);
- }
-
- return m;
- }
-
- /**
- * Retrieve the To address line from the parsed mailto URL. This could be
- * several email address that are comma-space delimited.
- * If no To line was specified, then null is return
- * @return comma delimited email addresses or null
- */
- public String getTo() {
- return mHeaders.get(TO);
- }
-
- /**
- * Retrieve the CC address line from the parsed mailto URL. This could be
- * several email address that are comma-space delimited.
- * If no CC line was specified, then null is return
- * @return comma delimited email addresses or null
- */
- public String getCc() {
- return mHeaders.get(CC);
- }
-
- /**
- * Retrieve the subject line from the parsed mailto URL.
- * If no subject line was specified, then null is return
- * @return subject or null
- */
- public String getSubject() {
- return mHeaders.get(SUBJECT);
- }
-
- /**
- * Retrieve the body line from the parsed mailto URL.
- * If no body line was specified, then null is return
- * @return body or null
- */
- public String getBody() {
- return mHeaders.get(BODY);
- }
-
- /**
- * Retrieve all the parsed email headers from the mailto URL
- * @return map containing all parsed values
- */
- public Map<String, String> getHeaders() {
- return mHeaders;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder(MAILTO_SCHEME);
- sb.append('?');
- for (Map.Entry<String,String> header : mHeaders.entrySet()) {
- sb.append(Uri.encode(header.getKey()));
- sb.append('=');
- sb.append(Uri.encode(header.getValue()));
- sb.append('&');
- }
- return sb.toString();
- }
-
- /**
- * Private constructor. The only way to build a Mailto object is through
- * the parse() method.
- */
- private MailTo() {
- mHeaders = new HashMap<String, String>();
- }
-}
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
deleted file mode 100644
index 1d939e1..0000000
--- a/core/java/android/net/MobileDataStateTracker.java
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.RemoteException;
-import android.os.Handler;
-import android.os.ServiceManager;
-import android.os.SystemProperties;
-import com.android.internal.telephony.ITelephony;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.TelephonyIntents;
-import android.net.NetworkInfo.DetailedState;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-import android.text.TextUtils;
-
-import java.util.List;
-import java.util.ArrayList;
-
-/**
- * Track the state of mobile data connectivity. This is done by
- * receiving broadcast intents from the Phone process whenever
- * the state of data connectivity changes.
- *
- * {@hide}
- */
-public class MobileDataStateTracker extends NetworkStateTracker {
-
- private static final String TAG = "MobileDataStateTracker";
- private static final boolean DBG = false;
-
- private Phone.DataState mMobileDataState;
- private ITelephony mPhoneService;
- private static final String[] sDnsPropNames = {
- "net.rmnet0.dns1",
- "net.rmnet0.dns2",
- "net.eth0.dns1",
- "net.eth0.dns2",
- "net.eth0.dns3",
- "net.eth0.dns4",
- "net.gprs.dns1",
- "net.gprs.dns2"
- };
- private List<String> mDnsServers;
- private String mInterfaceName;
- private int mDefaultGatewayAddr;
- private int mLastCallingPid = -1;
-
- /**
- * Create a new MobileDataStateTracker
- * @param context the application context of the caller
- * @param target a message handler for getting callbacks about state changes
- */
- public MobileDataStateTracker(Context context, Handler target) {
- super(context, target, ConnectivityManager.TYPE_MOBILE,
- TelephonyManager.getDefault().getNetworkType(), "MOBILE",
- TelephonyManager.getDefault().getNetworkTypeName());
- mPhoneService = null;
- mDnsServers = new ArrayList<String>();
- }
-
- /**
- * Begin monitoring mobile data connectivity.
- */
- public void startMonitoring() {
- IntentFilter filter =
- new IntentFilter(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
- filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
- filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
-
- Intent intent = mContext.registerReceiver(new MobileDataStateReceiver(), filter);
- if (intent != null)
- mMobileDataState = getMobileDataState(intent);
- else
- mMobileDataState = Phone.DataState.DISCONNECTED;
- }
-
- private static Phone.DataState getMobileDataState(Intent intent) {
- String str = intent.getStringExtra(Phone.STATE_KEY);
- if (str != null)
- return Enum.valueOf(Phone.DataState.class, str);
- else
- return Phone.DataState.DISCONNECTED;
- }
-
- private class MobileDataStateReceiver extends BroadcastReceiver {
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
- Phone.DataState state = getMobileDataState(intent);
- String reason = intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY);
- String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
- boolean unavailable = intent.getBooleanExtra(Phone.NETWORK_UNAVAILABLE_KEY, false);
- if (DBG) Log.d(TAG, "Received " + intent.getAction() +
- " broadcast - state = " + state
- + ", unavailable = " + unavailable
- + ", reason = " + (reason == null ? "(unspecified)" : reason));
- mNetworkInfo.setIsAvailable(!unavailable);
- if (mMobileDataState != state) {
- mMobileDataState = state;
-
- switch (state) {
- case DISCONNECTED:
- setDetailedState(DetailedState.DISCONNECTED, reason, apnName);
- if (mInterfaceName != null) {
- NetworkUtils.resetConnections(mInterfaceName);
- }
- mInterfaceName = null;
- mDefaultGatewayAddr = 0;
- break;
- case CONNECTING:
- setDetailedState(DetailedState.CONNECTING, reason, apnName);
- break;
- case SUSPENDED:
- setDetailedState(DetailedState.SUSPENDED, reason, apnName);
- break;
- case CONNECTED:
- mInterfaceName = intent.getStringExtra(Phone.DATA_IFACE_NAME_KEY);
- if (mInterfaceName == null) {
- Log.d(TAG, "CONNECTED event did not supply interface name.");
- }
- setupDnsProperties();
- setDetailedState(DetailedState.CONNECTED, reason, apnName);
- break;
- }
- }
- } else if (intent.getAction().equals(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED)) {
- String reason = intent.getStringExtra(Phone.FAILURE_REASON_KEY);
- String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
- if (DBG) Log.d(TAG, "Received " + intent.getAction() + " broadcast" +
- reason == null ? "" : "(" + reason + ")");
- setDetailedState(DetailedState.FAILED, reason, apnName);
- }
- TelephonyManager tm = TelephonyManager.getDefault();
- setRoamingStatus(tm.isNetworkRoaming());
- setSubtype(tm.getNetworkType(), tm.getNetworkTypeName());
- }
- }
-
- /**
- * Make sure that route(s) exist to the carrier DNS server(s).
- */
- public void addPrivateRoutes() {
- if (mInterfaceName != null) {
- for (String addrString : mDnsServers) {
- int addr = NetworkUtils.lookupHost(addrString);
- if (addr != -1) {
- NetworkUtils.addHostRoute(mInterfaceName, addr);
- }
- }
- }
- }
-
- public void removePrivateRoutes() {
- if(mInterfaceName != null) {
- NetworkUtils.removeHostRoutes(mInterfaceName);
- }
- }
-
- public void removeDefaultRoute() {
- if(mInterfaceName != null) {
- mDefaultGatewayAddr = NetworkUtils.getDefaultRoute(mInterfaceName);
- NetworkUtils.removeDefaultRoute(mInterfaceName);
- }
- }
-
- public void restoreDefaultRoute() {
- // 0 is not a valid address for a gateway
- if (mInterfaceName != null && mDefaultGatewayAddr != 0) {
- NetworkUtils.setDefaultRoute(mInterfaceName, mDefaultGatewayAddr);
- }
- }
-
- private void getPhoneService(boolean forceRefresh) {
- if ((mPhoneService == null) || forceRefresh) {
- mPhoneService = ITelephony.Stub.asInterface(ServiceManager.getService("phone"));
- }
- }
-
- /**
- * Report whether data connectivity is possible.
- */
- public boolean isAvailable() {
- getPhoneService(false);
-
- /*
- * If the phone process has crashed in the past, we'll get a
- * RemoteException and need to re-reference the service.
- */
- for (int retry = 0; retry < 2; retry++) {
- if (mPhoneService == null) break;
-
- try {
- return mPhoneService.isDataConnectivityPossible();
- } catch (RemoteException e) {
- // First-time failed, get the phone service again
- if (retry == 0) getPhoneService(true);
- }
- }
-
- return false;
- }
-
- /**
- * Return the IP addresses of the DNS servers available for the mobile data
- * network interface.
- * @return a list of DNS addresses, with no holes.
- */
- public String[] getNameServers() {
- return getNameServerList(sDnsPropNames);
- }
-
- /**
- * {@inheritDoc}
- * The mobile data network subtype indicates what generation network technology is in effect,
- * e.g., GPRS, EDGE, UMTS, etc.
- */
- public int getNetworkSubtype() {
- return TelephonyManager.getDefault().getNetworkType();
- }
-
- /**
- * Return the system properties name associated with the tcp buffer sizes
- * for this network.
- */
- public String getTcpBufferSizesPropName() {
- String networkTypeStr = "unknown";
- TelephonyManager tm = new TelephonyManager(mContext);
- switch(tm.getNetworkType()) {
- case TelephonyManager.NETWORK_TYPE_GPRS:
- networkTypeStr = "gprs";
- break;
- case TelephonyManager.NETWORK_TYPE_EDGE:
- networkTypeStr = "edge";
- break;
- case TelephonyManager.NETWORK_TYPE_UMTS:
- networkTypeStr = "umts";
- break;
- }
- return "net.tcp.buffersize." + networkTypeStr;
- }
-
- /**
- * Tear down mobile data connectivity, i.e., disable the ability to create
- * mobile data connections.
- */
- @Override
- public boolean teardown() {
- getPhoneService(false);
- /*
- * If the phone process has crashed in the past, we'll get a
- * RemoteException and need to re-reference the service.
- */
- for (int retry = 0; retry < 2; retry++) {
- if (mPhoneService == null) {
- Log.w(TAG,
- "Ignoring mobile data teardown request because could not acquire PhoneService");
- break;
- }
-
- try {
- return mPhoneService.disableDataConnectivity();
- } catch (RemoteException e) {
- if (retry == 0) getPhoneService(true);
- }
- }
-
- Log.w(TAG, "Failed to tear down mobile data connectivity");
- return false;
- }
-
- /**
- * Re-enable mobile data connectivity after a {@link #teardown()}.
- */
- public boolean reconnect() {
- getPhoneService(false);
- /*
- * If the phone process has crashed in the past, we'll get a
- * RemoteException and need to re-reference the service.
- */
- for (int retry = 0; retry < 2; retry++) {
- if (mPhoneService == null) {
- Log.w(TAG,
- "Ignoring mobile data connect request because could not acquire PhoneService");
- break;
- }
-
- try {
- return mPhoneService.enableDataConnectivity();
- } catch (RemoteException e) {
- if (retry == 0) getPhoneService(true);
- }
- }
-
- Log.w(TAG, "Failed to set up mobile data connectivity");
- return false;
- }
-
- /**
- * Turn on or off the mobile radio. No connectivity will be possible while the
- * radio is off. The operation is a no-op if the radio is already in the desired state.
- * @param turnOn {@code true} if the radio should be turned on, {@code false} if
- */
- public boolean setRadio(boolean turnOn) {
- getPhoneService(false);
- /*
- * If the phone process has crashed in the past, we'll get a
- * RemoteException and need to re-reference the service.
- */
- for (int retry = 0; retry < 2; retry++) {
- if (mPhoneService == null) {
- Log.w(TAG,
- "Ignoring mobile radio request because could not acquire PhoneService");
- break;
- }
-
- try {
- return mPhoneService.setRadio(turnOn);
- } catch (RemoteException e) {
- if (retry == 0) getPhoneService(true);
- }
- }
-
- Log.w(TAG, "Could not set radio power to " + (turnOn ? "on" : "off"));
- return false;
- }
-
- /**
- * Tells the phone sub-system that the caller wants to
- * begin using the named feature. The only supported feature at
- * this time is {@code Phone.FEATURE_ENABLE_MMS}, which allows an application
- * to specify that it wants to send and/or receive MMS data.
- * @param feature the name of the feature to be used
- * @param callingPid the process ID of the process that is issuing this request
- * @param callingUid the user ID of the process that is issuing this request
- * @return an integer value representing the outcome of the request.
- * The interpretation of this value is feature-specific.
- * specific, except that the value {@code -1}
- * always indicates failure. For {@code Phone.FEATURE_ENABLE_MMS},
- * the other possible return values are
- * <ul>
- * <li>{@code Phone.APN_ALREADY_ACTIVE}</li>
- * <li>{@code Phone.APN_REQUEST_STARTED}</li>
- * <li>{@code Phone.APN_TYPE_NOT_AVAILABLE}</li>
- * <li>{@code Phone.APN_REQUEST_FAILED}</li>
- * </ul>
- */
- public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) {
- if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
- mLastCallingPid = callingPid;
- return setEnableApn(Phone.APN_TYPE_MMS, true);
- } else {
- return -1;
- }
- }
-
- /**
- * Tells the phone sub-system that the caller is finished
- * using the named feature. The only supported feature at
- * this time is {@code Phone.FEATURE_ENABLE_MMS}, which allows an application
- * to specify that it wants to send and/or receive MMS data.
- * @param feature the name of the feature that is no longer needed
- * @param callingPid the process ID of the process that is issuing this request
- * @param callingUid the user ID of the process that is issuing this request
- * @return an integer value representing the outcome of the request.
- * The interpretation of this value is feature-specific, except that
- * the value {@code -1} always indicates failure.
- */
- public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
- if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
- return setEnableApn(Phone.APN_TYPE_MMS, false);
- } else {
- return -1;
- }
- }
-
- /**
- * Ensure that a network route exists to deliver traffic to the specified
- * host via the mobile data network.
- * @param hostAddress the IP address of the host to which the route is desired,
- * in network byte order.
- * @return {@code true} on success, {@code false} on failure
- */
- @Override
- public boolean requestRouteToHost(int hostAddress) {
- if (mInterfaceName != null && hostAddress != -1) {
- if (DBG) {
- Log.d(TAG, "Requested host route to " + Integer.toHexString(hostAddress));
- }
- return NetworkUtils.addHostRoute(mInterfaceName, hostAddress) == 0;
- } else {
- return false;
- }
- }
-
- @Override
- public String toString() {
- StringBuffer sb = new StringBuffer("Mobile data state: ");
-
- sb.append(mMobileDataState);
- return sb.toString();
- }
-
- private void setupDnsProperties() {
- mDnsServers.clear();
- // Set up per-process DNS server list on behalf of the MMS process
- int i = 1;
- if (mInterfaceName != null) {
- for (String propName : sDnsPropNames) {
- if (propName.indexOf(mInterfaceName) != -1) {
- String propVal = SystemProperties.get(propName);
- if (propVal != null && propVal.length() != 0 && !propVal.equals("0.0.0.0")) {
- mDnsServers.add(propVal);
- if (mLastCallingPid != -1) {
- SystemProperties.set("net.dns" + i + "." + mLastCallingPid, propVal);
- }
- ++i;
- }
- }
- }
- }
- if (i == 1) {
- Log.d(TAG, "DNS server addresses are not known.");
- } else if (mLastCallingPid != -1) {
- /*
- * Bump the property that tells the name resolver library
- * to reread the DNS server list from the properties.
- */
- String propVal = SystemProperties.get("net.dnschange");
- if (propVal.length() != 0) {
- try {
- int n = Integer.parseInt(propVal);
- SystemProperties.set("net.dnschange", "" + (n+1));
- } catch (NumberFormatException e) {
- }
- }
- }
- mLastCallingPid = -1;
- }
-
- /**
- * Internal method supporting the ENABLE_MMS feature.
- * @param apnType the type of APN to be enabled or disabled (e.g., mms)
- * @param enable {@code true} to enable the specified APN type,
- * {@code false} to disable it.
- * @return an integer value representing the outcome of the request.
- */
- private int setEnableApn(String apnType, boolean enable) {
- getPhoneService(false);
- /*
- * If the phone process has crashed in the past, we'll get a
- * RemoteException and need to re-reference the service.
- */
- for (int retry = 0; retry < 2; retry++) {
- if (mPhoneService == null) {
- Log.w(TAG,
- "Ignoring feature request because could not acquire PhoneService");
- break;
- }
-
- try {
- if (enable) {
- return mPhoneService.enableApnType(apnType);
- } else {
- return mPhoneService.disableApnType(apnType);
- }
- } catch (RemoteException e) {
- if (retry == 0) getPhoneService(true);
- }
- }
-
- Log.w(TAG, "Could not " + (enable ? "enable" : "disable")
- + " APN type \"" + apnType + "\"");
- return Phone.APN_REQUEST_FAILED;
- }
-}
diff --git a/core/java/android/net/NetworkConnectivityListener.java b/core/java/android/net/NetworkConnectivityListener.java
deleted file mode 100644
index 858fc77..0000000
--- a/core/java/android/net/NetworkConnectivityListener.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Iterator;
-
-/**
- * A wrapper for a broadcast receiver that provides network connectivity
- * state information, independent of network type (mobile, Wi-Fi, etc.).
- * {@hide}
- */
-public class NetworkConnectivityListener {
- private static final String TAG = "NetworkConnectivityListener";
- private static final boolean DBG = false;
-
- private Context mContext;
- private HashMap<Handler, Integer> mHandlers = new HashMap<Handler, Integer>();
- private State mState;
- private boolean mListening;
- private String mReason;
- private boolean mIsFailover;
-
- /** Network connectivity information */
- private NetworkInfo mNetworkInfo;
-
- /**
- * In case of a Disconnect, the connectivity manager may have
- * already established, or may be attempting to establish, connectivity
- * with another network. If so, {@code mOtherNetworkInfo} will be non-null.
- */
- private NetworkInfo mOtherNetworkInfo;
-
- private ConnectivityBroadcastReceiver mReceiver;
-
- private class ConnectivityBroadcastReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
-
- if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
- mListening == false) {
- Log.w(TAG, "onReceived() called with " + mState.toString() + " and " + intent);
- return;
- }
-
- boolean noConnectivity =
- intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
-
- if (noConnectivity) {
- mState = State.NOT_CONNECTED;
- } else {
- mState = State.CONNECTED;
- }
-
- mNetworkInfo = (NetworkInfo)
- intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
- mOtherNetworkInfo = (NetworkInfo)
- intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
-
- mReason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
- mIsFailover =
- intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
-
- if (DBG) {
- Log.d(TAG, "onReceive(): mNetworkInfo=" + mNetworkInfo + " mOtherNetworkInfo = "
- + (mOtherNetworkInfo == null ? "[none]" : mOtherNetworkInfo +
- " noConn=" + noConnectivity) + " mState=" + mState.toString());
- }
-
- // Notifiy any handlers.
- Iterator<Handler> it = mHandlers.keySet().iterator();
- while (it.hasNext()) {
- Handler target = it.next();
- Message message = Message.obtain(target, mHandlers.get(target));
- target.sendMessage(message);
- }
- }
- };
-
- public enum State {
- UNKNOWN,
-
- /** This state is returned if there is connectivity to any network **/
- CONNECTED,
- /**
- * This state is returned if there is no connectivity to any network. This is set
- * to true under two circumstances:
- * <ul>
- * <li>When connectivity is lost to one network, and there is no other available
- * network to attempt to switch to.</li>
- * <li>When connectivity is lost to one network, and the attempt to switch to
- * another network fails.</li>
- */
- NOT_CONNECTED
- }
-
- /**
- * Create a new NetworkConnectivityListener.
- */
- public NetworkConnectivityListener() {
- mState = State.UNKNOWN;
- mReceiver = new ConnectivityBroadcastReceiver();
- }
-
- /**
- * This method starts listening for network connectivity state changes.
- * @param context
- */
- public synchronized void startListening(Context context) {
- if (!mListening) {
- mContext = context;
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
- context.registerReceiver(mReceiver, filter);
- mListening = true;
- }
- }
-
- /**
- * This method stops this class from listening for network changes.
- */
- public synchronized void stopListening() {
- if (mListening) {
- mContext.unregisterReceiver(mReceiver);
- mContext = null;
- mNetworkInfo = null;
- mOtherNetworkInfo = null;
- mIsFailover = false;
- mReason = null;
- mListening = false;
- }
- }
-
- /**
- * This methods registers a Handler to be called back onto with the specified what code when
- * the network connectivity state changes.
- *
- * @param target The target handler.
- * @param what The what code to be used when posting a message to the handler.
- */
- public void registerHandler(Handler target, int what) {
- mHandlers.put(target, what);
- }
-
- /**
- * This methods unregisters the specified Handler.
- * @param target
- */
- public void unregisterHandler(Handler target) {
- mHandlers.remove(target);
- }
-
- public State getState() {
- return mState;
- }
-
- /**
- * Return the NetworkInfo associated with the most recent connectivity event.
- * @return {@code NetworkInfo} for the network that had the most recent connectivity event.
- */
- public NetworkInfo getNetworkInfo() {
- return mNetworkInfo;
- }
-
- /**
- * If the most recent connectivity event was a DISCONNECT, return
- * any information supplied in the broadcast about an alternate
- * network that might be available. If this returns a non-null
- * value, then another broadcast should follow shortly indicating
- * whether connection to the other network succeeded.
- *
- * @return NetworkInfo
- */
- public NetworkInfo getOtherNetworkInfo() {
- return mOtherNetworkInfo;
- }
-
- /**
- * Returns true if the most recent event was for an attempt to switch over to
- * a new network following loss of connectivity on another network.
- * @return {@code true} if this was a failover attempt, {@code false} otherwise.
- */
- public boolean isFailover() {
- return mIsFailover;
- }
-
- /**
- * An optional reason for the connectivity state change may have been supplied.
- * This returns it.
- * @return the reason for the state change, if available, or {@code null}
- * otherwise.
- */
- public String getReason() {
- return mReason;
- }
-}
diff --git a/core/java/android/net/NetworkInfo.aidl b/core/java/android/net/NetworkInfo.aidl
deleted file mode 100644
index f501873..0000000
--- a/core/java/android/net/NetworkInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2007, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-parcelable NetworkInfo;
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
deleted file mode 100644
index 8c82212..0000000
--- a/core/java/android/net/NetworkInfo.java
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import java.util.EnumMap;
-
-/**
- * Describes the status of a network interface of a given type
- * (currently either Mobile or Wifi).
- */
-public class NetworkInfo implements Parcelable {
-
- /**
- * Coarse-grained network state. This is probably what most applications should
- * use, rather than {@link android.net.NetworkInfo.DetailedState DetailedState}.
- * The mapping between the two is as follows:
- * <br/><br/>
- * <table>
- * <tr><td><b>Detailed state</b></td><td><b>Coarse-grained state</b></td></tr>
- * <tr><td><code>IDLE</code></td><td><code>DISCONNECTED</code></td></tr>
- * <tr><td><code>SCANNING</code></td><td><code>CONNECTING</code></td></tr>
- * <tr><td><code>CONNECTING</code></td><td><code>CONNECTING</code></td></tr>
- * <tr><td><code>AUTHENTICATING</code></td><td><code>CONNECTING</code></td></tr>
- * <tr><td><code>CONNECTED</code></td><td<code>CONNECTED</code></td></tr>
- * <tr><td><code>DISCONNECTING</code></td><td><code>DISCONNECTING</code></td></tr>
- * <tr><td><code>DISCONNECTED</code></td><td><code>DISCONNECTED</code></td></tr>
- * <tr><td><code>UNAVAILABLE</code></td><td><code>DISCONNECTED</code></td></tr>
- * <tr><td><code>FAILED</code></td><td><code>DISCONNECTED</code></td></tr>
- * </table>
- */
- public enum State {
- CONNECTING, CONNECTED, SUSPENDED, DISCONNECTING, DISCONNECTED, UNKNOWN
- }
-
- /**
- * The fine-grained state of a network connection. This level of detail
- * is probably of interest to few applications. Most should use
- * {@link android.net.NetworkInfo.State State} instead.
- */
- public enum DetailedState {
- /** Ready to start data connection setup. */
- IDLE,
- /** Searching for an available access point. */
- SCANNING,
- /** Currently setting up data connection. */
- CONNECTING,
- /** Network link established, performing authentication. */
- AUTHENTICATING,
- /** Awaiting response from DHCP server in order to assign IP address information. */
- OBTAINING_IPADDR,
- /** IP traffic should be available. */
- CONNECTED,
- /** IP traffic is suspended */
- SUSPENDED,
- /** Currently tearing down data connection. */
- DISCONNECTING,
- /** IP traffic not available. */
- DISCONNECTED,
- /** Attempt to connect failed. */
- FAILED
- }
-
- /**
- * This is the map described in the Javadoc comment above. The positions
- * of the elements of the array must correspond to the ordinal values
- * of <code>DetailedState</code>.
- */
- private static final EnumMap<DetailedState, State> stateMap =
- new EnumMap<DetailedState, State>(DetailedState.class);
-
- static {
- stateMap.put(DetailedState.IDLE, State.DISCONNECTED);
- stateMap.put(DetailedState.SCANNING, State.DISCONNECTED);
- stateMap.put(DetailedState.CONNECTING, State.CONNECTING);
- stateMap.put(DetailedState.AUTHENTICATING, State.CONNECTING);
- stateMap.put(DetailedState.OBTAINING_IPADDR, State.CONNECTING);
- stateMap.put(DetailedState.CONNECTED, State.CONNECTED);
- stateMap.put(DetailedState.SUSPENDED, State.SUSPENDED);
- stateMap.put(DetailedState.DISCONNECTING, State.DISCONNECTING);
- stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED);
- stateMap.put(DetailedState.FAILED, State.DISCONNECTED);
- }
-
- private int mNetworkType;
- private int mSubtype;
- private String mTypeName;
- private String mSubtypeName;
- private State mState;
- private DetailedState mDetailedState;
- private String mReason;
- private String mExtraInfo;
- private boolean mIsFailover;
- private boolean mIsRoaming;
- /**
- * Indicates whether network connectivity is possible:
- */
- private boolean mIsAvailable;
-
- /**
- * TODO This is going away as soon as API council review happens.
- * @param type network type
- */
- public NetworkInfo(int type) {}
-
- NetworkInfo(int type, int subtype, String typeName, String subtypeName) {
- if (!ConnectivityManager.isNetworkTypeValid(type)) {
- throw new IllegalArgumentException("Invalid network type: " + type);
- }
- mNetworkType = type;
- mSubtype = subtype;
- mTypeName = typeName;
- mSubtypeName = subtypeName;
- setDetailedState(DetailedState.IDLE, null, null);
- mState = State.UNKNOWN;
- mIsAvailable = true;
- mIsRoaming = false;
- }
-
- /**
- * Reports the type of network (currently mobile or Wi-Fi) to which the
- * info in this object pertains.
- * @return the network type
- */
- public int getType() {
- return mNetworkType;
- }
-
- /**
- * Return a network-type-specific integer describing the subtype
- * of the network.
- * @return the network subtype
- *
- * @hide pending API council review
- */
- public int getSubtype() {
- return mSubtype;
- }
-
- void setSubtype(int subtype, String subtypeName) {
- mSubtype = subtype;
- mSubtypeName = subtypeName;
- }
-
- /**
- * Return a human-readable name describe the type of the network,
- * for example "WIFI" or "MOBILE".
- * @return the name of the network type
- */
- public String getTypeName() {
- return mTypeName;
- }
-
- /**
- * Return a human-readable name describing the subtype of the network.
- * @return the name of the network subtype
- *
- * @hide pending API council review
- */
- public String getSubtypeName() {
- return mSubtypeName;
- }
-
- /**
- * Indicates whether network connectivity exists or is in the process
- * of being established. This is good for applications that need to
- * do anything related to the network other than read or write data.
- * For the latter, call {@link #isConnected()} instead, which guarantees
- * that the network is fully usable.
- * @return {@code true} if network connectivity exists or is in the process
- * of being established, {@code false} otherwise.
- */
- public boolean isConnectedOrConnecting() {
- return mState == State.CONNECTED || mState == State.CONNECTING;
- }
-
- /**
- * Indicates whether network connectivity exists and it is possible to establish
- * connections and pass data.
- * @return {@code true} if network connectivity exists, {@code false} otherwise.
- */
- public boolean isConnected() {
- return mState == State.CONNECTED;
- }
-
- /**
- * Indicates whether network connectivity is possible. A network is unavailable
- * when a persistent or semi-persistent condition prevents the possibility
- * of connecting to that network. Examples include
- * <ul>
- * <li>The device is out of the coverage area for any network of this type.</li>
- * <li>The device is on a network other than the home network (i.e., roaming), and
- * data roaming has been disabled.</li>
- * <li>The device's radio is turned off, e.g., because airplane mode is enabled.</li>
- * </ul>
- * @return {@code true} if the network is available, {@code false} otherwise
- */
- public boolean isAvailable() {
- return mIsAvailable;
- }
-
- /**
- * Sets if the network is available, ie, if the connectivity is possible.
- * @param isAvailable the new availability value.
- *
- * @hide
- */
- public void setIsAvailable(boolean isAvailable) {
- mIsAvailable = isAvailable;
- }
-
- /**
- * Indicates whether the current attempt to connect to the network
- * resulted from the ConnectivityManager trying to fail over to this
- * network following a disconnect from another network.
- * @return {@code true} if this is a failover attempt, {@code false}
- * otherwise.
- */
- public boolean isFailover() {
- return mIsFailover;
- }
-
- /**
- * Set the failover boolean.
- * @param isFailover {@code true} to mark the current connection attempt
- * as a failover.
- * @hide
- */
- public void setFailover(boolean isFailover) {
- mIsFailover = isFailover;
- }
-
- /**
- * Indicates whether the device is currently roaming on this network.
- * When {@code true}, it suggests that use of data on this network
- * may incur extra costs.
- * @return {@code true} if roaming is in effect, {@code false} otherwise.
- *
- * @hide pending API council
- */
- public boolean isRoaming() {
- return mIsRoaming;
- }
-
- void setRoaming(boolean isRoaming) {
- mIsRoaming = isRoaming;
- }
-
- /**
- * Reports the current coarse-grained state of the network.
- * @return the coarse-grained state
- */
- public State getState() {
- return mState;
- }
-
- /**
- * Reports the current fine-grained state of the network.
- * @return the fine-grained state
- */
- public DetailedState getDetailedState() {
- return mDetailedState;
- }
-
- /**
- * Sets the fine-grained state of the network.
- * @param detailedState the {@link DetailedState}.
- * @param reason a {@code String} indicating the reason for the state change,
- * if one was supplied. May be {@code null}.
- * @param extraInfo an optional {@code String} providing addditional network state
- * information passed up from the lower networking layers.
- */
- void setDetailedState(DetailedState detailedState, String reason, String extraInfo) {
- this.mDetailedState = detailedState;
- this.mState = stateMap.get(detailedState);
- this.mReason = reason;
- this.mExtraInfo = extraInfo;
- }
-
- /**
- * Report the reason an attempt to establish connectivity failed,
- * if one is available.
- * @return the reason for failure, or null if not available
- */
- public String getReason() {
- return mReason;
- }
-
- /**
- * Report the extra information about the network state, if any was
- * provided by the lower networking layers.,
- * if one is available.
- * @return the extra information, or null if not available
- */
- public String getExtraInfo() {
- return mExtraInfo;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder("NetworkInfo: ");
- builder.append("type: ").append(getTypeName()).append("[").append(getSubtypeName()).
- append("], state: ").append(mState).append("/").append(mDetailedState).
- append(", reason: ").append(mReason == null ? "(unspecified)" : mReason).
- append(", extra: ").append(mExtraInfo == null ? "(none)" : mExtraInfo).
- append(", roaming: ").append(mIsRoaming).
- append(", failover: ").append(mIsFailover).
- append(", isAvailable: ").append(mIsAvailable);
- return builder.toString();
- }
-
- /**
- * Implement the Parcelable interface
- * @hide
- */
- public int describeContents() {
- return 0;
- }
-
- /**
- * Implement the Parcelable interface.
- * @hide
- */
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mNetworkType);
- dest.writeInt(mSubtype);
- dest.writeString(mTypeName);
- dest.writeString(mSubtypeName);
- dest.writeString(mState.name());
- dest.writeString(mDetailedState.name());
- dest.writeInt(mIsFailover ? 1 : 0);
- dest.writeInt(mIsAvailable ? 1 : 0);
- dest.writeInt(mIsRoaming ? 1 : 0);
- dest.writeString(mReason);
- dest.writeString(mExtraInfo);
- }
-
- /**
- * Implement the Parcelable interface.
- * @hide
- */
- public static final Creator<NetworkInfo> CREATOR =
- new Creator<NetworkInfo>() {
- public NetworkInfo createFromParcel(Parcel in) {
- int netType = in.readInt();
- int subtype = in.readInt();
- String typeName = in.readString();
- String subtypeName = in.readString();
- NetworkInfo netInfo = new NetworkInfo(netType, subtype, typeName, subtypeName);
- netInfo.mState = State.valueOf(in.readString());
- netInfo.mDetailedState = DetailedState.valueOf(in.readString());
- netInfo.mIsFailover = in.readInt() != 0;
- netInfo.mIsAvailable = in.readInt() != 0;
- netInfo.mIsRoaming = in.readInt() != 0;
- netInfo.mReason = in.readString();
- netInfo.mExtraInfo = in.readString();
- return netInfo;
- }
-
- public NetworkInfo[] newArray(int size) {
- return new NetworkInfo[size];
- }
- };
-}
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
deleted file mode 100644
index 37087ac..0000000
--- a/core/java/android/net/NetworkStateTracker.java
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import java.io.FileWriter;
-import java.io.IOException;
-
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemProperties;
-import android.content.Context;
-import android.text.TextUtils;
-import android.util.Config;
-import android.util.Log;
-
-/**
- * Each subclass of this class keeps track of the state of connectivity
- * of a network interface. All state information for a network should
- * be kept in a Tracker class. This superclass manages the
- * network-type-independent aspects of network state.
- *
- * {@hide}
- */
-public abstract class NetworkStateTracker extends Handler {
-
- protected NetworkInfo mNetworkInfo;
- protected Context mContext;
- protected Handler mTarget;
- private boolean mTeardownRequested;
-
- private static boolean DBG = Config.LOGV;
- private static final String TAG = "NetworkStateTracker";
-
- public static final int EVENT_STATE_CHANGED = 1;
- public static final int EVENT_SCAN_RESULTS_AVAILABLE = 2;
- /**
- * arg1: 1 to show, 0 to hide
- * arg2: ID of the notification
- * obj: Notification (if showing)
- */
- public static final int EVENT_NOTIFICATION_CHANGED = 3;
- public static final int EVENT_CONFIGURATION_CHANGED = 4;
- public static final int EVENT_ROAMING_CHANGED = 5;
- public static final int EVENT_NETWORK_SUBTYPE_CHANGED = 6;
-
- public NetworkStateTracker(Context context,
- Handler target,
- int networkType,
- int subType,
- String typeName,
- String subtypeName) {
- super();
- mContext = context;
- mTarget = target;
- mTeardownRequested = false;
- this.mNetworkInfo = new NetworkInfo(networkType, subType, typeName, subtypeName);
- }
-
- public NetworkInfo getNetworkInfo() {
- return mNetworkInfo;
- }
-
- /**
- * Return the list of DNS servers associated with this network.
- * @return a list of the IP addresses of the DNS servers available
- * for the network.
- */
- public abstract String[] getNameServers();
-
- /**
- * Return the system properties name associated with the tcp buffer sizes
- * for this network.
- */
- public abstract String getTcpBufferSizesPropName();
-
- /**
- * Return the IP addresses of the DNS servers available for this
- * network interface.
- * @param propertyNames the names of the system properties whose values
- * give the IP addresses. Properties with no values are skipped.
- * @return an array of {@code String}s containing the IP addresses
- * of the DNS servers, in dot-notation. This may have fewer
- * non-null entries than the list of names passed in, since
- * some of the passed-in names may have empty values.
- */
- static protected String[] getNameServerList(String[] propertyNames) {
- String[] dnsAddresses = new String[propertyNames.length];
- int i, j;
-
- for (i = 0, j = 0; i < propertyNames.length; i++) {
- String value = SystemProperties.get(propertyNames[i]);
- // The GSM layer sometimes sets a bogus DNS server address of
- // 0.0.0.0
- if (!TextUtils.isEmpty(value) && !TextUtils.equals(value, "0.0.0.0")) {
- dnsAddresses[j++] = value;
- }
- }
- return dnsAddresses;
- }
-
- /**
- * Reads the network specific TCP buffer sizes from SystemProperties
- * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system
- * wide use
- */
- public void updateNetworkSettings() {
- String key = getTcpBufferSizesPropName();
- String bufferSizes = SystemProperties.get(key);
-
- if (bufferSizes.length() == 0) {
- Log.e(TAG, key + " not found in system properties. Using defaults");
-
- // Setting to default values so we won't be stuck to previous values
- key = "net.tcp.buffersize.default";
- bufferSizes = SystemProperties.get(key);
- }
-
- // Set values in kernel
- if (bufferSizes.length() != 0) {
- if (DBG) {
- Log.v(TAG, "Setting TCP values: [" + bufferSizes
- + "] which comes from [" + key + "]");
- }
- setBufferSize(bufferSizes);
- }
- }
-
- /**
- * Release the wakelock, if any, that may be held while handling a
- * disconnect operation.
- */
- public void releaseWakeLock() {
- }
-
- /**
- * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max]
- * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem
- *
- * @param bufferSizes in the format of "readMin, readInitial, readMax,
- * writeMin, writeInitial, writeMax"
- */
- private void setBufferSize(String bufferSizes) {
- try {
- String[] values = bufferSizes.split(",");
-
- if (values.length == 6) {
- final String prefix = "/sys/kernel/ipv4/tcp_";
- stringToFile(prefix + "rmem_min", values[0]);
- stringToFile(prefix + "rmem_def", values[1]);
- stringToFile(prefix + "rmem_max", values[2]);
- stringToFile(prefix + "wmem_min", values[3]);
- stringToFile(prefix + "wmem_def", values[4]);
- stringToFile(prefix + "wmem_max", values[5]);
- } else {
- Log.e(TAG, "Invalid buffersize string: " + bufferSizes);
- }
- } catch (IOException e) {
- Log.e(TAG, "Can't set tcp buffer sizes:" + e);
- }
- }
-
- /**
- * Writes string to file. Basically same as "echo -n $string > $filename"
- *
- * @param filename
- * @param string
- * @throws IOException
- */
- private void stringToFile(String filename, String string) throws IOException {
- FileWriter out = new FileWriter(filename);
- try {
- out.write(string);
- } finally {
- out.close();
- }
- }
-
- /**
- * Record the detailed state of a network, and if it is a
- * change from the previous state, send a notification to
- * any listeners.
- * @param state the new @{code DetailedState}
- */
- public void setDetailedState(NetworkInfo.DetailedState state) {
- setDetailedState(state, null, null);
- }
-
- /**
- * Record the detailed state of a network, and if it is a
- * change from the previous state, send a notification to
- * any listeners.
- * @param state the new @{code DetailedState}
- * @param reason a {@code String} indicating a reason for the state change,
- * if one was supplied. May be {@code null}.
- * @param extraInfo optional {@code String} providing extra information about the state change
- */
- public void setDetailedState(NetworkInfo.DetailedState state, String reason, String extraInfo) {
- if (state != mNetworkInfo.getDetailedState()) {
- boolean wasConnecting = (mNetworkInfo.getState() == NetworkInfo.State.CONNECTING);
- String lastReason = mNetworkInfo.getReason();
- /*
- * If a reason was supplied when the CONNECTING state was entered, and no
- * reason was supplied for entering the CONNECTED state, then retain the
- * reason that was supplied when going to CONNECTING.
- */
- if (wasConnecting && state == NetworkInfo.DetailedState.CONNECTED && reason == null
- && lastReason != null)
- reason = lastReason;
- mNetworkInfo.setDetailedState(state, reason, extraInfo);
- Message msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
- msg.sendToTarget();
- }
- }
-
- protected void setDetailedStateInternal(NetworkInfo.DetailedState state) {
- mNetworkInfo.setDetailedState(state, null, null);
- }
-
- public void setTeardownRequested(boolean isRequested) {
- mTeardownRequested = isRequested;
- }
-
- public boolean isTeardownRequested() {
- return mTeardownRequested;
- }
-
- /**
- * Send a notification that the results of a scan for network access
- * points has completed, and results are available.
- */
- protected void sendScanResultsAvailable() {
- Message msg = mTarget.obtainMessage(EVENT_SCAN_RESULTS_AVAILABLE, mNetworkInfo);
- msg.sendToTarget();
- }
-
- /**
- * Record the roaming status of the device, and if it is a change from the previous
- * status, send a notification to any listeners.
- * @param isRoaming {@code true} if the device is now roaming, {@code false}
- * if it is no longer roaming.
- */
- protected void setRoamingStatus(boolean isRoaming) {
- if (isRoaming != mNetworkInfo.isRoaming()) {
- mNetworkInfo.setRoaming(isRoaming);
- Message msg = mTarget.obtainMessage(EVENT_ROAMING_CHANGED, mNetworkInfo);
- msg.sendToTarget();
- }
- }
-
- protected void setSubtype(int subtype, String subtypeName) {
- if (mNetworkInfo.isConnected()) {
- int oldSubtype = mNetworkInfo.getSubtype();
- if (subtype != oldSubtype) {
- mNetworkInfo.setSubtype(subtype, subtypeName);
- Message msg = mTarget.obtainMessage(
- EVENT_NETWORK_SUBTYPE_CHANGED, oldSubtype, 0, mNetworkInfo);
- msg.sendToTarget();
- }
- }
- }
-
- public abstract void startMonitoring();
-
- /**
- * Disable connectivity to a network
- * @return {@code true} if a teardown occurred, {@code false} if the
- * teardown did not occur.
- */
- public abstract boolean teardown();
-
- /**
- * Reenable connectivity to a network after a {@link #teardown()}.
- */
- public abstract boolean reconnect();
-
- /**
- * Turn the wireless radio off for a network.
- * @param turnOn {@code true} to turn the radio on, {@code false}
- */
- public abstract boolean setRadio(boolean turnOn);
-
- /**
- * Returns an indication of whether this network is available for
- * connections. A value of {@code false} means that some quasi-permanent
- * condition prevents connectivity to this network.
- */
- public abstract boolean isAvailable();
-
- /**
- * Tells the underlying networking system that the caller wants to
- * begin using the named feature. The interpretation of {@code feature}
- * is completely up to each networking implementation.
- * @param feature the name of the feature to be used
- * @param callingPid the process ID of the process that is issuing this request
- * @param callingUid the user ID of the process that is issuing this request
- * @return an integer value representing the outcome of the request.
- * The interpretation of this value is specific to each networking
- * implementation+feature combination, except that the value {@code -1}
- * always indicates failure.
- */
- public abstract int startUsingNetworkFeature(String feature, int callingPid, int callingUid);
-
- /**
- * Tells the underlying networking system that the caller is finished
- * using the named feature. The interpretation of {@code feature}
- * is completely up to each networking implementation.
- * @param feature the name of the feature that is no longer needed.
- * @param callingPid the process ID of the process that is issuing this request
- * @param callingUid the user ID of the process that is issuing this request
- * @return an integer value representing the outcome of the request.
- * The interpretation of this value is specific to each networking
- * implementation+feature combination, except that the value {@code -1}
- * always indicates failure.
- */
- public abstract int stopUsingNetworkFeature(String feature, int callingPid, int callingUid);
-
- /**
- * Ensure that a network route exists to deliver traffic to the specified
- * host via this network interface.
- * @param hostAddress the IP address of the host to which the route is desired
- * @return {@code true} on success, {@code false} on failure
- */
- public boolean requestRouteToHost(int hostAddress) {
- return false;
- }
-
- /**
- * Interprets scan results. This will be called at a safe time for
- * processing, and from a safe thread.
- */
- public void interpretScanResultsAvailable() {
- }
-
-}
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
deleted file mode 100644
index 1153648..0000000
--- a/core/java/android/net/NetworkUtils.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-/**
- * Native methods for managing network interfaces.
- *
- * {@hide}
- */
-public class NetworkUtils {
- /** Bring the named network interface down. */
- public native static int disableInterface(String interfaceName);
-
- /** Add a route to the specified host via the named interface. */
- public native static int addHostRoute(String interfaceName, int hostaddr);
-
- /** Add a default route for the named interface. */
- public native static int setDefaultRoute(String interfaceName, int gwayAddr);
-
- /** Return the gateway address for the default route for the named interface. */
- public native static int getDefaultRoute(String interfaceName);
-
- /** Remove host routes that uses the named interface. */
- public native static int removeHostRoutes(String interfaceName);
-
- /** Remove the default route for the named interface. */
- public native static int removeDefaultRoute(String interfaceName);
-
- /** Reset any sockets that are connected via the named interface. */
- public native static int resetConnections(String interfaceName);
-
- /**
- * Start the DHCP client daemon, in order to have it request addresses
- * for the named interface, and then configure the interface with those
- * addresses. This call blocks until it obtains a result (either success
- * or failure) from the daemon.
- * @param interfaceName the name of the interface to configure
- * @param ipInfo if the request succeeds, this object is filled in with
- * the IP address information.
- * @return {@code true} for success, {@code false} for failure
- */
- public native static boolean runDhcp(String interfaceName, DhcpInfo ipInfo);
-
- /**
- * Shut down the DHCP client daemon.
- * @param interfaceName the name of the interface for which the daemon
- * should be stopped
- * @return {@code true} for success, {@code false} for failure
- */
- public native static boolean stopDhcp(String interfaceName);
-
- /**
- * Release the current DHCP lease.
- * @param interfaceName the name of the interface for which the lease should
- * be released
- * @return {@code true} for success, {@code false} for failure
- */
- public native static boolean releaseDhcpLease(String interfaceName);
-
- /**
- * Return the last DHCP-related error message that was recorded.
- * <p/>NOTE: This string is not localized, but currently it is only
- * used in logging.
- * @return the most recent error message, if any
- */
- public native static String getDhcpError();
-
- /**
- * When static IP configuration has been specified, configure the network
- * interface according to the values supplied.
- * @param interfaceName the name of the interface to configure
- * @param ipInfo the IP address, default gateway, and DNS server addresses
- * with which to configure the interface.
- * @return {@code true} for success, {@code false} for failure
- */
- public static boolean configureInterface(String interfaceName, DhcpInfo ipInfo) {
- return configureNative(interfaceName,
- ipInfo.ipAddress,
- ipInfo.netmask,
- ipInfo.gateway,
- ipInfo.dns1,
- ipInfo.dns2);
- }
-
- private native static boolean configureNative(
- String interfaceName, int ipAddress, int netmask, int gateway, int dns1, int dns2);
-
- /**
- * Look up a host name and return the result as an int. Works if the argument
- * is an IP address in dot notation. Obviously, this can only be used for IPv4
- * addresses.
- * @param hostname the name of the host (or the IP address)
- * @return the IP address as an {@code int} in network byte order
- */
- public static int lookupHost(String hostname) {
- InetAddress inetAddress;
- try {
- inetAddress = InetAddress.getByName(hostname);
- } catch (UnknownHostException e) {
- return -1;
- }
- byte[] addrBytes;
- int addr;
- addrBytes = inetAddress.getAddress();
- addr = ((addrBytes[3] & 0xff) << 24)
- | ((addrBytes[2] & 0xff) << 16)
- | ((addrBytes[1] & 0xff) << 8)
- | (addrBytes[0] & 0xff);
- return addr;
- }
-}
diff --git a/core/java/android/net/ParseException.java b/core/java/android/net/ParseException.java
deleted file mode 100644
index 000fa68..0000000
--- a/core/java/android/net/ParseException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-/**
- *
- *
- * When WebAddress Parser Fails, this exception is thrown
- */
-public class ParseException extends RuntimeException {
- public String response;
-
- ParseException(String response) {
- this.response = response;
- }
-}
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
deleted file mode 100644
index 9f07c0a..0000000
--- a/core/java/android/net/Proxy.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.util.Log;
-
-import junit.framework.Assert;
-
-/**
- * A convenience class for accessing the user and default proxy
- * settings.
- */
-final public class Proxy {
-
- static final public String PROXY_CHANGE_ACTION =
- "android.intent.action.PROXY_CHANGE";
-
- /**
- * Return the proxy host set by the user.
- * @param ctx A Context used to get the settings for the proxy host.
- * @return String containing the host name. If the user did not set a host
- * name it returns the default host. A null value means that no
- * host is to be used.
- */
- static final public String getHost(Context ctx) {
- ContentResolver contentResolver = ctx.getContentResolver();
- Assert.assertNotNull(contentResolver);
- String host = Settings.Secure.getString(
- contentResolver,
- Settings.Secure.HTTP_PROXY);
- if (host != null) {
- int i = host.indexOf(':');
- if (i == -1) {
- if (android.util.Config.DEBUG) {
- Assert.assertTrue(host.length() == 0);
- }
- return null;
- }
- return host.substring(0, i);
- }
- return getDefaultHost();
- }
-
- /**
- * Return the proxy port set by the user.
- * @param ctx A Context used to get the settings for the proxy port.
- * @return The port number to use or -1 if no proxy is to be used.
- */
- static final public int getPort(Context ctx) {
- ContentResolver contentResolver = ctx.getContentResolver();
- Assert.assertNotNull(contentResolver);
- String host = Settings.Secure.getString(
- contentResolver,
- Settings.Secure.HTTP_PROXY);
- if (host != null) {
- int i = host.indexOf(':');
- if (i == -1) {
- if (android.util.Config.DEBUG) {
- Assert.assertTrue(host.length() == 0);
- }
- return -1;
- }
- if (android.util.Config.DEBUG) {
- Assert.assertTrue(i < host.length());
- }
- return Integer.parseInt(host.substring(i+1));
- }
- return getDefaultPort();
- }
-
- /**
- * Return the default proxy host specified by the carrier.
- * @return String containing the host name or null if there is no proxy for
- * this carrier.
- */
- static final public String getDefaultHost() {
- String host = SystemProperties.get("net.gprs.http-proxy");
- if (host != null) {
- Uri u = Uri.parse(host);
- host = u.getHost();
- return host;
- } else {
- return null;
- }
- }
-
- /**
- * Return the default proxy port specified by the carrier.
- * @return The port number to be used with the proxy host or -1 if there is
- * no proxy for this carrier.
- */
- static final public int getDefaultPort() {
- String host = SystemProperties.get("net.gprs.http-proxy");
- if (host != null) {
- Uri u = Uri.parse(host);
- return u.getPort();
- } else {
- return -1;
- }
- }
-
-};
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
deleted file mode 100644
index f816caa..0000000
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.util.Log;
-import android.util.Config;
-import android.net.http.DomainNameChecker;
-import android.os.SystemProperties;
-
-import javax.net.SocketFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.security.NoSuchAlgorithmException;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.GeneralSecurityException;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
-
-public class SSLCertificateSocketFactory extends SSLSocketFactory {
-
- private static final boolean DBG = true;
- private static final String LOG_TAG = "SSLCertificateSocketFactory";
-
- private static X509TrustManager sDefaultTrustManager;
-
- private final int socketReadTimeoutForSslHandshake;
-
- static {
- try {
- TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
- tmf.init((KeyStore)null);
- TrustManager[] tms = tmf.getTrustManagers();
- if (tms != null) {
- for (TrustManager tm : tms) {
- if (tm instanceof X509TrustManager) {
- sDefaultTrustManager = (X509TrustManager)tm;
- break;
- }
- }
- }
- } catch (NoSuchAlgorithmException e) {
- Log.e(LOG_TAG, "Unable to get X509 Trust Manager ", e);
- } catch (KeyStoreException e) {
- Log.e(LOG_TAG, "Key Store exception while initializing TrustManagerFactory ", e);
- }
- }
-
- private static final TrustManager[] TRUST_MANAGER = new TrustManager[] {
- new X509TrustManager() {
- public X509Certificate[] getAcceptedIssuers() {
- return null;
- }
-
- public void checkClientTrusted(X509Certificate[] certs,
- String authType) { }
-
- public void checkServerTrusted(X509Certificate[] certs,
- String authType) { }
- }
- };
-
- private SSLSocketFactory factory;
-
- public SSLCertificateSocketFactory(int socketReadTimeoutForSslHandshake)
- throws NoSuchAlgorithmException, KeyManagementException {
- SSLContext context = SSLContext.getInstance("TLS");
- context.init(null, TRUST_MANAGER, new java.security.SecureRandom());
- factory = (SSLSocketFactory) context.getSocketFactory();
- this.socketReadTimeoutForSslHandshake = socketReadTimeoutForSslHandshake;
- }
-
- /**
- * Returns a default instantiation of a new socket factory which
- * only allows SSL connections with valid certificates.
- *
- * @param socketReadTimeoutForSslHandshake the socket read timeout used for performing
- * ssl handshake. The socket read timeout is set back to 0 after the handshake.
- * @return a new SocketFactory, or null on error
- */
- public static SocketFactory getDefault(int socketReadTimeoutForSslHandshake) {
- try {
- return new SSLCertificateSocketFactory(socketReadTimeoutForSslHandshake);
- } catch (NoSuchAlgorithmException e) {
- Log.e(LOG_TAG,
- "SSLCertifcateSocketFactory.getDefault" +
- " NoSuchAlgorithmException " , e);
- return null;
- } catch (KeyManagementException e) {
- Log.e(LOG_TAG,
- "SSLCertifcateSocketFactory.getDefault" +
- " KeyManagementException " , e);
- return null;
- }
- }
-
- private boolean hasValidCertificateChain(Certificate[] certs)
- throws IOException {
- if (sDefaultTrustManager == null) {
- if (Config.LOGD) {
- Log.d(LOG_TAG,"hasValidCertificateChain():" +
- " null default trust manager!");
- }
- throw new IOException("null default trust manager");
- }
-
- boolean trusted = (certs != null && (certs.length > 0));
-
- if (trusted) {
- try {
- // the authtype we pass in doesn't actually matter
- sDefaultTrustManager.checkServerTrusted((X509Certificate[]) certs, "RSA");
- } catch (GeneralSecurityException e) {
- String exceptionMessage = e != null ? e.getMessage() : "none";
- if (Config.LOGD) {
- Log.d(LOG_TAG,"hasValidCertificateChain(): sec. exception: "
- + exceptionMessage);
- }
- trusted = false;
- }
- }
-
- return trusted;
- }
-
- private void validateSocket(SSLSocket sslSock, String destHost)
- throws IOException
- {
- if (Config.LOGV) {
- Log.v(LOG_TAG,"validateSocket() to host "+destHost);
- }
-
- String relaxSslCheck = SystemProperties.get("socket.relaxsslcheck");
- String secure = SystemProperties.get("ro.secure");
-
- // only allow relaxing the ssl check on non-secure builds where the relaxation is
- // specifically requested.
- if ("0".equals(secure) && "yes".equals(relaxSslCheck)) {
- if (Config.LOGD) {
- Log.d(LOG_TAG,"sys prop socket.relaxsslcheck is set," +
- " ignoring invalid certs");
- }
- return;
- }
-
- Certificate[] certs = null;
- sslSock.setUseClientMode(true);
- sslSock.startHandshake();
- certs = sslSock.getSession().getPeerCertificates();
-
- // check that the root certificate in the chain belongs to
- // a CA we trust
- if (certs == null) {
- Log.e(LOG_TAG,
- "[SSLCertificateSocketFactory] no trusted root CA");
- throw new IOException("no trusted root CA");
- }
-
- if (Config.LOGV) {
- Log.v(LOG_TAG,"validateSocket # certs = " +certs.length);
- }
-
- if (!hasValidCertificateChain(certs)) {
- if (Config.LOGD) {
- Log.d(LOG_TAG,"validateSocket(): certificate untrusted!");
- }
- throw new IOException("Certificate untrusted");
- }
-
- X509Certificate lastChainCert = (X509Certificate) certs[0];
-
- if (!DomainNameChecker.match(lastChainCert, destHost)) {
- if (Config.LOGD) {
- Log.d(LOG_TAG,"validateSocket(): domain name check failed");
- }
- throw new IOException("Domain Name check failed");
- }
- }
-
- public Socket createSocket(Socket socket, String s, int i, boolean flag)
- throws IOException
- {
- throw new IOException("Cannot validate certification without a hostname");
- }
-
- public Socket createSocket(InetAddress inaddr, int i, InetAddress inaddr2, int j)
- throws IOException
- {
- throw new IOException("Cannot validate certification without a hostname");
- }
-
- public Socket createSocket(InetAddress inaddr, int i) throws IOException {
- throw new IOException("Cannot validate certification without a hostname");
- }
-
- public Socket createSocket(String s, int i, InetAddress inaddr, int j) throws IOException {
- SSLSocket sslSock = (SSLSocket) factory.createSocket(s, i, inaddr, j);
-
- if (socketReadTimeoutForSslHandshake >= 0) {
- sslSock.setSoTimeout(socketReadTimeoutForSslHandshake);
- }
-
- validateSocket(sslSock,s);
- sslSock.setSoTimeout(0);
-
- return sslSock;
- }
-
- public Socket createSocket(String s, int i) throws IOException {
- SSLSocket sslSock = (SSLSocket) factory.createSocket(s, i);
-
- if (socketReadTimeoutForSslHandshake >= 0) {
- sslSock.setSoTimeout(socketReadTimeoutForSslHandshake);
- }
-
- validateSocket(sslSock,s);
- sslSock.setSoTimeout(0);
-
- return sslSock;
- }
-
- public String[] getDefaultCipherSuites() {
- return factory.getSupportedCipherSuites();
- }
-
- public String[] getSupportedCipherSuites() {
- return factory.getSupportedCipherSuites();
- }
-}
-
-
diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
deleted file mode 100644
index 28134b2..0000000
--- a/core/java/android/net/SntpClient.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.os.SystemClock;
-import android.util.Config;
-import android.util.Log;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-
-/**
- * {@hide}
- *
- * Simple SNTP client class for retrieving network time.
- *
- * Sample usage:
- * <pre>SntpClient client = new SntpClient();
- * if (client.requestTime("time.foo.com")) {
- * long now = client.getNtpTime() + SystemClock.elapsedRealtime() - client.getNtpTimeReference();
- * }
- * </pre>
- */
-public class SntpClient
-{
- private static final String TAG = "SntpClient";
-
- private static final int REFERENCE_TIME_OFFSET = 16;
- private static final int ORIGINATE_TIME_OFFSET = 24;
- private static final int RECEIVE_TIME_OFFSET = 32;
- private static final int TRANSMIT_TIME_OFFSET = 40;
- private static final int NTP_PACKET_SIZE = 48;
-
- private static final int NTP_PORT = 123;
- private static final int NTP_MODE_CLIENT = 3;
- private static final int NTP_VERSION = 3;
-
- // Number of seconds between Jan 1, 1900 and Jan 1, 1970
- // 70 years plus 17 leap days
- private static final long OFFSET_1900_TO_1970 = ((365L * 70L) + 17L) * 24L * 60L * 60L;
-
- // system time computed from NTP server response
- private long mNtpTime;
-
- // value of SystemClock.elapsedRealtime() corresponding to mNtpTime
- private long mNtpTimeReference;
-
- // round trip time in milliseconds
- private long mRoundTripTime;
-
- /**
- * Sends an SNTP request to the given host and processes the response.
- *
- * @param host host name of the server.
- * @param timeout network timeout in milliseconds.
- * @return true if the transaction was successful.
- */
- public boolean requestTime(String host, int timeout) {
- try {
- DatagramSocket socket = new DatagramSocket();
- socket.setSoTimeout(timeout);
- InetAddress address = InetAddress.getByName(host);
- byte[] buffer = new byte[NTP_PACKET_SIZE];
- DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, NTP_PORT);
-
- // set mode = 3 (client) and version = 3
- // mode is in low 3 bits of first byte
- // version is in bits 3-5 of first byte
- buffer[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3);
-
- // get current time and write it to the request packet
- long requestTime = System.currentTimeMillis();
- long requestTicks = SystemClock.elapsedRealtime();
- writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET, requestTime);
-
- socket.send(request);
-
- // read the response
- DatagramPacket response = new DatagramPacket(buffer, buffer.length);
- socket.receive(response);
- long responseTicks = SystemClock.elapsedRealtime();
- long responseTime = requestTime + (responseTicks - requestTicks);
- socket.close();
-
- // extract the results
- long originateTime = readTimeStamp(buffer, ORIGINATE_TIME_OFFSET);
- long receiveTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET);
- long transmitTime = readTimeStamp(buffer, TRANSMIT_TIME_OFFSET);
- long roundTripTime = responseTicks - requestTicks - (transmitTime - receiveTime);
- long clockOffset = (receiveTime - originateTime) + (transmitTime - responseTime);
- if (Config.LOGD) Log.d(TAG, "round trip: " + roundTripTime + " ms");
- if (Config.LOGD) Log.d(TAG, "clock offset: " + clockOffset + " ms");
-
- // save our results
- mNtpTime = requestTime + clockOffset;
- mNtpTimeReference = requestTicks;
- mRoundTripTime = roundTripTime;
- } catch (Exception e) {
- if (Config.LOGD) Log.d(TAG, "request time failed: " + e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Returns the time computed from the NTP transaction.
- *
- * @return time value computed from NTP server response.
- */
- public long getNtpTime() {
- return mNtpTime;
- }
-
- /**
- * Returns the reference clock value (value of SystemClock.elapsedRealtime())
- * corresponding to the NTP time.
- *
- * @return reference clock corresponding to the NTP time.
- */
- public long getNtpTimeReference() {
- return mNtpTimeReference;
- }
-
- /**
- * Returns the round trip time of the NTP transaction
- *
- * @return round trip time in milliseconds.
- */
- public long getRoundTripTime() {
- return mRoundTripTime;
- }
-
- /**
- * Reads an unsigned 32 bit big endian number from the given offset in the buffer.
- */
- private long read32(byte[] buffer, int offset) {
- byte b0 = buffer[offset];
- byte b1 = buffer[offset+1];
- byte b2 = buffer[offset+2];
- byte b3 = buffer[offset+3];
-
- // convert signed bytes to unsigned values
- int i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0);
- int i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1);
- int i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2);
- int i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3);
-
- return ((long)i0 << 24) + ((long)i1 << 16) + ((long)i2 << 8) + (long)i3;
- }
-
- /**
- * Reads the NTP time stamp at the given offset in the buffer and returns
- * it as a system time (milliseconds since January 1, 1970).
- */
- private long readTimeStamp(byte[] buffer, int offset) {
- long seconds = read32(buffer, offset);
- long fraction = read32(buffer, offset + 4);
- return ((seconds - OFFSET_1900_TO_1970) * 1000) + ((fraction * 1000L) / 0x100000000L);
- }
-
- /**
- * Writes system time (milliseconds since January 1, 1970) as an NTP time stamp
- * at the given offset in the buffer.
- */
- private void writeTimeStamp(byte[] buffer, int offset, long time) {
- long seconds = time / 1000L;
- long milliseconds = time - seconds * 1000L;
- seconds += OFFSET_1900_TO_1970;
-
- // write seconds in big endian format
- buffer[offset++] = (byte)(seconds >> 24);
- buffer[offset++] = (byte)(seconds >> 16);
- buffer[offset++] = (byte)(seconds >> 8);
- buffer[offset++] = (byte)(seconds >> 0);
-
- long fraction = milliseconds * 0x100000000L / 1000L;
- // write fraction in big endian format
- buffer[offset++] = (byte)(fraction >> 24);
- buffer[offset++] = (byte)(fraction >> 16);
- buffer[offset++] = (byte)(fraction >> 8);
- // low order bits should be random data
- buffer[offset++] = (byte)(Math.random() * 255.0);
- }
-}
diff --git a/core/java/android/net/Uri.aidl b/core/java/android/net/Uri.aidl
deleted file mode 100755
index 6bd3be5..0000000
--- a/core/java/android/net/Uri.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2007, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-parcelable Uri;
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
deleted file mode 100644
index c23df21..0000000
--- a/core/java/android/net/Uri.java
+++ /dev/null
@@ -1,2252 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.io.ByteArrayOutputStream;
-import java.net.URLEncoder;
-import java.util.AbstractList;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.RandomAccess;
-
-/**
- * Immutable URI reference. A URI reference includes a URI and a fragment, the
- * component of the URI following a '#'. Builds and parses URI references
- * which conform to
- * <a href="http://www.faqs.org/rfcs/rfc2396.html">RFC 2396</a>.
- *
- * <p>In the interest of performance, this class performs little to no
- * validation. Behavior is undefined for invalid input. This class is very
- * forgiving--in the face of invalid input, it will return garbage
- * rather than throw an exception unless otherwise specified.
- */
-public abstract class Uri implements Parcelable, Comparable<Uri> {
-
- /*
-
- This class aims to do as little up front work as possible. To accomplish
- that, we vary the implementation dependending on what the user passes in.
- For example, we have one implementation if the user passes in a
- URI string (StringUri) and another if the user passes in the
- individual components (OpaqueUri).
-
- *Concurrency notes*: Like any truly immutable object, this class is safe
- for concurrent use. This class uses a caching pattern in some places where
- it doesn't use volatile or synchronized. This is safe to do with ints
- because getting or setting an int is atomic. It's safe to do with a String
- because the internal fields are final and the memory model guarantees other
- threads won't see a partially initialized instance. We are not guaranteed
- that some threads will immediately see changes from other threads on
- certain platforms, but we don't mind if those threads reconstruct the
- cached result. As a result, we get thread safe caching with no concurrency
- overhead, which means the most common case, access from a single thread,
- is as fast as possible.
-
- From the Java Language spec.:
-
- "17.5 Final Field Semantics
-
- ... when the object is seen by another thread, that thread will always
- see the correctly constructed version of that object's final fields.
- It will also see versions of any object or array referenced by
- those final fields that are at least as up-to-date as the final fields
- are."
-
- In that same vein, all non-transient fields within Uri
- implementations should be final and immutable so as to ensure true
- immutability for clients even when they don't use proper concurrency
- control.
-
- For reference, from RFC 2396:
-
- "4.3. Parsing a URI Reference
-
- A URI reference is typically parsed according to the four main
- components and fragment identifier in order to determine what
- components are present and whether the reference is relative or
- absolute. The individual components are then parsed for their
- subparts and, if not opaque, to verify their validity.
-
- Although the BNF defines what is allowed in each component, it is
- ambiguous in terms of differentiating between an authority component
- and a path component that begins with two slash characters. The
- greedy algorithm is used for disambiguation: the left-most matching
- rule soaks up as much of the URI reference string as it is capable of
- matching. In other words, the authority component wins."
-
- The "four main components" of a hierarchical URI consist of
- <scheme>://<authority><path>?<query>
-
- */
-
- /** Log tag. */
- private static final String LOG = Uri.class.getSimpleName();
-
- /**
- * The empty URI, equivalent to "".
- */
- public static final Uri EMPTY = new HierarchicalUri(null, Part.NULL,
- PathPart.EMPTY, Part.NULL, Part.NULL);
-
- /**
- * Prevents external subclassing.
- */
- private Uri() {}
-
- /**
- * Returns true if this URI is hierarchical like "http://google.com".
- * Absolute URIs are hierarchical if the scheme-specific part starts with
- * a '/'. Relative URIs are always hierarchical.
- */
- public abstract boolean isHierarchical();
-
- /**
- * Returns true if this URI is opaque like "mailto:nobody@google.com". The
- * scheme-specific part of an opaque URI cannot start with a '/'.
- */
- public boolean isOpaque() {
- return !isHierarchical();
- }
-
- /**
- * Returns true if this URI is relative, i.e. if it doesn't contain an
- * explicit scheme.
- *
- * @return true if this URI is relative, false if it's absolute
- */
- public abstract boolean isRelative();
-
- /**
- * Returns true if this URI is absolute, i.e. if it contains an
- * explicit scheme.
- *
- * @return true if this URI is absolute, false if it's relative
- */
- public boolean isAbsolute() {
- return !isRelative();
- }
-
- /**
- * Gets the scheme of this URI. Example: "http"
- *
- * @return the scheme or null if this is a relative URI
- */
- public abstract String getScheme();
-
- /**
- * Gets the scheme-specific part of this URI, i.e. everything between the
- * scheme separator ':' and the fragment separator '#'. If this is a
- * relative URI, this method returns the entire URI. Decodes escaped octets.
- *
- * <p>Example: "//www.google.com/search?q=android"
- *
- * @return the decoded scheme-specific-part
- */
- public abstract String getSchemeSpecificPart();
-
- /**
- * Gets the scheme-specific part of this URI, i.e. everything between the
- * scheme separator ':' and the fragment separator '#'. If this is a
- * relative URI, this method returns the entire URI. Leaves escaped octets
- * intact.
- *
- * <p>Example: "//www.google.com/search?q=android"
- *
- * @return the decoded scheme-specific-part
- */
- public abstract String getEncodedSchemeSpecificPart();
-
- /**
- * Gets the decoded authority part of this URI. For
- * server addresses, the authority is structured as follows:
- * {@code [ userinfo '@' ] host [ ':' port ]}
- *
- * <p>Examples: "google.com", "bob@google.com:80"
- *
- * @return the authority for this URI or null if not present
- */
- public abstract String getAuthority();
-
- /**
- * Gets the encoded authority part of this URI. For
- * server addresses, the authority is structured as follows:
- * {@code [ userinfo '@' ] host [ ':' port ]}
- *
- * <p>Examples: "google.com", "bob@google.com:80"
- *
- * @return the authority for this URI or null if not present
- */
- public abstract String getEncodedAuthority();
-
- /**
- * Gets the decoded user information from the authority.
- * For example, if the authority is "nobody@google.com", this method will
- * return "nobody".
- *
- * @return the user info for this URI or null if not present
- */
- public abstract String getUserInfo();
-
- /**
- * Gets the encoded user information from the authority.
- * For example, if the authority is "nobody@google.com", this method will
- * return "nobody".
- *
- * @return the user info for this URI or null if not present
- */
- public abstract String getEncodedUserInfo();
-
- /**
- * Gets the encoded host from the authority for this URI. For example,
- * if the authority is "bob@google.com", this method will return
- * "google.com".
- *
- * @return the host for this URI or null if not present
- */
- public abstract String getHost();
-
- /**
- * Gets the port from the authority for this URI. For example,
- * if the authority is "google.com:80", this method will return 80.
- *
- * @return the port for this URI or -1 if invalid or not present
- */
- public abstract int getPort();
-
- /**
- * Gets the decoded path.
- *
- * @return the decoded path, or null if this is not a hierarchical URI
- * (like "mailto:nobody@google.com") or the URI is invalid
- */
- public abstract String getPath();
-
- /**
- * Gets the encoded path.
- *
- * @return the encoded path, or null if this is not a hierarchical URI
- * (like "mailto:nobody@google.com") or the URI is invalid
- */
- public abstract String getEncodedPath();
-
- /**
- * Gets the decoded query component from this URI. The query comes after
- * the query separator ('?') and before the fragment separator ('#'). This
- * method would return "q=android" for
- * "http://www.google.com/search?q=android".
- *
- * @return the decoded query or null if there isn't one
- */
- public abstract String getQuery();
-
- /**
- * Gets the encoded query component from this URI. The query comes after
- * the query separator ('?') and before the fragment separator ('#'). This
- * method would return "q=android" for
- * "http://www.google.com/search?q=android".
- *
- * @return the encoded query or null if there isn't one
- */
- public abstract String getEncodedQuery();
-
- /**
- * Gets the decoded fragment part of this URI, everything after the '#'.
- *
- * @return the decoded fragment or null if there isn't one
- */
- public abstract String getFragment();
-
- /**
- * Gets the encoded fragment part of this URI, everything after the '#'.
- *
- * @return the encoded fragment or null if there isn't one
- */
- public abstract String getEncodedFragment();
-
- /**
- * Gets the decoded path segments.
- *
- * @return decoded path segments, each without a leading or trailing '/'
- */
- public abstract List<String> getPathSegments();
-
- /**
- * Gets the decoded last segment in the path.
- *
- * @return the decoded last segment or null if the path is empty
- */
- public abstract String getLastPathSegment();
-
- /**
- * Compares this Uri to another object for equality. Returns true if the
- * encoded string representations of this Uri and the given Uri are
- * equal. Case counts. Paths are not normalized. If one Uri specifies a
- * default port explicitly and the other leaves it implicit, they will not
- * be considered equal.
- */
- public boolean equals(Object o) {
- if (!(o instanceof Uri)) {
- return false;
- }
-
- Uri other = (Uri) o;
-
- return toString().equals(other.toString());
- }
-
- /**
- * Hashes the encoded string represention of this Uri consistently with
- * {@link #equals(Object)}.
- */
- public int hashCode() {
- return toString().hashCode();
- }
-
- /**
- * Compares the string representation of this Uri with that of
- * another.
- */
- public int compareTo(Uri other) {
- return toString().compareTo(other.toString());
- }
-
- /**
- * Returns the encoded string representation of this URI.
- * Example: "http://google.com/"
- */
- public abstract String toString();
-
- /**
- * Constructs a new builder, copying the attributes from this Uri.
- */
- public abstract Builder buildUpon();
-
- /** Index of a component which was not found. */
- private final static int NOT_FOUND = -1;
-
- /** Placeholder value for an index which hasn't been calculated yet. */
- private final static int NOT_CALCULATED = -2;
-
- /**
- * Placeholder for strings which haven't been cached. This enables us
- * to cache null. We intentionally create a new String instance so we can
- * compare its identity and there is no chance we will confuse it with
- * user data.
- */
- @SuppressWarnings("RedundantStringConstructorCall")
- private static final String NOT_CACHED = new String("NOT CACHED");
-
- /**
- * Error message presented when a user tries to treat an opaque URI as
- * hierarchical.
- */
- private static final String NOT_HIERARCHICAL
- = "This isn't a hierarchical URI.";
-
- /** Default encoding. */
- private static final String DEFAULT_ENCODING = "UTF-8";
-
- /**
- * Creates a Uri which parses the given encoded URI string.
- *
- * @param uriString an RFC 3296-compliant, encoded URI
- * @throws NullPointerException if uriString is null
- * @return Uri for this given uri string
- */
- public static Uri parse(String uriString) {
- return new StringUri(uriString);
- }
-
- /**
- * Creates a Uri from a file. The URI has the form
- * "file://<absolute path>". Encodes path characters with the exception of
- * '/'.
- *
- * <p>Example: "file:///tmp/android.txt"
- *
- * @throws NullPointerException if file is null
- * @return a Uri for the given file
- */
- public static Uri fromFile(File file) {
- if (file == null) {
- throw new NullPointerException("file");
- }
-
- PathPart path = PathPart.fromDecoded(file.getAbsolutePath());
- return new HierarchicalUri(
- "file", Part.EMPTY, path, Part.NULL, Part.NULL);
- }
-
- /**
- * An implementation which wraps a String URI. This URI can be opaque or
- * hierarchical, but we extend AbstractHierarchicalUri in case we need
- * the hierarchical functionality.
- */
- private static class StringUri extends AbstractHierarchicalUri {
-
- /** Used in parcelling. */
- static final int TYPE_ID = 1;
-
- /** URI string representation. */
- private final String uriString;
-
- private StringUri(String uriString) {
- if (uriString == null) {
- throw new NullPointerException("uriString");
- }
-
- this.uriString = uriString;
- }
-
- static Uri readFrom(Parcel parcel) {
- return new StringUri(parcel.readString());
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeInt(TYPE_ID);
- parcel.writeString(uriString);
- }
-
- /** Cached scheme separator index. */
- private volatile int cachedSsi = NOT_CALCULATED;
-
- /** Finds the first ':'. Returns -1 if none found. */
- private int findSchemeSeparator() {
- return cachedSsi == NOT_CALCULATED
- ? cachedSsi = uriString.indexOf(':')
- : cachedSsi;
- }
-
- /** Cached fragment separator index. */
- private volatile int cachedFsi = NOT_CALCULATED;
-
- /** Finds the first '#'. Returns -1 if none found. */
- private int findFragmentSeparator() {
- return cachedFsi == NOT_CALCULATED
- ? cachedFsi = uriString.indexOf('#', findSchemeSeparator())
- : cachedFsi;
- }
-
- public boolean isHierarchical() {
- int ssi = findSchemeSeparator();
-
- if (ssi == NOT_FOUND) {
- // All relative URIs are hierarchical.
- return true;
- }
-
- if (uriString.length() == ssi + 1) {
- // No ssp.
- return false;
- }
-
- // If the ssp starts with a '/', this is hierarchical.
- return uriString.charAt(ssi + 1) == '/';
- }
-
- public boolean isRelative() {
- // Note: We return true if the index is 0
- return findSchemeSeparator() == NOT_FOUND;
- }
-
- private volatile String scheme = NOT_CACHED;
-
- public String getScheme() {
- @SuppressWarnings("StringEquality")
- boolean cached = (scheme != NOT_CACHED);
- return cached ? scheme : (scheme = parseScheme());
- }
-
- private String parseScheme() {
- int ssi = findSchemeSeparator();
- return ssi == NOT_FOUND ? null : uriString.substring(0, ssi);
- }
-
- private Part ssp;
-
- private Part getSsp() {
- return ssp == null ? ssp = Part.fromEncoded(parseSsp()) : ssp;
- }
-
- public String getEncodedSchemeSpecificPart() {
- return getSsp().getEncoded();
- }
-
- public String getSchemeSpecificPart() {
- return getSsp().getDecoded();
- }
-
- private String parseSsp() {
- int ssi = findSchemeSeparator();
- int fsi = findFragmentSeparator();
-
- // Return everything between ssi and fsi.
- return fsi == NOT_FOUND
- ? uriString.substring(ssi + 1)
- : uriString.substring(ssi + 1, fsi);
- }
-
- private Part authority;
-
- private Part getAuthorityPart() {
- if (authority == null) {
- String encodedAuthority
- = parseAuthority(this.uriString, findSchemeSeparator());
- return authority = Part.fromEncoded(encodedAuthority);
- }
-
- return authority;
- }
-
- public String getEncodedAuthority() {
- return getAuthorityPart().getEncoded();
- }
-
- public String getAuthority() {
- return getAuthorityPart().getDecoded();
- }
-
- private PathPart path;
-
- private PathPart getPathPart() {
- return path == null
- ? path = PathPart.fromEncoded(parsePath())
- : path;
- }
-
- public String getPath() {
- return getPathPart().getDecoded();
- }
-
- public String getEncodedPath() {
- return getPathPart().getEncoded();
- }
-
- public List<String> getPathSegments() {
- return getPathPart().getPathSegments();
- }
-
- private String parsePath() {
- String uriString = this.uriString;
- int ssi = findSchemeSeparator();
-
- // If the URI is absolute.
- if (ssi > -1) {
- // Is there anything after the ':'?
- boolean schemeOnly = ssi + 1 == uriString.length();
- if (schemeOnly) {
- // Opaque URI.
- return null;
- }
-
- // A '/' after the ':' means this is hierarchical.
- if (uriString.charAt(ssi + 1) != '/') {
- // Opaque URI.
- return null;
- }
- } else {
- // All relative URIs are hierarchical.
- }
-
- return parsePath(uriString, ssi);
- }
-
- private Part query;
-
- private Part getQueryPart() {
- return query == null
- ? query = Part.fromEncoded(parseQuery()) : query;
- }
-
- public String getEncodedQuery() {
- return getQueryPart().getEncoded();
- }
-
- private String parseQuery() {
- // It doesn't make sense to cache this index. We only ever
- // calculate it once.
- int qsi = uriString.indexOf('?', findSchemeSeparator());
- if (qsi == NOT_FOUND) {
- return null;
- }
-
- int fsi = findFragmentSeparator();
-
- if (fsi == NOT_FOUND) {
- return uriString.substring(qsi + 1);
- }
-
- if (fsi < qsi) {
- // Invalid.
- return null;
- }
-
- return uriString.substring(qsi + 1, fsi);
- }
-
- public String getQuery() {
- return getQueryPart().getDecoded();
- }
-
- private Part fragment;
-
- private Part getFragmentPart() {
- return fragment == null
- ? fragment = Part.fromEncoded(parseFragment()) : fragment;
- }
-
- public String getEncodedFragment() {
- return getFragmentPart().getEncoded();
- }
-
- private String parseFragment() {
- int fsi = findFragmentSeparator();
- return fsi == NOT_FOUND ? null : uriString.substring(fsi + 1);
- }
-
- public String getFragment() {
- return getFragmentPart().getDecoded();
- }
-
- public String toString() {
- return uriString;
- }
-
- /**
- * Parses an authority out of the given URI string.
- *
- * @param uriString URI string
- * @param ssi scheme separator index, -1 for a relative URI
- *
- * @return the authority or null if none is found
- */
- static String parseAuthority(String uriString, int ssi) {
- int length = uriString.length();
-
- // If "//" follows the scheme separator, we have an authority.
- if (length > ssi + 2
- && uriString.charAt(ssi + 1) == '/'
- && uriString.charAt(ssi + 2) == '/') {
- // We have an authority.
-
- // Look for the start of the path, query, or fragment, or the
- // end of the string.
- int end = ssi + 3;
- LOOP: while (end < length) {
- switch (uriString.charAt(end)) {
- case '/': // Start of path
- case '?': // Start of query
- case '#': // Start of fragment
- break LOOP;
- }
- end++;
- }
-
- return uriString.substring(ssi + 3, end);
- } else {
- return null;
- }
-
- }
-
- /**
- * Parses a path out of this given URI string.
- *
- * @param uriString URI string
- * @param ssi scheme separator index, -1 for a relative URI
- *
- * @return the path
- */
- static String parsePath(String uriString, int ssi) {
- int length = uriString.length();
-
- // Find start of path.
- int pathStart;
- if (length > ssi + 2
- && uriString.charAt(ssi + 1) == '/'
- && uriString.charAt(ssi + 2) == '/') {
- // Skip over authority to path.
- pathStart = ssi + 3;
- LOOP: while (pathStart < length) {
- switch (uriString.charAt(pathStart)) {
- case '?': // Start of query
- case '#': // Start of fragment
- return ""; // Empty path.
- case '/': // Start of path!
- break LOOP;
- }
- pathStart++;
- }
- } else {
- // Path starts immediately after scheme separator.
- pathStart = ssi + 1;
- }
-
- // Find end of path.
- int pathEnd = pathStart;
- LOOP: while (pathEnd < length) {
- switch (uriString.charAt(pathEnd)) {
- case '?': // Start of query
- case '#': // Start of fragment
- break LOOP;
- }
- pathEnd++;
- }
-
- return uriString.substring(pathStart, pathEnd);
- }
-
- public Builder buildUpon() {
- if (isHierarchical()) {
- return new Builder()
- .scheme(getScheme())
- .authority(getAuthorityPart())
- .path(getPathPart())
- .query(getQueryPart())
- .fragment(getFragmentPart());
- } else {
- return new Builder()
- .scheme(getScheme())
- .opaquePart(getSsp())
- .fragment(getFragmentPart());
- }
- }
- }
-
- /**
- * Creates an opaque Uri from the given components. Encodes the ssp
- * which means this method cannot be used to create hierarchical URIs.
- *
- * @param scheme of the URI
- * @param ssp scheme-specific-part, everything between the
- * scheme separator (':') and the fragment separator ('#'), which will
- * get encoded
- * @param fragment fragment, everything after the '#', null if undefined,
- * will get encoded
- *
- * @throws NullPointerException if scheme or ssp is null
- * @return Uri composed of the given scheme, ssp, and fragment
- *
- * @see Builder if you don't want the ssp and fragment to be encoded
- */
- public static Uri fromParts(String scheme, String ssp,
- String fragment) {
- if (scheme == null) {
- throw new NullPointerException("scheme");
- }
- if (ssp == null) {
- throw new NullPointerException("ssp");
- }
-
- return new OpaqueUri(scheme, Part.fromDecoded(ssp),
- Part.fromDecoded(fragment));
- }
-
- /**
- * Opaque URI.
- */
- private static class OpaqueUri extends Uri {
-
- /** Used in parcelling. */
- static final int TYPE_ID = 2;
-
- private final String scheme;
- private final Part ssp;
- private final Part fragment;
-
- private OpaqueUri(String scheme, Part ssp, Part fragment) {
- this.scheme = scheme;
- this.ssp = ssp;
- this.fragment = fragment == null ? Part.NULL : fragment;
- }
-
- static Uri readFrom(Parcel parcel) {
- return new OpaqueUri(
- parcel.readString(),
- Part.readFrom(parcel),
- Part.readFrom(parcel)
- );
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeInt(TYPE_ID);
- parcel.writeString(scheme);
- ssp.writeTo(parcel);
- fragment.writeTo(parcel);
- }
-
- public boolean isHierarchical() {
- return false;
- }
-
- public boolean isRelative() {
- return scheme == null;
- }
-
- public String getScheme() {
- return this.scheme;
- }
-
- public String getEncodedSchemeSpecificPart() {
- return ssp.getEncoded();
- }
-
- public String getSchemeSpecificPart() {
- return ssp.getDecoded();
- }
-
- public String getAuthority() {
- return null;
- }
-
- public String getEncodedAuthority() {
- return null;
- }
-
- public String getPath() {
- return null;
- }
-
- public String getEncodedPath() {
- return null;
- }
-
- public String getQuery() {
- return null;
- }
-
- public String getEncodedQuery() {
- return null;
- }
-
- public String getFragment() {
- return fragment.getDecoded();
- }
-
- public String getEncodedFragment() {
- return fragment.getEncoded();
- }
-
- public List<String> getPathSegments() {
- return Collections.emptyList();
- }
-
- public String getLastPathSegment() {
- return null;
- }
-
- public String getUserInfo() {
- return null;
- }
-
- public String getEncodedUserInfo() {
- return null;
- }
-
- public String getHost() {
- return null;
- }
-
- public int getPort() {
- return -1;
- }
-
- private volatile String cachedString = NOT_CACHED;
-
- public String toString() {
- @SuppressWarnings("StringEquality")
- boolean cached = cachedString != NOT_CACHED;
- if (cached) {
- return cachedString;
- }
-
- StringBuilder sb = new StringBuilder();
-
- sb.append(scheme).append(':');
- sb.append(getEncodedSchemeSpecificPart());
-
- if (!fragment.isEmpty()) {
- sb.append('#').append(fragment.getEncoded());
- }
-
- return cachedString = sb.toString();
- }
-
- public Builder buildUpon() {
- return new Builder()
- .scheme(this.scheme)
- .opaquePart(this.ssp)
- .fragment(this.fragment);
- }
- }
-
- /**
- * Wrapper for path segment array.
- */
- static class PathSegments extends AbstractList<String>
- implements RandomAccess {
-
- static final PathSegments EMPTY = new PathSegments(null, 0);
-
- final String[] segments;
- final int size;
-
- PathSegments(String[] segments, int size) {
- this.segments = segments;
- this.size = size;
- }
-
- public String get(int index) {
- if (index >= size) {
- throw new IndexOutOfBoundsException();
- }
-
- return segments[index];
- }
-
- public int size() {
- return this.size;
- }
- }
-
- /**
- * Builds PathSegments.
- */
- static class PathSegmentsBuilder {
-
- String[] segments;
- int size = 0;
-
- void add(String segment) {
- if (segments == null) {
- segments = new String[4];
- } else if (size + 1 == segments.length) {
- String[] expanded = new String[segments.length * 2];
- System.arraycopy(segments, 0, expanded, 0, segments.length);
- segments = expanded;
- }
-
- segments[size++] = segment;
- }
-
- PathSegments build() {
- if (segments == null) {
- return PathSegments.EMPTY;
- }
-
- try {
- return new PathSegments(segments, size);
- } finally {
- // Makes sure this doesn't get reused.
- segments = null;
- }
- }
- }
-
- /**
- * Support for hierarchical URIs.
- */
- private abstract static class AbstractHierarchicalUri extends Uri {
-
- public String getLastPathSegment() {
- // TODO: If we haven't parsed all of the segments already, just
- // grab the last one directly so we only allocate one string.
-
- List<String> segments = getPathSegments();
- int size = segments.size();
- if (size == 0) {
- return null;
- }
- return segments.get(size - 1);
- }
-
- private Part userInfo;
-
- private Part getUserInfoPart() {
- return userInfo == null
- ? userInfo = Part.fromEncoded(parseUserInfo()) : userInfo;
- }
-
- public final String getEncodedUserInfo() {
- return getUserInfoPart().getEncoded();
- }
-
- private String parseUserInfo() {
- String authority = getEncodedAuthority();
- if (authority == null) {
- return null;
- }
-
- int end = authority.indexOf('@');
- return end == NOT_FOUND ? null : authority.substring(0, end);
- }
-
- public String getUserInfo() {
- return getUserInfoPart().getDecoded();
- }
-
- private volatile String host = NOT_CACHED;
-
- public String getHost() {
- @SuppressWarnings("StringEquality")
- boolean cached = (host != NOT_CACHED);
- return cached ? host
- : (host = parseHost());
- }
-
- private String parseHost() {
- String authority = getAuthority();
- if (authority == null) {
- return null;
- }
-
- // Parse out user info and then port.
- int userInfoSeparator = authority.indexOf('@');
- int portSeparator = authority.indexOf(':', userInfoSeparator);
-
- return portSeparator == NOT_FOUND
- ? authority.substring(userInfoSeparator + 1)
- : authority.substring(userInfoSeparator + 1, portSeparator);
- }
-
- private volatile int port = NOT_CALCULATED;
-
- public int getPort() {
- return port == NOT_CALCULATED
- ? port = parsePort()
- : port;
- }
-
- private int parsePort() {
- String authority = getAuthority();
- if (authority == null) {
- return -1;
- }
-
- // Make sure we look for the port separtor *after* the user info
- // separator. We have URLs with a ':' in the user info.
- int userInfoSeparator = authority.indexOf('@');
- int portSeparator = authority.indexOf(':', userInfoSeparator);
-
- if (portSeparator == NOT_FOUND) {
- return -1;
- }
-
- String portString = authority.substring(portSeparator + 1);
- try {
- return Integer.parseInt(portString);
- } catch (NumberFormatException e) {
- Log.w(LOG, "Error parsing port string.", e);
- return -1;
- }
- }
- }
-
- /**
- * Hierarchical Uri.
- */
- private static class HierarchicalUri extends AbstractHierarchicalUri {
-
- /** Used in parcelling. */
- static final int TYPE_ID = 3;
-
- private final String scheme;
- private final Part authority;
- private final PathPart path;
- private final Part query;
- private final Part fragment;
-
- private HierarchicalUri(String scheme, Part authority, PathPart path,
- Part query, Part fragment) {
- this.scheme = scheme;
- this.authority = authority;
- this.path = path;
- this.query = query;
- this.fragment = fragment;
- }
-
- static Uri readFrom(Parcel parcel) {
- return new HierarchicalUri(
- parcel.readString(),
- Part.readFrom(parcel),
- PathPart.readFrom(parcel),
- Part.readFrom(parcel),
- Part.readFrom(parcel)
- );
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeInt(TYPE_ID);
- parcel.writeString(scheme);
- authority.writeTo(parcel);
- path.writeTo(parcel);
- query.writeTo(parcel);
- fragment.writeTo(parcel);
- }
-
- public boolean isHierarchical() {
- return true;
- }
-
- public boolean isRelative() {
- return scheme == null;
- }
-
- public String getScheme() {
- return scheme;
- }
-
- private Part ssp;
-
- private Part getSsp() {
- return ssp == null
- ? ssp = Part.fromEncoded(makeSchemeSpecificPart()) : ssp;
- }
-
- public String getEncodedSchemeSpecificPart() {
- return getSsp().getEncoded();
- }
-
- public String getSchemeSpecificPart() {
- return getSsp().getDecoded();
- }
-
- /**
- * Creates the encoded scheme-specific part from its sub parts.
- */
- private String makeSchemeSpecificPart() {
- StringBuilder builder = new StringBuilder();
- appendSspTo(builder);
- return builder.toString();
- }
-
- private void appendSspTo(StringBuilder builder) {
- if (authority != null) {
- String encodedAuthority = authority.getEncoded();
- if (encodedAuthority != null) {
- // Even if the authority is "", we still want to append "//".
- builder.append("//").append(encodedAuthority);
- }
- }
-
- // path is never null.
- String encodedPath = path.getEncoded();
- if (encodedPath != null) {
- builder.append(encodedPath);
- }
-
- if (query != null && !query.isEmpty()) {
- builder.append('?').append(query.getEncoded());
- }
- }
-
- public String getAuthority() {
- return this.authority.getDecoded();
- }
-
- public String getEncodedAuthority() {
- return this.authority.getEncoded();
- }
-
- public String getEncodedPath() {
- return this.path.getEncoded();
- }
-
- public String getPath() {
- return this.path.getDecoded();
- }
-
- public String getQuery() {
- return this.query.getDecoded();
- }
-
- public String getEncodedQuery() {
- return this.query.getEncoded();
- }
-
- public String getFragment() {
- return this.fragment.getDecoded();
- }
-
- public String getEncodedFragment() {
- return this.fragment.getEncoded();
- }
-
- public List<String> getPathSegments() {
- return this.path.getPathSegments();
- }
-
- private volatile String uriString = NOT_CACHED;
-
- @Override
- public String toString() {
- @SuppressWarnings("StringEquality")
- boolean cached = (uriString != NOT_CACHED);
- return cached ? uriString
- : (uriString = makeUriString());
- }
-
- private String makeUriString() {
- StringBuilder builder = new StringBuilder();
-
- if (scheme != null) {
- builder.append(scheme).append(':');
- }
-
- appendSspTo(builder);
-
- if (fragment != null && !fragment.isEmpty()) {
- builder.append('#').append(fragment.getEncoded());
- }
-
- return builder.toString();
- }
-
- public Builder buildUpon() {
- return new Builder()
- .scheme(scheme)
- .authority(authority)
- .path(path)
- .query(query)
- .fragment(fragment);
- }
- }
-
- /**
- * Helper class for building or manipulating URI references. Not safe for
- * concurrent use.
- *
- * <p>An absolute hierarchical URI reference follows the pattern:
- * {@code &lt;scheme&gt;://&lt;authority&gt;&lt;absolute path&gt;?&lt;query&gt;#&lt;fragment&gt;}
- *
- * <p>Relative URI references (which are always hierarchical) follow one
- * of two patterns: {@code &lt;relative or absolute path&gt;?&lt;query&gt;#&lt;fragment&gt;}
- * or {@code //&lt;authority&gt;&lt;absolute path&gt;?&lt;query&gt;#&lt;fragment&gt;}
- *
- * <p>An opaque URI follows this pattern:
- * {@code &lt;scheme&gt;:&lt;opaque part&gt;#&lt;fragment&gt;}
- */
- public static final class Builder {
-
- private String scheme;
- private Part opaquePart;
- private Part authority;
- private PathPart path;
- private Part query;
- private Part fragment;
-
- /**
- * Constructs a new Builder.
- */
- public Builder() {}
-
- /**
- * Sets the scheme.
- *
- * @param scheme name or {@code null} if this is a relative Uri
- */
- public Builder scheme(String scheme) {
- this.scheme = scheme;
- return this;
- }
-
- Builder opaquePart(Part opaquePart) {
- this.opaquePart = opaquePart;
- return this;
- }
-
- /**
- * Encodes and sets the given opaque scheme-specific-part.
- *
- * @param opaquePart decoded opaque part
- */
- public Builder opaquePart(String opaquePart) {
- return opaquePart(Part.fromDecoded(opaquePart));
- }
-
- /**
- * Sets the previously encoded opaque scheme-specific-part.
- *
- * @param opaquePart encoded opaque part
- */
- public Builder encodedOpaquePart(String opaquePart) {
- return opaquePart(Part.fromEncoded(opaquePart));
- }
-
- Builder authority(Part authority) {
- // This URI will be hierarchical.
- this.opaquePart = null;
-
- this.authority = authority;
- return this;
- }
-
- /**
- * Encodes and sets the authority.
- */
- public Builder authority(String authority) {
- return authority(Part.fromDecoded(authority));
- }
-
- /**
- * Sets the previously encoded authority.
- */
- public Builder encodedAuthority(String authority) {
- return authority(Part.fromEncoded(authority));
- }
-
- Builder path(PathPart path) {
- // This URI will be hierarchical.
- this.opaquePart = null;
-
- this.path = path;
- return this;
- }
-
- /**
- * Sets the path. Leaves '/' characters intact but encodes others as
- * necessary.
- *
- * <p>If the path is not null and doesn't start with a '/', and if
- * you specify a scheme and/or authority, the builder will prepend the
- * given path with a '/'.
- */
- public Builder path(String path) {
- return path(PathPart.fromDecoded(path));
- }
-
- /**
- * Sets the previously encoded path.
- *
- * <p>If the path is not null and doesn't start with a '/', and if
- * you specify a scheme and/or authority, the builder will prepend the
- * given path with a '/'.
- */
- public Builder encodedPath(String path) {
- return path(PathPart.fromEncoded(path));
- }
-
- /**
- * Encodes the given segment and appends it to the path.
- */
- public Builder appendPath(String newSegment) {
- return path(PathPart.appendDecodedSegment(path, newSegment));
- }
-
- /**
- * Appends the given segment to the path.
- */
- public Builder appendEncodedPath(String newSegment) {
- return path(PathPart.appendEncodedSegment(path, newSegment));
- }
-
- Builder query(Part query) {
- // This URI will be hierarchical.
- this.opaquePart = null;
-
- this.query = query;
- return this;
- }
-
- /**
- * Encodes and sets the query.
- */
- public Builder query(String query) {
- return query(Part.fromDecoded(query));
- }
-
- /**
- * Sets the previously encoded query.
- */
- public Builder encodedQuery(String query) {
- return query(Part.fromEncoded(query));
- }
-
- Builder fragment(Part fragment) {
- this.fragment = fragment;
- return this;
- }
-
- /**
- * Encodes and sets the fragment.
- */
- public Builder fragment(String fragment) {
- return fragment(Part.fromDecoded(fragment));
- }
-
- /**
- * Sets the previously encoded fragment.
- */
- public Builder encodedFragment(String fragment) {
- return fragment(Part.fromEncoded(fragment));
- }
-
- /**
- * Encodes the key and value and then appends the parameter to the
- * query string.
- *
- * @param key which will be encoded
- * @param value which will be encoded
- */
- public Builder appendQueryParameter(String key, String value) {
- // This URI will be hierarchical.
- this.opaquePart = null;
-
- String encodedParameter = encode(key, null) + "="
- + encode(value, null);
-
- if (query == null) {
- query = Part.fromEncoded(encodedParameter);
- return this;
- }
-
- String oldQuery = query.getEncoded();
- if (oldQuery == null || oldQuery.length() == 0) {
- query = Part.fromEncoded(encodedParameter);
- } else {
- query = Part.fromEncoded(oldQuery + "&" + encodedParameter);
- }
-
- return this;
- }
-
- /**
- * Constructs a Uri with the current attributes.
- *
- * @throws UnsupportedOperationException if the URI is opaque and the
- * scheme is null
- */
- public Uri build() {
- if (opaquePart != null) {
- if (this.scheme == null) {
- throw new UnsupportedOperationException(
- "An opaque URI must have a scheme.");
- }
-
- return new OpaqueUri(scheme, opaquePart, fragment);
- } else {
- // Hierarchical URIs should not return null for getPath().
- PathPart path = this.path;
- if (path == null || path == PathPart.NULL) {
- path = PathPart.EMPTY;
- } else {
- // If we have a scheme and/or authority, the path must
- // be absolute. Prepend it with a '/' if necessary.
- if (hasSchemeOrAuthority()) {
- path = PathPart.makeAbsolute(path);
- }
- }
-
- return new HierarchicalUri(
- scheme, authority, path, query, fragment);
- }
- }
-
- private boolean hasSchemeOrAuthority() {
- return scheme != null
- || (authority != null && authority != Part.NULL);
-
- }
-
- @Override
- public String toString() {
- return build().toString();
- }
- }
-
- /**
- * Searches the query string for parameter values with the given key.
- *
- * @param key which will be encoded
- *
- * @throws UnsupportedOperationException if this isn't a hierarchical URI
- * @throws NullPointerException if key is null
- *
- * @return a list of decoded values
- */
- public List<String> getQueryParameters(String key) {
- if (isOpaque()) {
- throw new UnsupportedOperationException(NOT_HIERARCHICAL);
- }
-
- String query = getQuery();
- if (query == null) {
- return Collections.emptyList();
- }
-
- String encodedKey;
- try {
- encodedKey = URLEncoder.encode(key, DEFAULT_ENCODING);
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e);
- }
-
- // Prepend query with "&" making the first parameter the same as the
- // rest.
- query = "&" + query;
-
- // Parameter prefix.
- String prefix = "&" + encodedKey + "=";
-
- ArrayList<String> values = new ArrayList<String>();
-
- int start = 0;
- int length = query.length();
- while (start < length) {
- start = query.indexOf(prefix, start);
-
- if (start == -1) {
- // No more values.
- break;
- }
-
- // Move start to start of value.
- start += prefix.length();
-
- // Find end of value.
- int end = query.indexOf('&', start);
- if (end == -1) {
- end = query.length();
- }
-
- String value = query.substring(start, end);
- values.add(decode(value));
-
- start = end;
- }
-
- return Collections.unmodifiableList(values);
- }
-
- /**
- * Searches the query string for the first value with the given key.
- *
- * @param key which will be encoded
- * @throws UnsupportedOperationException if this isn't a hierarchical URI
- * @throws NullPointerException if key is null
- *
- * @return the decoded value or null if no parameter is found
- */
- public String getQueryParameter(String key) {
- if (isOpaque()) {
- throw new UnsupportedOperationException(NOT_HIERARCHICAL);
- }
-
- String query = getQuery();
-
- if (query == null) {
- return null;
- }
-
- String encodedKey;
- try {
- encodedKey = URLEncoder.encode(key, DEFAULT_ENCODING);
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e);
- }
-
- String prefix = encodedKey + "=";
-
- if (query.length() < prefix.length()) {
- return null;
- }
-
- int start;
- if (query.startsWith(prefix)) {
- // It's the first parameter.
- start = prefix.length();
- } else {
- // It must be later in the query string.
- prefix = "&" + prefix;
- start = query.indexOf(prefix);
-
- if (start == -1) {
- // Not found.
- return null;
- }
-
- start += prefix.length();
- }
-
- // Find end of value.
- int end = query.indexOf('&', start);
- if (end == -1) {
- end = query.length();
- }
-
- String value = query.substring(start, end);
- return decode(value);
- }
-
- /** Identifies a null parcelled Uri. */
- private static final int NULL_TYPE_ID = 0;
-
- /**
- * Reads Uris from Parcels.
- */
- public static final Parcelable.Creator<Uri> CREATOR
- = new Parcelable.Creator<Uri>() {
- public Uri createFromParcel(Parcel in) {
- int type = in.readInt();
- switch (type) {
- case NULL_TYPE_ID: return null;
- case StringUri.TYPE_ID: return StringUri.readFrom(in);
- case OpaqueUri.TYPE_ID: return OpaqueUri.readFrom(in);
- case HierarchicalUri.TYPE_ID:
- return HierarchicalUri.readFrom(in);
- }
-
- throw new AssertionError("Unknown URI type: " + type);
- }
-
- public Uri[] newArray(int size) {
- return new Uri[size];
- }
- };
-
- /**
- * Writes a Uri to a Parcel.
- *
- * @param out parcel to write to
- * @param uri to write, can be null
- */
- public static void writeToParcel(Parcel out, Uri uri) {
- if (uri == null) {
- out.writeInt(NULL_TYPE_ID);
- } else {
- uri.writeToParcel(out, 0);
- }
- }
-
- private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
-
- /**
- * Encodes characters in the given string as '%'-escaped octets
- * using the UTF-8 scheme. Leaves letters ("A-Z", "a-z"), numbers
- * ("0-9"), and unreserved characters ("_-!.~'()*") intact. Encodes
- * all other characters.
- *
- * @param s string to encode
- * @return an encoded version of s suitable for use as a URI component,
- * or null if s is null
- */
- public static String encode(String s) {
- return encode(s, null);
- }
-
- /**
- * Encodes characters in the given string as '%'-escaped octets
- * using the UTF-8 scheme. Leaves letters ("A-Z", "a-z"), numbers
- * ("0-9"), and unreserved characters ("_-!.~'()*") intact. Encodes
- * all other characters with the exception of those specified in the
- * allow argument.
- *
- * @param s string to encode
- * @param allow set of additional characters to allow in the encoded form,
- * null if no characters should be skipped
- * @return an encoded version of s suitable for use as a URI component,
- * or null if s is null
- */
- public static String encode(String s, String allow) {
- if (s == null) {
- return null;
- }
-
- // Lazily-initialized buffers.
- StringBuilder encoded = null;
-
- int oldLength = s.length();
-
- // This loop alternates between copying over allowed characters and
- // encoding in chunks. This results in fewer method calls and
- // allocations than encoding one character at a time.
- int current = 0;
- while (current < oldLength) {
- // Start in "copying" mode where we copy over allowed chars.
-
- // Find the next character which needs to be encoded.
- int nextToEncode = current;
- while (nextToEncode < oldLength
- && isAllowed(s.charAt(nextToEncode), allow)) {
- nextToEncode++;
- }
-
- // If there's nothing more to encode...
- if (nextToEncode == oldLength) {
- if (current == 0) {
- // We didn't need to encode anything!
- return s;
- } else {
- // Presumably, we've already done some encoding.
- encoded.append(s, current, oldLength);
- return encoded.toString();
- }
- }
-
- if (encoded == null) {
- encoded = new StringBuilder();
- }
-
- if (nextToEncode > current) {
- // Append allowed characters leading up to this point.
- encoded.append(s, current, nextToEncode);
- } else {
- // assert nextToEncode == current
- }
-
- // Switch to "encoding" mode.
-
- // Find the next allowed character.
- current = nextToEncode;
- int nextAllowed = current + 1;
- while (nextAllowed < oldLength
- && !isAllowed(s.charAt(nextAllowed), allow)) {
- nextAllowed++;
- }
-
- // Convert the substring to bytes and encode the bytes as
- // '%'-escaped octets.
- String toEncode = s.substring(current, nextAllowed);
- try {
- byte[] bytes = toEncode.getBytes(DEFAULT_ENCODING);
- int bytesLength = bytes.length;
- for (int i = 0; i < bytesLength; i++) {
- encoded.append('%');
- encoded.append(HEX_DIGITS[(bytes[i] & 0xf0) >> 4]);
- encoded.append(HEX_DIGITS[bytes[i] & 0xf]);
- }
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e);
- }
-
- current = nextAllowed;
- }
-
- // Encoded could still be null at this point if s is empty.
- return encoded == null ? s : encoded.toString();
- }
-
- /**
- * Returns true if the given character is allowed.
- *
- * @param c character to check
- * @param allow characters to allow
- * @return true if the character is allowed or false if it should be
- * encoded
- */
- private static boolean isAllowed(char c, String allow) {
- return (c >= 'A' && c <= 'Z')
- || (c >= 'a' && c <= 'z')
- || (c >= '0' && c <= '9')
- || "_-!.~'()*".indexOf(c) != NOT_FOUND
- || (allow != null && allow.indexOf(c) != NOT_FOUND);
- }
-
- /** Unicode replacement character: \\uFFFD. */
- private static final byte[] REPLACEMENT = { (byte) 0xFF, (byte) 0xFD };
-
- /**
- * Decodes '%'-escaped octets in the given string using the UTF-8 scheme.
- * Replaces invalid octets with the unicode replacement character
- * ("\\uFFFD").
- *
- * @param s encoded string to decode
- * @return the given string with escaped octets decoded, or null if
- * s is null
- */
- public static String decode(String s) {
- /*
- Compared to java.net.URLEncoderDecoder.decode(), this method decodes a
- chunk at a time instead of one character at a time, and it doesn't
- throw exceptions. It also only allocates memory when necessary--if
- there's nothing to decode, this method won't do much.
- */
-
- if (s == null) {
- return null;
- }
-
- // Lazily-initialized buffers.
- StringBuilder decoded = null;
- ByteArrayOutputStream out = null;
-
- int oldLength = s.length();
-
- // This loop alternates between copying over normal characters and
- // escaping in chunks. This results in fewer method calls and
- // allocations than decoding one character at a time.
- int current = 0;
- while (current < oldLength) {
- // Start in "copying" mode where we copy over normal characters.
-
- // Find the next escape sequence.
- int nextEscape = s.indexOf('%', current);
-
- if (nextEscape == NOT_FOUND) {
- if (decoded == null) {
- // We didn't actually decode anything.
- return s;
- } else {
- // Append the remainder and return the decoded string.
- decoded.append(s, current, oldLength);
- return decoded.toString();
- }
- }
-
- // Prepare buffers.
- if (decoded == null) {
- // Looks like we're going to need the buffers...
- // We know the new string will be shorter. Using the old length
- // may overshoot a bit, but it will save us from resizing the
- // buffer.
- decoded = new StringBuilder(oldLength);
- out = new ByteArrayOutputStream(4);
- } else {
- // Clear decoding buffer.
- out.reset();
- }
-
- // Append characters leading up to the escape.
- if (nextEscape > current) {
- decoded.append(s, current, nextEscape);
-
- current = nextEscape;
- } else {
- // assert current == nextEscape
- }
-
- // Switch to "decoding" mode where we decode a string of escape
- // sequences.
-
- // Decode and append escape sequences. Escape sequences look like
- // "%ab" where % is literal and a and b are hex digits.
- try {
- do {
- if (current + 2 >= oldLength) {
- // Truncated escape sequence.
- out.write(REPLACEMENT);
- } else {
- int a = Character.digit(s.charAt(current + 1), 16);
- int b = Character.digit(s.charAt(current + 2), 16);
-
- if (a == -1 || b == -1) {
- // Non hex digits.
- out.write(REPLACEMENT);
- } else {
- // Combine the hex digits into one byte and write.
- out.write((a << 4) + b);
- }
- }
-
- // Move passed the escape sequence.
- current += 3;
- } while (current < oldLength && s.charAt(current) == '%');
-
- // Decode UTF-8 bytes into a string and append it.
- decoded.append(out.toString(DEFAULT_ENCODING));
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e);
- } catch (IOException e) {
- throw new AssertionError(e);
- }
- }
-
- // If we don't have a buffer, we didn't have to decode anything.
- return decoded == null ? s : decoded.toString();
- }
-
- /**
- * Support for part implementations.
- */
- static abstract class AbstractPart {
-
- /**
- * Enum which indicates which representation of a given part we have.
- */
- static class Representation {
- static final int BOTH = 0;
- static final int ENCODED = 1;
- static final int DECODED = 2;
- }
-
- volatile String encoded;
- volatile String decoded;
-
- AbstractPart(String encoded, String decoded) {
- this.encoded = encoded;
- this.decoded = decoded;
- }
-
- abstract String getEncoded();
-
- final String getDecoded() {
- @SuppressWarnings("StringEquality")
- boolean hasDecoded = decoded != NOT_CACHED;
- return hasDecoded ? decoded : (decoded = decode(encoded));
- }
-
- final void writeTo(Parcel parcel) {
- @SuppressWarnings("StringEquality")
- boolean hasEncoded = encoded != NOT_CACHED;
-
- @SuppressWarnings("StringEquality")
- boolean hasDecoded = decoded != NOT_CACHED;
-
- if (hasEncoded && hasDecoded) {
- parcel.writeInt(Representation.BOTH);
- parcel.writeString(encoded);
- parcel.writeString(decoded);
- } else if (hasEncoded) {
- parcel.writeInt(Representation.ENCODED);
- parcel.writeString(encoded);
- } else if (hasDecoded) {
- parcel.writeInt(Representation.DECODED);
- parcel.writeString(decoded);
- } else {
- throw new AssertionError();
- }
- }
- }
-
- /**
- * Immutable wrapper of encoded and decoded versions of a URI part. Lazily
- * creates the encoded or decoded version from the other.
- */
- static class Part extends AbstractPart {
-
- /** A part with null values. */
- static final Part NULL = new EmptyPart(null);
-
- /** A part with empty strings for values. */
- static final Part EMPTY = new EmptyPart("");
-
- private Part(String encoded, String decoded) {
- super(encoded, decoded);
- }
-
- boolean isEmpty() {
- return false;
- }
-
- String getEncoded() {
- @SuppressWarnings("StringEquality")
- boolean hasEncoded = encoded != NOT_CACHED;
- return hasEncoded ? encoded : (encoded = encode(decoded));
- }
-
- static Part readFrom(Parcel parcel) {
- int representation = parcel.readInt();
- switch (representation) {
- case Representation.BOTH:
- return from(parcel.readString(), parcel.readString());
- case Representation.ENCODED:
- return fromEncoded(parcel.readString());
- case Representation.DECODED:
- return fromDecoded(parcel.readString());
- default:
- throw new AssertionError();
- }
- }
-
- /**
- * Returns given part or {@link #NULL} if the given part is null.
- */
- static Part nonNull(Part part) {
- return part == null ? NULL : part;
- }
-
- /**
- * Creates a part from the encoded string.
- *
- * @param encoded part string
- */
- static Part fromEncoded(String encoded) {
- return from(encoded, NOT_CACHED);
- }
-
- /**
- * Creates a part from the decoded string.
- *
- * @param decoded part string
- */
- static Part fromDecoded(String decoded) {
- return from(NOT_CACHED, decoded);
- }
-
- /**
- * Creates a part from the encoded and decoded strings.
- *
- * @param encoded part string
- * @param decoded part string
- */
- static Part from(String encoded, String decoded) {
- // We have to check both encoded and decoded in case one is
- // NOT_CACHED.
-
- if (encoded == null) {
- return NULL;
- }
- if (encoded.length() == 0) {
- return EMPTY;
- }
-
- if (decoded == null) {
- return NULL;
- }
- if (decoded .length() == 0) {
- return EMPTY;
- }
-
- return new Part(encoded, decoded);
- }
-
- private static class EmptyPart extends Part {
- public EmptyPart(String value) {
- super(value, value);
- }
-
- @Override
- boolean isEmpty() {
- return true;
- }
- }
- }
-
- /**
- * Immutable wrapper of encoded and decoded versions of a path part. Lazily
- * creates the encoded or decoded version from the other.
- */
- static class PathPart extends AbstractPart {
-
- /** A part with null values. */
- static final PathPart NULL = new PathPart(null, null);
-
- /** A part with empty strings for values. */
- static final PathPart EMPTY = new PathPart("", "");
-
- private PathPart(String encoded, String decoded) {
- super(encoded, decoded);
- }
-
- String getEncoded() {
- @SuppressWarnings("StringEquality")
- boolean hasEncoded = encoded != NOT_CACHED;
-
- // Don't encode '/'.
- return hasEncoded ? encoded : (encoded = encode(decoded, "/"));
- }
-
- /**
- * Cached path segments. This doesn't need to be volatile--we don't
- * care if other threads see the result.
- */
- private PathSegments pathSegments;
-
- /**
- * Gets the individual path segments. Parses them if necessary.
- *
- * @return parsed path segments or null if this isn't a hierarchical
- * URI
- */
- PathSegments getPathSegments() {
- if (pathSegments != null) {
- return pathSegments;
- }
-
- String path = getEncoded();
- if (path == null) {
- return pathSegments = PathSegments.EMPTY;
- }
-
- PathSegmentsBuilder segmentBuilder = new PathSegmentsBuilder();
-
- int previous = 0;
- int current;
- while ((current = path.indexOf('/', previous)) > -1) {
- // This check keeps us from adding a segment if the path starts
- // '/' and an empty segment for "//".
- if (previous < current) {
- String decodedSegment
- = decode(path.substring(previous, current));
- segmentBuilder.add(decodedSegment);
- }
- previous = current + 1;
- }
-
- // Add in the final path segment.
- if (previous < path.length()) {
- segmentBuilder.add(decode(path.substring(previous)));
- }
-
- return pathSegments = segmentBuilder.build();
- }
-
- static PathPart appendEncodedSegment(PathPart oldPart,
- String newSegment) {
- // If there is no old path, should we make the new path relative
- // or absolute? I pick absolute.
-
- if (oldPart == null) {
- // No old path.
- return fromEncoded("/" + newSegment);
- }
-
- String oldPath = oldPart.getEncoded();
-
- if (oldPath == null) {
- oldPath = "";
- }
-
- int oldPathLength = oldPath.length();
- String newPath;
- if (oldPathLength == 0) {
- // No old path.
- newPath = "/" + newSegment;
- } else if (oldPath.charAt(oldPathLength - 1) == '/') {
- newPath = oldPath + newSegment;
- } else {
- newPath = oldPath + "/" + newSegment;
- }
-
- return fromEncoded(newPath);
- }
-
- static PathPart appendDecodedSegment(PathPart oldPart, String decoded) {
- String encoded = encode(decoded);
-
- // TODO: Should we reuse old PathSegments? Probably not.
- return appendEncodedSegment(oldPart, encoded);
- }
-
- static PathPart readFrom(Parcel parcel) {
- int representation = parcel.readInt();
- switch (representation) {
- case Representation.BOTH:
- return from(parcel.readString(), parcel.readString());
- case Representation.ENCODED:
- return fromEncoded(parcel.readString());
- case Representation.DECODED:
- return fromDecoded(parcel.readString());
- default:
- throw new AssertionError();
- }
- }
-
- /**
- * Creates a path from the encoded string.
- *
- * @param encoded part string
- */
- static PathPart fromEncoded(String encoded) {
- return from(encoded, NOT_CACHED);
- }
-
- /**
- * Creates a path from the decoded string.
- *
- * @param decoded part string
- */
- static PathPart fromDecoded(String decoded) {
- return from(NOT_CACHED, decoded);
- }
-
- /**
- * Creates a path from the encoded and decoded strings.
- *
- * @param encoded part string
- * @param decoded part string
- */
- static PathPart from(String encoded, String decoded) {
- if (encoded == null) {
- return NULL;
- }
-
- if (encoded.length() == 0) {
- return EMPTY;
- }
-
- return new PathPart(encoded, decoded);
- }
-
- /**
- * Prepends path values with "/" if they're present, not empty, and
- * they don't already start with "/".
- */
- static PathPart makeAbsolute(PathPart oldPart) {
- @SuppressWarnings("StringEquality")
- boolean encodedCached = oldPart.encoded != NOT_CACHED;
-
- // We don't care which version we use, and we don't want to force
- // unneccessary encoding/decoding.
- String oldPath = encodedCached ? oldPart.encoded : oldPart.decoded;
-
- if (oldPath == null || oldPath.length() == 0
- || oldPath.startsWith("/")) {
- return oldPart;
- }
-
- // Prepend encoded string if present.
- String newEncoded = encodedCached
- ? "/" + oldPart.encoded : NOT_CACHED;
-
- // Prepend decoded string if present.
- @SuppressWarnings("StringEquality")
- boolean decodedCached = oldPart.decoded != NOT_CACHED;
- String newDecoded = decodedCached
- ? "/" + oldPart.decoded
- : NOT_CACHED;
-
- return new PathPart(newEncoded, newDecoded);
- }
- }
-
- /**
- * Creates a new Uri by appending an already-encoded path segment to a
- * base Uri.
- *
- * @param baseUri Uri to append path segment to
- * @param pathSegment encoded path segment to append
- * @return a new Uri based on baseUri with the given segment appended to
- * the path
- * @throws NullPointerException if baseUri is null
- */
- public static Uri withAppendedPath(Uri baseUri, String pathSegment) {
- Builder builder = baseUri.buildUpon();
- builder = builder.appendEncodedPath(pathSegment);
- return builder.build();
- }
-}
diff --git a/core/java/android/net/UrlQuerySanitizer.java b/core/java/android/net/UrlQuerySanitizer.java
deleted file mode 100644
index a6efcdd..0000000
--- a/core/java/android/net/UrlQuerySanitizer.java
+++ /dev/null
@@ -1,913 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Set;
-import java.util.StringTokenizer;
-
-/**
- *
- * Sanitizes the Query portion of a URL. Simple example:
- * <code>
- * UrlQuerySanitizer sanitizer = new UrlQuerySanitizer();
- * sanitizer.setAllowUnregisteredParamaters(true);
- * sanitizer.parseUrl("http://example.com/?name=Joe+User");
- * String name = sanitizer.getValue("name"));
- * // name now contains "Joe_User"
- * </code>
- *
- * Register ValueSanitizers to customize the way individual
- * parameters are sanitized:
- * <code>
- * UrlQuerySanitizer sanitizer = new UrlQuerySanitizer();
- * sanitizer.registerParamater("name", UrlQuerySanitizer.createSpaceLegal());
- * sanitizer.parseUrl("http://example.com/?name=Joe+User");
- * String name = sanitizer.getValue("name"));
- * // name now contains "Joe User". (The string is first decoded, which
- * // converts the '+' to a ' '. Then the string is sanitized, which
- * // converts the ' ' to an '_'. (The ' ' is converted because the default
- * unregistered parameter sanitizer does not allow any special characters,
- * and ' ' is a special character.)
- * </code>
- *
- * There are several ways to create ValueSanitizers. In order of increasing
- * sophistication:
- * <ol>
- * <li>Call one of the UrlQuerySanitizer.createXXX() methods.
- * <li>Construct your own instance of
- * UrlQuerySanitizer.IllegalCharacterValueSanitizer.
- * <li>Subclass UrlQuerySanitizer.ValueSanitizer to define your own value
- * sanitizer.
- * </ol>
- *
- */
-public class UrlQuerySanitizer {
-
- /**
- * A simple tuple that holds parameter-value pairs.
- *
- */
- public class ParameterValuePair {
- /**
- * Construct a parameter-value tuple.
- * @param parameter an unencoded parameter
- * @param value an unencoded value
- */
- public ParameterValuePair(String parameter,
- String value) {
- mParameter = parameter;
- mValue = value;
- }
- /**
- * The unencoded parameter
- */
- public String mParameter;
- /**
- * The unencoded value
- */
- public String mValue;
- }
-
- final private HashMap<String, ValueSanitizer> mSanitizers =
- new HashMap<String, ValueSanitizer>();
- final private HashMap<String, String> mEntries =
- new HashMap<String, String>();
- final private ArrayList<ParameterValuePair> mEntriesList =
- new ArrayList<ParameterValuePair>();
- private boolean mAllowUnregisteredParamaters;
- private boolean mPreferFirstRepeatedParameter;
- private ValueSanitizer mUnregisteredParameterValueSanitizer =
- getAllIllegal();
-
- /**
- * A functor used to sanitize a single query value.
- *
- */
- public static interface ValueSanitizer {
- /**
- * Sanitize an unencoded value.
- * @param value
- * @return the sanitized unencoded value
- */
- public String sanitize(String value);
- }
-
- /**
- * Sanitize values based on which characters they contain. Illegal
- * characters are replaced with either space or '_', depending upon
- * whether space is a legal character or not.
- */
- public static class IllegalCharacterValueSanitizer implements
- ValueSanitizer {
- private int mFlags;
-
- /**
- * Allow space (' ') characters.
- */
- public final static int SPACE_OK = 1 << 0;
- /**
- * Allow whitespace characters other than space. The
- * other whitespace characters are
- * '\t' '\f' '\n' '\r' and '\0x000b' (vertical tab)
- */
- public final static int OTHER_WHITESPACE_OK = 1 << 1;
- /**
- * Allow characters with character codes 128 to 255.
- */
- public final static int NON_7_BIT_ASCII_OK = 1 << 2;
- /**
- * Allow double quote characters. ('"')
- */
- public final static int DQUOTE_OK = 1 << 3;
- /**
- * Allow single quote characters. ('\'')
- */
- public final static int SQUOTE_OK = 1 << 4;
- /**
- * Allow less-than characters. ('<')
- */
- public final static int LT_OK = 1 << 5;
- /**
- * Allow greater-than characters. ('>')
- */
- public final static int GT_OK = 1 << 6;
- /**
- * Allow ampersand characters ('&')
- */
- public final static int AMP_OK = 1 << 7;
- /**
- * Allow percent-sign characters ('%')
- */
- public final static int PCT_OK = 1 << 8;
- /**
- * Allow nul characters ('\0')
- */
- public final static int NUL_OK = 1 << 9;
- /**
- * Allow text to start with a script URL
- * such as "javascript:" or "vbscript:"
- */
- public final static int SCRIPT_URL_OK = 1 << 10;
-
- /**
- * Mask with all fields set to OK
- */
- public final static int ALL_OK = 0x7ff;
-
- /**
- * Mask with both regular space and other whitespace OK
- */
- public final static int ALL_WHITESPACE_OK =
- SPACE_OK | OTHER_WHITESPACE_OK;
-
-
- // Common flag combinations:
-
- /**
- * <ul>
- * <li>Deny all special characters.
- * <li>Deny script URLs.
- * </ul>
- */
- public final static int ALL_ILLEGAL =
- 0;
- /**
- * <ul>
- * <li>Allow all special characters except Nul. ('\0').
- * <li>Allow script URLs.
- * </ul>
- */
- public final static int ALL_BUT_NUL_LEGAL =
- ALL_OK & ~NUL_OK;
- /**
- * <ul>
- * <li>Allow all special characters except for:
- * <ul>
- * <li>whitespace characters
- * <li>Nul ('\0')
- * </ul>
- * <li>Allow script URLs.
- * </ul>
- */
- public final static int ALL_BUT_WHITESPACE_LEGAL =
- ALL_OK & ~(ALL_WHITESPACE_OK | NUL_OK);
- /**
- * <ul>
- * <li>Allow characters used by encoded URLs.
- * <li>Deny script URLs.
- * </ul>
- */
- public final static int URL_LEGAL =
- NON_7_BIT_ASCII_OK | SQUOTE_OK | AMP_OK | PCT_OK;
- /**
- * <ul>
- * <li>Allow characters used by encoded URLs.
- * <li>Allow spaces.
- * <li>Deny script URLs.
- * </ul>
- */
- public final static int URL_AND_SPACE_LEGAL =
- URL_LEGAL | SPACE_OK;
- /**
- * <ul>
- * <li>Allow ampersand.
- * <li>Deny script URLs.
- * </ul>
- */
- public final static int AMP_LEGAL =
- AMP_OK;
- /**
- * <ul>
- * <li>Allow ampersand.
- * <li>Allow space.
- * <li>Deny script URLs.
- * </ul>
- */
- public final static int AMP_AND_SPACE_LEGAL =
- AMP_OK | SPACE_OK;
- /**
- * <ul>
- * <li>Allow space.
- * <li>Deny script URLs.
- * </ul>
- */
- public final static int SPACE_LEGAL =
- SPACE_OK;
- /**
- * <ul>
- * <li>Allow all but.
- * <ul>
- * <li>Nul ('\0')
- * <li>Angle brackets ('<', '>')
- * </ul>
- * <li>Deny script URLs.
- * </ul>
- */
- public final static int ALL_BUT_NUL_AND_ANGLE_BRACKETS_LEGAL =
- ALL_OK & ~(NUL_OK | LT_OK | GT_OK);
-
- /**
- * Script URL definitions
- */
-
- private final static String JAVASCRIPT_PREFIX = "javascript:";
-
- private final static String VBSCRIPT_PREFIX = "vbscript:";
-
- private final static int MIN_SCRIPT_PREFIX_LENGTH = Math.min(
- JAVASCRIPT_PREFIX.length(), VBSCRIPT_PREFIX.length());
-
- /**
- * Construct a sanitizer. The parameters set the behavior of the
- * sanitizer.
- * @param flags some combination of the XXX_OK flags.
- */
- public IllegalCharacterValueSanitizer(
- int flags) {
- mFlags = flags;
- }
- /**
- * Sanitize a value.
- * <ol>
- * <li>If script URLs are not OK, the will be removed.
- * <li>If neither spaces nor other white space is OK, then
- * white space will be trimmed from the beginning and end of
- * the URL. (Just the actual white space characters are trimmed, not
- * other control codes.)
- * <li> Illegal characters will be replaced with
- * either ' ' or '_', depending on whether a space is itself a
- * legal character.
- * </ol>
- * @param value
- * @return the sanitized value
- */
- public String sanitize(String value) {
- if (value == null) {
- return null;
- }
- int length = value.length();
- if ((mFlags & SCRIPT_URL_OK) != 0) {
- if (length >= MIN_SCRIPT_PREFIX_LENGTH) {
- String asLower = value.toLowerCase();
- if (asLower.startsWith(JAVASCRIPT_PREFIX) ||
- asLower.startsWith(VBSCRIPT_PREFIX)) {
- return "";
- }
- }
- }
-
- // If whitespace isn't OK, get rid of whitespace at beginning
- // and end of value.
- if ( (mFlags & ALL_WHITESPACE_OK) == 0) {
- value = trimWhitespace(value);
- // The length could have changed, so we need to correct
- // the length variable.
- length = value.length();
- }
-
- StringBuilder stringBuilder = new StringBuilder(length);
- for(int i = 0; i < length; i++) {
- char c = value.charAt(i);
- if (!characterIsLegal(c)) {
- if ((mFlags & SPACE_OK) != 0) {
- c = ' ';
- }
- else {
- c = '_';
- }
- }
- stringBuilder.append(c);
- }
- return stringBuilder.toString();
- }
-
- /**
- * Trim whitespace from the beginning and end of a string.
- * <p>
- * Note: can't use {@link String#trim} because {@link String#trim} has a
- * different definition of whitespace than we want.
- * @param value the string to trim
- * @return the trimmed string
- */
- private String trimWhitespace(String value) {
- int start = 0;
- int last = value.length() - 1;
- int end = last;
- while (start <= end && isWhitespace(value.charAt(start))) {
- start++;
- }
- while (end >= start && isWhitespace(value.charAt(end))) {
- end--;
- }
- if (start == 0 && end == last) {
- return value;
- }
- return value.substring(start, end + 1);
- }
-
- /**
- * Check if c is whitespace.
- * @param c character to test
- * @return true if c is a whitespace character
- */
- private boolean isWhitespace(char c) {
- switch(c) {
- case ' ':
- case '\t':
- case '\f':
- case '\n':
- case '\r':
- case 11: /* VT */
- return true;
- default:
- return false;
- }
- }
-
- /**
- * Check whether an individual character is legal. Uses the
- * flag bit-set passed into the constructor.
- * @param c
- * @return true if c is a legal character
- */
- private boolean characterIsLegal(char c) {
- switch(c) {
- case ' ' : return (mFlags & SPACE_OK) != 0;
- case '\t': case '\f': case '\n': case '\r': case 11: /* VT */
- return (mFlags & OTHER_WHITESPACE_OK) != 0;
- case '\"': return (mFlags & DQUOTE_OK) != 0;
- case '\'': return (mFlags & SQUOTE_OK) != 0;
- case '<' : return (mFlags & LT_OK) != 0;
- case '>' : return (mFlags & GT_OK) != 0;
- case '&' : return (mFlags & AMP_OK) != 0;
- case '%' : return (mFlags & PCT_OK) != 0;
- case '\0': return (mFlags & NUL_OK) != 0;
- default : return (c >= 32 && c < 127) ||
- ((c >= 128) && ((mFlags & NON_7_BIT_ASCII_OK) != 0));
- }
- }
- }
-
- /**
- * Get the current value sanitizer used when processing
- * unregistered parameter values.
- * <p>
- * <b>Note:</b> The default unregistered parameter value sanitizer is
- * one that doesn't allow any special characters, similar to what
- * is returned by calling createAllIllegal.
- *
- * @return the current ValueSanitizer used to sanitize unregistered
- * parameter values.
- */
- public ValueSanitizer getUnregisteredParameterValueSanitizer() {
- return mUnregisteredParameterValueSanitizer;
- }
-
- /**
- * Set the value sanitizer used when processing unregistered
- * parameter values.
- * @param sanitizer set the ValueSanitizer used to sanitize unregistered
- * parameter values.
- */
- public void setUnregisteredParameterValueSanitizer(
- ValueSanitizer sanitizer) {
- mUnregisteredParameterValueSanitizer = sanitizer;
- }
-
-
- // Private fields for singleton sanitizers:
-
- private static final ValueSanitizer sAllIllegal =
- new IllegalCharacterValueSanitizer(
- IllegalCharacterValueSanitizer.ALL_ILLEGAL);
-
- private static final ValueSanitizer sAllButNulLegal =
- new IllegalCharacterValueSanitizer(
- IllegalCharacterValueSanitizer.ALL_BUT_NUL_LEGAL);
-
- private static final ValueSanitizer sAllButWhitespaceLegal =
- new IllegalCharacterValueSanitizer(
- IllegalCharacterValueSanitizer.ALL_BUT_WHITESPACE_LEGAL);
-
- private static final ValueSanitizer sURLLegal =
- new IllegalCharacterValueSanitizer(
- IllegalCharacterValueSanitizer.URL_LEGAL);
-
- private static final ValueSanitizer sUrlAndSpaceLegal =
- new IllegalCharacterValueSanitizer(
- IllegalCharacterValueSanitizer.URL_AND_SPACE_LEGAL);
-
- private static final ValueSanitizer sAmpLegal =
- new IllegalCharacterValueSanitizer(
- IllegalCharacterValueSanitizer.AMP_LEGAL);
-
- private static final ValueSanitizer sAmpAndSpaceLegal =
- new IllegalCharacterValueSanitizer(
- IllegalCharacterValueSanitizer.AMP_AND_SPACE_LEGAL);
-
- private static final ValueSanitizer sSpaceLegal =
- new IllegalCharacterValueSanitizer(
- IllegalCharacterValueSanitizer.SPACE_LEGAL);
-
- private static final ValueSanitizer sAllButNulAndAngleBracketsLegal =
- new IllegalCharacterValueSanitizer(
- IllegalCharacterValueSanitizer.ALL_BUT_NUL_AND_ANGLE_BRACKETS_LEGAL);
-
- /**
- * Return a value sanitizer that does not allow any special characters,
- * and also does not allow script URLs.
- * @return a value sanitizer
- */
- public static final ValueSanitizer getAllIllegal() {
- return sAllIllegal;
- }
-
- /**
- * Return a value sanitizer that allows everything except Nul ('\0')
- * characters. Script URLs are allowed.
- * @return a value sanitizer
- */
- public static final ValueSanitizer getAllButNulLegal() {
- return sAllButNulLegal;
- }
- /**
- * Return a value sanitizer that allows everything except Nul ('\0')
- * characters, space (' '), and other whitespace characters.
- * Script URLs are allowed.
- * @return a value sanitizer
- */
- public static final ValueSanitizer getAllButWhitespaceLegal() {
- return sAllButWhitespaceLegal;
- }
- /**
- * Return a value sanitizer that allows all the characters used by
- * encoded URLs. Does not allow script URLs.
- * @return a value sanitizer
- */
- public static final ValueSanitizer getUrlLegal() {
- return sURLLegal;
- }
- /**
- * Return a value sanitizer that allows all the characters used by
- * encoded URLs and allows spaces, which are not technically legal
- * in encoded URLs, but commonly appear anyway.
- * Does not allow script URLs.
- * @return a value sanitizer
- */
- public static final ValueSanitizer getUrlAndSpaceLegal() {
- return sUrlAndSpaceLegal;
- }
- /**
- * Return a value sanitizer that does not allow any special characters
- * except ampersand ('&'). Does not allow script URLs.
- * @return a value sanitizer
- */
- public static final ValueSanitizer getAmpLegal() {
- return sAmpLegal;
- }
- /**
- * Return a value sanitizer that does not allow any special characters
- * except ampersand ('&') and space (' '). Does not allow script URLs.
- * @return a value sanitizer
- */
- public static final ValueSanitizer getAmpAndSpaceLegal() {
- return sAmpAndSpaceLegal;
- }
- /**
- * Return a value sanitizer that does not allow any special characters
- * except space (' '). Does not allow script URLs.
- * @return a value sanitizer
- */
- public static final ValueSanitizer getSpaceLegal() {
- return sSpaceLegal;
- }
- /**
- * Return a value sanitizer that allows any special characters
- * except angle brackets ('<' and '>') and Nul ('\0').
- * Allows script URLs.
- * @return a value sanitizer
- */
- public static final ValueSanitizer getAllButNulAndAngleBracketsLegal() {
- return sAllButNulAndAngleBracketsLegal;
- }
-
- /**
- * Constructs a UrlQuerySanitizer.
- * <p>
- * Defaults:
- * <ul>
- * <li>unregistered parameters are not allowed.
- * <li>the last instance of a repeated parameter is preferred.
- * <li>The default value sanitizer is an AllIllegal value sanitizer.
- * <ul>
- */
- public UrlQuerySanitizer() {
- }
-
- /**
- * Constructs a UrlQuerySanitizer and parse a URL.
- * This constructor is provided for convenience when the
- * default parsing behavior is acceptable.
- * <p>
- * Because the URL is parsed before the constructor returns, there isn't
- * a chance to configure the sanitizer to change the parsing behavior.
- * <p>
- * <code>
- * UrlQuerySanitizer sanitizer = new UrlQuerySanitizer(myUrl);
- * String name = sanitizer.getValue("name");
- * </code>
- * <p>
- * Defaults:
- * <ul>
- * <li>unregistered parameters <em>are</em> allowed.
- * <li>the last instance of a repeated parameter is preferred.
- * <li>The default value sanitizer is an AllIllegal value sanitizer.
- * <ul>
- */
- public UrlQuerySanitizer(String url) {
- setAllowUnregisteredParamaters(true);
- parseUrl(url);
- }
-
- /**
- * Parse the query parameters out of an encoded URL.
- * Works by extracting the query portion from the URL and then
- * calling parseQuery(). If there is no query portion it is
- * treated as if the query portion is an empty string.
- * @param url the encoded URL to parse.
- */
- public void parseUrl(String url) {
- int queryIndex = url.indexOf('?');
- String query;
- if (queryIndex >= 0) {
- query = url.substring(queryIndex + 1);
- }
- else {
- query = "";
- }
- parseQuery(query);
- }
-
- /**
- * Parse a query. A query string is any number of parameter-value clauses
- * separated by any non-zero number of ampersands. A parameter-value clause
- * is a parameter followed by an equal sign, followed by a value. If the
- * equal sign is missing, the value is assumed to be the empty string.
- * @param query the query to parse.
- */
- public void parseQuery(String query) {
- clear();
- // Split by '&'
- StringTokenizer tokenizer = new StringTokenizer(query, "&");
- while(tokenizer.hasMoreElements()) {
- String attributeValuePair = tokenizer.nextToken();
- if (attributeValuePair.length() > 0) {
- int assignmentIndex = attributeValuePair.indexOf('=');
- if (assignmentIndex < 0) {
- // No assignment found, treat as if empty value
- parseEntry(attributeValuePair, "");
- }
- else {
- parseEntry(attributeValuePair.substring(0, assignmentIndex),
- attributeValuePair.substring(assignmentIndex + 1));
- }
- }
- }
- }
-
- /**
- * Get a set of all of the parameters found in the sanitized query.
- * <p>
- * Note: Do not modify this set. Treat it as a read-only set.
- * @return all the parameters found in the current query.
- */
- public Set<String> getParameterSet() {
- return mEntries.keySet();
- }
-
- /**
- * An array list of all of the parameter value pairs in the sanitized
- * query, in the order they appeared in the query. May contain duplicate
- * parameters.
- * <p class="note"><b>Note:</b> Do not modify this list. Treat it as a read-only list.</p>
- */
- public List<ParameterValuePair> getParameterList() {
- return mEntriesList;
- }
-
- /**
- * Check if a parameter exists in the current sanitized query.
- * @param parameter the unencoded name of a parameter.
- * @return true if the paramater exists in the current sanitized queary.
- */
- public boolean hasParameter(String parameter) {
- return mEntries.containsKey(parameter);
- }
-
- /**
- * Get the value for a parameter in the current sanitized query.
- * Returns null if the parameter does not
- * exit.
- * @param parameter the unencoded name of a parameter.
- * @return the sanitized unencoded value of the parameter,
- * or null if the parameter does not exist.
- */
- public String getValue(String parameter) {
- return mEntries.get(parameter);
- }
-
- /**
- * Register a value sanitizer for a particular parameter. Can also be used
- * to replace or remove an already-set value sanitizer.
- * <p>
- * Registering a non-null value sanitizer for a particular parameter
- * makes that parameter a registered parameter.
- * @param parameter an unencoded parameter name
- * @param valueSanitizer the value sanitizer to use for a particular
- * parameter. May be null in order to unregister that parameter.
- * @see #getAllowUnregisteredParamaters()
- */
- public void registerParameter(String parameter,
- ValueSanitizer valueSanitizer) {
- if (valueSanitizer == null) {
- mSanitizers.remove(parameter);
- }
- mSanitizers.put(parameter, valueSanitizer);
- }
-
- /**
- * Register a value sanitizer for an array of parameters.
- * @param parameters An array of unencoded parameter names.
- * @param valueSanitizer
- * @see #registerParameter
- */
- public void registerParameters(String[] parameters,
- ValueSanitizer valueSanitizer) {
- int length = parameters.length;
- for(int i = 0; i < length; i++) {
- mSanitizers.put(parameters[i], valueSanitizer);
- }
- }
-
- /**
- * Set whether or not unregistered parameters are allowed. If they
- * are not allowed, then they will be dropped when a query is sanitized.
- * <p>
- * Defaults to false.
- * @param allowUnregisteredParamaters true to allow unregistered parameters.
- * @see #getAllowUnregisteredParamaters()
- */
- public void setAllowUnregisteredParamaters(
- boolean allowUnregisteredParamaters) {
- mAllowUnregisteredParamaters = allowUnregisteredParamaters;
- }
-
- /**
- * Get whether or not unregistered parameters are allowed. If not
- * allowed, they will be dropped when a query is parsed.
- * @return true if unregistered parameters are allowed.
- * @see #setAllowUnregisteredParamaters(boolean)
- */
- public boolean getAllowUnregisteredParamaters() {
- return mAllowUnregisteredParamaters;
- }
-
- /**
- * Set whether or not the first occurrence of a repeated parameter is
- * preferred. True means the first repeated parameter is preferred.
- * False means that the last repeated parameter is preferred.
- * <p>
- * The preferred parameter is the one that is returned when getParameter
- * is called.
- * <p>
- * defaults to false.
- * @param preferFirstRepeatedParameter True if the first repeated
- * parameter is preferred.
- * @see #getPreferFirstRepeatedParameter()
- */
- public void setPreferFirstRepeatedParameter(
- boolean preferFirstRepeatedParameter) {
- mPreferFirstRepeatedParameter = preferFirstRepeatedParameter;
- }
-
- /**
- * Get whether or not the first occurrence of a repeated parameter is
- * preferred.
- * @return true if the first occurrence of a repeated parameter is
- * preferred.
- * @see #setPreferFirstRepeatedParameter(boolean)
- */
- public boolean getPreferFirstRepeatedParameter() {
- return mPreferFirstRepeatedParameter;
- }
-
- /**
- * Parse an escaped parameter-value pair. The default implementation
- * unescapes both the parameter and the value, then looks up the
- * effective value sanitizer for the parameter and uses it to sanitize
- * the value. If all goes well then addSanitizedValue is called with
- * the unescaped parameter and the sanitized unescaped value.
- * @param parameter an escaped parameter
- * @param value an unsanitzied escaped value
- */
- protected void parseEntry(String parameter, String value) {
- String unescapedParameter = unescape(parameter);
- ValueSanitizer valueSanitizer =
- getEffectiveValueSanitizer(unescapedParameter);
-
- if (valueSanitizer == null) {
- return;
- }
- String unescapedValue = unescape(value);
- String sanitizedValue = valueSanitizer.sanitize(unescapedValue);
- addSanitizedEntry(unescapedParameter, sanitizedValue);
- }
-
- /**
- * Record a sanitized parameter-value pair. Override if you want to
- * do additional filtering or validation.
- * @param parameter an unescaped parameter
- * @param value a sanitized unescaped value
- */
- protected void addSanitizedEntry(String parameter, String value) {
- mEntriesList.add(
- new ParameterValuePair(parameter, value));
- if (mPreferFirstRepeatedParameter) {
- if (mEntries.containsKey(parameter)) {
- return;
- }
- }
- mEntries.put(parameter, value);
- }
-
- /**
- * Get the value sanitizer for a parameter. Returns null if there
- * is no value sanitizer registered for the parameter.
- * @param parameter the unescaped parameter
- * @return the currently registered value sanitizer for this parameter.
- * @see #registerParameter(String, android.net.UrlQuerySanitizer.ValueSanitizer)
- */
- public ValueSanitizer getValueSanitizer(String parameter) {
- return mSanitizers.get(parameter);
- }
-
- /**
- * Get the effective value sanitizer for a parameter. Like getValueSanitizer,
- * except if there is no value sanitizer registered for a parameter, and
- * unregistered paramaters are allowed, then the default value sanitizer is
- * returned.
- * @param parameter an unescaped parameter
- * @return the effective value sanitizer for a parameter.
- */
- public ValueSanitizer getEffectiveValueSanitizer(String parameter) {
- ValueSanitizer sanitizer = getValueSanitizer(parameter);
- if (sanitizer == null && mAllowUnregisteredParamaters) {
- sanitizer = getUnregisteredParameterValueSanitizer();
- }
- return sanitizer;
- }
-
- /**
- * Unescape an escaped string.
- * <ul>
- * <li>'+' characters are replaced by
- * ' ' characters.
- * <li>Valid "%xx" escape sequences are replaced by the
- * corresponding unescaped character.
- * <li>Invalid escape sequences such as %1z", are passed through unchanged.
- * <ol>
- * @param string the escaped string
- * @return the unescaped string.
- */
- public String unescape(String string) {
- // Early exit if no escaped characters.
- int firstEscape = string.indexOf('%');
- if ( firstEscape < 0) {
- firstEscape = string.indexOf('+');
- if (firstEscape < 0) {
- return string;
- }
- }
-
- int length = string.length();
-
- StringBuilder stringBuilder = new StringBuilder(length);
- stringBuilder.append(string.substring(0, firstEscape));
- for (int i = firstEscape; i < length; i++) {
- char c = string.charAt(i);
- if (c == '+') {
- c = ' ';
- }
- else if ( c == '%' && i + 2 < length) {
- char c1 = string.charAt(i + 1);
- char c2 = string.charAt(i + 2);
- if (isHexDigit(c1) && isHexDigit(c2)) {
- c = (char) (decodeHexDigit(c1) * 16 + decodeHexDigit(c2));
- i += 2;
- }
- }
- stringBuilder.append(c);
- }
- return stringBuilder.toString();
- }
-
- /**
- * Test if a character is a hexidecimal digit. Both upper case and lower
- * case hex digits are allowed.
- * @param c the character to test
- * @return true if c is a hex digit.
- */
- protected boolean isHexDigit(char c) {
- return decodeHexDigit(c) >= 0;
- }
-
- /**
- * Convert a character that represents a hexidecimal digit into an integer.
- * If the character is not a hexidecimal digit, then -1 is returned.
- * Both upper case and lower case hex digits are allowed.
- * @param c the hexidecimal digit.
- * @return the integer value of the hexidecimal digit.
- */
-
- protected int decodeHexDigit(char c) {
- if (c >= '0' && c <= '9') {
- return c - '0';
- }
- else if (c >= 'A' && c <= 'F') {
- return c - 'A' + 10;
- }
- else if (c >= 'a' && c <= 'f') {
- return c - 'a' + 10;
- }
- else {
- return -1;
- }
- }
-
- /**
- * Clear the existing entries. Called to get ready to parse a new
- * query string.
- */
- protected void clear() {
- mEntries.clear();
- mEntriesList.clear();
- }
-}
-
diff --git a/core/java/android/net/WebAddress.java b/core/java/android/net/WebAddress.java
deleted file mode 100644
index f4a2a6a..0000000
--- a/core/java/android/net/WebAddress.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * {@hide}
- *
- * Web Address Parser
- *
- * This is called WebAddress, rather than URL or URI, because it
- * attempts to parse the stuff that a user will actually type into a
- * browser address widget.
- *
- * Unlike java.net.uri, this parser will not choke on URIs missing
- * schemes. It will only throw a ParseException if the input is
- * really hosed.
- *
- * If given an https scheme but no port, fills in port
- *
- */
-public class WebAddress {
-
- private final static String LOGTAG = "http";
-
- public String mScheme;
- public String mHost;
- public int mPort;
- public String mPath;
- public String mAuthInfo;
-
- static final int MATCH_GROUP_SCHEME = 1;
- static final int MATCH_GROUP_AUTHORITY = 2;
- static final int MATCH_GROUP_HOST = 3;
- static final int MATCH_GROUP_PORT = 4;
- static final int MATCH_GROUP_PATH = 5;
-
- static Pattern sAddressPattern = Pattern.compile(
- /* scheme */ "(?:(http|HTTP|https|HTTPS|file|FILE)\\:\\/\\/)?" +
- /* authority */ "(?:([-A-Za-z0-9$_.+!*'(),;?&=]+(?:\\:[-A-Za-z0-9$_.+!*'(),;?&=]+)?)@)?" +
- /* host */ "([-A-Za-z0-9%]+(?:\\.[-A-Za-z0-9%]+)*)?" +
- /* port */ "(?:\\:([0-9]+))?" +
- /* path */ "(\\/?.*)?");
-
- /** parses given uriString. */
- public WebAddress(String address) throws ParseException {
- if (address == null) {
- throw new NullPointerException();
- }
-
- // android.util.Log.d(LOGTAG, "WebAddress: " + address);
-
- mScheme = "";
- mHost = "";
- mPort = -1;
- mPath = "/";
- mAuthInfo = "";
-
- Matcher m = sAddressPattern.matcher(address);
- String t;
- if (m.matches()) {
- t = m.group(MATCH_GROUP_SCHEME);
- if (t != null) mScheme = t;
- t = m.group(MATCH_GROUP_AUTHORITY);
- if (t != null) mAuthInfo = t;
- t = m.group(MATCH_GROUP_HOST);
- if (t != null) mHost = t;
- t = m.group(MATCH_GROUP_PORT);
- if (t != null) {
- try {
- mPort = Integer.parseInt(t);
- } catch (NumberFormatException ex) {
- throw new ParseException("Bad port");
- }
- }
- t = m.group(MATCH_GROUP_PATH);
- if (t != null && t.length() > 0) {
- /* handle busted myspace frontpage redirect with
- missing initial "/" */
- if (t.charAt(0) == '/') {
- mPath = t;
- } else {
- mPath = "/" + t;
- }
- }
-
- } else {
- // nothing found... outa here
- throw new ParseException("Bad address");
- }
-
- /* Get port from scheme or scheme from port, if necessary and
- possible */
- if (mPort == 443 && mScheme.equals("")) {
- mScheme = "https";
- } else if (mPort == -1) {
- if (mScheme.equals("https"))
- mPort = 443;
- else
- mPort = 80; // default
- }
- if (mScheme.equals("")) mScheme = "http";
- }
-
- public String toString() {
- String port = "";
- if ((mPort != 443 && mScheme.equals("https")) ||
- (mPort != 80 && mScheme.equals("http"))) {
- port = ":" + Integer.toString(mPort);
- }
- String authInfo = "";
- if (mAuthInfo.length() > 0) {
- authInfo = mAuthInfo + "@";
- }
-
- return mScheme + "://" + authInfo + mHost + port + mPath;
- }
-}
diff --git a/core/java/android/net/http/AndroidHttpClient.java b/core/java/android/net/http/AndroidHttpClient.java
deleted file mode 100644
index 4fb1499..0000000
--- a/core/java/android/net/http/AndroidHttpClient.java
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpEntityEnclosingRequest;
-import org.apache.http.HttpException;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpRequestInterceptor;
-import org.apache.http.HttpResponse;
-import org.apache.http.entity.AbstractHttpEntity;
-import org.apache.http.entity.ByteArrayEntity;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.ResponseHandler;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.protocol.ClientContext;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.params.HttpClientParams;
-import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.conn.scheme.PlainSocketFactory;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.conn.ssl.SSLSocketFactory;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.client.RequestWrapper;
-import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpParams;
-import org.apache.http.params.HttpProtocolParams;
-import org.apache.http.protocol.BasicHttpProcessor;
-import org.apache.http.protocol.HttpContext;
-import org.apache.http.protocol.BasicHttpContext;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-import java.net.URI;
-
-import android.util.Log;
-import android.content.ContentResolver;
-import android.provider.Settings;
-import android.text.TextUtils;
-
-/**
- * Subclass of the Apache {@link DefaultHttpClient} that is configured with
- * reasonable default settings and registered schemes for Android, and
- * also lets the user add {@link HttpRequestInterceptor} classes.
- * Don't create this directly, use the {@link #newInstance} factory method.
- *
- * <p>This client processes cookies but does not retain them by default.
- * To retain cookies, simply add a cookie store to the HttpContext:</p>
- *
- * <pre>context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);</pre>
- *
- * {@hide}
- */
-public final class AndroidHttpClient implements HttpClient {
-
- // Gzip of data shorter than this probably won't be worthwhile
- public static long DEFAULT_SYNC_MIN_GZIP_BYTES = 256;
-
- private static final String TAG = "AndroidHttpClient";
-
-
- /** Set if HTTP requests are blocked from being executed on this thread */
- private static final ThreadLocal<Boolean> sThreadBlocked =
- new ThreadLocal<Boolean>();
-
- /** Interceptor throws an exception if the executing thread is blocked */
- private static final HttpRequestInterceptor sThreadCheckInterceptor =
- new HttpRequestInterceptor() {
- public void process(HttpRequest request, HttpContext context) {
- if (sThreadBlocked.get() != null && sThreadBlocked.get()) {
- throw new RuntimeException("This thread forbids HTTP requests");
- }
- }
- };
-
- /**
- * Create a new HttpClient with reasonable defaults (which you can update).
- * @param userAgent to report in your HTTP requests.
- * @return AndroidHttpClient for you to use for all your requests.
- */
- public static AndroidHttpClient newInstance(String userAgent) {
- HttpParams params = new BasicHttpParams();
-
- // Turn off stale checking. Our connections break all the time anyway,
- // and it's not worth it to pay the penalty of checking every time.
- HttpConnectionParams.setStaleCheckingEnabled(params, false);
-
- // Default connection and socket timeout of 20 seconds. Tweak to taste.
- HttpConnectionParams.setConnectionTimeout(params, 20 * 1000);
- HttpConnectionParams.setSoTimeout(params, 20 * 1000);
- HttpConnectionParams.setSocketBufferSize(params, 8192);
-
- // Don't handle redirects -- return them to the caller. Our code
- // often wants to re-POST after a redirect, which we must do ourselves.
- HttpClientParams.setRedirecting(params, false);
-
- // Set the specified user agent and register standard protocols.
- HttpProtocolParams.setUserAgent(params, userAgent);
- SchemeRegistry schemeRegistry = new SchemeRegistry();
- schemeRegistry.register(new Scheme("http",
- PlainSocketFactory.getSocketFactory(), 80));
- schemeRegistry.register(new Scheme("https",
- SSLSocketFactory.getSocketFactory(), 443));
- ClientConnectionManager manager =
- new ThreadSafeClientConnManager(params, schemeRegistry);
-
- // We use a factory method to modify superclass initialization
- // parameters without the funny call-a-static-method dance.
- return new AndroidHttpClient(manager, params);
- }
-
- private final HttpClient delegate;
-
- private RuntimeException mLeakedException = new IllegalStateException(
- "AndroidHttpClient created and never closed");
-
- private AndroidHttpClient(ClientConnectionManager ccm, HttpParams params) {
- this.delegate = new DefaultHttpClient(ccm, params) {
- @Override
- protected BasicHttpProcessor createHttpProcessor() {
- // Add interceptor to prevent making requests from main thread.
- BasicHttpProcessor processor = super.createHttpProcessor();
- processor.addRequestInterceptor(sThreadCheckInterceptor);
- processor.addRequestInterceptor(new CurlLogger());
-
- return processor;
- }
-
- @Override
- protected HttpContext createHttpContext() {
- // Same as DefaultHttpClient.createHttpContext() minus the
- // cookie store.
- HttpContext context = new BasicHttpContext();
- context.setAttribute(
- ClientContext.AUTHSCHEME_REGISTRY,
- getAuthSchemes());
- context.setAttribute(
- ClientContext.COOKIESPEC_REGISTRY,
- getCookieSpecs());
- context.setAttribute(
- ClientContext.CREDS_PROVIDER,
- getCredentialsProvider());
- return context;
- }
- };
- }
-
- @Override
- protected void finalize() throws Throwable {
- super.finalize();
- if (mLeakedException != null) {
- Log.e(TAG, "Leak found", mLeakedException);
- mLeakedException = null;
- }
- }
-
- /**
- * Block this thread from executing HTTP requests.
- * Used to guard against HTTP requests blocking the main application thread.
- * @param blocked if HTTP requests run on this thread should be denied
- */
- public static void setThreadBlocked(boolean blocked) {
- sThreadBlocked.set(blocked);
- }
-
- /**
- * Modifies a request to indicate to the server that we would like a
- * gzipped response. (Uses the "Accept-Encoding" HTTP header.)
- * @param request the request to modify
- * @see #getUngzippedContent
- */
- public static void modifyRequestToAcceptGzipResponse(HttpRequest request) {
- request.addHeader("Accept-Encoding", "gzip");
- }
-
- /**
- * Gets the input stream from a response entity. If the entity is gzipped
- * then this will get a stream over the uncompressed data.
- *
- * @param entity the entity whose content should be read
- * @return the input stream to read from
- * @throws IOException
- */
- public static InputStream getUngzippedContent(HttpEntity entity)
- throws IOException {
- InputStream responseStream = entity.getContent();
- if (responseStream == null) return responseStream;
- Header header = entity.getContentEncoding();
- if (header == null) return responseStream;
- String contentEncoding = header.getValue();
- if (contentEncoding == null) return responseStream;
- if (contentEncoding.contains("gzip")) responseStream
- = new GZIPInputStream(responseStream);
- return responseStream;
- }
-
- /**
- * Release resources associated with this client. You must call this,
- * or significant resources (sockets and memory) may be leaked.
- */
- public void close() {
- if (mLeakedException != null) {
- getConnectionManager().shutdown();
- mLeakedException = null;
- }
- }
-
- public HttpParams getParams() {
- return delegate.getParams();
- }
-
- public ClientConnectionManager getConnectionManager() {
- return delegate.getConnectionManager();
- }
-
- public HttpResponse execute(HttpUriRequest request) throws IOException {
- return delegate.execute(request);
- }
-
- public HttpResponse execute(HttpUriRequest request, HttpContext context)
- throws IOException {
- return delegate.execute(request, context);
- }
-
- public HttpResponse execute(HttpHost target, HttpRequest request)
- throws IOException {
- return delegate.execute(target, request);
- }
-
- public HttpResponse execute(HttpHost target, HttpRequest request,
- HttpContext context) throws IOException {
- return delegate.execute(target, request, context);
- }
-
- public <T> T execute(HttpUriRequest request,
- ResponseHandler<? extends T> responseHandler)
- throws IOException, ClientProtocolException {
- return delegate.execute(request, responseHandler);
- }
-
- public <T> T execute(HttpUriRequest request,
- ResponseHandler<? extends T> responseHandler, HttpContext context)
- throws IOException, ClientProtocolException {
- return delegate.execute(request, responseHandler, context);
- }
-
- public <T> T execute(HttpHost target, HttpRequest request,
- ResponseHandler<? extends T> responseHandler) throws IOException,
- ClientProtocolException {
- return delegate.execute(target, request, responseHandler);
- }
-
- public <T> T execute(HttpHost target, HttpRequest request,
- ResponseHandler<? extends T> responseHandler, HttpContext context)
- throws IOException, ClientProtocolException {
- return delegate.execute(target, request, responseHandler, context);
- }
-
- /**
- * Compress data to send to server.
- * Creates a Http Entity holding the gzipped data.
- * The data will not be compressed if it is too short.
- * @param data The bytes to compress
- * @return Entity holding the data
- */
- public static AbstractHttpEntity getCompressedEntity(byte data[], ContentResolver resolver)
- throws IOException {
- AbstractHttpEntity entity;
- if (data.length < getMinGzipSize(resolver)) {
- entity = new ByteArrayEntity(data);
- } else {
- ByteArrayOutputStream arr = new ByteArrayOutputStream();
- OutputStream zipper = new GZIPOutputStream(arr);
- zipper.write(data);
- zipper.close();
- entity = new ByteArrayEntity(arr.toByteArray());
- entity.setContentEncoding("gzip");
- }
- return entity;
- }
-
- /**
- * Retrieves the minimum size for compressing data.
- * Shorter data will not be compressed.
- */
- public static long getMinGzipSize(ContentResolver resolver) {
- String sMinGzipBytes = Settings.Gservices.getString(resolver,
- Settings.Gservices.SYNC_MIN_GZIP_BYTES);
-
- if (!TextUtils.isEmpty(sMinGzipBytes)) {
- try {
- return Long.parseLong(sMinGzipBytes);
- } catch (NumberFormatException nfe) {
- Log.w(TAG, "Unable to parse " +
- Settings.Gservices.SYNC_MIN_GZIP_BYTES + " " +
- sMinGzipBytes, nfe);
- }
- }
- return DEFAULT_SYNC_MIN_GZIP_BYTES;
- }
-
- /* cURL logging support. */
-
- /**
- * Logging tag and level.
- */
- private static class LoggingConfiguration {
-
- private final String tag;
- private final int level;
-
- private LoggingConfiguration(String tag, int level) {
- this.tag = tag;
- this.level = level;
- }
-
- /**
- * Returns true if logging is turned on for this configuration.
- */
- private boolean isLoggable() {
- return Log.isLoggable(tag, level);
- }
-
- /**
- * Returns true if auth logging is turned on for this configuration.
- */
- private boolean isAuthLoggable() {
- return Log.isLoggable(tag + "-auth", level);
- }
-
- /**
- * Prints a message using this configuration.
- */
- private void println(String message) {
- Log.println(level, tag, message);
- }
- }
-
- /** cURL logging configuration. */
- private volatile LoggingConfiguration curlConfiguration;
-
- /**
- * Enables cURL request logging for this client.
- *
- * @param name to log messages with
- * @param level at which to log messages (see {@link android.util.Log})
- */
- public void enableCurlLogging(String name, int level) {
- if (name == null) {
- throw new NullPointerException("name");
- }
- if (level < Log.VERBOSE || level > Log.ASSERT) {
- throw new IllegalArgumentException("Level is out of range ["
- + Log.VERBOSE + ".." + Log.ASSERT + "]");
- }
-
- curlConfiguration = new LoggingConfiguration(name, level);
- }
-
- /**
- * Disables cURL logging for this client.
- */
- public void disableCurlLogging() {
- curlConfiguration = null;
- }
-
- /**
- * Logs cURL commands equivalent to requests.
- */
- private class CurlLogger implements HttpRequestInterceptor {
- public void process(HttpRequest request, HttpContext context)
- throws HttpException, IOException {
- LoggingConfiguration configuration = curlConfiguration;
- if (configuration != null
- && configuration.isLoggable()
- && request instanceof HttpUriRequest) {
- configuration.println(toCurl((HttpUriRequest) request,
- configuration.isAuthLoggable()));
- }
- }
- }
-
- /**
- * Generates a cURL command equivalent to the given request.
- */
- private static String toCurl(HttpUriRequest request, boolean logAuthToken) throws IOException {
- StringBuilder builder = new StringBuilder();
-
- builder.append("curl ");
-
- for (Header header: request.getAllHeaders()) {
- if (!logAuthToken
- && (header.getName().equals("Authorization") ||
- header.getName().equals("Cookie"))) {
- continue;
- }
- builder.append("--header \"");
- builder.append(header.toString().trim());
- builder.append("\" ");
- }
-
- URI uri = request.getURI();
-
- // If this is a wrapped request, use the URI from the original
- // request instead. getURI() on the wrapper seems to return a
- // relative URI. We want an absolute URI.
- if (request instanceof RequestWrapper) {
- HttpRequest original = ((RequestWrapper) request).getOriginal();
- if (original instanceof HttpUriRequest) {
- uri = ((HttpUriRequest) original).getURI();
- }
- }
-
- builder.append("\"");
- builder.append(uri);
- builder.append("\"");
-
- if (request instanceof HttpEntityEnclosingRequest) {
- HttpEntityEnclosingRequest entityRequest =
- (HttpEntityEnclosingRequest) request;
- HttpEntity entity = entityRequest.getEntity();
- if (entity != null && entity.isRepeatable()) {
- if (entity.getContentLength() < 1024) {
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
- entity.writeTo(stream);
- String entityString = stream.toString();
-
- // TODO: Check the content type, too.
- builder.append(" --data-ascii \"")
- .append(entityString)
- .append("\"");
- } else {
- builder.append(" [TOO MUCH DATA TO INCLUDE]");
- }
- }
- }
-
- return builder.toString();
- }
-}
diff --git a/core/java/android/net/http/AndroidHttpClientConnection.java b/core/java/android/net/http/AndroidHttpClientConnection.java
deleted file mode 100644
index eb96679..0000000
--- a/core/java/android/net/http/AndroidHttpClientConnection.java
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import org.apache.http.Header;
-
-import org.apache.http.HttpConnection;
-import org.apache.http.HttpClientConnection;
-import org.apache.http.HttpConnectionMetrics;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpEntityEnclosingRequest;
-import org.apache.http.HttpException;
-import org.apache.http.HttpInetConnection;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpResponseFactory;
-import org.apache.http.NoHttpResponseException;
-import org.apache.http.StatusLine;
-import org.apache.http.entity.BasicHttpEntity;
-import org.apache.http.entity.ContentLengthStrategy;
-import org.apache.http.impl.DefaultHttpResponseFactory;
-import org.apache.http.impl.HttpConnectionMetricsImpl;
-import org.apache.http.impl.entity.EntitySerializer;
-import org.apache.http.impl.entity.StrictContentLengthStrategy;
-import org.apache.http.impl.io.ChunkedInputStream;
-import org.apache.http.impl.io.ContentLengthInputStream;
-import org.apache.http.impl.io.HttpRequestWriter;
-import org.apache.http.impl.io.IdentityInputStream;
-import org.apache.http.impl.io.SocketInputBuffer;
-import org.apache.http.impl.io.SocketOutputBuffer;
-import org.apache.http.io.HttpMessageWriter;
-import org.apache.http.io.SessionInputBuffer;
-import org.apache.http.io.SessionOutputBuffer;
-import org.apache.http.message.BasicLineParser;
-import org.apache.http.message.ParserCursor;
-import org.apache.http.params.CoreConnectionPNames;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpParams;
-import org.apache.http.ParseException;
-import org.apache.http.util.CharArrayBuffer;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.SocketException;
-
-/**
- * A alternate class for (@link DefaultHttpClientConnection).
- * It has better performance than DefaultHttpClientConnection
- *
- * {@hide}
- */
-public class AndroidHttpClientConnection
- implements HttpInetConnection, HttpConnection {
-
- private SessionInputBuffer inbuffer = null;
- private SessionOutputBuffer outbuffer = null;
- private int maxHeaderCount;
- // store CoreConnectionPNames.MAX_LINE_LENGTH for performance
- private int maxLineLength;
-
- private final EntitySerializer entityserializer;
-
- private HttpMessageWriter requestWriter = null;
- private HttpConnectionMetricsImpl metrics = null;
- private volatile boolean open;
- private Socket socket = null;
-
- public AndroidHttpClientConnection() {
- this.entityserializer = new EntitySerializer(
- new StrictContentLengthStrategy());
- }
-
- /**
- * Bind socket and set HttpParams to AndroidHttpClientConnection
- * @param socket outgoing socket
- * @param params HttpParams
- * @throws IOException
- */
- public void bind(
- final Socket socket,
- final HttpParams params) throws IOException {
- if (socket == null) {
- throw new IllegalArgumentException("Socket may not be null");
- }
- if (params == null) {
- throw new IllegalArgumentException("HTTP parameters may not be null");
- }
- assertNotOpen();
- socket.setTcpNoDelay(HttpConnectionParams.getTcpNoDelay(params));
- socket.setSoTimeout(HttpConnectionParams.getSoTimeout(params));
-
- int linger = HttpConnectionParams.getLinger(params);
- if (linger >= 0) {
- socket.setSoLinger(linger > 0, linger);
- }
- this.socket = socket;
-
- int buffersize = HttpConnectionParams.getSocketBufferSize(params);
- this.inbuffer = new SocketInputBuffer(socket, buffersize, params);
- this.outbuffer = new SocketOutputBuffer(socket, buffersize, params);
-
- maxHeaderCount = params.getIntParameter(
- CoreConnectionPNames.MAX_HEADER_COUNT, -1);
- maxLineLength = params.getIntParameter(
- CoreConnectionPNames.MAX_LINE_LENGTH, -1);
-
- this.requestWriter = new HttpRequestWriter(outbuffer, null, params);
-
- this.metrics = new HttpConnectionMetricsImpl(
- inbuffer.getMetrics(),
- outbuffer.getMetrics());
-
- this.open = true;
- }
-
- @Override
- public String toString() {
- StringBuilder buffer = new StringBuilder();
- buffer.append(getClass().getSimpleName()).append("[");
- if (isOpen()) {
- buffer.append(getRemotePort());
- } else {
- buffer.append("closed");
- }
- buffer.append("]");
- return buffer.toString();
- }
-
-
- private void assertNotOpen() {
- if (this.open) {
- throw new IllegalStateException("Connection is already open");
- }
- }
-
- private void assertOpen() {
- if (!this.open) {
- throw new IllegalStateException("Connection is not open");
- }
- }
-
- public boolean isOpen() {
- // to make this method useful, we want to check if the socket is connected
- return (this.open && this.socket != null && this.socket.isConnected());
- }
-
- public InetAddress getLocalAddress() {
- if (this.socket != null) {
- return this.socket.getLocalAddress();
- } else {
- return null;
- }
- }
-
- public int getLocalPort() {
- if (this.socket != null) {
- return this.socket.getLocalPort();
- } else {
- return -1;
- }
- }
-
- public InetAddress getRemoteAddress() {
- if (this.socket != null) {
- return this.socket.getInetAddress();
- } else {
- return null;
- }
- }
-
- public int getRemotePort() {
- if (this.socket != null) {
- return this.socket.getPort();
- } else {
- return -1;
- }
- }
-
- public void setSocketTimeout(int timeout) {
- assertOpen();
- if (this.socket != null) {
- try {
- this.socket.setSoTimeout(timeout);
- } catch (SocketException ignore) {
- // It is not quite clear from the original documentation if there are any
- // other legitimate cases for a socket exception to be thrown when setting
- // SO_TIMEOUT besides the socket being already closed
- }
- }
- }
-
- public int getSocketTimeout() {
- if (this.socket != null) {
- try {
- return this.socket.getSoTimeout();
- } catch (SocketException ignore) {
- return -1;
- }
- } else {
- return -1;
- }
- }
-
- public void shutdown() throws IOException {
- this.open = false;
- Socket tmpsocket = this.socket;
- if (tmpsocket != null) {
- tmpsocket.close();
- }
- }
-
- public void close() throws IOException {
- if (!this.open) {
- return;
- }
- this.open = false;
- doFlush();
- try {
- try {
- this.socket.shutdownOutput();
- } catch (IOException ignore) {
- }
- try {
- this.socket.shutdownInput();
- } catch (IOException ignore) {
- }
- } catch (UnsupportedOperationException ignore) {
- // if one isn't supported, the other one isn't either
- }
- this.socket.close();
- }
-
- /**
- * Sends the request line and all headers over the connection.
- * @param request the request whose headers to send.
- * @throws HttpException
- * @throws IOException
- */
- public void sendRequestHeader(final HttpRequest request)
- throws HttpException, IOException {
- if (request == null) {
- throw new IllegalArgumentException("HTTP request may not be null");
- }
- assertOpen();
- this.requestWriter.write(request);
- this.metrics.incrementRequestCount();
- }
-
- /**
- * Sends the request entity over the connection.
- * @param request the request whose entity to send.
- * @throws HttpException
- * @throws IOException
- */
- public void sendRequestEntity(final HttpEntityEnclosingRequest request)
- throws HttpException, IOException {
- if (request == null) {
- throw new IllegalArgumentException("HTTP request may not be null");
- }
- assertOpen();
- if (request.getEntity() == null) {
- return;
- }
- this.entityserializer.serialize(
- this.outbuffer,
- request,
- request.getEntity());
- }
-
- protected void doFlush() throws IOException {
- this.outbuffer.flush();
- }
-
- public void flush() throws IOException {
- assertOpen();
- doFlush();
- }
-
- /**
- * Parses the response headers and adds them to the
- * given {@code headers} object, and returns the response StatusLine
- * @param headers store parsed header to headers.
- * @throws IOException
- * @return StatusLine
- * @see HttpClientConnection#receiveResponseHeader()
- */
- public StatusLine parseResponseHeader(Headers headers)
- throws IOException, ParseException {
- assertOpen();
-
- CharArrayBuffer current = new CharArrayBuffer(64);
-
- if (inbuffer.readLine(current) == -1) {
- throw new NoHttpResponseException("The target server failed to respond");
- }
-
- // Create the status line from the status string
- StatusLine statusline = BasicLineParser.DEFAULT.parseStatusLine(
- current, new ParserCursor(0, current.length()));
-
- if (HttpLog.LOGV) HttpLog.v("read: " + statusline);
- int statusCode = statusline.getStatusCode();
-
- // Parse header body
- CharArrayBuffer previous = null;
- int headerNumber = 0;
- while(true) {
- if (current == null) {
- current = new CharArrayBuffer(64);
- } else {
- // This must be he buffer used to parse the status
- current.clear();
- }
- int l = inbuffer.readLine(current);
- if (l == -1 || current.length() < 1) {
- break;
- }
- // Parse the header name and value
- // Check for folded headers first
- // Detect LWS-char see HTTP/1.0 or HTTP/1.1 Section 2.2
- // discussion on folded headers
- char first = current.charAt(0);
- if ((first == ' ' || first == '\t') && previous != null) {
- // we have continuation folded header
- // so append value
- int start = 0;
- int length = current.length();
- while (start < length) {
- char ch = current.charAt(start);
- if (ch != ' ' && ch != '\t') {
- break;
- }
- start++;
- }
- if (maxLineLength > 0 &&
- previous.length() + 1 + current.length() - start >
- maxLineLength) {
- throw new IOException("Maximum line length limit exceeded");
- }
- previous.append(' ');
- previous.append(current, start, current.length() - start);
- } else {
- if (previous != null) {
- headers.parseHeader(previous);
- }
- headerNumber++;
- previous = current;
- current = null;
- }
- if (maxHeaderCount > 0 && headerNumber >= maxHeaderCount) {
- throw new IOException("Maximum header count exceeded");
- }
- }
-
- if (previous != null) {
- headers.parseHeader(previous);
- }
-
- if (statusCode >= 200) {
- this.metrics.incrementResponseCount();
- }
- return statusline;
- }
-
- /**
- * Return the next response entity.
- * @param headers contains values for parsing entity
- * @see HttpClientConnection#receiveResponseEntity(HttpResponse response)
- */
- public HttpEntity receiveResponseEntity(final Headers headers) {
- assertOpen();
- BasicHttpEntity entity = new BasicHttpEntity();
-
- long len = determineLength(headers);
- if (len == ContentLengthStrategy.CHUNKED) {
- entity.setChunked(true);
- entity.setContentLength(-1);
- entity.setContent(new ChunkedInputStream(inbuffer));
- } else if (len == ContentLengthStrategy.IDENTITY) {
- entity.setChunked(false);
- entity.setContentLength(-1);
- entity.setContent(new IdentityInputStream(inbuffer));
- } else {
- entity.setChunked(false);
- entity.setContentLength(len);
- entity.setContent(new ContentLengthInputStream(inbuffer, len));
- }
-
- String contentTypeHeader = headers.getContentType();
- if (contentTypeHeader != null) {
- entity.setContentType(contentTypeHeader);
- }
- String contentEncodingHeader = headers.getContentEncoding();
- if (contentEncodingHeader != null) {
- entity.setContentEncoding(contentEncodingHeader);
- }
-
- return entity;
- }
-
- private long determineLength(final Headers headers) {
- long transferEncoding = headers.getTransferEncoding();
- // We use Transfer-Encoding if present and ignore Content-Length.
- // RFC2616, 4.4 item number 3
- if (transferEncoding < Headers.NO_TRANSFER_ENCODING) {
- return transferEncoding;
- } else {
- long contentlen = headers.getContentLength();
- if (contentlen > Headers.NO_CONTENT_LENGTH) {
- return contentlen;
- } else {
- return ContentLengthStrategy.IDENTITY;
- }
- }
- }
-
- /**
- * Checks whether this connection has gone down.
- * Network connections may get closed during some time of inactivity
- * for several reasons. The next time a read is attempted on such a
- * connection it will throw an IOException.
- * This method tries to alleviate this inconvenience by trying to
- * find out if a connection is still usable. Implementations may do
- * that by attempting a read with a very small timeout. Thus this
- * method may block for a small amount of time before returning a result.
- * It is therefore an <i>expensive</i> operation.
- *
- * @return <code>true</code> if attempts to use this connection are
- * likely to succeed, or <code>false</code> if they are likely
- * to fail and this connection should be closed
- */
- public boolean isStale() {
- assertOpen();
- try {
- this.inbuffer.isDataAvailable(1);
- return false;
- } catch (IOException ex) {
- return true;
- }
- }
-
- /**
- * Returns a collection of connection metrcis
- * @return HttpConnectionMetrics
- */
- public HttpConnectionMetrics getMetrics() {
- return this.metrics;
- }
-}
diff --git a/core/java/android/net/http/CertificateChainValidator.java b/core/java/android/net/http/CertificateChainValidator.java
deleted file mode 100644
index b7f7368..0000000
--- a/core/java/android/net/http/CertificateChainValidator.java
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import android.os.SystemClock;
-
-import java.io.IOException;
-
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.X509Certificate;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-
-import java.util.Arrays;
-import java.util.Date;
-import java.util.Enumeration;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-
-import org.apache.http.HttpHost;
-
-import org.bouncycastle.asn1.x509.X509Name;
-
-/**
- * Class responsible for all server certificate validation functionality
- *
- * {@hide}
- */
-class CertificateChainValidator {
-
- private static long sTotal = 0;
- private static long sTotalReused = 0;
-
- /**
- * The singleton instance of the certificate chain validator
- */
- private static CertificateChainValidator sInstance;
-
- /**
- * Default trust manager (used to perform CA certificate validation)
- */
- private X509TrustManager mDefaultTrustManager;
-
- /**
- * @return The singleton instance of the certificator chain validator
- */
- public static CertificateChainValidator getInstance() {
- if (sInstance == null) {
- sInstance = new CertificateChainValidator();
- }
-
- return sInstance;
- }
-
- /**
- * Creates a new certificate chain validator. This is a pivate constructor.
- * If you need a Certificate chain validator, call getInstance().
- */
- private CertificateChainValidator() {
- try {
- TrustManagerFactory trustManagerFactory
- = TrustManagerFactory.getInstance("X509");
- trustManagerFactory.init((KeyStore)null);
- TrustManager[] trustManagers =
- trustManagerFactory.getTrustManagers();
- if (trustManagers != null && trustManagers.length > 0) {
- for (TrustManager trustManager : trustManagers) {
- if (trustManager instanceof X509TrustManager) {
- mDefaultTrustManager = (X509TrustManager)(trustManager);
- break;
- }
- }
- }
- } catch (Exception exc) {
- if (HttpLog.LOGV) {
- HttpLog.v("CertificateChainValidator():" +
- " failed to initialize the trust manager");
- }
- }
- }
-
- /**
- * Performs the handshake and server certificates validation
- * @param sslSocket The secure connection socket
- * @param domain The website domain
- * @return An SSL error object if there is an error and null otherwise
- */
- public SslError doHandshakeAndValidateServerCertificates(
- HttpsConnection connection, SSLSocket sslSocket, String domain)
- throws SSLHandshakeException, IOException {
-
- ++sTotal;
-
- SSLContext sslContext = HttpsConnection.getContext();
- if (sslContext == null) {
- closeSocketThrowException(sslSocket, "SSL context is null");
- }
-
- X509Certificate[] serverCertificates = null;
-
- long sessionBeforeHandshakeLastAccessedTime = 0;
- byte[] sessionBeforeHandshakeId = null;
-
- SSLSession sessionAfterHandshake = null;
-
- synchronized(sslContext) {
- // get SSL session before the handshake
- SSLSession sessionBeforeHandshake =
- getSSLSession(sslContext, connection.getHost());
- if (sessionBeforeHandshake != null) {
- sessionBeforeHandshakeLastAccessedTime =
- sessionBeforeHandshake.getLastAccessedTime();
-
- sessionBeforeHandshakeId =
- sessionBeforeHandshake.getId();
- }
-
- // start handshake, close the socket if we fail
- try {
- sslSocket.setUseClientMode(true);
- sslSocket.startHandshake();
- } catch (IOException e) {
- closeSocketThrowException(
- sslSocket, e.getMessage(),
- "failed to perform SSL handshake");
- }
-
- // retrieve the chain of the server peer certificates
- Certificate[] peerCertificates =
- sslSocket.getSession().getPeerCertificates();
-
- if (peerCertificates == null || peerCertificates.length <= 0) {
- closeSocketThrowException(
- sslSocket, "failed to retrieve peer certificates");
- } else {
- serverCertificates =
- new X509Certificate[peerCertificates.length];
- for (int i = 0; i < peerCertificates.length; ++i) {
- serverCertificates[i] =
- (X509Certificate)(peerCertificates[i]);
- }
-
- // update the SSL certificate associated with the connection
- if (connection != null) {
- if (serverCertificates[0] != null) {
- connection.setCertificate(
- new SslCertificate(serverCertificates[0]));
- }
- }
- }
-
- // get SSL session after the handshake
- sessionAfterHandshake =
- getSSLSession(sslContext, connection.getHost());
- }
-
- if (sessionBeforeHandshakeLastAccessedTime != 0 &&
- sessionAfterHandshake != null &&
- Arrays.equals(
- sessionBeforeHandshakeId, sessionAfterHandshake.getId()) &&
- sessionBeforeHandshakeLastAccessedTime <
- sessionAfterHandshake.getLastAccessedTime()) {
-
- if (HttpLog.LOGV) {
- HttpLog.v("SSL session was reused: total reused: "
- + sTotalReused
- + " out of total of: " + sTotal);
-
- ++sTotalReused;
- }
-
- // no errors!!!
- return null;
- }
-
- // check if the first certificate in the chain is for this site
- X509Certificate currCertificate = serverCertificates[0];
- if (currCertificate == null) {
- closeSocketThrowException(
- sslSocket, "certificate for this site is null");
- } else {
- if (!DomainNameChecker.match(currCertificate, domain)) {
- String errorMessage = "certificate not for this host: " + domain;
-
- if (HttpLog.LOGV) {
- HttpLog.v(errorMessage);
- }
-
- sslSocket.getSession().invalidate();
- return new SslError(
- SslError.SSL_IDMISMATCH, currCertificate);
- }
- }
-
- //
- // first, we validate the chain using the standard validation
- // solution; if we do not find any errors, we are done; if we
- // fail the standard validation, we re-validate again below,
- // this time trying to retrieve any individual errors we can
- // report back to the user.
- //
- try {
- synchronized (mDefaultTrustManager) {
- mDefaultTrustManager.checkServerTrusted(
- serverCertificates, "RSA");
-
- // no errors!!!
- return null;
- }
- } catch (CertificateException e) {
- if (HttpLog.LOGV) {
- HttpLog.v(
- "failed to pre-validate the certificate chain, error: " +
- e.getMessage());
- }
- }
-
- sslSocket.getSession().invalidate();
-
- SslError error = null;
-
- // we check the root certificate separately from the rest of the
- // chain; this is because we need to know what certificate in
- // the chain resulted in an error if any
- currCertificate =
- serverCertificates[serverCertificates.length - 1];
- if (currCertificate == null) {
- closeSocketThrowException(
- sslSocket, "root certificate is null");
- }
-
- // check if the last certificate in the chain (root) is trusted
- X509Certificate[] rootCertificateChain = { currCertificate };
- try {
- synchronized (mDefaultTrustManager) {
- mDefaultTrustManager.checkServerTrusted(
- rootCertificateChain, "RSA");
- }
- } catch (CertificateExpiredException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "root certificate has expired";
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v(errorMessage);
- }
-
- error = new SslError(
- SslError.SSL_EXPIRED, currCertificate);
- } catch (CertificateNotYetValidException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "root certificate not valid yet";
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v(errorMessage);
- }
-
- error = new SslError(
- SslError.SSL_NOTYETVALID, currCertificate);
- } catch (CertificateException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "root certificate not trusted";
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v(errorMessage);
- }
-
- return new SslError(
- SslError.SSL_UNTRUSTED, currCertificate);
- }
-
- // Then go through the certificate chain checking that each
- // certificate trusts the next and that each certificate is
- // within its valid date range. Walk the chain in the order
- // from the CA to the end-user
- X509Certificate prevCertificate =
- serverCertificates[serverCertificates.length - 1];
-
- for (int i = serverCertificates.length - 2; i >= 0; --i) {
- currCertificate = serverCertificates[i];
-
- // if a certificate is null, we cannot verify the chain
- if (currCertificate == null) {
- closeSocketThrowException(
- sslSocket, "null certificate in the chain");
- }
-
- // verify if trusted by chain
- if (!prevCertificate.getSubjectDN().equals(
- currCertificate.getIssuerDN())) {
- String errorMessage = "not trusted by chain";
-
- if (HttpLog.LOGV) {
- HttpLog.v(errorMessage);
- }
-
- return new SslError(
- SslError.SSL_UNTRUSTED, currCertificate);
- }
-
- try {
- currCertificate.verify(prevCertificate.getPublicKey());
- } catch (GeneralSecurityException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "not trusted by chain";
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v(errorMessage);
- }
-
- return new SslError(
- SslError.SSL_UNTRUSTED, currCertificate);
- }
-
- // verify if the dates are valid
- try {
- currCertificate.checkValidity();
- } catch (CertificateExpiredException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "certificate expired";
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v(errorMessage);
- }
-
- if (error == null ||
- error.getPrimaryError() < SslError.SSL_EXPIRED) {
- error = new SslError(
- SslError.SSL_EXPIRED, currCertificate);
- }
- } catch (CertificateNotYetValidException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "certificate not valid yet";
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v(errorMessage);
- }
-
- if (error == null ||
- error.getPrimaryError() < SslError.SSL_NOTYETVALID) {
- error = new SslError(
- SslError.SSL_NOTYETVALID, currCertificate);
- }
- }
-
- prevCertificate = currCertificate;
- }
-
- // if we do not have an error to report back to the user, throw
- // an exception (a generic error will be reported instead)
- if (error == null) {
- closeSocketThrowException(
- sslSocket,
- "failed to pre-validate the certificate chain due to a non-standard error");
- }
-
- return error;
- }
-
- private void closeSocketThrowException(
- SSLSocket socket, String errorMessage, String defaultErrorMessage)
- throws SSLHandshakeException, IOException {
- closeSocketThrowException(
- socket, errorMessage != null ? errorMessage : defaultErrorMessage);
- }
-
- private void closeSocketThrowException(SSLSocket socket, String errorMessage)
- throws SSLHandshakeException, IOException {
- if (HttpLog.LOGV) {
- HttpLog.v("validation error: " + errorMessage);
- }
-
- if (socket != null) {
- SSLSession session = socket.getSession();
- if (session != null) {
- session.invalidate();
- }
-
- socket.close();
- }
-
- throw new SSLHandshakeException(errorMessage);
- }
-
- /**
- * @param sslContext The SSL context shared accross all the SSL sessions
- * @param host The host associated with the session
- * @return A suitable SSL session from the SSL context
- */
- private SSLSession getSSLSession(SSLContext sslContext, HttpHost host) {
- if (sslContext != null && host != null) {
- Enumeration en = sslContext.getClientSessionContext().getIds();
- while (en.hasMoreElements()) {
- byte[] id = (byte[]) en.nextElement();
- if (id != null) {
- SSLSession session =
- sslContext.getClientSessionContext().getSession(id);
- if (session.isValid() &&
- host.getHostName().equals(session.getPeerHost()) &&
- host.getPort() == session.getPeerPort()) {
- return session;
- }
- }
- }
- }
-
- return null;
- }
-}
diff --git a/core/java/android/net/http/CertificateValidatorCache.java b/core/java/android/net/http/CertificateValidatorCache.java
deleted file mode 100644
index 54a1dbe..0000000
--- a/core/java/android/net/http/CertificateValidatorCache.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import android.os.SystemClock;
-
-import android.security.Sha1MessageDigest;
-
-import java.security.cert.Certificate;
-import java.security.cert.CertificateFactory;
-import java.security.cert.CertPath;
-import java.security.GeneralSecurityException;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Random;
-
-
-/**
- * Validator cache used to speed-up certificate chain validation. The idea is
- * to keep each secure domain name associated with a cryptographically secure
- * hash of the certificate chain successfully used to validate the domain. If
- * we establish connection with the domain more than once and each time receive
- * the same list of certificates, we do not have to re-validate.
- *
- * {@hide}
- */
-class CertificateValidatorCache {
-
- // TODO: debug only!
- public static long mSave = 0;
- public static long mCost = 0;
- // TODO: debug only!
-
- /**
- * The cache-entry lifetime in milliseconds (here, 10 minutes)
- */
- private static final long CACHE_ENTRY_LIFETIME = 10 * 60 * 1000;
-
- /**
- * The certificate factory
- */
- private static CertificateFactory sCertificateFactory;
-
- /**
- * The certificate validator cache map (domain to a cache entry)
- */
- private HashMap<Integer, CacheEntry> mCacheMap;
-
- /**
- * Random salt
- */
- private int mBigScrew;
-
- /**
- * @param certificate The array of server certificates to compute a
- * secure hash from
- * @return The secure hash computed from server certificates
- */
- public static byte[] secureHash(Certificate[] certificates) {
- byte[] secureHash = null;
-
- // TODO: debug only!
- long beg = SystemClock.uptimeMillis();
- // TODO: debug only!
-
- if (certificates != null && certificates.length != 0) {
- byte[] encodedCertPath = null;
- try {
- synchronized (CertificateValidatorCache.class) {
- if (sCertificateFactory == null) {
- try {
- sCertificateFactory =
- CertificateFactory.getInstance("X.509");
- } catch(GeneralSecurityException e) {
- if (HttpLog.LOGV) {
- HttpLog.v("CertificateValidatorCache:" +
- " failed to create the certificate factory");
- }
- }
- }
- }
-
- CertPath certPath =
- sCertificateFactory.generateCertPath(Arrays.asList(certificates));
- if (certPath != null) {
- encodedCertPath = certPath.getEncoded();
- if (encodedCertPath != null) {
- Sha1MessageDigest messageDigest =
- new Sha1MessageDigest();
- secureHash = messageDigest.digest(encodedCertPath);
- }
- }
- } catch (GeneralSecurityException e) {}
- }
-
- // TODO: debug only!
- long end = SystemClock.uptimeMillis();
- mCost += (end - beg);
- // TODO: debug only!
-
- return secureHash;
- }
-
- /**
- * Creates a new certificate-validator cache
- */
- public CertificateValidatorCache() {
- Random random = new Random();
- mBigScrew = random.nextInt();
-
- mCacheMap = new HashMap<Integer, CacheEntry>();
- }
-
- /**
- * @param domain The domain to check against
- * @param secureHash The secure hash to check against
- * @return True iff there is a valid (not expired) cache entry
- * associated with the domain and the secure hash
- */
- public boolean has(String domain, byte[] secureHash) {
- boolean rval = false;
-
- if (domain != null && domain.length() != 0) {
- if (secureHash != null && secureHash.length != 0) {
- CacheEntry cacheEntry = (CacheEntry)mCacheMap.get(
- new Integer(mBigScrew ^ domain.hashCode()));
- if (cacheEntry != null) {
- if (!cacheEntry.expired()) {
- rval = cacheEntry.has(domain, secureHash);
- // TODO: debug only!
- if (rval) {
- mSave += cacheEntry.mSave;
- }
- // TODO: debug only!
- } else {
- mCacheMap.remove(cacheEntry);
- }
- }
- }
- }
-
- return rval;
- }
-
- /**
- * Adds the (domain, secureHash) tuple to the cache
- * @param domain The domain to be added to the cache
- * @param secureHash The secure hash to be added to the cache
- * @return True iff succeeds
- */
- public boolean put(String domain, byte[] secureHash, long save) {
- if (domain != null && domain.length() != 0) {
- if (secureHash != null && secureHash.length != 0) {
- mCacheMap.put(
- new Integer(mBigScrew ^ domain.hashCode()),
- new CacheEntry(domain, secureHash, save));
-
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Certificate-validator cache entry. We have one per domain
- */
- private class CacheEntry {
-
- /**
- * The hash associated with this cache entry
- */
- private byte[] mHash;
-
- /**
- * The time associated with this cache entry
- */
- private long mTime;
-
- // TODO: debug only!
- public long mSave;
- // TODO: debug only!
-
- /**
- * The host associated with this cache entry
- */
- private String mDomain;
-
- /**
- * Creates a new certificate-validator cache entry
- * @param domain The domain to be associated with this cache entry
- * @param secureHash The secure hash to be associated with this cache
- * entry
- */
- public CacheEntry(String domain, byte[] secureHash, long save) {
- mDomain = domain;
- mHash = secureHash;
- // TODO: debug only!
- mSave = save;
- // TODO: debug only!
- mTime = SystemClock.uptimeMillis();
- }
-
- /**
- * @return True iff the cache item has expired
- */
- public boolean expired() {
- return CACHE_ENTRY_LIFETIME < SystemClock.uptimeMillis() - mTime;
- }
-
- /**
- * @param domain The domain to check
- * @param secureHash The secure hash to check
- * @return True iff the given domain and hash match those associated
- * with this entry
- */
- public boolean has(String domain, byte[] secureHash) {
- if (domain != null && 0 < domain.length()) {
- if (!mDomain.equals(domain)) {
- return false;
- }
- }
-
- int hashLength = secureHash.length;
- if (secureHash != null && 0 < hashLength) {
- if (hashLength == mHash.length) {
- for (int i = 0; i < hashLength; ++i) {
- if (secureHash[i] != mHash[i]) {
- return false;
- }
- }
- return true;
- }
- }
-
- return false;
- }
- }
-};
diff --git a/core/java/android/net/http/CharArrayBuffers.java b/core/java/android/net/http/CharArrayBuffers.java
deleted file mode 100644
index 77d45f6..0000000
--- a/core/java/android/net/http/CharArrayBuffers.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import org.apache.http.util.CharArrayBuffer;
-import org.apache.http.protocol.HTTP;
-
-/**
- * Utility methods for working on CharArrayBuffers.
- *
- * {@hide}
- */
-class CharArrayBuffers {
-
- static final char uppercaseAddon = 'a' - 'A';
-
- /**
- * Returns true if the buffer contains the given string. Ignores leading
- * whitespace and case.
- *
- * @param buffer to search
- * @param beginIndex index at which we should start
- * @param str to search for
- */
- static boolean containsIgnoreCaseTrimmed(CharArrayBuffer buffer,
- int beginIndex, final String str) {
- int len = buffer.length();
- char[] chars = buffer.buffer();
- while (beginIndex < len && HTTP.isWhitespace(chars[beginIndex])) {
- beginIndex++;
- }
- int size = str.length();
- boolean ok = len >= beginIndex + size;
- for (int j=0; ok && (j<size); j++) {
- char a = chars[beginIndex+j];
- char b = str.charAt(j);
- if (a != b) {
- a = toLower(a);
- b = toLower(b);
- ok = a == b;
- }
- }
- return ok;
- }
-
- /**
- * Returns index of first occurence ch. Lower cases characters leading up
- * to first occurrence of ch.
- */
- static int setLowercaseIndexOf(CharArrayBuffer buffer, final int ch) {
-
- int beginIndex = 0;
- int endIndex = buffer.length();
- char[] chars = buffer.buffer();
-
- for (int i = beginIndex; i < endIndex; i++) {
- char current = chars[i];
- if (current == ch) {
- return i;
- } else if (current >= 'A' && current <= 'Z'){
- // make lower case
- current += uppercaseAddon;
- chars[i] = current;
- }
- }
- return -1;
- }
-
- private static char toLower(char c) {
- if (c >= 'A' && c <= 'Z'){
- c += uppercaseAddon;
- }
- return c;
- }
-}
diff --git a/core/java/android/net/http/Connection.java b/core/java/android/net/http/Connection.java
deleted file mode 100644
index 563634f..0000000
--- a/core/java/android/net/http/Connection.java
+++ /dev/null
@@ -1,528 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import android.content.Context;
-import android.os.SystemClock;
-
-import java.io.IOException;
-import java.net.UnknownHostException;
-import java.util.ListIterator;
-import java.util.LinkedList;
-
-import javax.net.ssl.SSLHandshakeException;
-
-import org.apache.http.ConnectionReuseStrategy;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpException;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpVersion;
-import org.apache.http.ParseException;
-import org.apache.http.ProtocolVersion;
-import org.apache.http.protocol.ExecutionContext;
-import org.apache.http.protocol.HttpContext;
-import org.apache.http.protocol.BasicHttpContext;
-
-/**
- * {@hide}
- */
-abstract class Connection {
-
- /**
- * Allow a TCP connection 60 idle seconds before erroring out
- */
- static final int SOCKET_TIMEOUT = 60000;
-
- private static final int SEND = 0;
- private static final int READ = 1;
- private static final int DRAIN = 2;
- private static final int DONE = 3;
- private static final String[] states = {"SEND", "READ", "DRAIN", "DONE"};
-
- Context mContext;
-
- /** The low level connection */
- protected AndroidHttpClientConnection mHttpClientConnection = null;
-
- /**
- * The server SSL certificate associated with this connection
- * (null if the connection is not secure)
- * It would be nice to store the whole certificate chain, but
- * we want to keep things as light-weight as possible
- */
- protected SslCertificate mCertificate = null;
-
- /**
- * The host this connection is connected to. If using proxy,
- * this is set to the proxy address
- */
- HttpHost mHost;
-
- /** true if the connection can be reused for sending more requests */
- private boolean mCanPersist;
-
- /** context required by ConnectionReuseStrategy. */
- private HttpContext mHttpContext;
-
- /** set when cancelled */
- private static int STATE_NORMAL = 0;
- private static int STATE_CANCEL_REQUESTED = 1;
- private int mActive = STATE_NORMAL;
-
- /** The number of times to try to re-connect (if connect fails). */
- private final static int RETRY_REQUEST_LIMIT = 2;
-
- private static final int MIN_PIPE = 2;
- private static final int MAX_PIPE = 3;
-
- /**
- * Doesn't seem to exist anymore in the new HTTP client, so copied here.
- */
- private static final String HTTP_CONNECTION = "http.connection";
-
- RequestQueue.ConnectionManager mConnectionManager;
- RequestFeeder mRequestFeeder;
-
- /**
- * Buffer for feeding response blocks to webkit. One block per
- * connection reduces memory churn.
- */
- private byte[] mBuf;
-
- protected Connection(Context context, HttpHost host,
- RequestQueue.ConnectionManager connectionManager,
- RequestFeeder requestFeeder) {
- mContext = context;
- mHost = host;
- mConnectionManager = connectionManager;
- mRequestFeeder = requestFeeder;
-
- mCanPersist = false;
- mHttpContext = new BasicHttpContext(null);
- }
-
- HttpHost getHost() {
- return mHost;
- }
-
- /**
- * connection factory: returns an HTTP or HTTPS connection as
- * necessary
- */
- static Connection getConnection(
- Context context, HttpHost host,
- RequestQueue.ConnectionManager connectionManager,
- RequestFeeder requestFeeder) {
-
- if (host.getSchemeName().equals("http")) {
- return new HttpConnection(context, host, connectionManager,
- requestFeeder);
- }
-
- // Otherwise, default to https
- return new HttpsConnection(context, host, connectionManager,
- requestFeeder);
- }
-
- /**
- * @return The server SSL certificate associated with this
- * connection (null if the connection is not secure)
- */
- /* package */ SslCertificate getCertificate() {
- return mCertificate;
- }
-
- /**
- * Close current network connection
- * Note: this runs in non-network thread
- */
- void cancel() {
- mActive = STATE_CANCEL_REQUESTED;
- closeConnection();
- if (HttpLog.LOGV) HttpLog.v(
- "Connection.cancel(): connection closed " + mHost);
- }
-
- /**
- * Process requests in queue
- * pipelines requests
- */
- void processRequests(Request firstRequest) {
- Request req = null;
- boolean empty;
- int error = EventHandler.OK;
- Exception exception = null;
-
- LinkedList<Request> pipe = new LinkedList<Request>();
-
- int minPipe = MIN_PIPE, maxPipe = MAX_PIPE;
- int state = SEND;
-
- while (state != DONE) {
- if (HttpLog.LOGV) HttpLog.v(
- states[state] + " pipe " + pipe.size());
-
- /* If a request was cancelled, give other cancel requests
- some time to go through so we don't uselessly restart
- connections */
- if (mActive == STATE_CANCEL_REQUESTED) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException x) { /* ignore */ }
- mActive = STATE_NORMAL;
- }
-
- switch (state) {
- case SEND: {
- if (pipe.size() == maxPipe) {
- state = READ;
- break;
- }
- /* get a request */
- if (firstRequest == null) {
- req = mRequestFeeder.getRequest(mHost);
- } else {
- req = firstRequest;
- firstRequest = null;
- }
- if (req == null) {
- state = DRAIN;
- break;
- }
- req.setConnection(this);
-
- /* Don't work on cancelled requests. */
- if (req.mCancelled) {
- if (HttpLog.LOGV) HttpLog.v(
- "processRequests(): skipping cancelled request "
- + req);
- req.complete();
- break;
- }
-
- if (mHttpClientConnection == null ||
- !mHttpClientConnection.isOpen()) {
- /* If this call fails, the address is bad or
- the net is down. Punt for now.
-
- FIXME: blow out entire queue here on
- connection failure if net up? */
-
- if (!openHttpConnection(req)) {
- state = DONE;
- break;
- }
- }
-
- try {
- /* FIXME: don't increment failure count if old
- connection? There should not be a penalty for
- attempting to reuse an old connection */
- req.sendRequest(mHttpClientConnection);
- } catch (HttpException e) {
- exception = e;
- error = EventHandler.ERROR;
- } catch (IOException e) {
- exception = e;
- error = EventHandler.ERROR_IO;
- } catch (IllegalStateException e) {
- exception = e;
- error = EventHandler.ERROR_IO;
- }
- if (exception != null) {
- if (httpFailure(req, error, exception) &&
- !req.mCancelled) {
- /* retry request if not permanent failure
- or cancelled */
- pipe.addLast(req);
- }
- exception = null;
- state = (clearPipe(pipe) ||
- !mConnectionManager.isNetworkConnected()) ?
- DONE : SEND;
- minPipe = maxPipe = 1;
- break;
- }
-
- pipe.addLast(req);
- if (!mCanPersist) state = READ;
- break;
-
- }
- case DRAIN:
- case READ: {
- empty = !mRequestFeeder.haveRequest(mHost);
- int pipeSize = pipe.size();
- if (state != DRAIN && pipeSize < minPipe &&
- !empty && mCanPersist) {
- state = SEND;
- break;
- } else if (pipeSize == 0) {
- /* Done if no other work to do */
- state = empty ? DONE : SEND;
- break;
- }
-
- req = (Request)pipe.removeFirst();
- if (HttpLog.LOGV) HttpLog.v(
- "processRequests() reading " + req);
-
- try {
- req.readResponse(mHttpClientConnection);
- } catch (ParseException e) {
- exception = e;
- error = EventHandler.ERROR_IO;
- } catch (IOException e) {
- exception = e;
- error = EventHandler.ERROR_IO;
- } catch (IllegalStateException e) {
- exception = e;
- error = EventHandler.ERROR_IO;
- }
- if (exception != null) {
- if (httpFailure(req, error, exception) &&
- !req.mCancelled) {
- /* retry request if not permanent failure
- or cancelled */
- req.reset();
- pipe.addFirst(req);
- }
- exception = null;
- mCanPersist = false;
- }
- if (!mCanPersist) {
- if (HttpLog.LOGV) HttpLog.v(
- "processRequests(): no persist, closing " +
- mHost);
-
- closeConnection();
-
- mHttpContext.removeAttribute(HTTP_CONNECTION);
- clearPipe(pipe);
- minPipe = maxPipe = 1;
- /* If network active continue to service this queue */
- state = mConnectionManager.isNetworkConnected() ?
- SEND : DONE;
- }
- break;
- }
- }
- }
- }
-
- /**
- * After a send/receive failure, any pipelined requests must be
- * cleared back to the mRequest queue
- * @return true if mRequests is empty after pipe cleared
- */
- private boolean clearPipe(LinkedList<Request> pipe) {
- boolean empty = true;
- if (HttpLog.LOGV) HttpLog.v(
- "Connection.clearPipe(): clearing pipe " + pipe.size());
- synchronized (mRequestFeeder) {
- Request tReq;
- while (!pipe.isEmpty()) {
- tReq = (Request)pipe.removeLast();
- if (HttpLog.LOGV) HttpLog.v(
- "clearPipe() adding back " + mHost + " " + tReq);
- mRequestFeeder.requeueRequest(tReq);
- empty = false;
- }
- if (empty) empty = mRequestFeeder.haveRequest(mHost);
- }
- return empty;
- }
-
- /**
- * @return true on success
- */
- private boolean openHttpConnection(Request req) {
-
- long now = SystemClock.uptimeMillis();
- int error = EventHandler.OK;
- Exception exception = null;
-
- try {
- // reset the certificate to null before opening a connection
- mCertificate = null;
- mHttpClientConnection = openConnection(req);
- if (mHttpClientConnection != null) {
- mHttpClientConnection.setSocketTimeout(SOCKET_TIMEOUT);
- mHttpContext.setAttribute(HTTP_CONNECTION,
- mHttpClientConnection);
- } else {
- // we tried to do SSL tunneling, failed,
- // and need to drop the request;
- // we have already informed the handler
- req.mFailCount = RETRY_REQUEST_LIMIT;
- return false;
- }
- } catch (UnknownHostException e) {
- if (HttpLog.LOGV) HttpLog.v("Failed to open connection");
- error = EventHandler.ERROR_LOOKUP;
- exception = e;
- } catch (IllegalArgumentException e) {
- if (HttpLog.LOGV) HttpLog.v("Illegal argument exception");
- error = EventHandler.ERROR_CONNECT;
- req.mFailCount = RETRY_REQUEST_LIMIT;
- exception = e;
- } catch (SSLConnectionClosedByUserException e) {
- // hack: if we have an SSL connection failure,
- // we don't want to reconnect
- req.mFailCount = RETRY_REQUEST_LIMIT;
- // no error message
- return false;
- } catch (SSLHandshakeException e) {
- // hack: if we have an SSL connection failure,
- // we don't want to reconnect
- req.mFailCount = RETRY_REQUEST_LIMIT;
- if (HttpLog.LOGV) HttpLog.v(
- "SSL exception performing handshake");
- error = EventHandler.ERROR_FAILED_SSL_HANDSHAKE;
- exception = e;
- } catch (IOException e) {
- error = EventHandler.ERROR_CONNECT;
- exception = e;
- }
-
- if (HttpLog.LOGV) {
- long now2 = SystemClock.uptimeMillis();
- HttpLog.v("Connection.openHttpConnection() " +
- (now2 - now) + " " + mHost);
- }
-
- if (error == EventHandler.OK) {
- return true;
- } else {
- if (mConnectionManager.isNetworkConnected() == false ||
- req.mFailCount < RETRY_REQUEST_LIMIT) {
- // requeue
- mRequestFeeder.requeueRequest(req);
- req.mFailCount++;
- } else {
- httpFailure(req, error, exception);
- }
- return error == EventHandler.OK;
- }
- }
-
- /**
- * Helper. Calls the mEventHandler's error() method only if
- * request failed permanently. Increments mFailcount on failure.
- *
- * Increments failcount only if the network is believed to be
- * connected
- *
- * @return true if request can be retried (less than
- * RETRY_REQUEST_LIMIT failures have occurred).
- */
- private boolean httpFailure(Request req, int errorId, Exception e) {
- boolean ret = true;
- boolean networkConnected = mConnectionManager.isNetworkConnected();
-
- // e.printStackTrace();
- if (HttpLog.LOGV) HttpLog.v(
- "httpFailure() ******* " + e + " count " + req.mFailCount +
- " networkConnected " + networkConnected + " " + mHost + " " + req.getUri());
-
- if (networkConnected && ++req.mFailCount >= RETRY_REQUEST_LIMIT) {
- ret = false;
- String error;
- if (errorId < 0) {
- error = mContext.getText(
- EventHandler.errorStringResources[-errorId]).toString();
- } else {
- Throwable cause = e.getCause();
- error = cause != null ? cause.toString() : e.getMessage();
- }
- req.mEventHandler.error(errorId, error);
- req.complete();
- }
-
- closeConnection();
- mHttpContext.removeAttribute(HTTP_CONNECTION);
-
- return ret;
- }
-
- HttpContext getHttpContext() {
- return mHttpContext;
- }
-
- /**
- * Use same logic as ConnectionReuseStrategy
- * @see ConnectionReuseStrategy
- */
- private boolean keepAlive(HttpEntity entity,
- ProtocolVersion ver, int connType, final HttpContext context) {
- org.apache.http.HttpConnection conn = (org.apache.http.HttpConnection)
- context.getAttribute(ExecutionContext.HTTP_CONNECTION);
-
- if (conn != null && !conn.isOpen())
- return false;
- // do NOT check for stale connection, that is an expensive operation
-
- if (entity != null) {
- if (entity.getContentLength() < 0) {
- if (!entity.isChunked() || ver.lessEquals(HttpVersion.HTTP_1_0)) {
- // if the content length is not known and is not chunk
- // encoded, the connection cannot be reused
- return false;
- }
- }
- }
- // Check for 'Connection' directive
- if (connType == Headers.CONN_CLOSE) {
- return false;
- } else if (connType == Headers.CONN_KEEP_ALIVE) {
- return true;
- }
- // Resorting to protocol version default close connection policy
- return !ver.lessEquals(HttpVersion.HTTP_1_0);
- }
-
- void setCanPersist(HttpEntity entity, ProtocolVersion ver, int connType) {
- mCanPersist = keepAlive(entity, ver, connType, mHttpContext);
- }
-
- void setCanPersist(boolean canPersist) {
- mCanPersist = canPersist;
- }
-
- boolean getCanPersist() {
- return mCanPersist;
- }
-
- /** typically http or https... set by subclass */
- abstract String getScheme();
- abstract void closeConnection();
- abstract AndroidHttpClientConnection openConnection(Request req) throws IOException;
-
- /**
- * Prints request queue to log, for debugging.
- * returns request count
- */
- public synchronized String toString() {
- return mHost.toString();
- }
-
- byte[] getBuf() {
- if (mBuf == null) mBuf = new byte[8192];
- return mBuf;
- }
-
-}
diff --git a/core/java/android/net/http/ConnectionThread.java b/core/java/android/net/http/ConnectionThread.java
deleted file mode 100644
index 8e759e2..0000000
--- a/core/java/android/net/http/ConnectionThread.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import android.content.Context;
-import android.os.SystemClock;
-
-import org.apache.http.HttpHost;
-
-import java.lang.Thread;
-
-/**
- * {@hide}
- */
-class ConnectionThread extends Thread {
-
- static final int WAIT_TIMEOUT = 5000;
- static final int WAIT_TICK = 1000;
-
- // Performance probe
- long mStartThreadTime;
- long mCurrentThreadTime;
-
- private boolean mWaiting;
- private volatile boolean mRunning = true;
- private Context mContext;
- private RequestQueue.ConnectionManager mConnectionManager;
- private RequestFeeder mRequestFeeder;
-
- private int mId;
- Connection mConnection;
-
- ConnectionThread(Context context,
- int id,
- RequestQueue.ConnectionManager connectionManager,
- RequestFeeder requestFeeder) {
- super();
- mContext = context;
- setName("http" + id);
- mId = id;
- mConnectionManager = connectionManager;
- mRequestFeeder = requestFeeder;
- }
-
- void requestStop() {
- synchronized (mRequestFeeder) {
- mRunning = false;
- mRequestFeeder.notify();
- }
- }
-
- /**
- * Loop until app shutdown. Runs connections in priority
- * order.
- */
- public void run() {
- android.os.Process.setThreadPriority(
- android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE);
-
- mStartThreadTime = -1;
- mCurrentThreadTime = SystemClock.currentThreadTimeMillis();
-
- while (mRunning) {
- Request request;
-
- /* Get a request to process */
- request = mRequestFeeder.getRequest();
-
- /* wait for work */
- if (request == null) {
- synchronized(mRequestFeeder) {
- if (HttpLog.LOGV) HttpLog.v("ConnectionThread: Waiting for work");
- mWaiting = true;
- try {
- if (mStartThreadTime != -1) {
- mCurrentThreadTime = SystemClock
- .currentThreadTimeMillis();
- }
- mRequestFeeder.wait();
- } catch (InterruptedException e) {
- }
- mWaiting = false;
- }
- } else {
- if (HttpLog.LOGV) HttpLog.v("ConnectionThread: new request " +
- request.mHost + " " + request );
-
- HttpHost proxy = mConnectionManager.getProxyHost();
-
- HttpHost host;
- if (false) {
- // Allow https proxy
- host = proxy == null ? request.mHost : proxy;
- } else {
- // Disallow https proxy -- tmob proxy server
- // serves a request loop for https reqs
- host = (proxy == null ||
- request.mHost.getSchemeName().equals("https")) ?
- request.mHost : proxy;
- }
- mConnection = mConnectionManager.getConnection(mContext, host);
- mConnection.processRequests(request);
- if (mConnection.getCanPersist()) {
- if (!mConnectionManager.recycleConnection(host,
- mConnection)) {
- mConnection.closeConnection();
- }
- } else {
- mConnection.closeConnection();
- }
- mConnection = null;
- }
-
- }
- }
-
- public synchronized String toString() {
- String con = mConnection == null ? "" : mConnection.toString();
- String active = mWaiting ? "w" : "a";
- return "cid " + mId + " " + active + " " + con;
- }
-
-}
diff --git a/core/java/android/net/http/DomainNameChecker.java b/core/java/android/net/http/DomainNameChecker.java
deleted file mode 100644
index e4c8009..0000000
--- a/core/java/android/net/http/DomainNameChecker.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import org.bouncycastle.asn1.x509.X509Name;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.security.cert.X509Certificate;
-import java.security.cert.CertificateParsingException;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-import java.util.Vector;
-
-/**
- * Implements basic domain-name validation as specified by RFC2818.
- *
- * {@hide}
- */
-public class DomainNameChecker {
- private static Pattern QUICK_IP_PATTERN;
- static {
- try {
- QUICK_IP_PATTERN = Pattern.compile("^[a-f0-9\\.:]+$");
- } catch (PatternSyntaxException e) {}
- }
-
- private static final int ALT_DNS_NAME = 2;
- private static final int ALT_IPA_NAME = 7;
-
- /**
- * Checks the site certificate against the domain name of the site being visited
- * @param certificate The certificate to check
- * @param thisDomain The domain name of the site being visited
- * @return True iff if there is a domain match as specified by RFC2818
- */
- public static boolean match(X509Certificate certificate, String thisDomain) {
- if (certificate == null || thisDomain == null || thisDomain.length() == 0) {
- return false;
- }
-
- thisDomain = thisDomain.toLowerCase();
- if (!isIpAddress(thisDomain)) {
- return matchDns(certificate, thisDomain);
- } else {
- return matchIpAddress(certificate, thisDomain);
- }
- }
-
- /**
- * @return True iff the domain name is specified as an IP address
- */
- private static boolean isIpAddress(String domain) {
- boolean rval = (domain != null && domain.length() != 0);
- if (rval) {
- try {
- // do a quick-dirty IP match first to avoid DNS lookup
- rval = QUICK_IP_PATTERN.matcher(domain).matches();
- if (rval) {
- rval = domain.equals(
- InetAddress.getByName(domain).getHostAddress());
- }
- } catch (UnknownHostException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "unknown host exception";
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v("DomainNameChecker.isIpAddress(): " + errorMessage);
- }
-
- rval = false;
- }
- }
-
- return rval;
- }
-
- /**
- * Checks the site certificate against the IP domain name of the site being visited
- * @param certificate The certificate to check
- * @param thisDomain The DNS domain name of the site being visited
- * @return True iff if there is a domain match as specified by RFC2818
- */
- private static boolean matchIpAddress(X509Certificate certificate, String thisDomain) {
- if (HttpLog.LOGV) {
- HttpLog.v("DomainNameChecker.matchIpAddress(): this domain: " + thisDomain);
- }
-
- try {
- Collection subjectAltNames = certificate.getSubjectAlternativeNames();
- if (subjectAltNames != null) {
- Iterator i = subjectAltNames.iterator();
- while (i.hasNext()) {
- List altNameEntry = (List)(i.next());
- if (altNameEntry != null && 2 <= altNameEntry.size()) {
- Integer altNameType = (Integer)(altNameEntry.get(0));
- if (altNameType != null) {
- if (altNameType.intValue() == ALT_IPA_NAME) {
- String altName = (String)(altNameEntry.get(1));
- if (altName != null) {
- if (HttpLog.LOGV) {
- HttpLog.v("alternative IP: " + altName);
- }
- if (thisDomain.equalsIgnoreCase(altName)) {
- return true;
- }
- }
- }
- }
- }
- }
- }
- } catch (CertificateParsingException e) {}
-
- return false;
- }
-
- /**
- * Checks the site certificate against the DNS domain name of the site being visited
- * @param certificate The certificate to check
- * @param thisDomain The DNS domain name of the site being visited
- * @return True iff if there is a domain match as specified by RFC2818
- */
- private static boolean matchDns(X509Certificate certificate, String thisDomain) {
- boolean hasDns = false;
- try {
- Collection subjectAltNames = certificate.getSubjectAlternativeNames();
- if (subjectAltNames != null) {
- Iterator i = subjectAltNames.iterator();
- while (i.hasNext()) {
- List altNameEntry = (List)(i.next());
- if (altNameEntry != null && 2 <= altNameEntry.size()) {
- Integer altNameType = (Integer)(altNameEntry.get(0));
- if (altNameType != null) {
- if (altNameType.intValue() == ALT_DNS_NAME) {
- hasDns = true;
- String altName = (String)(altNameEntry.get(1));
- if (altName != null) {
- if (matchDns(thisDomain, altName)) {
- return true;
- }
- }
- }
- }
- }
- }
- }
- } catch (CertificateParsingException e) {
- // one way we can get here is if an alternative name starts with
- // '*' character, which is contrary to one interpretation of the
- // spec (a valid DNS name must start with a letter); there is no
- // good way around this, and in order to be compatible we proceed
- // to check the common name (ie, ignore alternative names)
- if (HttpLog.LOGV) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "failed to parse certificate";
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v("DomainNameChecker.matchDns(): " + errorMessage);
- }
- }
- }
-
- if (!hasDns) {
- X509Name xName = new X509Name(certificate.getSubjectDN().getName());
- Vector val = xName.getValues();
- Vector oid = xName.getOIDs();
- for (int i = 0; i < oid.size(); i++) {
- if (oid.elementAt(i).equals(X509Name.CN)) {
- return matchDns(thisDomain, (String)(val.elementAt(i)));
- }
- }
- }
-
- return false;
- }
-
- /**
- * @param thisDomain The domain name of the site being visited
- * @param thatDomain The domain name from the certificate
- * @return True iff thisDomain matches thatDomain as specified by RFC2818
- */
- private static boolean matchDns(String thisDomain, String thatDomain) {
- if (HttpLog.LOGV) {
- HttpLog.v("DomainNameChecker.matchDns():" +
- " this domain: " + thisDomain +
- " that domain: " + thatDomain);
- }
-
- if (thisDomain == null || thisDomain.length() == 0 ||
- thatDomain == null || thatDomain.length() == 0) {
- return false;
- }
-
- thatDomain = thatDomain.toLowerCase();
-
- // (a) domain name strings are equal, ignoring case: X matches X
- boolean rval = thisDomain.equals(thatDomain);
- if (!rval) {
- String[] thisDomainTokens = thisDomain.split("\\.");
- String[] thatDomainTokens = thatDomain.split("\\.");
-
- int thisDomainTokensNum = thisDomainTokens.length;
- int thatDomainTokensNum = thatDomainTokens.length;
-
- // (b) OR thatHost is a '.'-suffix of thisHost: Z.Y.X matches X
- if (thisDomainTokensNum >= thatDomainTokensNum) {
- for (int i = thatDomainTokensNum - 1; i >= 0; --i) {
- rval = thisDomainTokens[i].equals(thatDomainTokens[i]);
- if (!rval) {
- // (c) OR we have a special *-match:
- // Z.Y.X matches *.Y.X but does not match *.X
- rval = (i == 0 && thisDomainTokensNum == thatDomainTokensNum);
- if (rval) {
- rval = thatDomainTokens[0].equals("*");
- if (!rval) {
- // (d) OR we have a *-component match:
- // f*.com matches foo.com but not bar.com
- rval = domainTokenMatch(
- thisDomainTokens[0], thatDomainTokens[0]);
- }
- }
-
- break;
- }
- }
- }
- }
-
- return rval;
- }
-
- /**
- * @param thisDomainToken The domain token from the current domain name
- * @param thatDomainToken The domain token from the certificate
- * @return True iff thisDomainToken matches thatDomainToken, using the
- * wildcard match as specified by RFC2818-3.1. For example, f*.com must
- * match foo.com but not bar.com
- */
- private static boolean domainTokenMatch(String thisDomainToken, String thatDomainToken) {
- if (thisDomainToken != null && thatDomainToken != null) {
- int starIndex = thatDomainToken.indexOf('*');
- if (starIndex >= 0) {
- if (thatDomainToken.length() - 1 <= thisDomainToken.length()) {
- String prefix = thatDomainToken.substring(0, starIndex);
- String suffix = thatDomainToken.substring(starIndex + 1);
-
- return thisDomainToken.startsWith(prefix) && thisDomainToken.endsWith(suffix);
- }
- }
- }
-
- return false;
- }
-}
diff --git a/core/java/android/net/http/EventHandler.java b/core/java/android/net/http/EventHandler.java
deleted file mode 100644
index 830d1f1..0000000
--- a/core/java/android/net/http/EventHandler.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-
-/**
- * Callbacks in this interface are made as an HTTP request is
- * processed. The normal order of callbacks is status(), headers(),
- * then multiple data() then endData(). handleSslErrorRequest(), if
- * there is an SSL certificate error. error() can occur anywhere
- * in the transaction.
- *
- * {@hide}
- */
-
-public interface EventHandler {
-
- /**
- * Error codes used in the error() callback. Positive error codes
- * are reserved for codes sent by http servers. Negative error
- * codes are connection/parsing failures, etc.
- */
-
- /** Success */
- public static final int OK = 0;
- /** Generic error */
- public static final int ERROR = -1;
- /** Server or proxy hostname lookup failed */
- public static final int ERROR_LOOKUP = -2;
- /** Unsupported authentication scheme (ie, not basic or digest) */
- public static final int ERROR_UNSUPPORTED_AUTH_SCHEME = -3;
- /** User authentication failed on server */
- public static final int ERROR_AUTH = -4;
- /** User authentication failed on proxy */
- public static final int ERROR_PROXYAUTH = -5;
- /** Could not connect to server */
- public static final int ERROR_CONNECT = -6;
- /** Failed to write to or read from server */
- public static final int ERROR_IO = -7;
- /** Connection timed out */
- public static final int ERROR_TIMEOUT = -8;
- /** Too many redirects */
- public static final int ERROR_REDIRECT_LOOP = -9;
- /** Unsupported URI scheme (ie, not http, https, etc) */
- public static final int ERROR_UNSUPPORTED_SCHEME = -10;
- /** Failed to perform SSL handshake */
- public static final int ERROR_FAILED_SSL_HANDSHAKE = -11;
- /** Bad URL */
- public static final int ERROR_BAD_URL = -12;
- /** Generic file error for file:/// loads */
- public static final int FILE_ERROR = -13;
- /** File not found error for file:/// loads */
- public static final int FILE_NOT_FOUND_ERROR = -14;
- /** Too many requests queued */
- public static final int TOO_MANY_REQUESTS_ERROR = -15;
-
- final static int[] errorStringResources = {
- com.android.internal.R.string.httpErrorOk,
- com.android.internal.R.string.httpError,
- com.android.internal.R.string.httpErrorLookup,
- com.android.internal.R.string.httpErrorUnsupportedAuthScheme,
- com.android.internal.R.string.httpErrorAuth,
- com.android.internal.R.string.httpErrorProxyAuth,
- com.android.internal.R.string.httpErrorConnect,
- com.android.internal.R.string.httpErrorIO,
- com.android.internal.R.string.httpErrorTimeout,
- com.android.internal.R.string.httpErrorRedirectLoop,
- com.android.internal.R.string.httpErrorUnsupportedScheme,
- com.android.internal.R.string.httpErrorFailedSslHandshake,
- com.android.internal.R.string.httpErrorBadUrl,
- com.android.internal.R.string.httpErrorFile,
- com.android.internal.R.string.httpErrorFileNotFound,
- com.android.internal.R.string.httpErrorTooManyRequests
- };
-
- /**
- * Called after status line has been sucessfully processed.
- * @param major_version HTTP version advertised by server. major
- * is the part before the "."
- * @param minor_version HTTP version advertised by server. minor
- * is the part after the "."
- * @param code HTTP Status code. See RFC 2616.
- * @param reason_phrase Textual explanation sent by server
- */
- public void status(int major_version,
- int minor_version,
- int code,
- String reason_phrase);
-
- /**
- * Called after all headers are successfully processed.
- */
- public void headers(Headers headers);
-
- /**
- * An array containing all or part of the http body as read from
- * the server.
- * @param data A byte array containing the content
- * @param len The length of valid content in data
- *
- * Note: chunked and compressed encodings are handled within
- * android.net.http. Decoded data is passed through this
- * interface.
- */
- public void data(byte[] data, int len);
-
- /**
- * Called when the document is completely read. No more data()
- * callbacks will be made after this call
- */
- public void endData();
-
- /**
- * SSL certificate callback called every time a resource is
- * loaded via a secure connection
- */
- public void certificate(SslCertificate certificate);
-
- /**
- * There was trouble.
- * @param id One of the error codes defined below
- * @param description of error
- */
- public void error(int id, String description);
-
- /**
- * SSL certificate error callback. Handles SSL error(s) on the way
- * up to the user. The callback has to make sure that restartConnection() is called,
- * otherwise the connection will be suspended indefinitely.
- */
- public void handleSslErrorRequest(SslError error);
-
-}
diff --git a/core/java/android/net/http/Headers.java b/core/java/android/net/http/Headers.java
deleted file mode 100644
index b0923d1..0000000
--- a/core/java/android/net/http/Headers.java
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import android.util.Config;
-import android.util.Log;
-
-import java.util.ArrayList;
-
-import org.apache.http.HeaderElement;
-import org.apache.http.entity.ContentLengthStrategy;
-import org.apache.http.message.BasicHeaderValueParser;
-import org.apache.http.message.ParserCursor;
-import org.apache.http.protocol.HTTP;
-import org.apache.http.util.CharArrayBuffer;
-
-/**
- * Manages received headers
- *
- * {@hide}
- */
-public final class Headers {
- private static final String LOGTAG = "Http";
-
- // header parsing constant
- /**
- * indicate HTTP 1.0 connection close after the response
- */
- public final static int CONN_CLOSE = 1;
- /**
- * indicate HTTP 1.1 connection keep alive
- */
- public final static int CONN_KEEP_ALIVE = 2;
-
- // initial values.
- public final static int NO_CONN_TYPE = 0;
- public final static long NO_TRANSFER_ENCODING = 0;
- public final static long NO_CONTENT_LENGTH = -1;
-
- // header strings
- public final static String TRANSFER_ENCODING = "transfer-encoding";
- public final static String CONTENT_LEN = "content-length";
- public final static String CONTENT_TYPE = "content-type";
- public final static String CONTENT_ENCODING = "content-encoding";
- public final static String CONN_DIRECTIVE = "connection";
-
- public final static String LOCATION = "location";
- public final static String PROXY_CONNECTION = "proxy-connection";
-
- public final static String WWW_AUTHENTICATE = "www-authenticate";
- public final static String PROXY_AUTHENTICATE = "proxy-authenticate";
- public final static String CONTENT_DISPOSITION = "content-disposition";
- public final static String ACCEPT_RANGES = "accept-ranges";
- public final static String EXPIRES = "expires";
- public final static String CACHE_CONTROL = "cache-control";
- public final static String LAST_MODIFIED = "last-modified";
- public final static String ETAG = "etag";
- public final static String SET_COOKIE = "set-cookie";
- public final static String PRAGMA = "pragma";
- public final static String REFRESH = "refresh";
-
- // following hash are generated by String.hashCode()
- private final static int HASH_TRANSFER_ENCODING = 1274458357;
- private final static int HASH_CONTENT_LEN = -1132779846;
- private final static int HASH_CONTENT_TYPE = 785670158;
- private final static int HASH_CONTENT_ENCODING = 2095084583;
- private final static int HASH_CONN_DIRECTIVE = -775651618;
- private final static int HASH_LOCATION = 1901043637;
- private final static int HASH_PROXY_CONNECTION = 285929373;
- private final static int HASH_WWW_AUTHENTICATE = -243037365;
- private final static int HASH_PROXY_AUTHENTICATE = -301767724;
- private final static int HASH_CONTENT_DISPOSITION = -1267267485;
- private final static int HASH_ACCEPT_RANGES = 1397189435;
- private final static int HASH_EXPIRES = -1309235404;
- private final static int HASH_CACHE_CONTROL = -208775662;
- private final static int HASH_LAST_MODIFIED = 150043680;
- private final static int HASH_ETAG = 3123477;
- private final static int HASH_SET_COOKIE = 1237214767;
- private final static int HASH_PRAGMA = -980228804;
- private final static int HASH_REFRESH = 1085444827;
-
- // keep any headers that require direct access in a presized
- // string array
- private final static int IDX_TRANSFER_ENCODING = 0;
- private final static int IDX_CONTENT_LEN = 1;
- private final static int IDX_CONTENT_TYPE = 2;
- private final static int IDX_CONTENT_ENCODING = 3;
- private final static int IDX_CONN_DIRECTIVE = 4;
- private final static int IDX_LOCATION = 5;
- private final static int IDX_PROXY_CONNECTION = 6;
- private final static int IDX_WWW_AUTHENTICATE = 7;
- private final static int IDX_PROXY_AUTHENTICATE = 8;
- private final static int IDX_CONTENT_DISPOSITION = 9;
- private final static int IDX_ACCEPT_RANGES = 10;
- private final static int IDX_EXPIRES = 11;
- private final static int IDX_CACHE_CONTROL = 12;
- private final static int IDX_LAST_MODIFIED = 13;
- private final static int IDX_ETAG = 14;
- private final static int IDX_SET_COOKIE = 15;
- private final static int IDX_PRAGMA = 16;
- private final static int IDX_REFRESH = 17;
-
- private final static int HEADER_COUNT = 18;
-
- /* parsed values */
- private long transferEncoding;
- private long contentLength; // Content length of the incoming data
- private int connectionType;
- private ArrayList<String> cookies = new ArrayList<String>(2);
-
- private String[] mHeaders = new String[HEADER_COUNT];
- private final static String[] sHeaderNames = {
- TRANSFER_ENCODING,
- CONTENT_LEN,
- CONTENT_TYPE,
- CONTENT_ENCODING,
- CONN_DIRECTIVE,
- LOCATION,
- PROXY_CONNECTION,
- WWW_AUTHENTICATE,
- PROXY_AUTHENTICATE,
- CONTENT_DISPOSITION,
- ACCEPT_RANGES,
- EXPIRES,
- CACHE_CONTROL,
- LAST_MODIFIED,
- ETAG,
- SET_COOKIE,
- PRAGMA,
- REFRESH
- };
-
- // Catch-all for headers not explicitly handled
- private ArrayList<String> mExtraHeaderNames = new ArrayList<String>(4);
- private ArrayList<String> mExtraHeaderValues = new ArrayList<String>(4);
-
- public Headers() {
- transferEncoding = NO_TRANSFER_ENCODING;
- contentLength = NO_CONTENT_LENGTH;
- connectionType = NO_CONN_TYPE;
- }
-
- public void parseHeader(CharArrayBuffer buffer) {
- int pos = CharArrayBuffers.setLowercaseIndexOf(buffer, ':');
- if (pos == -1) {
- return;
- }
- String name = buffer.substringTrimmed(0, pos);
- if (name.length() == 0) {
- return;
- }
- pos++;
-
- String val = buffer.substringTrimmed(pos, buffer.length());
- if (HttpLog.LOGV) {
- HttpLog.v("hdr " + buffer.length() + " " + buffer);
- }
-
- switch (name.hashCode()) {
- case HASH_TRANSFER_ENCODING:
- if (name.equals(TRANSFER_ENCODING)) {
- mHeaders[IDX_TRANSFER_ENCODING] = val;
- HeaderElement[] encodings = BasicHeaderValueParser.DEFAULT
- .parseElements(buffer, new ParserCursor(pos,
- buffer.length()));
- // The chunked encoding must be the last one applied RFC2616,
- // 14.41
- int len = encodings.length;
- if (HTTP.IDENTITY_CODING.equalsIgnoreCase(val)) {
- transferEncoding = ContentLengthStrategy.IDENTITY;
- } else if ((len > 0)
- && (HTTP.CHUNK_CODING
- .equalsIgnoreCase(encodings[len - 1].getName()))) {
- transferEncoding = ContentLengthStrategy.CHUNKED;
- } else {
- transferEncoding = ContentLengthStrategy.IDENTITY;
- }
- }
- break;
- case HASH_CONTENT_LEN:
- if (name.equals(CONTENT_LEN)) {
- mHeaders[IDX_CONTENT_LEN] = val;
- try {
- contentLength = Long.parseLong(val);
- } catch (NumberFormatException e) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "Headers.headers(): error parsing"
- + " content length: " + buffer.toString());
- }
- }
- }
- break;
- case HASH_CONTENT_TYPE:
- if (name.equals(CONTENT_TYPE)) {
- mHeaders[IDX_CONTENT_TYPE] = val;
- }
- break;
- case HASH_CONTENT_ENCODING:
- if (name.equals(CONTENT_ENCODING)) {
- mHeaders[IDX_CONTENT_ENCODING] = val;
- }
- break;
- case HASH_CONN_DIRECTIVE:
- if (name.equals(CONN_DIRECTIVE)) {
- mHeaders[IDX_CONN_DIRECTIVE] = val;
- setConnectionType(buffer, pos);
- }
- break;
- case HASH_LOCATION:
- if (name.equals(LOCATION)) {
- mHeaders[IDX_LOCATION] = val;
- }
- break;
- case HASH_PROXY_CONNECTION:
- if (name.equals(PROXY_CONNECTION)) {
- mHeaders[IDX_PROXY_CONNECTION] = val;
- setConnectionType(buffer, pos);
- }
- break;
- case HASH_WWW_AUTHENTICATE:
- if (name.equals(WWW_AUTHENTICATE)) {
- mHeaders[IDX_WWW_AUTHENTICATE] = val;
- }
- break;
- case HASH_PROXY_AUTHENTICATE:
- if (name.equals(PROXY_AUTHENTICATE)) {
- mHeaders[IDX_PROXY_AUTHENTICATE] = val;
- }
- break;
- case HASH_CONTENT_DISPOSITION:
- if (name.equals(CONTENT_DISPOSITION)) {
- mHeaders[IDX_CONTENT_DISPOSITION] = val;
- }
- break;
- case HASH_ACCEPT_RANGES:
- if (name.equals(ACCEPT_RANGES)) {
- mHeaders[IDX_ACCEPT_RANGES] = val;
- }
- break;
- case HASH_EXPIRES:
- if (name.equals(EXPIRES)) {
- mHeaders[IDX_EXPIRES] = val;
- }
- break;
- case HASH_CACHE_CONTROL:
- if (name.equals(CACHE_CONTROL)) {
- mHeaders[IDX_CACHE_CONTROL] = val;
- }
- break;
- case HASH_LAST_MODIFIED:
- if (name.equals(LAST_MODIFIED)) {
- mHeaders[IDX_LAST_MODIFIED] = val;
- }
- break;
- case HASH_ETAG:
- if (name.equals(ETAG)) {
- mHeaders[IDX_ETAG] = val;
- }
- break;
- case HASH_SET_COOKIE:
- if (name.equals(SET_COOKIE)) {
- mHeaders[IDX_SET_COOKIE] = val;
- cookies.add(val);
- }
- break;
- case HASH_PRAGMA:
- if (name.equals(PRAGMA)) {
- mHeaders[IDX_PRAGMA] = val;
- }
- break;
- case HASH_REFRESH:
- if (name.equals(REFRESH)) {
- mHeaders[IDX_REFRESH] = val;
- }
- break;
- default:
- mExtraHeaderNames.add(name);
- mExtraHeaderValues.add(val);
- }
- }
-
- public long getTransferEncoding() {
- return transferEncoding;
- }
-
- public long getContentLength() {
- return contentLength;
- }
-
- public int getConnectionType() {
- return connectionType;
- }
-
- public String getContentType() {
- return mHeaders[IDX_CONTENT_TYPE];
- }
-
- public String getContentEncoding() {
- return mHeaders[IDX_CONTENT_ENCODING];
- }
-
- public String getLocation() {
- return mHeaders[IDX_LOCATION];
- }
-
- public String getWwwAuthenticate() {
- return mHeaders[IDX_WWW_AUTHENTICATE];
- }
-
- public String getProxyAuthenticate() {
- return mHeaders[IDX_PROXY_AUTHENTICATE];
- }
-
- public String getContentDisposition() {
- return mHeaders[IDX_CONTENT_DISPOSITION];
- }
-
- public String getAcceptRanges() {
- return mHeaders[IDX_ACCEPT_RANGES];
- }
-
- public String getExpires() {
- return mHeaders[IDX_EXPIRES];
- }
-
- public String getCacheControl() {
- return mHeaders[IDX_CACHE_CONTROL];
- }
-
- public String getLastModified() {
- return mHeaders[IDX_LAST_MODIFIED];
- }
-
- public String getEtag() {
- return mHeaders[IDX_ETAG];
- }
-
- public ArrayList<String> getSetCookie() {
- return this.cookies;
- }
-
- public String getPragma() {
- return mHeaders[IDX_PRAGMA];
- }
-
- public String getRefresh() {
- return mHeaders[IDX_REFRESH];
- }
-
- public void setContentLength(long value) {
- this.contentLength = value;
- }
-
- public void setContentType(String value) {
- mHeaders[IDX_CONTENT_TYPE] = value;
- }
-
- public void setContentEncoding(String value) {
- mHeaders[IDX_CONTENT_ENCODING] = value;
- }
-
- public void setLocation(String value) {
- mHeaders[IDX_LOCATION] = value;
- }
-
- public void setWwwAuthenticate(String value) {
- mHeaders[IDX_WWW_AUTHENTICATE] = value;
- }
-
- public void setProxyAuthenticate(String value) {
- mHeaders[IDX_PROXY_AUTHENTICATE] = value;
- }
-
- public void setContentDisposition(String value) {
- mHeaders[IDX_CONTENT_DISPOSITION] = value;
- }
-
- public void setAcceptRanges(String value) {
- mHeaders[IDX_ACCEPT_RANGES] = value;
- }
-
- public void setExpires(String value) {
- mHeaders[IDX_EXPIRES] = value;
- }
-
- public void setCacheControl(String value) {
- mHeaders[IDX_CACHE_CONTROL] = value;
- }
-
- public void setLastModified(String value) {
- mHeaders[IDX_LAST_MODIFIED] = value;
- }
-
- public void setEtag(String value) {
- mHeaders[IDX_ETAG] = value;
- }
-
- public interface HeaderCallback {
- public void header(String name, String value);
- }
-
- /**
- * Reports all non-null headers to the callback
- */
- public void getHeaders(HeaderCallback hcb) {
- for (int i = 0; i < HEADER_COUNT; i++) {
- String h = mHeaders[i];
- if (h != null) {
- hcb.header(sHeaderNames[i], h);
- }
- }
- int extraLen = mExtraHeaderNames.size();
- for (int i = 0; i < extraLen; i++) {
- if (Config.LOGV) {
- HttpLog.v("Headers.getHeaders() extra: " + i + " " +
- mExtraHeaderNames.get(i) + " " + mExtraHeaderValues.get(i));
- }
- hcb.header(mExtraHeaderNames.get(i),
- mExtraHeaderValues.get(i));
- }
-
- }
-
- private void setConnectionType(CharArrayBuffer buffer, int pos) {
- if (CharArrayBuffers.containsIgnoreCaseTrimmed(
- buffer, pos, HTTP.CONN_CLOSE)) {
- connectionType = CONN_CLOSE;
- } else if (CharArrayBuffers.containsIgnoreCaseTrimmed(
- buffer, pos, HTTP.CONN_KEEP_ALIVE)) {
- connectionType = CONN_KEEP_ALIVE;
- }
- }
-}
diff --git a/core/java/android/net/http/HttpAuthHeader.java b/core/java/android/net/http/HttpAuthHeader.java
deleted file mode 100644
index d41284c..0000000
--- a/core/java/android/net/http/HttpAuthHeader.java
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-/**
- * HttpAuthHeader: a class to store HTTP authentication-header parameters.
- * For more information, see: RFC 2617: HTTP Authentication.
- *
- * {@hide}
- */
-public class HttpAuthHeader {
- /**
- * Possible HTTP-authentication header tokens to search for:
- */
- public final static String BASIC_TOKEN = "Basic";
- public final static String DIGEST_TOKEN = "Digest";
-
- private final static String REALM_TOKEN = "realm";
- private final static String NONCE_TOKEN = "nonce";
- private final static String STALE_TOKEN = "stale";
- private final static String OPAQUE_TOKEN = "opaque";
- private final static String QOP_TOKEN = "qop";
- private final static String ALGORITHM_TOKEN = "algorithm";
-
- /**
- * An authentication scheme. We currently support two different schemes:
- * HttpAuthHeader.BASIC - basic, and
- * HttpAuthHeader.DIGEST - digest (algorithm=MD5, QOP="auth").
- */
- private int mScheme;
-
- public static final int UNKNOWN = 0;
- public static final int BASIC = 1;
- public static final int DIGEST = 2;
-
- /**
- * A flag, indicating that the previous request from the client was
- * rejected because the nonce value was stale. If stale is TRUE
- * (case-insensitive), the client may wish to simply retry the request
- * with a new encrypted response, without reprompting the user for a
- * new username and password.
- */
- private boolean mStale;
-
- /**
- * A string to be displayed to users so they know which username and
- * password to use.
- */
- private String mRealm;
-
- /**
- * A server-specified data string which should be uniquely generated
- * each time a 401 response is made.
- */
- private String mNonce;
-
- /**
- * A string of data, specified by the server, which should be returned
- * by the client unchanged in the Authorization header of subsequent
- * requests with URIs in the same protection space.
- */
- private String mOpaque;
-
- /**
- * This directive is optional, but is made so only for backward
- * compatibility with RFC 2069 [6]; it SHOULD be used by all
- * implementations compliant with this version of the Digest scheme.
- * If present, it is a quoted string of one or more tokens indicating
- * the "quality of protection" values supported by the server. The
- * value "auth" indicates authentication; the value "auth-int"
- * indicates authentication with integrity protection.
- */
- private String mQop;
-
- /**
- * A string indicating a pair of algorithms used to produce the digest
- * and a checksum. If this is not present it is assumed to be "MD5".
- */
- private String mAlgorithm;
-
- /**
- * Is this authentication request a proxy authentication request?
- */
- private boolean mIsProxy;
-
- /**
- * Username string we get from the user.
- */
- private String mUsername;
-
- /**
- * Password string we get from the user.
- */
- private String mPassword;
-
- /**
- * Creates a new HTTP-authentication header object from the
- * input header string.
- * The header string is assumed to contain parameters of at
- * most one authentication-scheme (ensured by the caller).
- */
- public HttpAuthHeader(String header) {
- if (header != null) {
- parseHeader(header);
- }
- }
-
- /**
- * @return True iff this is a proxy authentication header.
- */
- public boolean isProxy() {
- return mIsProxy;
- }
-
- /**
- * Marks this header as a proxy authentication header.
- */
- public void setProxy() {
- mIsProxy = true;
- }
-
- /**
- * @return The username string.
- */
- public String getUsername() {
- return mUsername;
- }
-
- /**
- * Sets the username string.
- */
- public void setUsername(String username) {
- mUsername = username;
- }
-
- /**
- * @return The password string.
- */
- public String getPassword() {
- return mPassword;
- }
-
- /**
- * Sets the password string.
- */
- public void setPassword(String password) {
- mPassword = password;
- }
-
- /**
- * @return True iff this is the BASIC-authentication request.
- */
- public boolean isBasic () {
- return mScheme == BASIC;
- }
-
- /**
- * @return True iff this is the DIGEST-authentication request.
- */
- public boolean isDigest() {
- return mScheme == DIGEST;
- }
-
- /**
- * @return The authentication scheme requested. We currently
- * support two schemes:
- * HttpAuthHeader.BASIC - basic, and
- * HttpAuthHeader.DIGEST - digest (algorithm=MD5, QOP="auth").
- */
- public int getScheme() {
- return mScheme;
- }
-
- /**
- * @return True if indicating that the previous request from
- * the client was rejected because the nonce value was stale.
- */
- public boolean getStale() {
- return mStale;
- }
-
- /**
- * @return The realm value or null if there is none.
- */
- public String getRealm() {
- return mRealm;
- }
-
- /**
- * @return The nonce value or null if there is none.
- */
- public String getNonce() {
- return mNonce;
- }
-
- /**
- * @return The opaque value or null if there is none.
- */
- public String getOpaque() {
- return mOpaque;
- }
-
- /**
- * @return The QOP ("quality-of_protection") value or null if
- * there is none. The QOP value is always lower-case.
- */
- public String getQop() {
- return mQop;
- }
-
- /**
- * @return The name of the algorithm used or null if there is
- * none. By default, MD5 is used.
- */
- public String getAlgorithm() {
- return mAlgorithm;
- }
-
- /**
- * @return True iff the authentication scheme requested by the
- * server is supported; currently supported schemes:
- * BASIC,
- * DIGEST (only algorithm="md5", no qop or qop="auth).
- */
- public boolean isSupportedScheme() {
- // it is a good idea to enforce non-null realms!
- if (mRealm != null) {
- if (mScheme == BASIC) {
- return true;
- } else {
- if (mScheme == DIGEST) {
- return
- mAlgorithm.equals("md5") &&
- (mQop == null || mQop.equals("auth"));
- }
- }
- }
-
- return false;
- }
-
- /**
- * Parses the header scheme name and then scheme parameters if
- * the scheme is supported.
- */
- private void parseHeader(String header) {
- if (HttpLog.LOGV) {
- HttpLog.v("HttpAuthHeader.parseHeader(): header: " + header);
- }
-
- if (header != null) {
- String parameters = parseScheme(header);
- if (parameters != null) {
- // if we have a supported scheme
- if (mScheme != UNKNOWN) {
- parseParameters(parameters);
- }
- }
- }
- }
-
- /**
- * Parses the authentication scheme name. If we have a Digest
- * scheme, sets the algorithm value to the default of MD5.
- * @return The authentication scheme parameters string to be
- * parsed later (if the scheme is supported) or null if failed
- * to parse the scheme (the header value is null?).
- */
- private String parseScheme(String header) {
- if (header != null) {
- int i = header.indexOf(' ');
- if (i >= 0) {
- String scheme = header.substring(0, i).trim();
- if (scheme.equalsIgnoreCase(DIGEST_TOKEN)) {
- mScheme = DIGEST;
-
- // md5 is the default algorithm!!!
- mAlgorithm = "md5";
- } else {
- if (scheme.equalsIgnoreCase(BASIC_TOKEN)) {
- mScheme = BASIC;
- }
- }
-
- return header.substring(i + 1);
- }
- }
-
- return null;
- }
-
- /**
- * Parses a comma-separated list of authentification scheme
- * parameters.
- */
- private void parseParameters(String parameters) {
- if (HttpLog.LOGV) {
- HttpLog.v("HttpAuthHeader.parseParameters():" +
- " parameters: " + parameters);
- }
-
- if (parameters != null) {
- int i;
- do {
- i = parameters.indexOf(',');
- if (i < 0) {
- // have only one parameter
- parseParameter(parameters);
- } else {
- parseParameter(parameters.substring(0, i));
- parameters = parameters.substring(i + 1);
- }
- } while (i >= 0);
- }
- }
-
- /**
- * Parses a single authentication scheme parameter. The parameter
- * string is expected to follow the format: PARAMETER=VALUE.
- */
- private void parseParameter(String parameter) {
- if (parameter != null) {
- // here, we are looking for the 1st occurence of '=' only!!!
- int i = parameter.indexOf('=');
- if (i >= 0) {
- String token = parameter.substring(0, i).trim();
- String value =
- trimDoubleQuotesIfAny(parameter.substring(i + 1).trim());
-
- if (HttpLog.LOGV) {
- HttpLog.v("HttpAuthHeader.parseParameter():" +
- " token: " + token +
- " value: " + value);
- }
-
- if (token.equalsIgnoreCase(REALM_TOKEN)) {
- mRealm = value;
- } else {
- if (mScheme == DIGEST) {
- parseParameter(token, value);
- }
- }
- }
- }
- }
-
- /**
- * If the token is a known parameter name, parses and initializes
- * the token value.
- */
- private void parseParameter(String token, String value) {
- if (token != null && value != null) {
- if (token.equalsIgnoreCase(NONCE_TOKEN)) {
- mNonce = value;
- return;
- }
-
- if (token.equalsIgnoreCase(STALE_TOKEN)) {
- parseStale(value);
- return;
- }
-
- if (token.equalsIgnoreCase(OPAQUE_TOKEN)) {
- mOpaque = value;
- return;
- }
-
- if (token.equalsIgnoreCase(QOP_TOKEN)) {
- mQop = value.toLowerCase();
- return;
- }
-
- if (token.equalsIgnoreCase(ALGORITHM_TOKEN)) {
- mAlgorithm = value.toLowerCase();
- return;
- }
- }
- }
-
- /**
- * Parses and initializes the 'stale' paramer value. Any value
- * different from case-insensitive "true" is considered "false".
- */
- private void parseStale(String value) {
- if (value != null) {
- if (value.equalsIgnoreCase("true")) {
- mStale = true;
- }
- }
- }
-
- /**
- * Trims double-quotes around a parameter value if there are any.
- * @return The string value without the outermost pair of double-
- * quotes or null if the original value is null.
- */
- static private String trimDoubleQuotesIfAny(String value) {
- if (value != null) {
- int len = value.length();
- if (len > 2 &&
- value.charAt(0) == '\"' && value.charAt(len - 1) == '\"') {
- return value.substring(1, len - 1);
- }
- }
-
- return value;
- }
-}
diff --git a/core/java/android/net/http/HttpConnection.java b/core/java/android/net/http/HttpConnection.java
deleted file mode 100644
index 8b12d0b..0000000
--- a/core/java/android/net/http/HttpConnection.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import android.content.Context;
-
-import java.net.Socket;
-import java.io.IOException;
-
-import org.apache.http.HttpClientConnection;
-import org.apache.http.HttpHost;
-import org.apache.http.impl.DefaultHttpClientConnection;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpConnectionParams;
-
-/**
- * A requestConnection connecting to a normal (non secure) http server
- *
- * {@hide}
- */
-class HttpConnection extends Connection {
-
- HttpConnection(Context context, HttpHost host,
- RequestQueue.ConnectionManager connectionManager,
- RequestFeeder requestFeeder) {
- super(context, host, connectionManager, requestFeeder);
- }
-
- /**
- * Opens the connection to a http server
- *
- * @return the opened low level connection
- * @throws IOException if the connection fails for any reason.
- */
- @Override
- AndroidHttpClientConnection openConnection(Request req) throws IOException {
-
- // Update the certificate info (connection not secure - set to null)
- EventHandler eventHandler = req.getEventHandler();
- mCertificate = null;
- eventHandler.certificate(mCertificate);
-
- AndroidHttpClientConnection conn = new AndroidHttpClientConnection();
- BasicHttpParams params = new BasicHttpParams();
- Socket sock = new Socket(mHost.getHostName(), mHost.getPort());
- params.setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 8192);
- conn.bind(sock, params);
- return conn;
- }
-
- /**
- * Closes the low level connection.
- *
- * If an exception is thrown then it is assumed that the
- * connection will have been closed (to the extent possible)
- * anyway and the caller does not need to take any further action.
- *
- */
- void closeConnection() {
- try {
- if (mHttpClientConnection != null && mHttpClientConnection.isOpen()) {
- mHttpClientConnection.close();
- }
- } catch (IOException e) {
- if (HttpLog.LOGV) HttpLog.v(
- "closeConnection(): failed closing connection " +
- mHost);
- e.printStackTrace();
- }
- }
-
- /**
- * Restart a secure connection suspended waiting for user interaction.
- */
- void restartConnection(boolean abort) {
- // not required for plain http connections
- }
-
- String getScheme() {
- return "http";
- }
-}
diff --git a/core/java/android/net/http/HttpLog.java b/core/java/android/net/http/HttpLog.java
deleted file mode 100644
index 30bf647..0000000
--- a/core/java/android/net/http/HttpLog.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * package-level logging flag
- */
-
-package android.net.http;
-
-import android.os.SystemClock;
-
-import android.util.Log;
-import android.util.Config;
-
-/**
- * {@hide}
- */
-class HttpLog {
- private final static String LOGTAG = "http";
-
- private static final boolean DEBUG = false;
- static final boolean LOGV = DEBUG ? Config.LOGD : Config.LOGV;
-
- static void v(String logMe) {
- Log.v(LOGTAG, SystemClock.uptimeMillis() + " " + Thread.currentThread().getName() + " " + logMe);
- }
-
- static void e(String logMe) {
- Log.e(LOGTAG, logMe);
- }
-}
diff --git a/core/java/android/net/http/HttpsConnection.java b/core/java/android/net/http/HttpsConnection.java
deleted file mode 100644
index fe02d3e..0000000
--- a/core/java/android/net/http/HttpsConnection.java
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import android.content.Context;
-
-import junit.framework.Assert;
-
-import java.io.IOException;
-
-import java.security.cert.X509Certificate;
-
-import java.net.Socket;
-import java.net.InetSocketAddress;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-
-import org.apache.http.Header;
-import org.apache.http.HttpClientConnection;
-import org.apache.http.HttpException;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.ParseException;
-import org.apache.http.ProtocolVersion;
-import org.apache.http.StatusLine;
-import org.apache.http.impl.DefaultHttpClientConnection;
-import org.apache.http.message.BasicHttpRequest;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpParams;
-import org.apache.http.params.HttpConnectionParams;
-
-/**
- * Simple exception we throw if the SSL connection is closed by the user.
- *
- * {@hide}
- */
-class SSLConnectionClosedByUserException extends SSLException {
-
- public SSLConnectionClosedByUserException(String reason) {
- super(reason);
- }
-}
-
-/**
- * A Connection connecting to a secure http server or tunneling through
- * a http proxy server to a https server.
- */
-class HttpsConnection extends Connection {
-
- /**
- * SSL context
- */
- private static SSLContext mSslContext = null;
-
- /**
- * SSL socket factory
- */
- private static SSLSocketFactory mSslSocketFactory = null;
-
- static {
- // initialize the socket factory
- try {
- mSslContext = SSLContext.getInstance("TLS");
- if (mSslContext != null) {
- // here, trust managers is a single trust-all manager
- TrustManager[] trustManagers = new TrustManager[] {
- new X509TrustManager() {
- public X509Certificate[] getAcceptedIssuers() {
- return null;
- }
-
- public void checkClientTrusted(
- X509Certificate[] certs, String authType) {
- }
-
- public void checkServerTrusted(
- X509Certificate[] certs, String authType) {
- }
- }
- };
-
- mSslContext.init(null, trustManagers, null);
- mSslSocketFactory = mSslContext.getSocketFactory();
- }
- } catch (Exception t) {
- if (HttpLog.LOGV) {
- HttpLog.v("HttpsConnection: failed to initialize the socket factory");
- }
- }
- }
-
- /**
- * @return The shared SSL context.
- */
- /*package*/ static SSLContext getContext() {
- return mSslContext;
- }
-
- /**
- * Object to wait on when suspending the SSL connection
- */
- private Object mSuspendLock = new Object();
-
- /**
- * True if the connection is suspended pending the result of asking the
- * user about an error.
- */
- private boolean mSuspended = false;
-
- /**
- * True if the connection attempt should be aborted due to an ssl
- * error.
- */
- private boolean mAborted = false;
-
- /**
- * Contructor for a https connection.
- */
- HttpsConnection(Context context, HttpHost host,
- RequestQueue.ConnectionManager connectionManager,
- RequestFeeder requestFeeder) {
- super(context, host, connectionManager, requestFeeder);
- }
-
- /**
- * Sets the server SSL certificate associated with this
- * connection.
- * @param certificate The SSL certificate
- */
- /* package */ void setCertificate(SslCertificate certificate) {
- mCertificate = certificate;
- }
-
- /**
- * Opens the connection to a http server or proxy.
- *
- * @return the opened low level connection
- * @throws IOException if the connection fails for any reason.
- */
- @Override
- AndroidHttpClientConnection openConnection(Request req) throws IOException {
- SSLSocket sslSock = null;
-
- HttpHost proxyHost = mConnectionManager.getProxyHost();
- if (proxyHost != null) {
- // If we have a proxy set, we first send a CONNECT request
- // to the proxy; if the proxy returns 200 OK, we negotiate
- // a secure connection to the target server via the proxy.
- // If the request fails, we drop it, but provide the event
- // handler with the response status and headers. The event
- // handler is then responsible for cancelling the load or
- // issueing a new request.
- AndroidHttpClientConnection proxyConnection = null;
- Socket proxySock = null;
- try {
- proxySock = new Socket
- (proxyHost.getHostName(), proxyHost.getPort());
-
- proxySock.setSoTimeout(60 * 1000);
-
- proxyConnection = new AndroidHttpClientConnection();
- HttpParams params = new BasicHttpParams();
- HttpConnectionParams.setSocketBufferSize(params, 8192);
-
- proxyConnection.bind(proxySock, params);
- } catch(IOException e) {
- if (proxyConnection != null) {
- proxyConnection.close();
- }
-
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage =
- "failed to establish a connection to the proxy";
- }
-
- throw new IOException(errorMessage);
- }
-
- StatusLine statusLine = null;
- int statusCode = 0;
- Headers headers = new Headers();
- try {
- BasicHttpRequest proxyReq = new BasicHttpRequest
- ("CONNECT", mHost.toHostString());
-
- // add all 'proxy' headers from the original request
- for (Header h : req.mHttpRequest.getAllHeaders()) {
- String headerName = h.getName().toLowerCase();
- if (headerName.startsWith("proxy") || headerName.equals("keep-alive")) {
- proxyReq.addHeader(h);
- }
- }
-
- proxyConnection.sendRequestHeader(proxyReq);
- proxyConnection.flush();
-
- // it is possible to receive informational status
- // codes prior to receiving actual headers;
- // all those status codes are smaller than OK 200
- // a loop is a standard way of dealing with them
- do {
- statusLine = proxyConnection.parseResponseHeader(headers);
- statusCode = statusLine.getStatusCode();
- } while (statusCode < HttpStatus.SC_OK);
- } catch (ParseException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage =
- "failed to send a CONNECT request";
- }
-
- throw new IOException(errorMessage);
- } catch (HttpException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage =
- "failed to send a CONNECT request";
- }
-
- throw new IOException(errorMessage);
- } catch (IOException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage =
- "failed to send a CONNECT request";
- }
-
- throw new IOException(errorMessage);
- }
-
- if (statusCode == HttpStatus.SC_OK) {
- try {
- synchronized (mSslSocketFactory) {
- sslSock = (SSLSocket) mSslSocketFactory.createSocket(
- proxySock, mHost.getHostName(), mHost.getPort(), true);
- }
- } catch(IOException e) {
- if (sslSock != null) {
- sslSock.close();
- }
-
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage =
- "failed to create an SSL socket";
- }
- throw new IOException(errorMessage);
- }
- } else {
- // if the code is not OK, inform the event handler
- ProtocolVersion version = statusLine.getProtocolVersion();
-
- req.mEventHandler.status(version.getMajor(),
- version.getMinor(),
- statusCode,
- statusLine.getReasonPhrase());
- req.mEventHandler.headers(headers);
- req.mEventHandler.endData();
-
- proxyConnection.close();
-
- // here, we return null to indicate that the original
- // request needs to be dropped
- return null;
- }
- } else {
- // if we do not have a proxy, we simply connect to the host
- try {
- synchronized (mSslSocketFactory) {
- sslSock = (SSLSocket) mSslSocketFactory.createSocket();
-
- sslSock.setSoTimeout(SOCKET_TIMEOUT);
- sslSock.connect(new InetSocketAddress(mHost.getHostName(),
- mHost.getPort()));
-
- }
- } catch(IOException e) {
- if (sslSock != null) {
- sslSock.close();
- }
-
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "failed to create an SSL socket";
- }
-
- throw new IOException(errorMessage);
- }
- }
-
- // do handshake and validate server certificates
- SslError error = CertificateChainValidator.getInstance().
- doHandshakeAndValidateServerCertificates(this, sslSock, mHost.getHostName());
-
- EventHandler eventHandler = req.getEventHandler();
-
- // Update the certificate info (to be consistent, it is better to do it
- // here, before we start handling SSL errors, if any)
- eventHandler.certificate(mCertificate);
-
- // Inform the user if there is a problem
- if (error != null) {
- // handleSslErrorRequest may immediately unsuspend if it wants to
- // allow the certificate anyway.
- // So we mark the connection as suspended, call handleSslErrorRequest
- // then check if we're still suspended and only wait if we actually
- // need to.
- synchronized (mSuspendLock) {
- mSuspended = true;
- }
- // don't hold the lock while calling out to the event handler
- eventHandler.handleSslErrorRequest(error);
- synchronized (mSuspendLock) {
- if (mSuspended) {
- try {
- // Put a limit on how long we are waiting; if the timeout
- // expires (which should never happen unless you choose
- // to ignore the SSL error dialog for a very long time),
- // we wake up the thread and abort the request. This is
- // to prevent us from stalling the network if things go
- // very bad.
- mSuspendLock.wait(10 * 60 * 1000);
- if (mSuspended) {
- // mSuspended is true if we have not had a chance to
- // restart the connection yet (ie, the wait timeout
- // has expired)
- mSuspended = false;
- mAborted = true;
- if (HttpLog.LOGV) {
- HttpLog.v("HttpsConnection.openConnection():" +
- " SSL timeout expired and request was cancelled!!!");
- }
- }
- } catch (InterruptedException e) {
- // ignore
- }
- }
- if (mAborted) {
- // The user decided not to use this unverified connection
- // so close it immediately.
- sslSock.close();
- throw new SSLConnectionClosedByUserException("connection closed by the user");
- }
- }
- }
-
- // All went well, we have an open, verified connection.
- AndroidHttpClientConnection conn = new AndroidHttpClientConnection();
- BasicHttpParams params = new BasicHttpParams();
- params.setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 8192);
- conn.bind(sslSock, params);
- return conn;
- }
-
- /**
- * Closes the low level connection.
- *
- * If an exception is thrown then it is assumed that the connection will
- * have been closed (to the extent possible) anyway and the caller does not
- * need to take any further action.
- *
- */
- @Override
- void closeConnection() {
- // if the connection has been suspended due to an SSL error
- if (mSuspended) {
- // wake up the network thread
- restartConnection(false);
- }
-
- try {
- if (mHttpClientConnection != null && mHttpClientConnection.isOpen()) {
- mHttpClientConnection.close();
- }
- } catch (IOException e) {
- if (HttpLog.LOGV)
- HttpLog.v("HttpsConnection.closeConnection():" +
- " failed closing connection " + mHost);
- e.printStackTrace();
- }
- }
-
- /**
- * Restart a secure connection suspended waiting for user interaction.
- */
- void restartConnection(boolean proceed) {
- if (HttpLog.LOGV) {
- HttpLog.v("HttpsConnection.restartConnection():" +
- " proceed: " + proceed);
- }
-
- synchronized (mSuspendLock) {
- if (mSuspended) {
- mSuspended = false;
- mAborted = !proceed;
- mSuspendLock.notify();
- }
- }
- }
-
- @Override
- String getScheme() {
- return "https";
- }
-}
diff --git a/core/java/android/net/http/IdleCache.java b/core/java/android/net/http/IdleCache.java
deleted file mode 100644
index fda6009..0000000
--- a/core/java/android/net/http/IdleCache.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Hangs onto idle live connections for a little while
- */
-
-package android.net.http;
-
-import org.apache.http.HttpHost;
-
-import android.os.SystemClock;
-
-/**
- * {@hide}
- */
-class IdleCache {
-
- class Entry {
- HttpHost mHost;
- Connection mConnection;
- long mTimeout;
- };
-
- private final static int IDLE_CACHE_MAX = 8;
-
- /* Allow five consecutive empty queue checks before shutdown */
- private final static int EMPTY_CHECK_MAX = 5;
-
- /* six second timeout for connections */
- private final static int TIMEOUT = 6 * 1000;
- private final static int CHECK_INTERVAL = 2 * 1000;
- private Entry[] mEntries = new Entry[IDLE_CACHE_MAX];
-
- private int mCount = 0;
-
- private IdleReaper mThread = null;
-
- /* stats */
- private int mCached = 0;
- private int mReused = 0;
-
- IdleCache() {
- for (int i = 0; i < IDLE_CACHE_MAX; i++) {
- mEntries[i] = new Entry();
- }
- }
-
- /**
- * Caches connection, if there is room.
- * @return true if connection cached
- */
- synchronized boolean cacheConnection(
- HttpHost host, Connection connection) {
-
- boolean ret = false;
-
- if (HttpLog.LOGV) {
- HttpLog.v("IdleCache size " + mCount + " host " + host);
- }
-
- if (mCount < IDLE_CACHE_MAX) {
- long time = SystemClock.uptimeMillis();
- for (int i = 0; i < IDLE_CACHE_MAX; i++) {
- Entry entry = mEntries[i];
- if (entry.mHost == null) {
- entry.mHost = host;
- entry.mConnection = connection;
- entry.mTimeout = time + TIMEOUT;
- mCount++;
- if (HttpLog.LOGV) mCached++;
- ret = true;
- if (mThread == null) {
- mThread = new IdleReaper();
- mThread.start();
- }
- break;
- }
- }
- }
- return ret;
- }
-
- synchronized Connection getConnection(HttpHost host) {
- Connection ret = null;
-
- if (mCount > 0) {
- for (int i = 0; i < IDLE_CACHE_MAX; i++) {
- Entry entry = mEntries[i];
- HttpHost eHost = entry.mHost;
- if (eHost != null && eHost.equals(host)) {
- ret = entry.mConnection;
- entry.mHost = null;
- entry.mConnection = null;
- mCount--;
- if (HttpLog.LOGV) mReused++;
- break;
- }
- }
- }
- return ret;
- }
-
- synchronized void clear() {
- for (int i = 0; mCount > 0 && i < IDLE_CACHE_MAX; i++) {
- Entry entry = mEntries[i];
- if (entry.mHost != null) {
- entry.mHost = null;
- entry.mConnection.closeConnection();
- entry.mConnection = null;
- mCount--;
- }
- }
- }
-
- private synchronized void clearIdle() {
- if (mCount > 0) {
- long time = SystemClock.uptimeMillis();
- for (int i = 0; i < IDLE_CACHE_MAX; i++) {
- Entry entry = mEntries[i];
- if (entry.mHost != null && time > entry.mTimeout) {
- entry.mHost = null;
- entry.mConnection.closeConnection();
- entry.mConnection = null;
- mCount--;
- }
- }
- }
- }
-
- private class IdleReaper extends Thread {
-
- public void run() {
- int check = 0;
-
- setName("IdleReaper");
- android.os.Process.setThreadPriority(
- android.os.Process.THREAD_PRIORITY_BACKGROUND);
- synchronized (IdleCache.this) {
- while (check < EMPTY_CHECK_MAX) {
- try {
- IdleCache.this.wait(CHECK_INTERVAL);
- } catch (InterruptedException ex) {
- }
- if (mCount == 0) {
- check++;
- } else {
- check = 0;
- clearIdle();
- }
- }
- mThread = null;
- }
- if (HttpLog.LOGV) {
- HttpLog.v("IdleCache IdleReaper shutdown: cached " + mCached +
- " reused " + mReused);
- mCached = 0;
- mReused = 0;
- }
- }
- }
-}
diff --git a/core/java/android/net/http/LoggingEventHandler.java b/core/java/android/net/http/LoggingEventHandler.java
deleted file mode 100644
index 1b18651..0000000
--- a/core/java/android/net/http/LoggingEventHandler.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * A test EventHandler: Logs everything received
- */
-
-package android.net.http;
-
-import android.net.http.Headers;
-
-/**
- * {@hide}
- */
-public class LoggingEventHandler implements EventHandler {
-
- public void requestSent() {
- HttpLog.v("LoggingEventHandler:requestSent()");
- }
-
- public void status(int major_version,
- int minor_version,
- int code, /* Status-Code value */
- String reason_phrase) {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler:status() major: " + major_version +
- " minor: " + minor_version +
- " code: " + code +
- " reason: " + reason_phrase);
- }
- }
-
- public void headers(Headers headers) {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler:headers()");
- HttpLog.v(headers.toString());
- }
- }
-
- public void locationChanged(String newLocation, boolean permanent) {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler: locationChanged() " + newLocation +
- " permanent " + permanent);
- }
- }
-
- public void data(byte[] data, int len) {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler: data() " + len + " bytes");
- }
- // HttpLog.v(new String(data, 0, len));
- }
- public void endData() {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler: endData() called");
- }
- }
-
- public void certificate(SslCertificate certificate) {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler: certificate(): " + certificate);
- }
- }
-
- public void error(int id, String description) {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler: error() called Id:" + id +
- " description " + description);
- }
- }
-
- public void handleSslErrorRequest(SslError error) {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler: handleSslErrorRequest():" + error);
- }
- }
-}
diff --git a/core/java/android/net/http/Request.java b/core/java/android/net/http/Request.java
deleted file mode 100644
index df4fff0..0000000
--- a/core/java/android/net/http/Request.java
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import java.io.EOFException;
-import java.io.InputStream;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.zip.GZIPInputStream;
-
-import org.apache.http.entity.InputStreamEntity;
-import org.apache.http.Header;
-import org.apache.http.HttpClientConnection;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpEntityEnclosingRequest;
-import org.apache.http.HttpException;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.ParseException;
-import org.apache.http.ProtocolVersion;
-
-import org.apache.http.StatusLine;
-import org.apache.http.message.BasicHttpRequest;
-import org.apache.http.message.BasicHttpEntityEnclosingRequest;
-import org.apache.http.protocol.RequestContent;
-
-/**
- * Represents an HTTP request for a given host.
- *
- * {@hide}
- */
-
-class Request {
-
- /** The eventhandler to call as the request progresses */
- EventHandler mEventHandler;
-
- private Connection mConnection;
-
- /** The Apache http request */
- BasicHttpRequest mHttpRequest;
-
- /** The path component of this request */
- String mPath;
-
- /** Host serving this request */
- HttpHost mHost;
-
- /** Set if I'm using a proxy server */
- HttpHost mProxyHost;
-
- /** True if request is .html, .js, .css */
- boolean mHighPriority;
-
- /** True if request has been cancelled */
- volatile boolean mCancelled = false;
-
- int mFailCount = 0;
-
- private InputStream mBodyProvider;
- private int mBodyLength;
-
- private final static String HOST_HEADER = "Host";
- private final static String ACCEPT_ENCODING_HEADER = "Accept-Encoding";
- private final static String CONTENT_LENGTH_HEADER = "content-length";
-
- /* Used to synchronize waitUntilComplete() requests */
- private final Object mClientResource = new Object();
-
- /**
- * Processor used to set content-length and transfer-encoding
- * headers.
- */
- private static RequestContent requestContentProcessor =
- new RequestContent();
-
- /**
- * Instantiates a new Request.
- * @param method GET/POST/PUT
- * @param host The server that will handle this request
- * @param path path part of URI
- * @param bodyProvider InputStream providing HTTP body, null if none
- * @param bodyLength length of body, must be 0 if bodyProvider is null
- * @param eventHandler request will make progress callbacks on
- * this interface
- * @param headers reqeust headers
- * @param highPriority true for .html, css, .cs
- */
- Request(String method, HttpHost host, HttpHost proxyHost, String path,
- InputStream bodyProvider, int bodyLength,
- EventHandler eventHandler,
- Map<String, String> headers, boolean highPriority) {
- mEventHandler = eventHandler;
- mHost = host;
- mProxyHost = proxyHost;
- mPath = path;
- mHighPriority = highPriority;
- mBodyProvider = bodyProvider;
- mBodyLength = bodyLength;
-
- if (bodyProvider == null) {
- mHttpRequest = new BasicHttpRequest(method, getUri());
- } else {
- mHttpRequest = new BasicHttpEntityEnclosingRequest(
- method, getUri());
- setBodyProvider(bodyProvider, bodyLength);
- }
- addHeader(HOST_HEADER, getHostPort());
-
- /* FIXME: if webcore will make the root document a
- high-priority request, we can ask for gzip encoding only on
- high priority reqs (saving the trouble for images, etc) */
- addHeader(ACCEPT_ENCODING_HEADER, "gzip");
- addHeaders(headers);
- }
-
- /**
- * @param connection Request served by this connection
- */
- void setConnection(Connection connection) {
- mConnection = connection;
- }
-
- /* package */ EventHandler getEventHandler() {
- return mEventHandler;
- }
-
- /**
- * Add header represented by given pair to request. Header will
- * be formatted in request as "name: value\r\n".
- * @param name of header
- * @param value of header
- */
- void addHeader(String name, String value) {
- if (name == null) {
- String damage = "Null http header name";
- HttpLog.e(damage);
- throw new NullPointerException(damage);
- }
- if (value == null || value.length() == 0) {
- String damage = "Null or empty value for header \"" + name + "\"";
- HttpLog.e(damage);
- throw new RuntimeException(damage);
- }
- mHttpRequest.addHeader(name, value);
- }
-
- /**
- * Add all headers in given map to this request. This is a helper
- * method: it calls addHeader for each pair in the map.
- */
- void addHeaders(Map<String, String> headers) {
- if (headers == null) {
- return;
- }
-
- Entry<String, String> entry;
- Iterator<Entry<String, String>> i = headers.entrySet().iterator();
- while (i.hasNext()) {
- entry = i.next();
- addHeader(entry.getKey(), entry.getValue());
- }
- }
-
- /**
- * Send the request line and headers
- */
- void sendRequest(AndroidHttpClientConnection httpClientConnection)
- throws HttpException, IOException {
-
- if (mCancelled) return; // don't send cancelled requests
-
- if (HttpLog.LOGV) {
- HttpLog.v("Request.sendRequest() " + mHost.getSchemeName() + "://" + getHostPort());
- // HttpLog.v(mHttpRequest.getRequestLine().toString());
- if (false) {
- Iterator i = mHttpRequest.headerIterator();
- while (i.hasNext()) {
- Header header = (Header)i.next();
- HttpLog.v(header.getName() + ": " + header.getValue());
- }
- }
- }
-
- requestContentProcessor.process(mHttpRequest,
- mConnection.getHttpContext());
- httpClientConnection.sendRequestHeader(mHttpRequest);
- if (mHttpRequest instanceof HttpEntityEnclosingRequest) {
- httpClientConnection.sendRequestEntity(
- (HttpEntityEnclosingRequest) mHttpRequest);
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v("Request.requestSent() " + mHost.getSchemeName() + "://" + getHostPort() + mPath);
- }
- }
-
-
- /**
- * Receive a single http response.
- *
- * @param httpClientConnection the request to receive the response for.
- */
- void readResponse(AndroidHttpClientConnection httpClientConnection)
- throws IOException, ParseException {
-
- if (mCancelled) return; // don't send cancelled requests
-
- StatusLine statusLine = null;
- boolean hasBody = false;
- boolean reuse = false;
- httpClientConnection.flush();
- int statusCode = 0;
-
- Headers header = new Headers();
- do {
- statusLine = httpClientConnection.parseResponseHeader(header);
- statusCode = statusLine.getStatusCode();
- } while (statusCode < HttpStatus.SC_OK);
- if (HttpLog.LOGV) HttpLog.v(
- "Request.readResponseStatus() " +
- statusLine.toString().length() + " " + statusLine);
-
- ProtocolVersion v = statusLine.getProtocolVersion();
- mEventHandler.status(v.getMajor(), v.getMinor(),
- statusCode, statusLine.getReasonPhrase());
- mEventHandler.headers(header);
- HttpEntity entity = null;
- hasBody = canResponseHaveBody(mHttpRequest, statusCode);
-
- if (hasBody)
- entity = httpClientConnection.receiveResponseEntity(header);
-
- if (entity != null) {
- InputStream is = entity.getContent();
-
- // process gzip content encoding
- Header contentEncoding = entity.getContentEncoding();
- InputStream nis = null;
- try {
- if (contentEncoding != null &&
- contentEncoding.getValue().equals("gzip")) {
- nis = new GZIPInputStream(is);
- } else {
- nis = is;
- }
-
- /* accumulate enough data to make it worth pushing it
- * up the stack */
- byte[] buf = mConnection.getBuf();
- int len = 0;
- int count = 0;
- int lowWater = buf.length / 2;
- while (len != -1) {
- len = nis.read(buf, count, buf.length - count);
- if (len != -1) {
- count += len;
- }
- if (len == -1 || count >= lowWater) {
- if (HttpLog.LOGV) HttpLog.v("Request.readResponse() " + count);
- mEventHandler.data(buf, count);
- count = 0;
- }
- }
- } catch (EOFException e) {
- /* InflaterInputStream throws an EOFException when the
- server truncates gzipped content. Handle this case
- as we do truncated non-gzipped content: no error */
- if (HttpLog.LOGV) HttpLog.v( "readResponse() handling " + e);
- } catch(IOException e) {
- // don't throw if we have a non-OK status code
- if (statusCode == HttpStatus.SC_OK) {
- throw e;
- }
- } finally {
- if (nis != null) {
- nis.close();
- }
- }
- }
- mConnection.setCanPersist(entity, statusLine.getProtocolVersion(),
- header.getConnectionType());
- mEventHandler.endData();
- complete();
-
- if (HttpLog.LOGV) HttpLog.v("Request.readResponse(): done " +
- mHost.getSchemeName() + "://" + getHostPort() + mPath);
- }
-
- /**
- * Data will not be sent to or received from server after cancel()
- * call. Does not close connection--use close() below for that.
- *
- * Called by RequestHandle from non-network thread
- */
- void cancel() {
- if (HttpLog.LOGV) {
- HttpLog.v("Request.cancel(): " + getUri());
- }
- mCancelled = true;
- if (mConnection != null) {
- mConnection.cancel();
- }
- }
-
- String getHostPort() {
- String myScheme = mHost.getSchemeName();
- int myPort = mHost.getPort();
-
- // Only send port when we must... many servers can't deal with it
- if (myPort != 80 && myScheme.equals("http") ||
- myPort != 443 && myScheme.equals("https")) {
- return mHost.toHostString();
- } else {
- return mHost.getHostName();
- }
- }
-
- String getUri() {
- if (mProxyHost == null ||
- mHost.getSchemeName().equals("https")) {
- return mPath;
- }
- return mHost.getSchemeName() + "://" + getHostPort() + mPath;
- }
-
- /**
- * for debugging
- */
- public String toString() {
- return (mHighPriority ? "P*" : "") + mPath;
- }
-
-
- /**
- * If this request has been sent once and failed, it must be reset
- * before it can be sent again.
- */
- void reset() {
- /* clear content-length header */
- mHttpRequest.removeHeaders(CONTENT_LENGTH_HEADER);
-
- if (mBodyProvider != null) {
- try {
- mBodyProvider.reset();
- } catch (IOException ex) {
- if (HttpLog.LOGV) HttpLog.v(
- "failed to reset body provider " +
- getUri());
- }
- setBodyProvider(mBodyProvider, mBodyLength);
- }
- }
-
- /**
- * Pause thread request completes. Used for synchronous requests,
- * and testing
- */
- void waitUntilComplete() {
- synchronized (mClientResource) {
- try {
- if (HttpLog.LOGV) HttpLog.v("Request.waitUntilComplete()");
- mClientResource.wait();
- if (HttpLog.LOGV) HttpLog.v("Request.waitUntilComplete() done waiting");
- } catch (InterruptedException e) {
- }
- }
- }
-
- void complete() {
- synchronized (mClientResource) {
- mClientResource.notifyAll();
- }
- }
-
- /**
- * Decide whether a response comes with an entity.
- * The implementation in this class is based on RFC 2616.
- * Unknown methods and response codes are supposed to
- * indicate responses with an entity.
- * <br/>
- * Derived executors can override this method to handle
- * methods and response codes not specified in RFC 2616.
- *
- * @param request the request, to obtain the executed method
- * @param response the response, to obtain the status code
- */
-
- private static boolean canResponseHaveBody(final HttpRequest request,
- final int status) {
-
- if ("HEAD".equalsIgnoreCase(request.getRequestLine().getMethod())) {
- return false;
- }
- return status >= HttpStatus.SC_OK
- && status != HttpStatus.SC_NO_CONTENT
- && status != HttpStatus.SC_NOT_MODIFIED
- && status != HttpStatus.SC_RESET_CONTENT;
- }
-
- /**
- * Supply an InputStream that provides the body of a request. It's
- * not great that the caller must also provide the length of the data
- * returned by that InputStream, but the client needs to know up
- * front, and I'm not sure how to get this out of the InputStream
- * itself without a costly readthrough. I'm not sure skip() would
- * do what we want. If you know a better way, please let me know.
- */
- private void setBodyProvider(InputStream bodyProvider, int bodyLength) {
- if (!bodyProvider.markSupported()) {
- throw new IllegalArgumentException(
- "bodyProvider must support mark()");
- }
- // Mark beginning of stream
- bodyProvider.mark(Integer.MAX_VALUE);
-
- ((BasicHttpEntityEnclosingRequest)mHttpRequest).setEntity(
- new InputStreamEntity(bodyProvider, bodyLength));
- }
-
-
- /**
- * Handles SSL error(s) on the way down from the user (the user
- * has already provided their feedback).
- */
- public void handleSslErrorResponse(boolean proceed) {
- HttpsConnection connection = (HttpsConnection)(mConnection);
- if (connection != null) {
- connection.restartConnection(proceed);
- }
- }
-
- /**
- * Helper: calls error() on eventhandler with appropriate message
- * This should not be called before the mConnection is set.
- */
- void error(int errorId, int resourceId) {
- mEventHandler.error(
- errorId,
- mConnection.mContext.getText(
- resourceId).toString());
- }
-
-}
diff --git a/core/java/android/net/http/RequestFeeder.java b/core/java/android/net/http/RequestFeeder.java
deleted file mode 100644
index 34ca267..0000000
--- a/core/java/android/net/http/RequestFeeder.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Supplies Requests to a Connection
- */
-
-package android.net.http;
-
-import org.apache.http.HttpHost;
-
-/**
- * {@hide}
- */
-interface RequestFeeder {
-
- Request getRequest();
- Request getRequest(HttpHost host);
-
- /**
- * @return true if a request for this host is available
- */
- boolean haveRequest(HttpHost host);
-
- /**
- * Put request back on head of queue
- */
- void requeueRequest(Request request);
-}
diff --git a/core/java/android/net/http/RequestHandle.java b/core/java/android/net/http/RequestHandle.java
deleted file mode 100644
index c4ee5b0..0000000
--- a/core/java/android/net/http/RequestHandle.java
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import android.net.ParseException;
-import android.net.WebAddress;
-import android.security.Md5MessageDigest;
-import junit.framework.Assert;
-import android.webkit.CookieManager;
-
-import org.apache.commons.codec.binary.Base64;
-
-import java.io.InputStream;
-import java.lang.Math;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Random;
-
-/**
- * RequestHandle: handles a request session that may include multiple
- * redirects, HTTP authentication requests, etc.
- *
- * {@hide}
- */
-public class RequestHandle {
-
- private String mUrl;
- private WebAddress mUri;
- private String mMethod;
- private Map<String, String> mHeaders;
-
- private RequestQueue mRequestQueue;
-
- private Request mRequest;
-
- private InputStream mBodyProvider;
- private int mBodyLength;
-
- private int mRedirectCount = 0;
-
- private final static String AUTHORIZATION_HEADER = "Authorization";
- private final static String PROXY_AUTHORIZATION_HEADER = "Proxy-Authorization";
-
- public final static int MAX_REDIRECT_COUNT = 16;
-
- /**
- * Creates a new request session.
- */
- public RequestHandle(RequestQueue requestQueue, String url, WebAddress uri,
- String method, Map<String, String> headers,
- InputStream bodyProvider, int bodyLength, Request request) {
-
- if (headers == null) {
- headers = new HashMap<String, String>();
- }
- mHeaders = headers;
- mBodyProvider = bodyProvider;
- mBodyLength = bodyLength;
- mMethod = method == null? "GET" : method;
-
- mUrl = url;
- mUri = uri;
-
- mRequestQueue = requestQueue;
-
- mRequest = request;
- }
-
- /**
- * Cancels this request
- */
- public void cancel() {
- if (mRequest != null) {
- mRequest.cancel();
- }
- }
-
- /**
- * Handles SSL error(s) on the way down from the user (the user
- * has already provided their feedback).
- */
- public void handleSslErrorResponse(boolean proceed) {
- if (mRequest != null) {
- mRequest.handleSslErrorResponse(proceed);
- }
- }
-
- /**
- * @return true if we've hit the max redirect count
- */
- public boolean isRedirectMax() {
- return mRedirectCount >= MAX_REDIRECT_COUNT;
- }
-
- public int getRedirectCount() {
- return mRedirectCount;
- }
-
- public void setRedirectCount(int count) {
- mRedirectCount = count;
- }
-
- /**
- * Create and queue a redirect request.
- *
- * @param redirectTo URL to redirect to
- * @param statusCode HTTP status code returned from original request
- * @param cacheHeaders Cache header for redirect URL
- * @return true if setup succeeds, false otherwise (redirect loop
- * count exceeded, body provider unable to rewind on 307 redirect)
- */
- public boolean setupRedirect(String redirectTo, int statusCode,
- Map<String, String> cacheHeaders) {
- if (HttpLog.LOGV) {
- HttpLog.v("RequestHandle.setupRedirect(): redirectCount " +
- mRedirectCount);
- }
-
- // be careful and remove authentication headers, if any
- mHeaders.remove(AUTHORIZATION_HEADER);
- mHeaders.remove(PROXY_AUTHORIZATION_HEADER);
-
- if (++mRedirectCount == MAX_REDIRECT_COUNT) {
- // Way too many redirects -- fail out
- if (HttpLog.LOGV) HttpLog.v(
- "RequestHandle.setupRedirect(): too many redirects " +
- mRequest);
- mRequest.error(EventHandler.ERROR_REDIRECT_LOOP,
- com.android.internal.R.string.httpErrorRedirectLoop);
- return false;
- }
-
- if (mUrl.startsWith("https:") && redirectTo.startsWith("http:")) {
- // implement http://www.w3.org/Protocols/rfc2616/rfc2616-sec15.html#sec15.1.3
- if (HttpLog.LOGV) {
- HttpLog.v("blowing away the referer on an https -> http redirect");
- }
- mHeaders.remove("Referer");
- }
-
- mUrl = redirectTo;
- try {
- mUri = new WebAddress(mUrl);
- } catch (ParseException e) {
- e.printStackTrace();
- }
-
- // update the "cookie" header based on the redirected url
- mHeaders.remove("cookie");
- String cookie = CookieManager.getInstance().getCookie(mUri);
- if (cookie != null && cookie.length() > 0) {
- mHeaders.put("cookie", cookie);
- }
-
- if ((statusCode == 302 || statusCode == 303) && mMethod.equals("POST")) {
- if (HttpLog.LOGV) {
- HttpLog.v("replacing POST with GET on redirect to " + redirectTo);
- }
- mMethod = "GET";
- }
- /* Only repost content on a 307. If 307, reset the body
- provider so we can replay the body */
- if (statusCode == 307) {
- try {
- if (mBodyProvider != null) mBodyProvider.reset();
- } catch (java.io.IOException ex) {
- if (HttpLog.LOGV) {
- HttpLog.v("setupAuthResponse() failed to reset body provider");
- }
- return false;
- }
-
- } else {
- mHeaders.remove("Content-Type");
- mBodyProvider = null;
- }
-
- // Update the cache headers for this URL
- mHeaders.putAll(cacheHeaders);
-
- createAndQueueNewRequest();
- return true;
- }
-
- /**
- * Create and queue an HTTP authentication-response (basic) request.
- */
- public void setupBasicAuthResponse(boolean isProxy, String username, String password) {
- String response = computeBasicAuthResponse(username, password);
- if (HttpLog.LOGV) {
- HttpLog.v("setupBasicAuthResponse(): response: " + response);
- }
- mHeaders.put(authorizationHeader(isProxy), "Basic " + response);
- setupAuthResponse();
- }
-
- /**
- * Create and queue an HTTP authentication-response (digest) request.
- */
- public void setupDigestAuthResponse(boolean isProxy,
- String username,
- String password,
- String realm,
- String nonce,
- String QOP,
- String algorithm,
- String opaque) {
-
- String response = computeDigestAuthResponse(
- username, password, realm, nonce, QOP, algorithm, opaque);
- if (HttpLog.LOGV) {
- HttpLog.v("setupDigestAuthResponse(): response: " + response);
- }
- mHeaders.put(authorizationHeader(isProxy), "Digest " + response);
- setupAuthResponse();
- }
-
- private void setupAuthResponse() {
- try {
- if (mBodyProvider != null) mBodyProvider.reset();
- } catch (java.io.IOException ex) {
- if (HttpLog.LOGV) {
- HttpLog.v("setupAuthResponse() failed to reset body provider");
- }
- }
- createAndQueueNewRequest();
- }
-
- /**
- * @return HTTP request method (GET, PUT, etc).
- */
- public String getMethod() {
- return mMethod;
- }
-
- /**
- * @return Basic-scheme authentication response: BASE64(username:password).
- */
- public static String computeBasicAuthResponse(String username, String password) {
- Assert.assertNotNull(username);
- Assert.assertNotNull(password);
-
- // encode username:password to base64
- return new String(Base64.encodeBase64((username + ':' + password).getBytes()));
- }
-
- public void waitUntilComplete() {
- mRequest.waitUntilComplete();
- }
-
- /**
- * @return Digest-scheme authentication response.
- */
- private String computeDigestAuthResponse(String username,
- String password,
- String realm,
- String nonce,
- String QOP,
- String algorithm,
- String opaque) {
-
- Assert.assertNotNull(username);
- Assert.assertNotNull(password);
- Assert.assertNotNull(realm);
-
- String A1 = username + ":" + realm + ":" + password;
- String A2 = mMethod + ":" + mUrl;
-
- // because we do not preemptively send authorization headers, nc is always 1
- String nc = "000001";
- String cnonce = computeCnonce();
- String digest = computeDigest(A1, A2, nonce, QOP, nc, cnonce);
-
- String response = "";
- response += "username=" + doubleQuote(username) + ", ";
- response += "realm=" + doubleQuote(realm) + ", ";
- response += "nonce=" + doubleQuote(nonce) + ", ";
- response += "uri=" + doubleQuote(mUrl) + ", ";
- response += "response=" + doubleQuote(digest) ;
-
- if (opaque != null) {
- response += ", opaque=" + doubleQuote(opaque);
- }
-
- if (algorithm != null) {
- response += ", algorithm=" + algorithm;
- }
-
- if (QOP != null) {
- response += ", qop=" + QOP + ", nc=" + nc + ", cnonce=" + doubleQuote(cnonce);
- }
-
- return response;
- }
-
- /**
- * @return The right authorization header (dependeing on whether it is a proxy or not).
- */
- public static String authorizationHeader(boolean isProxy) {
- if (!isProxy) {
- return AUTHORIZATION_HEADER;
- } else {
- return PROXY_AUTHORIZATION_HEADER;
- }
- }
-
- /**
- * @return Double-quoted MD5 digest.
- */
- private String computeDigest(
- String A1, String A2, String nonce, String QOP, String nc, String cnonce) {
- if (HttpLog.LOGV) {
- HttpLog.v("computeDigest(): QOP: " + QOP);
- }
-
- if (QOP == null) {
- return KD(H(A1), nonce + ":" + H(A2));
- } else {
- if (QOP.equalsIgnoreCase("auth")) {
- return KD(H(A1), nonce + ":" + nc + ":" + cnonce + ":" + QOP + ":" + H(A2));
- }
- }
-
- return null;
- }
-
- /**
- * @return MD5 hash of concat(secret, ":", data).
- */
- private String KD(String secret, String data) {
- return H(secret + ":" + data);
- }
-
- /**
- * @return MD5 hash of param.
- */
- private String H(String param) {
- if (param != null) {
- Md5MessageDigest md5 = new Md5MessageDigest();
-
- byte[] d = md5.digest(param.getBytes());
- if (d != null) {
- return bufferToHex(d);
- }
- }
-
- return null;
- }
-
- /**
- * @return HEX buffer representation.
- */
- private String bufferToHex(byte[] buffer) {
- final char hexChars[] =
- { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
-
- if (buffer != null) {
- int length = buffer.length;
- if (length > 0) {
- StringBuilder hex = new StringBuilder(2 * length);
-
- for (int i = 0; i < length; ++i) {
- byte l = (byte) (buffer[i] & 0x0F);
- byte h = (byte)((buffer[i] & 0xF0) >> 4);
-
- hex.append(hexChars[h]);
- hex.append(hexChars[l]);
- }
-
- return hex.toString();
- } else {
- return "";
- }
- }
-
- return null;
- }
-
- /**
- * Computes a random cnonce value based on the current time.
- */
- private String computeCnonce() {
- Random rand = new Random();
- int nextInt = rand.nextInt();
- nextInt = (nextInt == Integer.MIN_VALUE) ?
- Integer.MAX_VALUE : Math.abs(nextInt);
- return Integer.toString(nextInt, 16);
- }
-
- /**
- * "Double-quotes" the argument.
- */
- private String doubleQuote(String param) {
- if (param != null) {
- return "\"" + param + "\"";
- }
-
- return null;
- }
-
- /**
- * Creates and queues new request.
- */
- private void createAndQueueNewRequest() {
- mRequest = mRequestQueue.queueRequest(
- mUrl, mUri, mMethod, mHeaders, mRequest.mEventHandler,
- mBodyProvider,
- mBodyLength, mRequest.mHighPriority).mRequest;
- }
-}
diff --git a/core/java/android/net/http/RequestQueue.java b/core/java/android/net/http/RequestQueue.java
deleted file mode 100644
index 66d5722..0000000
--- a/core/java/android/net/http/RequestQueue.java
+++ /dev/null
@@ -1,647 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * High level HTTP Interface
- * Queues requests as necessary
- */
-
-package android.net.http;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.ConnectivityManager;
-import android.net.NetworkConnectivityListener;
-import android.net.NetworkInfo;
-import android.net.Proxy;
-import android.net.WebAddress;
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemProperties;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.io.InputStream;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.ListIterator;
-import java.util.Map;
-
-import org.apache.http.HttpHost;
-
-/**
- * {@hide}
- */
-public class RequestQueue implements RequestFeeder {
-
- private Context mContext;
-
- /**
- * Requests, indexed by HttpHost (scheme, host, port)
- */
- private LinkedHashMap<HttpHost, LinkedList<Request>> mPending;
-
- /* Support for notifying a client when queue is empty */
- private boolean mClientWaiting = false;
-
- /** true if connected */
- boolean mNetworkConnected = true;
-
- private HttpHost mProxyHost = null;
- private BroadcastReceiver mProxyChangeReceiver;
-
- private ActivePool mActivePool;
-
- /* default simultaneous connection count */
- private static final int CONNECTION_COUNT = 4;
-
- /**
- * This intent broadcast when http is paused or unpaused due to
- * net availability toggling
- */
- public final static String HTTP_NETWORK_STATE_CHANGED_INTENT =
- "android.net.http.NETWORK_STATE";
- public final static String HTTP_NETWORK_STATE_UP = "up";
-
- /**
- * Listen to platform network state. On a change,
- * (1) kick stack on or off as appropriate
- * (2) send an intent to my host app telling
- * it what I've done
- */
- private NetworkStateTracker mNetworkStateTracker;
- class NetworkStateTracker {
-
- final static int EVENT_DATA_STATE_CHANGED = 100;
-
- Context mContext;
- NetworkConnectivityListener mConnectivityListener;
- NetworkInfo.State mLastNetworkState = NetworkInfo.State.CONNECTED;
- int mCurrentNetworkType;
-
- NetworkStateTracker(Context context) {
- mContext = context;
- }
-
- /**
- * register for updates
- */
- protected void enable() {
- if (mConnectivityListener == null) {
- /*
- * Initializing the network type is really unnecessary,
- * since as soon as we register with the NCL, we'll
- * get a CONNECTED event for the active network, and
- * we'll configure the HTTP proxy accordingly. However,
- * as a fallback in case that doesn't happen for some
- * reason, initializing to type WIFI would mean that
- * we'd start out without a proxy. This seems better
- * than thinking we have a proxy (which is probably
- * private to the carrier network and therefore
- * unreachable outside of that network) when we really
- * shouldn't.
- */
- mCurrentNetworkType = ConnectivityManager.TYPE_WIFI;
- mConnectivityListener = new NetworkConnectivityListener();
- mConnectivityListener.registerHandler(mHandler, EVENT_DATA_STATE_CHANGED);
- mConnectivityListener.startListening(mContext);
- }
- }
-
- protected void disable() {
- if (mConnectivityListener != null) {
- mConnectivityListener.unregisterHandler(mHandler);
- mConnectivityListener.stopListening();
- mConnectivityListener = null;
- }
- }
-
- private Handler mHandler = new Handler() {
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case EVENT_DATA_STATE_CHANGED:
- networkStateChanged();
- break;
- }
- }
- };
-
- int getCurrentNetworkType() {
- return mCurrentNetworkType;
- }
-
- void networkStateChanged() {
- if (mConnectivityListener == null)
- return;
-
-
- NetworkConnectivityListener.State connectivityState = mConnectivityListener.getState();
- NetworkInfo info = mConnectivityListener.getNetworkInfo();
- if (info == null) {
- /**
- * We've been seeing occasional NPEs here. I believe recent changes
- * have made this impossible, but in the interest of being totally
- * paranoid, check and log this here.
- */
- HttpLog.v("NetworkStateTracker: connectivity broadcast"
- + " has null network info - ignoring");
- return;
- }
- NetworkInfo.State state = info.getState();
-
- if (HttpLog.LOGV) {
- HttpLog.v("NetworkStateTracker " + info.getTypeName() +
- " state= " + state + " last= " + mLastNetworkState +
- " connectivityState= " + connectivityState.toString());
- }
-
- boolean newConnection =
- state != mLastNetworkState && state == NetworkInfo.State.CONNECTED;
-
- if (state == NetworkInfo.State.CONNECTED) {
- mCurrentNetworkType = info.getType();
- setProxyConfig();
- }
-
- mLastNetworkState = state;
- if (connectivityState == NetworkConnectivityListener.State.NOT_CONNECTED) {
- setNetworkState(false);
- broadcastState(false);
- } else if (newConnection) {
- setNetworkState(true);
- broadcastState(true);
- }
-
- }
-
- void broadcastState(boolean connected) {
- Intent intent = new Intent(HTTP_NETWORK_STATE_CHANGED_INTENT);
- intent.putExtra(HTTP_NETWORK_STATE_UP, connected);
- mContext.sendBroadcast(intent);
- }
- }
-
- /**
- * This class maintains active connection threads
- */
- class ActivePool implements ConnectionManager {
- /** Threads used to process requests */
- ConnectionThread[] mThreads;
-
- IdleCache mIdleCache;
-
- private int mTotalRequest;
- private int mTotalConnection;
- private int mConnectionCount;
-
- ActivePool(int connectionCount) {
- mIdleCache = new IdleCache();
- mConnectionCount = connectionCount;
- mThreads = new ConnectionThread[mConnectionCount];
-
- for (int i = 0; i < mConnectionCount; i++) {
- mThreads[i] = new ConnectionThread(
- mContext, i, this, RequestQueue.this);
- }
- }
-
- void startup() {
- for (int i = 0; i < mConnectionCount; i++) {
- mThreads[i].start();
- }
- }
-
- void shutdown() {
- for (int i = 0; i < mConnectionCount; i++) {
- mThreads[i].requestStop();
- }
- }
-
- public boolean isNetworkConnected() {
- return mNetworkConnected;
- }
-
- void startConnectionThread() {
- synchronized (RequestQueue.this) {
- RequestQueue.this.notify();
- }
- }
-
- public void startTiming() {
- for (int i = 0; i < mConnectionCount; i++) {
- mThreads[i].mStartThreadTime = mThreads[i].mCurrentThreadTime;
- }
- mTotalRequest = 0;
- mTotalConnection = 0;
- }
-
- public void stopTiming() {
- int totalTime = 0;
- for (int i = 0; i < mConnectionCount; i++) {
- ConnectionThread rt = mThreads[i];
- totalTime += (rt.mCurrentThreadTime - rt.mStartThreadTime);
- rt.mStartThreadTime = -1;
- }
- Log.d("Http", "Http thread used " + totalTime + " ms " + " for "
- + mTotalRequest + " requests and " + mTotalConnection
- + " connections");
- }
-
- void logState() {
- StringBuilder dump = new StringBuilder();
- for (int i = 0; i < mConnectionCount; i++) {
- dump.append(mThreads[i] + "\n");
- }
- HttpLog.v(dump.toString());
- }
-
-
- public HttpHost getProxyHost() {
- return mProxyHost;
- }
-
- /**
- * Turns off persistence on all live connections
- */
- void disablePersistence() {
- for (int i = 0; i < mConnectionCount; i++) {
- Connection connection = mThreads[i].mConnection;
- if (connection != null) connection.setCanPersist(false);
- }
- mIdleCache.clear();
- }
-
- /* Linear lookup -- okay for small thread counts. Might use
- private HashMap<HttpHost, LinkedList<ConnectionThread>> mActiveMap;
- if this turns out to be a hotspot */
- ConnectionThread getThread(HttpHost host) {
- synchronized(RequestQueue.this) {
- for (int i = 0; i < mThreads.length; i++) {
- ConnectionThread ct = mThreads[i];
- Connection connection = ct.mConnection;
- if (connection != null && connection.mHost.equals(host)) {
- return ct;
- }
- }
- }
- return null;
- }
-
- public Connection getConnection(Context context, HttpHost host) {
- Connection con = mIdleCache.getConnection(host);
- if (con == null) {
- mTotalConnection++;
- con = Connection.getConnection(
- mContext, host, this, RequestQueue.this);
- }
- return con;
- }
- public boolean recycleConnection(HttpHost host, Connection connection) {
- return mIdleCache.cacheConnection(host, connection);
- }
-
- }
-
- /**
- * A RequestQueue class instance maintains a set of queued
- * requests. It orders them, makes the requests against HTTP
- * servers, and makes callbacks to supplied eventHandlers as data
- * is read. It supports request prioritization, connection reuse
- * and pipelining.
- *
- * @param context application context
- */
- public RequestQueue(Context context) {
- this(context, CONNECTION_COUNT);
- }
-
- /**
- * A RequestQueue class instance maintains a set of queued
- * requests. It orders them, makes the requests against HTTP
- * servers, and makes callbacks to supplied eventHandlers as data
- * is read. It supports request prioritization, connection reuse
- * and pipelining.
- *
- * @param context application context
- * @param connectionCount The number of simultaneous connections
- */
- public RequestQueue(Context context, int connectionCount) {
- mContext = context;
-
- mPending = new LinkedHashMap<HttpHost, LinkedList<Request>>(32);
-
- mActivePool = new ActivePool(connectionCount);
- mActivePool.startup();
- }
-
- /**
- * Enables data state and proxy tracking
- */
- public synchronized void enablePlatformNotifications() {
- if (HttpLog.LOGV) HttpLog.v("RequestQueue.enablePlatformNotifications() network");
-
- if (mProxyChangeReceiver == null) {
- mProxyChangeReceiver =
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context ctx, Intent intent) {
- setProxyConfig();
- }
- };
- mContext.registerReceiver(mProxyChangeReceiver,
- new IntentFilter(Proxy.PROXY_CHANGE_ACTION));
- }
-
- /* Network state notification is broken on the simulator
- don't register for notifications on SIM */
- String device = SystemProperties.get("ro.product.device");
- boolean simulation = TextUtils.isEmpty(device);
-
- if (!simulation) {
- if (mNetworkStateTracker == null) {
- mNetworkStateTracker = new NetworkStateTracker(mContext);
- }
- mNetworkStateTracker.enable();
- }
- }
-
- /**
- * If platform notifications have been enabled, call this method
- * to disable before destroying RequestQueue
- */
- public synchronized void disablePlatformNotifications() {
- if (HttpLog.LOGV) HttpLog.v("RequestQueue.disablePlatformNotifications() network");
-
- if (mNetworkStateTracker != null) {
- mNetworkStateTracker.disable();
- }
-
- if (mProxyChangeReceiver != null) {
- mContext.unregisterReceiver(mProxyChangeReceiver);
- mProxyChangeReceiver = null;
- }
- }
-
- /**
- * Because our IntentReceiver can run within a different thread,
- * synchronize setting the proxy
- */
- private synchronized void setProxyConfig() {
- if (mNetworkStateTracker.getCurrentNetworkType() == ConnectivityManager.TYPE_WIFI) {
- mProxyHost = null;
- } else {
- String host = Proxy.getHost(mContext);
- if (HttpLog.LOGV) HttpLog.v("RequestQueue.setProxyConfig " + host);
- if (host == null) {
- mProxyHost = null;
- } else {
- mActivePool.disablePersistence();
- mProxyHost = new HttpHost(host, Proxy.getPort(mContext), "http");
- }
- }
- }
-
- /**
- * used by webkit
- * @return proxy host if set, null otherwise
- */
- public HttpHost getProxyHost() {
- return mProxyHost;
- }
-
- /**
- * Queues an HTTP request
- * @param url The url to load.
- * @param method "GET" or "POST."
- * @param headers A hashmap of http headers.
- * @param eventHandler The event handler for handling returned
- * data. Callbacks will be made on the supplied instance.
- * @param bodyProvider InputStream providing HTTP body, null if none
- * @param bodyLength length of body, must be 0 if bodyProvider is null
- * @param highPriority If true, queues before low priority
- * requests if possible
- */
- public RequestHandle queueRequest(
- String url, String method,
- Map<String, String> headers, EventHandler eventHandler,
- InputStream bodyProvider, int bodyLength, boolean highPriority) {
- WebAddress uri = new WebAddress(url);
- return queueRequest(url, uri, method, headers, eventHandler,
- bodyProvider, bodyLength, highPriority);
- }
-
- /**
- * Queues an HTTP request
- * @param url The url to load.
- * @param uri The uri of the url to load.
- * @param method "GET" or "POST."
- * @param headers A hashmap of http headers.
- * @param eventHandler The event handler for handling returned
- * data. Callbacks will be made on the supplied instance.
- * @param bodyProvider InputStream providing HTTP body, null if none
- * @param bodyLength length of body, must be 0 if bodyProvider is null
- * @param highPriority If true, queues before low priority
- * requests if possible
- */
- public RequestHandle queueRequest(
- String url, WebAddress uri, String method, Map<String, String> headers,
- EventHandler eventHandler,
- InputStream bodyProvider, int bodyLength,
- boolean highPriority) {
-
- if (HttpLog.LOGV) HttpLog.v("RequestQueue.queueRequest " + uri);
-
- // Ensure there is an eventHandler set
- if (eventHandler == null) {
- eventHandler = new LoggingEventHandler();
- }
-
- /* Create and queue request */
- Request req;
- HttpHost httpHost = new HttpHost(uri.mHost, uri.mPort, uri.mScheme);
-
- // set up request
- req = new Request(method, httpHost, mProxyHost, uri.mPath, bodyProvider,
- bodyLength, eventHandler, headers, highPriority);
-
- queueRequest(req, highPriority);
-
- mActivePool.mTotalRequest++;
-
- // dump();
- mActivePool.startConnectionThread();
-
- return new RequestHandle(
- this, url, uri, method, headers, bodyProvider, bodyLength,
- req);
- }
-
- /**
- * Called by the NetworkStateTracker -- updates when network connectivity
- * is lost/restored.
- *
- * If isNetworkConnected is true, start processing requests
- */
- public void setNetworkState(boolean isNetworkConnected) {
- if (HttpLog.LOGV) HttpLog.v("RequestQueue.setNetworkState() " + isNetworkConnected);
- mNetworkConnected = isNetworkConnected;
- if (isNetworkConnected)
- mActivePool.startConnectionThread();
- }
-
- /**
- * @return true iff there are any non-active requests pending
- */
- synchronized boolean requestsPending() {
- return !mPending.isEmpty();
- }
-
-
- /**
- * debug tool: prints request queue to log
- */
- synchronized void dump() {
- HttpLog.v("dump()");
- StringBuilder dump = new StringBuilder();
- int count = 0;
- Iterator<Map.Entry<HttpHost, LinkedList<Request>>> iter;
-
- // mActivePool.log(dump);
-
- if (!mPending.isEmpty()) {
- iter = mPending.entrySet().iterator();
- while (iter.hasNext()) {
- Map.Entry<HttpHost, LinkedList<Request>> entry = iter.next();
- String hostName = entry.getKey().getHostName();
- StringBuilder line = new StringBuilder("p" + count++ + " " + hostName + " ");
-
- LinkedList<Request> reqList = entry.getValue();
- ListIterator reqIter = reqList.listIterator(0);
- while (iter.hasNext()) {
- Request request = (Request)iter.next();
- line.append(request + " ");
- }
- dump.append(line);
- dump.append("\n");
- }
- }
- HttpLog.v(dump.toString());
- }
-
- /*
- * RequestFeeder implementation
- */
- public synchronized Request getRequest() {
- Request ret = null;
-
- if (mNetworkConnected && !mPending.isEmpty()) {
- ret = removeFirst(mPending);
- }
- if (HttpLog.LOGV) HttpLog.v("RequestQueue.getRequest() => " + ret);
- return ret;
- }
-
- /**
- * @return a request for given host if possible
- */
- public synchronized Request getRequest(HttpHost host) {
- Request ret = null;
-
- if (mNetworkConnected && mPending.containsKey(host)) {
- LinkedList<Request> reqList = mPending.get(host);
- ret = reqList.removeFirst();
- if (reqList.isEmpty()) {
- mPending.remove(host);
- }
- }
- if (HttpLog.LOGV) HttpLog.v("RequestQueue.getRequest(" + host + ") => " + ret);
- return ret;
- }
-
- /**
- * @return true if a request for this host is available
- */
- public synchronized boolean haveRequest(HttpHost host) {
- return mPending.containsKey(host);
- }
-
- /**
- * Put request back on head of queue
- */
- public void requeueRequest(Request request) {
- queueRequest(request, true);
- }
-
- /**
- * This must be called to cleanly shutdown RequestQueue
- */
- public void shutdown() {
- mActivePool.shutdown();
- }
-
- protected synchronized void queueRequest(Request request, boolean head) {
- HttpHost host = request.mProxyHost == null ? request.mHost : request.mProxyHost;
- LinkedList<Request> reqList;
- if (mPending.containsKey(host)) {
- reqList = mPending.get(host);
- } else {
- reqList = new LinkedList<Request>();
- mPending.put(host, reqList);
- }
- if (head) {
- reqList.addFirst(request);
- } else {
- reqList.add(request);
- }
- }
-
-
- public void startTiming() {
- mActivePool.startTiming();
- }
-
- public void stopTiming() {
- mActivePool.stopTiming();
- }
-
- /* helper */
- private Request removeFirst(LinkedHashMap<HttpHost, LinkedList<Request>> requestQueue) {
- Request ret = null;
- Iterator<Map.Entry<HttpHost, LinkedList<Request>>> iter = requestQueue.entrySet().iterator();
- if (iter.hasNext()) {
- Map.Entry<HttpHost, LinkedList<Request>> entry = iter.next();
- LinkedList<Request> reqList = entry.getValue();
- ret = reqList.removeFirst();
- if (reqList.isEmpty()) {
- requestQueue.remove(entry.getKey());
- }
- }
- return ret;
- }
-
- /**
- * This interface is exposed to each connection
- */
- interface ConnectionManager {
- boolean isNetworkConnected();
- HttpHost getProxyHost();
- Connection getConnection(Context context, HttpHost host);
- boolean recycleConnection(HttpHost host, Connection connection);
- }
-}
diff --git a/core/java/android/net/http/SslCertificate.java b/core/java/android/net/http/SslCertificate.java
deleted file mode 100644
index 46b2bee..0000000
--- a/core/java/android/net/http/SslCertificate.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import android.os.Bundle;
-
-import java.text.DateFormat;
-import java.util.Vector;
-
-import java.security.cert.X509Certificate;
-
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.x509.X509Name;
-
-/**
- * SSL certificate info (certificate details) class
- */
-public class SslCertificate {
-
- /**
- * Name of the entity this certificate is issued to
- */
- private DName mIssuedTo;
-
- /**
- * Name of the entity this certificate is issued by
- */
- private DName mIssuedBy;
-
- /**
- * Not-before date from the validity period
- */
- private String mValidNotBefore;
-
- /**
- * Not-after date from the validity period
- */
- private String mValidNotAfter;
-
- /**
- * Bundle key names
- */
- private static final String ISSUED_TO = "issued-to";
- private static final String ISSUED_BY = "issued-by";
- private static final String VALID_NOT_BEFORE = "valid-not-before";
- private static final String VALID_NOT_AFTER = "valid-not-after";
-
- /**
- * Saves the certificate state to a bundle
- * @param certificate The SSL certificate to store
- * @return A bundle with the certificate stored in it or null if fails
- */
- public static Bundle saveState(SslCertificate certificate) {
- Bundle bundle = null;
-
- if (certificate != null) {
- bundle = new Bundle();
-
- bundle.putString(ISSUED_TO, certificate.getIssuedTo().getDName());
- bundle.putString(ISSUED_BY, certificate.getIssuedBy().getDName());
-
- bundle.putString(VALID_NOT_BEFORE, certificate.getValidNotBefore());
- bundle.putString(VALID_NOT_AFTER, certificate.getValidNotAfter());
- }
-
- return bundle;
- }
-
- /**
- * Restores the certificate stored in the bundle
- * @param bundle The bundle with the certificate state stored in it
- * @return The SSL certificate stored in the bundle or null if fails
- */
- public static SslCertificate restoreState(Bundle bundle) {
- if (bundle != null) {
- return new SslCertificate(
- bundle.getString(ISSUED_TO),
- bundle.getString(ISSUED_BY),
- bundle.getString(VALID_NOT_BEFORE),
- bundle.getString(VALID_NOT_AFTER));
- }
-
- return null;
- }
-
- /**
- * Creates a new SSL certificate object
- * @param issuedTo The entity this certificate is issued to
- * @param issuedBy The entity that issued this certificate
- * @param validNotBefore The not-before date from the certificate validity period
- * @param validNotAfter The not-after date from the certificate validity period
- */
- public SslCertificate(
- String issuedTo, String issuedBy, String validNotBefore, String validNotAfter) {
- mIssuedTo = new DName(issuedTo);
- mIssuedBy = new DName(issuedBy);
-
- mValidNotBefore = validNotBefore;
- mValidNotAfter = validNotAfter;
- }
-
- /**
- * Creates a new SSL certificate object from an X509 certificate
- * @param certificate X509 certificate
- */
- public SslCertificate(X509Certificate certificate) {
- this(certificate.getSubjectDN().getName(),
- certificate.getIssuerDN().getName(),
- DateFormat.getInstance().format(certificate.getNotBefore()),
- DateFormat.getInstance().format(certificate.getNotAfter()));
- }
-
- /**
- * @return Not-before date from the certificate validity period or
- * "" if none has been set
- */
- public String getValidNotBefore() {
- return mValidNotBefore != null ? mValidNotBefore : "";
- }
-
- /**
- * @return Not-after date from the certificate validity period or
- * "" if none has been set
- */
- public String getValidNotAfter() {
- return mValidNotAfter != null ? mValidNotAfter : "";
- }
-
- /**
- * @return Issued-to distinguished name or null if none has been set
- */
- public DName getIssuedTo() {
- return mIssuedTo;
- }
-
- /**
- * @return Issued-by distinguished name or null if none has been set
- */
- public DName getIssuedBy() {
- return mIssuedBy;
- }
-
- /**
- * @return A string representation of this certificate for debugging
- */
- public String toString() {
- return
- "Issued to: " + mIssuedTo.getDName() + ";\n" +
- "Issued by: " + mIssuedBy.getDName() + ";\n";
- }
-
- /**
- * A distinguished name helper class: a 3-tuple of:
- * - common name (CN),
- * - organization (O),
- * - organizational unit (OU)
- */
- public class DName {
- /**
- * Distinguished name (normally includes CN, O, and OU names)
- */
- private String mDName;
-
- /**
- * Common-name (CN) component of the name
- */
- private String mCName;
-
- /**
- * Organization (O) component of the name
- */
- private String mOName;
-
- /**
- * Organizational Unit (OU) component of the name
- */
- private String mUName;
-
- /**
- * Creates a new distinguished name
- * @param dName The distinguished name
- */
- public DName(String dName) {
- if (dName != null) {
- X509Name x509Name = new X509Name(mDName = dName);
-
- Vector val = x509Name.getValues();
- Vector oid = x509Name.getOIDs();
-
- for (int i = 0; i < oid.size(); i++) {
- if (oid.elementAt(i).equals(X509Name.CN)) {
- mCName = (String) val.elementAt(i);
- continue;
- }
-
- if (oid.elementAt(i).equals(X509Name.O)) {
- mOName = (String) val.elementAt(i);
- continue;
- }
-
- if (oid.elementAt(i).equals(X509Name.OU)) {
- mUName = (String) val.elementAt(i);
- continue;
- }
- }
- }
- }
-
- /**
- * @return The distinguished name (normally includes CN, O, and OU names)
- */
- public String getDName() {
- return mDName != null ? mDName : "";
- }
-
- /**
- * @return The Common-name (CN) component of this name
- */
- public String getCName() {
- return mCName != null ? mCName : "";
- }
-
- /**
- * @return The Organization (O) component of this name
- */
- public String getOName() {
- return mOName != null ? mOName : "";
- }
-
- /**
- * @return The Organizational Unit (OU) component of this name
- */
- public String getUName() {
- return mUName != null ? mUName : "";
- }
- }
-}
diff --git a/core/java/android/net/http/SslError.java b/core/java/android/net/http/SslError.java
deleted file mode 100644
index 2788cb1..0000000
--- a/core/java/android/net/http/SslError.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import java.security.cert.X509Certificate;
-
-/**
- * One or more individual SSL errors and the associated SSL certificate
- *
- * {@hide}
- */
-public class SslError {
-
- /**
- * Individual SSL errors (in the order from the least to the most severe):
- */
-
- /**
- * The certificate is not yet valid
- */
- public static final int SSL_NOTYETVALID = 0;
- /**
- * The certificate has expired
- */
- public static final int SSL_EXPIRED = 1;
- /**
- * Hostname mismatch
- */
- public static final int SSL_IDMISMATCH = 2;
- /**
- * The certificate authority is not trusted
- */
- public static final int SSL_UNTRUSTED = 3;
-
-
- /**
- * The number of different SSL errors (update if you add a new SSL error!!!)
- */
- public static final int SSL_MAX_ERROR = 4;
-
- /**
- * The SSL error set bitfield (each individual error is an bit index;
- * multiple individual errors can be OR-ed)
- */
- int mErrors;
-
- /**
- * The SSL certificate associated with the error set
- */
- SslCertificate mCertificate;
-
- /**
- * Creates a new SSL error set object
- * @param error The SSL error
- * @param certificate The associated SSL certificate
- */
- public SslError(int error, SslCertificate certificate) {
- addError(error);
- mCertificate = certificate;
- }
-
- /**
- * Creates a new SSL error set object
- * @param error The SSL error
- * @param certificate The associated SSL certificate
- */
- public SslError(int error, X509Certificate certificate) {
- addError(error);
- mCertificate = new SslCertificate(certificate);
- }
-
- /**
- * @return The SSL certificate associated with the error set
- */
- public SslCertificate getCertificate() {
- return mCertificate;
- }
-
- /**
- * Adds the SSL error to the error set
- * @param error The SSL error to add
- * @return True iff the error being added is a known SSL error
- */
- public boolean addError(int error) {
- boolean rval = (0 <= error && error < SslError.SSL_MAX_ERROR);
- if (rval) {
- mErrors |= (0x1 << error);
- }
-
- return rval;
- }
-
- /**
- * @param error The SSL error to check
- * @return True iff the set includes the error
- */
- public boolean hasError(int error) {
- boolean rval = (0 <= error && error < SslError.SSL_MAX_ERROR);
- if (rval) {
- rval = ((mErrors & (0x1 << error)) != 0);
- }
-
- return rval;
- }
-
- /**
- * @return The primary, most severe, SSL error in the set
- */
- public int getPrimaryError() {
- if (mErrors != 0) {
- // go from the most to the least severe errors
- for (int error = SslError.SSL_MAX_ERROR - 1; error >= 0; --error) {
- if ((mErrors & (0x1 << error)) != 0) {
- return error;
- }
- }
- }
-
- return 0;
- }
-
- /**
- * @return A String representation of this SSL error object
- * (used mostly for debugging).
- */
- public String toString() {
- return "primary error: " + getPrimaryError() +
- " certificate: " + getCertificate();
- }
-}
diff --git a/core/java/android/net/http/Timer.java b/core/java/android/net/http/Timer.java
deleted file mode 100644
index cc15a30..0000000
--- a/core/java/android/net/http/Timer.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import android.os.SystemClock;
-
-/**
- * {@hide}
- * Debugging tool
- */
-class Timer {
-
- private long mStart;
- private long mLast;
-
- public Timer() {
- mStart = mLast = SystemClock.uptimeMillis();
- }
-
- public void mark(String message) {
- long now = SystemClock.uptimeMillis();
- if (HttpLog.LOGV) {
- HttpLog.v(message + " " + (now - mLast) + " total " + (now - mStart));
- }
- mLast = now;
- }
-}
diff --git a/core/java/android/net/http/package.html b/core/java/android/net/http/package.html
deleted file mode 100755
index a81cbce..0000000
--- a/core/java/android/net/http/package.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<body>
-</body>
diff --git a/core/java/android/net/package.html b/core/java/android/net/package.html
deleted file mode 100755
index 47c57e6..0000000
--- a/core/java/android/net/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-Classes that help with network access, beyond the normal java.net.* APIs.
-
-</body>
diff --git a/core/java/android/os/AsyncResult.java b/core/java/android/os/AsyncResult.java
deleted file mode 100644
index 5bad09d..0000000
--- a/core/java/android/os/AsyncResult.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.os.Message;
-
-/** @hide */
-public class AsyncResult
-{
-
- /*************************** Instance Variables **************************/
-
- // Expect either exception or result to be null
- public Object userObj;
- public Throwable exception;
- public Object result;
-
- /***************************** Class Methods *****************************/
-
- /** Saves and sets m.obj */
- public static AsyncResult
- forMessage(Message m, Object r, Throwable ex)
- {
- AsyncResult ret;
-
- ret = new AsyncResult (m.obj, r, ex);
-
- m.obj = ret;
-
- return ret;
- }
-
- /** Saves and sets m.obj */
- public static AsyncResult
- forMessage(Message m)
- {
- AsyncResult ret;
-
- ret = new AsyncResult (m.obj, null, null);
-
- m.obj = ret;
-
- return ret;
- }
-
- /** please note, this sets m.obj to be this */
- public
- AsyncResult (Object uo, Object r, Throwable ex)
- {
- userObj = uo;
- result = r;
- exception = ex;
- }
-}
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
deleted file mode 100644
index ee4e897..0000000
--- a/core/java/android/os/AsyncTask.java
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.Callable;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * <p>AsyncTask enables proper and easy use of the UI thread. This class allows to
- * perform background operations and publish results on the UI thread without
- * having to manipulate threads and/or handlers.</p>
- *
- * <p>An asynchronous task is defined by a computation that runs on a background thread and
- * whose result is published on the UI thread. An asynchronous task is defined by 3 generic
- * types, called <code>Params</code>, <code>Progress</code> and <code>Result</code>,
- * and 4 steps, called <code>begin</code>, <code>doInBackground</code>,
- * <code>processProgress<code> and <code>end</code>.</p>
- *
- * <h2>Usage</h2>
- * <p>AsyncTask must be subclassed to be used. The subclass will override at least
- * one method ({@link #doInBackground}), and most often will override a
- * second one ({@link #onPostExecute}.)</p>
- *
- * <p>Here is an example of subclassing:</p>
- * <pre class="prettyprint">
- * private class DownloadFilesTask extends AsyncTask&lt;URL, Integer, Long&gt; {
- * protected Long doInBackground(URL... urls) {
- * int count = urls.length;
- * long totalSize = 0;
- * for (int i = 0; i < count; i++) {
- * totalSize += Downloader.downloadFile(urls[i]);
- * publishProgress((int) ((i / (float) count) * 100));
- * }
- * return totalSize;
- * }
- *
- * protected void onProgressUpdate(Integer... progress) {
- * setProgressPercent(progress[0]);
- * }
- *
- * protected void onPostExecute(Long result) {
- * showDialog("Downloaded " + result + " bytes");
- * }
- * }
- * </pre>
- *
- * <p>Once created, a task is executed very simply:</p>
- * <pre class="prettyprint">
- * new DownloadFilesTask().execute(url1, url2, url3);
- * </pre>
- *
- * <h2>AsyncTask's generic types</h2>
- * <p>The three types used by an asynchronous task are the following:</p>
- * <ol>
- * <li><code>Params</code>, the type of the parameters sent to the task upon
- * execution.</li>
- * <li><code>Progress</code>, the type of the progress units published during
- * the background computation.</li>
- * <li><code>Result</code>, the type of the result of the background
- * computation.</li>
- * </ol>
- * <p>Not all types are always used by am asynchronous task. To mark a type as unused,
- * simply use the type {@link Void}:</p>
- * <pre>
- * private class MyTask extends AsyncTask<Void, Void, Void) { ... }
- * </pre>
- *
- * <h2>The 4 steps</h2>
- * <p>When an asynchronous task is executed, the task goes through 4 steps:</p>
- * <ol>
- * <li>{@link #onPreExecute()}, invoked on the UI thread immediately after the task
- * is executed. This step is normally used to setup the task, for instance by
- * showing a progress bar in the user interface.</li>
- * <li>{@link #doInBackground}, invoked on the background thread
- * immediately after {@link #onPreExecute()} finishes executing. This step is used
- * to perform background computation that can take a long time. The parameters
- * of the asynchronous task are passed to this step. The result of the computation must
- * be returned by this step and will be passed back to the last step. This step
- * can also use {@link #publishProgress} to publish one or more units
- * of progress. These values are published on the UI thread, in the
- * {@link #onProgressUpdate} step.</li>
- * <li>{@link #onProgressUpdate}, invoked on the UI thread after a
- * call to {@link #publishProgress}. The timing of the execution is
- * undefined. This method is used to display any form of progress in the user
- * interface while the background computation is still executing. For instance,
- * it can be used to animate a progress bar or show logs in a text field.</li>
- * <li>{@link #onPostExecute}, invoked on the UI thread after the background
- * computation finishes. The result of the background computation is passed to
- * this step as a parameter.</li>
- * </ol>
- *
- * <h2>Threading rules</h2>
- * <p>There are a few threading rules that must be followed for this class to
- * work properly:</p>
- * <ul>
- * <li>The task instance must be created on the UI thread.</li>
- * <li>{@link #execute} must be invoked on the UI thread.</li>
- * <li>Do not call {@link #onPreExecute()}, {@link #onPostExecute},
- * {@link #doInBackground}, {@link #onProgressUpdate} manually.</li>
- * <li>The task can be executed only once (an exception will be thrown if
- * a second execution is attempted.)</li>
- * </ul>
- */
-public abstract class AsyncTask<Params, Progress, Result> {
- private static final String LOG_TAG = "AsyncTask";
-
- private static final int CORE_POOL_SIZE = 1;
- private static final int MAXIMUM_POOL_SIZE = 10;
- private static final int KEEP_ALIVE = 10;
-
- private static final BlockingQueue<Runnable> sWorkQueue =
- new LinkedBlockingQueue<Runnable>(MAXIMUM_POOL_SIZE);
-
- private static final ThreadFactory sThreadFactory = new ThreadFactory() {
- private final AtomicInteger mCount = new AtomicInteger(1);
-
- public Thread newThread(Runnable r) {
- return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
- }
- };
-
- private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
- MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);
-
- private static final int MESSAGE_POST_RESULT = 0x1;
- private static final int MESSAGE_POST_PROGRESS = 0x2;
- private static final int MESSAGE_POST_CANCEL = 0x3;
-
- private static final InternalHandler sHandler = new InternalHandler();
-
- private final WorkerRunnable<Params, Result> mWorker;
- private final FutureTask<Result> mFuture;
-
- private volatile Status mStatus = Status.PENDING;
-
- /**
- * Indicates the current status of the task. Each status will be set only once
- * during the lifetime of a task.
- */
- public enum Status {
- /**
- * Indicates that the task has not been executed yet.
- */
- PENDING,
- /**
- * Indicates that the task is running.
- */
- RUNNING,
- /**
- * Indicates that {@link AsyncTask#onPostExecute} has finished.
- */
- FINISHED,
- }
-
- /**
- * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
- */
- public AsyncTask() {
- mWorker = new WorkerRunnable<Params, Result>() {
- public Result call() throws Exception {
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- return doInBackground(mParams);
- }
- };
-
- mFuture = new FutureTask<Result>(mWorker) {
- @Override
- protected void done() {
- Message message;
- Result result = null;
-
- try {
- result = get();
- } catch (InterruptedException e) {
- android.util.Log.w(LOG_TAG, e);
- } catch (ExecutionException e) {
- throw new RuntimeException("An error occured while executing doInBackground()",
- e.getCause());
- } catch (CancellationException e) {
- message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
- new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
- message.sendToTarget();
- return;
- } catch (Throwable t) {
- throw new RuntimeException("An error occured while executing "
- + "doInBackground()", t);
- }
-
- message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
- new AsyncTaskResult<Result>(AsyncTask.this, result));
- message.sendToTarget();
- }
- };
- }
-
- /**
- * Returns the current status of this task.
- *
- * @return The current status.
- */
- public final Status getStatus() {
- return mStatus;
- }
-
- /**
- * Override this method to perform a computation on a background thread. The
- * specified parameters are the parameters passed to {@link #execute}
- * by the caller of this task.
- *
- * This method can call {@link #publishProgress} to publish updates
- * on the UI thread.
- *
- * @param params The parameters of the task.
- *
- * @return A result, defined by the subclass of this task.
- *
- * @see #onPreExecute()
- * @see #onPostExecute
- * @see #publishProgress
- */
- protected abstract Result doInBackground(Params... params);
-
- /**
- * Runs on the UI thread before {@link #doInBackground}.
- *
- * @see #onPostExecute
- * @see #doInBackground
- */
- protected void onPreExecute() {
- }
-
- /**
- * Runs on the UI thread after {@link #doInBackground}. The
- * specified result is the value returned by {@link #doInBackground}
- * or null if the task was cancelled or an exception occured.
- *
- * @param result The result of the operation computed by {@link #doInBackground}.
- *
- * @see #onPreExecute
- * @see #doInBackground
- */
- @SuppressWarnings({"UnusedDeclaration"})
- protected void onPostExecute(Result result) {
- }
-
- /**
- * Runs on the UI thread after {@link #publishProgress} is invoked.
- * The specified values are the values passed to {@link #publishProgress}.
- *
- * @param values The values indicating progress.
- *
- * @see #publishProgress
- * @see #doInBackground
- */
- @SuppressWarnings({"UnusedDeclaration"})
- protected void onProgressUpdate(Progress... values) {
- }
-
- /**
- * Runs on the UI thread after {@link #cancel(boolean)} is invoked.
- *
- * @see #cancel(boolean)
- * @see #isCancelled()
- */
- protected void onCancelled() {
- }
-
- /**
- * Returns <tt>true</tt> if this task was cancelled before it completed
- * normally.
- *
- * @return <tt>true</tt> if task was cancelled before it completed
- *
- * @see #cancel(boolean)
- */
- public final boolean isCancelled() {
- return mFuture.isCancelled();
- }
-
- /**
- * Attempts to cancel execution of this task. This attempt will
- * fail if the task has already completed, already been cancelled,
- * or could not be cancelled for some other reason. If successful,
- * and this task has not started when <tt>cancel</tt> is called,
- * this task should never run. If the task has already started,
- * then the <tt>mayInterruptIfRunning</tt> parameter determines
- * whether the thread executing this task should be interrupted in
- * an attempt to stop the task.
- *
- * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
- * task should be interrupted; otherwise, in-progress tasks are allowed
- * to complete.
- *
- * @return <tt>false</tt> if the task could not be cancelled,
- * typically because it has already completed normally;
- * <tt>true</tt> otherwise
- *
- * @see #isCancelled()
- * @see #onCancelled()
- */
- public final boolean cancel(boolean mayInterruptIfRunning) {
- return mFuture.cancel(mayInterruptIfRunning);
- }
-
- /**
- * Waits if necessary for the computation to complete, and then
- * retrieves its result.
- *
- * @return The computed result.
- *
- * @throws CancellationException If the computation was cancelled.
- * @throws ExecutionException If the computation threw an exception.
- * @throws InterruptedException If the current thread was interrupted
- * while waiting.
- */
- public final Result get() throws InterruptedException, ExecutionException {
- return mFuture.get();
- }
-
- /**
- * Waits if necessary for at most the given time for the computation
- * to complete, and then retrieves its result.
- *
- * @param timeout Time to wait before cancelling the operation.
- * @param unit The time unit for the timeout.
- *
- * @return The computed result.
- *
- * @throws CancellationException If the computation was cancelled.
- * @throws ExecutionException If the computation threw an exception.
- * @throws InterruptedException If the current thread was interrupted
- * while waiting.
- * @throws TimeoutException If the wait timed out.
- */
- public final Result get(long timeout, TimeUnit unit) throws InterruptedException,
- ExecutionException, TimeoutException {
- return mFuture.get(timeout, unit);
- }
-
- /**
- * Executes the task with the specified parameters. The task returns
- * itself (this) so that the caller can keep a reference to it.
- *
- * This method must be invoked on the UI thread.
- *
- * @param params The parameters of the task.
- *
- * @return This instance of AsyncTask.
- *
- * @throws IllegalStateException If {@link #getStatus()} returns either
- * {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
- */
- public final AsyncTask<Params, Progress, Result> execute(Params... params) {
- if (mStatus != Status.PENDING) {
- switch (mStatus) {
- case RUNNING:
- throw new IllegalStateException("Cannot execute task:"
- + " the task is already running.");
- case FINISHED:
- throw new IllegalStateException("Cannot execute task:"
- + " the task has already been executed "
- + "(a task can be executed only once)");
- }
- }
-
- mStatus = Status.RUNNING;
-
- onPreExecute();
-
- mWorker.mParams = params;
- sExecutor.execute(mFuture);
-
- return this;
- }
-
- /**
- * This method can be invoked from {@link #doInBackground} to
- * publish updates on the UI thread while the background computation is
- * still running. Each call to this method will trigger the execution of
- * {@link #onProgressUpdate} on the UI thread.
- *
- * @param values The progress values to update the UI with.
- *
- * @see #onProgressUpdate
- * @see #doInBackground
- */
- protected final void publishProgress(Progress... values) {
- sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
- new AsyncTaskResult<Progress>(this, values)).sendToTarget();
- }
-
- private void finish(Result result) {
- onPostExecute(result);
- mStatus = Status.FINISHED;
- }
-
- private static class InternalHandler extends Handler {
- @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
- @Override
- public void handleMessage(Message msg) {
- AsyncTaskResult result = (AsyncTaskResult) msg.obj;
- switch (msg.what) {
- case MESSAGE_POST_RESULT:
- // There is only one result
- result.mTask.finish(result.mData[0]);
- break;
- case MESSAGE_POST_PROGRESS:
- result.mTask.onProgressUpdate(result.mData);
- break;
- case MESSAGE_POST_CANCEL:
- result.mTask.onCancelled();
- break;
- }
- }
- }
-
- private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
- Params[] mParams;
- }
-
- @SuppressWarnings({"RawUseOfParameterizedType"})
- private static class AsyncTaskResult<Data> {
- final AsyncTask mTask;
- final Data[] mData;
-
- AsyncTaskResult(AsyncTask task, Data... data) {
- mTask = task;
- mData = data;
- }
- }
-}
diff --git a/core/java/android/os/BadParcelableException.java b/core/java/android/os/BadParcelableException.java
deleted file mode 100644
index a1c5bb2..0000000
--- a/core/java/android/os/BadParcelableException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-import android.util.AndroidRuntimeException;
-
-/**
- * The object you are calling has died, because its hosting process
- * no longer exists.
- */
-public class BadParcelableException extends AndroidRuntimeException {
- public BadParcelableException(String msg) {
- super(msg);
- }
- public BadParcelableException(Exception cause) {
- super(cause);
- }
-}
diff --git a/core/java/android/os/Base64Utils.java b/core/java/android/os/Base64Utils.java
deleted file mode 100644
index 684a469..0000000
--- a/core/java/android/os/Base64Utils.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * {@hide}
- */
-public class Base64Utils
-{
- // TODO add encode api here if possible
-
- public static byte [] decodeBase64(String data) {
- return decodeBase64Native(data);
- }
- private static native byte[] decodeBase64Native(String data);
-}
-
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
deleted file mode 100644
index 8f1a756..0000000
--- a/core/java/android/os/BatteryManager.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * The BatteryManager class contains strings and constants used for values
- * in the ACTION_BATTERY_CHANGED Intent.
- */
-public class BatteryManager {
-
- // values for "status" field in the ACTION_BATTERY_CHANGED Intent
- public static final int BATTERY_STATUS_UNKNOWN = 1;
- public static final int BATTERY_STATUS_CHARGING = 2;
- public static final int BATTERY_STATUS_DISCHARGING = 3;
- public static final int BATTERY_STATUS_NOT_CHARGING = 4;
- public static final int BATTERY_STATUS_FULL = 5;
-
- // values for "health" field in the ACTION_BATTERY_CHANGED Intent
- public static final int BATTERY_HEALTH_UNKNOWN = 1;
- public static final int BATTERY_HEALTH_GOOD = 2;
- public static final int BATTERY_HEALTH_OVERHEAT = 3;
- public static final int BATTERY_HEALTH_DEAD = 4;
- public static final int BATTERY_HEALTH_OVER_VOLTAGE = 5;
- public static final int BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6;
-
- // values of the "plugged" field in the ACTION_BATTERY_CHANGED intent.
- // These must be powers of 2.
- /** Power source is an AC charger. */
- public static final int BATTERY_PLUGGED_AC = 1;
- /** Power source is a USB port. */
- public static final int BATTERY_PLUGGED_USB = 2;
-}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
deleted file mode 100644
index 6f9d6c6..0000000
--- a/core/java/android/os/BatteryStats.java
+++ /dev/null
@@ -1,795 +0,0 @@
-package android.os;
-
-import java.io.PrintWriter;
-import java.util.Formatter;
-import java.util.Map;
-
-import android.util.Log;
-import android.util.Printer;
-import android.util.SparseArray;
-
-/**
- * A class providing access to battery usage statistics, including information on
- * wakelocks, processes, packages, and services. All times are represented in microseconds
- * except where indicated otherwise.
- * @hide
- */
-public abstract class BatteryStats implements Parcelable {
-
- /**
- * A constant indicating a partial wake lock timer.
- */
- public static final int WAKE_TYPE_PARTIAL = 0;
-
- /**
- * A constant indicating a full wake lock timer.
- */
- public static final int WAKE_TYPE_FULL = 1;
-
- /**
- * A constant indicating a window wake lock timer.
- */
- public static final int WAKE_TYPE_WINDOW = 2;
-
- /**
- * A constant indicating a sensor timer.
- *
- * {@hide}
- */
- public static final int SENSOR = 3;
-
- /**
- * Include all of the data in the stats, including previously saved data.
- */
- public static final int STATS_TOTAL = 0;
-
- /**
- * Include only the last run in the stats.
- */
- public static final int STATS_LAST = 1;
-
- /**
- * Include only the current run in the stats.
- */
- public static final int STATS_CURRENT = 2;
-
- /**
- * Include only the run since the last time the device was unplugged in the stats.
- */
- public static final int STATS_UNPLUGGED = 3;
-
- /**
- * Bump the version on this if the checkin format changes.
- */
- private static final int BATTERY_STATS_CHECKIN_VERSION = 1;
-
- // TODO: Update this list if you add/change any stats above.
- private static final String[] STAT_NAMES = { "total", "last", "current", "unplugged" };
-
- private static final String APK_DATA = "apk";
- private static final String PROCESS_DATA = "process";
- private static final String SENSOR_DATA = "sensor";
- private static final String WAKELOCK_DATA = "wakelock";
- private static final String NETWORK_DATA = "network";
- private static final String BATTERY_DATA = "battery";
-
- private final StringBuilder mFormatBuilder = new StringBuilder(8);
- private final Formatter mFormatter = new Formatter(mFormatBuilder);
-
- /**
- * State for keeping track of timing information.
- */
- public static abstract class Timer {
-
- /**
- * Returns the count associated with this Timer for the
- * selected type of statistics.
- *
- * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
- */
- public abstract int getCount(int which);
-
- /**
- * Returns the total time in microseconds associated with this Timer for the
- * selected type of statistics.
- *
- * @param now system uptime time in microseconds
- * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
- * @return a time in microseconds
- */
- public abstract long getTotalTime(long now, int which);
-
- /**
- * Temporary for debugging.
- */
- public abstract void logState();
- }
-
- /**
- * The statistics associated with a particular uid.
- */
- public static abstract class Uid {
-
- /**
- * Returns a mapping containing wakelock statistics.
- *
- * @return a Map from Strings to Uid.Wakelock objects.
- */
- public abstract Map<String, ? extends Wakelock> getWakelockStats();
-
- /**
- * The statistics associated with a particular wake lock.
- */
- public static abstract class Wakelock {
- public abstract Timer getWakeTime(int type);
- }
-
- /**
- * Returns a mapping containing sensor statistics.
- *
- * @return a Map from Integer sensor ids to Uid.Sensor objects.
- */
- public abstract Map<Integer, ? extends Sensor> getSensorStats();
-
- /**
- * Returns a mapping containing process statistics.
- *
- * @return a Map from Strings to Uid.Proc objects.
- */
- public abstract Map<String, ? extends Proc> getProcessStats();
-
- /**
- * Returns a mapping containing package statistics.
- *
- * @return a Map from Strings to Uid.Pkg objects.
- */
- public abstract Map<String, ? extends Pkg> getPackageStats();
-
- /**
- * {@hide}
- */
- public abstract int getUid();
-
- /**
- * {@hide}
- */
- public abstract long getTcpBytesReceived(int which);
-
- /**
- * {@hide}
- */
- public abstract long getTcpBytesSent(int which);
-
- public static abstract class Sensor {
- // Magic sensor number for the GPS.
- public static final int GPS = -10000;
-
- public abstract int getHandle();
-
- public abstract Timer getSensorTime();
- }
-
- /**
- * The statistics associated with a particular process.
- */
- public static abstract class Proc {
-
- /**
- * Returns the total time (in 1/100 sec) spent executing in user code.
- *
- * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
- */
- public abstract long getUserTime(int which);
-
- /**
- * Returns the total time (in 1/100 sec) spent executing in system code.
- *
- * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
- */
- public abstract long getSystemTime(int which);
-
- /**
- * Returns the number of times the process has been started.
- *
- * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
- */
- public abstract int getStarts(int which);
- }
-
- /**
- * The statistics associated with a particular package.
- */
- public static abstract class Pkg {
-
- /**
- * Returns the number of times this package has done something that could wake up the
- * device from sleep.
- *
- * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
- */
- public abstract int getWakeups(int which);
-
- /**
- * Returns a mapping containing service statistics.
- */
- public abstract Map<String, ? extends Serv> getServiceStats();
-
- /**
- * The statistics associated with a particular service.
- */
- public abstract class Serv {
-
- /**
- * Returns the amount of time spent started.
- *
- * @param now elapsed realtime in microseconds.
- * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
- * @return
- */
- public abstract long getStartTime(long now, int which);
-
- /**
- * Returns the total number of times startService() has been called.
- *
- * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
- */
- public abstract int getStarts(int which);
-
- /**
- * Returns the total number times the service has been launched.
- *
- * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
- */
- public abstract int getLaunches(int which);
- }
- }
- }
-
- /**
- * Returns the number of times the device has been started.
- */
- public abstract int getStartCount();
-
- /**
- * Returns the time in milliseconds that the screen has been on while the device was
- * running on battery.
- *
- * {@hide}
- */
- public abstract long getBatteryScreenOnTime();
-
- /**
- * Returns the time in milliseconds that the screen has been on while the device was
- * plugged in.
- *
- * {@hide}
- */
- public abstract long getPluggedScreenOnTime();
-
- /**
- * Return whether we are currently running on battery.
- */
- public abstract boolean getIsOnBattery();
-
- /**
- * Returns a SparseArray containing the statistics for each uid.
- */
- public abstract SparseArray<? extends Uid> getUidStats();
-
- /**
- * Returns the current battery uptime in microseconds.
- *
- * @param curTime the amount of elapsed realtime in microseconds.
- */
- public abstract long getBatteryUptime(long curTime);
-
- /**
- * Returns the current battery realtime in microseconds.
- *
- * @param curTime the amount of elapsed realtime in microseconds.
- */
- public abstract long getBatteryRealtime(long curTime);
-
- /**
- * Returns the total, last, or current battery uptime in microseconds.
- *
- * @param curTime the elapsed realtime in microseconds.
- * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
- */
- public abstract long computeBatteryUptime(long curTime, int which);
-
- /**
- * Returns the total, last, or current battery realtime in microseconds.
- *
- * @param curTime the current elapsed realtime in microseconds.
- * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
- */
- public abstract long computeBatteryRealtime(long curTime, int which);
-
- /**
- * Returns the total, last, or current uptime in microseconds.
- *
- * @param curTime the current elapsed realtime in microseconds.
- * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
- */
- public abstract long computeUptime(long curTime, int which);
-
- /**
- * Returns the total, last, or current realtime in microseconds.
- * *
- * @param curTime the current elapsed realtime in microseconds.
- * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
- */
- public abstract long computeRealtime(long curTime, int which);
-
- private final static void formatTime(StringBuilder out, long seconds) {
- long days = seconds / (60 * 60 * 24);
- if (days != 0) {
- out.append(days);
- out.append("d ");
- }
- long used = days * 60 * 60 * 24;
-
- long hours = (seconds - used) / (60 * 60);
- if (hours != 0 || used != 0) {
- out.append(hours);
- out.append("h ");
- }
- used += hours * 60 * 60;
-
- long mins = (seconds-used) / 60;
- if (mins != 0 || used != 0) {
- out.append(mins);
- out.append("m ");
- }
- used += mins * 60;
-
- if (seconds != 0 || used != 0) {
- out.append(seconds-used);
- out.append("s ");
- }
- }
-
- private final static String formatTime(long time) {
- long sec = time / 100;
- StringBuilder sb = new StringBuilder();
- formatTime(sb, sec);
- sb.append((time - (sec * 100)) * 10);
- sb.append("ms ");
- return sb.toString();
- }
-
- private final static String formatTimeMs(long time) {
- long sec = time / 1000;
- StringBuilder sb = new StringBuilder();
- formatTime(sb, sec);
- sb.append(time - (sec * 1000));
- sb.append("ms ");
- return sb.toString();
- }
-
- private final String formatRatioLocked(long num, long den) {
- if (den == 0L) {
- return "---%";
- }
- float perc = ((float)num) / ((float)den) * 100;
- mFormatBuilder.setLength(0);
- mFormatter.format("%.1f%%", perc);
- return mFormatBuilder.toString();
- }
-
- /**
- *
- * @param sb a StringBuilder object.
- * @param timer a Timer object contining the wakelock times.
- * @param now the current time in microseconds.
- * @param name the name of the wakelock.
- * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
- * @param linePrefix a String to be prepended to each line of output.
- * @return the line prefix
- */
- private static final String printWakeLock(StringBuilder sb, Timer timer, long now,
- String name, int which, String linePrefix) {
-
- if (timer != null) {
- // Convert from microseconds to milliseconds with rounding
- long totalTimeMicros = timer.getTotalTime(now, which);
- long totalTimeMillis = (totalTimeMicros + 500) / 1000;
-
- int count = timer.getCount(which);
- if (totalTimeMillis != 0) {
- sb.append(linePrefix);
- sb.append(formatTimeMs(totalTimeMillis));
- sb.append(name);
- sb.append(' ');
- sb.append('(');
- sb.append(count);
- sb.append(" times)");
- return ", ";
- }
- }
- return linePrefix;
- }
-
- /**
- * Checkin version of wakelock printer. Prints simple comma-separated list.
- *
- * @param sb a StringBuilder object.
- * @param timer a Timer object contining the wakelock times.
- * @param now the current time in microseconds.
- * @param name the name of the wakelock.
- * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
- * @param linePrefix a String to be prepended to each line of output.
- * @return the line prefix
- */
- private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now,
- String name, int which, String linePrefix) {
- long totalTimeMicros = 0;
- int count = 0;
- if (timer != null) {
- totalTimeMicros = timer.getTotalTime(now, which);
- count = timer.getCount(which);
- }
- sb.append(linePrefix);
- sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
- sb.append(',');
- sb.append(name);
- sb.append(',');
- sb.append(count);
- return ",";
- }
-
- /**
- * Dump a comma-separated line of values for terse checkin mode.
- *
- * @param pw the PageWriter to dump log to
- * @param category category of data (e.g. "total", "last", "unplugged", "current" )
- * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" , "process", "network")
- * @param args type-dependent data arguments
- */
- private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
- Object... args ) {
- pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
- pw.print(uid); pw.print(',');
- pw.print(category); pw.print(',');
- pw.print(type);
-
- for (Object arg : args) {
- pw.print(',');
- pw.print(arg);
- }
- pw.print('\n');
- }
-
- /**
- * Checkin server version of dump to produce more compact, computer-readable log.
- *
- * NOTE: all times are expressed in 'ms'.
- * @param fd
- * @param pw
- * @param which
- */
- private final void dumpCheckinLocked(PrintWriter pw, int which) {
- long uSecTime = SystemClock.elapsedRealtime() * 1000;
- final long uSecNow = getBatteryUptime(uSecTime);
-
- StringBuilder sb = new StringBuilder(128);
- long batteryUptime = computeBatteryUptime(uSecNow, which);
- long batteryRealtime = computeBatteryRealtime(getBatteryRealtime(uSecTime), which);
- long elapsedRealtime = computeRealtime(uSecTime, which);
- long uptime = computeUptime(SystemClock.uptimeMillis() * 1000, which);
-
- String category = STAT_NAMES[which];
-
- // Dump "battery" stat
- dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
- which == STATS_TOTAL ? getStartCount() : "N/A",
- batteryUptime / 1000,
- formatRatioLocked(batteryUptime, elapsedRealtime),
- batteryRealtime / 1000,
- formatRatioLocked(batteryRealtime, elapsedRealtime),
- uptime / 1000,
- elapsedRealtime / 1000);
-
- SparseArray<? extends Uid> uidStats = getUidStats();
- final int NU = uidStats.size();
- for (int iu = 0; iu < NU; iu++) {
- final int uid = uidStats.keyAt(iu);
- Uid u = uidStats.valueAt(iu);
- // Dump Network stats per uid, if any
- long rx = u.getTcpBytesReceived(which);
- long tx = u.getTcpBytesSent(which);
- if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
-
- Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
- if (wakelocks.size() > 0) {
- for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
- : wakelocks.entrySet()) {
- Uid.Wakelock wl = ent.getValue();
- String linePrefix = "";
- sb.setLength(0);
- linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), uSecNow,
- "full", which, linePrefix);
- linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), uSecNow,
- "partial", which, linePrefix);
- linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), uSecNow,
- "window", which, linePrefix);
-
- // Only log if we had at lease one wakelock...
- if (sb.length() > 0) {
- dumpLine(pw, uid, category, WAKELOCK_DATA, ent.getKey(), sb.toString());
- }
- }
- }
-
- Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
- if (sensors.size() > 0) {
- for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
- : sensors.entrySet()) {
- Uid.Sensor se = ent.getValue();
- int sensorNumber = ent.getKey();
- Timer timer = se.getSensorTime();
- if (timer != null) {
- // Convert from microseconds to milliseconds with rounding
- long totalTime = (timer.getTotalTime(uSecNow, which) + 500) / 1000;
- int count = timer.getCount(which);
- if (totalTime != 0) {
- dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
- }
- }
- }
- }
-
- Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
- if (processStats.size() > 0) {
- for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
- : processStats.entrySet()) {
- Uid.Proc ps = ent.getValue();
-
- long userTime = ps.getUserTime(which);
- long systemTime = ps.getSystemTime(which);
- int starts = ps.getStarts(which);
-
- if (userTime != 0 || systemTime != 0 || starts != 0) {
- dumpLine(pw, uid, category, PROCESS_DATA,
- ent.getKey(), // proc
- userTime * 10, // cpu time in ms
- systemTime * 10, // user time in ms
- starts); // process starts
- }
- }
- }
-
- Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
- if (packageStats.size() > 0) {
- for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
- : packageStats.entrySet()) {
-
- Uid.Pkg ps = ent.getValue();
- int wakeups = ps.getWakeups(which);
- Map<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
- for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
- : serviceStats.entrySet()) {
- BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
- long startTime = ss.getStartTime(uSecNow, which);
- int starts = ss.getStarts(which);
- int launches = ss.getLaunches(which);
- if (startTime != 0 || starts != 0 || launches != 0) {
- dumpLine(pw, uid, category, APK_DATA,
- wakeups, // wakeup alarms
- ent.getKey(), // Apk
- sent.getKey(), // service
- startTime / 1000, // time spent started, in ms
- starts,
- launches);
- }
- }
- }
- }
- }
- }
-
- @SuppressWarnings("unused")
- private final void dumpLocked(Printer pw, String prefix, int which) {
- long uSecTime = SystemClock.elapsedRealtime() * 1000;
- final long uSecNow = getBatteryUptime(uSecTime);
-
- StringBuilder sb = new StringBuilder(128);
- long batteryUptime = computeBatteryUptime(uSecNow, which);
- long batteryRealtime = computeBatteryRealtime(getBatteryRealtime(uSecTime), which);
- long elapsedRealtime = computeRealtime(uSecTime, which);
- long uptime = computeUptime(SystemClock.uptimeMillis() * 1000, which);
-
- pw.println(prefix
- + " Time on battery: " + formatTimeMs(batteryUptime / 1000) + "("
- + formatRatioLocked(batteryUptime, elapsedRealtime)
- + ") uptime, "
- + formatTimeMs(batteryRealtime / 1000) + "("
- + formatRatioLocked(batteryRealtime, elapsedRealtime)
- + ") realtime");
- pw.println(prefix
- + " Total: "
- + formatTimeMs(uptime / 1000)
- + "uptime, "
- + formatTimeMs(elapsedRealtime / 1000)
- + "realtime");
-
- pw.println(" ");
-
- SparseArray<? extends Uid> uidStats = getUidStats();
- final int NU = uidStats.size();
- for (int iu=0; iu<NU; iu++) {
- final int uid = uidStats.keyAt(iu);
- Uid u = uidStats.valueAt(iu);
- pw.println(prefix + " #" + uid + ":");
- boolean uidActivity = false;
-
- long tcpReceived = u.getTcpBytesReceived(which);
- long tcpSent = u.getTcpBytesSent(which);
- if (tcpReceived != 0 || tcpSent != 0) {
- pw.println(prefix + " Network: " + tcpReceived + " bytes received, "
- + tcpSent + " bytes sent");
- }
-
- Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
- if (wakelocks.size() > 0) {
- for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
- : wakelocks.entrySet()) {
- Uid.Wakelock wl = ent.getValue();
- String linePrefix = ": ";
- sb.setLength(0);
- sb.append(prefix);
- sb.append(" Wake lock ");
- sb.append(ent.getKey());
- linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), uSecNow,
- "full", which, linePrefix);
- linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), uSecNow,
- "partial", which, linePrefix);
- linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), uSecNow,
- "window", which, linePrefix);
- if (!linePrefix.equals(": ")) {
- sb.append(" realtime");
- } else {
- sb.append(": (nothing executed)");
- }
- pw.println(sb.toString());
- uidActivity = true;
- }
- }
-
- Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
- if (sensors.size() > 0) {
- for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
- : sensors.entrySet()) {
- Uid.Sensor se = ent.getValue();
- int sensorNumber = ent.getKey();
- sb.setLength(0);
- sb.append(prefix);
- sb.append(" Sensor ");
- int handle = se.getHandle();
- if (handle == Uid.Sensor.GPS) {
- sb.append("GPS");
- } else {
- sb.append(handle);
- }
- sb.append(": ");
-
- Timer timer = se.getSensorTime();
- if (timer != null) {
- // Convert from microseconds to milliseconds with rounding
- long totalTime = (timer.getTotalTime(uSecNow, which) + 500) / 1000;
- int count = timer.getCount(which);
- //timer.logState();
- if (totalTime != 0) {
- sb.append(formatTimeMs(totalTime));
- sb.append("realtime (");
- sb.append(count);
- sb.append(" times)");
- } else {
- sb.append("(not used)");
- }
- } else {
- sb.append("(not used)");
- }
-
- pw.println(sb.toString());
- uidActivity = true;
- }
- }
-
- Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
- if (processStats.size() > 0) {
- for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
- : processStats.entrySet()) {
- Uid.Proc ps = ent.getValue();
- long userTime;
- long systemTime;
- int starts;
-
- userTime = ps.getUserTime(which);
- systemTime = ps.getSystemTime(which);
- starts = ps.getStarts(which);
-
- if (userTime != 0 || systemTime != 0 || starts != 0) {
- pw.println(prefix + " Proc " + ent.getKey() + ":");
- pw.println(prefix + " CPU: " + formatTime(userTime) + "user + "
- + formatTime(systemTime) + "kernel");
- pw.println(prefix + " " + starts + " process starts");
- uidActivity = true;
- }
- }
- }
-
- Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
- if (packageStats.size() > 0) {
- for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
- : packageStats.entrySet()) {
- pw.println(prefix + " Apk " + ent.getKey() + ":");
- boolean apkActivity = false;
- Uid.Pkg ps = ent.getValue();
- int wakeups = ps.getWakeups(which);
- if (wakeups != 0) {
- pw.println(prefix + " " + wakeups + " wakeup alarms");
- apkActivity = true;
- }
- Map<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
- if (serviceStats.size() > 0) {
- for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
- : serviceStats.entrySet()) {
- BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
- long startTime = ss.getStartTime(uSecNow, which);
- int starts = ss.getStarts(which);
- int launches = ss.getLaunches(which);
- if (startTime != 0 || starts != 0 || launches != 0) {
- pw.println(prefix + " Service " + sent.getKey() + ":");
- pw.println(prefix + " Created for: "
- + formatTimeMs(startTime / 1000)
- + " uptime");
- pw.println(prefix + " Starts: " + starts
- + ", launches: " + launches);
- apkActivity = true;
- }
- }
- }
- if (!apkActivity) {
- pw.println(prefix + " (nothing executed)");
- }
- uidActivity = true;
- }
- }
- if (!uidActivity) {
- pw.println(prefix + " (nothing executed)");
- }
- }
- }
-
- /**
- * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
- *
- * @param pw a Printer to receive the dump output.
- */
- @SuppressWarnings("unused")
- public void dumpLocked(Printer pw) {
- pw.println("Total Statistics (Current and Historic):");
- pw.println(" System starts: " + getStartCount()
- + ", currently on battery: " + getIsOnBattery());
- dumpLocked(pw, "", STATS_TOTAL);
- pw.println("");
- pw.println("Last Run Statistics (Previous run of system):");
- dumpLocked(pw, "", STATS_LAST);
- pw.println("");
- pw.println("Current Battery Statistics (Currently running system):");
- dumpLocked(pw, "", STATS_CURRENT);
- pw.println("");
- pw.println("Unplugged Statistics (Since last unplugged from power):");
- dumpLocked(pw, "", STATS_UNPLUGGED);
- }
-
- @SuppressWarnings("unused")
- public void dumpCheckinLocked(PrintWriter pw, String[] args) {
- dumpCheckinLocked(pw, STATS_TOTAL);
- dumpCheckinLocked(pw, STATS_LAST);
- dumpCheckinLocked(pw, STATS_UNPLUGGED);
- dumpCheckinLocked(pw, STATS_CURRENT);
- }
-}
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
deleted file mode 100644
index df10c6a..0000000
--- a/core/java/android/os/Binder.java
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.util.Config;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.Modifier;
-
-/**
- * Base class for a remotable object, the core part of a lightweight
- * remote procedure call mechanism defined by {@link IBinder}.
- * This class is an implementation of IBinder that provides
- * the standard support creating a local implementation of such an object.
- *
- * <p>Most developers will not implement this class directly, instead using the
- * <a href="{@docRoot}guide/developing/tools/aidl.html">aidl</a> tool to describe the desired
- * interface, having it generate the appropriate Binder subclass. You can,
- * however, derive directly from Binder to implement your own custom RPC
- * protocol or simply instantiate a raw Binder object directly to use as a
- * token that can be shared across processes.
- *
- * @see IBinder
- */
-public class Binder implements IBinder {
- /*
- * Set this flag to true to detect anonymous, local or member classes
- * that extend this Binder class and that are not static. These kind
- * of classes can potentially create leaks.
- */
- private static final boolean FIND_POTENTIAL_LEAKS = false;
- private static final String TAG = "Binder";
-
- private int mObject;
- private IInterface mOwner;
- private String mDescriptor;
-
- /**
- * Return the ID of the process that sent you the current transaction
- * that is being processed. This pid can be used with higher-level
- * system services to determine its identity and check permissions.
- * If the current thread is not currently executing an incoming transaction,
- * then its own pid is returned.
- */
- public static final native int getCallingPid();
-
- /**
- * Return the ID of the user assigned to the process that sent you the
- * current transaction that is being processed. This uid can be used with
- * higher-level system services to determine its identity and check
- * permissions. If the current thread is not currently executing an
- * incoming transaction, then its own uid is returned.
- */
- public static final native int getCallingUid();
-
- /**
- * Reset the identity of the incoming IPC to the local process. This can
- * be useful if, while handling an incoming call, you will be calling
- * on interfaces of other objects that may be local to your process and
- * need to do permission checks on the calls coming into them (so they
- * will check the permission of your own local process, and not whatever
- * process originally called you).
- *
- * @return Returns an opaque token that can be used to restore the
- * original calling identity by passing it to
- * {@link #restoreCallingIdentity(long)}.
- *
- * @see #getCallingPid()
- * @see #getCallingUid()
- * @see #restoreCallingIdentity(long)
- */
- public static final native long clearCallingIdentity();
-
- /**
- * Restore the identity of the incoming IPC back to a previously identity
- * that was returned by {@link #clearCallingIdentity}.
- *
- * @param token The opaque token that was previously returned by
- * {@link #clearCallingIdentity}.
- *
- * @see #clearCallingIdentity
- */
- public static final native void restoreCallingIdentity(long token);
-
- /**
- * Flush any Binder commands pending in the current thread to the kernel
- * driver. This can be
- * useful to call before performing an operation that may block for a long
- * time, to ensure that any pending object references have been released
- * in order to prevent the process from holding on to objects longer than
- * it needs to.
- */
- public static final native void flushPendingCommands();
-
- /**
- * Add the calling thread to the IPC thread pool. This function does
- * not return until the current process is exiting.
- */
- public static final native void joinThreadPool();
-
- /**
- * Default constructor initializes the object.
- */
- public Binder() {
- init();
-
- if (FIND_POTENTIAL_LEAKS) {
- final Class<? extends Binder> klass = getClass();
- if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
- (klass.getModifiers() & Modifier.STATIC) == 0) {
- Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
- klass.getCanonicalName());
- }
- }
- }
-
- /**
- * Convenience method for associating a specific interface with the Binder.
- * After calling, queryLocalInterface() will be implemented for you
- * to return the given owner IInterface when the corresponding
- * descriptor is requested.
- */
- public void attachInterface(IInterface owner, String descriptor) {
- mOwner = owner;
- mDescriptor = descriptor;
- }
-
- /**
- * Default implementation returns an empty interface name.
- */
- public String getInterfaceDescriptor() {
- return mDescriptor;
- }
-
- /**
- * Default implementation always returns true -- if you got here,
- * the object is alive.
- */
- public boolean pingBinder() {
- return true;
- }
-
- /**
- * {@inheritDoc}
- *
- * Note that if you're calling on a local binder, this always returns true
- * because your process is alive if you're calling it.
- */
- public boolean isBinderAlive() {
- return true;
- }
-
- /**
- * Use information supplied to attachInterface() to return the
- * associated IInterface if it matches the requested
- * descriptor.
- */
- public IInterface queryLocalInterface(String descriptor) {
- if (mDescriptor.equals(descriptor)) {
- return mOwner;
- }
- return null;
- }
-
- /**
- * Default implementation is a stub that returns false. You will want
- * to override this to do the appropriate unmarshalling of transactions.
- *
- * <p>If you want to call this, call transact().
- */
- protected boolean onTransact(int code, Parcel data, Parcel reply,
- int flags) throws RemoteException {
- if (code == INTERFACE_TRANSACTION) {
- reply.writeString(getInterfaceDescriptor());
- return true;
- } else if (code == DUMP_TRANSACTION) {
- ParcelFileDescriptor fd = data.readFileDescriptor();
- String[] args = data.readStringArray();
- if (fd != null) {
- try {
- dump(fd.getFileDescriptor(), args);
- } finally {
- try {
- fd.close();
- } catch (IOException e) {
- }
- }
- }
- return true;
- }
- return false;
- }
-
- /**
- * Implemented to call the more convenient version
- * {@link #dump(FileDescriptor, PrintWriter, String[])}.
- */
- public void dump(FileDescriptor fd, String[] args) {
- FileOutputStream fout = new FileOutputStream(fd);
- PrintWriter pw = new PrintWriter(fout);
- try {
- dump(fd, pw, args);
- } finally {
- pw.flush();
- }
- }
-
- /**
- * Print the object's state into the given stream.
- *
- * @param fd The raw file descriptor that the dump is being sent to.
- * @param fout The file to which you should dump your state. This will be
- * closed for you after you return.
- * @param args additional arguments to the dump request.
- */
- protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
- }
-
- /**
- * Default implementation rewinds the parcels and calls onTransact. On
- * the remote side, transact calls into the binder to do the IPC.
- */
- public final boolean transact(int code, Parcel data, Parcel reply,
- int flags) throws RemoteException {
- if (Config.LOGV) Log.v("Binder", "Transact: " + code + " to " + this);
- if (data != null) {
- data.setDataPosition(0);
- }
- boolean r = onTransact(code, data, reply, flags);
- if (reply != null) {
- reply.setDataPosition(0);
- }
- return r;
- }
-
- /**
- * Local implementation is a no-op.
- */
- public void linkToDeath(DeathRecipient recipient, int flags) {
- }
-
- /**
- * Local implementation is a no-op.
- */
- public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
- return true;
- }
-
- protected void finalize() throws Throwable {
- try {
- destroy();
- } finally {
- super.finalize();
- }
- }
-
- private native final void init();
- private native final void destroy();
- private boolean execTransact(int code, int dataObj, int replyObj,
- int flags) {
- Parcel data = Parcel.obtain(dataObj);
- Parcel reply = Parcel.obtain(replyObj);
- // theoretically, we should call transact, which will call onTransact,
- // but all that does is rewind it, and we just got these from an IPC,
- // so we'll just call it directly.
- boolean res;
- try {
- res = onTransact(code, data, reply, flags);
- } catch (RemoteException e) {
- reply.writeException(e);
- res = true;
- } catch (RuntimeException e) {
- reply.writeException(e);
- res = true;
- }
- reply.recycle();
- data.recycle();
- return res;
- }
-}
-
-final class BinderProxy implements IBinder {
- public native boolean pingBinder();
- public native boolean isBinderAlive();
-
- public IInterface queryLocalInterface(String descriptor) {
- return null;
- }
-
- public native String getInterfaceDescriptor() throws RemoteException;
- public native boolean transact(int code, Parcel data, Parcel reply,
- int flags) throws RemoteException;
- public native void linkToDeath(DeathRecipient recipient, int flags)
- throws RemoteException;
- public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
-
- public void dump(FileDescriptor fd, String[] args) throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeFileDescriptor(fd);
- data.writeStringArray(args);
- try {
- transact(DUMP_TRANSACTION, data, null, 0);
- } finally {
- data.recycle();
- }
- }
-
- BinderProxy() {
- mSelf = new WeakReference(this);
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- destroy();
- } finally {
- super.finalize();
- }
- }
-
- private native final void destroy();
-
- private static final void sendDeathNotice(DeathRecipient recipient) {
- if (Config.LOGV) Log.v("JavaBinder", "sendDeathNotice to " + recipient);
- try {
- recipient.binderDied();
- }
- catch (RuntimeException exc) {
- Log.w("BinderNative", "Uncaught exception from death notification",
- exc);
- }
- }
-
- final private WeakReference mSelf;
- private int mObject;
-}
diff --git a/core/java/android/os/Broadcaster.java b/core/java/android/os/Broadcaster.java
deleted file mode 100644
index 96dc61a..0000000
--- a/core/java/android/os/Broadcaster.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/** @hide */
-public class Broadcaster
-{
- public Broadcaster()
- {
- }
-
- /**
- * Sign up for notifications about something.
- *
- * When this broadcaster pushes a message with senderWhat in the what field,
- * target will be sent a copy of that message with targetWhat in the what field.
- */
- public void request(int senderWhat, Handler target, int targetWhat)
- {
- synchronized (this) {
- Registration r = null;
- if (mReg == null) {
- r = new Registration();
- r.senderWhat = senderWhat;
- r.targets = new Handler[1];
- r.targetWhats = new int[1];
- r.targets[0] = target;
- r.targetWhats[0] = targetWhat;
- mReg = r;
- r.next = r;
- r.prev = r;
- } else {
- // find its place in the map
- Registration start = mReg;
- r = start;
- do {
- if (r.senderWhat >= senderWhat) {
- break;
- }
- r = r.next;
- } while (r != start);
- int n;
- if (r.senderWhat != senderWhat) {
- // we didn't find a senderWhat match, but r is right
- // after where it goes
- Registration reg = new Registration();
- reg.senderWhat = senderWhat;
- reg.targets = new Handler[1];
- reg.targetWhats = new int[1];
- reg.next = r;
- reg.prev = r.prev;
- r.prev.next = reg;
- r.prev = reg;
-
- if (r == mReg && r.senderWhat > reg.senderWhat) {
- mReg = reg;
- }
-
- r = reg;
- n = 0;
- } else {
- n = r.targets.length;
- Handler[] oldTargets = r.targets;
- int[] oldWhats = r.targetWhats;
- // check for duplicates, and don't do it if we are dup.
- for (int i=0; i<n; i++) {
- if (oldTargets[i] == target && oldWhats[i] == targetWhat) {
- return;
- }
- }
- r.targets = new Handler[n+1];
- System.arraycopy(oldTargets, 0, r.targets, 0, n);
- r.targetWhats = new int[n+1];
- System.arraycopy(oldWhats, 0, r.targetWhats, 0, n);
- }
- r.targets[n] = target;
- r.targetWhats[n] = targetWhat;
- }
- }
- }
-
- /**
- * Unregister for notifications for this senderWhat/target/targetWhat tuple.
- */
- public void cancelRequest(int senderWhat, Handler target, int targetWhat)
- {
- synchronized (this) {
- Registration start = mReg;
- Registration r = start;
-
- if (r == null) {
- return;
- }
-
- do {
- if (r.senderWhat >= senderWhat) {
- break;
- }
- r = r.next;
- } while (r != start);
-
- if (r.senderWhat == senderWhat) {
- Handler[] targets = r.targets;
- int[] whats = r.targetWhats;
- int oldLen = targets.length;
- for (int i=0; i<oldLen; i++) {
- if (targets[i] == target && whats[i] == targetWhat) {
- r.targets = new Handler[oldLen-1];
- r.targetWhats = new int[oldLen-1];
- if (i > 0) {
- System.arraycopy(targets, 0, r.targets, 0, i);
- System.arraycopy(whats, 0, r.targetWhats, 0, i);
- }
-
- int remainingLen = oldLen-i-1;
- if (remainingLen != 0) {
- System.arraycopy(targets, i+1, r.targets, i,
- remainingLen);
- System.arraycopy(whats, i+1, r.targetWhats, i,
- remainingLen);
- }
- break;
- }
- }
- }
- }
- }
-
- /**
- * For debugging purposes, print the registrations to System.out
- */
- public void dumpRegistrations()
- {
- synchronized (this) {
- Registration start = mReg;
- System.out.println("Broadcaster " + this + " {");
- if (start != null) {
- Registration r = start;
- do {
- System.out.println(" senderWhat=" + r.senderWhat);
- int n = r.targets.length;
- for (int i=0; i<n; i++) {
- System.out.println(" [" + r.targetWhats[i]
- + "] " + r.targets[i]);
- }
- r = r.next;
- } while (r != start);
- }
- System.out.println("}");
- }
- }
-
- /**
- * Send out msg. Anyone who has registered via the request() method will be
- * sent the message.
- */
- public void broadcast(Message msg)
- {
- synchronized (this) {
- if (mReg == null) {
- return;
- }
-
- int senderWhat = msg.what;
- Registration start = mReg;
- Registration r = start;
- do {
- if (r.senderWhat >= senderWhat) {
- break;
- }
- r = r.next;
- } while (r != start);
- if (r.senderWhat == senderWhat) {
- Handler[] targets = r.targets;
- int[] whats = r.targetWhats;
- int n = targets.length;
- for (int i=0; i<n; i++) {
- Handler target = targets[i];
- Message m = Message.obtain();
- m.copyFrom(msg);
- m.what = whats[i];
- target.sendMessage(m);
- }
- }
- }
- }
-
- private class Registration
- {
- Registration next;
- Registration prev;
-
- int senderWhat;
- Handler[] targets;
- int[] targetWhats;
- }
- private Registration mReg;
-}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
deleted file mode 100644
index 467c17f..0000000
--- a/core/java/android/os/Build.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * Information about the current build, extracted from system properties.
- */
-public class Build {
- /** Value used for when a build property is unknown. */
- private static final String UNKNOWN = "unknown";
-
- /** Either a changelist number, or a label like "M4-rc20". */
- public static final String ID = getString("ro.build.id");
-
- /** A build ID string meant for displaying to the user */
- public static final String DISPLAY = getString("ro.build.display.id");
-
- /** The name of the overall product. */
- public static final String PRODUCT = getString("ro.product.name");
-
- /** The name of the industrial design. */
- public static final String DEVICE = getString("ro.product.device");
-
- /** The name of the underlying board, like "goldfish". */
- public static final String BOARD = getString("ro.product.board");
-
- /** The brand (e.g., carrier) the software is customized for, if any. */
- public static final String BRAND = getString("ro.product.brand");
-
- /** The end-user-visible name for the end product. */
- public static final String MODEL = getString("ro.product.model");
-
- /** Various version strings. */
- public static class VERSION {
- /**
- * The internal value used by the underlying source control to
- * represent this build. E.g., a perforce changelist number
- * or a git hash.
- */
- public static final String INCREMENTAL = getString("ro.build.version.incremental");
-
- /**
- * The user-visible version string. E.g., "1.0" or "3.4b5".
- */
- public static final String RELEASE = getString("ro.build.version.release");
-
- /**
- * The user-visible SDK version of the framework. It is an integer starting at 1.
- */
- public static final String SDK = getString("ro.build.version.sdk");
- }
-
- /** The type of build, like "user" or "eng". */
- public static final String TYPE = getString("ro.build.type");
-
- /** Comma-separated tags describing the build, like "unsigned,debug". */
- public static final String TAGS = getString("ro.build.tags");
-
- /** A string that uniquely identifies this build. Do not attempt to parse this value. */
- public static final String FINGERPRINT = getString("ro.build.fingerprint");
-
- // The following properties only make sense for internal engineering builds.
- public static final long TIME = getLong("ro.build.date.utc") * 1000;
- public static final String USER = getString("ro.build.user");
- public static final String HOST = getString("ro.build.host");
-
- private static String getString(String property) {
- return SystemProperties.get(property, UNKNOWN);
- }
-
- private static long getLong(String property) {
- try {
- return Long.parseLong(SystemProperties.get(property));
- } catch (NumberFormatException e) {
- return -1;
- }
- }
-}
diff --git a/core/java/android/os/Bundle.aidl b/core/java/android/os/Bundle.aidl
deleted file mode 100644
index b9e1224..0000000
--- a/core/java/android/os/Bundle.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/os/Bundle.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.os;
-
-parcelable Bundle;
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
deleted file mode 100644
index b669fa2..0000000
--- a/core/java/android/os/Bundle.java
+++ /dev/null
@@ -1,1452 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.util.Log;
-import android.util.SparseArray;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * A mapping from String values to various Parcelable types.
- *
- */
-public final class Bundle implements Parcelable, Cloneable {
- private static final String LOG_TAG = "Bundle";
- public static final Bundle EMPTY;
-
- static {
- EMPTY = new Bundle();
- EMPTY.mMap = Collections.unmodifiableMap(new HashMap<String, Object>());
- }
-
- // Invariant - exactly one of mMap / mParcelledData will be null
- // (except inside a call to unparcel)
-
- /* package */ Map<String, Object> mMap = null;
-
- /*
- * If mParcelledData is non-null, then mMap will be null and the
- * data are stored as a Parcel containing a Bundle. When the data
- * are unparcelled, mParcelledData willbe set to null.
- */
- /* package */ Parcel mParcelledData = null;
-
- private boolean mHasFds = false;
- private boolean mFdsKnown = true;
-
- /**
- * The ClassLoader used when unparcelling data from mParcelledData.
- */
- private ClassLoader mClassLoader;
-
- /**
- * Constructs a new, empty Bundle.
- */
- public Bundle() {
- mMap = new HashMap<String, Object>();
- mClassLoader = getClass().getClassLoader();
- }
-
- /**
- * Constructs a Bundle whose data is stored as a Parcel. The data
- * will be unparcelled on first contact, using the assigned ClassLoader.
- *
- * @param parcelledData a Parcel containing a Bundle
- */
- Bundle(Parcel parcelledData) {
- readFromParcel(parcelledData);
- }
-
- /**
- * Constructs a new, empty Bundle that uses a specific ClassLoader for
- * instantiating Parcelable and Serializable objects.
- *
- * @param loader An explicit ClassLoader to use when instantiating objects
- * inside of the Bundle.
- */
- public Bundle(ClassLoader loader) {
- mMap = new HashMap<String, Object>();
- mClassLoader = loader;
- }
-
- /**
- * Constructs a new, empty Bundle sized to hold the given number of
- * elements. The Bundle will grow as needed.
- *
- * @param capacity the initial capacity of the Bundle
- */
- public Bundle(int capacity) {
- mMap = new HashMap<String, Object>(capacity);
- mClassLoader = getClass().getClassLoader();
- }
-
- /**
- * Constructs a Bundle containing a copy of the mappings from the given
- * Bundle.
- *
- * @param b a Bundle to be copied.
- */
- public Bundle(Bundle b) {
- if (b.mParcelledData != null) {
- mParcelledData = Parcel.obtain();
- mParcelledData.appendFrom(b.mParcelledData, 0, b.mParcelledData.dataSize());
- mParcelledData.setDataPosition(0);
- } else {
- mParcelledData = null;
- }
-
- if (b.mMap != null) {
- mMap = new HashMap<String, Object>(b.mMap);
- } else {
- mMap = null;
- }
-
- mHasFds = b.mHasFds;
- mFdsKnown = b.mFdsKnown;
- mClassLoader = b.mClassLoader;
- }
-
- /**
- * Changes the ClassLoader this Bundle uses when instantiating objects.
- *
- * @param loader An explicit ClassLoader to use when instantiating objects
- * inside of the Bundle.
- */
- public void setClassLoader(ClassLoader loader) {
- mClassLoader = loader;
- }
-
- /**
- * Clones the current Bundle. The internal map is cloned, but the keys and
- * values to which it refers are copied by reference.
- */
- @Override
- public Object clone() {
- return new Bundle(this);
- }
-
- /**
- * If the underlying data are stored as a Parcel, unparcel them
- * using the currently assigned class loader.
- */
- /* package */ synchronized void unparcel() {
- if (mParcelledData == null) {
- return;
- }
-
- mParcelledData.setDataPosition(0);
- Bundle b = mParcelledData.readBundleUnpacked(mClassLoader);
- mMap = b.mMap;
-
- mHasFds = mParcelledData.hasFileDescriptors();
- mFdsKnown = true;
-
- mParcelledData.recycle();
- mParcelledData = null;
- }
-
- /**
- * Returns the number of mappings contained in this Bundle.
- *
- * @return the number of mappings as an int.
- */
- public int size() {
- unparcel();
- return mMap.size();
- }
-
- /**
- * Returns true if the mapping of this Bundle is empty, false otherwise.
- */
- public boolean isEmpty() {
- unparcel();
- return mMap.isEmpty();
- }
-
- /**
- * Removes all elements from the mapping of this Bundle.
- */
- public void clear() {
- unparcel();
- mMap.clear();
- mHasFds = false;
- mFdsKnown = true;
- }
-
- /**
- * Returns true if the given key is contained in the mapping
- * of this Bundle.
- *
- * @param key a String key
- * @return true if the key is part of the mapping, false otherwise
- */
- public boolean containsKey(String key) {
- unparcel();
- return mMap.containsKey(key);
- }
-
- /**
- * Returns the entry with the given key as an object.
- *
- * @param key a String key
- * @return an Object, or null
- */
- public Object get(String key) {
- unparcel();
- return mMap.get(key);
- }
-
- /**
- * Removes any entry with the given key from the mapping of this Bundle.
- *
- * @param key a String key
- */
- public void remove(String key) {
- unparcel();
- mMap.remove(key);
- }
-
- /**
- * Inserts all mappings from the given Bundle into this Bundle.
- *
- * @param map a Bundle
- */
- public void putAll(Bundle map) {
- unparcel();
- map.unparcel();
- mMap.putAll(map.mMap);
-
- // fd state is now known if and only if both bundles already knew
- mHasFds |= map.mHasFds;
- mFdsKnown = mFdsKnown && map.mFdsKnown;
- }
-
- /**
- * Returns a Set containing the Strings used as keys in this Bundle.
- *
- * @return a Set of String keys
- */
- public Set<String> keySet() {
- unparcel();
- return mMap.keySet();
- }
-
- /**
- * Reports whether the bundle contains any parcelled file descriptors.
- */
- public boolean hasFileDescriptors() {
- if (!mFdsKnown) {
- boolean fdFound = false; // keep going until we find one or run out of data
-
- if (mParcelledData != null) {
- if (mParcelledData.hasFileDescriptors()) {
- fdFound = true;
- }
- } else {
- // It's been unparcelled, so we need to walk the map
- Iterator<Map.Entry<String, Object>> iter = mMap.entrySet().iterator();
- while (!fdFound && iter.hasNext()) {
- Object obj = iter.next().getValue();
- if (obj instanceof Parcelable) {
- if ((((Parcelable)obj).describeContents()
- & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
- fdFound = true;
- break;
- }
- } else if (obj instanceof Parcelable[]) {
- Parcelable[] array = (Parcelable[]) obj;
- for (int n = array.length - 1; n >= 0; n--) {
- if ((array[n].describeContents()
- & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
- fdFound = true;
- break;
- }
- }
- } else if (obj instanceof SparseArray) {
- SparseArray<? extends Parcelable> array =
- (SparseArray<? extends Parcelable>) obj;
- for (int n = array.size() - 1; n >= 0; n--) {
- if ((array.get(n).describeContents()
- & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
- fdFound = true;
- break;
- }
- }
- } else if (obj instanceof ArrayList) {
- ArrayList array = (ArrayList) obj;
- // an ArrayList here might contain either Strings or
- // Parcelables; only look inside for Parcelables
- if ((array.size() > 0)
- && (array.get(0) instanceof Parcelable)) {
- for (int n = array.size() - 1; n >= 0; n--) {
- Parcelable p = (Parcelable) array.get(n);
- if (p != null && ((p.describeContents()
- & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) {
- fdFound = true;
- break;
- }
- }
- }
- }
- }
- }
-
- mHasFds = fdFound;
- mFdsKnown = true;
- }
- return mHasFds;
- }
-
- /**
- * Inserts a Boolean value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a Boolean, or null
- */
- public void putBoolean(String key, boolean value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a byte value into the mapping of this Bundle, replacing
- * any existing value for the given key.
- *
- * @param key a String, or null
- * @param value a byte
- */
- public void putByte(String key, byte value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a char value into the mapping of this Bundle, replacing
- * any existing value for the given key.
- *
- * @param key a String, or null
- * @param value a char, or null
- */
- public void putChar(String key, char value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a short value into the mapping of this Bundle, replacing
- * any existing value for the given key.
- *
- * @param key a String, or null
- * @param value a short
- */
- public void putShort(String key, short value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts an int value into the mapping of this Bundle, replacing
- * any existing value for the given key.
- *
- * @param key a String, or null
- * @param value an int, or null
- */
- public void putInt(String key, int value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a long value into the mapping of this Bundle, replacing
- * any existing value for the given key.
- *
- * @param key a String, or null
- * @param value a long
- */
- public void putLong(String key, long value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a float value into the mapping of this Bundle, replacing
- * any existing value for the given key.
- *
- * @param key a String, or null
- * @param value a float
- */
- public void putFloat(String key, float value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a double value into the mapping of this Bundle, replacing
- * any existing value for the given key.
- *
- * @param key a String, or null
- * @param value a double
- */
- public void putDouble(String key, double value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a String value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a String, or null
- */
- public void putString(String key, String value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a CharSequence value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a CharSequence, or null
- */
- public void putCharSequence(String key, CharSequence value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a Parcelable value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a Parcelable object, or null
- */
- public void putParcelable(String key, Parcelable value) {
- unparcel();
- mMap.put(key, value);
- mFdsKnown = false;
- }
-
- /**
- * Inserts an array of Parcelable values into the mapping of this Bundle,
- * replacing any existing value for the given key. Either key or value may
- * be null.
- *
- * @param key a String, or null
- * @param value an array of Parcelable objects, or null
- */
- public void putParcelableArray(String key, Parcelable[] value) {
- unparcel();
- mMap.put(key, value);
- mFdsKnown = false;
- }
-
- /**
- * Inserts a List of Parcelable values into the mapping of this Bundle,
- * replacing any existing value for the given key. Either key or value may
- * be null.
- *
- * @param key a String, or null
- * @param value an ArrayList of Parcelable objects, or null
- */
- public void putParcelableArrayList(String key,
- ArrayList<? extends Parcelable> value) {
- unparcel();
- mMap.put(key, value);
- mFdsKnown = false;
- }
-
- /**
- * Inserts a SparceArray of Parcelable values into the mapping of this
- * Bundle, replacing any existing value for the given key. Either key
- * or value may be null.
- *
- * @param key a String, or null
- * @param value a SparseArray of Parcelable objects, or null
- */
- public void putSparseParcelableArray(String key,
- SparseArray<? extends Parcelable> value) {
- unparcel();
- mMap.put(key, value);
- mFdsKnown = false;
- }
-
- /**
- * Inserts an ArrayList<Integer> value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value an ArrayList<Integer> object, or null
- */
- public void putIntegerArrayList(String key, ArrayList<Integer> value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts an ArrayList<String> value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value an ArrayList<String> object, or null
- */
- public void putStringArrayList(String key, ArrayList<String> value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a Serializable value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a Serializable object, or null
- */
- public void putSerializable(String key, Serializable value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a boolean array value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a boolean array object, or null
- */
- public void putBooleanArray(String key, boolean[] value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a byte array value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a byte array object, or null
- */
- public void putByteArray(String key, byte[] value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a short array value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a short array object, or null
- */
- public void putShortArray(String key, short[] value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a char array value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a char array object, or null
- */
- public void putCharArray(String key, char[] value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts an int array value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value an int array object, or null
- */
- public void putIntArray(String key, int[] value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a long array value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a long array object, or null
- */
- public void putLongArray(String key, long[] value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a float array value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a float array object, or null
- */
- public void putFloatArray(String key, float[] value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a double array value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a double array object, or null
- */
- public void putDoubleArray(String key, double[] value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a String array value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a String array object, or null
- */
- public void putStringArray(String key, String[] value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts a Bundle value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value a Bundle object, or null
- */
- public void putBundle(String key, Bundle value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Inserts an IBinder value into the mapping of this Bundle, replacing
- * any existing value for the given key. Either key or value may be null.
- *
- * @param key a String, or null
- * @param value an IBinder object, or null
- *
- * @deprecated
- * @hide
- */
- @Deprecated
- public void putIBinder(String key, IBinder value) {
- unparcel();
- mMap.put(key, value);
- }
-
- /**
- * Returns the value associated with the given key, or false if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return a boolean value
- */
- public boolean getBoolean(String key) {
- unparcel();
- return getBoolean(key, false);
- }
-
- // Log a message if the value was non-null but not of the expected type
- private void typeWarning(String key, Object value, String className,
- Object defaultValue, ClassCastException e) {
- StringBuilder sb = new StringBuilder();
- sb.append("Key ");
- sb.append(key);
- sb.append(" expected ");
- sb.append(className);
- sb.append(" but value was a ");
- sb.append(value.getClass().getName());
- sb.append(". The default value ");
- sb.append(defaultValue);
- sb.append(" was returned.");
- Log.w(LOG_TAG, sb.toString());
- Log.w(LOG_TAG, "Attempt to cast generated internal exception:", e);
- }
-
- private void typeWarning(String key, Object value, String className,
- ClassCastException e) {
- typeWarning(key, value, className, "<null>", e);
- }
-
- /**
- * Returns the value associated with the given key, or defaultValue if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return a boolean value
- */
- public boolean getBoolean(String key, boolean defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Boolean) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Boolean", defaultValue, e);
- return defaultValue;
- }
- }
-
- /**
- * Returns the value associated with the given key, or (byte) 0 if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return a byte value
- */
- public byte getByte(String key) {
- unparcel();
- return getByte(key, (byte) 0);
- }
-
- /**
- * Returns the value associated with the given key, or defaultValue if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return a byte value
- */
- public Byte getByte(String key, byte defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Byte) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Byte", defaultValue, e);
- return defaultValue;
- }
- }
-
- /**
- * Returns the value associated with the given key, or false if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return a char value
- */
- public char getChar(String key) {
- unparcel();
- return getChar(key, (char) 0);
- }
-
- /**
- * Returns the value associated with the given key, or (char) 0 if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return a char value
- */
- public char getChar(String key, char defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Character) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Character", defaultValue, e);
- return defaultValue;
- }
- }
-
- /**
- * Returns the value associated with the given key, or (short) 0 if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return a short value
- */
- public short getShort(String key) {
- unparcel();
- return getShort(key, (short) 0);
- }
-
- /**
- * Returns the value associated with the given key, or defaultValue if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return a short value
- */
- public short getShort(String key, short defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Short) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Short", defaultValue, e);
- return defaultValue;
- }
- }
-
- /**
- * Returns the value associated with the given key, or 0 if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return an int value
- */
- public int getInt(String key) {
- unparcel();
- return getInt(key, 0);
- }
-
- /**
- * Returns the value associated with the given key, or defaultValue if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return an int value
- */
- public int getInt(String key, int defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Integer) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Integer", defaultValue, e);
- return defaultValue;
- }
- }
-
- /**
- * Returns the value associated with the given key, or 0L if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return a long value
- */
- public long getLong(String key) {
- unparcel();
- return getLong(key, 0L);
- }
-
- /**
- * Returns the value associated with the given key, or defaultValue if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return a long value
- */
- public long getLong(String key, long defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Long) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Long", defaultValue, e);
- return defaultValue;
- }
- }
-
- /**
- * Returns the value associated with the given key, or 0.0f if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return a float value
- */
- public float getFloat(String key) {
- unparcel();
- return getFloat(key, 0.0f);
- }
-
- /**
- * Returns the value associated with the given key, or defaultValue if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return a float value
- */
- public float getFloat(String key, float defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Float) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Float", defaultValue, e);
- return defaultValue;
- }
- }
-
- /**
- * Returns the value associated with the given key, or 0.0 if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return a double value
- */
- public double getDouble(String key) {
- unparcel();
- return getDouble(key, 0.0);
- }
-
- /**
- * Returns the value associated with the given key, or defaultValue if
- * no mapping of the desired type exists for the given key.
- *
- * @param key a String
- * @return a double value
- */
- public double getDouble(String key, double defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Double) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Double", defaultValue, e);
- return defaultValue;
- }
- }
-
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return a String value, or null
- */
- public String getString(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (String) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "String", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return a CharSequence value, or null
- */
- public CharSequence getCharSequence(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (CharSequence) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "CharSequence", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return a Bundle value, or null
- */
- public Bundle getBundle(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (Bundle) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Bundle", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return a Parcelable value, or null
- */
- public <T extends Parcelable> T getParcelable(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (T) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Parcelable", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return a Parcelable[] value, or null
- */
- public Parcelable[] getParcelableArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (Parcelable[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Parcelable[]", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return an ArrayList<T> value, or null
- */
- public <T extends Parcelable> ArrayList<T> getParcelableArrayList(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (ArrayList<T>) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "ArrayList", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- *
- * @return a SparseArray of T values, or null
- */
- public <T extends Parcelable> SparseArray<T> getSparseParcelableArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (SparseArray<T>) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "SparseArray", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return a Serializable value, or null
- */
- public Serializable getSerializable(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (Serializable) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Serializable", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return an ArrayList<String> value, or null
- */
- public ArrayList<Integer> getIntegerArrayList(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (ArrayList<Integer>) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "ArrayList<Integer>", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return an ArrayList<String> value, or null
- */
- public ArrayList<String> getStringArrayList(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (ArrayList<String>) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "ArrayList<String>", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return a boolean[] value, or null
- */
- public boolean[] getBooleanArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (boolean[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "byte[]", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return a byte[] value, or null
- */
- public byte[] getByteArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (byte[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "byte[]", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return a short[] value, or null
- */
- public short[] getShortArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (short[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "short[]", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return a char[] value, or null
- */
- public char[] getCharArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (char[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "char[]", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return an int[] value, or null
- */
- public int[] getIntArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (int[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "int[]", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return a long[] value, or null
- */
- public long[] getLongArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (long[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "long[]", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return a float[] value, or null
- */
- public float[] getFloatArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (float[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "float[]", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return a double[] value, or null
- */
- public double[] getDoubleArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (double[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "double[]", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return a String[] value, or null
- */
- public String[] getStringArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (String[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "String[]", e);
- return null;
- }
- }
-
- /**
- * Returns the value associated with the given key, or null if
- * no mapping of the desired type exists for the given key or a null
- * value is explicitly associated with the key.
- *
- * @param key a String, or null
- * @return an IBinder value, or null
- *
- * @deprecated
- * @hide
- */
- @Deprecated
- public IBinder getIBinder(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (IBinder) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "IBinder", e);
- return null;
- }
- }
-
- public static final Parcelable.Creator<Bundle> CREATOR =
- new Parcelable.Creator<Bundle>() {
- public Bundle createFromParcel(Parcel in) {
- return in.readBundle();
- }
-
- public Bundle[] newArray(int size) {
- return new Bundle[size];
- }
- };
-
- /**
- * Report the nature of this Parcelable's contents
- */
- public int describeContents() {
- int mask = 0;
- if (hasFileDescriptors()) {
- mask |= Parcelable.CONTENTS_FILE_DESCRIPTOR;
- }
- return mask;
- }
-
- /**
- * Writes the Bundle contents to a Parcel, typically in order for
- * it to be passed through an IBinder connection.
- * @param parcel The parcel to copy this bundle to.
- */
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeBundle(this);
- }
-
- /**
- * Reads the Parcel contents into this Bundle, typically in order for
- * it to be passed through an IBinder connection.
- * @param parcel The parcel to overwrite this bundle from.
- */
- public void readFromParcel(Parcel parcel) {
- mParcelledData = parcel;
- mHasFds = mParcelledData.hasFileDescriptors();
- mFdsKnown = true;
- }
-
- @Override
- public synchronized String toString() {
- if (mParcelledData != null) {
- return "Bundle[mParcelledData.dataSize=" +
- mParcelledData.dataSize() + "]";
- }
- return "Bundle[" + mMap.toString() + "]";
- }
-}
diff --git a/core/java/android/os/ConditionVariable.java b/core/java/android/os/ConditionVariable.java
deleted file mode 100644
index 95a9259..0000000
--- a/core/java/android/os/ConditionVariable.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * Class that implements the condition variable locking paradigm.
- *
- * <p>
- * This differs from the built-in java.lang.Object wait() and notify()
- * in that this class contains the condition to wait on itself. That means
- * open(), close() and block() are sticky. If open() is called before block(),
- * block() will not block, and instead return immediately.
- *
- * <p>
- * This class uses itself is at the object to wait on, so if you wait()
- * or notify() on a ConditionVariable, the results are undefined.
- */
-public class ConditionVariable
-{
- private volatile boolean mCondition;
-
- /**
- * Create the ConditionVariable in the default closed state.
- */
- public ConditionVariable()
- {
- mCondition = false;
- }
-
- /**
- * Create the ConditionVariable with the given state.
- *
- * <p>
- * Pass true for opened and false for closed.
- */
- public ConditionVariable(boolean state)
- {
- mCondition = state;
- }
-
- /**
- * Open the condition, and release all threads that are blocked.
- *
- * <p>
- * Any threads that later approach block() will not block unless close()
- * is called.
- */
- public void open()
- {
- synchronized (this) {
- boolean old = mCondition;
- mCondition = true;
- if (!old) {
- this.notifyAll();
- }
- }
- }
-
- /**
- * Reset the condition to the closed state.
- *
- * <p>
- * Any threads that call block() will block until someone calls open.
- */
- public void close()
- {
- synchronized (this) {
- mCondition = false;
- }
- }
-
- /**
- * Block the current thread until the condition is opened.
- *
- * <p>
- * If the condition is already opened, return immediately.
- */
- public void block()
- {
- synchronized (this) {
- while (!mCondition) {
- try {
- this.wait();
- }
- catch (InterruptedException e) {
- }
- }
- }
- }
-
- /**
- * Block the current thread until the condition is opened or until
- * timeout milliseconds have passed.
- *
- * <p>
- * If the condition is already opened, return immediately.
- *
- * @param timeout the minimum time to wait in milliseconds.
- *
- * @return true if the condition was opened, false if the call returns
- * because of the timeout.
- */
- public boolean block(long timeout)
- {
- // Object.wait(0) means wait forever, to mimic this, we just
- // call the other block() method in that case. It simplifies
- // this code for the common case.
- if (timeout != 0) {
- synchronized (this) {
- long now = System.currentTimeMillis();
- long end = now + timeout;
- while (!mCondition && now < end) {
- try {
- this.wait(end-now);
- }
- catch (InterruptedException e) {
- }
- now = System.currentTimeMillis();
- }
- return mCondition;
- }
- } else {
- this.block();
- return true;
- }
- }
-}
diff --git a/core/java/android/os/CountDownTimer.java b/core/java/android/os/CountDownTimer.java
deleted file mode 100644
index 0c5c615..0000000
--- a/core/java/android/os/CountDownTimer.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.util.Log;
-
-/**
- * Schedule a countdown until a time in the future, with
- * regular notifications on intervals along the way.
- *
- * Example of showing a 30 second countdown in a text field:
- *
- * <pre class="prettyprint">
- * new CountdownTimer(30000, 1000) {
- *
- * public void onTick(long millisUntilFinished) {
- * mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
- * }
- *
- * public void onFinish() {
- * mTextField.setText("done!");
- * }
- * }.start();
- * </pre>
- *
- * The calls to {@link #onTick(long)} are synchronized to this object so that
- * one call to {@link #onTick(long)} won't ever occur before the previous
- * callback is complete. This is only relevant when the implementation of
- * {@link #onTick(long)} takes an amount of time to execute that is significant
- * compared to the countdown interval.
- */
-public abstract class CountDownTimer {
-
- /**
- * Millis since epoch when alarm should stop.
- */
- private final long mMillisInFuture;
-
- /**
- * The interval in millis that the user receives callbacks
- */
- private final long mCountdownInterval;
-
- private long mStopTimeInFuture;
-
- /**
- * @param millisInFuture The number of millis in the future from the call
- * to {@link #start()} until the countdown is done and {@link #onFinish()}
- * is called.
- * @param countDownInterval The interval along the way to receive
- * {@link #onTick(long)} callbacks.
- */
- public CountDownTimer(long millisInFuture, long countDownInterval) {
- mMillisInFuture = millisInFuture;
- mCountdownInterval = countDownInterval;
- }
-
- /**
- * Cancel the countdown.
- */
- public final void cancel() {
- mHandler.removeMessages(MSG);
- }
-
- /**
- * Start the countdown.
- */
- public synchronized final CountDownTimer start() {
- if (mMillisInFuture <= 0) {
- onFinish();
- return this;
- }
- mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
- mHandler.sendMessage(mHandler.obtainMessage(MSG));
- return this;
- }
-
-
- /**
- * Callback fired on regular interval.
- * @param millisUntilFinished The amount of time until finished.
- */
- public abstract void onTick(long millisUntilFinished);
-
- /**
- * Callback fired when the time is up.
- */
- public abstract void onFinish();
-
-
- private static final int MSG = 1;
-
-
- // handles counting down
- private Handler mHandler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
-
- synchronized (CountDownTimer.this) {
- final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
-
- if (millisLeft <= 0) {
- onFinish();
- } else if (millisLeft < mCountdownInterval) {
- // no tick, just delay until done
- sendMessageDelayed(obtainMessage(MSG), millisLeft);
- } else {
- long lastTickStart = SystemClock.elapsedRealtime();
- onTick(millisLeft);
-
- // take into account user's onTick taking time to execute
- long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();
-
- // special case: user's onTick took more than interval to
- // complete, skip to next interval
- while (delay < 0) delay += mCountdownInterval;
-
- sendMessageDelayed(obtainMessage(MSG), delay);
- }
- }
- }
- };
-}
diff --git a/core/java/android/os/DeadObjectException.java b/core/java/android/os/DeadObjectException.java
deleted file mode 100644
index 94c5387..0000000
--- a/core/java/android/os/DeadObjectException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-import android.os.RemoteException;
-
-/**
- * The object you are calling has died, because its hosting process
- * no longer exists.
- */
-public class DeadObjectException extends RemoteException {
- public DeadObjectException() {
- super();
- }
-}
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
deleted file mode 100644
index 950bb09..0000000
--- a/core/java/android/os/Debug.java
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-
-import org.apache.harmony.dalvik.ddmc.Chunk;
-import org.apache.harmony.dalvik.ddmc.ChunkHandler;
-import org.apache.harmony.dalvik.ddmc.DdmServer;
-
-import dalvik.bytecode.Opcodes;
-import dalvik.system.VMDebug;
-
-
-/**
- * Provides various debugging functions for Android applications, including
- * tracing and allocation counts.
- * <p><strong>Logging Trace Files</strong></p>
- * <p>Debug can create log files that give details about an application, such as
- * a call stack and start/stop times for any running methods. See <a
-href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
- * information about reading trace files. To start logging trace files, call one
- * of the startMethodTracing() methods. To stop tracing, call
- * {@link #stopMethodTracing()}.
- */
-public final class Debug
-{
- /**
- * Flags for startMethodTracing(). These can be ORed together.
- *
- * TRACE_COUNT_ALLOCS adds the results from startAllocCounting to the
- * trace key file.
- */
- public static final int TRACE_COUNT_ALLOCS = VMDebug.TRACE_COUNT_ALLOCS;
-
- /**
- * Flags for printLoadedClasses(). Default behavior is to only show
- * the class name.
- */
- public static final int SHOW_FULL_DETAIL = 1;
- public static final int SHOW_CLASSLOADER = (1 << 1);
- public static final int SHOW_INITIALIZED = (1 << 2);
-
- // set/cleared by waitForDebugger()
- private static volatile boolean mWaiting = false;
-
- private Debug() {}
-
- /*
- * How long to wait for the debugger to finish sending requests. I've
- * seen this hit 800msec on the device while waiting for a response
- * to travel over USB and get processed, so we take that and add
- * half a second.
- */
- private static final int MIN_DEBUGGER_IDLE = 1300; // msec
-
- /* how long to sleep when polling for activity */
- private static final int SPIN_DELAY = 200; // msec
-
- /**
- * Default trace file path and file
- */
- private static final String DEFAULT_TRACE_PATH_PREFIX = "/sdcard/";
- private static final String DEFAULT_TRACE_BODY = "dmtrace";
- private static final String DEFAULT_TRACE_EXTENSION = ".trace";
- private static final String DEFAULT_TRACE_FILE_PATH =
- DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY
- + DEFAULT_TRACE_EXTENSION;
-
-
- /**
- * This class is used to retrieved various statistics about the memory mappings for this
- * process. The returns info broken down by dalvik, native, and other. All results are in kB.
- */
- public static class MemoryInfo {
- /** The proportional set size for dalvik. */
- public int dalvikPss;
- /** The private dirty pages used by dalvik. */
- public int dalvikPrivateDirty;
- /** The shared dirty pages used by dalvik. */
- public int dalvikSharedDirty;
-
- /** The proportional set size for the native heap. */
- public int nativePss;
- /** The private dirty pages used by the native heap. */
- public int nativePrivateDirty;
- /** The shared dirty pages used by the native heap. */
- public int nativeSharedDirty;
-
- /** The proportional set size for everything else. */
- public int otherPss;
- /** The private dirty pages used by everything else. */
- public int otherPrivateDirty;
- /** The shared dirty pages used by everything else. */
- public int otherSharedDirty;
- }
-
-
- /**
- * Wait until a debugger attaches. As soon as the debugger attaches,
- * this returns, so you will need to place a breakpoint after the
- * waitForDebugger() call if you want to start tracing immediately.
- */
- public static void waitForDebugger() {
- if (!VMDebug.isDebuggingEnabled()) {
- //System.out.println("debugging not enabled, not waiting");
- return;
- }
- if (isDebuggerConnected())
- return;
-
- // if DDMS is listening, inform them of our plight
- System.out.println("Sending WAIT chunk");
- byte[] data = new byte[] { 0 }; // 0 == "waiting for debugger"
- Chunk waitChunk = new Chunk(ChunkHandler.type("WAIT"), data, 0, 1);
- DdmServer.sendChunk(waitChunk);
-
- mWaiting = true;
- while (!isDebuggerConnected()) {
- try { Thread.sleep(SPIN_DELAY); }
- catch (InterruptedException ie) {}
- }
- mWaiting = false;
-
- System.out.println("Debugger has connected");
-
- /*
- * There is no "ready to go" signal from the debugger, and we're
- * not allowed to suspend ourselves -- the debugger expects us to
- * be running happily, and gets confused if we aren't. We need to
- * allow the debugger a chance to set breakpoints before we start
- * running again.
- *
- * Sit and spin until the debugger has been idle for a short while.
- */
- while (true) {
- long delta = VMDebug.lastDebuggerActivity();
- if (delta < 0) {
- System.out.println("debugger detached?");
- break;
- }
-
- if (delta < MIN_DEBUGGER_IDLE) {
- System.out.println("waiting for debugger to settle...");
- try { Thread.sleep(SPIN_DELAY); }
- catch (InterruptedException ie) {}
- } else {
- System.out.println("debugger has settled (" + delta + ")");
- break;
- }
- }
- }
-
- /**
- * Returns "true" if one or more threads is waiting for a debugger
- * to attach.
- */
- public static boolean waitingForDebugger() {
- return mWaiting;
- }
-
- /**
- * Determine if a debugger is currently attached.
- */
- public static boolean isDebuggerConnected() {
- return VMDebug.isDebuggerConnected();
- }
-
- /**
- * Change the JDWP port.
- *
- * @deprecated no longer needed or useful
- */
- @Deprecated
- public static void changeDebugPort(int port) {}
-
- /**
- * This is the pathname to the sysfs file that enables and disables
- * tracing on the qemu emulator.
- */
- private static final String SYSFS_QEMU_TRACE_STATE = "/sys/qemu_trace/state";
-
- /**
- * Enable qemu tracing. For this to work requires running everything inside
- * the qemu emulator; otherwise, this method will have no effect. The trace
- * file is specified on the command line when the emulator is started. For
- * example, the following command line <br />
- * <code>emulator -trace foo</code><br />
- * will start running the emulator and create a trace file named "foo". This
- * method simply enables writing the trace records to the trace file.
- *
- * <p>
- * The main differences between this and {@link #startMethodTracing()} are
- * that tracing in the qemu emulator traces every cpu instruction of every
- * process, including kernel code, so we have more complete information,
- * including all context switches. We can also get more detailed information
- * such as cache misses. The sequence of calls is determined by
- * post-processing the instruction trace. The qemu tracing is also done
- * without modifying the application or perturbing the timing of calls
- * because no instrumentation is added to the application being traced.
- * </p>
- *
- * <p>
- * One limitation of using this method compared to using
- * {@link #startMethodTracing()} on the real device is that the emulator
- * does not model all of the real hardware effects such as memory and
- * bus contention. The emulator also has a simple cache model and cannot
- * capture all the complexities of a real cache.
- * </p>
- */
- public static void startNativeTracing() {
- // Open the sysfs file for writing and write "1" to it.
- PrintWriter outStream = null;
- try {
- FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
- outStream = new PrintWriter(new OutputStreamWriter(fos));
- outStream.println("1");
- } catch (Exception e) {
- } finally {
- if (outStream != null)
- outStream.close();
- }
-
- VMDebug.startEmulatorTracing();
- }
-
- /**
- * Stop qemu tracing. See {@link #startNativeTracing()} to start tracing.
- *
- * <p>Tracing can be started and stopped as many times as desired. When
- * the qemu emulator itself is stopped then the buffered trace records
- * are flushed and written to the trace file. In fact, it is not necessary
- * to call this method at all; simply killing qemu is sufficient. But
- * starting and stopping a trace is useful for examining a specific
- * region of code.</p>
- */
- public static void stopNativeTracing() {
- VMDebug.stopEmulatorTracing();
-
- // Open the sysfs file for writing and write "0" to it.
- PrintWriter outStream = null;
- try {
- FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
- outStream = new PrintWriter(new OutputStreamWriter(fos));
- outStream.println("0");
- } catch (Exception e) {
- // We could print an error message here but we probably want
- // to quietly ignore errors if we are not running in the emulator.
- } finally {
- if (outStream != null)
- outStream.close();
- }
- }
-
- /**
- * Enable "emulator traces", in which information about the current
- * method is made available to the "emulator -trace" feature. There
- * is no corresponding "disable" call -- this is intended for use by
- * the framework when tracing should be turned on and left that way, so
- * that traces captured with F9/F10 will include the necessary data.
- *
- * This puts the VM into "profile" mode, which has performance
- * consequences.
- *
- * To temporarily enable tracing, use {@link #startNativeTracing()}.
- */
- public static void enableEmulatorTraceOutput() {
- VMDebug.startEmulatorTracing();
- }
-
- /**
- * Start method tracing with default log name and buffer size. See <a
-href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
- * information about reading these files. Call stopMethodTracing() to stop
- * tracing.
- */
- public static void startMethodTracing() {
- VMDebug.startMethodTracing(DEFAULT_TRACE_FILE_PATH, 0, 0);
- }
-
- /**
- * Start method tracing, specifying the trace log file name. The trace
- * file will be put under "/sdcard" unless an absolute path is given.
- * See <a
- href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
- * information about reading trace files.
- *
- * @param traceName Name for the trace log file to create.
- * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
- * If the files already exist, they will be truncated.
- * If the trace file given does not end in ".trace", it will be appended for you.
- */
- public static void startMethodTracing(String traceName) {
- startMethodTracing(traceName, 0, 0);
- }
-
- /**
- * Start method tracing, specifying the trace log file name and the
- * buffer size. The trace files will be put under "/sdcard" unless an
- * absolute path is given. See <a
- href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
- * information about reading trace files.
- * @param traceName Name for the trace log file to create.
- * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
- * If the files already exist, they will be truncated.
- * If the trace file given does not end in ".trace", it will be appended for you.
- *
- * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
- */
- public static void startMethodTracing(String traceName, int bufferSize) {
- startMethodTracing(traceName, bufferSize, 0);
- }
-
- /**
- * Start method tracing, specifying the trace log file name and the
- * buffer size. The trace files will be put under "/sdcard" unless an
- * absolute path is given. See <a
- href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
- * information about reading trace files.
- *
- * <p>
- * When method tracing is enabled, the VM will run more slowly than
- * usual, so the timings from the trace files should only be considered
- * in relative terms (e.g. was run #1 faster than run #2). The times
- * for native methods will not change, so don't try to use this to
- * compare the performance of interpreted and native implementations of the
- * same method. As an alternative, consider using "native" tracing
- * in the emulator via {@link #startNativeTracing()}.
- * </p>
- *
- * @param traceName Name for the trace log file to create.
- * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
- * If the files already exist, they will be truncated.
- * If the trace file given does not end in ".trace", it will be appended for you.
- * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
- */
- public static void startMethodTracing(String traceName, int bufferSize,
- int flags) {
-
- String pathName = traceName;
- if (pathName.charAt(0) != '/')
- pathName = DEFAULT_TRACE_PATH_PREFIX + pathName;
- if (!pathName.endsWith(DEFAULT_TRACE_EXTENSION))
- pathName = pathName + DEFAULT_TRACE_EXTENSION;
-
- VMDebug.startMethodTracing(pathName, bufferSize, flags);
- }
-
- /**
- * Stop method tracing.
- */
- public static void stopMethodTracing() {
- VMDebug.stopMethodTracing();
- }
-
- /**
- * Get an indication of thread CPU usage. The value returned
- * indicates the amount of time that the current thread has spent
- * executing code or waiting for certain types of I/O.
- *
- * The time is expressed in nanoseconds, and is only meaningful
- * when compared to the result from an earlier call. Note that
- * nanosecond resolution does not imply nanosecond accuracy.
- *
- * On system which don't support this operation, the call returns -1.
- */
- public static long threadCpuTimeNanos() {
- return VMDebug.threadCpuTimeNanos();
- }
-
- /**
- * Count the number and aggregate size of memory allocations between
- * two points.
- *
- * The "start" function resets the counts and enables counting. The
- * "stop" function disables the counting so that the analysis code
- * doesn't cause additional allocations. The "get" function returns
- * the specified value.
- *
- * Counts are kept for the system as a whole and for each thread.
- * The per-thread counts for threads other than the current thread
- * are not cleared by the "reset" or "start" calls.
- */
- public static void startAllocCounting() {
- VMDebug.startAllocCounting();
- }
- public static void stopAllocCounting() {
- VMDebug.stopAllocCounting();
- }
-
- public static int getGlobalAllocCount() {
- return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
- }
- public static int getGlobalAllocSize() {
- return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
- }
- public static int getGlobalFreedCount() {
- return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
- }
- public static int getGlobalFreedSize() {
- return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
- }
- public static int getGlobalExternalAllocCount() {
- return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_OBJECTS);
- }
- public static int getGlobalExternalAllocSize() {
- return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_BYTES);
- }
- public static int getGlobalExternalFreedCount() {
- return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_OBJECTS);
- }
- public static int getGlobalExternalFreedSize() {
- return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_BYTES);
- }
- public static int getGlobalGcInvocationCount() {
- return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
- }
- public static int getThreadAllocCount() {
- return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
- }
- public static int getThreadAllocSize() {
- return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
- }
- public static int getThreadExternalAllocCount() {
- return VMDebug.getAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_OBJECTS);
- }
- public static int getThreadExternalAllocSize() {
- return VMDebug.getAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_BYTES);
- }
- public static int getThreadGcInvocationCount() {
- return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
- }
-
- public static void resetGlobalAllocCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
- }
- public static void resetGlobalAllocSize() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
- }
- public static void resetGlobalFreedCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
- }
- public static void resetGlobalFreedSize() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
- }
- public static void resetGlobalExternalAllocCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_OBJECTS);
- }
- public static void resetGlobalExternalAllocSize() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_BYTES);
- }
- public static void resetGlobalExternalFreedCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_OBJECTS);
- }
- public static void resetGlobalExternalFreedSize() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_BYTES);
- }
- public static void resetGlobalGcInvocationCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
- }
- public static void resetThreadAllocCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
- }
- public static void resetThreadAllocSize() {
- VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
- }
- public static void resetThreadExternalAllocCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_OBJECTS);
- }
- public static void resetThreadExternalAllocSize() {
- VMDebug.resetAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_BYTES);
- }
- public static void resetThreadGcInvocationCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
- }
- public static void resetAllCounts() {
- VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS);
- }
-
- /**
- * Returns the size of the native heap.
- * @return The size of the native heap in bytes.
- */
- public static native long getNativeHeapSize();
-
- /**
- * Returns the amount of allocated memory in the native heap.
- * @return The allocated size in bytes.
- */
- public static native long getNativeHeapAllocatedSize();
-
- /**
- * Returns the amount of free memory in the native heap.
- * @return The freed size in bytes.
- */
- public static native long getNativeHeapFreeSize();
-
- /**
- * Retrieves information about this processes memory usages. This information is broken down by
- * how much is in use by dalivk, the native heap, and everything else.
- */
- public static native void getMemoryInfo(MemoryInfo memoryInfo);
-
- /**
- * Establish an object allocation limit in the current thread. Useful
- * for catching regressions in code that is expected to operate
- * without causing any allocations.
- *
- * Pass in the maximum number of allowed allocations. Use -1 to disable
- * the limit. Returns the previous limit.
- *
- * The preferred way to use this is:
- *
- * int prevLimit = -1;
- * try {
- * prevLimit = Debug.setAllocationLimit(0);
- * ... do stuff that's not expected to allocate memory ...
- * } finally {
- * Debug.setAllocationLimit(prevLimit);
- * }
- *
- * This allows limits to be nested. The try/finally ensures that the
- * limit is reset if something fails.
- *
- * Exceeding the limit causes a dalvik.system.AllocationLimitError to
- * be thrown from a memory allocation call. The limit is reset to -1
- * when this happens.
- *
- * The feature may be disabled in the VM configuration. If so, this
- * call has no effect, and always returns -1.
- */
- public static int setAllocationLimit(int limit) {
- return VMDebug.setAllocationLimit(limit);
- }
-
- /**
- * Establish a global object allocation limit. This is similar to
- * {@link #setAllocationLimit(int)} but applies to all threads in
- * the VM. It will coexist peacefully with per-thread limits.
- *
- * [ The value of "limit" is currently restricted to 0 (no allocations
- * allowed) or -1 (no global limit). This may be changed in a future
- * release. ]
- */
- public static int setGlobalAllocationLimit(int limit) {
- if (limit != 0 && limit != -1)
- throw new IllegalArgumentException("limit must be 0 or -1");
- return VMDebug.setGlobalAllocationLimit(limit);
- }
-
- /**
- * Dump a list of all currently loaded class to the log file.
- *
- * @param flags See constants above.
- */
- public static void printLoadedClasses(int flags) {
- VMDebug.printLoadedClasses(flags);
- }
-
- /**
- * Get the number of loaded classes.
- * @return the number of loaded classes.
- */
- public static int getLoadedClassCount() {
- return VMDebug.getLoadedClassCount();
- }
-
- /**
- * Dump "hprof" data to the specified file. This will cause a GC.
- *
- * @param fileName Full pathname of output file (e.g. "/sdcard/dump.hprof").
- * @throws UnsupportedOperationException if the VM was built without
- * HPROF support.
- * @throws IOException if an error occurs while opening or writing files.
- */
- public static void dumpHprofData(String fileName) throws IOException {
- VMDebug.dumpHprofData(fileName);
- }
-
- /**
- * Returns the number of sent transactions from this process.
- * @return The number of sent transactions or -1 if it could not read t.
- */
- public static native int getBinderSentTransactions();
-
- /**
- * Returns the number of received transactions from the binder driver.
- * @return The number of received transactions or -1 if it could not read the stats.
- */
- public static native int getBinderReceivedTransactions();
-
- /**
- * Returns the number of active local Binder objects that exist in the
- * current process.
- */
- public static final native int getBinderLocalObjectCount();
-
- /**
- * Returns the number of references to remote proxy Binder objects that
- * exist in the current process.
- */
- public static final native int getBinderProxyObjectCount();
-
- /**
- * Returns the number of death notification links to Binder objects that
- * exist in the current process.
- */
- public static final native int getBinderDeathObjectCount();
-
- /**
- * API for gathering and querying instruction counts.
- *
- * Example usage:
- * Debug.InstructionCount icount = new Debug.InstructionCount();
- * icount.resetAndStart();
- * [... do lots of stuff ...]
- * if (icount.collect()) {
- * System.out.println("Total instructions executed: "
- * + icount.globalTotal());
- * System.out.println("Method invocations: "
- * + icount.globalMethodInvocations());
- * }
- */
- public static class InstructionCount {
- private static final int NUM_INSTR = 256;
-
- private int[] mCounts;
-
- public InstructionCount() {
- mCounts = new int[NUM_INSTR];
- }
-
- /**
- * Reset counters and ensure counts are running. Counts may
- * have already been running.
- *
- * @return true if counting was started
- */
- public boolean resetAndStart() {
- try {
- VMDebug.startInstructionCounting();
- VMDebug.resetInstructionCount();
- } catch (UnsupportedOperationException uoe) {
- return false;
- }
- return true;
- }
-
- /**
- * Collect instruction counts. May or may not stop the
- * counting process.
- */
- public boolean collect() {
- try {
- VMDebug.stopInstructionCounting();
- VMDebug.getInstructionCount(mCounts);
- } catch (UnsupportedOperationException uoe) {
- return false;
- }
- return true;
- }
-
- /**
- * Return the total number of instructions executed globally (i.e. in
- * all threads).
- */
- public int globalTotal() {
- int count = 0;
- for (int i = 0; i < NUM_INSTR; i++)
- count += mCounts[i];
- return count;
- }
-
- /**
- * Return the total number of method-invocation instructions
- * executed globally.
- */
- public int globalMethodInvocations() {
- int count = 0;
-
- //count += mCounts[Opcodes.OP_EXECUTE_INLINE];
- count += mCounts[Opcodes.OP_INVOKE_VIRTUAL];
- count += mCounts[Opcodes.OP_INVOKE_SUPER];
- count += mCounts[Opcodes.OP_INVOKE_DIRECT];
- count += mCounts[Opcodes.OP_INVOKE_STATIC];
- count += mCounts[Opcodes.OP_INVOKE_INTERFACE];
- count += mCounts[Opcodes.OP_INVOKE_VIRTUAL_RANGE];
- count += mCounts[Opcodes.OP_INVOKE_SUPER_RANGE];
- count += mCounts[Opcodes.OP_INVOKE_DIRECT_RANGE];
- count += mCounts[Opcodes.OP_INVOKE_STATIC_RANGE];
- count += mCounts[Opcodes.OP_INVOKE_INTERFACE_RANGE];
- //count += mCounts[Opcodes.OP_INVOKE_DIRECT_EMPTY];
- count += mCounts[Opcodes.OP_INVOKE_VIRTUAL_QUICK];
- count += mCounts[Opcodes.OP_INVOKE_VIRTUAL_QUICK_RANGE];
- count += mCounts[Opcodes.OP_INVOKE_SUPER_QUICK];
- count += mCounts[Opcodes.OP_INVOKE_SUPER_QUICK_RANGE];
- return count;
- }
- };
-}
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
deleted file mode 100644
index f761e8e..0000000
--- a/core/java/android/os/Environment.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import java.io.File;
-
-/**
- * Provides access to environment variables.
- */
-public class Environment {
-
- private static final File ROOT_DIRECTORY
- = getDirectory("ANDROID_ROOT", "/system");
-
- /**
- * Gets the Android root directory.
- */
- public static File getRootDirectory() {
- return ROOT_DIRECTORY;
- }
-
- private static final File DATA_DIRECTORY
- = getDirectory("ANDROID_DATA", "/data");
-
- private static final File EXTERNAL_STORAGE_DIRECTORY
- = getDirectory("EXTERNAL_STORAGE", "/sdcard");
-
- private static final File DOWNLOAD_CACHE_DIRECTORY
- = getDirectory("DOWNLOAD_CACHE", "/cache");
-
- /**
- * Gets the Android data directory.
- */
- public static File getDataDirectory() {
- return DATA_DIRECTORY;
- }
-
- /**
- * Gets the Android external storage directory.
- */
- public static File getExternalStorageDirectory() {
- return EXTERNAL_STORAGE_DIRECTORY;
- }
-
- /**
- * Gets the Android Download/Cache content directory.
- */
- public static File getDownloadCacheDirectory() {
- return DOWNLOAD_CACHE_DIRECTORY;
- }
-
- /**
- * getExternalStorageState() returns MEDIA_REMOVED if the media is not present.
- */
- public static final String MEDIA_REMOVED = "removed";
-
- /**
- * getExternalStorageState() returns MEDIA_UNMOUNTED if the media is present
- * but not mounted.
- */
- public static final String MEDIA_UNMOUNTED = "unmounted";
-
- /**
- * getExternalStorageState() returns MEDIA_CHECKING if the media is present
- * and being disk-checked
- */
- public static final String MEDIA_CHECKING = "checking";
-
- /**
- * getExternalStorageState() returns MEDIA_NOFS if the media is present
- * but is blank or is using an unsupported filesystem
- */
- public static final String MEDIA_NOFS = "nofs";
-
- /**
- * getExternalStorageState() returns MEDIA_MOUNTED if the media is present
- * and mounted at its mount point with read/write access.
- */
- public static final String MEDIA_MOUNTED = "mounted";
-
- /**
- * getExternalStorageState() returns MEDIA_MOUNTED_READ_ONLY if the media is present
- * and mounted at its mount point with read only access.
- */
- public static final String MEDIA_MOUNTED_READ_ONLY = "mounted_ro";
-
- /**
- * getExternalStorageState() returns MEDIA_SHARED if the media is present
- * not mounted, and shared via USB mass storage.
- */
- public static final String MEDIA_SHARED = "shared";
-
- /**
- * getExternalStorageState() returns MEDIA_BAD_REMOVAL if the media was
- * removed before it was unmounted.
- */
- public static final String MEDIA_BAD_REMOVAL = "bad_removal";
-
- /**
- * getExternalStorageState() returns MEDIA_UNMOUNTABLE if the media is present
- * but cannot be mounted. Typically this happens if the file system on the
- * media is corrupted.
- */
- public static final String MEDIA_UNMOUNTABLE = "unmountable";
-
- /**
- * Gets the current state of the external storage device.
- */
- public static String getExternalStorageState() {
- return SystemProperties.get("EXTERNAL_STORAGE_STATE", MEDIA_REMOVED);
- }
-
- static File getDirectory(String variableName, String defaultPath) {
- String path = System.getenv(variableName);
- return path == null ? new File(defaultPath) : new File(path);
- }
-}
diff --git a/core/java/android/os/Exec.java b/core/java/android/os/Exec.java
deleted file mode 100644
index a50d5fe..0000000
--- a/core/java/android/os/Exec.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import java.io.FileDescriptor;
-
-/**
- * @hide
- * Tools for executing commands. Not for public consumption.
- */
-
-public class Exec
-{
- /**
- * @param cmd The command to execute
- * @param arg0 The first argument to the command, may be null
- * @param arg1 the second argument to the command, may be null
- * @return the file descriptor of the started process.
- *
- */
- public static FileDescriptor createSubprocess(
- String cmd, String arg0, String arg1) {
- return createSubprocess(cmd, arg0, arg1, null);
- }
-
- /**
- * @param cmd The command to execute
- * @param arg0 The first argument to the command, may be null
- * @param arg1 the second argument to the command, may be null
- * @param processId A one-element array to which the process ID of the
- * started process will be written.
- * @return the file descriptor of the started process.
- *
- */
- public static native FileDescriptor createSubprocess(
- String cmd, String arg0, String arg1, int[] processId);
-
- public static native void setPtyWindowSize(FileDescriptor fd,
- int row, int col, int xpixel, int ypixel);
- /**
- * Causes the calling thread to wait for the process associated with the
- * receiver to finish executing.
- *
- * @return The exit value of the Process being waited on
- *
- */
- public static native int waitFor(int processId);
-}
-
diff --git a/core/java/android/os/FileObserver.java b/core/java/android/os/FileObserver.java
deleted file mode 100644
index d9804ea..0000000
--- a/core/java/android/os/FileObserver.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.util.Log;
-
-import com.android.internal.os.RuntimeInit;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-public abstract class FileObserver {
- public static final int ACCESS = 0x00000001; /* File was accessed */
- public static final int MODIFY = 0x00000002; /* File was modified */
- public static final int ATTRIB = 0x00000004; /* Metadata changed */
- public static final int CLOSE_WRITE = 0x00000008; /* Writtable file was closed */
- public static final int CLOSE_NOWRITE = 0x00000010; /* Unwrittable file closed */
- public static final int OPEN = 0x00000020; /* File was opened */
- public static final int MOVED_FROM = 0x00000040; /* File was moved from X */
- public static final int MOVED_TO = 0x00000080; /* File was moved to Y */
- public static final int CREATE = 0x00000100; /* Subfile was created */
- public static final int DELETE = 0x00000200; /* Subfile was deleted */
- public static final int DELETE_SELF = 0x00000400; /* Self was deleted */
- public static final int MOVE_SELF = 0x00000800; /* Self was moved */
- public static final int ALL_EVENTS = ACCESS | MODIFY | ATTRIB | CLOSE_WRITE
- | CLOSE_NOWRITE | OPEN | MOVED_FROM | MOVED_TO | DELETE | CREATE
- | DELETE_SELF | MOVE_SELF;
-
- private static final String LOG_TAG = "FileObserver";
-
- private static class ObserverThread extends Thread {
- private HashMap<Integer, WeakReference> m_observers = new HashMap<Integer, WeakReference>();
- private int m_fd;
-
- public ObserverThread() {
- super("FileObserver");
- m_fd = init();
- }
-
- public void run() {
- observe(m_fd);
- }
-
- public int startWatching(String path, int mask, FileObserver observer) {
- int wfd = startWatching(m_fd, path, mask);
-
- Integer i = new Integer(wfd);
- if (wfd >= 0) {
- synchronized (m_observers) {
- m_observers.put(i, new WeakReference(observer));
- }
- }
-
- return i;
- }
-
- public void stopWatching(int descriptor) {
- stopWatching(m_fd, descriptor);
- }
-
- public void onEvent(int wfd, int mask, String path) {
- // look up our observer, fixing up the map if necessary...
- FileObserver observer;
-
- synchronized (m_observers) {
- WeakReference weak = m_observers.get(wfd);
- observer = (FileObserver) weak.get();
- if (observer == null) {
- m_observers.remove(wfd);
- }
- }
-
- // ...then call out to the observer without the sync lock held
- if (observer != null) {
- try {
- observer.onEvent(mask, path);
- } catch (Throwable throwable) {
- Log.e(LOG_TAG, "Unhandled throwable " + throwable.toString() +
- " (returned by observer " + observer + ")", throwable);
- RuntimeInit.crash("FileObserver", throwable);
- }
- }
- }
-
- private native int init();
- private native void observe(int fd);
- private native int startWatching(int fd, String path, int mask);
- private native void stopWatching(int fd, int wfd);
- }
-
- private static ObserverThread s_observerThread;
-
- static {
- s_observerThread = new ObserverThread();
- s_observerThread.start();
- }
-
- // instance
- private String m_path;
- private Integer m_descriptor;
- private int m_mask;
-
- public FileObserver(String path) {
- this(path, ALL_EVENTS);
- }
-
- public FileObserver(String path, int mask) {
- m_path = path;
- m_mask = mask;
- m_descriptor = -1;
- }
-
- protected void finalize() {
- stopWatching();
- }
-
- public void startWatching() {
- if (m_descriptor < 0) {
- m_descriptor = s_observerThread.startWatching(m_path, m_mask, this);
- }
- }
-
- public void stopWatching() {
- if (m_descriptor >= 0) {
- s_observerThread.stopWatching(m_descriptor);
- m_descriptor = -1;
- }
- }
-
- public abstract void onEvent(int event, String path);
-}
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
deleted file mode 100644
index 51dfb5b..0000000
--- a/core/java/android/os/FileUtils.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.regex.Pattern;
-
-
-/**
- * Tools for managing files. Not for public consumption.
- * @hide
- */
-public class FileUtils
-{
- public static final int S_IRWXU = 00700;
- public static final int S_IRUSR = 00400;
- public static final int S_IWUSR = 00200;
- public static final int S_IXUSR = 00100;
-
- public static final int S_IRWXG = 00070;
- public static final int S_IRGRP = 00040;
- public static final int S_IWGRP = 00020;
- public static final int S_IXGRP = 00010;
-
- public static final int S_IRWXO = 00007;
- public static final int S_IROTH = 00004;
- public static final int S_IWOTH = 00002;
- public static final int S_IXOTH = 00001;
-
-
- /**
- * File status information. This class maps directly to the POSIX stat structure.
- * @hide
- */
- public static final class FileStatus {
- public int dev;
- public int ino;
- public int mode;
- public int nlink;
- public int uid;
- public int gid;
- public int rdev;
- public long size;
- public int blksize;
- public long blocks;
- public long atime;
- public long mtime;
- public long ctime;
- }
-
- /**
- * Get the status for the given path. This is equivalent to the POSIX stat(2) system call.
- * @param path The path of the file to be stat'd.
- * @param status Optional argument to fill in. It will only fill in the status if the file
- * exists.
- * @return true if the file exists and false if it does not exist. If you do not have
- * permission to stat the file, then this method will return false.
- */
- public static native boolean getFileStatus(String path, FileStatus status);
-
- /** Regular expression for safe filenames: no spaces or metacharacters */
- private static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("[\\w%+,./=_-]+");
-
- public static native int setPermissions(String file, int mode, int uid, int gid);
-
- public static native int getPermissions(String file, int[] outPermissions);
-
- /** returns the FAT file system volume ID for the volume mounted
- * at the given mount point, or -1 for failure
- * @param mount point for FAT volume
- * @return volume ID or -1
- */
- public static native int getFatVolumeId(String mountPoint);
-
- // copy a file from srcFile to destFile, return true if succeed, return
- // false if fail
- public static boolean copyFile(File srcFile, File destFile) {
- boolean result = false;
- try {
- InputStream in = new FileInputStream(srcFile);
- try {
- result = copyToFile(in, destFile);
- } finally {
- in.close();
- }
- } catch (IOException e) {
- result = false;
- }
- return result;
- }
-
- /**
- * Copy data from a source stream to destFile.
- * Return true if succeed, return false if failed.
- */
- public static boolean copyToFile(InputStream inputStream, File destFile) {
- try {
- OutputStream out = new FileOutputStream(destFile);
- try {
- byte[] buffer = new byte[4096];
- int bytesRead;
- while ((bytesRead = inputStream.read(buffer)) >= 0) {
- out.write(buffer, 0, bytesRead);
- }
- } finally {
- out.close();
- }
- return true;
- } catch (IOException e) {
- return false;
- }
- }
-
- /**
- * Check if a filename is "safe" (no metacharacters or spaces).
- * @param file The file to check
- */
- public static boolean isFilenameSafe(File file) {
- // Note, we check whether it matches what's known to be safe,
- // rather than what's known to be unsafe. Non-ASCII, control
- // characters, etc. are all unsafe by default.
- return SAFE_FILENAME_PATTERN.matcher(file.getPath()).matches();
- }
-
- /**
- * Read a text file into a String, optionally limiting the length.
- * @param file to read (will not seek, so things like /proc files are OK)
- * @param max length (positive for head, negative of tail, 0 for no limit)
- * @param ellipsis to add of the file was truncated (can be null)
- * @return the contents of the file, possibly truncated
- * @throws IOException if something goes wrong reading the file
- */
- public static String readTextFile(File file, int max, String ellipsis) throws IOException {
- InputStream input = new FileInputStream(file);
- try {
- if (max > 0) { // "head" mode: read the first N bytes
- byte[] data = new byte[max + 1];
- int length = input.read(data);
- if (length <= 0) return "";
- if (length <= max) return new String(data, 0, length);
- if (ellipsis == null) return new String(data, 0, max);
- return new String(data, 0, max) + ellipsis;
- } else if (max < 0) { // "tail" mode: read it all, keep the last N
- int len;
- boolean rolled = false;
- byte[] last = null, data = null;
- do {
- if (last != null) rolled = true;
- byte[] tmp = last; last = data; data = tmp;
- if (data == null) data = new byte[-max];
- len = input.read(data);
- } while (len == data.length);
-
- if (last == null && len <= 0) return "";
- if (last == null) return new String(data, 0, len);
- if (len > 0) {
- rolled = true;
- System.arraycopy(last, len, last, 0, last.length - len);
- System.arraycopy(data, 0, last, last.length - len, len);
- }
- if (ellipsis == null || !rolled) return new String(last);
- return ellipsis + new String(last);
- } else { // "cat" mode: read it all
- ByteArrayOutputStream contents = new ByteArrayOutputStream();
- int len;
- byte[] data = new byte[1024];
- do {
- len = input.read(data);
- if (len > 0) contents.write(data, 0, len);
- } while (len == data.length);
- return contents.toString();
- }
- } finally {
- input.close();
- }
- }
-}
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
deleted file mode 100644
index 2a32e54..0000000
--- a/core/java/android/os/Handler.java
+++ /dev/null
@@ -1,594 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.util.Log;
-import android.util.Printer;
-
-import java.lang.reflect.Modifier;
-
-/**
- * A Handler allows you to send and process {@link Message} and Runnable
- * objects associated with a thread's {@link MessageQueue}. Each Handler
- * instance is associated with a single thread and that thread's message
- * queue. When you create a new Handler, it is bound to the thread /
- * message queue of the thread that is creating it -- from that point on,
- * it will deliver messages and runnables to that message queue and execute
- * them as they come out of the message queue.
- *
- * <p>There are two main uses for a Handler: (1) to schedule messages and
- * runnables to be executed as some point in the future; and (2) to enqueue
- * an action to be performed on a different thread than your own.
- *
- * <p>Scheduling messages is accomplished with the
- * {@link #post}, {@link #postAtTime(Runnable, long)},
- * {@link #postDelayed}, {@link #sendEmptyMessage},
- * {@link #sendMessage}, {@link #sendMessageAtTime}, and
- * {@link #sendMessageDelayed} methods. The <em>post</em> versions allow
- * you to enqueue Runnable objects to be called by the message queue when
- * they are received; the <em>sendMessage</em> versions allow you to enqueue
- * a {@link Message} object containing a bundle of data that will be
- * processed by the Handler's {@link #handleMessage} method (requiring that
- * you implement a subclass of Handler).
- *
- * <p>When posting or sending to a Handler, you can either
- * allow the item to be processed as soon as the message queue is ready
- * to do so, or specify a delay before it gets processed or absolute time for
- * it to be processed. The latter two allow you to implement timeouts,
- * ticks, and other timing-based behavior.
- *
- * <p>When a
- * process is created for your application, its main thread is dedicated to
- * running a message queue that takes care of managing the top-level
- * application objects (activities, broadcast receivers, etc) and any windows
- * they create. You can create your own threads, and communicate back with
- * the main application thread through a Handler. This is done by calling
- * the same <em>post</em> or <em>sendMessage</em> methods as before, but from
- * your new thread. The given Runnable or Message will than be scheduled
- * in the Handler's message queue and processed when appropriate.
- */
-public class Handler {
- /*
- * Set this flag to true to detect anonymous, local or member classes
- * that extend this Handler class and that are not static. These kind
- * of classes can potentially create leaks.
- */
- private static final boolean FIND_POTENTIAL_LEAKS = false;
- private static final String TAG = "Handler";
-
- /**
- * Callback interface you can use when instantiating a Handler to avoid
- * having to implement your own subclass of Handler.
- */
- public interface Callback {
- public boolean handleMessage(Message msg);
- }
-
- /**
- * Subclasses must implement this to receive messages.
- */
- public void handleMessage(Message msg) {
- }
-
- /**
- * Handle system messages here.
- */
- public void dispatchMessage(Message msg) {
- if (msg.callback != null) {
- handleCallback(msg);
- } else {
- if (mCallback != null) {
- if (mCallback.handleMessage(msg)) {
- return;
- }
- }
- handleMessage(msg);
- }
- }
-
- /**
- * Default constructor associates this handler with the queue for the
- * current thread.
- *
- * If there isn't one, this handler won't be able to receive messages.
- */
- public Handler() {
- if (FIND_POTENTIAL_LEAKS) {
- final Class<? extends Handler> klass = getClass();
- if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
- (klass.getModifiers() & Modifier.STATIC) == 0) {
- Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
- klass.getCanonicalName());
- }
- }
-
- mLooper = Looper.myLooper();
- if (mLooper == null) {
- throw new RuntimeException(
- "Can't create handler inside thread that has not called Looper.prepare()");
- }
- mQueue = mLooper.mQueue;
- mCallback = null;
- }
-
- /**
- * Constructor associates this handler with the queue for the
- * current thread and takes a callback interface in which you can handle
- * messages.
- */
- public Handler(Callback callback) {
- if (FIND_POTENTIAL_LEAKS) {
- final Class<? extends Handler> klass = getClass();
- if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
- (klass.getModifiers() & Modifier.STATIC) == 0) {
- Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
- klass.getCanonicalName());
- }
- }
-
- mLooper = Looper.myLooper();
- if (mLooper == null) {
- throw new RuntimeException(
- "Can't create handler inside thread that has not called Looper.prepare()");
- }
- mQueue = mLooper.mQueue;
- mCallback = callback;
- }
-
- /**
- * Use the provided queue instead of the default one.
- */
- public Handler(Looper looper) {
- mLooper = looper;
- mQueue = looper.mQueue;
- mCallback = null;
- }
-
- /**
- * Use the provided queue instead of the default one and take a callback
- * interface in which to handle messages.
- */
- public Handler(Looper looper, Callback callback) {
- mLooper = looper;
- mQueue = looper.mQueue;
- mCallback = callback;
- }
-
- /**
- * Returns a new {@link android.os.Message Message} from the global message pool. More efficient than
- * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).
- * If you don't want that facility, just call Message.obtain() instead.
- */
- public final Message obtainMessage()
- {
- return Message.obtain(this);
- }
-
- /**
- * Same as {@link #obtainMessage()}, except that it also sets the what member of the returned Message.
- *
- * @param what Value to assign to the returned Message.what field.
- * @return A Message from the global message pool.
- */
- public final Message obtainMessage(int what)
- {
- return Message.obtain(this, what);
- }
-
- /**
- *
- * Same as {@link #obtainMessage()}, except that it also sets the what and obj members
- * of the returned Message.
- *
- * @param what Value to assign to the returned Message.what field.
- * @param obj Value to assign to the returned Message.obj field.
- * @return A Message from the global message pool.
- */
- public final Message obtainMessage(int what, Object obj)
- {
- return Message.obtain(this, what, obj);
- }
-
- /**
- *
- * Same as {@link #obtainMessage()}, except that it also sets the what, arg1 and arg2 members of the returned
- * Message.
- * @param what Value to assign to the returned Message.what field.
- * @param arg1 Value to assign to the returned Message.arg1 field.
- * @param arg2 Value to assign to the returned Message.arg2 field.
- * @return A Message from the global message pool.
- */
- public final Message obtainMessage(int what, int arg1, int arg2)
- {
- return Message.obtain(this, what, arg1, arg2);
- }
-
- /**
- *
- * Same as {@link #obtainMessage()}, except that it also sets the what, obj, arg1,and arg2 values on the
- * returned Message.
- * @param what Value to assign to the returned Message.what field.
- * @param arg1 Value to assign to the returned Message.arg1 field.
- * @param arg2 Value to assign to the returned Message.arg2 field.
- * @param obj Value to assign to the returned Message.obj field.
- * @return A Message from the global message pool.
- */
- public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
- {
- return Message.obtain(this, what, arg1, arg2, obj);
- }
-
- /**
- * Causes the Runnable r to be added to the message queue.
- * The runnable will be run on the thread to which this handler is
- * attached.
- *
- * @param r The Runnable that will be executed.
- *
- * @return Returns true if the Runnable was successfully placed in to the
- * message queue. Returns false on failure, usually because the
- * looper processing the message queue is exiting.
- */
- public final boolean post(Runnable r)
- {
- return sendMessageDelayed(getPostMessage(r), 0);
- }
-
- /**
- * Causes the Runnable r to be added to the message queue, to be run
- * at a specific time given by <var>uptimeMillis</var>.
- * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
- * The runnable will be run on the thread to which this handler is attached.
- *
- * @param r The Runnable that will be executed.
- * @param uptimeMillis The absolute time at which the callback should run,
- * using the {@link android.os.SystemClock#uptimeMillis} time-base.
- *
- * @return Returns true if the Runnable was successfully placed in to the
- * message queue. Returns false on failure, usually because the
- * looper processing the message queue is exiting. Note that a
- * result of true does not mean the Runnable will be processed -- if
- * the looper is quit before the delivery time of the message
- * occurs then the message will be dropped.
- */
- public final boolean postAtTime(Runnable r, long uptimeMillis)
- {
- return sendMessageAtTime(getPostMessage(r), uptimeMillis);
- }
-
- /**
- * Causes the Runnable r to be added to the message queue, to be run
- * at a specific time given by <var>uptimeMillis</var>.
- * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
- * The runnable will be run on the thread to which this handler is attached.
- *
- * @param r The Runnable that will be executed.
- * @param uptimeMillis The absolute time at which the callback should run,
- * using the {@link android.os.SystemClock#uptimeMillis} time-base.
- *
- * @return Returns true if the Runnable was successfully placed in to the
- * message queue. Returns false on failure, usually because the
- * looper processing the message queue is exiting. Note that a
- * result of true does not mean the Runnable will be processed -- if
- * the looper is quit before the delivery time of the message
- * occurs then the message will be dropped.
- *
- * @see android.os.SystemClock#uptimeMillis
- */
- public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
- {
- return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
- }
-
- /**
- * Causes the Runnable r to be added to the message queue, to be run
- * after the specified amount of time elapses.
- * The runnable will be run on the thread to which this handler
- * is attached.
- *
- * @param r The Runnable that will be executed.
- * @param delayMillis The delay (in milliseconds) until the Runnable
- * will be executed.
- *
- * @return Returns true if the Runnable was successfully placed in to the
- * message queue. Returns false on failure, usually because the
- * looper processing the message queue is exiting. Note that a
- * result of true does not mean the Runnable will be processed --
- * if the looper is quit before the delivery time of the message
- * occurs then the message will be dropped.
- */
- public final boolean postDelayed(Runnable r, long delayMillis)
- {
- return sendMessageDelayed(getPostMessage(r), delayMillis);
- }
-
- /**
- * Posts a message to an object that implements Runnable.
- * Causes the Runnable r to executed on the next iteration through the
- * message queue. The runnable will be run on the thread to which this
- * handler is attached.
- * <b>This method is only for use in very special circumstances -- it
- * can easily starve the message queue, cause ordering problems, or have
- * other unexpected side-effects.</b>
- *
- * @param r The Runnable that will be executed.
- *
- * @return Returns true if the message was successfully placed in to the
- * message queue. Returns false on failure, usually because the
- * looper processing the message queue is exiting.
- */
- public final boolean postAtFrontOfQueue(Runnable r)
- {
- return sendMessageAtFrontOfQueue(getPostMessage(r));
- }
-
- /**
- * Remove any pending posts of Runnable r that are in the message queue.
- */
- public final void removeCallbacks(Runnable r)
- {
- mQueue.removeMessages(this, r, null);
- }
-
- /**
- * Remove any pending posts of Runnable <var>r</var> with Object
- * <var>token</var> that are in the message queue.
- */
- public final void removeCallbacks(Runnable r, Object token)
- {
- mQueue.removeMessages(this, r, token);
- }
-
- /**
- * Pushes a message onto the end of the message queue after all pending messages
- * before the current time. It will be received in {@link #handleMessage},
- * in the thread attached to this handler.
- *
- * @return Returns true if the message was successfully placed in to the
- * message queue. Returns false on failure, usually because the
- * looper processing the message queue is exiting.
- */
- public final boolean sendMessage(Message msg)
- {
- return sendMessageDelayed(msg, 0);
- }
-
- /**
- * Sends a Message containing only the what value.
- *
- * @return Returns true if the message was successfully placed in to the
- * message queue. Returns false on failure, usually because the
- * looper processing the message queue is exiting.
- */
- public final boolean sendEmptyMessage(int what)
- {
- return sendEmptyMessageDelayed(what, 0);
- }
-
- /**
- * Sends a Message containing only the what value, to be delivered
- * after the specified amount of time elapses.
- * @see #sendMessageDelayed(android.os.Message, long)
- *
- * @return Returns true if the message was successfully placed in to the
- * message queue. Returns false on failure, usually because the
- * looper processing the message queue is exiting.
- */
- public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
- Message msg = Message.obtain();
- msg.what = what;
- return sendMessageDelayed(msg, delayMillis);
- }
-
- /**
- * Sends a Message containing only the what value, to be delivered
- * at a specific time.
- * @see #sendMessageAtTime(android.os.Message, long)
- *
- * @return Returns true if the message was successfully placed in to the
- * message queue. Returns false on failure, usually because the
- * looper processing the message queue is exiting.
- */
-
- public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
- Message msg = Message.obtain();
- msg.what = what;
- return sendMessageAtTime(msg, uptimeMillis);
- }
-
- /**
- * Enqueue a message into the message queue after all pending messages
- * before (current time + delayMillis). You will receive it in
- * {@link #handleMessage}, in the thread attached to this handler.
- *
- * @return Returns true if the message was successfully placed in to the
- * message queue. Returns false on failure, usually because the
- * looper processing the message queue is exiting. Note that a
- * result of true does not mean the message will be processed -- if
- * the looper is quit before the delivery time of the message
- * occurs then the message will be dropped.
- */
- public final boolean sendMessageDelayed(Message msg, long delayMillis)
- {
- if (delayMillis < 0) {
- delayMillis = 0;
- }
- return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
- }
-
- /**
- * Enqueue a message into the message queue after all pending messages
- * before the absolute time (in milliseconds) <var>uptimeMillis</var>.
- * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
- * You will receive it in {@link #handleMessage}, in the thread attached
- * to this handler.
- *
- * @param uptimeMillis The absolute time at which the message should be
- * delivered, using the
- * {@link android.os.SystemClock#uptimeMillis} time-base.
- *
- * @return Returns true if the message was successfully placed in to the
- * message queue. Returns false on failure, usually because the
- * looper processing the message queue is exiting. Note that a
- * result of true does not mean the message will be processed -- if
- * the looper is quit before the delivery time of the message
- * occurs then the message will be dropped.
- */
- public boolean sendMessageAtTime(Message msg, long uptimeMillis)
- {
- boolean sent = false;
- MessageQueue queue = mQueue;
- if (queue != null) {
- msg.target = this;
- sent = queue.enqueueMessage(msg, uptimeMillis);
- }
- else {
- RuntimeException e = new RuntimeException(
- this + " sendMessageAtTime() called with no mQueue");
- Log.w("Looper", e.getMessage(), e);
- }
- return sent;
- }
-
- /**
- * Enqueue a message at the front of the message queue, to be processed on
- * the next iteration of the message loop. You will receive it in
- * {@link #handleMessage}, in the thread attached to this handler.
- * <b>This method is only for use in very special circumstances -- it
- * can easily starve the message queue, cause ordering problems, or have
- * other unexpected side-effects.</b>
- *
- * @return Returns true if the message was successfully placed in to the
- * message queue. Returns false on failure, usually because the
- * looper processing the message queue is exiting.
- */
- public final boolean sendMessageAtFrontOfQueue(Message msg)
- {
- boolean sent = false;
- MessageQueue queue = mQueue;
- if (queue != null) {
- msg.target = this;
- sent = queue.enqueueMessage(msg, 0);
- }
- else {
- RuntimeException e = new RuntimeException(
- this + " sendMessageAtTime() called with no mQueue");
- Log.w("Looper", e.getMessage(), e);
- }
- return sent;
- }
-
- /**
- * Remove any pending posts of messages with code 'what' that are in the
- * message queue.
- */
- public final void removeMessages(int what) {
- mQueue.removeMessages(this, what, null, true);
- }
-
- /**
- * Remove any pending posts of messages with code 'what' and whose obj is
- * 'object' that are in the message queue.
- */
- public final void removeMessages(int what, Object object) {
- mQueue.removeMessages(this, what, object, true);
- }
-
- /**
- * Remove any pending posts of callbacks and sent messages whose
- * <var>obj</var> is <var>token</var>.
- */
- public final void removeCallbacksAndMessages(Object token) {
- mQueue.removeCallbacksAndMessages(this, token);
- }
-
- /**
- * Check if there are any pending posts of messages with code 'what' in
- * the message queue.
- */
- public final boolean hasMessages(int what) {
- return mQueue.removeMessages(this, what, null, false);
- }
-
- /**
- * Check if there are any pending posts of messages with code 'what' and
- * whose obj is 'object' in the message queue.
- */
- public final boolean hasMessages(int what, Object object) {
- return mQueue.removeMessages(this, what, object, false);
- }
-
- // if we can get rid of this method, the handler need not remember its loop
- // we could instead export a getMessageQueue() method...
- public final Looper getLooper() {
- return mLooper;
- }
-
- public final void dump(Printer pw, String prefix) {
- pw.println(prefix + this + " @ " + SystemClock.uptimeMillis());
- if (mLooper == null) {
- pw.println(prefix + "looper uninitialized");
- } else {
- mLooper.dump(pw, prefix + " ");
- }
- }
-
- @Override
- public String toString() {
- return "Handler{"
- + Integer.toHexString(System.identityHashCode(this))
- + "}";
- }
-
- final IMessenger getIMessenger() {
- synchronized (mQueue) {
- if (mMessenger != null) {
- return mMessenger;
- }
- mMessenger = new MessengerImpl();
- return mMessenger;
- }
- }
-
- private final class MessengerImpl extends IMessenger.Stub {
- public void send(Message msg) {
- Handler.this.sendMessage(msg);
- }
- }
-
- private final Message getPostMessage(Runnable r) {
- Message m = Message.obtain();
- m.callback = r;
- return m;
- }
-
- private final Message getPostMessage(Runnable r, Object token) {
- Message m = Message.obtain();
- m.obj = token;
- m.callback = r;
- return m;
- }
-
- private final void handleCallback(Message message) {
- message.callback.run();
- }
-
- final MessageQueue mQueue;
- final Looper mLooper;
- final Callback mCallback;
- IMessenger mMessenger;
-}
diff --git a/core/java/android/os/HandlerState.java b/core/java/android/os/HandlerState.java
deleted file mode 100644
index 0708f7d..0000000
--- a/core/java/android/os/HandlerState.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * {@hide}
- */
-public abstract class HandlerState {
- public HandlerState() {
- }
-
- public void enter(Message message) {
- }
-
- public abstract void processMessage(Message message);
-
- public void exit(Message message) {
- }
-}
diff --git a/core/java/android/os/HandlerStateMachine.java b/core/java/android/os/HandlerStateMachine.java
deleted file mode 100644
index d004a25..0000000
--- a/core/java/android/os/HandlerStateMachine.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.util.Log;
-import android.util.LogPrinter;
-
-/**
- * {@hide}
- *
- * Implement a state machine where each state is an object,
- * HandlerState. Each HandlerState must implement processMessage
- * and optionally enter/exit. When a state machine is created
- * the initial state must be set. When messages are sent to
- * a state machine the current state's processMessage method is
- * invoked. If this is the first message for this state the
- * enter method is called prior to processMessage and when
- * transtionTo is invoked the state's exit method will be
- * called after returning from processMessage.
- *
- * If a message should be handled in a different state the
- * processMessage method may call deferMessage. This causes
- * the message to be saved on a list until transitioning
- * to a new state, at which time all of the deferred messages
- * will be put on the front of the state machines queue and
- * processed by the new current state's processMessage
- * method.
- *
- * Below is an example state machine with two state's, S1 and S2.
- * The initial state is S1 which defers all messages and only
- * transition to S2 when message.what == TEST_WHAT_2. State S2
- * will process each messages until it receives TEST_WHAT_2
- * where it will transition back to S1:
-<code>
- class StateMachine1 extends HandlerStateMachine {
- private static final int TEST_WHAT_1 = 1;
- private static final int TEST_WHAT_2 = 2;
-
- StateMachine1(String name) {
- super(name);
- setInitialState(mS1);
- }
-
- class S1 extends HandlerState {
- @Override public void enter(Message message) {
- }
-
- @Override public void processMessage(Message message) {
- deferMessage(message);
- if (message.what == TEST_WHAT_2) {
- transitionTo(mS2);
- }
- }
-
- @Override public void exit(Message message) {
- }
- }
-
- class S2 extends HandlerState {
- @Override public void processMessage(Message message) {
- // Do some processing
- if (message.what == TEST_WHAT_2) {
- transtionTo(mS1);
- }
- }
- }
-
- private S1 mS1 = new S1();
- private S2 mS2 = new S2();
- }
-</code>
- */
-public class HandlerStateMachine {
-
- private boolean mDbg = false;
- private static final String TAG = "HandlerStateMachine";
- private String mName;
- private SmHandler mHandler;
- private HandlerThread mHandlerThread;
-
- /**
- * Handle messages sent to the state machine by calling
- * the current state's processMessage. It also handles
- * the enter/exit calls and placing any deferred messages
- * back onto the queue when transitioning to a new state.
- */
- class SmHandler extends Handler {
-
- SmHandler(Looper looper) {
- super(looper);
- }
-
- /**
- * This will dispatch the message to the
- * current state's processMessage.
- */
- @Override
- final public void handleMessage(Message msg) {
- if (mDbg) Log.d(TAG, "SmHandler.handleMessage E");
- if (mDestState != null) {
- if (mDbg) Log.d(TAG, "SmHandler.handleMessage; new destation call enter");
- mCurrentState = mDestState;
- mDestState = null;
- mCurrentState.enter(msg);
- }
- if (mCurrentState != null) {
- if (mDbg) Log.d(TAG, "SmHandler.handleMessage; call processMessage");
- mCurrentState.processMessage(msg);
- } else {
- /* Strange no state to execute */
- Log.e(TAG, "handleMessage: no current state, did you call setInitialState");
- }
-
- if (mDestState != null) {
- if (mDbg) Log.d(TAG, "SmHandler.handleMessage; new destination call exit");
- mCurrentState.exit(msg);
-
- /**
- * Place the messages from the deferred queue:t
- * on to the Handler's message queue in the
- * same order that they originally arrived.
- *
- * We set cur.when = 0 to circumvent the check
- * that this message has already been sent.
- */
- while (mDeferredMessages != null) {
- Message cur = mDeferredMessages;
- mDeferredMessages = mDeferredMessages.next;
- cur.when = 0;
- if (mDbg) Log.d(TAG, "SmHandler.handleMessage; queue deferred message what="
- + cur.what + " target=" + cur.target);
- sendMessageAtFrontOfQueue(cur);
- }
- if (mDbg) Log.d(TAG, "SmHandler.handleMessage X");
- }
- }
-
- public HandlerState mCurrentState;
- public HandlerState mDestState;
- public Message mDeferredMessages;
- }
-
- /**
- * Create an active StateMachine, one that has a
- * dedicated thread/looper/queue.
- */
- public HandlerStateMachine(String name) {
- mName = name;
- mHandlerThread = new HandlerThread(name);
- mHandlerThread.start();
- mHandler = new SmHandler(mHandlerThread.getLooper());
- }
-
- /**
- * Get a message and set Message.target = this.
- */
- public final Message obtainMessage()
- {
- Message msg = Message.obtain(mHandler);
- if (mDbg) Log.d(TAG, "StateMachine.obtainMessage() EX target=" + msg.target);
- return msg;
- }
-
- /**
- * Get a message and set Message.target = this and
- * Message.what = what.
- */
- public final Message obtainMessage(int what) {
- Message msg = Message.obtain(mHandler, what);
- if (mDbg) {
- Log.d(TAG, "StateMachine.obtainMessage(what) EX what=" + msg.what +
- " target=" + msg.target);
- }
- return msg;
- }
-
- /**
- * Enqueue a message to this state machine.
- */
- public final void sendMessage(Message msg) {
- if (mDbg) Log.d(TAG, "StateMachine.sendMessage EX msg.what=" + msg.what);
- mHandler.sendMessage(msg);
- }
-
- /**
- * Enqueue a message to this state machine after a delay.
- */
- public final void sendMessageDelayed(Message msg, long delayMillis) {
- if (mDbg) {
- Log.d(TAG, "StateMachine.sendMessageDelayed EX msg.what="
- + msg.what + " delay=" + delayMillis);
- }
- mHandler.sendMessageDelayed(msg, delayMillis);
- }
-
- /**
- * Set the initial state. This must be invoked before
- * and messages are sent to the state machine.
- */
- public void setInitialState(HandlerState initialState) {
- if (mDbg) {
- Log.d(TAG, "StateMachine.setInitialState EX initialState"
- + initialState.getClass().getName());
- }
- mHandler.mDestState = initialState;
- }
-
- /**
- * transition to destination state. Upon returning
- * from processMessage the current state's exit will
- * be executed and upon the next message arriving
- * destState.enter will be invoked.
- */
- final public void transitionTo(HandlerState destState) {
- if (mDbg) {
- Log.d(TAG, "StateMachine.transitionTo EX destState"
- + destState.getClass().getName());
- }
- mHandler.mDestState = destState;
- }
-
- /**
- * Defer this message until next state transition.
- * Upon transitioning all deferred messages will be
- * placed on the queue and reprocessed in the original
- * order. (i.e. The next state the oldest messages will
- * be processed first)
- */
- final public void deferMessage(Message msg) {
- if (mDbg) {
- Log.d(TAG, "StateMachine.deferMessage EX mDeferredMessages="
- + mHandler.mDeferredMessages);
- }
-
- /* Copy the "msg" to "newMsg" as "msg" will be recycled */
- Message newMsg = obtainMessage();
- newMsg.copyFrom(msg);
-
- /* Place on front of queue */
- newMsg.next = mHandler.mDeferredMessages;
- mHandler.mDeferredMessages = newMsg;
- }
-
- /**
- * @return the name
- */
- public String getName() {
- return mName;
- }
-
- /**
- * @return Handler
- */
- public Handler getHandler() {
- return mHandler;
- }
-
- /**
- * @return if debugging is enabled
- */
- public boolean isDbg() {
- return mDbg;
- }
-
- /**
- * Set debug enable/disabled.
- */
- public void setDbg(boolean dbg) {
- mDbg = dbg;
- if (mDbg) {
- mHandlerThread.getLooper().setMessageLogging(new LogPrinter(Log.VERBOSE, TAG));
- } else {
- mHandlerThread.getLooper().setMessageLogging(null);
- }
- }
-}
diff --git a/core/java/android/os/HandlerThread.java b/core/java/android/os/HandlerThread.java
deleted file mode 100644
index 0ce86db..0000000
--- a/core/java/android/os/HandlerThread.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * Handy class for starting a new thread that has a looper. The looper can then be
- * used to create handler classes. Note that start() must still be called.
- */
-public class HandlerThread extends Thread {
- private int mPriority;
- private int mTid = -1;
- private Looper mLooper;
-
- public HandlerThread(String name) {
- super(name);
- mPriority = Process.THREAD_PRIORITY_DEFAULT;
- }
-
- /**
- * Constructs a HandlerThread.
- * @param name
- * @param priority The priority to run the thread at. The value supplied must be from
- * {@link android.os.Process} and not from java.lang.Thread.
- */
- public HandlerThread(String name, int priority) {
- super(name);
- mPriority = priority;
- }
-
- /**
- * Call back method that can be explicitly over ridden if needed to execute some
- * setup before Looper loops.
- */
- protected void onLooperPrepared() {
- }
-
- public void run() {
- mTid = Process.myTid();
- Looper.prepare();
- synchronized (this) {
- mLooper = Looper.myLooper();
- Process.setThreadPriority(mPriority);
- notifyAll();
- }
- onLooperPrepared();
- Looper.loop();
- mTid = -1;
- }
-
- /**
- * This method returns the Looper associated with this thread. If this thread not been started
- * or for any reason is isAlive() returns false, this method will return null. If this thread
- * has been started, this method will blocked until the looper has been initialized.
- * @return The looper.
- */
- public Looper getLooper() {
- if (!isAlive()) {
- return null;
- }
-
- // If the thread has been started, wait until the looper has been created.
- synchronized (this) {
- while (isAlive() && mLooper == null) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
- }
- return mLooper;
- }
-
- /**
- * Returns the identifier of this thread. See Process.myTid().
- */
- public int getThreadId() {
- return mTid;
- }
-}
diff --git a/core/java/android/os/Hardware.java b/core/java/android/os/Hardware.java
deleted file mode 100644
index 3b6c9d7..0000000
--- a/core/java/android/os/Hardware.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * {@hide}
- */
-public class Hardware
-{
- /**
- * Control the LED.
- */
- public static native int setLedState(int colorARGB, int onMS, int offMS);
-
- /**
- * Control the Flashlight
- */
- public static native boolean getFlashlightEnabled();
- public static native void setFlashlightEnabled(boolean on);
- public static native void enableCameraFlash(int milliseconds);
-
- /**
- * Control the backlights
- */
- public static native void setScreenBacklight(int brightness);
- public static native void setKeyboardBacklight(boolean on);
- public static native void setButtonBacklight(boolean on);
-}
diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java
deleted file mode 100644
index 5c40c9a0..0000000
--- a/core/java/android/os/IBinder.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * Base interface for a remotable object, the core part of a lightweight
- * remote procedure call mechanism designed for high performance when
- * performing in-process and cross-process calls. This
- * interface describes the abstract protocol for interacting with a
- * remotable object. Do not implement this interface directly, instead
- * extend from {@link Binder}.
- *
- * <p>The key IBinder API is {@link #transact transact()} matched by
- * {@link Binder#onTransact Binder.onTransact()}. These
- * methods allow you to send a call to an IBinder object and receive a
- * call coming in to a Binder object, respectively. This transaction API
- * is synchronous, such that a call to {@link #transact transact()} does not
- * return until the target has returned from
- * {@link Binder#onTransact Binder.onTransact()}; this is the
- * expected behavior when calling an object that exists in the local
- * process, and the underlying inter-process communication (IPC) mechanism
- * ensures that these same semantics apply when going across processes.
- *
- * <p>The data sent through transact() is a {@link Parcel}, a generic buffer
- * of data that also maintains some meta-data about its contents. The meta
- * data is used to manage IBinder object references in the buffer, so that those
- * references can be maintained as the buffer moves across processes. This
- * mechanism ensures that when an IBinder is written into a Parcel and sent to
- * another process, if that other process sends a reference to that same IBinder
- * back to the original process, then the original process will receive the
- * same IBinder object back. These semantics allow IBinder/Binder objects to
- * be used as a unique identity (to serve as a token or for other purposes)
- * that can be managed across processes.
- *
- * <p>The system maintains a pool of transaction threads in each process that
- * it runs in. These threads are used to dispatch all
- * IPCs coming in from other processes. For example, when an IPC is made from
- * process A to process B, the calling thread in A blocks in transact() as
- * it sends the transaction to process B. The next available pool thread in
- * B receives the incoming transaction, calls Binder.onTransact() on the target
- * object, and replies with the result Parcel. Upon receiving its result, the
- * thread in process A returns to allow its execution to continue. In effect,
- * other processes appear to use as additional threads that you did not create
- * executing in your own process.
- *
- * <p>The Binder system also supports recursion across processes. For example
- * if process A performs a transaction to process B, and process B while
- * handling that transaction calls transact() on an IBinder that is implemented
- * in A, then the thread in A that is currently waiting for the original
- * transaction to finish will take care of calling Binder.onTransact() on the
- * object being called by B. This ensures that the recursion semantics when
- * calling remote binder object are the same as when calling local objects.
- *
- * <p>When working with remote objects, you often want to find out when they
- * are no longer valid. There are three ways this can be determined:
- * <ul>
- * <li> The {@link #transact transact()} method will throw a
- * {@link RemoteException} exception if you try to call it on an IBinder
- * whose process no longer exists.
- * <li> The {@link #pingBinder()} method can be called, and will return false
- * if the remote process no longer exists.
- * <li> The {@link #linkToDeath linkToDeath()} method can be used to register
- * a {@link DeathRecipient} with the IBinder, which will be called when its
- * containing process goes away.
- * </ul>
- *
- * @see Binder
- */
-public interface IBinder {
- /**
- * The first transaction code available for user commands.
- */
- int FIRST_CALL_TRANSACTION = 0x00000001;
- /**
- * The last transaction code available for user commands.
- */
- int LAST_CALL_TRANSACTION = 0x00ffffff;
-
- /**
- * IBinder protocol transaction code: pingBinder().
- */
- int PING_TRANSACTION = ('_'<<24)|('P'<<16)|('N'<<8)|'G';
-
- /**
- * IBinder protocol transaction code: dump internal state.
- */
- int DUMP_TRANSACTION = ('_'<<24)|('D'<<16)|('M'<<8)|'P';
-
- /**
- * IBinder protocol transaction code: interrogate the recipient side
- * of the transaction for its canonical interface descriptor.
- */
- int INTERFACE_TRANSACTION = ('_'<<24)|('N'<<16)|('T'<<8)|'F';
-
- /**
- * Flag to {@link #transact}: this is a one-way call, meaning that the
- * caller returns immediately, without waiting for a result from the
- * callee.
- */
- int FLAG_ONEWAY = 0x00000001;
-
- /**
- * Get the canonical name of the interface supported by this binder.
- */
- public String getInterfaceDescriptor() throws RemoteException;
-
- /**
- * Check to see if the object still exists.
- *
- * @return Returns false if the
- * hosting process is gone, otherwise the result (always by default
- * true) returned by the pingBinder() implementation on the other
- * side.
- */
- public boolean pingBinder();
-
- /**
- * Check to see if the process that the binder is in is still alive.
- *
- * @return false if the process is not alive. Note that if it returns
- * true, the process may have died while the call is returning.
- */
- public boolean isBinderAlive();
-
- /**
- * Attempt to retrieve a local implementation of an interface
- * for this Binder object. If null is returned, you will need
- * to instantiate a proxy class to marshall calls through
- * the transact() method.
- */
- public IInterface queryLocalInterface(String descriptor);
-
- /**
- * Print the object's state into the given stream.
- *
- * @param fd The raw file descriptor that the dump is being sent to.
- * @param args additional arguments to the dump request.
- */
- public void dump(FileDescriptor fd, String[] args) throws RemoteException;
-
- /**
- * Perform a generic operation with the object.
- *
- * @param code The action to perform. This should
- * be a number between {@link #FIRST_CALL_TRANSACTION} and
- * {@link #LAST_CALL_TRANSACTION}.
- * @param data Marshalled data to send to the target. Most not be null.
- * If you are not sending any data, you must create an empty Parcel
- * that is given here.
- * @param reply Marshalled data to be received from the target. May be
- * null if you are not interested in the return value.
- * @param flags Additional operation flags. Either 0 for a normal
- * RPC, or {@link #FLAG_ONEWAY} for a one-way RPC.
- */
- public boolean transact(int code, Parcel data, Parcel reply, int flags)
- throws RemoteException;
-
- /**
- * Interface for receiving a callback when the process hosting an IBinder
- * has gone away.
- *
- * @see #linkToDeath
- */
- public interface DeathRecipient {
- public void binderDied();
- }
-
- /**
- * Register the recipient for a notification if this binder
- * goes away. If this binder object unexpectedly goes away
- * (typically because its hosting process has been killed),
- * then the given {@link DeathRecipient}'s
- * {@link DeathRecipient#binderDied DeathRecipient.binderDied()} method
- * will be called.
- *
- * <p>You will only receive death notifications for remote binders,
- * as local binders by definition can't die without you dying as well.
- *
- * @throws Throws {@link RemoteException} if the target IBinder's
- * process has already died.
- *
- * @see #unlinkToDeath
- */
- public void linkToDeath(DeathRecipient recipient, int flags)
- throws RemoteException;
-
- /**
- * Remove a previously registered death notification.
- * The recipient will no longer be called if this object
- * dies.
- *
- * @return Returns true if the <var>recipient</var> is successfully
- * unlinked, assuring you that its
- * {@link DeathRecipient#binderDied DeathRecipient.binderDied()} method
- * will not be called. Returns false if the target IBinder has already
- * died, meaning the method has been (or soon will be) called.
- *
- * @throws Throws {@link java.util.NoSuchElementException} if the given
- * <var>recipient</var> has not been registered with the IBinder, and
- * the IBinder is still alive. Note that if the <var>recipient</var>
- * was never registered, but the IBinder has already died, then this
- * exception will <em>not</em> be thrown, and you will receive a false
- * return value instead.
- */
- public boolean unlinkToDeath(DeathRecipient recipient, int flags);
-}
diff --git a/core/java/android/os/ICheckinService.aidl b/core/java/android/os/ICheckinService.aidl
deleted file mode 100644
index e56b55d..0000000
--- a/core/java/android/os/ICheckinService.aidl
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.os.IParentalControlCallback;
-
-/**
- * System private API for direct access to the checkin service.
- * Users should use the content provider instead.
- *
- * @see android.provider.Checkin
- * {@hide}
- */
-interface ICheckinService {
- /** Synchronously attempt a checkin with the server, return true
- * on success.
- * @throws IllegalStateException whenever an error occurs. The
- * cause of the exception will be the real exception:
- * IOException for network errors, JSONException for invalid
- * server responses, etc.
- */
- boolean checkin();
-
- /** Direct submission of crash data; returns after writing the crash. */
- void reportCrashSync(in byte[] crashData);
-
- /** Asynchronous "fire and forget" version of crash reporting. */
- oneway void reportCrashAsync(in byte[] crashData);
-
- /** Reboot into the recovery system and wipe all user data. */
- void masterClear();
-
- /**
- * Determine if the device is under parental control. Return null if
- * we are unable to check the parental control status.
- */
- void getParentalControlState(IParentalControlCallback p,
- String requestingApp);
-}
diff --git a/core/java/android/os/IHardwareService.aidl b/core/java/android/os/IHardwareService.aidl
deleted file mode 100755
index 4f6029f..0000000
--- a/core/java/android/os/IHardwareService.aidl
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Copyright (c) 2007, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/** {@hide} */
-interface IHardwareService
-{
- // Vibrator support
- void vibrate(long milliseconds);
- void vibratePattern(in long[] pattern, int repeat, IBinder token);
- void cancelVibrate();
-
- // flashlight support
- boolean getFlashlightEnabled();
- void setFlashlightEnabled(boolean on);
- void enableCameraFlash(int milliseconds);
-
- // backlight support
- void setScreenBacklight(int brightness);
- void setKeyboardBacklight(boolean on);
- void setButtonBacklight(boolean on);
-
- // LED support
- void setLedState(int colorARGB, int onMS, int offMS);
-}
-
diff --git a/core/java/android/os/IInterface.java b/core/java/android/os/IInterface.java
deleted file mode 100644
index 2a2605a..0000000
--- a/core/java/android/os/IInterface.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * Base class for Binder interfaces. When defining a new interface,
- * you must derive it from IInterface.
- */
-public interface IInterface
-{
- /**
- * Retrieve the Binder object associated with this interface.
- * You must use this instead of a plain cast, so that proxy objects
- * can return the correct result.
- */
- public IBinder asBinder();
-}
diff --git a/core/java/android/os/IMessenger.aidl b/core/java/android/os/IMessenger.aidl
deleted file mode 100644
index e4a8431..0000000
--- a/core/java/android/os/IMessenger.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/* //device/java/android/android/app/IActivityPendingResult.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.os;
-
-import android.os.Message;
-
-/** @hide */
-oneway interface IMessenger {
- void send(in Message msg);
-}
diff --git a/core/java/android/os/IMountService.aidl b/core/java/android/os/IMountService.aidl
deleted file mode 100644
index 88dae85..0000000
--- a/core/java/android/os/IMountService.aidl
+++ /dev/null
@@ -1,66 +0,0 @@
-/* //device/java/android/android/os/IUsb.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.os;
-
-/** WARNING! Update IMountService.h and IMountService.cpp if you change this file.
- * In particular, the ordering of the methods below must match the
- * _TRANSACTION enum in IMountService.cpp
- * @hide
- */
-interface IMountService
-{
- /**
- * Is mass storage support enabled?
- */
- boolean getMassStorageEnabled();
-
- /**
- * Enable or disable mass storage support.
- */
- void setMassStorageEnabled(boolean enabled);
-
- /**
- * Is mass storage connected?
- */
- boolean getMassStorageConnected();
-
- /**
- * Mount external storage at given mount point.
- */
- void mountMedia(String mountPoint);
-
- /**
- * Safely unmount external storage at given mount point.
- */
- void unmountMedia(String mountPoint);
-
- /**
- * Format external storage given a mount point
- */
- void formatMedia(String mountPoint);
-
- /**
- * Returns true if media notification sounds are enabled.
- */
- boolean getPlayNotificationSounds();
-
- /**
- * Sets whether or not media notification sounds are played.
- */
- void setPlayNotificationSounds(boolean value);
-}
diff --git a/core/java/android/os/INetStatService.aidl b/core/java/android/os/INetStatService.aidl
deleted file mode 100644
index a8f3de0..0000000
--- a/core/java/android/os/INetStatService.aidl
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * Retrieves packet and byte counts for the phone data interface,
- * and for all interfaces.
- * Used for the data activity icon and the phone status in Settings.
- *
- * {@hide}
- */
-interface INetStatService {
- long getMobileTxPackets();
- long getMobileRxPackets();
- long getMobileTxBytes();
- long getMobileRxBytes();
- long getTotalTxPackets();
- long getTotalRxPackets();
- long getTotalTxBytes();
- long getTotalRxBytes();
-}
diff --git a/core/java/android/os/IParentalControlCallback.aidl b/core/java/android/os/IParentalControlCallback.aidl
deleted file mode 100644
index 2f1a563..0000000
--- a/core/java/android/os/IParentalControlCallback.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import com.google.android.net.ParentalControlState;
-
-/**
- * This callback interface is used to deliver the parental control state to the calling application.
- * {@hide}
- */
-oneway interface IParentalControlCallback {
- void onResult(in ParentalControlState state);
-}
diff --git a/core/java/android/os/IPermissionController.aidl b/core/java/android/os/IPermissionController.aidl
deleted file mode 100644
index 73a68f1..0000000
--- a/core/java/android/os/IPermissionController.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/* //device/java/android/android/os/IPowerManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.os;
-
-/** @hide */
-interface IPermissionController {
- boolean checkPermission(String permission, int pid, int uid);
-}
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
deleted file mode 100644
index 5486920..0000000
--- a/core/java/android/os/IPowerManager.aidl
+++ /dev/null
@@ -1,33 +0,0 @@
-/* //device/java/android/android/os/IPowerManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.os;
-
-/** @hide */
-interface IPowerManager
-{
- void acquireWakeLock(int flags, IBinder lock, String tag);
- void goToSleep(long time);
- void releaseWakeLock(IBinder lock);
- void userActivity(long when, boolean noChangeLights);
- void userActivityWithForce(long when, boolean noChangeLights, boolean force);
- void setPokeLock(int pokey, IBinder lock, String tag);
- void setStayOnSetting(int val);
- long getScreenOnTime();
- void preventScreenOn(boolean prevent);
- void setScreenBrightnessOverride(int brightness);
-}
diff --git a/core/java/android/os/IServiceManager.java b/core/java/android/os/IServiceManager.java
deleted file mode 100644
index 9a5ff47..0000000
--- a/core/java/android/os/IServiceManager.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * Basic interface for finding and publishing system services.
- *
- * An implementation of this interface is usually published as the
- * global context object, which can be retrieved via
- * BinderNative.getContextObject(). An easy way to retrieve this
- * is with the static method BnServiceManager.getDefault().
- *
- * @hide
- */
-public interface IServiceManager extends IInterface
-{
- /**
- * Retrieve an existing service called @a name from the
- * service manager. Blocks for a few seconds waiting for it to be
- * published if it does not already exist.
- */
- public IBinder getService(String name) throws RemoteException;
-
- /**
- * Retrieve an existing service called @a name from the
- * service manager. Non-blocking.
- */
- public IBinder checkService(String name) throws RemoteException;
-
- /**
- * Place a new @a service called @a name into the service
- * manager.
- */
- public void addService(String name, IBinder service) throws RemoteException;
-
- /**
- * Return a list of all currently running services.
- */
- public String[] listServices() throws RemoteException;
-
- /**
- * Assign a permission controller to the service manager. After set, this
- * interface is checked before any services are added.
- */
- public void setPermissionController(IPermissionController controller)
- throws RemoteException;
-
- static final String descriptor = "android.os.IServiceManager";
-
- int GET_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
- int CHECK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+1;
- int ADD_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+2;
- int LIST_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+3;
- int CHECK_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+4;
- int SET_PERMISSION_CONTROLLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+5;
-}
diff --git a/core/java/android/os/LocalPowerManager.java b/core/java/android/os/LocalPowerManager.java
deleted file mode 100644
index 55d7972..0000000
--- a/core/java/android/os/LocalPowerManager.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/** @hide */
-public interface LocalPowerManager {
- public static final int OTHER_EVENT = 0;
- public static final int CHEEK_EVENT = 1;
- public static final int TOUCH_EVENT = 2;
- public static final int BUTTON_EVENT = 3; // Button and trackball events.
-
- public static final int POKE_LOCK_IGNORE_CHEEK_EVENTS = 0x1;
- public static final int POKE_LOCK_SHORT_TIMEOUT = 0x2;
- public static final int POKE_LOCK_MEDIUM_TIMEOUT = 0x4;
-
- public static final int POKE_LOCK_TIMEOUT_MASK = 0x6;
-
- void goToSleep(long time);
-
- // notify power manager when keyboard is opened/closed
- void setKeyboardVisibility(boolean visible);
-
- // when the keyguard is up, it manages the power state, and userActivity doesn't do anything.
- void enableUserActivity(boolean enabled);
-
- // the same as the method on PowerManager
- public void userActivity(long time, boolean noChangeLights, int eventType);
-}
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
deleted file mode 100644
index 9581893..0000000
--- a/core/java/android/os/Looper.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.util.Config;
-import android.util.Printer;
-
-/**
- * Class used to run a message loop for a thread. Threads by default do
- * not have a message loop associated with them; to create one, call
- * {@link #prepare} in the thread that is to run the loop, and then
- * {@link #loop} to have it process messages until the loop is stopped.
- *
- * <p>Most interaction with a message loop is through the
- * {@link Handler} class.
- *
- * <p>This is a typical example of the implementation of a Looper thread,
- * using the separation of {@link #prepare} and {@link #loop} to create an
- * initial Handler to communicate with the Looper.
- *
- * <pre>
- * class LooperThread extends Thread {
- * public Handler mHandler;
- *
- * public void run() {
- * Looper.prepare();
- *
- * mHandler = new Handler() {
- * public void handleMessage(Message msg) {
- * // process incoming messages here
- * }
- * };
- *
- * Looper.loop();
- * }
- * }</pre>
- */
-public class Looper {
- private static final boolean DEBUG = false;
- private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
-
- // sThreadLocal.get() will return null unless you've called prepare().
- private static final ThreadLocal sThreadLocal = new ThreadLocal();
-
- final MessageQueue mQueue;
- volatile boolean mRun;
- Thread mThread;
- private Printer mLogging = null;
- private static Looper mMainLooper = null;
-
- /** Initialize the current thread as a looper.
- * This gives you a chance to create handlers that then reference
- * this looper, before actually starting the loop. Be sure to call
- * {@link #loop()} after calling this method, and end it by calling
- * {@link #quit()}.
- */
- public static final void prepare() {
- if (sThreadLocal.get() != null) {
- throw new RuntimeException("Only one Looper may be created per thread");
- }
- sThreadLocal.set(new Looper());
- }
-
- /** Initialize the current thread as a looper, marking it as an application's main
- * looper. The main looper for your application is created by the Android environment,
- * so you should never need to call this function yourself.
- * {@link #prepare()}
- */
-
- public static final void prepareMainLooper() {
- prepare();
- setMainLooper(myLooper());
- if (Process.supportsProcesses()) {
- myLooper().mQueue.mQuitAllowed = false;
- }
- }
-
- private synchronized static void setMainLooper(Looper looper) {
- mMainLooper = looper;
- }
-
- /** Returns the application's main looper, which lives in the main thread of the application.
- */
- public synchronized static final Looper getMainLooper() {
- return mMainLooper;
- }
-
- /**
- * Run the message queue in this thread. Be sure to call
- * {@link #quit()} to end the loop.
- */
- public static final void loop() {
- Looper me = myLooper();
- MessageQueue queue = me.mQueue;
- while (true) {
- Message msg = queue.next(); // might block
- //if (!me.mRun) {
- // break;
- //}
- if (msg != null) {
- if (msg.target == null) {
- // No target is a magic identifier for the quit message.
- return;
- }
- if (me.mLogging!= null) me.mLogging.println(
- ">>>>> Dispatching to " + msg.target + " "
- + msg.callback + ": " + msg.what
- );
- msg.target.dispatchMessage(msg);
- if (me.mLogging!= null) me.mLogging.println(
- "<<<<< Finished to " + msg.target + " "
- + msg.callback);
- msg.recycle();
- }
- }
- }
-
- /**
- * Return the Looper object associated with the current thread. Returns
- * null if the calling thread is not associated with a Looper.
- */
- public static final Looper myLooper() {
- return (Looper)sThreadLocal.get();
- }
-
- /**
- * Control logging of messages as they are processed by this Looper. If
- * enabled, a log message will be written to <var>printer</var>
- * at the beginning and ending of each message dispatch, identifying the
- * target Handler and message contents.
- *
- * @param printer A Printer object that will receive log messages, or
- * null to disable message logging.
- */
- public void setMessageLogging(Printer printer) {
- mLogging = printer;
- }
-
- /**
- * Return the {@link MessageQueue} object associated with the current
- * thread. This must be called from a thread running a Looper, or a
- * NullPointerException will be thrown.
- */
- public static final MessageQueue myQueue() {
- return myLooper().mQueue;
- }
-
- private Looper() {
- mQueue = new MessageQueue();
- mRun = true;
- mThread = Thread.currentThread();
- }
-
- public void quit() {
- Message msg = Message.obtain();
- // NOTE: By enqueueing directly into the message queue, the
- // message is left with a null target. This is how we know it is
- // a quit message.
- mQueue.enqueueMessage(msg, 0);
- }
-
- /**
- * Return the Thread associated with this Looper.
- *
- * @since CURRENT
- * {@hide pending API Council approval}
- */
- public Thread getThread() {
- return mThread;
- }
-
- public void dump(Printer pw, String prefix) {
- pw.println(prefix + this);
- pw.println(prefix + "mRun=" + mRun);
- pw.println(prefix + "mThread=" + mThread);
- pw.println(prefix + "mQueue=" + ((mQueue != null) ? mQueue : "(null"));
- if (mQueue != null) {
- synchronized (mQueue) {
- Message msg = mQueue.mMessages;
- int n = 0;
- while (msg != null) {
- pw.println(prefix + " Message " + n + ": " + msg);
- n++;
- msg = msg.next;
- }
- pw.println(prefix + "(Total messages: " + n + ")");
- }
- }
- }
-
- public String toString() {
- return "Looper{"
- + Integer.toHexString(System.identityHashCode(this))
- + "}";
- }
-
- static class HandlerException extends Exception {
-
- HandlerException(Message message, Throwable cause) {
- super(createMessage(cause), cause);
- }
-
- static String createMessage(Throwable cause) {
- String causeMsg = cause.getMessage();
- if (causeMsg == null) {
- causeMsg = cause.toString();
- }
- return causeMsg;
- }
- }
-}
-
diff --git a/core/java/android/os/MailboxNotAvailableException.java b/core/java/android/os/MailboxNotAvailableException.java
deleted file mode 100644
index 574adbd..0000000
--- a/core/java/android/os/MailboxNotAvailableException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/** @hide */
-public class MailboxNotAvailableException extends Throwable
-{
- /**
- * This exception represents the case when a request for a
- * named, published mailbox fails because the requested name has not been published
- */
-
- public
- MailboxNotAvailableException()
- {
- }
-
- public
- MailboxNotAvailableException(String s)
- {
- super(s);
- }
-}
diff --git a/core/java/android/os/MemoryFile.java b/core/java/android/os/MemoryFile.java
deleted file mode 100644
index 76e4f47..0000000
--- a/core/java/android/os/MemoryFile.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-
-/**
- * MemoryFile is a wrapper for the Linux ashmem driver.
- * MemoryFiles are backed by shared memory, which can be optionally
- * set to be purgeable.
- * Purgeable files may have their contents reclaimed by the kernel
- * in low memory conditions (only if allowPurging is set to true).
- * After a file is purged, attempts to read or write the file will
- * cause an IOException to be thrown.
- */
-public class MemoryFile
-{
- private static String TAG = "MemoryFile";
-
- // returns fd
- private native int native_open(String name, int length);
- // returns memory address for ashmem region
- private native int native_mmap(int fd, int length);
- private native void native_close(int fd);
- private native int native_read(int fd, int address, byte[] buffer,
- int srcOffset, int destOffset, int count, boolean isUnpinned);
- private native void native_write(int fd, int address, byte[] buffer,
- int srcOffset, int destOffset, int count, boolean isUnpinned);
- private native void native_pin(int fd, boolean pin);
-
- private int mFD; // ashmem file descriptor
- private int mAddress; // address of ashmem memory
- private int mLength; // total length of our ashmem region
- private boolean mAllowPurging = false; // true if our ashmem region is unpinned
-
- /**
- * MemoryFile constructor.
- *
- * @param name optional name for the file (can be null).
- * @param length of the memory file in bytes.
- */
- public MemoryFile(String name, int length) {
- mLength = length;
- mFD = native_open(name, length);
- mAddress = native_mmap(mFD, length);
- }
-
- /**
- * Closes and releases all resources for the memory file.
- */
- public void close() {
- if (mFD > 0) {
- native_close(mFD);
- mFD = 0;
- }
- }
-
- @Override
- protected void finalize() {
- if (mFD > 0) {
- Log.e(TAG, "MemoryFile.finalize() called while ashmem still open");
- close();
- }
- }
-
- /**
- * Returns the length of the memory file.
- *
- * @return file length.
- */
- public int length() {
- return mLength;
- }
-
- /**
- * Is memory file purging enabled?
- *
- * @return true if the file may be purged.
- */
- public boolean isPurgingAllowed() {
- return mAllowPurging;
- }
-
- /**
- * Enables or disables purging of the memory file.
- *
- * @param allowPurging true if the operating system can purge the contents
- * of the file in low memory situations
- * @return previous value of allowPurging
- */
- synchronized public boolean allowPurging(boolean allowPurging) throws IOException {
- boolean oldValue = mAllowPurging;
- if (oldValue != allowPurging) {
- native_pin(mFD, !allowPurging);
- mAllowPurging = allowPurging;
- }
- return oldValue;
- }
-
- /**
- * Creates a new InputStream for reading from the memory file.
- *
- @return InputStream
- */
- public InputStream getInputStream() {
- return new MemoryInputStream();
- }
-
- /**
- * Creates a new OutputStream for writing to the memory file.
- *
- @return OutputStream
- */
- public OutputStream getOutputStream() {
-
- return new MemoryOutputStream();
- }
-
- /**
- * Reads bytes from the memory file.
- * Will throw an IOException if the file has been purged.
- *
- * @param buffer byte array to read bytes into.
- * @param srcOffset offset into the memory file to read from.
- * @param destOffset offset into the byte array buffer to read into.
- * @param count number of bytes to read.
- * @return number of bytes read.
- */
- public int readBytes(byte[] buffer, int srcOffset, int destOffset, int count)
- throws IOException {
- if (destOffset < 0 || destOffset > buffer.length || count < 0
- || count > buffer.length - destOffset
- || srcOffset < 0 || srcOffset > mLength
- || count > mLength - srcOffset) {
- throw new IndexOutOfBoundsException();
- }
- return native_read(mFD, mAddress, buffer, srcOffset, destOffset, count, mAllowPurging);
- }
-
- /**
- * Write bytes to the memory file.
- * Will throw an IOException if the file has been purged.
- *
- * @param buffer byte array to write bytes from.
- * @param srcOffset offset into the byte array buffer to write from.
- * @param destOffset offset into the memory file to write to.
- * @param count number of bytes to write.
- */
- public void writeBytes(byte[] buffer, int srcOffset, int destOffset, int count)
- throws IOException {
- if (srcOffset < 0 || srcOffset > buffer.length || count < 0
- || count > buffer.length - srcOffset
- || destOffset < 0 || destOffset > mLength
- || count > mLength - destOffset) {
- throw new IndexOutOfBoundsException();
- }
- native_write(mFD, mAddress, buffer, srcOffset, destOffset, count, mAllowPurging);
- }
-
- private class MemoryInputStream extends InputStream {
-
- private int mMark = 0;
- private int mOffset = 0;
- private byte[] mSingleByte;
-
- @Override
- public int available() throws IOException {
- if (mOffset >= mLength) {
- return 0;
- }
- return mLength - mOffset;
- }
-
- @Override
- public boolean markSupported() {
- return true;
- }
-
- @Override
- public void mark(int readlimit) {
- mMark = mOffset;
- }
-
- @Override
- public void reset() throws IOException {
- mOffset = mMark;
- }
-
- @Override
- public int read() throws IOException {
- if (mSingleByte == null) {
- mSingleByte = new byte[1];
- }
- int result = read(mSingleByte, 0, 1);
- if (result != 1) {
- throw new IOException("read() failed");
- }
- return mSingleByte[0];
- }
-
- @Override
- public int read(byte buffer[], int offset, int count) throws IOException {
- int result = readBytes(buffer, mOffset, offset, count);
- if (result > 0) {
- mOffset += result;
- }
- return result;
- }
-
- @Override
- public long skip(long n) throws IOException {
- if (mOffset + n > mLength) {
- n = mLength - mOffset;
- }
- mOffset += n;
- return n;
- }
- }
-
- private class MemoryOutputStream extends OutputStream {
-
- private int mOffset = 0;
- private byte[] mSingleByte;
-
- @Override
- public void write(byte buffer[], int offset, int count) throws IOException {
- writeBytes(buffer, offset, mOffset, count);
- }
-
- @Override
- public void write(int oneByte) throws IOException {
- if (mSingleByte == null) {
- mSingleByte = new byte[1];
- }
- mSingleByte[0] = (byte)oneByte;
- write(mSingleByte, 0, 1);
- }
- }
-}
diff --git a/core/java/android/os/Message.aidl b/core/java/android/os/Message.aidl
deleted file mode 100644
index e8dbb5a..0000000
--- a/core/java/android/os/Message.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/content/Intent.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.os;
-
-parcelable Message;
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
deleted file mode 100644
index 4130109..0000000
--- a/core/java/android/os/Message.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- *
- * Defines a message containing a description and arbitrary data object that can be
- * sent to a {@link Handler}. This object contains two extra int fields and an
- * extra object field that allow you to not do allocations in many cases.
- *
- * <p class="note">While the constructor of Message is public, the best way to get
- * one of these is to call {@link #obtain Message.obtain()} or one of the
- * {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull
- * them from a pool of recycled objects.</p>
- */
-public final class Message implements Parcelable {
- /**
- * User-defined message code so that the recipient can identify
- * what this message is about. Each {@link Handler} has its own name-space
- * for message codes, so you do not need to worry about yours conflicting
- * with other handlers.
- */
- public int what;
-
- // Use these fields instead of using the class's Bundle if you can.
- /** arg1 and arg2 are lower-cost alternatives to using {@link #setData(Bundle) setData()}
- if you only need to store a few integer values. */
- public int arg1;
-
- /** arg1 and arg2 are lower-cost alternatives to using {@link #setData(Bundle) setData()}
- if you only need to store a few integer values.*/
- public int arg2;
-
- /** An arbitrary object to send to the recipient. This must be null when
- * sending messages across processes. */
- public Object obj;
-
- /** Optional Messenger where replies to this message can be sent.
- */
- public Messenger replyTo;
-
- /*package*/ long when;
-
- /*package*/ Bundle data;
-
- /*package*/ Handler target;
-
- /*package*/ Runnable callback;
-
- // sometimes we store linked lists of these things
- /*package*/ Message next;
-
- private static Object mPoolSync = new Object();
- private static Message mPool;
- private static int mPoolSize = 0;
-
- private static final int MAX_POOL_SIZE = 10;
-
- /**
- * Return a new Message instance from the global pool. Allows us to
- * avoid allocating new objects in many cases.
- */
- public static Message obtain() {
- synchronized (mPoolSync) {
- if (mPool != null) {
- Message m = mPool;
- mPool = m.next;
- m.next = null;
- return m;
- }
- }
- return new Message();
- }
-
- /**
- * Same as {@link #obtain()}, but copies the values of an existing
- * message (including its target) into the new one.
- * @param orig Original message to copy.
- * @return A Message object from the global pool.
- */
- public static Message obtain(Message orig) {
- Message m = obtain();
- m.what = orig.what;
- m.arg1 = orig.arg1;
- m.arg2 = orig.arg2;
- m.obj = orig.obj;
- m.replyTo = orig.replyTo;
- if (orig.data != null) {
- m.data = new Bundle(orig.data);
- }
- m.target = orig.target;
- m.callback = orig.callback;
-
- return m;
- }
-
- /**
- * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned.
- * @param h Handler to assign to the returned Message object's <em>target</em> member.
- * @return A Message object from the global pool.
- */
- public static Message obtain(Handler h) {
- Message m = obtain();
- m.target = h;
-
- return m;
- }
-
- /**
- * Same as {@link #obtain(Handler)}, but assigns a callback Runnable on
- * the Message that is returned.
- * @param h Handler to assign to the returned Message object's <em>target</em> member.
- * @param callback Runnable that will execute when the message is handled.
- * @return A Message object from the global pool.
- */
- public static Message obtain(Handler h, Runnable callback) {
- Message m = obtain();
- m.target = h;
- m.callback = callback;
-
- return m;
- }
-
- /**
- * Same as {@link #obtain()}, but sets the values for both <em>target</em> and
- * <em>what</em> members on the Message.
- * @param h Value to assign to the <em>target</em> member.
- * @param what Value to assign to the <em>what</em> member.
- * @return A Message object from the global pool.
- */
- public static Message obtain(Handler h, int what) {
- Message m = obtain();
- m.target = h;
- m.what = what;
-
- return m;
- }
-
- /**
- * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em>
- * members.
- * @param h The <em>target</em> value to set.
- * @param what The <em>what</em> value to set.
- * @param obj The <em>object</em> method to set.
- * @return A Message object from the global pool.
- */
- public static Message obtain(Handler h, int what, Object obj) {
- Message m = obtain();
- m.target = h;
- m.what = what;
- m.obj = obj;
-
- return m;
- }
-
- /**
- * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
- * <em>arg1</em>, and <em>arg2</em> members.
- *
- * @param h The <em>target</em> value to set.
- * @param what The <em>what</em> value to set.
- * @param arg1 The <em>arg1</em> value to set.
- * @param arg2 The <em>arg2</em> value to set.
- * @return A Message object from the global pool.
- */
- public static Message obtain(Handler h, int what, int arg1, int arg2) {
- Message m = obtain();
- m.target = h;
- m.what = what;
- m.arg1 = arg1;
- m.arg2 = arg2;
-
- return m;
- }
-
- /**
- * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
- * <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members.
- *
- * @param h The <em>target</em> value to set.
- * @param what The <em>what</em> value to set.
- * @param arg1 The <em>arg1</em> value to set.
- * @param arg2 The <em>arg2</em> value to set.
- * @param obj The <em>obj</em> value to set.
- * @return A Message object from the global pool.
- */
- public static Message obtain(Handler h, int what,
- int arg1, int arg2, Object obj) {
- Message m = obtain();
- m.target = h;
- m.what = what;
- m.arg1 = arg1;
- m.arg2 = arg2;
- m.obj = obj;
-
- return m;
- }
-
- /**
- * Return a Message instance to the global pool. You MUST NOT touch
- * the Message after calling this function -- it has effectively been
- * freed.
- */
- public void recycle() {
- synchronized (mPoolSync) {
- if (mPoolSize < MAX_POOL_SIZE) {
- clearForRecycle();
-
- next = mPool;
- mPool = this;
- }
- }
- }
-
- /**
- * Make this message like o. Performs a shallow copy of the data field.
- * Does not copy the linked list fields, nor the timestamp or
- * target/callback of the original message.
- */
- public void copyFrom(Message o) {
- this.what = o.what;
- this.arg1 = o.arg1;
- this.arg2 = o.arg2;
- this.obj = o.obj;
- this.replyTo = o.replyTo;
-
- if (o.data != null) {
- this.data = (Bundle) o.data.clone();
- } else {
- this.data = null;
- }
- }
-
- /**
- * Return the targeted delivery time of this message, in milliseconds.
- */
- public long getWhen() {
- return when;
- }
-
- public void setTarget(Handler target) {
- this.target = target;
- }
-
- /**
- * Retrieve the a {@link android.os.Handler Handler} implementation that
- * will receive this message. The object must implement
- * {@link android.os.Handler#handleMessage(android.os.Message)
- * Handler.handleMessage()}. Each Handler has its own name-space for
- * message codes, so you do not need to
- * worry about yours conflicting with other handlers.
- */
- public Handler getTarget() {
- return target;
- }
-
- /**
- * Retrieve callback object that will execute when this message is handled.
- * This object must implement Runnable. This is called by
- * the <em>target</em> {@link Handler} that is receiving this Message to
- * dispatch it. If
- * not set, the message will be dispatched to the receiving Handler's
- * {@link Handler#handleMessage(Message Handler.handleMessage())}. */
- public Runnable getCallback() {
- return callback;
- }
-
- /**
- * Obtains a Bundle of arbitrary data associated with this
- * event, lazily creating it if necessary. Set this value by calling {@link #setData(Bundle)}.
- */
- public Bundle getData() {
- if (data == null) {
- data = new Bundle();
- }
-
- return data;
- }
-
- /**
- * Like getData(), but does not lazily create the Bundle. A null
- * is returned if the Bundle does not already exist.
- */
- public Bundle peekData() {
- return data;
- }
-
- /** Sets a Bundle of arbitrary data values. Use arg1 and arg1 members
- * as a lower cost way to send a few simple integer values, if you can. */
- public void setData(Bundle data) {
- this.data = data;
- }
-
- /**
- * Sends this Message to the Handler specified by {@link #getTarget}.
- * Throws a null pointer exception if this field has not been set.
- */
- public void sendToTarget() {
- target.sendMessage(this);
- }
-
- /*package*/ void clearForRecycle() {
- what = 0;
- arg1 = 0;
- arg2 = 0;
- obj = null;
- replyTo = null;
- when = 0;
- target = null;
- callback = null;
- data = null;
- }
-
- /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
- */
- public Message() {
- }
-
- public String toString() {
- StringBuilder b = new StringBuilder();
-
- b.append("{ what=");
- b.append(what);
-
- b.append(" when=");
- b.append(when);
-
- if (arg1 != 0) {
- b.append(" arg1=");
- b.append(arg1);
- }
-
- if (arg2 != 0) {
- b.append(" arg2=");
- b.append(arg2);
- }
-
- if (obj != null) {
- b.append(" obj=");
- b.append(obj);
- }
-
- b.append(" }");
-
- return b.toString();
- }
-
- public static final Parcelable.Creator<Message> CREATOR
- = new Parcelable.Creator<Message>() {
- public Message createFromParcel(Parcel source) {
- Message msg = Message.obtain();
- msg.readFromParcel(source);
- return msg;
- }
-
- public Message[] newArray(int size) {
- return new Message[size];
- }
- };
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- if (obj != null || callback != null) {
- throw new RuntimeException(
- "Can't marshal objects across processes.");
- }
- dest.writeInt(what);
- dest.writeInt(arg1);
- dest.writeInt(arg2);
- dest.writeLong(when);
- dest.writeBundle(data);
- Messenger.writeMessengerOrNullToParcel(replyTo, dest);
- }
-
- private final void readFromParcel(Parcel source) {
- what = source.readInt();
- arg1 = source.readInt();
- arg2 = source.readInt();
- when = source.readLong();
- data = source.readBundle();
- replyTo = Messenger.readMessengerOrNullFromParcel(source);
- }
-}
-
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
deleted file mode 100644
index caf0923..0000000
--- a/core/java/android/os/MessageQueue.java
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import java.util.ArrayList;
-
-import android.util.AndroidRuntimeException;
-import android.util.Config;
-import android.util.Log;
-
-import com.android.internal.os.RuntimeInit;
-
-/**
- * Low-level class holding the list of messages to be dispatched by a
- * {@link Looper}. Messages are not added directly to a MessageQueue,
- * but rather through {@link Handler} objects associated with the Looper.
- *
- * <p>You can retrieve the MessageQueue for the current thread with
- * {@link Looper#myQueue() Looper.myQueue()}.
- */
-public class MessageQueue {
- Message mMessages;
- private final ArrayList mIdleHandlers = new ArrayList();
- private boolean mQuiting = false;
- boolean mQuitAllowed = true;
-
- /**
- * Callback interface for discovering when a thread is going to block
- * waiting for more messages.
- */
- public static interface IdleHandler {
- /**
- * Called when the message queue has run out of messages and will now
- * wait for more. Return true to keep your idle handler active, false
- * to have it removed. This may be called if there are still messages
- * pending in the queue, but they are all scheduled to be dispatched
- * after the current time.
- */
- boolean queueIdle();
- }
-
- /**
- * Add a new {@link IdleHandler} to this message queue. This may be
- * removed automatically for you by returning false from
- * {@link IdleHandler#queueIdle IdleHandler.queueIdle()} when it is
- * invoked, or explicitly removing it with {@link #removeIdleHandler}.
- *
- * <p>This method is safe to call from any thread.
- *
- * @param handler The IdleHandler to be added.
- */
- public final void addIdleHandler(IdleHandler handler) {
- if (handler == null) {
- throw new NullPointerException("Can't add a null IdleHandler");
- }
- synchronized (this) {
- mIdleHandlers.add(handler);
- }
- }
-
- /**
- * Remove an {@link IdleHandler} from the queue that was previously added
- * with {@link #addIdleHandler}. If the given object is not currently
- * in the idle list, nothing is done.
- *
- * @param handler The IdleHandler to be removed.
- */
- public final void removeIdleHandler(IdleHandler handler) {
- synchronized (this) {
- mIdleHandlers.remove(handler);
- }
- }
-
- MessageQueue() {
- }
-
- final Message next() {
- boolean tryIdle = true;
-
- while (true) {
- long now;
- Object[] idlers = null;
-
- // Try to retrieve the next message, returning if found.
- synchronized (this) {
- now = SystemClock.uptimeMillis();
- Message msg = pullNextLocked(now);
- if (msg != null) return msg;
- if (tryIdle && mIdleHandlers.size() > 0) {
- idlers = mIdleHandlers.toArray();
- }
- }
-
- // There was no message so we are going to wait... but first,
- // if there are any idle handlers let them know.
- boolean didIdle = false;
- if (idlers != null) {
- for (Object idler : idlers) {
- boolean keep = false;
- try {
- didIdle = true;
- keep = ((IdleHandler)idler).queueIdle();
- } catch (Throwable t) {
- Log.e("MessageQueue",
- "IdleHandler threw exception", t);
- RuntimeInit.crash("MessageQueue", t);
- }
-
- if (!keep) {
- synchronized (this) {
- mIdleHandlers.remove(idler);
- }
- }
- }
- }
-
- // While calling an idle handler, a new message could have been
- // delivered... so go back and look again for a pending message.
- if (didIdle) {
- tryIdle = false;
- continue;
- }
-
- synchronized (this) {
- // No messages, nobody to tell about it... time to wait!
- try {
- if (mMessages != null) {
- if (mMessages.when-now > 0) {
- Binder.flushPendingCommands();
- this.wait(mMessages.when-now);
- }
- } else {
- Binder.flushPendingCommands();
- this.wait();
- }
- }
- catch (InterruptedException e) {
- }
- }
- }
- }
-
- final Message pullNextLocked(long now) {
- Message msg = mMessages;
- if (msg != null) {
- if (now >= msg.when) {
- mMessages = msg.next;
- if (Config.LOGV) Log.v(
- "MessageQueue", "Returning message: " + msg);
- return msg;
- }
- }
-
- return null;
- }
-
- final boolean enqueueMessage(Message msg, long when) {
- if (msg.when != 0) {
- throw new AndroidRuntimeException(msg
- + " This message is already in use.");
- }
- if (msg.target == null && !mQuitAllowed) {
- throw new RuntimeException("Main thread not allowed to quit");
- }
- synchronized (this) {
- if (mQuiting) {
- RuntimeException e = new RuntimeException(
- msg.target + " sending message to a Handler on a dead thread");
- Log.w("MessageQueue", e.getMessage(), e);
- return false;
- } else if (msg.target == null) {
- mQuiting = true;
- }
-
- msg.when = when;
- //Log.d("MessageQueue", "Enqueing: " + msg);
- Message p = mMessages;
- if (p == null || when == 0 || when < p.when) {
- msg.next = p;
- mMessages = msg;
- this.notify();
- } else {
- Message prev = null;
- while (p != null && p.when <= when) {
- prev = p;
- p = p.next;
- }
- msg.next = prev.next;
- prev.next = msg;
- this.notify();
- }
- }
- return true;
- }
-
- final boolean removeMessages(Handler h, int what, Object object,
- boolean doRemove) {
- synchronized (this) {
- Message p = mMessages;
- boolean found = false;
-
- // Remove all messages at front.
- while (p != null && p.target == h && p.what == what
- && (object == null || p.obj == object)) {
- if (!doRemove) return true;
- found = true;
- Message n = p.next;
- mMessages = n;
- p.recycle();
- p = n;
- }
-
- // Remove all messages after front.
- while (p != null) {
- Message n = p.next;
- if (n != null) {
- if (n.target == h && n.what == what
- && (object == null || n.obj == object)) {
- if (!doRemove) return true;
- found = true;
- Message nn = n.next;
- n.recycle();
- p.next = nn;
- continue;
- }
- }
- p = n;
- }
-
- return found;
- }
- }
-
- final void removeMessages(Handler h, Runnable r, Object object) {
- if (r == null) {
- return;
- }
-
- synchronized (this) {
- Message p = mMessages;
-
- // Remove all messages at front.
- while (p != null && p.target == h && p.callback == r
- && (object == null || p.obj == object)) {
- Message n = p.next;
- mMessages = n;
- p.recycle();
- p = n;
- }
-
- // Remove all messages after front.
- while (p != null) {
- Message n = p.next;
- if (n != null) {
- if (n.target == h && n.callback == r
- && (object == null || n.obj == object)) {
- Message nn = n.next;
- n.recycle();
- p.next = nn;
- continue;
- }
- }
- p = n;
- }
- }
- }
-
- final void removeCallbacksAndMessages(Handler h, Object object) {
- synchronized (this) {
- Message p = mMessages;
-
- // Remove all messages at front.
- while (p != null && p.target == h
- && (object == null || p.obj == object)) {
- Message n = p.next;
- mMessages = n;
- p.recycle();
- p = n;
- }
-
- // Remove all messages after front.
- while (p != null) {
- Message n = p.next;
- if (n != null) {
- if (n.target == h && (object == null || n.obj == object)) {
- Message nn = n.next;
- n.recycle();
- p.next = nn;
- continue;
- }
- }
- p = n;
- }
- }
- }
-
- /*
- private void dumpQueue_l()
- {
- Message p = mMessages;
- System.out.println(this + " queue is:");
- while (p != null) {
- System.out.println(" " + p);
- p = p.next;
- }
- }
- */
-
- void poke()
- {
- synchronized (this) {
- this.notify();
- }
- }
-}
diff --git a/core/java/android/os/Messenger.aidl b/core/java/android/os/Messenger.aidl
deleted file mode 100644
index e6b8886..0000000
--- a/core/java/android/os/Messenger.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/content/Intent.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.os;
-
-parcelable Messenger;
diff --git a/core/java/android/os/Messenger.java b/core/java/android/os/Messenger.java
deleted file mode 100644
index 1bc554e..0000000
--- a/core/java/android/os/Messenger.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * Reference to a Handler, which others can use to send messages to it.
- * This allows for the implementation of message-based communication across
- * processes, by creating a Messenger pointing to a Handler in one process,
- * and handing that Messenger to another process.
- */
-public final class Messenger implements Parcelable {
- private final IMessenger mTarget;
-
- /**
- * Create a new Messenger pointing to the given Handler. Any Message
- * objects sent through this Messenger will appear in the Handler as if
- * {@link Handler#sendMessage(Message) Handler.sendMessage(Message)} had
- * be called directly.
- *
- * @param target The Handler that will receive sent messages.
- */
- public Messenger(Handler target) {
- mTarget = target.getIMessenger();
- }
-
- /**
- * Send a Message to this Messenger's Handler.
- *
- * @param message The Message to send. Usually retrieved through
- * {@link Message#obtain() Message.obtain()}.
- *
- * @throws RemoteException Throws DeadObjectException if the target
- * Handler no longer exists.
- */
- public void send(Message message) throws RemoteException {
- mTarget.send(message);
- }
-
- /**
- * Retrieve the IBinder that this Messenger is using to communicate with
- * its associated Handler.
- *
- * @return Returns the IBinder backing this Messenger.
- */
- public IBinder getBinder() {
- return mTarget.asBinder();
- }
-
- /**
- * Comparison operator on two Messenger objects, such that true
- * is returned then they both point to the same Handler.
- */
- public boolean equals(Object otherObj) {
- if (otherObj == null) {
- return false;
- }
- try {
- return mTarget.asBinder().equals(((Messenger)otherObj)
- .mTarget.asBinder());
- } catch (ClassCastException e) {
- }
- return false;
- }
-
- public int hashCode() {
- return mTarget.asBinder().hashCode();
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeStrongBinder(mTarget.asBinder());
- }
-
- public static final Parcelable.Creator<Messenger> CREATOR
- = new Parcelable.Creator<Messenger>() {
- public Messenger createFromParcel(Parcel in) {
- IBinder target = in.readStrongBinder();
- return target != null ? new Messenger(target) : null;
- }
-
- public Messenger[] newArray(int size) {
- return new Messenger[size];
- }
- };
-
- /**
- * Convenience function for writing either a Messenger or null pointer to
- * a Parcel. You must use this with {@link #readMessengerOrNullFromParcel}
- * for later reading it.
- *
- * @param messenger The Messenger to write, or null.
- * @param out Where to write the Messenger.
- */
- public static void writeMessengerOrNullToParcel(Messenger messenger,
- Parcel out) {
- out.writeStrongBinder(messenger != null ? messenger.mTarget.asBinder()
- : null);
- }
-
- /**
- * Convenience function for reading either a Messenger or null pointer from
- * a Parcel. You must have previously written the Messenger with
- * {@link #writeMessengerOrNullToParcel}.
- *
- * @param in The Parcel containing the written Messenger.
- *
- * @return Returns the Messenger read from the Parcel, or null if null had
- * been written.
- */
- public static Messenger readMessengerOrNullFromParcel(Parcel in) {
- IBinder b = in.readStrongBinder();
- return b != null ? new Messenger(b) : null;
- }
-
- /**
- * Create a Messenger from a raw IBinder, which had previously been
- * retrieved with {@link #getBinder}.
- *
- * @param target The IBinder this Messenger should communicate with.
- */
- public Messenger(IBinder target) {
- mTarget = IMessenger.Stub.asInterface(target);
- }
-}
diff --git a/core/java/android/os/NetStat.java b/core/java/android/os/NetStat.java
deleted file mode 100644
index 733137a..0000000
--- a/core/java/android/os/NetStat.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.util.Log;
-
-import java.io.File;
-import java.io.RandomAccessFile;
-import java.io.IOException;
-
-/** @hide */
-public class NetStat{
-
- /**
- * Get total number of tx packets sent through rmnet0 or ppp0
- *
- * @return number of Tx packets through rmnet0 or ppp0
- */
- public static long getMobileTxPkts() {
- return getMobileStat("tx_packets");
- }
-
- /**
- * Get total number of rx packets received through rmnet0 or ppp0
- *
- * @return number of Rx packets through rmnet0 or ppp0
- */
- public static long getMobileRxPkts() {
- return getMobileStat("rx_packets");
- }
-
- /**
- * Get total number of tx bytes received through rmnet0 or ppp0
- *
- * @return number of Tx bytes through rmnet0 or ppp0
- */
- public static long getMobileTxBytes() {
- return getMobileStat("tx_bytes");
- }
-
- /**
- * Get total number of rx bytes received through rmnet0 or ppp0
- *
- * @return number of Rx bytes through rmnet0 or ppp0
- */
- public static long getMobileRxBytes() {
- return getMobileStat("rx_bytes");
- }
-
- /**
- * Get the total number of packets sent through all network interfaces.
- *
- * @return the number of packets sent through all network interfaces
- */
- public static long getTotalTxPkts() {
- return getTotalStat("tx_packets");
- }
-
- /**
- * Get the total number of packets received through all network interfaces.
- *
- * @return the number of packets received through all network interfaces
- */
- public static long getTotalRxPkts() {
- return getTotalStat("rx_packets");
- }
-
- /**
- * Get the total number of bytes sent through all network interfaces.
- *
- * @return the number of bytes sent through all network interfaces
- */
- public static long getTotalTxBytes() {
- return getTotalStat("tx_bytes");
- }
-
- /**
- * Get the total number of bytes received through all network interfaces.
- *
- * @return the number of bytes received through all network interfaces
- */
- public static long getTotalRxBytes() {
- return getTotalStat("rx_bytes");
- }
-
- /**
- * Gets network bytes sent for this UID.
- * The statistics are across all interfaces.
- * The statistics come from /proc/uid_stat.
- *
- * {@see android.os.Process#myUid()}.
- *
- * @param uid
- * @return byte count
- */
- public static long getUidTxBytes(int uid) {
- return getNumberFromFilePath("/proc/uid_stat/" + uid + "/tcp_snd");
- }
-
- /**
- * Gets network bytes received for this UID.
- * The statistics are across all interfaces.
- * The statistics come from /proc/uid_stat.
- *
- * {@see android.os.Process#myUid()}.
- *
- * @param uid
- * @return byte count
- */
- public static long getUidRxBytes(int uid) {
- return getNumberFromFilePath("/proc/uid_stat/" + uid + "/tcp_rcv");
- }
-
- private static String TAG = "netstat";
- private static final byte[] buf = new byte[16];
-
- private static long getTotalStat(String whatStat) {
- File netdir = new File("/sys/class/net");
-
- File[] nets = netdir.listFiles();
- if (nets == null) {
- return 0;
- }
- long total = 0;
- StringBuffer strbuf = new StringBuffer();
- for (File net : nets) {
- strbuf.append(net.getPath()).append(File.separator).append("statistics")
- .append(File.separator).append(whatStat);
- total += getNumberFromFilePath(strbuf.toString());
- strbuf.setLength(0);
- }
- return total;
- }
-
- private static long getMobileStat(String whatStat) {
- String filename = "/sys/class/net/rmnet0/statistics/" + whatStat;
- RandomAccessFile raf = getFile(filename);
- if (raf == null) {
- filename = "/sys/class/net/ppp0/statistics/" + whatStat;
- raf = getFile(filename);
- }
- if (raf == null) {
- return 0L;
- }
- return getNumberFromFile(raf, filename);
- }
-
- // File will have format <number><newline>
- private static long getNumberFromFilePath(String filename) {
- RandomAccessFile raf = getFile(filename);
- if (raf == null) {
- return 0L;
- }
- return getNumberFromFile(raf, filename);
- }
-
- private static synchronized long getNumberFromFile(RandomAccessFile raf, String filename) {
- try {
- raf.read(buf);
- raf.close();
- } catch (IOException e) {
- Log.w(TAG, "Exception getting TCP bytes from " + filename, e);
- return 0L;
- } finally {
- if (raf != null) {
- try {
- raf.close();
- } catch (IOException e) {
- Log.w(TAG, "Exception closing " + filename, e);
- }
- }
- }
-
- long num = 0L;
- for (int i = 0; i < buf.length; i++) {
- if (buf[i] < '0' || buf[i] > '9') {
- break;
- }
- num *= 10;
- num += buf[i] - '0';
- }
- return num;
- }
-
- private static RandomAccessFile getFile(String filename) {
- File f = new File(filename);
- if (!f.canRead()) {
- return null;
- }
-
- try {
- return new RandomAccessFile(f, "r");
- } catch (IOException e) {
- Log.w(TAG, "Exception opening TCP statistics file " + filename, e);
- return null;
- }
- }
-}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
deleted file mode 100644
index 9a71f6e..0000000
--- a/core/java/android/os/Parcel.java
+++ /dev/null
@@ -1,2051 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.SparseArray;
-import android.util.SparseBooleanArray;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.FileDescriptor;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Container for a message (data and object references) that can
- * be sent through an IBinder. A Parcel can contain both flattened data
- * that will be unflattened on the other side of the IPC (using the various
- * methods here for writing specific types, or the general
- * {@link Parcelable} interface), and references to live {@link IBinder}
- * objects that will result in the other side receiving a proxy IBinder
- * connected with the original IBinder in the Parcel.
- *
- * <p class="note">Parcel is <strong>not</strong> a general-purpose
- * serialization mechanism. This class (and the corresponding
- * {@link Parcelable} API for placing arbitrary objects into a Parcel) is
- * designed as a high-performance IPC transport. As such, it is not
- * appropriate to place any Parcel data in to persistent storage: changes
- * in the underlying implementation of any of the data in the Parcel can
- * render older data unreadable.</p>
- *
- * <p>The bulk of the Parcel API revolves around reading and writing data
- * of various types. There are six major classes of such functions available.</p>
- *
- * <h3>Primitives</h3>
- *
- * <p>The most basic data functions are for writing and reading primitive
- * data types: {@link #writeByte}, {@link #readByte}, {@link #writeDouble},
- * {@link #readDouble}, {@link #writeFloat}, {@link #readFloat}, {@link #writeInt},
- * {@link #readInt}, {@link #writeLong}, {@link #readLong},
- * {@link #writeString}, {@link #readString}. Most other
- * data operations are built on top of these. The given data is written and
- * read using the endianess of the host CPU.</p>
- *
- * <h3>Primitive Arrays</h3>
- *
- * <p>There are a variety of methods for reading and writing raw arrays
- * of primitive objects, which generally result in writing a 4-byte length
- * followed by the primitive data items. The methods for reading can either
- * read the data into an existing array, or create and return a new array.
- * These available types are:</p>
- *
- * <ul>
- * <li> {@link #writeBooleanArray(boolean[])},
- * {@link #readBooleanArray(boolean[])}, {@link #createBooleanArray()}
- * <li> {@link #writeByteArray(byte[])},
- * {@link #writeByteArray(byte[], int, int)}, {@link #readByteArray(byte[])},
- * {@link #createByteArray()}
- * <li> {@link #writeCharArray(char[])}, {@link #readCharArray(char[])},
- * {@link #createCharArray()}
- * <li> {@link #writeDoubleArray(double[])}, {@link #readDoubleArray(double[])},
- * {@link #createDoubleArray()}
- * <li> {@link #writeFloatArray(float[])}, {@link #readFloatArray(float[])},
- * {@link #createFloatArray()}
- * <li> {@link #writeIntArray(int[])}, {@link #readIntArray(int[])},
- * {@link #createIntArray()}
- * <li> {@link #writeLongArray(long[])}, {@link #readLongArray(long[])},
- * {@link #createLongArray()}
- * <li> {@link #writeStringArray(String[])}, {@link #readStringArray(String[])},
- * {@link #createStringArray()}.
- * <li> {@link #writeSparseBooleanArray(SparseBooleanArray)},
- * {@link #readSparseBooleanArray()}.
- * </ul>
- *
- * <h3>Parcelables</h3>
- *
- * <p>The {@link Parcelable} protocol provides an extremely efficient (but
- * low-level) protocol for objects to write and read themselves from Parcels.
- * You can use the direct methods {@link #writeParcelable(Parcelable, int)}
- * and {@link #readParcelable(ClassLoader)} or
- * {@link #writeParcelableArray} and
- * {@link #readParcelableArray(ClassLoader)} to write or read. These
- * methods write both the class type and its data to the Parcel, allowing
- * that class to be reconstructed from the appropriate class loader when
- * later reading.</p>
- *
- * <p>There are also some methods that provide a more efficient way to work
- * with Parcelables: {@link #writeTypedArray},
- * {@link #writeTypedList(List)},
- * {@link #readTypedArray} and {@link #readTypedList}. These methods
- * do not write the class information of the original object: instead, the
- * caller of the read function must know what type to expect and pass in the
- * appropriate {@link Parcelable.Creator Parcelable.Creator} instead to
- * properly construct the new object and read its data. (To more efficient
- * write and read a single Parceable object, you can directly call
- * {@link Parcelable#writeToParcel Parcelable.writeToParcel} and
- * {@link Parcelable.Creator#createFromParcel Parcelable.Creator.createFromParcel}
- * yourself.)</p>
- *
- * <h3>Bundles</h3>
- *
- * <p>A special type-safe container, called {@link Bundle}, is available
- * for key/value maps of heterogeneous values. This has many optimizations
- * for improved performance when reading and writing data, and its type-safe
- * API avoids difficult to debug type errors when finally marshalling the
- * data contents into a Parcel. The methods to use are
- * {@link #writeBundle(Bundle)}, {@link #readBundle()}, and
- * {@link #readBundle(ClassLoader)}.
- *
- * <h3>Active Objects</h3>
- *
- * <p>An unusual feature of Parcel is the ability to read and write active
- * objects. For these objects the actual contents of the object is not
- * written, rather a special token referencing the object is written. When
- * reading the object back from the Parcel, you do not get a new instance of
- * the object, but rather a handle that operates on the exact same object that
- * was originally written. There are two forms of active objects available.</p>
- *
- * <p>{@link Binder} objects are a core facility of Android's general cross-process
- * communication system. The {@link IBinder} interface describes an abstract
- * protocol with a Binder object. Any such interface can be written in to
- * a Parcel, and upon reading you will receive either the original object
- * implementing that interface or a special proxy implementation
- * that communicates calls back to the original object. The methods to use are
- * {@link #writeStrongBinder(IBinder)},
- * {@link #writeStrongInterface(IInterface)}, {@link #readStrongBinder()},
- * {@link #writeBinderArray(IBinder[])}, {@link #readBinderArray(IBinder[])},
- * {@link #createBinderArray()},
- * {@link #writeBinderList(List)}, {@link #readBinderList(List)},
- * {@link #createBinderArrayList()}.</p>
- *
- * <p>FileDescriptor objects, representing raw Linux file descriptor identifiers,
- * can be written and {@link ParcelFileDescriptor} objects returned to operate
- * on the original file descriptor. The returned file descriptor is a dup
- * of the original file descriptor: the object and fd is different, but
- * operating on the same underlying file stream, with the same position, etc.
- * The methods to use are {@link #writeFileDescriptor(FileDescriptor)},
- * {@link #readFileDescriptor()}.
- *
- * <h3>Untyped Containers</h3>
- *
- * <p>A final class of methods are for writing and reading standard Java
- * containers of arbitrary types. These all revolve around the
- * {@link #writeValue(Object)} and {@link #readValue(ClassLoader)} methods
- * which define the types of objects allowed. The container methods are
- * {@link #writeArray(Object[])}, {@link #readArray(ClassLoader)},
- * {@link #writeList(List)}, {@link #readList(List, ClassLoader)},
- * {@link #readArrayList(ClassLoader)},
- * {@link #writeMap(Map)}, {@link #readMap(Map, ClassLoader)},
- * {@link #writeSparseArray(SparseArray)},
- * {@link #readSparseArray(ClassLoader)}.
- */
-public final class Parcel {
- private static final boolean DEBUG_RECYCLE = false;
-
- @SuppressWarnings({"UnusedDeclaration"})
- private int mObject; // used by native code
- @SuppressWarnings({"UnusedDeclaration"})
- private int mOwnObject; // used by native code
- private RuntimeException mStack;
-
- private static final int POOL_SIZE = 6;
- private static final Parcel[] sOwnedPool = new Parcel[POOL_SIZE];
- private static final Parcel[] sHolderPool = new Parcel[POOL_SIZE];
-
- private static final int VAL_NULL = -1;
- private static final int VAL_STRING = 0;
- private static final int VAL_INTEGER = 1;
- private static final int VAL_MAP = 2;
- private static final int VAL_BUNDLE = 3;
- private static final int VAL_PARCELABLE = 4;
- private static final int VAL_SHORT = 5;
- private static final int VAL_LONG = 6;
- private static final int VAL_FLOAT = 7;
- private static final int VAL_DOUBLE = 8;
- private static final int VAL_BOOLEAN = 9;
- private static final int VAL_CHARSEQUENCE = 10;
- private static final int VAL_LIST = 11;
- private static final int VAL_SPARSEARRAY = 12;
- private static final int VAL_BYTEARRAY = 13;
- private static final int VAL_STRINGARRAY = 14;
- private static final int VAL_IBINDER = 15;
- private static final int VAL_PARCELABLEARRAY = 16;
- private static final int VAL_OBJECTARRAY = 17;
- private static final int VAL_INTARRAY = 18;
- private static final int VAL_LONGARRAY = 19;
- private static final int VAL_BYTE = 20;
- private static final int VAL_SERIALIZABLE = 21;
- private static final int VAL_SPARSEBOOLEANARRAY = 22;
- private static final int VAL_BOOLEANARRAY = 23;
-
- private static final int EX_SECURITY = -1;
- private static final int EX_BAD_PARCELABLE = -2;
- private static final int EX_ILLEGAL_ARGUMENT = -3;
- private static final int EX_NULL_POINTER = -4;
- private static final int EX_ILLEGAL_STATE = -5;
-
- public final static Parcelable.Creator<String> STRING_CREATOR
- = new Parcelable.Creator<String>() {
- public String createFromParcel(Parcel source) {
- return source.readString();
- }
- public String[] newArray(int size) {
- return new String[size];
- }
- };
-
- /**
- * Retrieve a new Parcel object from the pool.
- */
- public static Parcel obtain() {
- final Parcel[] pool = sOwnedPool;
- synchronized (pool) {
- Parcel p;
- for (int i=0; i<POOL_SIZE; i++) {
- p = pool[i];
- if (p != null) {
- pool[i] = null;
- if (DEBUG_RECYCLE) {
- p.mStack = new RuntimeException();
- }
- return p;
- }
- }
- }
- return new Parcel(0);
- }
-
- /**
- * Put a Parcel object back into the pool. You must not touch
- * the object after this call.
- */
- public final void recycle() {
- if (DEBUG_RECYCLE) mStack = null;
- freeBuffer();
- final Parcel[] pool = mOwnObject != 0 ? sOwnedPool : sHolderPool;
- synchronized (pool) {
- for (int i=0; i<POOL_SIZE; i++) {
- if (pool[i] == null) {
- pool[i] = this;
- return;
- }
- }
- }
- }
-
- /**
- * Returns the total amount of data contained in the parcel.
- */
- public final native int dataSize();
-
- /**
- * Returns the amount of data remaining to be read from the
- * parcel. That is, {@link #dataSize}-{@link #dataPosition}.
- */
- public final native int dataAvail();
-
- /**
- * Returns the current position in the parcel data. Never
- * more than {@link #dataSize}.
- */
- public final native int dataPosition();
-
- /**
- * Returns the total amount of space in the parcel. This is always
- * >= {@link #dataSize}. The difference between it and dataSize() is the
- * amount of room left until the parcel needs to re-allocate its
- * data buffer.
- */
- public final native int dataCapacity();
-
- /**
- * Change the amount of data in the parcel. Can be either smaller or
- * larger than the current size. If larger than the current capacity,
- * more memory will be allocated.
- *
- * @param size The new number of bytes in the Parcel.
- */
- public final native void setDataSize(int size);
-
- /**
- * Move the current read/write position in the parcel.
- * @param pos New offset in the parcel; must be between 0 and
- * {@link #dataSize}.
- */
- public final native void setDataPosition(int pos);
-
- /**
- * Change the capacity (current available space) of the parcel.
- *
- * @param size The new capacity of the parcel, in bytes. Can not be
- * less than {@link #dataSize} -- that is, you can not drop existing data
- * with this method.
- */
- public final native void setDataCapacity(int size);
-
- /**
- * Returns the raw bytes of the parcel.
- *
- * <p class="note">The data you retrieve here <strong>must not</strong>
- * be placed in any kind of persistent storage (on local disk, across
- * a network, etc). For that, you should use standard serialization
- * or another kind of general serialization mechanism. The Parcel
- * marshalled representation is highly optimized for local IPC, and as
- * such does not attempt to maintain compatibility with data created
- * in different versions of the platform.
- */
- public final native byte[] marshall();
-
- /**
- * Set the bytes in data to be the raw bytes of this Parcel.
- */
- public final native void unmarshall(byte[] data, int offest, int length);
-
- public final native void appendFrom(Parcel parcel, int offset, int length);
-
- /**
- * Report whether the parcel contains any marshalled file descriptors.
- */
- public final native boolean hasFileDescriptors();
-
- /**
- * Store or read an IBinder interface token in the parcel at the current
- * {@link #dataPosition}. This is used to validate that the marshalled
- * transaction is intended for the target interface.
- */
- public final native void writeInterfaceToken(String interfaceName);
- public final native void enforceInterface(String interfaceName);
-
- /**
- * Write a byte array into the parcel at the current {#link #dataPosition},
- * growing {@link #dataCapacity} if needed.
- * @param b Bytes to place into the parcel.
- */
- public final void writeByteArray(byte[] b) {
- writeByteArray(b, 0, (b != null) ? b.length : 0);
- }
-
- /**
- * Write an byte array into the parcel at the current {#link #dataPosition},
- * growing {@link #dataCapacity} if needed.
- * @param b Bytes to place into the parcel.
- * @param offset Index of first byte to be written.
- * @param len Number of bytes to write.
- */
- public final void writeByteArray(byte[] b, int offset, int len) {
- if (b == null) {
- writeInt(-1);
- return;
- }
- if (b.length < offset + len || len < 0 || offset < 0) {
- throw new ArrayIndexOutOfBoundsException();
- }
- writeNative(b, offset, len);
- }
-
- private native void writeNative(byte[] b, int offset, int len);
-
- /**
- * Write an integer value into the parcel at the current dataPosition(),
- * growing dataCapacity() if needed.
- */
- public final native void writeInt(int val);
-
- /**
- * Write a long integer value into the parcel at the current dataPosition(),
- * growing dataCapacity() if needed.
- */
- public final native void writeLong(long val);
-
- /**
- * Write a floating point value into the parcel at the current
- * dataPosition(), growing dataCapacity() if needed.
- */
- public final native void writeFloat(float val);
-
- /**
- * Write a double precision floating point value into the parcel at the
- * current dataPosition(), growing dataCapacity() if needed.
- */
- public final native void writeDouble(double val);
-
- /**
- * Write a string value into the parcel at the current dataPosition(),
- * growing dataCapacity() if needed.
- */
- public final native void writeString(String val);
-
- /**
- * Write an object into the parcel at the current dataPosition(),
- * growing dataCapacity() if needed.
- */
- public final native void writeStrongBinder(IBinder val);
-
- /**
- * Write an object into the parcel at the current dataPosition(),
- * growing dataCapacity() if needed.
- */
- public final void writeStrongInterface(IInterface val) {
- writeStrongBinder(val == null ? null : val.asBinder());
- }
-
- /**
- * Write a FileDescriptor into the parcel at the current dataPosition(),
- * growing dataCapacity() if needed.
- */
- public final native void writeFileDescriptor(FileDescriptor val);
-
- /**
- * Write an byte value into the parcel at the current dataPosition(),
- * growing dataCapacity() if needed.
- */
- public final void writeByte(byte val) {
- writeInt(val);
- }
-
- /**
- * Please use {@link #writeBundle} instead. Flattens a Map into the parcel
- * at the current dataPosition(),
- * growing dataCapacity() if needed. The Map keys must be String objects.
- * The Map values are written using {@link #writeValue} and must follow
- * the specification there.
- *
- * <p>It is strongly recommended to use {@link #writeBundle} instead of
- * this method, since the Bundle class provides a type-safe API that
- * allows you to avoid mysterious type errors at the point of marshalling.
- */
- public final void writeMap(Map val) {
- writeMapInternal((Map<String,Object>) val);
- }
-
- /**
- * Flatten a Map into the parcel at the current dataPosition(),
- * growing dataCapacity() if needed. The Map keys must be String objects.
- */
- private void writeMapInternal(Map<String,Object> val) {
- if (val == null) {
- writeInt(-1);
- return;
- }
- Set<Map.Entry<String,Object>> entries = val.entrySet();
- writeInt(entries.size());
- for (Map.Entry<String,Object> e : entries) {
- writeValue(e.getKey());
- writeValue(e.getValue());
- }
- }
-
- /**
- * Flatten a Bundle into the parcel at the current dataPosition(),
- * growing dataCapacity() if needed.
- */
- public final void writeBundle(Bundle val) {
- if (val == null) {
- writeInt(-1);
- return;
- }
-
- if (val.mParcelledData != null) {
- int length = val.mParcelledData.dataSize();
- appendFrom(val.mParcelledData, 0, length);
- } else {
- writeInt(-1); // dummy, will hold length
- int oldPos = dataPosition();
- writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
-
- writeMapInternal(val.mMap);
- int newPos = dataPosition();
-
- // Backpatch length
- setDataPosition(oldPos - 4);
- int length = newPos - oldPos;
- writeInt(length);
- setDataPosition(newPos);
- }
- }
-
- /**
- * Flatten a List into the parcel at the current dataPosition(), growing
- * dataCapacity() if needed. The List values are written using
- * {@link #writeValue} and must follow the specification there.
- */
- public final void writeList(List val) {
- if (val == null) {
- writeInt(-1);
- return;
- }
- int N = val.size();
- int i=0;
- writeInt(N);
- while (i < N) {
- writeValue(val.get(i));
- i++;
- }
- }
-
- /**
- * Flatten an Object array into the parcel at the current dataPosition(),
- * growing dataCapacity() if needed. The array values are written using
- * {@link #writeValue} and must follow the specification there.
- */
- public final void writeArray(Object[] val) {
- if (val == null) {
- writeInt(-1);
- return;
- }
- int N = val.length;
- int i=0;
- writeInt(N);
- while (i < N) {
- writeValue(val[i]);
- i++;
- }
- }
-
- /**
- * Flatten a generic SparseArray into the parcel at the current
- * dataPosition(), growing dataCapacity() if needed. The SparseArray
- * values are written using {@link #writeValue} and must follow the
- * specification there.
- */
- public final void writeSparseArray(SparseArray<Object> val) {
- if (val == null) {
- writeInt(-1);
- return;
- }
- int N = val.size();
- writeInt(N);
- int i=0;
- while (i < N) {
- writeInt(val.keyAt(i));
- writeValue(val.valueAt(i));
- i++;
- }
- }
-
- public final void writeSparseBooleanArray(SparseBooleanArray val) {
- if (val == null) {
- writeInt(-1);
- return;
- }
- int N = val.size();
- writeInt(N);
- int i=0;
- while (i < N) {
- writeInt(val.keyAt(i));
- writeByte((byte)(val.valueAt(i) ? 1 : 0));
- i++;
- }
- }
-
- public final void writeBooleanArray(boolean[] val) {
- if (val != null) {
- int N = val.length;
- writeInt(N);
- for (int i=0; i<N; i++) {
- writeInt(val[i] ? 1 : 0);
- }
- } else {
- writeInt(-1);
- }
- }
-
- public final boolean[] createBooleanArray() {
- int N = readInt();
- // >>2 as a fast divide-by-4 works in the create*Array() functions
- // because dataAvail() will never return a negative number. 4 is
- // the size of a stored boolean in the stream.
- if (N >= 0 && N <= (dataAvail() >> 2)) {
- boolean[] val = new boolean[N];
- for (int i=0; i<N; i++) {
- val[i] = readInt() != 0;
- }
- return val;
- } else {
- return null;
- }
- }
-
- public final void readBooleanArray(boolean[] val) {
- int N = readInt();
- if (N == val.length) {
- for (int i=0; i<N; i++) {
- val[i] = readInt() != 0;
- }
- } else {
- throw new RuntimeException("bad array lengths");
- }
- }
-
- public final void writeCharArray(char[] val) {
- if (val != null) {
- int N = val.length;
- writeInt(N);
- for (int i=0; i<N; i++) {
- writeInt((int)val[i]);
- }
- } else {
- writeInt(-1);
- }
- }
-
- public final char[] createCharArray() {
- int N = readInt();
- if (N >= 0 && N <= (dataAvail() >> 2)) {
- char[] val = new char[N];
- for (int i=0; i<N; i++) {
- val[i] = (char)readInt();
- }
- return val;
- } else {
- return null;
- }
- }
-
- public final void readCharArray(char[] val) {
- int N = readInt();
- if (N == val.length) {
- for (int i=0; i<N; i++) {
- val[i] = (char)readInt();
- }
- } else {
- throw new RuntimeException("bad array lengths");
- }
- }
-
- public final void writeIntArray(int[] val) {
- if (val != null) {
- int N = val.length;
- writeInt(N);
- for (int i=0; i<N; i++) {
- writeInt(val[i]);
- }
- } else {
- writeInt(-1);
- }
- }
-
- public final int[] createIntArray() {
- int N = readInt();
- if (N >= 0 && N <= (dataAvail() >> 2)) {
- int[] val = new int[N];
- for (int i=0; i<N; i++) {
- val[i] = readInt();
- }
- return val;
- } else {
- return null;
- }
- }
-
- public final void readIntArray(int[] val) {
- int N = readInt();
- if (N == val.length) {
- for (int i=0; i<N; i++) {
- val[i] = readInt();
- }
- } else {
- throw new RuntimeException("bad array lengths");
- }
- }
-
- public final void writeLongArray(long[] val) {
- if (val != null) {
- int N = val.length;
- writeInt(N);
- for (int i=0; i<N; i++) {
- writeLong(val[i]);
- }
- } else {
- writeInt(-1);
- }
- }
-
- public final long[] createLongArray() {
- int N = readInt();
- // >>3 because stored longs are 64 bits
- if (N >= 0 && N <= (dataAvail() >> 3)) {
- long[] val = new long[N];
- for (int i=0; i<N; i++) {
- val[i] = readLong();
- }
- return val;
- } else {
- return null;
- }
- }
-
- public final void readLongArray(long[] val) {
- int N = readInt();
- if (N == val.length) {
- for (int i=0; i<N; i++) {
- val[i] = readLong();
- }
- } else {
- throw new RuntimeException("bad array lengths");
- }
- }
-
- public final void writeFloatArray(float[] val) {
- if (val != null) {
- int N = val.length;
- writeInt(N);
- for (int i=0; i<N; i++) {
- writeFloat(val[i]);
- }
- } else {
- writeInt(-1);
- }
- }
-
- public final float[] createFloatArray() {
- int N = readInt();
- // >>2 because stored floats are 4 bytes
- if (N >= 0 && N <= (dataAvail() >> 2)) {
- float[] val = new float[N];
- for (int i=0; i<N; i++) {
- val[i] = readFloat();
- }
- return val;
- } else {
- return null;
- }
- }
-
- public final void readFloatArray(float[] val) {
- int N = readInt();
- if (N == val.length) {
- for (int i=0; i<N; i++) {
- val[i] = readFloat();
- }
- } else {
- throw new RuntimeException("bad array lengths");
- }
- }
-
- public final void writeDoubleArray(double[] val) {
- if (val != null) {
- int N = val.length;
- writeInt(N);
- for (int i=0; i<N; i++) {
- writeDouble(val[i]);
- }
- } else {
- writeInt(-1);
- }
- }
-
- public final double[] createDoubleArray() {
- int N = readInt();
- // >>3 because stored doubles are 8 bytes
- if (N >= 0 && N <= (dataAvail() >> 3)) {
- double[] val = new double[N];
- for (int i=0; i<N; i++) {
- val[i] = readDouble();
- }
- return val;
- } else {
- return null;
- }
- }
-
- public final void readDoubleArray(double[] val) {
- int N = readInt();
- if (N == val.length) {
- for (int i=0; i<N; i++) {
- val[i] = readDouble();
- }
- } else {
- throw new RuntimeException("bad array lengths");
- }
- }
-
- public final void writeStringArray(String[] val) {
- if (val != null) {
- int N = val.length;
- writeInt(N);
- for (int i=0; i<N; i++) {
- writeString(val[i]);
- }
- } else {
- writeInt(-1);
- }
- }
-
- public final String[] createStringArray() {
- int N = readInt();
- if (N >= 0) {
- String[] val = new String[N];
- for (int i=0; i<N; i++) {
- val[i] = readString();
- }
- return val;
- } else {
- return null;
- }
- }
-
- public final void readStringArray(String[] val) {
- int N = readInt();
- if (N == val.length) {
- for (int i=0; i<N; i++) {
- val[i] = readString();
- }
- } else {
- throw new RuntimeException("bad array lengths");
- }
- }
-
- public final void writeBinderArray(IBinder[] val) {
- if (val != null) {
- int N = val.length;
- writeInt(N);
- for (int i=0; i<N; i++) {
- writeStrongBinder(val[i]);
- }
- } else {
- writeInt(-1);
- }
- }
-
- public final IBinder[] createBinderArray() {
- int N = readInt();
- if (N >= 0) {
- IBinder[] val = new IBinder[N];
- for (int i=0; i<N; i++) {
- val[i] = readStrongBinder();
- }
- return val;
- } else {
- return null;
- }
- }
-
- public final void readBinderArray(IBinder[] val) {
- int N = readInt();
- if (N == val.length) {
- for (int i=0; i<N; i++) {
- val[i] = readStrongBinder();
- }
- } else {
- throw new RuntimeException("bad array lengths");
- }
- }
-
- /**
- * Flatten a List containing a particular object type into the parcel, at
- * the current dataPosition() and growing dataCapacity() if needed. The
- * type of the objects in the list must be one that implements Parcelable.
- * Unlike the generic writeList() method, however, only the raw data of the
- * objects is written and not their type, so you must use the corresponding
- * readTypedList() to unmarshall them.
- *
- * @param val The list of objects to be written.
- *
- * @see #createTypedArrayList
- * @see #readTypedList
- * @see Parcelable
- */
- public final <T extends Parcelable> void writeTypedList(List<T> val) {
- if (val == null) {
- writeInt(-1);
- return;
- }
- int N = val.size();
- int i=0;
- writeInt(N);
- while (i < N) {
- T item = val.get(i);
- if (item != null) {
- writeInt(1);
- item.writeToParcel(this, 0);
- } else {
- writeInt(0);
- }
- i++;
- }
- }
-
- /**
- * Flatten a List containing String objects into the parcel, at
- * the current dataPosition() and growing dataCapacity() if needed. They
- * can later be retrieved with {@link #createStringArrayList} or
- * {@link #readStringList}.
- *
- * @param val The list of strings to be written.
- *
- * @see #createStringArrayList
- * @see #readStringList
- */
- public final void writeStringList(List<String> val) {
- if (val == null) {
- writeInt(-1);
- return;
- }
- int N = val.size();
- int i=0;
- writeInt(N);
- while (i < N) {
- writeString(val.get(i));
- i++;
- }
- }
-
- /**
- * Flatten a List containing IBinder objects into the parcel, at
- * the current dataPosition() and growing dataCapacity() if needed. They
- * can later be retrieved with {@link #createBinderArrayList} or
- * {@link #readBinderList}.
- *
- * @param val The list of strings to be written.
- *
- * @see #createBinderArrayList
- * @see #readBinderList
- */
- public final void writeBinderList(List<IBinder> val) {
- if (val == null) {
- writeInt(-1);
- return;
- }
- int N = val.size();
- int i=0;
- writeInt(N);
- while (i < N) {
- writeStrongBinder(val.get(i));
- i++;
- }
- }
-
- /**
- * Flatten a heterogeneous array containing a particular object type into
- * the parcel, at
- * the current dataPosition() and growing dataCapacity() if needed. The
- * type of the objects in the array must be one that implements Parcelable.
- * Unlike the {@link #writeParcelableArray} method, however, only the
- * raw data of the objects is written and not their type, so you must use
- * {@link #readTypedArray} with the correct corresponding
- * {@link Parcelable.Creator} implementation to unmarshall them.
- *
- * @param val The array of objects to be written.
- * @param parcelableFlags Contextual flags as per
- * {@link Parcelable#writeToParcel(Parcel, int) Parcelable.writeToParcel()}.
- *
- * @see #readTypedArray
- * @see #writeParcelableArray
- * @see Parcelable.Creator
- */
- public final <T extends Parcelable> void writeTypedArray(T[] val,
- int parcelableFlags) {
- if (val != null) {
- int N = val.length;
- writeInt(N);
- for (int i=0; i<N; i++) {
- T item = val[i];
- if (item != null) {
- writeInt(1);
- item.writeToParcel(this, parcelableFlags);
- } else {
- writeInt(0);
- }
- }
- } else {
- writeInt(-1);
- }
- }
-
- /**
- * Flatten a generic object in to a parcel. The given Object value may
- * currently be one of the following types:
- *
- * <ul>
- * <li> null
- * <li> String
- * <li> Byte
- * <li> Short
- * <li> Integer
- * <li> Long
- * <li> Float
- * <li> Double
- * <li> Boolean
- * <li> String[]
- * <li> boolean[]
- * <li> byte[]
- * <li> int[]
- * <li> long[]
- * <li> Object[] (supporting objects of the same type defined here).
- * <li> {@link Bundle}
- * <li> Map (as supported by {@link #writeMap}).
- * <li> Any object that implements the {@link Parcelable} protocol.
- * <li> Parcelable[]
- * <li> CharSequence (as supported by {@link TextUtils#writeToParcel}).
- * <li> List (as supported by {@link #writeList}).
- * <li> {@link SparseArray} (as supported by {@link #writeSparseArray}).
- * <li> {@link IBinder}
- * <li> Any object that implements Serializable (but see
- * {@link #writeSerializable} for caveats). Note that all of the
- * previous types have relatively efficient implementations for
- * writing to a Parcel; having to rely on the generic serialization
- * approach is much less efficient and should be avoided whenever
- * possible.
- * </ul>
- */
- public final void writeValue(Object v) {
- if (v == null) {
- writeInt(VAL_NULL);
- } else if (v instanceof String) {
- writeInt(VAL_STRING);
- writeString((String) v);
- } else if (v instanceof Integer) {
- writeInt(VAL_INTEGER);
- writeInt((Integer) v);
- } else if (v instanceof Map) {
- writeInt(VAL_MAP);
- writeMap((Map) v);
- } else if (v instanceof Bundle) {
- // Must be before Parcelable
- writeInt(VAL_BUNDLE);
- writeBundle((Bundle) v);
- } else if (v instanceof Parcelable) {
- writeInt(VAL_PARCELABLE);
- writeParcelable((Parcelable) v, 0);
- } else if (v instanceof Short) {
- writeInt(VAL_SHORT);
- writeInt(((Short) v).intValue());
- } else if (v instanceof Long) {
- writeInt(VAL_LONG);
- writeLong((Long) v);
- } else if (v instanceof Float) {
- writeInt(VAL_FLOAT);
- writeFloat((Float) v);
- } else if (v instanceof Double) {
- writeInt(VAL_DOUBLE);
- writeDouble((Double) v);
- } else if (v instanceof Boolean) {
- writeInt(VAL_BOOLEAN);
- writeInt((Boolean) v ? 1 : 0);
- } else if (v instanceof CharSequence) {
- // Must be after String
- writeInt(VAL_CHARSEQUENCE);
- TextUtils.writeToParcel((CharSequence) v, this, 0);
- } else if (v instanceof List) {
- writeInt(VAL_LIST);
- writeList((List) v);
- } else if (v instanceof SparseArray) {
- writeInt(VAL_SPARSEARRAY);
- writeSparseArray((SparseArray) v);
- } else if (v instanceof boolean[]) {
- writeInt(VAL_BOOLEANARRAY);
- writeBooleanArray((boolean[]) v);
- } else if (v instanceof byte[]) {
- writeInt(VAL_BYTEARRAY);
- writeByteArray((byte[]) v);
- } else if (v instanceof String[]) {
- writeInt(VAL_STRINGARRAY);
- writeStringArray((String[]) v);
- } else if (v instanceof IBinder) {
- writeInt(VAL_IBINDER);
- writeStrongBinder((IBinder) v);
- } else if (v instanceof Parcelable[]) {
- writeInt(VAL_PARCELABLEARRAY);
- writeParcelableArray((Parcelable[]) v, 0);
- } else if (v instanceof Object[]) {
- writeInt(VAL_OBJECTARRAY);
- writeArray((Object[]) v);
- } else if (v instanceof int[]) {
- writeInt(VAL_INTARRAY);
- writeIntArray((int[]) v);
- } else if (v instanceof long[]) {
- writeInt(VAL_LONGARRAY);
- writeLongArray((long[]) v);
- } else if (v instanceof Byte) {
- writeInt(VAL_BYTE);
- writeInt((Byte) v);
- } else if (v instanceof Serializable) {
- // Must be last
- writeInt(VAL_SERIALIZABLE);
- writeSerializable((Serializable) v);
- } else {
- throw new RuntimeException("Parcel: unable to marshal value " + v);
- }
- }
-
- /**
- * Flatten the name of the class of the Parcelable and its contents
- * into the parcel.
- *
- * @param p The Parcelable object to be written.
- * @param parcelableFlags Contextual flags as per
- * {@link Parcelable#writeToParcel(Parcel, int) Parcelable.writeToParcel()}.
- */
- public final void writeParcelable(Parcelable p, int parcelableFlags) {
- if (p == null) {
- writeString(null);
- return;
- }
- String name = p.getClass().getName();
- writeString(name);
- p.writeToParcel(this, parcelableFlags);
- }
-
- /**
- * Write a generic serializable object in to a Parcel. It is strongly
- * recommended that this method be avoided, since the serialization
- * overhead is extremely large, and this approach will be much slower than
- * using the other approaches to writing data in to a Parcel.
- */
- public final void writeSerializable(Serializable s) {
- if (s == null) {
- writeString(null);
- return;
- }
- String name = s.getClass().getName();
- writeString(name);
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- try {
- ObjectOutputStream oos = new ObjectOutputStream(baos);
- oos.writeObject(s);
- oos.close();
-
- writeByteArray(baos.toByteArray());
- } catch (IOException ioe) {
- throw new RuntimeException("Parcelable encountered " +
- "IOException writing serializable object (name = " + name +
- ")", ioe);
- }
- }
-
- /**
- * Special function for writing an exception result at the header of
- * a parcel, to be used when returning an exception from a transaction.
- * Note that this currently only supports a few exception types; any other
- * exception will be re-thrown by this function as a RuntimeException
- * (to be caught by the system's last-resort exception handling when
- * dispatching a transaction).
- *
- * <p>The supported exception types are:
- * <ul>
- * <li>{@link BadParcelableException}
- * <li>{@link IllegalArgumentException}
- * <li>{@link IllegalStateException}
- * <li>{@link NullPointerException}
- * <li>{@link SecurityException}
- * </ul>
- *
- * @param e The Exception to be written.
- *
- * @see #writeNoException
- * @see #readException
- */
- public final void writeException(Exception e) {
- int code = 0;
- if (e instanceof SecurityException) {
- code = EX_SECURITY;
- } else if (e instanceof BadParcelableException) {
- code = EX_BAD_PARCELABLE;
- } else if (e instanceof IllegalArgumentException) {
- code = EX_ILLEGAL_ARGUMENT;
- } else if (e instanceof NullPointerException) {
- code = EX_NULL_POINTER;
- } else if (e instanceof IllegalStateException) {
- code = EX_ILLEGAL_STATE;
- }
- writeInt(code);
- if (code == 0) {
- if (e instanceof RuntimeException) {
- throw (RuntimeException) e;
- }
- throw new RuntimeException(e);
- }
- writeString(e.getMessage());
- }
-
- /**
- * Special function for writing information at the front of the Parcel
- * indicating that no exception occurred.
- *
- * @see #writeException
- * @see #readException
- */
- public final void writeNoException() {
- writeInt(0);
- }
-
- /**
- * Special function for reading an exception result from the header of
- * a parcel, to be used after receiving the result of a transaction. This
- * will throw the exception for you if it had been written to the Parcel,
- * otherwise return and let you read the normal result data from the Parcel.
- *
- * @see #writeException
- * @see #writeNoException
- */
- public final void readException() {
- int code = readInt();
- if (code == 0) return;
- String msg = readString();
- readException(code, msg);
- }
-
- /**
- * Use this function for customized exception handling.
- * customized method call this method for all unknown case
- * @param code exception code
- * @param msg exception message
- */
- public final void readException(int code, String msg) {
- switch (code) {
- case EX_SECURITY:
- throw new SecurityException(msg);
- case EX_BAD_PARCELABLE:
- throw new BadParcelableException(msg);
- case EX_ILLEGAL_ARGUMENT:
- throw new IllegalArgumentException(msg);
- case EX_NULL_POINTER:
- throw new NullPointerException(msg);
- case EX_ILLEGAL_STATE:
- throw new IllegalStateException(msg);
- }
- throw new RuntimeException("Unknown exception code: " + code
- + " msg " + msg);
- }
-
- /**
- * Read an integer value from the parcel at the current dataPosition().
- */
- public final native int readInt();
-
- /**
- * Read a long integer value from the parcel at the current dataPosition().
- */
- public final native long readLong();
-
- /**
- * Read a floating point value from the parcel at the current
- * dataPosition().
- */
- public final native float readFloat();
-
- /**
- * Read a double precision floating point value from the parcel at the
- * current dataPosition().
- */
- public final native double readDouble();
-
- /**
- * Read a string value from the parcel at the current dataPosition().
- */
- public final native String readString();
-
- /**
- * Read an object from the parcel at the current dataPosition().
- */
- public final native IBinder readStrongBinder();
-
- /**
- * Read a FileDescriptor from the parcel at the current dataPosition().
- */
- public final ParcelFileDescriptor readFileDescriptor() {
- FileDescriptor fd = internalReadFileDescriptor();
- return fd != null ? new ParcelFileDescriptor(fd) : null;
- }
-
- private native FileDescriptor internalReadFileDescriptor();
- /*package*/ static native FileDescriptor openFileDescriptor(String file,
- int mode) throws FileNotFoundException;
- /*package*/ static native void closeFileDescriptor(FileDescriptor desc)
- throws IOException;
-
- /**
- * Read a byte value from the parcel at the current dataPosition().
- */
- public final byte readByte() {
- return (byte)(readInt() & 0xff);
- }
-
- /**
- * Please use {@link #readBundle(ClassLoader)} instead (whose data must have
- * been written with {@link #writeBundle}. Read into an existing Map object
- * from the parcel at the current dataPosition().
- */
- public final void readMap(Map outVal, ClassLoader loader) {
- int N = readInt();
- readMapInternal(outVal, N, loader);
- }
-
- /**
- * Read into an existing List object from the parcel at the current
- * dataPosition(), using the given class loader to load any enclosed
- * Parcelables. If it is null, the default class loader is used.
- */
- public final void readList(List outVal, ClassLoader loader) {
- int N = readInt();
- readListInternal(outVal, N, loader);
- }
-
- /**
- * Please use {@link #readBundle(ClassLoader)} instead (whose data must have
- * been written with {@link #writeBundle}. Read and return a new HashMap
- * object from the parcel at the current dataPosition(), using the given
- * class loader to load any enclosed Parcelables. Returns null if
- * the previously written map object was null.
- */
- public final HashMap readHashMap(ClassLoader loader)
- {
- int N = readInt();
- if (N < 0) {
- return null;
- }
- HashMap m = new HashMap(N);
- readMapInternal(m, N, loader);
- return m;
- }
-
- /**
- * Read and return a new Bundle object from the parcel at the current
- * dataPosition(). Returns null if the previously written Bundle object was
- * null.
- */
- public final Bundle readBundle() {
- return readBundle(null);
- }
-
- /**
- * Read and return a new Bundle object from the parcel at the current
- * dataPosition(), using the given class loader to initialize the class
- * loader of the Bundle for later retrieval of Parcelable objects.
- * Returns null if the previously written Bundle object was null.
- */
- public final Bundle readBundle(ClassLoader loader) {
- int offset = dataPosition();
- int length = readInt();
- if (length < 0) {
- return null;
- }
- int magic = readInt();
- if (magic != 0x4C444E42) {
- //noinspection ThrowableInstanceNeverThrown
- String st = Log.getStackTraceString(new RuntimeException());
- Log.e("Bundle", "readBundle: bad magic number");
- Log.e("Bundle", "readBundle: trace = " + st);
- }
-
- // Advance within this Parcel
- setDataPosition(offset + length + 4);
-
- Parcel p = new Parcel(0);
- p.setDataPosition(0);
- p.appendFrom(this, offset, length + 4);
- p.setDataPosition(0);
- final Bundle bundle = new Bundle(p);
- if (loader != null) {
- bundle.setClassLoader(loader);
- }
- return bundle;
- }
-
- /**
- * Read and return a new Bundle object from the parcel at the current
- * dataPosition(). Returns null if the previously written Bundle object was
- * null. The returned bundle will have its contents fully unpacked using
- * the given ClassLoader.
- */
- /* package */ Bundle readBundleUnpacked(ClassLoader loader) {
- int length = readInt();
- if (length == -1) {
- return null;
- }
- int magic = readInt();
- if (magic != 0x4C444E42) {
- //noinspection ThrowableInstanceNeverThrown
- String st = Log.getStackTraceString(new RuntimeException());
- Log.e("Bundle", "readBundleUnpacked: bad magic number");
- Log.e("Bundle", "readBundleUnpacked: trace = " + st);
- }
- Bundle m = new Bundle(loader);
- int N = readInt();
- if (N < 0) {
- return null;
- }
- readMapInternal(m.mMap, N, loader);
- return m;
- }
-
- /**
- * Read and return a byte[] object from the parcel.
- */
- public final native byte[] createByteArray();
-
- /**
- * Read a byte[] object from the parcel and copy it into the
- * given byte array.
- */
- public final void readByteArray(byte[] val) {
- // TODO: make this a native method to avoid the extra copy.
- byte[] ba = createByteArray();
- if (ba.length == val.length) {
- System.arraycopy(ba, 0, val, 0, ba.length);
- } else {
- throw new RuntimeException("bad array lengths");
- }
- }
-
- /**
- * Read and return a String[] object from the parcel.
- * {@hide}
- */
- public final String[] readStringArray() {
- String[] array = null;
-
- int length = readInt();
- if (length >= 0)
- {
- array = new String[length];
-
- for (int i = 0 ; i < length ; i++)
- {
- array[i] = readString();
- }
- }
-
- return array;
- }
-
- /**
- * Read and return a new ArrayList object from the parcel at the current
- * dataPosition(). Returns null if the previously written list object was
- * null. The given class loader will be used to load any enclosed
- * Parcelables.
- */
- public final ArrayList readArrayList(ClassLoader loader) {
- int N = readInt();
- if (N < 0) {
- return null;
- }
- ArrayList l = new ArrayList(N);
- readListInternal(l, N, loader);
- return l;
- }
-
- /**
- * Read and return a new Object array from the parcel at the current
- * dataPosition(). Returns null if the previously written array was
- * null. The given class loader will be used to load any enclosed
- * Parcelables.
- */
- public final Object[] readArray(ClassLoader loader) {
- int N = readInt();
- if (N < 0) {
- return null;
- }
- Object[] l = new Object[N];
- readArrayInternal(l, N, loader);
- return l;
- }
-
- /**
- * Read and return a new SparseArray object from the parcel at the current
- * dataPosition(). Returns null if the previously written list object was
- * null. The given class loader will be used to load any enclosed
- * Parcelables.
- */
- public final SparseArray readSparseArray(ClassLoader loader) {
- int N = readInt();
- if (N < 0) {
- return null;
- }
- SparseArray sa = new SparseArray(N);
- readSparseArrayInternal(sa, N, loader);
- return sa;
- }
-
- /**
- * Read and return a new SparseBooleanArray object from the parcel at the current
- * dataPosition(). Returns null if the previously written list object was
- * null.
- */
- public final SparseBooleanArray readSparseBooleanArray() {
- int N = readInt();
- if (N < 0) {
- return null;
- }
- SparseBooleanArray sa = new SparseBooleanArray(N);
- readSparseBooleanArrayInternal(sa, N);
- return sa;
- }
-
- /**
- * Read and return a new ArrayList containing a particular object type from
- * the parcel that was written with {@link #writeTypedList} at the
- * current dataPosition(). Returns null if the
- * previously written list object was null. The list <em>must</em> have
- * previously been written via {@link #writeTypedList} with the same object
- * type.
- *
- * @return A newly created ArrayList containing objects with the same data
- * as those that were previously written.
- *
- * @see #writeTypedList
- */
- public final <T> ArrayList<T> createTypedArrayList(Parcelable.Creator<T> c) {
- int N = readInt();
- if (N < 0) {
- return null;
- }
- ArrayList<T> l = new ArrayList<T>(N);
- while (N > 0) {
- if (readInt() != 0) {
- l.add(c.createFromParcel(this));
- } else {
- l.add(null);
- }
- N--;
- }
- return l;
- }
-
- /**
- * Read into the given List items containing a particular object type
- * that were written with {@link #writeTypedList} at the
- * current dataPosition(). The list <em>must</em> have
- * previously been written via {@link #writeTypedList} with the same object
- * type.
- *
- * @return A newly created ArrayList containing objects with the same data
- * as those that were previously written.
- *
- * @see #writeTypedList
- */
- public final <T> void readTypedList(List<T> list, Parcelable.Creator<T> c) {
- int M = list.size();
- int N = readInt();
- int i = 0;
- for (; i < M && i < N; i++) {
- if (readInt() != 0) {
- list.set(i, c.createFromParcel(this));
- } else {
- list.set(i, null);
- }
- }
- for (; i<N; i++) {
- if (readInt() != 0) {
- list.add(c.createFromParcel(this));
- } else {
- list.add(null);
- }
- }
- for (; i<M; i++) {
- list.remove(N);
- }
- }
-
- /**
- * Read and return a new ArrayList containing String objects from
- * the parcel that was written with {@link #writeStringList} at the
- * current dataPosition(). Returns null if the
- * previously written list object was null.
- *
- * @return A newly created ArrayList containing strings with the same data
- * as those that were previously written.
- *
- * @see #writeStringList
- */
- public final ArrayList<String> createStringArrayList() {
- int N = readInt();
- if (N < 0) {
- return null;
- }
- ArrayList<String> l = new ArrayList<String>(N);
- while (N > 0) {
- l.add(readString());
- N--;
- }
- return l;
- }
-
- /**
- * Read and return a new ArrayList containing IBinder objects from
- * the parcel that was written with {@link #writeBinderList} at the
- * current dataPosition(). Returns null if the
- * previously written list object was null.
- *
- * @return A newly created ArrayList containing strings with the same data
- * as those that were previously written.
- *
- * @see #writeBinderList
- */
- public final ArrayList<IBinder> createBinderArrayList() {
- int N = readInt();
- if (N < 0) {
- return null;
- }
- ArrayList<IBinder> l = new ArrayList<IBinder>(N);
- while (N > 0) {
- l.add(readStrongBinder());
- N--;
- }
- return l;
- }
-
- /**
- * Read into the given List items String objects that were written with
- * {@link #writeStringList} at the current dataPosition().
- *
- * @return A newly created ArrayList containing strings with the same data
- * as those that were previously written.
- *
- * @see #writeStringList
- */
- public final void readStringList(List<String> list) {
- int M = list.size();
- int N = readInt();
- int i = 0;
- for (; i < M && i < N; i++) {
- list.set(i, readString());
- }
- for (; i<N; i++) {
- list.add(readString());
- }
- for (; i<M; i++) {
- list.remove(N);
- }
- }
-
- /**
- * Read into the given List items IBinder objects that were written with
- * {@link #writeBinderList} at the current dataPosition().
- *
- * @return A newly created ArrayList containing strings with the same data
- * as those that were previously written.
- *
- * @see #writeBinderList
- */
- public final void readBinderList(List<IBinder> list) {
- int M = list.size();
- int N = readInt();
- int i = 0;
- for (; i < M && i < N; i++) {
- list.set(i, readStrongBinder());
- }
- for (; i<N; i++) {
- list.add(readStrongBinder());
- }
- for (; i<M; i++) {
- list.remove(N);
- }
- }
-
- /**
- * Read and return a new array containing a particular object type from
- * the parcel at the current dataPosition(). Returns null if the
- * previously written array was null. The array <em>must</em> have
- * previously been written via {@link #writeTypedArray} with the same
- * object type.
- *
- * @return A newly created array containing objects with the same data
- * as those that were previously written.
- *
- * @see #writeTypedArray
- */
- public final <T> T[] createTypedArray(Parcelable.Creator<T> c) {
- int N = readInt();
- if (N < 0) {
- return null;
- }
- T[] l = c.newArray(N);
- for (int i=0; i<N; i++) {
- if (readInt() != 0) {
- l[i] = c.createFromParcel(this);
- }
- }
- return l;
- }
-
- public final <T> void readTypedArray(T[] val, Parcelable.Creator<T> c) {
- int N = readInt();
- if (N == val.length) {
- for (int i=0; i<N; i++) {
- if (readInt() != 0) {
- val[i] = c.createFromParcel(this);
- } else {
- val[i] = null;
- }
- }
- } else {
- throw new RuntimeException("bad array lengths");
- }
- }
-
- /**
- * @deprecated
- * @hide
- */
- @Deprecated
- public final <T> T[] readTypedArray(Parcelable.Creator<T> c) {
- return createTypedArray(c);
- }
-
- /**
- * Write a heterogeneous array of Parcelable objects into the Parcel.
- * Each object in the array is written along with its class name, so
- * that the correct class can later be instantiated. As a result, this
- * has significantly more overhead than {@link #writeTypedArray}, but will
- * correctly handle an array containing more than one type of object.
- *
- * @param value The array of objects to be written.
- * @param parcelableFlags Contextual flags as per
- * {@link Parcelable#writeToParcel(Parcel, int) Parcelable.writeToParcel()}.
- *
- * @see #writeTypedArray
- */
- public final <T extends Parcelable> void writeParcelableArray(T[] value,
- int parcelableFlags) {
- if (value != null) {
- int N = value.length;
- writeInt(N);
- for (int i=0; i<N; i++) {
- writeParcelable(value[i], parcelableFlags);
- }
- } else {
- writeInt(-1);
- }
- }
-
- /**
- * Read a typed object from a parcel. The given class loader will be
- * used to load any enclosed Parcelables. If it is null, the default class
- * loader will be used.
- */
- public final Object readValue(ClassLoader loader) {
- int type = readInt();
-
- switch (type) {
- case VAL_NULL:
- return null;
-
- case VAL_STRING:
- return readString();
-
- case VAL_INTEGER:
- return readInt();
-
- case VAL_MAP:
- return readHashMap(loader);
-
- case VAL_PARCELABLE:
- return readParcelable(loader);
-
- case VAL_SHORT:
- return (short) readInt();
-
- case VAL_LONG:
- return readLong();
-
- case VAL_FLOAT:
- return readFloat();
-
- case VAL_DOUBLE:
- return readDouble();
-
- case VAL_BOOLEAN:
- return readInt() == 1;
-
- case VAL_CHARSEQUENCE:
- return TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(this);
-
- case VAL_LIST:
- return readArrayList(loader);
-
- case VAL_BOOLEANARRAY:
- return createBooleanArray();
-
- case VAL_BYTEARRAY:
- return createByteArray();
-
- case VAL_STRINGARRAY:
- return readStringArray();
-
- case VAL_IBINDER:
- return readStrongBinder();
-
- case VAL_OBJECTARRAY:
- return readArray(loader);
-
- case VAL_INTARRAY:
- return createIntArray();
-
- case VAL_LONGARRAY:
- return createLongArray();
-
- case VAL_BYTE:
- return readByte();
-
- case VAL_SERIALIZABLE:
- return readSerializable();
-
- case VAL_PARCELABLEARRAY:
- return readParcelableArray(loader);
-
- case VAL_SPARSEARRAY:
- return readSparseArray(loader);
-
- case VAL_SPARSEBOOLEANARRAY:
- return readSparseBooleanArray();
-
- case VAL_BUNDLE:
- return readBundle(loader); // loading will be deferred
-
- default:
- int off = dataPosition() - 4;
- throw new RuntimeException(
- "Parcel " + this + ": Unmarshalling unknown type code " + type + " at offset " + off);
- }
- }
-
- /**
- * Read and return a new Parcelable from the parcel. The given class loader
- * will be used to load any enclosed Parcelables. If it is null, the default
- * class loader will be used.
- * @param loader A ClassLoader from which to instantiate the Parcelable
- * object, or null for the default class loader.
- * @return Returns the newly created Parcelable, or null if a null
- * object has been written.
- * @throws BadParcelableException Throws BadParcelableException if there
- * was an error trying to instantiate the Parcelable.
- */
- public final <T extends Parcelable> T readParcelable(ClassLoader loader) {
- String name = readString();
- if (name == null) {
- return null;
- }
- Parcelable.Creator<T> creator;
- synchronized (mCreators) {
- HashMap<String,Parcelable.Creator> map = mCreators.get(loader);
- if (map == null) {
- map = new HashMap<String,Parcelable.Creator>();
- mCreators.put(loader, map);
- }
- creator = map.get(name);
- if (creator == null) {
- try {
- Class c = loader == null ?
- Class.forName(name) : Class.forName(name, true, loader);
- Field f = c.getField("CREATOR");
- creator = (Parcelable.Creator)f.get(null);
- }
- catch (IllegalAccessException e) {
- Log.e("Parcel", "Class not found when unmarshalling: "
- + name + ", e: " + e);
- throw new BadParcelableException(
- "IllegalAccessException when unmarshalling: " + name);
- }
- catch (ClassNotFoundException e) {
- Log.e("Parcel", "Class not found when unmarshalling: "
- + name + ", e: " + e);
- throw new BadParcelableException(
- "ClassNotFoundException when unmarshalling: " + name);
- }
- catch (ClassCastException e) {
- throw new BadParcelableException("Parcelable protocol requires a "
- + "Parcelable.Creator object called "
- + " CREATOR on class " + name);
- }
- catch (NoSuchFieldException e) {
- throw new BadParcelableException("Parcelable protocol requires a "
- + "Parcelable.Creator object called "
- + " CREATOR on class " + name);
- }
- if (creator == null) {
- throw new BadParcelableException("Parcelable protocol requires a "
- + "Parcelable.Creator object called "
- + " CREATOR on class " + name);
- }
-
- map.put(name, creator);
- }
- }
-
- return creator.createFromParcel(this);
- }
-
- /**
- * Read and return a new Parcelable array from the parcel.
- * The given class loader will be used to load any enclosed
- * Parcelables.
- * @return the Parcelable array, or null if the array is null
- */
- public final Parcelable[] readParcelableArray(ClassLoader loader) {
- int N = readInt();
- if (N < 0) {
- return null;
- }
- Parcelable[] p = new Parcelable[N];
- for (int i = 0; i < N; i++) {
- p[i] = (Parcelable) readParcelable(loader);
- }
- return p;
- }
-
- /**
- * Read and return a new Serializable object from the parcel.
- * @return the Serializable object, or null if the Serializable name
- * wasn't found in the parcel.
- */
- public final Serializable readSerializable() {
- String name = readString();
- if (name == null) {
- // For some reason we were unable to read the name of the Serializable (either there
- // is nothing left in the Parcel to read, or the next value wasn't a String), so
- // return null, which indicates that the name wasn't found in the parcel.
- return null;
- }
-
- byte[] serializedData = createByteArray();
- ByteArrayInputStream bais = new ByteArrayInputStream(serializedData);
- try {
- ObjectInputStream ois = new ObjectInputStream(bais);
- return (Serializable) ois.readObject();
- } catch (IOException ioe) {
- throw new RuntimeException("Parcelable encountered " +
- "IOException reading a Serializable object (name = " + name +
- ")", ioe);
- } catch (ClassNotFoundException cnfe) {
- throw new RuntimeException("Parcelable encountered" +
- "ClassNotFoundException reading a Serializable object (name = "
- + name + ")", cnfe);
- }
- }
-
- // Cache of previously looked up CREATOR.createFromParcel() methods for
- // particular classes. Keys are the names of the classes, values are
- // Method objects.
- private static final HashMap<ClassLoader,HashMap<String,Parcelable.Creator>>
- mCreators = new HashMap<ClassLoader,HashMap<String,Parcelable.Creator>>();
-
- static protected final Parcel obtain(int obj) {
- final Parcel[] pool = sHolderPool;
- synchronized (pool) {
- Parcel p;
- for (int i=0; i<POOL_SIZE; i++) {
- p = pool[i];
- if (p != null) {
- pool[i] = null;
- if (DEBUG_RECYCLE) {
- p.mStack = new RuntimeException();
- }
- p.init(obj);
- return p;
- }
- }
- }
- return new Parcel(obj);
- }
-
- private Parcel(int obj) {
- if (DEBUG_RECYCLE) {
- mStack = new RuntimeException();
- }
- //Log.i("Parcel", "Initializing obj=0x" + Integer.toHexString(obj), mStack);
- init(obj);
- }
-
- @Override
- protected void finalize() throws Throwable {
- if (DEBUG_RECYCLE) {
- if (mStack != null) {
- Log.w("Parcel", "Client did not call Parcel.recycle()", mStack);
- }
- }
- destroy();
- }
-
- private native void freeBuffer();
- private native void init(int obj);
- private native void destroy();
-
- private void readMapInternal(Map outVal, int N,
- ClassLoader loader) {
- while (N > 0) {
- Object key = readValue(loader);
- Object value = readValue(loader);
- outVal.put(key, value);
- N--;
- }
- }
-
- private void readListInternal(List outVal, int N,
- ClassLoader loader) {
- while (N > 0) {
- Object value = readValue(loader);
- //Log.d("Parcel", "Unmarshalling value=" + value);
- outVal.add(value);
- N--;
- }
- }
-
- private void readArrayInternal(Object[] outVal, int N,
- ClassLoader loader) {
- for (int i = 0; i < N; i++) {
- Object value = readValue(loader);
- //Log.d("Parcel", "Unmarshalling value=" + value);
- outVal[i] = value;
- }
- }
-
- private void readSparseArrayInternal(SparseArray outVal, int N,
- ClassLoader loader) {
- while (N > 0) {
- int key = readInt();
- Object value = readValue(loader);
- //Log.i("Parcel", "Unmarshalling key=" + key + " value=" + value);
- outVal.append(key, value);
- N--;
- }
- }
-
-
- private void readSparseBooleanArrayInternal(SparseBooleanArray outVal, int N) {
- while (N > 0) {
- int key = readInt();
- boolean value = this.readByte() == 1;
- //Log.i("Parcel", "Unmarshalling key=" + key + " value=" + value);
- outVal.append(key, value);
- N--;
- }
- }
-}
diff --git a/core/java/android/os/ParcelFileDescriptor.aidl b/core/java/android/os/ParcelFileDescriptor.aidl
deleted file mode 100644
index 5857aae..0000000
--- a/core/java/android/os/ParcelFileDescriptor.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/os/ParcelFileDescriptor.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.os;
-
-parcelable ParcelFileDescriptor;
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
deleted file mode 100644
index ed138cb..0000000
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.net.Socket;
-
-/**
- * The FileDescriptor returned by {@link Parcel#readFileDescriptor}, allowing
- * you to close it when done with it.
- */
-public class ParcelFileDescriptor implements Parcelable {
- private final FileDescriptor mFileDescriptor;
- private boolean mClosed;
- //this field is to create wrapper for ParcelFileDescriptor using another
- //PartialFileDescriptor but avoid invoking close twice
- //consider ParcelFileDescriptor A(fileDescriptor fd), ParcelFileDescriptor B(A)
- //in this particular case fd.close might be invoked twice.
- private final ParcelFileDescriptor mParcelDescriptor;
-
- /**
- * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied
- * and this file doesn't already exist, then create the file with
- * permissions such that any application can read it.
- */
- public static final int MODE_WORLD_READABLE = 0x00000001;
-
- /**
- * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied
- * and this file doesn't already exist, then create the file with
- * permissions such that any application can write it.
- */
- public static final int MODE_WORLD_WRITEABLE = 0x00000002;
-
- /**
- * For use with {@link #open}: open the file with read-only access.
- */
- public static final int MODE_READ_ONLY = 0x10000000;
-
- /**
- * For use with {@link #open}: open the file with write-only access.
- */
- public static final int MODE_WRITE_ONLY = 0x20000000;
-
- /**
- * For use with {@link #open}: open the file with read and write access.
- */
- public static final int MODE_READ_WRITE = 0x30000000;
-
- /**
- * For use with {@link #open}: create the file if it doesn't already exist.
- */
- public static final int MODE_CREATE = 0x08000000;
-
- /**
- * For use with {@link #open}: erase contents of file when opening.
- */
- public static final int MODE_TRUNCATE = 0x04000000;
-
- /**
- * Create a new ParcelFileDescriptor accessing a given file.
- *
- * @param file The file to be opened.
- * @param mode The desired access mode, must be one of
- * {@link #MODE_READ_ONLY}, {@link #MODE_WRITE_ONLY}, or
- * {@link #MODE_READ_WRITE}; may also be any combination of
- * {@link #MODE_CREATE}, {@link #MODE_TRUNCATE},
- * {@link #MODE_WORLD_READABLE}, and {@link #MODE_WORLD_WRITEABLE}.
- *
- * @return Returns a new ParcelFileDescriptor pointing to the given
- * file.
- *
- * @throws FileNotFoundException Throws FileNotFoundException if the given
- * file does not exist or can not be opened with the requested mode.
- */
- public static ParcelFileDescriptor open(File file, int mode)
- throws FileNotFoundException {
- String path = file.getPath();
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- security.checkRead(path);
- if ((mode&MODE_WRITE_ONLY) != 0) {
- security.checkWrite(path);
- }
- }
-
- if ((mode&MODE_READ_WRITE) == 0) {
- throw new IllegalArgumentException(
- "Must specify MODE_READ_ONLY, MODE_WRITE_ONLY, or MODE_READ_WRITE");
- }
-
- FileDescriptor fd = Parcel.openFileDescriptor(path, mode);
- return new ParcelFileDescriptor(fd);
- }
-
- /**
- * Create a new ParcelFileDescriptor from the specified Socket.
- *
- * @param socket The Socket whose FileDescriptor is used to create
- * a new ParcelFileDescriptor.
- *
- * @return A new ParcelFileDescriptor with the FileDescriptor of the
- * specified Socket.
- */
- public static ParcelFileDescriptor fromSocket(Socket socket) {
- FileDescriptor fd = getFileDescriptorFromSocket(socket);
- return new ParcelFileDescriptor(fd);
- }
-
- // Extracts the file descriptor from the specified socket and returns it untouched
- private static native FileDescriptor getFileDescriptorFromSocket(Socket socket);
-
- /**
- * Retrieve the actual FileDescriptor associated with this object.
- *
- * @return Returns the FileDescriptor associated with this object.
- */
- public FileDescriptor getFileDescriptor() {
- return mFileDescriptor;
- }
-
- /**
- * Close the ParcelFileDescriptor. This implementation closes the underlying
- * OS resources allocated to represent this stream.
- *
- * @throws IOException
- * If an error occurs attempting to close this ParcelFileDescriptor.
- */
- public void close() throws IOException {
- mClosed = true;
- if (mParcelDescriptor != null) {
- // If this is a proxy to another file descriptor, just call through to its
- // close method.
- mParcelDescriptor.close();
- } else {
- Parcel.closeFileDescriptor(mFileDescriptor);
- }
- }
-
- /**
- * An InputStream you can create on a ParcelFileDescriptor, which will
- * take care of calling {@link ParcelFileDescriptor#close
- * ParcelFileDescritor.close()} for you when the stream is closed.
- */
- public static class AutoCloseInputStream extends FileInputStream {
- private final ParcelFileDescriptor mFd;
-
- public AutoCloseInputStream(ParcelFileDescriptor fd) {
- super(fd.getFileDescriptor());
- mFd = fd;
- }
-
- @Override
- public void close() throws IOException {
- mFd.close();
- }
- }
-
- /**
- * An OutputStream you can create on a ParcelFileDescriptor, which will
- * take care of calling {@link ParcelFileDescriptor#close
- * ParcelFileDescritor.close()} for you when the stream is closed.
- */
- public static class AutoCloseOutputStream extends FileOutputStream {
- private final ParcelFileDescriptor mFd;
-
- public AutoCloseOutputStream(ParcelFileDescriptor fd) {
- super(fd.getFileDescriptor());
- mFd = fd;
- }
-
- @Override
- public void close() throws IOException {
- mFd.close();
- }
- }
-
- @Override
- public String toString() {
- return "{ParcelFileDescriptor: " + mFileDescriptor + "}";
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- if (!mClosed) {
- close();
- }
- } finally {
- super.finalize();
- }
- }
-
- public ParcelFileDescriptor(ParcelFileDescriptor descriptor) {
- super();
- mParcelDescriptor = descriptor;
- mFileDescriptor = mParcelDescriptor.mFileDescriptor;
- }
-
- /*package */ParcelFileDescriptor(FileDescriptor descriptor) {
- super();
- mFileDescriptor = descriptor;
- mParcelDescriptor = null;
- }
-
- /* Parcelable interface */
- public int describeContents() {
- return Parcelable.CONTENTS_FILE_DESCRIPTOR;
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeFileDescriptor(mFileDescriptor);
- if ((flags&PARCELABLE_WRITE_RETURN_VALUE) != 0 && !mClosed) {
- try {
- close();
- } catch (IOException e) {
- // Empty
- }
- }
- }
-
- public static final Parcelable.Creator<ParcelFileDescriptor> CREATOR
- = new Parcelable.Creator<ParcelFileDescriptor>() {
- public ParcelFileDescriptor createFromParcel(Parcel in) {
- return in.readFileDescriptor();
- }
- public ParcelFileDescriptor[] newArray(int size) {
- return new ParcelFileDescriptor[size];
- }
- };
-
-}
diff --git a/core/java/android/os/ParcelFormatException.java b/core/java/android/os/ParcelFormatException.java
deleted file mode 100644
index 8b6fda0..0000000
--- a/core/java/android/os/ParcelFormatException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * The contents of a Parcel (usually during unmarshalling) does not
- * contain the expected data.
- */
-public class ParcelFormatException extends RuntimeException {
- public ParcelFormatException() {
- super();
- }
-
- public ParcelFormatException(String reason) {
- super(reason);
- }
-}
diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java
deleted file mode 100644
index aee1e0b..0000000
--- a/core/java/android/os/Parcelable.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * Interface for classes whose instances can be written to
- * and restored from a {@link Parcel}. Classes implementing the Parcelable
- * interface must also have a static field called <code>CREATOR</code>, which
- * is an object implementing the {@link Parcelable.Creator Parcelable.Creator}
- * interface.
- *
- * <p>A typical implementation of Parcelable is:</p>
- *
- * <pre>
- * public class MyParcelable implements Parcelable {
- * private int mData;
- *
- * public void writeToParcel(Parcel out, int flags) {
- * out.writeInt(mData);
- * }
- *
- * public static final Parcelable.Creator<MyParcelable> CREATOR
- * = new Parcelable.Creator<MyParcelable>() {
- * public MyParcelable createFromParcel(Parcel in) {
- * return new MyParcelable(in);
- * }
- *
- * public MyParcelable[] newArray(int size) {
- * return new MyParcelable[size];
- * }
- * }
- *
- * private MyParcelable(Parcel in) {
- * mData = in.readInt();
- * }
- * }</pre>
- */
-public interface Parcelable {
- /**
- * Flag for use with {@link #writeToParcel}: the object being written
- * is a return value, that is the result of a function such as
- * "<code>Parcelable someFunction()</code>",
- * "<code>void someFunction(out Parcelable)</code>", or
- * "<code>void someFunction(inout Parcelable)</code>". Some implementations
- * may want to release resources at this point.
- */
- public static final int PARCELABLE_WRITE_RETURN_VALUE = 0x0001;
-
- /**
- * Bit masks for use with {@link #describeContents}: each bit represents a
- * kind of object considered to have potential special significance when
- * marshalled.
- */
- public static final int CONTENTS_FILE_DESCRIPTOR = 0x0001;
-
- /**
- * Describe the kinds of special objects contained in this Parcelable's
- * marshalled representation.
- *
- * @return a bitmask indicating the set of special object types marshalled
- * by the Parcelable.
- */
- public int describeContents();
-
- /**
- * Flatten this object in to a Parcel.
- *
- * @param dest The Parcel in which the object should be written.
- * @param flags Additional flags about how the object should be written.
- * May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
- */
- public void writeToParcel(Parcel dest, int flags);
-
- /**
- * Interface that must be implemented and provided as a public CREATOR
- * field that generates instances of your Parcelable class from a Parcel.
- */
- public interface Creator<T> {
- /**
- * Create a new instance of the Parcelable class, instantiating it
- * from the given Parcel whose data had previously been written by
- * {@link Parcelable#writeToParcel Parcelable.writeToParcel()}.
- *
- * @param source The Parcel to read the object's data from.
- * @return Returns a new instance of the Parcelable class.
- */
- public T createFromParcel(Parcel source);
-
- /**
- * Create a new array of the Parcelable class.
- *
- * @param size Size of the array.
- * @return Returns an array of the Parcelable class, with every entry
- * initialized to null.
- */
- public T[] newArray(int size);
- }
-}
diff --git a/core/java/android/os/PatternMatcher.aidl b/core/java/android/os/PatternMatcher.aidl
deleted file mode 100644
index 86309f1..0000000
--- a/core/java/android/os/PatternMatcher.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-parcelable PatternMatcher;
diff --git a/core/java/android/os/PatternMatcher.java b/core/java/android/os/PatternMatcher.java
deleted file mode 100644
index 56dc837..0000000
--- a/core/java/android/os/PatternMatcher.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * A simple pattern matcher, which is safe to use on untrusted data: it does
- * not provide full reg-exp support, only simple globbing that can not be
- * used maliciously.
- */
-public class PatternMatcher implements Parcelable {
- /**
- * Pattern type: the given pattern must exactly match the string it is
- * tested against.
- */
- public static final int PATTERN_LITERAL = 0;
-
- /**
- * Pattern type: the given pattern must match the
- * beginning of the string it is tested against.
- */
- public static final int PATTERN_PREFIX = 1;
-
- /**
- * Pattern type: the given pattern is interpreted with a
- * simple glob syntax for matching against the string it is tested against.
- * In this syntax, you can use the '*' character to match against zero or
- * more occurrences of the character immediately before. If the
- * character before it is '.' it will match any character. The character
- * '\' can be used as an escape. This essentially provides only the '*'
- * wildcard part of a normal regexp.
- */
- public static final int PATTERN_SIMPLE_GLOB = 2;
-
- private final String mPattern;
- private final int mType;
-
- public PatternMatcher(String pattern, int type) {
- mPattern = pattern;
- mType = type;
- }
-
- public final String getPath() {
- return mPattern;
- }
-
- public final int getType() {
- return mType;
- }
-
- public boolean match(String str) {
- return matchPattern(mPattern, str, mType);
- }
-
- public String toString() {
- String type = "? ";
- switch (mType) {
- case PATTERN_LITERAL:
- type = "LITERAL: ";
- break;
- case PATTERN_PREFIX:
- type = "PREFIX: ";
- break;
- case PATTERN_SIMPLE_GLOB:
- type = "GLOB: ";
- break;
- }
- return "PatternMatcher{" + type + mPattern + "}";
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mPattern);
- dest.writeInt(mType);
- }
-
- public PatternMatcher(Parcel src) {
- mPattern = src.readString();
- mType = src.readInt();
- }
-
- public static final Parcelable.Creator<PatternMatcher> CREATOR
- = new Parcelable.Creator<PatternMatcher>() {
- public PatternMatcher createFromParcel(Parcel source) {
- return new PatternMatcher(source);
- }
-
- public PatternMatcher[] newArray(int size) {
- return new PatternMatcher[size];
- }
- };
-
- static boolean matchPattern(String pattern, String match, int type) {
- if (match == null) return false;
- if (type == PATTERN_LITERAL) {
- return pattern.equals(match);
- } if (type == PATTERN_PREFIX) {
- return match.startsWith(pattern);
- } else if (type != PATTERN_SIMPLE_GLOB) {
- return false;
- }
-
- final int NP = pattern.length();
- if (NP <= 0) {
- return match.length() <= 0;
- }
- final int NM = match.length();
- int ip = 0, im = 0;
- char nextChar = pattern.charAt(0);
- while ((ip<NP) && (im<NM)) {
- char c = nextChar;
- ip++;
- nextChar = ip < NP ? pattern.charAt(ip) : 0;
- final boolean escaped = (c == '\\');
- if (escaped) {
- c = nextChar;
- ip++;
- nextChar = ip < NP ? pattern.charAt(ip) : 0;
- }
- if (nextChar == '*') {
- if (!escaped && c == '.') {
- if (ip >= (NP-1)) {
- // at the end with a pattern match, so
- // all is good without checking!
- return true;
- }
- ip++;
- nextChar = pattern.charAt(ip);
- // Consume everything until the next character in the
- // pattern is found.
- if (nextChar == '\\') {
- ip++;
- nextChar = ip < NP ? pattern.charAt(ip) : 0;
- }
- do {
- if (match.charAt(im) == nextChar) {
- break;
- }
- im++;
- } while (im < NM);
- if (im == NM) {
- // Whoops, the next character in the pattern didn't
- // exist in the match.
- return false;
- }
- ip++;
- nextChar = ip < NP ? pattern.charAt(ip) : 0;
- im++;
- } else {
- // Consume only characters matching the one before '*'.
- do {
- if (match.charAt(im) != c) {
- break;
- }
- im++;
- } while (im < NM);
- ip++;
- nextChar = ip < NP ? pattern.charAt(ip) : 0;
- }
- } else {
- if (c != '.' && match.charAt(im) != c) return false;
- im++;
- }
- }
-
- if (ip >= NP && im >= NM) {
- // Reached the end of both strings, all is good!
- return true;
- }
-
- // One last check: we may have finished the match string, but still
- // have a '.*' at the end of the pattern, which should still count
- // as a match.
- if (ip == NP-2 && pattern.charAt(ip) == '.'
- && pattern.charAt(ip+1) == '*') {
- return true;
- }
-
- return false;
- }
-}
diff --git a/core/java/android/os/Power.java b/core/java/android/os/Power.java
deleted file mode 100644
index b53e227..0000000
--- a/core/java/android/os/Power.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import java.io.IOException;
-
-/**
- * Class that provides access to some of the power management functions.
- *
- * {@hide}
- */
-public class Power
-{
- // can't instantiate this class
- private Power()
- {
- }
-
- /**
- * Wake lock that ensures that the CPU is running. The screen might
- * not be on.
- */
- public static final int PARTIAL_WAKE_LOCK = 1;
-
- /**
- * Wake lock that ensures that the screen is on.
- */
- public static final int FULL_WAKE_LOCK = 2;
-
- public static native void acquireWakeLock(int lock, String id);
- public static native void releaseWakeLock(String id);
-
- /**
- * Flag to turn on and off the keyboard light.
- */
- public static final int KEYBOARD_LIGHT = 0x00000001;
-
- /**
- * Flag to turn on and off the screen backlight.
- */
- public static final int SCREEN_LIGHT = 0x00000002;
-
- /**
- * Flag to turn on and off the button backlight.
- */
- public static final int BUTTON_LIGHT = 0x00000004;
-
- /**
- * Flags to turn on and off all the backlights.
- */
- public static final int ALL_LIGHTS = (KEYBOARD_LIGHT|SCREEN_LIGHT|BUTTON_LIGHT);
-
- /**
- * Brightness value for fully off
- */
- public static final int BRIGHTNESS_OFF = 0;
-
- /**
- * Brightness value for dim backlight
- */
- public static final int BRIGHTNESS_DIM = 20;
-
- /**
- * Brightness value for fully on
- */
- public static final int BRIGHTNESS_ON = 255;
-
- /**
- * Brightness value to use when battery is low
- */
- public static final int BRIGHTNESS_LOW_BATTERY = 10;
-
- /**
- * Threshold for BRIGHTNESS_LOW_BATTERY (percentage)
- * Screen will stay dim if battery level is <= LOW_BATTERY_THRESHOLD
- */
- public static final int LOW_BATTERY_THRESHOLD = 10;
-
- /**
- * Set the brightness for one or more lights
- *
- * @param mask flags indicating which lights to change brightness
- * @param brightness new brightness value (0 = off, 255 = fully bright)
- */
- public static native int setLightBrightness(int mask, int brightness);
-
- /**
- * Turn the screen on or off
- *
- * @param on Whether you want the screen on or off
- */
- public static native int setScreenState(boolean on);
-
- public static native int setLastUserActivityTimeout(long ms);
-
- /**
- * Turn the device off.
- *
- * This method is considered deprecated in favor of
- * {@link android.policy.ShutdownThread.shutdownAfterDisablingRadio()}.
- *
- * @deprecated
- * @hide
- */
- @Deprecated
- public static native void shutdown();
-
- /**
- * Reboot the device.
- * @param reason code to pass to the kernel (e.g. "recovery"), or null.
- *
- * @throws IOException if reboot fails for some reason (eg, lack of
- * permission)
- */
- public static native void reboot(String reason) throws IOException;
-}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
deleted file mode 100644
index bfcf2fc..0000000
--- a/core/java/android/os/PowerManager.java
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.util.Log;
-
-import com.android.internal.os.RuntimeInit;
-
-/**
- * This class gives you control of the power state of the device.
- *
- * <p><b>Device battery life will be significantly affected by the use of this API.</b> Do not
- * acquire WakeLocks unless you really need them, use the minimum levels possible, and be sure
- * to release it as soon as you can.
- *
- * <p>You can obtain an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- *
- * <p>The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}. This will
- * create a {@link PowerManager.WakeLock} object. You can then use methods on this object to
- * control the power state of the device. In practice it's quite simple:
- *
- * {@samplecode
- * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
- * PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
- * wl.acquire();
- * ..screen will stay on during this section..
- * wl.release();
- * }
- *
- * <p>The following flags are defined, with varying effects on system power. <i>These flags are
- * mutually exclusive - you may only specify one of them.</i>
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
- *
- * <thead>
- * <tr><th>Flag Value</th>
- * <th>CPU</th> <th>Screen</th> <th>Keyboard</th></tr>
- * </thead>
- *
- * <tbody>
- * <tr><th>{@link #PARTIAL_WAKE_LOCK}</th>
- * <td>On*</td> <td>Off</td> <td>Off</td>
- * </tr>
- *
- * <tr><th>{@link #SCREEN_DIM_WAKE_LOCK}</th>
- * <td>On</td> <td>Dim</td> <td>Off</td>
- * </tr>
- *
- * <tr><th>{@link #SCREEN_BRIGHT_WAKE_LOCK}</th>
- * <td>On</td> <td>Bright</td> <td>Off</td>
- * </tr>
- *
- * <tr><th>{@link #FULL_WAKE_LOCK}</th>
- * <td>On</td> <td>Bright</td> <td>Bright</td>
- * </tr>
- * </tbody>
- * </table>
- *
- * <p>*<i>If you hold a partial wakelock, the CPU will continue to run, irrespective of any timers
- * and even after the user presses the power button. In all other wakelocks, the CPU will run, but
- * the user can still put the device to sleep using the power button.</i>
- *
- * <p>In addition, you can add two more flags, which affect behavior of the screen only. <i>These
- * flags have no effect when combined with a {@link #PARTIAL_WAKE_LOCK}.</i>
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
- *
- * <thead>
- * <tr><th>Flag Value</th> <th>Description</th></tr>
- * </thead>
- *
- * <tbody>
- * <tr><th>{@link #ACQUIRE_CAUSES_WAKEUP}</th>
- * <td>Normal wake locks don't actually turn on the illumination. Instead, they cause
- * the illumination to remain on once it turns on (e.g. from user activity). This flag
- * will force the screen and/or keyboard to turn on immediately, when the WakeLock is
- * acquired. A typical use would be for notifications which are important for the user to
- * see immediately.</td>
- * </tr>
- *
- * <tr><th>{@link #ON_AFTER_RELEASE}</th>
- * <td>If this flag is set, the user activity timer will be reset when the WakeLock is
- * released, causing the illumination to remain on a bit longer. This can be used to
- * reduce flicker if you are cycling between wake lock conditions.</td>
- * </tr>
- * </tbody>
- * </table>
- *
- *
- */
-public class PowerManager
-{
- private static final String TAG = "PowerManager";
-
- /**
- * These internal values define the underlying power elements that we might
- * want to control individually. Eventually we'd like to expose them.
- */
- private static final int WAKE_BIT_CPU_STRONG = 1;
- private static final int WAKE_BIT_CPU_WEAK = 2;
- private static final int WAKE_BIT_SCREEN_DIM = 4;
- private static final int WAKE_BIT_SCREEN_BRIGHT = 8;
- private static final int WAKE_BIT_KEYBOARD_BRIGHT = 16;
-
- private static final int LOCK_MASK = WAKE_BIT_CPU_STRONG
- | WAKE_BIT_CPU_WEAK
- | WAKE_BIT_SCREEN_DIM
- | WAKE_BIT_SCREEN_BRIGHT
- | WAKE_BIT_KEYBOARD_BRIGHT;
-
- /**
- * Wake lock that ensures that the CPU is running. The screen might
- * not be on.
- */
- public static final int PARTIAL_WAKE_LOCK = WAKE_BIT_CPU_STRONG;
-
- /**
- * Wake lock that ensures that the screen and keyboard are on at
- * full brightness.
- */
- public static final int FULL_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT
- | WAKE_BIT_KEYBOARD_BRIGHT;
-
- /**
- * Wake lock that ensures that the screen is on at full brightness;
- * the keyboard backlight will be allowed to go off.
- */
- public static final int SCREEN_BRIGHT_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT;
-
- /**
- * Wake lock that ensures that the screen is on (but may be dimmed);
- * the keyboard backlight will be allowed to go off.
- */
- public static final int SCREEN_DIM_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_DIM;
-
- /**
- * Normally wake locks don't actually wake the device, they just cause
- * it to remain on once it's already on. Think of the video player
- * app as the normal behavior. Notifications that pop up and want
- * the device to be on are the exception; use this flag to be like them.
- * <p>
- * Does not work with PARTIAL_WAKE_LOCKs.
- */
- public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;
-
- /**
- * When this wake lock is released, poke the user activity timer
- * so the screen stays on for a little longer.
- * <p>
- * Will not turn the screen on if it is not already on. See {@link #ACQUIRE_CAUSES_WAKEUP}
- * if you want that.
- * <p>
- * Does not work with PARTIAL_WAKE_LOCKs.
- */
- public static final int ON_AFTER_RELEASE = 0x20000000;
-
- /**
- * Class lets you say that you need to have the device on.
- *
- * <p>Call release when you are done and don't need the lock anymore.
- */
- public class WakeLock
- {
- static final int RELEASE_WAKE_LOCK = 1;
-
- Runnable mReleaser = new Runnable() {
- public void run() {
- release();
- }
- };
-
- int mFlags;
- String mTag;
- IBinder mToken;
- int mCount = 0;
- boolean mRefCounted = true;
- boolean mHeld = false;
-
- WakeLock(int flags, String tag)
- {
- switch (flags & LOCK_MASK) {
- case PARTIAL_WAKE_LOCK:
- case SCREEN_DIM_WAKE_LOCK:
- case SCREEN_BRIGHT_WAKE_LOCK:
- case FULL_WAKE_LOCK:
- break;
- default:
- throw new IllegalArgumentException();
- }
-
- mFlags = flags;
- mTag = tag;
- mToken = new Binder();
- }
-
- /**
- * Sets whether this WakeLock is ref counted.
- *
- * @param value true for ref counted, false for not ref counted.
- */
- public void setReferenceCounted(boolean value)
- {
- mRefCounted = value;
- }
-
- /**
- * Makes sure the device is on at the level you asked when you created
- * the wake lock.
- */
- public void acquire()
- {
- synchronized (mToken) {
- if (!mRefCounted || mCount++ == 0) {
- try {
- mService.acquireWakeLock(mFlags, mToken, mTag);
- } catch (RemoteException e) {
- }
- mHeld = true;
- }
- }
- }
-
- /**
- * Makes sure the device is on at the level you asked when you created
- * the wake lock. The lock will be released after the given timeout.
- *
- * @param timeout Release the lock after the give timeout in milliseconds.
- */
- public void acquire(long timeout) {
- acquire();
- mHandler.postDelayed(mReleaser, timeout);
- }
-
-
- /**
- * Release your claim to the CPU or screen being on.
- *
- * <p>
- * It may turn off shortly after you release it, or it may not if there
- * are other wake locks held.
- */
- public void release()
- {
- synchronized (mToken) {
- if (!mRefCounted || --mCount == 0) {
- try {
- mService.releaseWakeLock(mToken);
- } catch (RemoteException e) {
- }
- mHeld = false;
- }
- if (mCount < 0) {
- throw new RuntimeException("WakeLock under-locked " + mTag);
- }
- }
- }
-
- public boolean isHeld()
- {
- synchronized (mToken) {
- return mHeld;
- }
- }
-
- public String toString() {
- synchronized (mToken) {
- return "WakeLock{"
- + Integer.toHexString(System.identityHashCode(this))
- + " held=" + mHeld + ", refCount=" + mCount + "}";
- }
- }
-
- @Override
- protected void finalize() throws Throwable
- {
- synchronized (mToken) {
- if (mHeld) {
- try {
- mService.releaseWakeLock(mToken);
- } catch (RemoteException e) {
- }
- RuntimeInit.crash(TAG, new Exception(
- "WakeLock finalized while still held: "+mTag));
- }
- }
- }
- }
-
- /**
- * Get a wake lock at the level of the flags parameter. Call
- * {@link WakeLock#acquire() acquire()} on the object to acquire the
- * wake lock, and {@link WakeLock#release release()} when you are done.
- *
- * {@samplecode
- *PowerManager pm = (PowerManager)mContext.getSystemService(
- * Context.POWER_SERVICE);
- *PowerManager.WakeLock wl = pm.newWakeLock(
- * PowerManager.SCREEN_DIM_WAKE_LOCK
- * | PowerManager.ON_AFTER_RELEASE,
- * TAG);
- *wl.acquire();
- * // ...
- *wl.release();
- * }
- *
- * @param flags Combination of flag values defining the requested behavior of the WakeLock.
- * @param tag Your class name (or other tag) for debugging purposes.
- *
- * @see WakeLock#acquire()
- * @see WakeLock#release()
- */
- public WakeLock newWakeLock(int flags, String tag)
- {
- return new WakeLock(flags, tag);
- }
-
- /**
- * User activity happened.
- * <p>
- * Turns the device from whatever state it's in to full on, and resets
- * the auto-off timer.
- *
- * @param when is used to order this correctly with the wake lock calls.
- * This time should be in the {@link SystemClock#uptimeMillis
- * SystemClock.uptimeMillis()} time base.
- * @param noChangeLights should be true if you don't want the lights to
- * turn on because of this event. This is set when the power
- * key goes down. We want the device to stay on while the button
- * is down, but we're about to turn off. Otherwise the lights
- * flash on and then off and it looks weird.
- */
- public void userActivity(long when, boolean noChangeLights)
- {
- try {
- mService.userActivity(when, noChangeLights);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Force the device to go to sleep. Overrides all the wake locks that are
- * held.
- *
- * @param time is used to order this correctly with the wake lock calls.
- * The time should be in the {@link SystemClock#uptimeMillis
- * SystemClock.uptimeMillis()} time base.
- */
- public void goToSleep(long time)
- {
- try {
- mService.goToSleep(time);
- } catch (RemoteException e) {
- }
- }
-
- private PowerManager()
- {
- }
-
- /**
- * {@hide}
- */
- public PowerManager(IPowerManager service, Handler handler)
- {
- mService = service;
- mHandler = handler;
- }
-
- /**
- * TODO: It would be nice to be able to set the poke lock here,
- * but I'm not sure what would be acceptable as an interface -
- * either a PokeLock object (like WakeLock) or, possibly just a
- * method call to set the poke lock.
- */
-
- IPowerManager mService;
- Handler mHandler;
-}
-
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
deleted file mode 100644
index cd86fbe..0000000
--- a/core/java/android/os/Process.java
+++ /dev/null
@@ -1,706 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.net.LocalSocketAddress;
-import android.net.LocalSocket;
-import android.util.Log;
-import dalvik.system.Zygote;
-
-import java.io.BufferedWriter;
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.util.ArrayList;
-
-/*package*/ class ZygoteStartFailedEx extends Exception {
- /**
- * Something prevented the zygote process startup from happening normally
- */
-
- ZygoteStartFailedEx() {};
- ZygoteStartFailedEx(String s) {super(s);}
- ZygoteStartFailedEx(Throwable cause) {super(cause);}
-}
-
-/**
- * Tools for managing OS processes.
- */
-public class Process {
- private static final String LOG_TAG = "Process";
-
- private static final String ZYGOTE_SOCKET = "zygote";
-
- /**
- * Name of a process for running the platform's media services.
- * {@hide}
- */
- public static final String ANDROID_SHARED_MEDIA = "com.android.process.media";
-
- /**
- * Name of the process that Google content providers can share.
- * {@hide}
- */
- public static final String GOOGLE_SHARED_APP_CONTENT = "com.google.process.content";
-
- /**
- * Defines the UID/GID under which system code runs.
- */
- public static final int SYSTEM_UID = 1000;
-
- /**
- * Defines the UID/GID under which the telephony code runs.
- */
- public static final int PHONE_UID = 1001;
-
- /**
- * Defines the start of a range of UIDs (and GIDs), going from this
- * number to {@link #LAST_APPLICATION_UID} that are reserved for assigning
- * to applications.
- */
- public static final int FIRST_APPLICATION_UID = 10000;
- /**
- * Last of application-specific UIDs starting at
- * {@link #FIRST_APPLICATION_UID}.
- */
- public static final int LAST_APPLICATION_UID = 99999;
-
- /**
- * Defines a secondary group id for access to the bluetooth hardware.
- */
- public static final int BLUETOOTH_GID = 2000;
-
- /**
- * Standard priority of application threads.
- * Use with {@link #setThreadPriority(int)} and
- * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
- * {@link java.lang.Thread} class.
- */
- public static final int THREAD_PRIORITY_DEFAULT = 0;
-
- /*
- * ***************************************
- * ** Keep in sync with utils/threads.h **
- * ***************************************
- */
-
- /**
- * Lowest available thread priority. Only for those who really, really
- * don't want to run if anything else is happening.
- * Use with {@link #setThreadPriority(int)} and
- * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
- * {@link java.lang.Thread} class.
- */
- public static final int THREAD_PRIORITY_LOWEST = 19;
-
- /**
- * Standard priority background threads. This gives your thread a slightly
- * lower than normal priority, so that it will have less chance of impacting
- * the responsiveness of the user interface.
- * Use with {@link #setThreadPriority(int)} and
- * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
- * {@link java.lang.Thread} class.
- */
- public static final int THREAD_PRIORITY_BACKGROUND = 10;
-
- /**
- * Standard priority of threads that are currently running a user interface
- * that the user is interacting with. Applications can not normally
- * change to this priority; the system will automatically adjust your
- * application threads as the user moves through the UI.
- * Use with {@link #setThreadPriority(int)} and
- * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
- * {@link java.lang.Thread} class.
- */
- public static final int THREAD_PRIORITY_FOREGROUND = -2;
-
- /**
- * Standard priority of system display threads, involved in updating
- * the user interface. Applications can not
- * normally change to this priority.
- * Use with {@link #setThreadPriority(int)} and
- * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
- * {@link java.lang.Thread} class.
- */
- public static final int THREAD_PRIORITY_DISPLAY = -4;
-
- /**
- * Standard priority of the most important display threads, for compositing
- * the screen and retrieving input events. Applications can not normally
- * change to this priority.
- * Use with {@link #setThreadPriority(int)} and
- * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
- * {@link java.lang.Thread} class.
- */
- public static final int THREAD_PRIORITY_URGENT_DISPLAY = -8;
-
- /**
- * Standard priority of audio threads. Applications can not normally
- * change to this priority.
- * Use with {@link #setThreadPriority(int)} and
- * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
- * {@link java.lang.Thread} class.
- */
- public static final int THREAD_PRIORITY_AUDIO = -16;
-
- /**
- * Standard priority of the most important audio threads.
- * Applications can not normally change to this priority.
- * Use with {@link #setThreadPriority(int)} and
- * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
- * {@link java.lang.Thread} class.
- */
- public static final int THREAD_PRIORITY_URGENT_AUDIO = -19;
-
- /**
- * Minimum increment to make a priority more favorable.
- */
- public static final int THREAD_PRIORITY_MORE_FAVORABLE = -1;
-
- /**
- * Minimum increment to make a priority less favorable.
- */
- public static final int THREAD_PRIORITY_LESS_FAVORABLE = +1;
-
- public static final int SIGNAL_QUIT = 3;
- public static final int SIGNAL_KILL = 9;
- public static final int SIGNAL_USR1 = 10;
-
- // State for communicating with zygote process
-
- static LocalSocket sZygoteSocket;
- static DataInputStream sZygoteInputStream;
- static BufferedWriter sZygoteWriter;
-
- /** true if previous zygote open failed */
- static boolean sPreviousZygoteOpenFailed;
-
- /**
- * Start a new process.
- *
- * <p>If processes are enabled, a new process is created and the
- * static main() function of a <var>processClass</var> is executed there.
- * The process will continue running after this function returns.
- *
- * <p>If processes are not enabled, a new thread in the caller's
- * process is created and main() of <var>processClass</var> called there.
- *
- * <p>The niceName parameter, if not an empty string, is a custom name to
- * give to the process instead of using processClass. This allows you to
- * make easily identifyable processes even if you are using the same base
- * <var>processClass</var> to start them.
- *
- * @param processClass The class to use as the process's main entry
- * point.
- * @param niceName A more readable name to use for the process.
- * @param uid The user-id under which the process will run.
- * @param gid The group-id under which the process will run.
- * @param gids Additional group-ids associated with the process.
- * @param enableDebugger True if debugging should be enabled for this process.
- * @param zygoteArgs Additional arguments to supply to the zygote process.
- *
- * @return int If > 0 the pid of the new process; if 0 the process is
- * being emulated by a thread
- * @throws RuntimeException on fatal start failure
- *
- * {@hide}
- */
- public static final int start(final String processClass,
- final String niceName,
- int uid, int gid, int[] gids,
- int debugFlags,
- String[] zygoteArgs)
- {
- if (supportsProcesses()) {
- try {
- return startViaZygote(processClass, niceName, uid, gid, gids,
- debugFlags, zygoteArgs);
- } catch (ZygoteStartFailedEx ex) {
- Log.e(LOG_TAG,
- "Starting VM process through Zygote failed");
- throw new RuntimeException(
- "Starting VM process through Zygote failed", ex);
- }
- } else {
- // Running in single-process mode
-
- Runnable runnable = new Runnable() {
- public void run() {
- Process.invokeStaticMain(processClass);
- }
- };
-
- // Thread constructors must not be called with null names (see spec).
- if (niceName != null) {
- new Thread(runnable, niceName).start();
- } else {
- new Thread(runnable).start();
- }
-
- return 0;
- }
- }
-
- /**
- * Start a new process. Don't supply a custom nice name.
- * {@hide}
- */
- public static final int start(String processClass, int uid, int gid,
- int[] gids, int debugFlags, String[] zygoteArgs) {
- return start(processClass, "", uid, gid, gids,
- debugFlags, zygoteArgs);
- }
-
- private static void invokeStaticMain(String className) {
- Class cl;
- Object args[] = new Object[1];
-
- args[0] = new String[0]; //this is argv
-
- try {
- cl = Class.forName(className);
- cl.getMethod("main", new Class[] { String[].class })
- .invoke(null, args);
- } catch (Exception ex) {
- // can be: ClassNotFoundException,
- // NoSuchMethodException, SecurityException,
- // IllegalAccessException, IllegalArgumentException
- // InvocationTargetException
- // or uncaught exception from main()
-
- Log.e(LOG_TAG, "Exception invoking static main on "
- + className, ex);
-
- throw new RuntimeException(ex);
- }
-
- }
-
- /** retry interval for opening a zygote socket */
- static final int ZYGOTE_RETRY_MILLIS = 500;
-
- /**
- * Tries to open socket to Zygote process if not already open. If
- * already open, does nothing. May block and retry.
- */
- private static void openZygoteSocketIfNeeded()
- throws ZygoteStartFailedEx {
-
- int retryCount;
-
- if (sPreviousZygoteOpenFailed) {
- /*
- * If we've failed before, expect that we'll fail again and
- * don't pause for retries.
- */
- retryCount = 0;
- } else {
- retryCount = 10;
- }
-
- /*
- * See bug #811181: Sometimes runtime can make it up before zygote.
- * Really, we'd like to do something better to avoid this condition,
- * but for now just wait a bit...
- */
- for (int retry = 0
- ; (sZygoteSocket == null) && (retry < (retryCount + 1))
- ; retry++ ) {
-
- if (retry > 0) {
- try {
- Log.i("Zygote", "Zygote not up yet, sleeping...");
- Thread.sleep(ZYGOTE_RETRY_MILLIS);
- } catch (InterruptedException ex) {
- // should never happen
- }
- }
-
- try {
- sZygoteSocket = new LocalSocket();
-
- sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,
- LocalSocketAddress.Namespace.RESERVED));
-
- sZygoteInputStream
- = new DataInputStream(sZygoteSocket.getInputStream());
-
- sZygoteWriter =
- new BufferedWriter(
- new OutputStreamWriter(
- sZygoteSocket.getOutputStream()),
- 256);
-
- Log.i("Zygote", "Process: zygote socket opened");
-
- sPreviousZygoteOpenFailed = false;
- break;
- } catch (IOException ex) {
- if (sZygoteSocket != null) {
- try {
- sZygoteSocket.close();
- } catch (IOException ex2) {
- Log.e(LOG_TAG,"I/O exception on close after exception",
- ex2);
- }
- }
-
- sZygoteSocket = null;
- }
- }
-
- if (sZygoteSocket == null) {
- sPreviousZygoteOpenFailed = true;
- throw new ZygoteStartFailedEx("connect failed");
- }
- }
-
- /**
- * Sends an argument list to the zygote process, which starts a new child
- * and returns the child's pid. Please note: the present implementation
- * replaces newlines in the argument list with spaces.
- * @param args argument list
- * @return PID of new child process
- * @throws ZygoteStartFailedEx if process start failed for any reason
- */
- private static int zygoteSendArgsAndGetPid(ArrayList<String> args)
- throws ZygoteStartFailedEx {
-
- int pid;
-
- openZygoteSocketIfNeeded();
-
- try {
- /**
- * See com.android.internal.os.ZygoteInit.readArgumentList()
- * Presently the wire format to the zygote process is:
- * a) a count of arguments (argc, in essence)
- * b) a number of newline-separated argument strings equal to count
- *
- * After the zygote process reads these it will write the pid of
- * the child or -1 on failure.
- */
-
- sZygoteWriter.write(Integer.toString(args.size()));
- sZygoteWriter.newLine();
-
- int sz = args.size();
- for (int i = 0; i < sz; i++) {
- String arg = args.get(i);
- if (arg.indexOf('\n') >= 0) {
- throw new ZygoteStartFailedEx(
- "embedded newlines not allowed");
- }
- sZygoteWriter.write(arg);
- sZygoteWriter.newLine();
- }
-
- sZygoteWriter.flush();
-
- // Should there be a timeout on this?
- pid = sZygoteInputStream.readInt();
-
- if (pid < 0) {
- throw new ZygoteStartFailedEx("fork() failed");
- }
- } catch (IOException ex) {
- try {
- if (sZygoteSocket != null) {
- sZygoteSocket.close();
- }
- } catch (IOException ex2) {
- // we're going to fail anyway
- Log.e(LOG_TAG,"I/O exception on routine close", ex2);
- }
-
- sZygoteSocket = null;
-
- throw new ZygoteStartFailedEx(ex);
- }
-
- return pid;
- }
-
- /**
- * Starts a new process via the zygote mechanism.
- *
- * @param processClass Class name whose static main() to run
- * @param niceName 'nice' process name to appear in ps
- * @param uid a POSIX uid that the new process should setuid() to
- * @param gid a POSIX gid that the new process shuold setgid() to
- * @param gids null-ok; a list of supplementary group IDs that the
- * new process should setgroup() to.
- * @param enableDebugger True if debugging should be enabled for this process.
- * @param extraArgs Additional arguments to supply to the zygote process.
- * @return PID
- * @throws ZygoteStartFailedEx if process start failed for any reason
- */
- private static int startViaZygote(final String processClass,
- final String niceName,
- final int uid, final int gid,
- final int[] gids,
- int debugFlags,
- String[] extraArgs)
- throws ZygoteStartFailedEx {
- int pid;
-
- synchronized(Process.class) {
- ArrayList<String> argsForZygote = new ArrayList<String>();
-
- // --runtime-init, --setuid=, --setgid=,
- // and --setgroups= must go first
- argsForZygote.add("--runtime-init");
- argsForZygote.add("--setuid=" + uid);
- argsForZygote.add("--setgid=" + gid);
- if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
- argsForZygote.add("--enable-debugger");
- }
- if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
- argsForZygote.add("--enable-checkjni");
- }
- if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
- argsForZygote.add("--enable-assert");
- }
-
- //TODO optionally enable debuger
- //argsForZygote.add("--enable-debugger");
-
- // --setgroups is a comma-separated list
- if (gids != null && gids.length > 0) {
- StringBuilder sb = new StringBuilder();
- sb.append("--setgroups=");
-
- int sz = gids.length;
- for (int i = 0; i < sz; i++) {
- if (i != 0) {
- sb.append(',');
- }
- sb.append(gids[i]);
- }
-
- argsForZygote.add(sb.toString());
- }
-
- if (niceName != null) {
- argsForZygote.add("--nice-name=" + niceName);
- }
-
- argsForZygote.add(processClass);
-
- if (extraArgs != null) {
- for (String arg : extraArgs) {
- argsForZygote.add(arg);
- }
- }
-
- pid = zygoteSendArgsAndGetPid(argsForZygote);
- }
-
- if (pid <= 0) {
- throw new ZygoteStartFailedEx("zygote start failed:" + pid);
- }
-
- return pid;
- }
-
- /**
- * Returns elapsed milliseconds of the time this process has run.
- * @return Returns the number of milliseconds this process has return.
- */
- public static final native long getElapsedCpuTime();
-
- /**
- * Returns the identifier of this process, which can be used with
- * {@link #killProcess} and {@link #sendSignal}.
- */
- public static final native int myPid();
-
- /**
- * Returns the identifier of the calling thread, which be used with
- * {@link #setThreadPriority(int, int)}.
- */
- public static final native int myTid();
-
- /**
- * Returns the identifier of this process's user.
- */
- public static final native int myUid();
-
- /**
- * Returns the UID assigned to a particular user name, or -1 if there is
- * none. If the given string consists of only numbers, it is converted
- * directly to a uid.
- */
- public static final native int getUidForName(String name);
-
- /**
- * Returns the GID assigned to a particular user name, or -1 if there is
- * none. If the given string consists of only numbers, it is converted
- * directly to a gid.
- */
- public static final native int getGidForName(String name);
-
- /**
- * Set the priority of a thread, based on Linux priorities.
- *
- * @param tid The identifier of the thread/process to change.
- * @param priority A Linux priority level, from -20 for highest scheduling
- * priority to 19 for lowest scheduling priority.
- *
- * @throws IllegalArgumentException Throws IllegalArgumentException if
- * <var>tid</var> does not exist.
- * @throws SecurityException Throws SecurityException if your process does
- * not have permission to modify the given thread, or to use the given
- * priority.
- */
- public static final native void setThreadPriority(int tid, int priority)
- throws IllegalArgumentException, SecurityException;
-
- /**
- * Set the priority of the calling thread, based on Linux priorities. See
- * {@link #setThreadPriority(int, int)} for more information.
- *
- * @param priority A Linux priority level, from -20 for highest scheduling
- * priority to 19 for lowest scheduling priority.
- *
- * @throws IllegalArgumentException Throws IllegalArgumentException if
- * <var>tid</var> does not exist.
- * @throws SecurityException Throws SecurityException if your process does
- * not have permission to modify the given thread, or to use the given
- * priority.
- *
- * @see #setThreadPriority(int, int)
- */
- public static final native void setThreadPriority(int priority)
- throws IllegalArgumentException, SecurityException;
-
- /**
- * Return the current priority of a thread, based on Linux priorities.
- *
- * @param tid The identifier of the thread/process to change.
- *
- * @return Returns the current priority, as a Linux priority level,
- * from -20 for highest scheduling priority to 19 for lowest scheduling
- * priority.
- *
- * @throws IllegalArgumentException Throws IllegalArgumentException if
- * <var>tid</var> does not exist.
- */
- public static final native int getThreadPriority(int tid)
- throws IllegalArgumentException;
-
- /**
- * Determine whether the current environment supports multiple processes.
- *
- * @return Returns true if the system can run in multiple processes, else
- * false if everything is running in a single process.
- */
- public static final native boolean supportsProcesses();
-
- /**
- * Set the out-of-memory badness adjustment for a process.
- *
- * @param pid The process identifier to set.
- * @param amt Adjustment value -- linux allows -16 to +15.
- *
- * @return Returns true if the underlying system supports this
- * feature, else false.
- *
- * {@hide}
- */
- public static final native boolean setOomAdj(int pid, int amt);
-
- /**
- * Change this process's argv[0] parameter. This can be useful to show
- * more descriptive information in things like the 'ps' command.
- *
- * @param text The new name of this process.
- *
- * {@hide}
- */
- public static final native void setArgV0(String text);
-
- /**
- * Kill the process with the given PID.
- * Note that, though this API allows us to request to
- * kill any process based on its PID, the kernel will
- * still impose standard restrictions on which PIDs you
- * are actually able to kill. Typically this means only
- * the process running the caller's packages/application
- * and any additional processes created by that app; packages
- * sharing a common UID will also be able to kill each
- * other's processes.
- */
- public static final void killProcess(int pid) {
- sendSignal(pid, SIGNAL_KILL);
- }
-
- /** @hide */
- public static final native int setUid(int uid);
-
- /** @hide */
- public static final native int setGid(int uid);
-
- /**
- * Send a signal to the given process.
- *
- * @param pid The pid of the target process.
- * @param signal The signal to send.
- */
- public static final native void sendSignal(int pid, int signal);
-
- /** @hide */
- public static final native int getFreeMemory();
-
- /** @hide */
- public static final native void readProcLines(String path,
- String[] reqFields, long[] outSizes);
-
- /** @hide */
- public static final native int[] getPids(String path, int[] lastArray);
-
- /** @hide */
- public static final int PROC_TERM_MASK = 0xff;
- /** @hide */
- public static final int PROC_ZERO_TERM = 0;
- /** @hide */
- public static final int PROC_SPACE_TERM = (int)' ';
- /** @hide */
- public static final int PROC_COMBINE = 0x100;
- /** @hide */
- public static final int PROC_PARENS = 0x200;
- /** @hide */
- public static final int PROC_OUT_STRING = 0x1000;
- /** @hide */
- public static final int PROC_OUT_LONG = 0x2000;
- /** @hide */
- public static final int PROC_OUT_FLOAT = 0x4000;
-
- /** @hide */
- public static final native boolean readProcFile(String file, int[] format,
- String[] outStrings, long[] outLongs, float[] outFloats);
-
- /**
- * Gets the total Pss value for a given process, in bytes.
- *
- * @param pid the process to the Pss for
- * @return the total Pss value for the given process in bytes,
- * or -1 if the value cannot be determined
- * @hide
- */
- public static final native long getPss(int pid);
-}
diff --git a/core/java/android/os/Registrant.java b/core/java/android/os/Registrant.java
deleted file mode 100644
index c1780b9..0000000
--- a/core/java/android/os/Registrant.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.os.Handler;
-import android.os.Message;
-
-import java.lang.ref.WeakReference;
-import java.util.HashMap;
-
-/** @hide */
-public class Registrant
-{
- public
- Registrant(Handler h, int what, Object obj)
- {
- refH = new WeakReference(h);
- this.what = what;
- userObj = obj;
- }
-
- public void
- clear()
- {
- refH = null;
- userObj = null;
- }
-
- public void
- notifyRegistrant()
- {
- internalNotifyRegistrant (null, null);
- }
-
- public void
- notifyResult(Object result)
- {
- internalNotifyRegistrant (result, null);
- }
-
- public void
- notifyException(Throwable exception)
- {
- internalNotifyRegistrant (null, exception);
- }
-
- /**
- * This makes a copy of @param ar
- */
- public void
- notifyRegistrant(AsyncResult ar)
- {
- internalNotifyRegistrant (ar.result, ar.exception);
- }
-
- /*package*/ void
- internalNotifyRegistrant (Object result, Throwable exception)
- {
- Handler h = getHandler();
-
- if (h == null) {
- clear();
- } else {
- Message msg = Message.obtain();
-
- msg.what = what;
-
- msg.obj = new AsyncResult(userObj, result, exception);
-
- h.sendMessage(msg);
- }
- }
-
- /**
- * NOTE: May return null if weak reference has been collected
- */
-
- public Message
- messageForRegistrant()
- {
- Handler h = getHandler();
-
- if (h == null) {
- clear();
-
- return null;
- } else {
- Message msg = h.obtainMessage();
-
- msg.what = what;
- msg.obj = userObj;
-
- return msg;
- }
- }
-
- public Handler
- getHandler()
- {
- if (refH == null)
- return null;
-
- return (Handler) refH.get();
- }
-
- WeakReference refH;
- int what;
- Object userObj;
-}
-
diff --git a/core/java/android/os/RegistrantList.java b/core/java/android/os/RegistrantList.java
deleted file mode 100644
index 56b9e2b..0000000
--- a/core/java/android/os/RegistrantList.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.os.Handler;
-import android.os.Message;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-/** @hide */
-public class RegistrantList
-{
- ArrayList registrants = new ArrayList(); // of Registrant
-
- public synchronized void
- add(Handler h, int what, Object obj)
- {
- add(new Registrant(h, what, obj));
- }
-
- public synchronized void
- addUnique(Handler h, int what, Object obj)
- {
- // if the handler is already in the registrant list, remove it
- remove(h);
- add(new Registrant(h, what, obj));
- }
-
- public synchronized void
- add(Registrant r)
- {
- removeCleared();
- registrants.add(r);
- }
-
- public synchronized void
- removeCleared()
- {
- for (int i = registrants.size() - 1; i >= 0 ; i--) {
- Registrant r = (Registrant) registrants.get(i);
-
- if (r.refH == null) {
- registrants.remove(i);
- }
- }
- }
-
- public synchronized int
- size()
- {
- return registrants.size();
- }
-
- public synchronized Object
- get(int index)
- {
- return registrants.get(index);
- }
-
- private synchronized void
- internalNotifyRegistrants (Object result, Throwable exception)
- {
- for (int i = 0, s = registrants.size(); i < s ; i++) {
- Registrant r = (Registrant) registrants.get(i);
- r.internalNotifyRegistrant(result, exception);
- }
- }
-
- public /*synchronized*/ void
- notifyRegistrants()
- {
- internalNotifyRegistrants(null, null);
- }
-
- public /*synchronized*/ void
- notifyException(Throwable exception)
- {
- internalNotifyRegistrants (null, exception);
- }
-
- public /*synchronized*/ void
- notifyResult(Object result)
- {
- internalNotifyRegistrants (result, null);
- }
-
-
- public /*synchronized*/ void
- notifyRegistrants(AsyncResult ar)
- {
- internalNotifyRegistrants(ar.result, ar.exception);
- }
-
- public synchronized void
- remove(Handler h)
- {
- for (int i = 0, s = registrants.size() ; i < s ; i++) {
- Registrant r = (Registrant) registrants.get(i);
- Handler rh;
-
- rh = r.getHandler();
-
- /* Clean up both the requested registrant and
- * any now-collected registrants
- */
- if (rh == null || rh == h) {
- r.clear();
- }
- }
-
- removeCleared();
- }
-}
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
deleted file mode 100644
index 04e7ef0..0000000
--- a/core/java/android/os/RemoteCallbackList.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import java.util.HashMap;
-
-/**
- * Takes care of the grunt work of maintaining a list of remote interfaces,
- * typically for the use of performing callbacks from a
- * {@link android.app.Service} to its clients. In particular, this:
- *
- * <ul>
- * <li> Keeps track of a set of registered {@link IInterface} callbacks,
- * taking care to identify them through their underlying unique {@link IBinder}
- * (by calling {@link IInterface#asBinder IInterface.asBinder()}.
- * <li> Attaches a {@link IBinder.DeathRecipient IBinder.DeathRecipient} to
- * each registered interface, so that it can be cleaned out of the list if its
- * process goes away.
- * <li> Performs locking of the underlying list of interfaces to deal with
- * multithreaded incoming calls, and a thread-safe way to iterate over a
- * snapshot of the list without holding its lock.
- * </ul>
- *
- * <p>To use this class, simply create a single instance along with your
- * service, and call its {@link #register} and {@link #unregister} methods
- * as client register and unregister with your service. To call back on to
- * the registered clients, use {@link #beginBroadcast},
- * {@link #getBroadcastItem}, and {@link #finishBroadcast}.
- *
- * <p>If a registered callback's process goes away, this class will take
- * care of automatically removing it from the list. If you want to do
- * additional work in this situation, you can create a subclass that
- * implements the {@link #onCallbackDied} method.
- */
-public class RemoteCallbackList<E extends IInterface> {
- /*package*/ HashMap<IBinder, Callback> mCallbacks
- = new HashMap<IBinder, Callback>();
- private IInterface[] mActiveBroadcast;
- private boolean mKilled = false;
-
- private final class Callback implements IBinder.DeathRecipient {
- final E mCallback;
-
- Callback(E callback) {
- mCallback = callback;
- }
-
- public void binderDied() {
- synchronized (mCallbacks) {
- mCallbacks.remove(mCallback.asBinder());
- }
- onCallbackDied(mCallback);
- }
- }
-
- /**
- * Add a new callback to the list. This callback will remain in the list
- * until a corresponding call to {@link #unregister} or its hosting process
- * goes away. If the callback was already registered (determined by
- * checking to see if the {@link IInterface#asBinder callback.asBinder()}
- * object is already in the list), then it will be left as-is.
- * Registrations are not counted; a single call to {@link #unregister}
- * will remove a callback after any number calls to register it.
- *
- * @param callback The callback interface to be added to the list. Must
- * not be null -- passing null here will cause a NullPointerException.
- * Most services will want to check for null before calling this with
- * an object given from a client, so that clients can't crash the
- * service with bad data.
- *
- * @return Returns true if the callback was successfully added to the list.
- * Returns false if it was not added, either because {@link #kill} had
- * previously been called or the callback's process has gone away.
- *
- * @see #unregister
- * @see #kill
- * @see #onCallbackDied
- */
- public boolean register(E callback) {
- synchronized (mCallbacks) {
- if (mKilled) {
- return false;
- }
- IBinder binder = callback.asBinder();
- try {
- Callback cb = new Callback(callback);
- binder.linkToDeath(cb, 0);
- mCallbacks.put(binder, cb);
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
- }
-
- /**
- * Remove from the list a callback that was previously added with
- * {@link #register}. This uses the
- * {@link IInterface#asBinder callback.asBinder()} object to correctly
- * find the previous registration.
- * Registrations are not counted; a single unregister call will remove
- * a callback after any number calls to {@link #register} for it.
- *
- * @param callback The callback to be removed from the list. Passing
- * null here will cause a NullPointerException, so you will generally want
- * to check for null before calling.
- *
- * @return Returns true if the callback was found and unregistered. Returns
- * false if the given callback was not found on the list.
- *
- * @see #register
- */
- public boolean unregister(E callback) {
- synchronized (mCallbacks) {
- Callback cb = mCallbacks.remove(callback.asBinder());
- if (cb != null) {
- cb.mCallback.asBinder().unlinkToDeath(cb, 0);
- return true;
- }
- return false;
- }
- }
-
- /**
- * Disable this callback list. All registered callbacks are unregistered,
- * and the list is disabled so that future calls to {@link #register} will
- * fail. This should be used when a Service is stopping, to prevent clients
- * from registering callbacks after it is stopped.
- *
- * @see #register
- */
- public void kill() {
- synchronized (mCallbacks) {
- for (Callback cb : mCallbacks.values()) {
- cb.mCallback.asBinder().unlinkToDeath(cb, 0);
- }
- mCallbacks.clear();
- mKilled = true;
- }
- }
-
- /**
- * Called when the process hosting a callback in the list has gone away.
- * The default implementation does nothing.
- *
- * @param callback The callback whose process has died. Note that, since
- * its process has died, you can not make any calls on to this interface.
- * You can, however, retrieve its IBinder and compare it with another
- * IBinder to see if it is the same object.
- *
- * @see #register
- */
- public void onCallbackDied(E callback) {
- }
-
- /**
- * Prepare to start making calls to the currently registered callbacks.
- * This creates a copy of the callback list, which you can retrieve items
- * from using {@link #getBroadcastItem}. Note that only one broadcast can
- * be active at a time, so you must be sure to always call this from the
- * same thread (usually by scheduling with {@link Handler} or
- * do your own synchronization. You must call {@link #finishBroadcast}
- * when done.
- *
- * <p>A typical loop delivering a broadcast looks like this:
- *
- * <pre>
- * final int N = callbacks.beginBroadcast();
- * for (int i=0; i<N; i++) {
- * try {
- * callbacks.getBroadcastItem(i).somethingHappened();
- * } catch (RemoteException e) {
- * // The RemoteCallbackList will take care of removing
- * // the dead object for us.
- * }
- * }
- * callbacks.finishBroadcast();</pre>
- *
- * @return Returns the number of callbacks in the broadcast, to be used
- * with {@link #getBroadcastItem} to determine the range of indices you
- * can supply.
- *
- * @see #getBroadcastItem
- * @see #finishBroadcast
- */
- public int beginBroadcast() {
- synchronized (mCallbacks) {
- final int N = mCallbacks.size();
- if (N <= 0) {
- return 0;
- }
- IInterface[] active = mActiveBroadcast;
- if (active == null || active.length < N) {
- mActiveBroadcast = active = new IInterface[N];
- }
- int i=0;
- for (Callback cb : mCallbacks.values()) {
- active[i++] = cb.mCallback;
- }
- return N;
- }
- }
-
- /**
- * Retrieve an item in the active broadcast that was previously started
- * with {@link #beginBroadcast}. This can <em>only</em> be called after
- * the broadcast is started, and its data is no longer valid after
- * calling {@link #finishBroadcast}.
- *
- * <p>Note that it is possible for the process of one of the returned
- * callbacks to go away before you call it, so you will need to catch
- * {@link RemoteException} when calling on to the returned object.
- * The callback list itself, however, will take care of unregistering
- * these objects once it detects that it is no longer valid, so you can
- * handle such an exception by simply ignoring it.
- *
- * @param index Which of the registered callbacks you would like to
- * retrieve. Ranges from 0 to 1-{@link #beginBroadcast}.
- *
- * @return Returns the callback interface that you can call. This will
- * always be non-null.
- *
- * @see #beginBroadcast
- */
- public E getBroadcastItem(int index) {
- return (E)mActiveBroadcast[index];
- }
-
- /**
- * Clean up the state of a broadcast previously initiated by calling
- * {@link #beginBroadcast}. This must always be called when you are done
- * with a broadcast.
- *
- * @see #beginBroadcast
- */
- public void finishBroadcast() {
- IInterface[] active = mActiveBroadcast;
- if (active != null) {
- final int N = active.length;
- for (int i=0; i<N; i++) {
- active[i] = null;
- }
- }
- }
-}
diff --git a/core/java/android/os/RemoteException.java b/core/java/android/os/RemoteException.java
deleted file mode 100644
index 9d76156..0000000
--- a/core/java/android/os/RemoteException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-import android.util.AndroidException;
-
-/**
- * Parent exception for all Binder remote-invocation errors
- */
-public class RemoteException extends AndroidException {
- public RemoteException() {
- super();
- }
-}
diff --git a/core/java/android/os/RemoteMailException.java b/core/java/android/os/RemoteMailException.java
deleted file mode 100644
index 1ac96d1..0000000
--- a/core/java/android/os/RemoteMailException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/** @hide */
-public class RemoteMailException extends Exception
-{
- public RemoteMailException()
- {
- }
-
- public RemoteMailException(String s)
- {
- super(s);
- }
-}
-
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
deleted file mode 100644
index b721665..0000000
--- a/core/java/android/os/ServiceManager.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import com.android.internal.os.BinderInternal;
-
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/** @hide */
-public final class ServiceManager {
- private static final String TAG = "ServiceManager";
-
- private static IServiceManager sServiceManager;
- private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();
-
- private static IServiceManager getIServiceManager() {
- if (sServiceManager != null) {
- return sServiceManager;
- }
-
- // Find the service manager
- sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
- return sServiceManager;
- }
-
- /**
- * Returns a reference to a service with the given name.
- *
- * @param name the name of the service to get
- * @return a reference to the service, or <code>null</code> if the service doesn't exist
- */
- public static IBinder getService(String name) {
- try {
- IBinder service = sCache.get(name);
- if (service != null) {
- return service;
- } else {
- return getIServiceManager().getService(name);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "error in getService", e);
- }
- return null;
- }
-
- /**
- * Place a new @a service called @a name into the service
- * manager.
- *
- * @param name the name of the new service
- * @param service the service object
- */
- public static void addService(String name, IBinder service) {
- try {
- getIServiceManager().addService(name, service);
- } catch (RemoteException e) {
- Log.e(TAG, "error in addService", e);
- }
- }
-
- /**
- * Retrieve an existing service called @a name from the
- * service manager. Non-blocking.
- */
- public static IBinder checkService(String name) {
- try {
- IBinder service = sCache.get(name);
- if (service != null) {
- return service;
- } else {
- return getIServiceManager().checkService(name);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "error in checkService", e);
- return null;
- }
- }
-
- /**
- * Return a list of all currently running services.
- */
- public static String[] listServices() throws RemoteException {
- try {
- return getIServiceManager().listServices();
- } catch (RemoteException e) {
- Log.e(TAG, "error in listServices", e);
- return null;
- }
- }
-
- /**
- * This is only intended to be called when the process is first being brought
- * up and bound by the activity manager. There is only one thread in the process
- * at that time, so no locking is done.
- *
- * @param cache the cache of service references
- * @hide
- */
- public static void initServiceCache(Map<String, IBinder> cache) {
- if (sCache.size() != 0 && Process.supportsProcesses()) {
- throw new IllegalStateException("setServiceCache may only be called once");
- }
- sCache.putAll(cache);
- }
-}
diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java
deleted file mode 100644
index 2aab0e6..0000000
--- a/core/java/android/os/ServiceManagerNative.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-
-/**
- * Native implementation of the service manager. Most clients will only
- * care about getDefault() and possibly asInterface().
- * @hide
- */
-public abstract class ServiceManagerNative extends Binder implements IServiceManager
-{
- /**
- * Cast a Binder object into a service manager interface, generating
- * a proxy if needed.
- */
- static public IServiceManager asInterface(IBinder obj)
- {
- if (obj == null) {
- return null;
- }
- IServiceManager in =
- (IServiceManager)obj.queryLocalInterface(descriptor);
- if (in != null) {
- return in;
- }
-
- return new ServiceManagerProxy(obj);
- }
-
- public ServiceManagerNative()
- {
- attachInterface(this, descriptor);
- }
-
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
- {
- try {
- switch (code) {
- case IServiceManager.GET_SERVICE_TRANSACTION: {
- data.enforceInterface(IServiceManager.descriptor);
- String name = data.readString();
- IBinder service = getService(name);
- reply.writeStrongBinder(service);
- return true;
- }
-
- case IServiceManager.CHECK_SERVICE_TRANSACTION: {
- data.enforceInterface(IServiceManager.descriptor);
- String name = data.readString();
- IBinder service = checkService(name);
- reply.writeStrongBinder(service);
- return true;
- }
-
- case IServiceManager.ADD_SERVICE_TRANSACTION: {
- data.enforceInterface(IServiceManager.descriptor);
- String name = data.readString();
- IBinder service = data.readStrongBinder();
- addService(name, service);
- return true;
- }
-
- case IServiceManager.LIST_SERVICES_TRANSACTION: {
- data.enforceInterface(IServiceManager.descriptor);
- String[] list = listServices();
- reply.writeStringArray(list);
- return true;
- }
-
- case IServiceManager.SET_PERMISSION_CONTROLLER_TRANSACTION: {
- data.enforceInterface(IServiceManager.descriptor);
- IPermissionController controller
- = IPermissionController.Stub.asInterface(
- data.readStrongBinder());
- setPermissionController(controller);
- return true;
- }
- }
- } catch (RemoteException e) {
- }
-
- return false;
- }
-
- public IBinder asBinder()
- {
- return this;
- }
-}
-
-class ServiceManagerProxy implements IServiceManager {
- public ServiceManagerProxy(IBinder remote) {
- mRemote = remote;
- }
-
- public IBinder asBinder() {
- return mRemote;
- }
-
- public IBinder getService(String name) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IServiceManager.descriptor);
- data.writeString(name);
- mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
- IBinder binder = reply.readStrongBinder();
- reply.recycle();
- data.recycle();
- return binder;
- }
-
- public IBinder checkService(String name) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IServiceManager.descriptor);
- data.writeString(name);
- mRemote.transact(CHECK_SERVICE_TRANSACTION, data, reply, 0);
- IBinder binder = reply.readStrongBinder();
- reply.recycle();
- data.recycle();
- return binder;
- }
-
- public void addService(String name, IBinder service)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IServiceManager.descriptor);
- data.writeString(name);
- data.writeStrongBinder(service);
- mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
- reply.recycle();
- data.recycle();
- }
-
- public String[] listServices() throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IServiceManager.descriptor);
- mRemote.transact(LIST_SERVICES_TRANSACTION, data, reply, 0);
- String[] list = reply.readStringArray();
- reply.recycle();
- data.recycle();
- return list;
- }
-
- public void setPermissionController(IPermissionController controller)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IServiceManager.descriptor);
- data.writeStrongBinder(controller.asBinder());
- mRemote.transact(SET_PERMISSION_CONTROLLER_TRANSACTION, data, reply, 0);
- reply.recycle();
- data.recycle();
- }
-
- private IBinder mRemote;
-}
diff --git a/core/java/android/os/StatFs.java b/core/java/android/os/StatFs.java
deleted file mode 100644
index 912bfdf..0000000
--- a/core/java/android/os/StatFs.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * Retrieve overall information about the space on a filesystem. This is a
- * Wrapper for Unix statfs().
- */
-public class StatFs {
- /**
- * Construct a new StatFs for looking at the stats of the
- * filesystem at <var>path</var>. Upon construction, the stat of
- * the file system will be performed, and the values retrieved available
- * from the methods on this class.
- *
- * @param path A path in the desired file system to state.
- */
- public StatFs(String path) { native_setup(path); }
-
- /**
- * Perform a restat of the file system referenced by this object. This
- * is the same as re-constructing the object with the same file system
- * path, and the new stat values are available upon return.
- */
- public void restat(String path) { native_restat(path); }
-
- @Override
- protected void finalize() { native_finalize(); }
-
- /**
- * The size, in bytes, of a block on the file system. This corresponds
- * to the Unix statfs.f_bsize field.
- */
- public native int getBlockSize();
-
- /**
- * The total number of blocks on the file system. This corresponds
- * to the Unix statfs.f_blocks field.
- */
- public native int getBlockCount();
-
- /**
- * The total number of blocks that are free on the file system, including
- * reserved blocks (that are not available to normal applications). This
- * corresponds to the Unix statfs.f_bfree field. Most applications will
- * want to use {@link #getAvailableBlocks()} instead.
- */
- public native int getFreeBlocks();
-
- /**
- * The number of blocks that are free on the file system and available to
- * applications. This corresponds to the Unix statfs.f_bavail field.
- */
- public native int getAvailableBlocks();
-
- private int mNativeContext;
- private native void native_restat(String path);
- private native void native_setup(String path);
- private native void native_finalize();
-}
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
deleted file mode 100644
index 2b57b39..0000000
--- a/core/java/android/os/SystemClock.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-
-/**
- * Core timekeeping facilities.
- *
- * <p> Three different clocks are available, and they should not be confused:
- *
- * <ul>
- * <li> <p> {@link System#currentTimeMillis System.currentTimeMillis()}
- * is the standard "wall" clock (time and date) expressing milliseconds
- * since the epoch. The wall clock can be set by the user or the phone
- * network (see {@link #setCurrentTimeMillis}), so the time may jump
- * backwards or forwards unpredictably. This clock should only be used
- * when correspondence with real-world dates and times is important, such
- * as in a calendar or alarm clock application. Interval or elapsed
- * time measurements should use a different clock.
- *
- * <li> <p> {@link #uptimeMillis} is counted in milliseconds since the
- * system was booted. This clock stops when the system enters deep
- * sleep (CPU off, display dark, device waiting for external input),
- * but is not affected by clock scaling, idle, or other power saving
- * mechanisms. This is the basis for most interval timing
- * such as {@link Thread#sleep(long) Thread.sleep(millls)},
- * {@link Object#wait(long) Object.wait(millis)}, and
- * {@link System#nanoTime System.nanoTime()}. This clock is guaranteed
- * to be monotonic, and is the recommended basis for the general purpose
- * interval timing of user interface events, performance measurements,
- * and anything else that does not need to measure elapsed time during
- * device sleep. Most methods that accept a timestamp value expect the
- * {@link #uptimeMillis} clock.
- *
- * <li> <p> {@link #elapsedRealtime} is counted in milliseconds since the
- * system was booted, including deep sleep. This clock should be used
- * when measuring time intervals that may span periods of system sleep.
- * </ul>
- *
- * There are several mechanisms for controlling the timing of events:
- *
- * <ul>
- * <li> <p> Standard functions like {@link Thread#sleep(long)
- * Thread.sleep(millis)} and {@link Object#wait(long) Object.wait(millis)}
- * are always available. These functions use the {@link #uptimeMillis}
- * clock; if the device enters sleep, the remainder of the time will be
- * postponed until the device wakes up. These synchronous functions may
- * be interrupted with {@link Thread#interrupt Thread.interrupt()}, and
- * you must handle {@link InterruptedException}.
- *
- * <li> <p> {@link #sleep SystemClock.sleep(millis)} is a utility function
- * very similar to {@link Thread#sleep(long) Thread.sleep(millis)}, but it
- * ignores {@link InterruptedException}. Use this function for delays if
- * you do not use {@link Thread#interrupt Thread.interrupt()}, as it will
- * preserve the interrupted state of the thread.
- *
- * <li> <p> The {@link android.os.Handler} class can schedule asynchronous
- * callbacks at an absolute or relative time. Handler objects also use the
- * {@link #uptimeMillis} clock, and require an {@link android.os.Looper
- * event loop} (normally present in any GUI application).
- *
- * <li> <p> The {@link android.app.AlarmManager} can trigger one-time or
- * recurring events which occur even when the device is in deep sleep
- * or your application is not running. Events may be scheduled with your
- * choice of {@link java.lang.System#currentTimeMillis} (RTC) or
- * {@link #elapsedRealtime} (ELAPSED_REALTIME), and cause an
- * {@link android.content.Intent} broadcast when they occur.
- * </ul>
- */
-public final class SystemClock {
- /**
- * This class is uninstantiable.
- */
- private SystemClock() {
- // This space intentionally left blank.
- }
-
- /**
- * Waits a given number of milliseconds (of uptimeMillis) before returning.
- * Similar to {@link java.lang.Thread#sleep(long)}, but does not throw
- * {@link InterruptedException}; {@link Thread#interrupt()} events are
- * deferred until the next interruptible operation. Does not return until
- * at least the specified number of milliseconds has elapsed.
- *
- * @param ms to sleep before returning, in milliseconds of uptime.
- */
- public static void sleep(long ms)
- {
- long start = uptimeMillis();
- long duration = ms;
- boolean interrupted = false;
- do {
- try {
- Thread.sleep(duration);
- }
- catch (InterruptedException e) {
- interrupted = true;
- }
- duration = start + ms - uptimeMillis();
- } while (duration > 0);
-
- if (interrupted) {
- // Important: we don't want to quietly eat an interrupt() event,
- // so we make sure to re-interrupt the thread so that the next
- // call to Thread.sleep() or Object.wait() will be interrupted.
- Thread.currentThread().interrupt();
- }
- }
-
- /**
- * Sets the current wall time, in milliseconds. Requires the calling
- * process to have appropriate permissions.
- *
- * @return if the clock was successfully set to the specified time.
- */
- native public static boolean setCurrentTimeMillis(long millis);
-
- /**
- * Returns milliseconds since boot, not counting time spent in deep sleep.
- * <b>Note:</b> This value may get reset occasionally (before it would
- * otherwise wrap around).
- *
- * @return milliseconds of non-sleep uptime since boot.
- */
- native public static long uptimeMillis();
-
- /**
- * Returns milliseconds since boot, including time spent in sleep.
- *
- * @return elapsed milliseconds since boot.
- */
- native public static long elapsedRealtime();
-
- /**
- * Returns milliseconds running in the current thread.
- *
- * @return elapsed milliseconds in the thread
- */
- public static native long currentThreadTimeMillis();
-}
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
deleted file mode 100644
index c3ae3c2..0000000
--- a/core/java/android/os/SystemProperties.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-
-/**
- * Gives access to the system properties store. The system properties
- * store contains a list of string key-value pairs.
- *
- * {@hide}
- */
-public class SystemProperties
-{
- public static final int PROP_NAME_MAX = 31;
- public static final int PROP_VALUE_MAX = 91;
-
- private static native String native_get(String key);
- private static native String native_get(String key, String def);
- private static native void native_set(String key, String def);
-
- /**
- * Get the value for the given key.
- * @return an empty string if the key isn't found
- * @throws IllegalArgumentException if the key exceeds 32 characters
- */
- public static String get(String key) {
- if (key.length() > PROP_NAME_MAX) {
- throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
- }
- return native_get(key);
- }
-
- /**
- * Get the value for the given key.
- * @return if the key isn't found, return def if it isn't null, or an empty string otherwise
- * @throws IllegalArgumentException if the key exceeds 32 characters
- */
- public static String get(String key, String def) {
- if (key.length() > PROP_NAME_MAX) {
- throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
- }
- return native_get(key, def);
- }
-
- /**
- * Get the value for the given key, and return as an integer.
- * @param key the key to lookup
- * @param def a default value to return
- * @return the key parsed as an integer, or def if the key isn't found or
- * cannot be parsed
- * @throws IllegalArgumentException if the key exceeds 32 characters
- */
- public static int getInt(String key, int def) {
- try {
- return Integer.parseInt(get(key));
- } catch (NumberFormatException e) {
- return def;
- }
- }
-
- /**
- * Get the value for the given key, and return as a long.
- * @param key the key to lookup
- * @param def a default value to return
- * @return the key parsed as a long, or def if the key isn't found or
- * cannot be parsed
- * @throws IllegalArgumentException if the key exceeds 32 characters
- */
- public static long getLong(String key, long def) {
- try {
- return Long.parseLong(get(key));
- } catch (NumberFormatException e) {
- return def;
- }
- }
-
- /**
- * Get the value for the given key, returned as a boolean.
- * Values 'n', 'no', '0', 'false' or 'off' are considered false.
- * Values 'y', 'yes', '1', 'true' or 'on' are considered true.
- * (case insensitive).
- * If the key does not exist, or has any other value, then the default
- * result is returned.
- * @param key the key to lookup
- * @param def a default value to return
- * @return the key parsed as a boolean, or def if the key isn't found or is
- * not able to be parsed as a boolean.
- * @throws IllegalArgumentException if the key exceeds 32 characters
- */
- public static boolean getBoolean(String key, boolean def) {
- String value = get(key);
- // Deal with these quick cases first: not found, 0 and 1
- if (value.equals("")) {
- return def;
- } else if (value.equals("0")) {
- return false;
- } else if (value.equals("1")) {
- return true;
- // now for slower (and hopefully less common) cases
- } else if (value.equalsIgnoreCase("n") ||
- value.equalsIgnoreCase("no") ||
- value.equalsIgnoreCase("false") ||
- value.equalsIgnoreCase("off")) {
- return false;
- } else if (value.equalsIgnoreCase("y") ||
- value.equalsIgnoreCase("yes") ||
- value.equalsIgnoreCase("true") ||
- value.equalsIgnoreCase("on")) {
- return true;
- }
- return def;
- }
-
- /**
- * Set the value for the given key.
- * @throws IllegalArgumentException if the key exceeds 32 characters
- * @throws IllegalArgumentException if the value exceeds 92 characters
- */
- public static void set(String key, String val) {
- if (key.length() > PROP_NAME_MAX) {
- throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
- }
- if (val != null && val.length() > PROP_VALUE_MAX) {
- throw new IllegalArgumentException("val.length > " +
- PROP_VALUE_MAX);
- }
- native_set(key, val);
- }
-}
diff --git a/core/java/android/os/SystemService.java b/core/java/android/os/SystemService.java
deleted file mode 100644
index 447cd1f..0000000
--- a/core/java/android/os/SystemService.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/** @hide */
-public class SystemService
-{
- /** Request that the init daemon start a named service. */
- public static void start(String name) {
- SystemProperties.set("ctl.start", name);
- }
-
- /** Request that the init daemon stop a named service. */
- public static void stop(String name) {
- SystemProperties.set("ctl.stop", name);
- }
-}
diff --git a/core/java/android/os/TokenWatcher.java b/core/java/android/os/TokenWatcher.java
deleted file mode 100755
index ac3cc92..0000000
--- a/core/java/android/os/TokenWatcher.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import java.util.WeakHashMap;
-import java.util.Set;
-import android.util.Log;
-
-/**
- * Helper class that helps you use IBinder objects as reference counted
- * tokens. IBinders make good tokens because we find out when they are
- * removed
- *
- */
-public abstract class TokenWatcher
-{
- /**
- * Construct the TokenWatcher
- *
- * @param h A handler to call {@link #acquired} and {@link #released}
- * on. If you don't care, just call it like this, although your thread
- * will have to be a Looper thread.
- * <code>new TokenWatcher(new Handler())</code>
- * @param tag A debugging tag for this TokenWatcher
- */
- public TokenWatcher(Handler h, String tag)
- {
- mHandler = h;
- mTag = tag != null ? tag : "TokenWatcher";
- }
-
- /**
- * Called when the number of active tokens goes from 0 to 1.
- */
- public abstract void acquired();
-
- /**
- * Called when the number of active tokens goes from 1 to 0.
- */
- public abstract void released();
-
- /**
- * Record that this token has been acquired. When acquire is called, and
- * the current count is 0, the acquired method is called on the given
- * handler.
- *
- * @param token An IBinder object. If this token has already been acquired,
- * no action is taken.
- * @param tag A string used by the {@link #dump} method for debugging,
- * to see who has references.
- */
- public void acquire(IBinder token, String tag)
- {
- synchronized (mTokens) {
- // explicitly checked to avoid bogus sendNotification calls because
- // of the WeakHashMap and the GC
- int oldSize = mTokens.size();
-
- Death d = new Death(token, tag);
- try {
- token.linkToDeath(d, 0);
- } catch (RemoteException e) {
- return;
- }
- mTokens.put(token, d);
-
- if (oldSize == 0 && !mAcquired) {
- sendNotificationLocked(true);
- mAcquired = true;
- }
- }
- }
-
- public void cleanup(IBinder token, boolean unlink)
- {
- synchronized (mTokens) {
- Death d = mTokens.remove(token);
- if (unlink && d != null) {
- d.token.unlinkToDeath(d, 0);
- d.token = null;
- }
-
- if (mTokens.size() == 0 && mAcquired) {
- sendNotificationLocked(false);
- mAcquired = false;
- }
- }
- }
-
- public void release(IBinder token)
- {
- cleanup(token, true);
- }
-
- public boolean isAcquired()
- {
- synchronized (mTokens) {
- return mAcquired;
- }
- }
-
- public void dump()
- {
- synchronized (mTokens) {
- Set<IBinder> keys = mTokens.keySet();
- Log.i(mTag, "Token count: " + mTokens.size());
- int i = 0;
- for (IBinder b: keys) {
- Log.i(mTag, "[" + i + "] " + mTokens.get(b).tag + " - " + b);
- i++;
- }
- }
- }
-
- private Runnable mNotificationTask = new Runnable() {
- public void run()
- {
- int value;
- synchronized (mTokens) {
- value = mNotificationQueue;
- mNotificationQueue = -1;
- }
- if (value == 1) {
- acquired();
- }
- else if (value == 0) {
- released();
- }
- }
- };
-
- private void sendNotificationLocked(boolean on)
- {
- int value = on ? 1 : 0;
- if (mNotificationQueue == -1) {
- // empty
- mNotificationQueue = value;
- mHandler.post(mNotificationTask);
- }
- else if (mNotificationQueue != value) {
- // it's a pair, so cancel it
- mNotificationQueue = -1;
- mHandler.removeCallbacks(mNotificationTask);
- }
- // else, same so do nothing -- maybe we should warn?
- }
-
- private class Death implements IBinder.DeathRecipient
- {
- IBinder token;
- String tag;
-
- Death(IBinder token, String tag)
- {
- this.token = token;
- this.tag = tag;
- }
-
- public void binderDied()
- {
- cleanup(token, false);
- }
-
- protected void finalize() throws Throwable
- {
- try {
- if (token != null) {
- Log.w(mTag, "cleaning up leaked reference: " + tag);
- release(token);
- }
- }
- finally {
- super.finalize();
- }
- }
- }
-
- private WeakHashMap<IBinder,Death> mTokens = new WeakHashMap<IBinder,Death>();
- private Handler mHandler;
- private String mTag;
- private int mNotificationQueue = -1;
- private volatile boolean mAcquired = false;
-}
diff --git a/core/java/android/os/UEventObserver.java b/core/java/android/os/UEventObserver.java
deleted file mode 100644
index b924e84..0000000
--- a/core/java/android/os/UEventObserver.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-/**
- * UEventObserver is an abstract class that receives UEvent's from the kernel.<p>
- *
- * Subclass UEventObserver, implementing onUEvent(UEvent event), then call
- * startObserving() with a match string. The UEvent thread will then call your
- * onUEvent() method when a UEvent occurs that contains your match string.<p>
- *
- * Call stopObserving() to stop receiving UEvent's.<p>
- *
- * There is only one UEvent thread per process, even if that process has
- * multiple UEventObserver subclass instances. The UEvent thread starts when
- * the startObserving() is called for the first time in that process. Once
- * started the UEvent thread will not stop (although it can stop notifying
- * UEventObserver's via stopObserving()).<p>
- *
- * @hide
-*/
-public abstract class UEventObserver {
- private static final String TAG = UEventObserver.class.getSimpleName();
-
- /**
- * Representation of a UEvent.
- */
- static public class UEvent {
- // collection of key=value pairs parsed from the uevent message
- public HashMap<String,String> mMap = new HashMap<String,String>();
-
- public UEvent(String message) {
- int offset = 0;
- int length = message.length();
-
- while (offset < length) {
- int equals = message.indexOf('=', offset);
- int at = message.indexOf(0, offset);
- if (at < 0) break;
-
- if (equals > offset && equals < at) {
- // key is before the equals sign, and value is after
- mMap.put(message.substring(offset, equals),
- message.substring(equals + 1, at));
- }
-
- offset = at + 1;
- }
- }
-
- public String get(String key) {
- return mMap.get(key);
- }
-
- public String get(String key, String defaultValue) {
- String result = mMap.get(key);
- return (result == null ? defaultValue : result);
- }
-
- public String toString() {
- return mMap.toString();
- }
- }
-
- private static UEventThread sThread;
- private static boolean sThreadStarted = false;
-
- private static class UEventThread extends Thread {
- /** Many to many mapping of string match to observer.
- * Multimap would be better, but not available in android, so use
- * an ArrayList where even elements are the String match and odd
- * elements the corresponding UEventObserver observer */
- private ArrayList<Object> mObservers = new ArrayList<Object>();
-
- UEventThread() {
- super("UEventObserver");
- }
-
- public void run() {
- native_setup();
-
- byte[] buffer = new byte[1024];
- int len;
- while (true) {
- len = next_event(buffer);
- if (len > 0) {
- String bufferStr = new String(buffer, 0, len); // easier to search a String
- synchronized (mObservers) {
- for (int i = 0; i < mObservers.size(); i += 2) {
- if (bufferStr.indexOf((String)mObservers.get(i)) != -1) {
- ((UEventObserver)mObservers.get(i+1))
- .onUEvent(new UEvent(bufferStr));
- }
- }
- }
- }
- }
- }
- public void addObserver(String match, UEventObserver observer) {
- synchronized(mObservers) {
- mObservers.add(match);
- mObservers.add(observer);
- }
- }
- /** Removes every key/value pair where value=observer from mObservers */
- public void removeObserver(UEventObserver observer) {
- synchronized(mObservers) {
- boolean found = true;
- while (found) {
- found = false;
- for (int i = 0; i < mObservers.size(); i += 2) {
- if (mObservers.get(i+1) == observer) {
- mObservers.remove(i+1);
- mObservers.remove(i);
- found = true;
- break;
- }
- }
- }
- }
- }
- }
-
- private static native void native_setup();
- private static native int next_event(byte[] buffer);
-
- private static final synchronized void ensureThreadStarted() {
- if (sThreadStarted == false) {
- sThread = new UEventThread();
- sThread.start();
- sThreadStarted = true;
- }
- }
-
- /**
- * Begin observation of UEvent's.<p>
- * This method will cause the UEvent thread to start if this is the first
- * invocation of startObserving in this process.<p>
- * Once called, the UEvent thread will call onUEvent() when an incoming
- * UEvent matches the specified string.<p>
- * This method can be called multiple times to register multiple matches.
- * Only one call to stopObserving is required even with multiple registered
- * matches.
- * @param match A substring of the UEvent to match. Use "" to match all
- * UEvent's
- */
- public final synchronized void startObserving(String match) {
- ensureThreadStarted();
- sThread.addObserver(match, this);
- }
-
- /**
- * End observation of UEvent's.<p>
- * This process's UEvent thread will never call onUEvent() on this
- * UEventObserver after this call. Repeated calls have no effect.
- */
- public final synchronized void stopObserving() {
- sThread.removeObserver(this);
- }
-
- /**
- * Subclasses of UEventObserver should override this method to handle
- * UEvents.
- */
- public abstract void onUEvent(UEvent event);
-
- protected void finalize() throws Throwable {
- try {
- stopObserving();
- } finally {
- super.finalize();
- }
- }
-}
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
deleted file mode 100644
index 0f75289..0000000
--- a/core/java/android/os/Vibrator.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * Class that operates the vibrator on the device.
- * <p>
- * If your process exits, any vibration you started with will stop.
- */
-public class Vibrator
-{
- IHardwareService mService;
-
- /** @hide */
- public Vibrator()
- {
- mService = IHardwareService.Stub.asInterface(
- ServiceManager.getService("hardware"));
- }
-
- /**
- * Turn the vibrator on.
- *
- * @param milliseconds How long to vibrate for.
- */
- public void vibrate(long milliseconds)
- {
- try {
- mService.vibrate(milliseconds);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Vibrate with a given pattern.
- *
- * <p>
- * Pass in an array of ints that are the times at which to turn on or off
- * the vibrator. The first one is how long to wait before turning it on,
- * and then after that it alternates. If you want to repeat, pass the
- * index into the pattern at which to start the repeat.
- *
- * @param pattern an array of longs of times to turn the vibrator on or off.
- * @param repeat the index into pattern at which to repeat, or -1 if
- * you don't want to repeat.
- */
- public void vibrate(long[] pattern, int repeat)
- {
- // catch this here because the server will do nothing. pattern may
- // not be null, let that be checked, because the server will drop it
- // anyway
- if (repeat < pattern.length) {
- try {
- mService.vibratePattern(pattern, repeat, new Binder());
- } catch (RemoteException e) {
- }
- } else {
- throw new ArrayIndexOutOfBoundsException();
- }
- }
-
- /**
- * Turn the vibrator off.
- */
- public void cancel()
- {
- try {
- mService.cancelVibrate();
- } catch (RemoteException e) {
- }
- }
-}
diff --git a/core/java/android/os/package.html b/core/java/android/os/package.html
deleted file mode 100644
index fb0ecda..0000000
--- a/core/java/android/os/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<HTML>
-<BODY>
-Provides basic operating system services, message passing, and inter-process
-communication on the device.
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/core/java/android/package.html b/core/java/android/package.html
deleted file mode 100644
index 1f1be2d..0000000
--- a/core/java/android/package.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<HTML>
-<BODY>
-Contains the resource classes used by standard Android applications.
-<p>
-This package contains the resource classes that Android defines to be used in
-Android applications. Third party developers can use many of them also for their applications.
-To learn more about how to use these classes, and what a
-resource is, see <a href="{@docRoot}guide/topics/resources/index.html">Resources and Assets</a>.
-</BODY>
-</HTML>
diff --git a/core/java/android/pim/ContactsAsyncHelper.java b/core/java/android/pim/ContactsAsyncHelper.java
deleted file mode 100644
index a21281e..0000000
--- a/core/java/android/pim/ContactsAsyncHelper.java
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.pim;
-
-import com.android.internal.telephony.CallerInfo;
-import com.android.internal.telephony.Connection;
-
-import android.content.ContentUris;
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.provider.Contacts;
-import android.provider.Contacts.People;
-import android.util.Log;
-import android.view.View;
-import android.widget.ImageView;
-
-import java.io.InputStream;
-
-/**
- * Helper class for async access of images.
- */
-public class ContactsAsyncHelper extends Handler {
-
- private static final boolean DBG = false;
- private static final String LOG_TAG = "ContactsAsyncHelper";
-
- /**
- * Interface for a WorkerHandler result return.
- */
- public interface OnImageLoadCompleteListener {
- /**
- * Called when the image load is complete.
- *
- * @param imagePresent true if an image was found
- */
- public void onImageLoadComplete(int token, Object cookie, ImageView iView,
- boolean imagePresent);
- }
-
- // constants
- private static final int EVENT_LOAD_IMAGE = 1;
- private static final int DEFAULT_TOKEN = -1;
-
- // static objects
- private static Handler sThreadHandler;
- private static ContactsAsyncHelper sInstance;
-
- static {
- sInstance = new ContactsAsyncHelper();
- }
-
- private static final class WorkerArgs {
- public Context context;
- public ImageView view;
- public Uri uri;
- public int defaultResource;
- public Object result;
- public Object cookie;
- public OnImageLoadCompleteListener listener;
- public CallerInfo info;
- }
-
- /**
- * public inner class to help out the ContactsAsyncHelper callers
- * with tracking the state of the CallerInfo Queries and image
- * loading.
- *
- * Logic contained herein is used to remove the race conditions
- * that exist as the CallerInfo queries run and mix with the image
- * loads, which then mix with the Phone state changes.
- */
- public static class ImageTracker {
-
- // Image display states
- public static final int DISPLAY_UNDEFINED = 0;
- public static final int DISPLAY_IMAGE = -1;
- public static final int DISPLAY_DEFAULT = -2;
-
- // State of the image on the imageview.
- private CallerInfo mCurrentCallerInfo;
- private int displayMode;
-
- public ImageTracker() {
- mCurrentCallerInfo = null;
- displayMode = DISPLAY_UNDEFINED;
- }
-
- /**
- * Used to see if the requested call / connection has a
- * different caller attached to it than the one we currently
- * have in the CallCard.
- */
- public boolean isDifferentImageRequest(CallerInfo ci) {
- // note, since the connections are around for the lifetime of the
- // call, and the CallerInfo-related items as well, we can
- // definitely use a simple != comparison.
- return (mCurrentCallerInfo != ci);
- }
-
- public boolean isDifferentImageRequest(Connection connection) {
- // if the connection does not exist, see if the
- // mCurrentCallerInfo is also null to match.
- if (connection == null) {
- if (DBG) Log.d(LOG_TAG, "isDifferentImageRequest: connection is null");
- return (mCurrentCallerInfo != null);
- }
- Object o = connection.getUserData();
-
- // if the call does NOT have a callerInfo attached
- // then it is ok to query.
- boolean runQuery = true;
- if (o instanceof CallerInfo) {
- runQuery = isDifferentImageRequest((CallerInfo) o);
- }
- return runQuery;
- }
-
- /**
- * Simple setter for the CallerInfo object.
- */
- public void setPhotoRequest(CallerInfo ci) {
- mCurrentCallerInfo = ci;
- }
-
- /**
- * Convenience method used to retrieve the URI
- * representing the Photo file recorded in the attached
- * CallerInfo Object.
- */
- public Uri getPhotoUri() {
- if (mCurrentCallerInfo != null) {
- return ContentUris.withAppendedId(People.CONTENT_URI,
- mCurrentCallerInfo.person_id);
- }
- return null;
- }
-
- /**
- * Simple setter for the Photo state.
- */
- public void setPhotoState(int state) {
- displayMode = state;
- }
-
- /**
- * Simple getter for the Photo state.
- */
- public int getPhotoState() {
- return displayMode;
- }
- }
-
- /**
- * Thread worker class that handles the task of opening the stream and loading
- * the images.
- */
- private class WorkerHandler extends Handler {
- public WorkerHandler(Looper looper) {
- super(looper);
- }
-
- public void handleMessage(Message msg) {
- WorkerArgs args = (WorkerArgs) msg.obj;
-
- switch (msg.arg1) {
- case EVENT_LOAD_IMAGE:
- InputStream inputStream = Contacts.People.openContactPhotoInputStream(
- args.context.getContentResolver(), args.uri);
- if (inputStream != null) {
- args.result = Drawable.createFromStream(inputStream, args.uri.toString());
-
- if (DBG) Log.d(LOG_TAG, "Loading image: " + msg.arg1 +
- " token: " + msg.what + " image URI: " + args.uri);
- } else {
- args.result = null;
- if (DBG) Log.d(LOG_TAG, "Problem with image: " + msg.arg1 +
- " token: " + msg.what + " image URI: " + args.uri +
- ", using default image.");
- }
- break;
- default:
- }
-
- // send the reply to the enclosing class.
- Message reply = ContactsAsyncHelper.this.obtainMessage(msg.what);
- reply.arg1 = msg.arg1;
- reply.obj = msg.obj;
- reply.sendToTarget();
- }
- }
-
- /**
- * Private constructor for static class
- */
- private ContactsAsyncHelper() {
- HandlerThread thread = new HandlerThread("ContactsAsyncWorker");
- thread.start();
- sThreadHandler = new WorkerHandler(thread.getLooper());
- }
-
- /**
- * Convenience method for calls that do not want to deal with listeners and tokens.
- */
- public static final void updateImageViewWithContactPhotoAsync(Context context,
- ImageView imageView, Uri person, int placeholderImageResource) {
- // Added additional Cookie field in the callee.
- updateImageViewWithContactPhotoAsync (null, DEFAULT_TOKEN, null, null, context,
- imageView, person, placeholderImageResource);
- }
-
- /**
- * Convenience method for calls that do not want to deal with listeners and tokens, but have
- * a CallerInfo object to cache the image to.
- */
- public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, Context context,
- ImageView imageView, Uri person, int placeholderImageResource) {
- // Added additional Cookie field in the callee.
- updateImageViewWithContactPhotoAsync (info, DEFAULT_TOKEN, null, null, context,
- imageView, person, placeholderImageResource);
- }
-
-
- /**
- * Start an image load, attach the result to the specified CallerInfo object.
- * Note, when the query is started, we make the ImageView INVISIBLE if the
- * placeholderImageResource value is -1. When we're given a valid (!= -1)
- * placeholderImageResource value, we make sure the image is visible.
- */
- public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, int token,
- OnImageLoadCompleteListener listener, Object cookie, Context context,
- ImageView imageView, Uri person, int placeholderImageResource) {
-
- // in case the source caller info is null, the URI will be null as well.
- // just update using the placeholder image in this case.
- if (person == null) {
- if (DBG) Log.d(LOG_TAG, "target image is null, just display placeholder.");
- imageView.setVisibility(View.VISIBLE);
- imageView.setImageResource(placeholderImageResource);
- return;
- }
-
- // Added additional Cookie field in the callee to handle arguments
- // sent to the callback function.
-
- // setup arguments
- WorkerArgs args = new WorkerArgs();
- args.cookie = cookie;
- args.context = context;
- args.view = imageView;
- args.uri = person;
- args.defaultResource = placeholderImageResource;
- args.listener = listener;
- args.info = info;
-
- // setup message arguments
- Message msg = sThreadHandler.obtainMessage(token);
- msg.arg1 = EVENT_LOAD_IMAGE;
- msg.obj = args;
-
- if (DBG) Log.d(LOG_TAG, "Begin loading image: " + args.uri +
- ", displaying default image for now.");
-
- // set the default image first, when the query is complete, we will
- // replace the image with the correct one.
- if (placeholderImageResource != -1) {
- imageView.setVisibility(View.VISIBLE);
- imageView.setImageResource(placeholderImageResource);
- } else {
- imageView.setVisibility(View.INVISIBLE);
- }
-
- // notify the thread to begin working
- sThreadHandler.sendMessage(msg);
- }
-
- /**
- * Called when loading is done.
- */
- @Override
- public void handleMessage(Message msg) {
- WorkerArgs args = (WorkerArgs) msg.obj;
- switch (msg.arg1) {
- case EVENT_LOAD_IMAGE:
- boolean imagePresent = false;
-
- // if the image has been loaded then display it, otherwise set default.
- // in either case, make sure the image is visible.
- if (args.result != null) {
- args.view.setVisibility(View.VISIBLE);
- args.view.setImageDrawable((Drawable) args.result);
- // make sure the cached photo data is updated.
- if (args.info != null) {
- args.info.cachedPhoto = (Drawable) args.result;
- }
- imagePresent = true;
- } else if (args.defaultResource != -1) {
- args.view.setVisibility(View.VISIBLE);
- args.view.setImageResource(args.defaultResource);
- }
-
- // Note that the data is cached.
- if (args.info != null) {
- args.info.isCachedPhotoCurrent = true;
- }
-
- // notify the listener if it is there.
- if (args.listener != null) {
- if (DBG) Log.d(LOG_TAG, "Notifying listener: " + args.listener.toString() +
- " image: " + args.uri + " completed");
- args.listener.onImageLoadComplete(msg.what, args.cookie, args.view,
- imagePresent);
- }
- break;
- default:
- }
- }
-}
diff --git a/core/java/android/pim/DateException.java b/core/java/android/pim/DateException.java
deleted file mode 100644
index 90bfe7f..0000000
--- a/core/java/android/pim/DateException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.pim;
-
-public class DateException extends Exception
-{
- public DateException(String message)
- {
- super(message);
- }
-}
-
diff --git a/core/java/android/pim/EventRecurrence.java b/core/java/android/pim/EventRecurrence.java
deleted file mode 100644
index edf69ee..0000000
--- a/core/java/android/pim/EventRecurrence.java
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.pim;
-
-import android.content.res.Resources;
-import android.text.TextUtils;
-import android.text.format.Time;
-
-import java.util.Calendar;
-
-public class EventRecurrence
-{
- /**
- * Thrown when a recurrence string provided can not be parsed according
- * to RFC2445.
- */
- public static class InvalidFormatException extends RuntimeException
- {
- InvalidFormatException(String s) {
- super(s);
- }
- }
-
- public EventRecurrence()
- {
- wkst = MO;
- }
-
- /**
- * Parse an iCalendar/RFC2445 recur type according to Section 4.3.10.
- */
- public native void parse(String recur);
-
- public void setStartDate(Time date) {
- startDate = date;
- }
-
- public static final int SECONDLY = 1;
- public static final int MINUTELY = 2;
- public static final int HOURLY = 3;
- public static final int DAILY = 4;
- public static final int WEEKLY = 5;
- public static final int MONTHLY = 6;
- public static final int YEARLY = 7;
-
- public static final int SU = 0x00010000;
- public static final int MO = 0x00020000;
- public static final int TU = 0x00040000;
- public static final int WE = 0x00080000;
- public static final int TH = 0x00100000;
- public static final int FR = 0x00200000;
- public static final int SA = 0x00400000;
-
- public Time startDate;
- public int freq;
- public String until;
- public int count;
- public int interval;
- public int wkst;
-
- public int[] bysecond;
- public int bysecondCount;
- public int[] byminute;
- public int byminuteCount;
- public int[] byhour;
- public int byhourCount;
- public int[] byday;
- public int[] bydayNum;
- public int bydayCount;
- public int[] bymonthday;
- public int bymonthdayCount;
- public int[] byyearday;
- public int byyeardayCount;
- public int[] byweekno;
- public int byweeknoCount;
- public int[] bymonth;
- public int bymonthCount;
- public int[] bysetpos;
- public int bysetposCount;
-
- /**
- * Converts one of the Calendar.SUNDAY constants to the SU, MO, etc.
- * constants. btw, I think we should switch to those here too, to
- * get rid of this function, if possible.
- */
- public static int calendarDay2Day(int day)
- {
- switch (day)
- {
- case Calendar.SUNDAY:
- return SU;
- case Calendar.MONDAY:
- return MO;
- case Calendar.TUESDAY:
- return TU;
- case Calendar.WEDNESDAY:
- return WE;
- case Calendar.THURSDAY:
- return TH;
- case Calendar.FRIDAY:
- return FR;
- case Calendar.SATURDAY:
- return SA;
- default:
- throw new RuntimeException("bad day of week: " + day);
- }
- }
-
- public static int timeDay2Day(int day)
- {
- switch (day)
- {
- case Time.SUNDAY:
- return SU;
- case Time.MONDAY:
- return MO;
- case Time.TUESDAY:
- return TU;
- case Time.WEDNESDAY:
- return WE;
- case Time.THURSDAY:
- return TH;
- case Time.FRIDAY:
- return FR;
- case Time.SATURDAY:
- return SA;
- default:
- throw new RuntimeException("bad day of week: " + day);
- }
- }
- public static int day2TimeDay(int day)
- {
- switch (day)
- {
- case SU:
- return Time.SUNDAY;
- case MO:
- return Time.MONDAY;
- case TU:
- return Time.TUESDAY;
- case WE:
- return Time.WEDNESDAY;
- case TH:
- return Time.THURSDAY;
- case FR:
- return Time.FRIDAY;
- case SA:
- return Time.SATURDAY;
- default:
- throw new RuntimeException("bad day of week: " + day);
- }
- }
-
- /**
- * Converts one of the SU, MO, etc. constants to the Calendar.SUNDAY
- * constants. btw, I think we should switch to those here too, to
- * get rid of this function, if possible.
- */
- public static int day2CalendarDay(int day)
- {
- switch (day)
- {
- case SU:
- return Calendar.SUNDAY;
- case MO:
- return Calendar.MONDAY;
- case TU:
- return Calendar.TUESDAY;
- case WE:
- return Calendar.WEDNESDAY;
- case TH:
- return Calendar.THURSDAY;
- case FR:
- return Calendar.FRIDAY;
- case SA:
- return Calendar.SATURDAY;
- default:
- throw new RuntimeException("bad day of week: " + day);
- }
- }
-
- /**
- * Converts one of the internal day constants (SU, MO, etc.) to the
- * two-letter string representing that constant.
- *
- * @throws IllegalArgumentException Thrown if the day argument is not one of
- * the defined day constants.
- *
- * @param day one the internal constants SU, MO, etc.
- * @return the two-letter string for the day ("SU", "MO", etc.)
- */
- private static String day2String(int day) {
- switch (day) {
- case SU:
- return "SU";
- case MO:
- return "MO";
- case TU:
- return "TU";
- case WE:
- return "WE";
- case TH:
- return "TH";
- case FR:
- return "FR";
- case SA:
- return "SA";
- default:
- throw new IllegalArgumentException("bad day argument: " + day);
- }
- }
-
- private static void appendNumbers(StringBuilder s, String label,
- int count, int[] values)
- {
- if (count > 0) {
- s.append(label);
- count--;
- for (int i=0; i<count; i++) {
- s.append(values[i]);
- s.append(",");
- }
- s.append(values[count]);
- }
- }
-
- private void appendByDay(StringBuilder s, int i)
- {
- int n = this.bydayNum[i];
- if (n != 0) {
- s.append(n);
- }
-
- String str = day2String(this.byday[i]);
- s.append(str);
- }
-
- @Override
- public String toString()
- {
- StringBuilder s = new StringBuilder();
-
- s.append("FREQ=");
- switch (this.freq)
- {
- case SECONDLY:
- s.append("SECONDLY");
- break;
- case MINUTELY:
- s.append("MINUTELY");
- break;
- case HOURLY:
- s.append("HOURLY");
- break;
- case DAILY:
- s.append("DAILY");
- break;
- case WEEKLY:
- s.append("WEEKLY");
- break;
- case MONTHLY:
- s.append("MONTHLY");
- break;
- case YEARLY:
- s.append("YEARLY");
- break;
- }
-
- if (!TextUtils.isEmpty(this.until)) {
- s.append(";UNTIL=");
- s.append(until);
- }
-
- if (this.count != 0) {
- s.append(";COUNT=");
- s.append(this.count);
- }
-
- if (this.interval != 0) {
- s.append(";INTERVAL=");
- s.append(this.interval);
- }
-
- if (this.wkst != 0) {
- s.append(";WKST=");
- s.append(day2String(this.wkst));
- }
-
- appendNumbers(s, ";BYSECOND=", this.bysecondCount, this.bysecond);
- appendNumbers(s, ";BYMINUTE=", this.byminuteCount, this.byminute);
- appendNumbers(s, ";BYSECOND=", this.byhourCount, this.byhour);
-
- // day
- int count = this.bydayCount;
- if (count > 0) {
- s.append(";BYDAY=");
- count--;
- for (int i=0; i<count; i++) {
- appendByDay(s, i);
- s.append(",");
- }
- appendByDay(s, count);
- }
-
- appendNumbers(s, ";BYMONTHDAY=", this.bymonthdayCount, this.bymonthday);
- appendNumbers(s, ";BYYEARDAY=", this.byyeardayCount, this.byyearday);
- appendNumbers(s, ";BYWEEKNO=", this.byweeknoCount, this.byweekno);
- appendNumbers(s, ";BYMONTH=", this.bymonthCount, this.bymonth);
- appendNumbers(s, ";BYSETPOS=", this.bysetposCount, this.bysetpos);
-
- return s.toString();
- }
-
- public String getRepeatString() {
- Resources r = Resources.getSystem();
-
- // TODO Implement "Until" portion of string, as well as custom settings
- switch (this.freq) {
- case DAILY:
- return r.getString(com.android.internal.R.string.daily);
- case WEEKLY: {
- if (repeatsOnEveryWeekDay()) {
- return r.getString(com.android.internal.R.string.every_weekday);
- } else {
- String format = r.getString(com.android.internal.R.string.weekly);
- StringBuilder days = new StringBuilder();
-
- // Do one less iteration in the loop so the last element is added out of the
- // loop. This is done so the comma is not placed after the last item.
- int count = this.bydayCount - 1;
- if (count >= 0) {
- for (int i = 0 ; i < count ; i++) {
- days.append(dayToString(r, this.byday[i]));
- days.append(",");
- }
- days.append(dayToString(r, this.byday[count]));
-
- return String.format(format, days.toString());
- }
-
- // There is no "BYDAY" specifier, so use the day of the
- // first event. For this to work, the setStartDate()
- // method must have been used by the caller to set the
- // date of the first event in the recurrence.
- if (startDate == null) {
- return null;
- }
-
- int day = timeDay2Day(startDate.weekDay);
- return String.format(format, dayToString(r, day));
- }
- }
- case MONTHLY: {
- return r.getString(com.android.internal.R.string.monthly);
- }
- case YEARLY:
- return r.getString(com.android.internal.R.string.yearly);
- }
-
- return null;
- }
-
- public boolean repeatsOnEveryWeekDay() {
- if (this.freq != WEEKLY) {
- return false;
- }
-
- int count = this.bydayCount;
- if (count != 5) {
- return false;
- }
-
- for (int i = 0 ; i < count ; i++) {
- int day = byday[i];
- if (day == SU || day == SA) {
- return false;
- }
- }
-
- return true;
- }
-
- public boolean repeatsMonthlyOnDayCount() {
- if (this.freq != MONTHLY) {
- return false;
- }
-
- if (bydayCount != 1 || bymonthdayCount != 0) {
- return false;
- }
-
- return true;
- }
-
- private String dayToString(Resources r, int day) {
- switch (day) {
- case SU: return r.getString(com.android.internal.R.string.sunday);
- case MO: return r.getString(com.android.internal.R.string.monday);
- case TU: return r.getString(com.android.internal.R.string.tuesday);
- case WE: return r.getString(com.android.internal.R.string.wednesday);
- case TH: return r.getString(com.android.internal.R.string.thursday);
- case FR: return r.getString(com.android.internal.R.string.friday);
- case SA: return r.getString(com.android.internal.R.string.saturday);
- default: throw new IllegalArgumentException("bad day argument: " + day);
- }
- }
-}
diff --git a/core/java/android/pim/ICalendar.java b/core/java/android/pim/ICalendar.java
deleted file mode 100644
index 4a5d7e4..0000000
--- a/core/java/android/pim/ICalendar.java
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.pim;
-
-import android.util.Log;
-import android.util.Config;
-
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-import java.util.ArrayList;
-
-/**
- * Parses RFC 2445 iCalendar objects.
- */
-public class ICalendar {
-
- private static final String TAG = "Sync";
-
- // TODO: keep track of VEVENT, VTODO, VJOURNAL, VFREEBUSY, VTIMEZONE, VALARM
- // components, by type field or by subclass? subclass would allow us to
- // enforce grammars.
-
- /**
- * Exception thrown when an iCalendar object has invalid syntax.
- */
- public static class FormatException extends Exception {
- public FormatException() {
- super();
- }
-
- public FormatException(String msg) {
- super(msg);
- }
-
- public FormatException(String msg, Throwable cause) {
- super(msg, cause);
- }
- }
-
- /**
- * A component within an iCalendar (VEVENT, VTODO, VJOURNAL, VFEEBUSY,
- * VTIMEZONE, VALARM).
- */
- public static class Component {
-
- // components
- private static final String BEGIN = "BEGIN";
- private static final String END = "END";
- private static final String NEWLINE = "\n";
- public static final String VCALENDAR = "VCALENDAR";
- public static final String VEVENT = "VEVENT";
- public static final String VTODO = "VTODO";
- public static final String VJOURNAL = "VJOURNAL";
- public static final String VFREEBUSY = "VFREEBUSY";
- public static final String VTIMEZONE = "VTIMEZONE";
- public static final String VALARM = "VALARM";
-
- private final String mName;
- private final Component mParent; // see if we can get rid of this
- private LinkedList<Component> mChildren = null;
- private final LinkedHashMap<String, ArrayList<Property>> mPropsMap =
- new LinkedHashMap<String, ArrayList<Property>>();
-
- /**
- * Creates a new component with the provided name.
- * @param name The name of the component.
- */
- public Component(String name, Component parent) {
- mName = name;
- mParent = parent;
- }
-
- /**
- * Returns the name of the component.
- * @return The name of the component.
- */
- public String getName() {
- return mName;
- }
-
- /**
- * Returns the parent of this component.
- * @return The parent of this component.
- */
- public Component getParent() {
- return mParent;
- }
-
- /**
- * Helper that lazily gets/creates the list of children.
- * @return The list of children.
- */
- protected LinkedList<Component> getOrCreateChildren() {
- if (mChildren == null) {
- mChildren = new LinkedList<Component>();
- }
- return mChildren;
- }
-
- /**
- * Adds a child component to this component.
- * @param child The child component.
- */
- public void addChild(Component child) {
- getOrCreateChildren().add(child);
- }
-
- /**
- * Returns a list of the Component children of this component. May be
- * null, if there are no children.
- *
- * @return A list of the children.
- */
- public List<Component> getComponents() {
- return mChildren;
- }
-
- /**
- * Adds a Property to this component.
- * @param prop
- */
- public void addProperty(Property prop) {
- String name= prop.getName();
- ArrayList<Property> props = mPropsMap.get(name);
- if (props == null) {
- props = new ArrayList<Property>();
- mPropsMap.put(name, props);
- }
- props.add(prop);
- }
-
- /**
- * Returns a set of the property names within this component.
- * @return A set of property names within this component.
- */
- public Set<String> getPropertyNames() {
- return mPropsMap.keySet();
- }
-
- /**
- * Returns a list of properties with the specified name. Returns null
- * if there are no such properties.
- * @param name The name of the property that should be returned.
- * @return A list of properties with the requested name.
- */
- public List<Property> getProperties(String name) {
- return mPropsMap.get(name);
- }
-
- /**
- * Returns the first property with the specified name. Returns null
- * if there is no such property.
- * @param name The name of the property that should be returned.
- * @return The first property with the specified name.
- */
- public Property getFirstProperty(String name) {
- List<Property> props = mPropsMap.get(name);
- if (props == null || props.size() == 0) {
- return null;
- }
- return props.get(0);
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- toString(sb);
- sb.append(NEWLINE);
- return sb.toString();
- }
-
- /**
- * Helper method that appends this component to a StringBuilder. The
- * caller is responsible for appending a newline at the end of the
- * component.
- */
- public void toString(StringBuilder sb) {
- sb.append(BEGIN);
- sb.append(":");
- sb.append(mName);
- sb.append(NEWLINE);
-
- // append the properties
- for (String propertyName : getPropertyNames()) {
- for (Property property : getProperties(propertyName)) {
- property.toString(sb);
- sb.append(NEWLINE);
- }
- }
-
- // append the sub-components
- if (mChildren != null) {
- for (Component component : mChildren) {
- component.toString(sb);
- sb.append(NEWLINE);
- }
- }
-
- sb.append(END);
- sb.append(":");
- sb.append(mName);
- }
- }
-
- /**
- * A property within an iCalendar component (e.g., DTSTART, DTEND, etc.,
- * within a VEVENT).
- */
- public static class Property {
- // properties
- // TODO: do we want to list these here? the complete list is long.
- public static final String DTSTART = "DTSTART";
- public static final String DTEND = "DTEND";
- public static final String DURATION = "DURATION";
- public static final String RRULE = "RRULE";
- public static final String RDATE = "RDATE";
- public static final String EXRULE = "EXRULE";
- public static final String EXDATE = "EXDATE";
- // ... need to add more.
-
- private final String mName;
- private LinkedHashMap<String, ArrayList<Parameter>> mParamsMap =
- new LinkedHashMap<String, ArrayList<Parameter>>();
- private String mValue; // TODO: make this final?
-
- /**
- * Creates a new property with the provided name.
- * @param name The name of the property.
- */
- public Property(String name) {
- mName = name;
- }
-
- /**
- * Creates a new property with the provided name and value.
- * @param name The name of the property.
- * @param value The value of the property.
- */
- public Property(String name, String value) {
- mName = name;
- mValue = value;
- }
-
- /**
- * Returns the name of the property.
- * @return The name of the property.
- */
- public String getName() {
- return mName;
- }
-
- /**
- * Returns the value of this property.
- * @return The value of this property.
- */
- public String getValue() {
- return mValue;
- }
-
- /**
- * Sets the value of this property.
- * @param value The desired value for this property.
- */
- public void setValue(String value) {
- mValue = value;
- }
-
- /**
- * Adds a {@link Parameter} to this property.
- * @param param The parameter that should be added.
- */
- public void addParameter(Parameter param) {
- ArrayList<Parameter> params = mParamsMap.get(param.name);
- if (params == null) {
- params = new ArrayList<Parameter>();
- mParamsMap.put(param.name, params);
- }
- params.add(param);
- }
-
- /**
- * Returns the set of parameter names for this property.
- * @return The set of parameter names for this property.
- */
- public Set<String> getParameterNames() {
- return mParamsMap.keySet();
- }
-
- /**
- * Returns the list of parameters with the specified name. May return
- * null if there are no such parameters.
- * @param name The name of the parameters that should be returned.
- * @return The list of parameters with the specified name.
- */
- public List<Parameter> getParameters(String name) {
- return mParamsMap.get(name);
- }
-
- /**
- * Returns the first parameter with the specified name. May return
- * nll if there is no such parameter.
- * @param name The name of the parameter that should be returned.
- * @return The first parameter with the specified name.
- */
- public Parameter getFirstParameter(String name) {
- ArrayList<Parameter> params = mParamsMap.get(name);
- if (params == null || params.size() == 0) {
- return null;
- }
- return params.get(0);
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- toString(sb);
- return sb.toString();
- }
-
- /**
- * Helper method that appends this property to a StringBuilder. The
- * caller is responsible for appending a newline after this property.
- */
- public void toString(StringBuilder sb) {
- sb.append(mName);
- Set<String> parameterNames = getParameterNames();
- for (String parameterName : parameterNames) {
- for (Parameter param : getParameters(parameterName)) {
- sb.append(";");
- param.toString(sb);
- }
- }
- sb.append(":");
- sb.append(mValue);
- }
- }
-
- /**
- * A parameter defined for an iCalendar property.
- */
- // TODO: make this a proper class rather than a struct?
- public static class Parameter {
- public String name;
- public String value;
-
- /**
- * Creates a new empty parameter.
- */
- public Parameter() {
- }
-
- /**
- * Creates a new parameter with the specified name and value.
- * @param name The name of the parameter.
- * @param value The value of the parameter.
- */
- public Parameter(String name, String value) {
- this.name = name;
- this.value = value;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- toString(sb);
- return sb.toString();
- }
-
- /**
- * Helper method that appends this parameter to a StringBuilder.
- */
- public void toString(StringBuilder sb) {
- sb.append(name);
- sb.append("=");
- sb.append(value);
- }
- }
-
- private static final class ParserState {
- // public int lineNumber = 0;
- public String line; // TODO: just point to original text
- public int index;
- }
-
- // use factory method
- private ICalendar() {
- }
-
- // TODO: get rid of this -- handle all of the parsing in one pass through
- // the text.
- private static String normalizeText(String text) {
- // first we deal with line folding, by replacing all "\r\n " strings
- // with nothing
- text = text.replaceAll("\r\n ", "");
-
- // it's supposed to be \r\n, but not everyone does that
- text = text.replaceAll("\r\n", "\n");
- text = text.replaceAll("\r", "\n");
- return text;
- }
-
- /**
- * Parses text into an iCalendar component. Parses into the provided
- * component, if not null, or parses into a new component. In the latter
- * case, expects a BEGIN as the first line. Returns the provided or newly
- * created top-level component.
- */
- // TODO: use an index into the text, so we can make this a recursive
- // function?
- private static Component parseComponentImpl(Component component,
- String text)
- throws FormatException {
- Component current = component;
- ParserState state = new ParserState();
- state.index = 0;
-
- // split into lines
- String[] lines = text.split("\n");
-
- // each line is of the format:
- // name *(";" param) ":" value
- for (String line : lines) {
- try {
- current = parseLine(line, state, current);
- // if the provided component was null, we will return the root
- // NOTE: in this case, if the first line is not a BEGIN, a
- // FormatException will get thrown.
- if (component == null) {
- component = current;
- }
- } catch (FormatException fe) {
- if (Config.LOGV) {
- Log.v(TAG, "Cannot parse " + line, fe);
- }
- // for now, we ignore the parse error. Google Calendar seems
- // to be emitting some misformatted iCalendar objects.
- }
- continue;
- }
- return component;
- }
-
- /**
- * Parses a line into the provided component. Creates a new component if
- * the line is a BEGIN, adding the newly created component to the provided
- * parent. Returns whatever component is the current one (to which new
- * properties will be added) in the parse.
- */
- private static Component parseLine(String line, ParserState state,
- Component component)
- throws FormatException {
- state.line = line;
- int len = state.line.length();
-
- // grab the name
- char c = 0;
- for (state.index = 0; state.index < len; ++state.index) {
- c = line.charAt(state.index);
- if (c == ';' || c == ':') {
- break;
- }
- }
- String name = line.substring(0, state.index);
-
- if (component == null) {
- if (!Component.BEGIN.equals(name)) {
- throw new FormatException("Expected BEGIN");
- }
- }
-
- Property property;
- if (Component.BEGIN.equals(name)) {
- // start a new component
- String componentName = extractValue(state);
- Component child = new Component(componentName, component);
- if (component != null) {
- component.addChild(child);
- }
- return child;
- } else if (Component.END.equals(name)) {
- // finish the current component
- String componentName = extractValue(state);
- if (component == null ||
- !componentName.equals(component.getName())) {
- throw new FormatException("Unexpected END " + componentName);
- }
- return component.getParent();
- } else {
- property = new Property(name);
- }
-
- if (c == ';') {
- Parameter parameter = null;
- while ((parameter = extractParameter(state)) != null) {
- property.addParameter(parameter);
- }
- }
- String value = extractValue(state);
- property.setValue(value);
- component.addProperty(property);
- return component;
- }
-
- /**
- * Extracts the value ":..." on the current line. The first character must
- * be a ':'.
- */
- private static String extractValue(ParserState state)
- throws FormatException {
- String line = state.line;
- char c = line.charAt(state.index);
- if (c != ':') {
- throw new FormatException("Expected ':' before end of line in "
- + line);
- }
- String value = line.substring(state.index + 1);
- state.index = line.length() - 1;
- return value;
- }
-
- /**
- * Extracts the next parameter from the line, if any. If there are no more
- * parameters, returns null.
- */
- private static Parameter extractParameter(ParserState state)
- throws FormatException {
- String text = state.line;
- int len = text.length();
- Parameter parameter = null;
- int startIndex = -1;
- int equalIndex = -1;
- while (state.index < len) {
- char c = text.charAt(state.index);
- if (c == ':') {
- if (parameter != null) {
- if (equalIndex == -1) {
- throw new FormatException("Expected '=' within "
- + "parameter in " + text);
- }
- parameter.value = text.substring(equalIndex + 1,
- state.index);
- }
- return parameter; // may be null
- } else if (c == ';') {
- if (parameter != null) {
- if (equalIndex == -1) {
- throw new FormatException("Expected '=' within "
- + "parameter in " + text);
- }
- parameter.value = text.substring(equalIndex + 1,
- state.index);
- return parameter;
- } else {
- parameter = new Parameter();
- startIndex = state.index;
- }
- } else if (c == '=') {
- equalIndex = state.index;
- if ((parameter == null) || (startIndex == -1)) {
- throw new FormatException("Expected ';' before '=' in "
- + text);
- }
- parameter.name = text.substring(startIndex + 1, equalIndex);
- }
- ++state.index;
- }
- throw new FormatException("Expected ':' before end of line in " + text);
- }
-
- /**
- * Parses the provided text into an iCalendar object. The top-level
- * component must be of type VCALENDAR.
- * @param text The text to be parsed.
- * @return The top-level VCALENDAR component.
- * @throws FormatException Thrown if the text could not be parsed into an
- * iCalendar VCALENDAR object.
- */
- public static Component parseCalendar(String text) throws FormatException {
- Component calendar = parseComponent(null, text);
- if (calendar == null || !Component.VCALENDAR.equals(calendar.getName())) {
- throw new FormatException("Expected " + Component.VCALENDAR);
- }
- return calendar;
- }
-
- /**
- * Parses the provided text into an iCalendar event. The top-level
- * component must be of type VEVENT.
- * @param text The text to be parsed.
- * @return The top-level VEVENT component.
- * @throws FormatException Thrown if the text could not be parsed into an
- * iCalendar VEVENT.
- */
- public static Component parseEvent(String text) throws FormatException {
- Component event = parseComponent(null, text);
- if (event == null || !Component.VEVENT.equals(event.getName())) {
- throw new FormatException("Expected " + Component.VEVENT);
- }
- return event;
- }
-
- /**
- * Parses the provided text into an iCalendar component.
- * @param text The text to be parsed.
- * @return The top-level component.
- * @throws FormatException Thrown if the text could not be parsed into an
- * iCalendar component.
- */
- public static Component parseComponent(String text) throws FormatException {
- return parseComponent(null, text);
- }
-
- /**
- * Parses the provided text, adding to the provided component.
- * @param component The component to which the parsed iCalendar data should
- * be added.
- * @param text The text to be parsed.
- * @return The top-level component.
- * @throws FormatException Thrown if the text could not be parsed as an
- * iCalendar object.
- */
- public static Component parseComponent(Component component, String text)
- throws FormatException {
- text = normalizeText(text);
- return parseComponentImpl(component, text);
- }
-}
diff --git a/core/java/android/pim/RecurrenceSet.java b/core/java/android/pim/RecurrenceSet.java
deleted file mode 100644
index 1a287c8..0000000
--- a/core/java/android/pim/RecurrenceSet.java
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.pim;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.os.Bundle;
-import android.provider.Calendar;
-import android.text.TextUtils;
-import android.text.format.Time;
-import android.util.Config;
-import android.util.Log;
-
-import java.util.List;
-
-/**
- * Basic information about a recurrence, following RFC 2445 Section 4.8.5.
- * Contains the RRULEs, RDATE, EXRULEs, and EXDATE properties.
- */
-public class RecurrenceSet {
-
- private final static String TAG = "CalendarProvider";
-
- private final static String RULE_SEPARATOR = "\n";
-
- // TODO: make these final?
- public EventRecurrence[] rrules = null;
- public long[] rdates = null;
- public EventRecurrence[] exrules = null;
- public long[] exdates = null;
-
- /**
- * Creates a new RecurrenceSet from information stored in the
- * events table in the CalendarProvider.
- * @param values The values retrieved from the Events table.
- */
- public RecurrenceSet(ContentValues values) {
- String rruleStr = values.getAsString(Calendar.Events.RRULE);
- String rdateStr = values.getAsString(Calendar.Events.RDATE);
- String exruleStr = values.getAsString(Calendar.Events.EXRULE);
- String exdateStr = values.getAsString(Calendar.Events.EXDATE);
- init(rruleStr, rdateStr, exruleStr, exdateStr);
- }
-
- /**
- * Creates a new RecurrenceSet from information stored in a database
- * {@link Cursor} pointing to the events table in the
- * CalendarProvider. The cursor must contain the RRULE, RDATE, EXRULE,
- * and EXDATE columns.
- *
- * @param cursor The cursor containing the RRULE, RDATE, EXRULE, and EXDATE
- * columns.
- */
- public RecurrenceSet(Cursor cursor) {
- int rruleColumn = cursor.getColumnIndex(Calendar.Events.RRULE);
- int rdateColumn = cursor.getColumnIndex(Calendar.Events.RDATE);
- int exruleColumn = cursor.getColumnIndex(Calendar.Events.EXRULE);
- int exdateColumn = cursor.getColumnIndex(Calendar.Events.EXDATE);
- String rruleStr = cursor.getString(rruleColumn);
- String rdateStr = cursor.getString(rdateColumn);
- String exruleStr = cursor.getString(exruleColumn);
- String exdateStr = cursor.getString(exdateColumn);
- init(rruleStr, rdateStr, exruleStr, exdateStr);
- }
-
- public RecurrenceSet(String rruleStr, String rdateStr,
- String exruleStr, String exdateStr) {
- init(rruleStr, rdateStr, exruleStr, exdateStr);
- }
-
- private void init(String rruleStr, String rdateStr,
- String exruleStr, String exdateStr) {
- if (!TextUtils.isEmpty(rruleStr) || !TextUtils.isEmpty(rdateStr)) {
-
- if (!TextUtils.isEmpty(rruleStr)) {
- String[] rruleStrs = rruleStr.split(RULE_SEPARATOR);
- rrules = new EventRecurrence[rruleStrs.length];
- for (int i = 0; i < rruleStrs.length; ++i) {
- EventRecurrence rrule = new EventRecurrence();
- rrule.parse(rruleStrs[i]);
- rrules[i] = rrule;
- }
- }
-
- if (!TextUtils.isEmpty(rdateStr)) {
- rdates = parseRecurrenceDates(rdateStr);
- }
-
- if (!TextUtils.isEmpty(exruleStr)) {
- String[] exruleStrs = exruleStr.split(RULE_SEPARATOR);
- exrules = new EventRecurrence[exruleStrs.length];
- for (int i = 0; i < exruleStrs.length; ++i) {
- EventRecurrence exrule = new EventRecurrence();
- exrule.parse(exruleStr);
- exrules[i] = exrule;
- }
- }
-
- if (!TextUtils.isEmpty(exdateStr)) {
- exdates = parseRecurrenceDates(exdateStr);
- }
- }
- }
-
- /**
- * Returns whether or not a recurrence is defined in this RecurrenceSet.
- * @return Whether or not a recurrence is defined in this RecurrenceSet.
- */
- public boolean hasRecurrence() {
- return (rrules != null || rdates != null);
- }
-
- /**
- * Parses the provided RDATE or EXDATE string into an array of longs
- * representing each date/time in the recurrence.
- * @param recurrence The recurrence to be parsed.
- * @return The list of date/times.
- */
- public static long[] parseRecurrenceDates(String recurrence) {
- // TODO: use "local" time as the default. will need to handle times
- // that end in "z" (UTC time) explicitly at that point.
- String tz = Time.TIMEZONE_UTC;
- int tzidx = recurrence.indexOf(";");
- if (tzidx != -1) {
- tz = recurrence.substring(0, tzidx);
- recurrence = recurrence.substring(tzidx + 1);
- }
- Time time = new Time(tz);
- String[] rawDates = recurrence.split(",");
- int n = rawDates.length;
- long[] dates = new long[n];
- for (int i = 0; i<n; ++i) {
- // The timezone is updated to UTC if the time string specified 'Z'.
- time.parse(rawDates[i]);
- dates[i] = time.toMillis(false /* use isDst */);
- time.timezone = tz;
- }
- return dates;
- }
-
- /**
- * Populates the database map of values with the appropriate RRULE, RDATE,
- * EXRULE, and EXDATE values extracted from the parsed iCalendar component.
- * @param component The iCalendar component containing the desired
- * recurrence specification.
- * @param values The db values that should be updated.
- * @return true if the component contained the necessary information
- * to specify a recurrence. The required fields are DTSTART,
- * one of DTEND/DURATION, and one of RRULE/RDATE. Returns false if
- * there was an error, including if the date is out of range.
- */
- public static boolean populateContentValues(ICalendar.Component component,
- ContentValues values) {
- ICalendar.Property dtstartProperty =
- component.getFirstProperty("DTSTART");
- String dtstart = dtstartProperty.getValue();
- ICalendar.Parameter tzidParam =
- dtstartProperty.getFirstParameter("TZID");
- // NOTE: the timezone may be null, if this is a floating time.
- String tzid = tzidParam == null ? null : tzidParam.value;
- Time start = new Time(tzidParam == null ? Time.TIMEZONE_UTC : tzid);
- boolean inUtc = start.parse(dtstart);
- boolean allDay = start.allDay;
-
- if (inUtc) {
- tzid = Time.TIMEZONE_UTC;
- }
-
- String duration = computeDuration(start, component);
- String rrule = flattenProperties(component, "RRULE");
- String rdate = extractDates(component.getFirstProperty("RDATE"));
- String exrule = flattenProperties(component, "EXRULE");
- String exdate = extractDates(component.getFirstProperty("EXDATE"));
-
- if ((TextUtils.isEmpty(dtstart))||
- (TextUtils.isEmpty(duration))||
- ((TextUtils.isEmpty(rrule))&&
- (TextUtils.isEmpty(rdate)))) {
- if (Config.LOGD) {
- Log.d(TAG, "Recurrence missing DTSTART, DTEND/DURATION, "
- + "or RRULE/RDATE: "
- + component.toString());
- }
- return false;
- }
-
- if (allDay) {
- // TODO: also change tzid to be UTC? that would be consistent, but
- // that would not reflect the original timezone value back to the
- // server.
- start.timezone = Time.TIMEZONE_UTC;
- }
- long millis = start.toMillis(false /* use isDst */);
- values.put(Calendar.Events.DTSTART, millis);
- if (millis == -1) {
- if (Config.LOGD) {
- Log.d(TAG, "DTSTART is out of range: " + component.toString());
- }
- return false;
- }
-
- values.put(Calendar.Events.RRULE, rrule);
- values.put(Calendar.Events.RDATE, rdate);
- values.put(Calendar.Events.EXRULE, exrule);
- values.put(Calendar.Events.EXDATE, exdate);
- values.put(Calendar.Events.EVENT_TIMEZONE, tzid);
- values.put(Calendar.Events.DURATION, duration);
- values.put(Calendar.Events.ALL_DAY, allDay ? 1 : 0);
- return true;
- }
-
- public static boolean populateComponent(Cursor cursor,
- ICalendar.Component component) {
-
- int dtstartColumn = cursor.getColumnIndex(Calendar.Events.DTSTART);
- int durationColumn = cursor.getColumnIndex(Calendar.Events.DURATION);
- int tzidColumn = cursor.getColumnIndex(Calendar.Events.EVENT_TIMEZONE);
- int rruleColumn = cursor.getColumnIndex(Calendar.Events.RRULE);
- int rdateColumn = cursor.getColumnIndex(Calendar.Events.RDATE);
- int exruleColumn = cursor.getColumnIndex(Calendar.Events.EXRULE);
- int exdateColumn = cursor.getColumnIndex(Calendar.Events.EXDATE);
- int allDayColumn = cursor.getColumnIndex(Calendar.Events.ALL_DAY);
-
-
- long dtstart = -1;
- if (!cursor.isNull(dtstartColumn)) {
- dtstart = cursor.getLong(dtstartColumn);
- }
- String duration = cursor.getString(durationColumn);
- String tzid = cursor.getString(tzidColumn);
- String rruleStr = cursor.getString(rruleColumn);
- String rdateStr = cursor.getString(rdateColumn);
- String exruleStr = cursor.getString(exruleColumn);
- String exdateStr = cursor.getString(exdateColumn);
- boolean allDay = cursor.getInt(allDayColumn) == 1;
-
- if ((dtstart == -1) ||
- (TextUtils.isEmpty(duration))||
- ((TextUtils.isEmpty(rruleStr))&&
- (TextUtils.isEmpty(rdateStr)))) {
- // no recurrence.
- return false;
- }
-
- ICalendar.Property dtstartProp = new ICalendar.Property("DTSTART");
- Time dtstartTime = null;
- if (!TextUtils.isEmpty(tzid)) {
- if (!allDay) {
- dtstartProp.addParameter(new ICalendar.Parameter("TZID", tzid));
- }
- dtstartTime = new Time(tzid);
- } else {
- // use the "floating" timezone
- dtstartTime = new Time(Time.TIMEZONE_UTC);
- }
-
- dtstartTime.set(dtstart);
- // make sure the time is printed just as a date, if all day.
- // TODO: android.pim.Time really should take care of this for us.
- if (allDay) {
- dtstartProp.addParameter(new ICalendar.Parameter("VALUE", "DATE"));
- dtstartTime.allDay = true;
- dtstartTime.hour = 0;
- dtstartTime.minute = 0;
- dtstartTime.second = 0;
- }
-
- dtstartProp.setValue(dtstartTime.format2445());
- component.addProperty(dtstartProp);
- ICalendar.Property durationProp = new ICalendar.Property("DURATION");
- durationProp.setValue(duration);
- component.addProperty(durationProp);
-
- addPropertiesForRuleStr(component, "RRULE", rruleStr);
- addPropertyForDateStr(component, "RDATE", rdateStr);
- addPropertiesForRuleStr(component, "EXRULE", exruleStr);
- addPropertyForDateStr(component, "EXDATE", exdateStr);
- return true;
- }
-
- private static void addPropertiesForRuleStr(ICalendar.Component component,
- String propertyName,
- String ruleStr) {
- if (TextUtils.isEmpty(ruleStr)) {
- return;
- }
- String[] rrules = ruleStr.split(RULE_SEPARATOR);
- for (String rrule : rrules) {
- ICalendar.Property prop = new ICalendar.Property(propertyName);
- prop.setValue(rrule);
- component.addProperty(prop);
- }
- }
-
- private static void addPropertyForDateStr(ICalendar.Component component,
- String propertyName,
- String dateStr) {
- if (TextUtils.isEmpty(dateStr)) {
- return;
- }
-
- ICalendar.Property prop = new ICalendar.Property(propertyName);
- String tz = null;
- int tzidx = dateStr.indexOf(";");
- if (tzidx != -1) {
- tz = dateStr.substring(0, tzidx);
- dateStr = dateStr.substring(tzidx + 1);
- }
- if (!TextUtils.isEmpty(tz)) {
- prop.addParameter(new ICalendar.Parameter("TZID", tz));
- }
- prop.setValue(dateStr);
- component.addProperty(prop);
- }
-
- private static String computeDuration(Time start,
- ICalendar.Component component) {
- // see if a duration is defined
- ICalendar.Property durationProperty =
- component.getFirstProperty("DURATION");
- if (durationProperty != null) {
- // just return the duration
- return durationProperty.getValue();
- }
-
- // must compute a duration from the DTEND
- ICalendar.Property dtendProperty =
- component.getFirstProperty("DTEND");
- if (dtendProperty == null) {
- // no DURATION, no DTEND: 0 second duration
- return "+P0S";
- }
- ICalendar.Parameter endTzidParameter =
- dtendProperty.getFirstParameter("TZID");
- String endTzid = (endTzidParameter == null)
- ? start.timezone : endTzidParameter.value;
-
- Time end = new Time(endTzid);
- end.parse(dtendProperty.getValue());
- long durationMillis = end.toMillis(false /* use isDst */)
- - start.toMillis(false /* use isDst */);
- long durationSeconds = (durationMillis / 1000);
- return "P" + durationSeconds + "S";
- }
-
- private static String flattenProperties(ICalendar.Component component,
- String name) {
- List<ICalendar.Property> properties = component.getProperties(name);
- if (properties == null || properties.isEmpty()) {
- return null;
- }
-
- if (properties.size() == 1) {
- return properties.get(0).getValue();
- }
-
- StringBuilder sb = new StringBuilder();
-
- boolean first = true;
- for (ICalendar.Property property : component.getProperties(name)) {
- if (first) {
- first = false;
- } else {
- // TODO: use commas. our RECUR parsing should handle that
- // anyway.
- sb.append(RULE_SEPARATOR);
- }
- sb.append(property.getValue());
- }
- return sb.toString();
- }
-
- private static String extractDates(ICalendar.Property recurrence) {
- if (recurrence == null) {
- return null;
- }
- ICalendar.Parameter tzidParam =
- recurrence.getFirstParameter("TZID");
- if (tzidParam != null) {
- return tzidParam.value + ";" + recurrence.getValue();
- }
- return recurrence.getValue();
- }
-}
diff --git a/core/java/android/pim/package.html b/core/java/android/pim/package.html
deleted file mode 100644
index 75237c9..0000000
--- a/core/java/android/pim/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<HTML>
-<BODY>
-{@hide}
-Provides helpers for working with PIM (Personal Information Manager) data used
-by contact lists and calendars.
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/core/java/android/preference/CheckBoxPreference.java b/core/java/android/preference/CheckBoxPreference.java
deleted file mode 100644
index 1e9b7ae..0000000
--- a/core/java/android/preference/CheckBoxPreference.java
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.res.TypedArray;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.Checkable;
-import android.widget.TextView;
-
-/**
- * A {@link Preference} that provides checkbox widget
- * functionality.
- * <p>
- * This preference will store a boolean into the SharedPreferences.
- *
- * @attr ref android.R.styleable#CheckBoxPreference_summaryOff
- * @attr ref android.R.styleable#CheckBoxPreference_summaryOn
- * @attr ref android.R.styleable#CheckBoxPreference_disableDependentsState
- */
-public class CheckBoxPreference extends Preference {
-
- private CharSequence mSummaryOn;
- private CharSequence mSummaryOff;
-
- private boolean mChecked;
-
- private boolean mDisableDependentsState;
-
- public CheckBoxPreference(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.CheckBoxPreference, defStyle, 0);
- mSummaryOn = a.getString(com.android.internal.R.styleable.CheckBoxPreference_summaryOn);
- mSummaryOff = a.getString(com.android.internal.R.styleable.CheckBoxPreference_summaryOff);
- mDisableDependentsState = a.getBoolean(
- com.android.internal.R.styleable.CheckBoxPreference_disableDependentsState, false);
- a.recycle();
- }
-
- public CheckBoxPreference(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.checkBoxPreferenceStyle);
- }
-
- public CheckBoxPreference(Context context) {
- this(context, null);
- }
-
- @Override
- protected void onBindView(View view) {
- super.onBindView(view);
-
- View checkboxView = view.findViewById(com.android.internal.R.id.checkbox);
- if (checkboxView != null && checkboxView instanceof Checkable) {
- ((Checkable) checkboxView).setChecked(mChecked);
- }
-
- // Sync the summary view
- TextView summaryView = (TextView) view.findViewById(com.android.internal.R.id.summary);
- if (summaryView != null) {
- boolean useDefaultSummary = true;
- if (mChecked && mSummaryOn != null) {
- summaryView.setText(mSummaryOn);
- useDefaultSummary = false;
- } else if (!mChecked && mSummaryOff != null) {
- summaryView.setText(mSummaryOff);
- useDefaultSummary = false;
- }
-
- if (useDefaultSummary) {
- final CharSequence summary = getSummary();
- if (summary != null) {
- summaryView.setText(summary);
- useDefaultSummary = false;
- }
- }
-
- int newVisibility = View.GONE;
- if (!useDefaultSummary) {
- // Someone has written to it
- newVisibility = View.VISIBLE;
- }
- if (newVisibility != summaryView.getVisibility()) {
- summaryView.setVisibility(newVisibility);
- }
- }
- }
-
- @Override
- protected void onClick() {
- super.onClick();
-
- boolean newValue = !isChecked();
-
- if (!callChangeListener(newValue)) {
- return;
- }
-
- setChecked(newValue);
- }
-
- /**
- * Sets the checked state and saves it to the {@link SharedPreferences}.
- *
- * @param checked The checked state.
- */
- public void setChecked(boolean checked) {
- mChecked = checked;
-
- persistBoolean(checked);
-
- notifyDependencyChange(shouldDisableDependents());
-
- notifyChanged();
- }
-
- /**
- * Returns the checked state.
- *
- * @return The checked state.
- */
- public boolean isChecked() {
- return mChecked;
- }
-
- @Override
- public boolean shouldDisableDependents() {
- boolean shouldDisable = mDisableDependentsState ? mChecked : !mChecked;
- return shouldDisable || super.shouldDisableDependents();
- }
-
- /**
- * Sets the summary to be shown when checked.
- *
- * @param summary The summary to be shown when checked.
- */
- public void setSummaryOn(CharSequence summary) {
- mSummaryOn = summary;
- if (isChecked()) {
- notifyChanged();
- }
- }
-
- /**
- * @see #setSummaryOn(CharSequence)
- * @param summaryResId The summary as a resource.
- */
- public void setSummaryOn(int summaryResId) {
- setSummaryOn(getContext().getString(summaryResId));
- }
-
- /**
- * Returns the summary to be shown when checked.
- * @return The summary.
- */
- public CharSequence getSummaryOn() {
- return mSummaryOn;
- }
-
- /**
- * Sets the summary to be shown when unchecked.
- *
- * @param summary The summary to be shown when unchecked.
- */
- public void setSummaryOff(CharSequence summary) {
- mSummaryOff = summary;
- if (!isChecked()) {
- notifyChanged();
- }
- }
-
- /**
- * @see #setSummaryOff(CharSequence)
- * @param summaryResId The summary as a resource.
- */
- public void setSummaryOff(int summaryResId) {
- setSummaryOff(getContext().getString(summaryResId));
- }
-
- /**
- * Returns the summary to be shown when unchecked.
- * @return The summary.
- */
- public CharSequence getSummaryOff() {
- return mSummaryOff;
- }
-
- /**
- * Returns whether dependents are disabled when this preference is on ({@code true})
- * or when this preference is off ({@code false}).
- *
- * @return Whether dependents are disabled when this preference is on ({@code true})
- * or when this preference is off ({@code false}).
- */
- public boolean getDisableDependentsState() {
- return mDisableDependentsState;
- }
-
- /**
- * Sets whether dependents are disabled when this preference is on ({@code true})
- * or when this preference is off ({@code false}).
- *
- * @param disableDependentsState The preference state that should disable dependents.
- */
- public void setDisableDependentsState(boolean disableDependentsState) {
- mDisableDependentsState = disableDependentsState;
- }
-
- @Override
- protected Object onGetDefaultValue(TypedArray a, int index) {
- return a.getBoolean(index, false);
- }
-
- @Override
- protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
- setChecked(restoreValue ? getPersistedBoolean(mChecked)
- : (Boolean) defaultValue);
- }
-
- @Override
- protected Parcelable onSaveInstanceState() {
- final Parcelable superState = super.onSaveInstanceState();
- if (isPersistent()) {
- // No need to save instance state since it's persistent
- return superState;
- }
-
- final SavedState myState = new SavedState(superState);
- myState.checked = isChecked();
- return myState;
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- if (state == null || !state.getClass().equals(SavedState.class)) {
- // Didn't save state for us in onSaveInstanceState
- super.onRestoreInstanceState(state);
- return;
- }
-
- SavedState myState = (SavedState) state;
- super.onRestoreInstanceState(myState.getSuperState());
- setChecked(myState.checked);
- }
-
- private static class SavedState extends BaseSavedState {
- boolean checked;
-
- public SavedState(Parcel source) {
- super(source);
- checked = source.readInt() == 1;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(checked ? 1 : 0);
- }
-
- public SavedState(Parcelable superState) {
- super(superState);
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR =
- new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
-}
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
deleted file mode 100644
index 666efae..0000000
--- a/core/java/android/preference/DialogPreference.java
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.SharedPreferences;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.TextView;
-
-/**
- * A base class for {@link Preference} objects that are
- * dialog-based. These preferences will, when clicked, open a dialog showing the
- * actual preference controls.
- *
- * @attr ref android.R.styleable#DialogPreference_dialogTitle
- * @attr ref android.R.styleable#DialogPreference_dialogMessage
- * @attr ref android.R.styleable#DialogPreference_dialogIcon
- * @attr ref android.R.styleable#DialogPreference_dialogLayout
- * @attr ref android.R.styleable#DialogPreference_positiveButtonText
- * @attr ref android.R.styleable#DialogPreference_negativeButtonText
- */
-public abstract class DialogPreference extends Preference implements
- DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
- PreferenceManager.OnActivityDestroyListener {
- private AlertDialog.Builder mBuilder;
-
- private CharSequence mDialogTitle;
- private CharSequence mDialogMessage;
- private Drawable mDialogIcon;
- private CharSequence mPositiveButtonText;
- private CharSequence mNegativeButtonText;
- private int mDialogLayoutResId;
-
- /** The dialog, if it is showing. */
- private Dialog mDialog;
-
- /** Which button was clicked. */
- private int mWhichButtonClicked;
-
- public DialogPreference(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.DialogPreference, defStyle, 0);
- mDialogTitle = a.getString(com.android.internal.R.styleable.DialogPreference_dialogTitle);
- if (mDialogTitle == null) {
- // Fallback on the regular title of the preference
- // (the one that is seen in the list)
- mDialogTitle = getTitle();
- }
- mDialogMessage = a.getString(com.android.internal.R.styleable.DialogPreference_dialogMessage);
- mDialogIcon = a.getDrawable(com.android.internal.R.styleable.DialogPreference_dialogIcon);
- mPositiveButtonText = a.getString(com.android.internal.R.styleable.DialogPreference_positiveButtonText);
- mNegativeButtonText = a.getString(com.android.internal.R.styleable.DialogPreference_negativeButtonText);
- mDialogLayoutResId = a.getResourceId(com.android.internal.R.styleable.DialogPreference_dialogLayout,
- mDialogLayoutResId);
- a.recycle();
-
- }
-
- public DialogPreference(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.dialogPreferenceStyle);
- }
-
- /**
- * Sets the title of the dialog. This will be shown on subsequent dialogs.
- *
- * @param dialogTitle The title.
- */
- public void setDialogTitle(CharSequence dialogTitle) {
- mDialogTitle = dialogTitle;
- }
-
- /**
- * @see #setDialogTitle(CharSequence)
- * @param dialogTitleResId The dialog title as a resource.
- */
- public void setDialogTitle(int dialogTitleResId) {
- setDialogTitle(getContext().getString(dialogTitleResId));
- }
-
- /**
- * Returns the title to be shown on subsequent dialogs.
- * @return The title.
- */
- public CharSequence getDialogTitle() {
- return mDialogTitle;
- }
-
- /**
- * Sets the message of the dialog. This will be shown on subsequent dialogs.
- * <p>
- * This message forms the content View of the dialog and conflicts with
- * list-based dialogs, for example. If setting a custom View on a dialog via
- * {@link #setDialogLayoutResource(int)}, include a text View with ID
- * {@link android.R.id#message} and it will be populated with this message.
- *
- * @param dialogMessage The message.
- */
- public void setDialogMessage(CharSequence dialogMessage) {
- mDialogMessage = dialogMessage;
- }
-
- /**
- * @see #setDialogMessage(CharSequence)
- * @param dialogMessageResId The dialog message as a resource.
- */
- public void setDialogMessage(int dialogMessageResId) {
- setDialogMessage(getContext().getString(dialogMessageResId));
- }
-
- /**
- * Returns the message to be shown on subsequent dialogs.
- * @return The message.
- */
- public CharSequence getDialogMessage() {
- return mDialogMessage;
- }
-
- /**
- * Sets the icon of the dialog. This will be shown on subsequent dialogs.
- *
- * @param dialogIcon The icon, as a {@link Drawable}.
- */
- public void setDialogIcon(Drawable dialogIcon) {
- mDialogIcon = dialogIcon;
- }
-
- /**
- * Sets the icon (resource ID) of the dialog. This will be shown on
- * subsequent dialogs.
- *
- * @param dialogIconRes The icon, as a resource ID.
- */
- public void setDialogIcon(int dialogIconRes) {
- mDialogIcon = getContext().getResources().getDrawable(dialogIconRes);
- }
-
- /**
- * Returns the icon to be shown on subsequent dialogs.
- * @return The icon, as a {@link Drawable}.
- */
- public Drawable getDialogIcon() {
- return mDialogIcon;
- }
-
- /**
- * Sets the text of the positive button of the dialog. This will be shown on
- * subsequent dialogs.
- *
- * @param positiveButtonText The text of the positive button.
- */
- public void setPositiveButtonText(CharSequence positiveButtonText) {
- mPositiveButtonText = positiveButtonText;
- }
-
- /**
- * @see #setPositiveButtonText(CharSequence)
- * @param positiveButtonTextResId The positive button text as a resource.
- */
- public void setPositiveButtonText(int positiveButtonTextResId) {
- setPositiveButtonText(getContext().getString(positiveButtonTextResId));
- }
-
- /**
- * Returns the text of the positive button to be shown on subsequent
- * dialogs.
- *
- * @return The text of the positive button.
- */
- public CharSequence getPositiveButtonText() {
- return mPositiveButtonText;
- }
-
- /**
- * Sets the text of the negative button of the dialog. This will be shown on
- * subsequent dialogs.
- *
- * @param negativeButtonText The text of the negative button.
- */
- public void setNegativeButtonText(CharSequence negativeButtonText) {
- mNegativeButtonText = negativeButtonText;
- }
-
- /**
- * @see #setNegativeButtonText(CharSequence)
- * @param negativeButtonTextResId The negative button text as a resource.
- */
- public void setNegativeButtonText(int negativeButtonTextResId) {
- setNegativeButtonText(getContext().getString(negativeButtonTextResId));
- }
-
- /**
- * Returns the text of the negative button to be shown on subsequent
- * dialogs.
- *
- * @return The text of the negative button.
- */
- public CharSequence getNegativeButtonText() {
- return mNegativeButtonText;
- }
-
- /**
- * Sets the layout resource that is inflated as the {@link View} to be shown
- * as the content View of subsequent dialogs.
- *
- * @param dialogLayoutResId The layout resource ID to be inflated.
- * @see #setDialogMessage(CharSequence)
- */
- public void setDialogLayoutResource(int dialogLayoutResId) {
- mDialogLayoutResId = dialogLayoutResId;
- }
-
- /**
- * Returns the layout resource that is used as the content View for
- * subsequent dialogs.
- *
- * @return The layout resource.
- */
- public int getDialogLayoutResource() {
- return mDialogLayoutResId;
- }
-
- /**
- * Prepares the dialog builder to be shown when the preference is clicked.
- * Use this to set custom properties on the dialog.
- * <p>
- * Do not {@link AlertDialog.Builder#create()} or
- * {@link AlertDialog.Builder#show()}.
- */
- protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
- }
-
- @Override
- protected void onClick() {
- showDialog(null);
- }
-
- /**
- * Shows the dialog associated with this Preference. This is normally initiated
- * automatically on clicking on the preference. Call this method if you need to
- * show the dialog on some other event.
- *
- * @param state Optional instance state to restore on the dialog
- */
- protected void showDialog(Bundle state) {
- Context context = getContext();
-
- mWhichButtonClicked = DialogInterface.BUTTON2;
-
- mBuilder = new AlertDialog.Builder(context)
- .setTitle(mDialogTitle)
- .setIcon(mDialogIcon)
- .setPositiveButton(mPositiveButtonText, this)
- .setNegativeButton(mNegativeButtonText, this);
-
- View contentView = onCreateDialogView();
- if (contentView != null) {
- onBindDialogView(contentView);
- mBuilder.setView(contentView);
- } else {
- mBuilder.setMessage(mDialogMessage);
- }
-
- onPrepareDialogBuilder(mBuilder);
-
- getPreferenceManager().registerOnActivityDestroyListener(this);
-
- // Create the dialog
- final Dialog dialog = mDialog = mBuilder.create();
- if (state != null) {
- dialog.onRestoreInstanceState(state);
- }
- dialog.setOnDismissListener(this);
- dialog.show();
- }
-
- /**
- * Creates the content view for the dialog (if a custom content view is
- * required). By default, it inflates the dialog layout resource if it is
- * set.
- *
- * @return The content View for the dialog.
- * @see #setLayoutResource(int)
- */
- protected View onCreateDialogView() {
- if (mDialogLayoutResId == 0) {
- return null;
- }
-
- LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- return inflater.inflate(mDialogLayoutResId, null);
- }
-
- /**
- * Binds views in the content View of the dialog to data.
- * <p>
- * Make sure to call through to the superclass implementation.
- *
- * @param view The content View of the dialog, if it is custom.
- */
- protected void onBindDialogView(View view) {
- View dialogMessageView = view.findViewById(com.android.internal.R.id.message);
-
- if (dialogMessageView != null) {
- final CharSequence message = getDialogMessage();
- int newVisibility = View.GONE;
-
- if (!TextUtils.isEmpty(message)) {
- if (dialogMessageView instanceof TextView) {
- ((TextView) dialogMessageView).setText(message);
- }
-
- newVisibility = View.VISIBLE;
- }
-
- if (dialogMessageView.getVisibility() != newVisibility) {
- dialogMessageView.setVisibility(newVisibility);
- }
- }
- }
-
- public void onClick(DialogInterface dialog, int which) {
- mWhichButtonClicked = which;
- }
-
- public void onDismiss(DialogInterface dialog) {
-
- getPreferenceManager().unregisterOnActivityDestroyListener(this);
-
- mDialog = null;
- onDialogClosed(mWhichButtonClicked == DialogInterface.BUTTON_POSITIVE);
- }
-
- /**
- * Called when the dialog is dismissed and should be used to save data to
- * the {@link SharedPreferences}.
- *
- * @param positiveResult Whether the positive button was clicked (true), or
- * the negative button was clicked or the dialog was canceled (false).
- */
- protected void onDialogClosed(boolean positiveResult) {
- }
-
- /**
- * Gets the dialog that is shown by this preference.
- *
- * @return The dialog, or null if a dialog is not being shown.
- */
- public Dialog getDialog() {
- return mDialog;
- }
-
- /**
- * {@inheritDoc}
- */
- public void onActivityDestroy() {
-
- if (mDialog == null || !mDialog.isShowing()) {
- return;
- }
-
- mDialog.dismiss();
- }
-
- @Override
- protected Parcelable onSaveInstanceState() {
- final Parcelable superState = super.onSaveInstanceState();
- if (mDialog == null || !mDialog.isShowing()) {
- return superState;
- }
-
- final SavedState myState = new SavedState(superState);
- myState.isDialogShowing = true;
- myState.dialogBundle = mDialog.onSaveInstanceState();
- return myState;
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- if (state == null || !state.getClass().equals(SavedState.class)) {
- // Didn't save state for us in onSaveInstanceState
- super.onRestoreInstanceState(state);
- return;
- }
-
- SavedState myState = (SavedState) state;
- super.onRestoreInstanceState(myState.getSuperState());
- if (myState.isDialogShowing) {
- showDialog(myState.dialogBundle);
- }
- }
-
- private static class SavedState extends BaseSavedState {
- boolean isDialogShowing;
- Bundle dialogBundle;
-
- public SavedState(Parcel source) {
- super(source);
- isDialogShowing = source.readInt() == 1;
- dialogBundle = source.readBundle();
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(isDialogShowing ? 1 : 0);
- dest.writeBundle(dialogBundle);
- }
-
- public SavedState(Parcelable superState) {
- super(superState);
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR =
- new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
-}
diff --git a/core/java/android/preference/EditTextPreference.java b/core/java/android/preference/EditTextPreference.java
deleted file mode 100644
index a12704f..0000000
--- a/core/java/android/preference/EditTextPreference.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.res.TypedArray;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-
-/**
- * A {@link Preference} that allows for string
- * input.
- * <p>
- * It is a subclass of {@link DialogPreference} and shows the {@link EditText}
- * in a dialog. This {@link EditText} can be modified either programmatically
- * via {@link #getEditText()}, or through XML by setting any EditText
- * attributes on the EditTextPreference.
- * <p>
- * This preference will store a string into the SharedPreferences.
- * <p>
- * See {@link android.R.styleable#EditText EditText Attributes}.
- */
-public class EditTextPreference extends DialogPreference {
- /**
- * The edit text shown in the dialog.
- */
- private EditText mEditText;
-
- private String mText;
-
- public EditTextPreference(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- mEditText = new EditText(context, attrs);
-
- // Give it an ID so it can be saved/restored
- mEditText.setId(com.android.internal.R.id.edit);
-
- /*
- * The preference framework and view framework both have an 'enabled'
- * attribute. Most likely, the 'enabled' specified in this XML is for
- * the preference framework, but it was also given to the view framework.
- * We reset the enabled state.
- */
- mEditText.setEnabled(true);
- }
-
- public EditTextPreference(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.editTextPreferenceStyle);
- }
-
- public EditTextPreference(Context context) {
- this(context, null);
- }
-
- /**
- * Saves the text to the {@link SharedPreferences}.
- *
- * @param text The text to save
- */
- public void setText(String text) {
- final boolean wasBlocking = shouldDisableDependents();
-
- mText = text;
-
- persistString(text);
-
- final boolean isBlocking = shouldDisableDependents();
- if (isBlocking != wasBlocking) {
- notifyDependencyChange(isBlocking);
- }
- }
-
- /**
- * Gets the text from the {@link SharedPreferences}.
- *
- * @return The current preference value.
- */
- public String getText() {
- return mText;
- }
-
- @Override
- protected void onBindDialogView(View view) {
- super.onBindDialogView(view);
-
- EditText editText = mEditText;
- editText.setText(getText());
-
- ViewParent oldParent = editText.getParent();
- if (oldParent != view) {
- if (oldParent != null) {
- ((ViewGroup) oldParent).removeView(editText);
- }
- onAddEditTextToDialogView(view, editText);
- }
- }
-
- /**
- * Adds the EditText widget of this preference to the dialog's view.
- *
- * @param dialogView The dialog view.
- */
- protected void onAddEditTextToDialogView(View dialogView, EditText editText) {
- ViewGroup container = (ViewGroup) dialogView
- .findViewById(com.android.internal.R.id.edittext_container);
- if (container != null) {
- container.addView(editText, ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- }
- }
-
- @Override
- protected void onDialogClosed(boolean positiveResult) {
- super.onDialogClosed(positiveResult);
-
- if (positiveResult) {
- String value = mEditText.getText().toString();
- if (callChangeListener(value)) {
- setText(value);
- }
- }
- }
-
- @Override
- protected Object onGetDefaultValue(TypedArray a, int index) {
- return a.getString(index);
- }
-
- @Override
- protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
- setText(restoreValue ? getPersistedString(mText) : (String) defaultValue);
- }
-
- @Override
- public boolean shouldDisableDependents() {
- return TextUtils.isEmpty(mText) || super.shouldDisableDependents();
- }
-
- /**
- * Returns the {@link EditText} widget that will be shown in the dialog.
- *
- * @return The {@link EditText} widget that will be shown in the dialog.
- */
- public EditText getEditText() {
- return mEditText;
- }
-
- @Override
- protected Parcelable onSaveInstanceState() {
- final Parcelable superState = super.onSaveInstanceState();
- if (isPersistent()) {
- // No need to save instance state since it's persistent
- return superState;
- }
-
- final SavedState myState = new SavedState(superState);
- myState.text = getText();
- return myState;
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- if (state == null || !state.getClass().equals(SavedState.class)) {
- // Didn't save state for us in onSaveInstanceState
- super.onRestoreInstanceState(state);
- return;
- }
-
- SavedState myState = (SavedState) state;
- super.onRestoreInstanceState(myState.getSuperState());
- setText(myState.text);
- }
-
- private static class SavedState extends BaseSavedState {
- String text;
-
- public SavedState(Parcel source) {
- super(source);
- text = source.readString();
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeString(text);
- }
-
- public SavedState(Parcelable superState) {
- super(superState);
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR =
- new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
-}
diff --git a/core/java/android/preference/GenericInflater.java b/core/java/android/preference/GenericInflater.java
deleted file mode 100644
index 3003290..0000000
--- a/core/java/android/preference/GenericInflater.java
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.util.HashMap;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-import android.content.res.XmlResourceParser;
-import android.util.AttributeSet;
-import android.util.Xml;
-import android.view.ContextThemeWrapper;
-import android.view.InflateException;
-import android.view.LayoutInflater;
-
-// TODO: fix generics
-/**
- * Generic XML inflater. This has been adapted from {@link LayoutInflater} and
- * quickly passed over to use generics.
- *
- * @hide
- * @param T The type of the items to inflate
- * @param P The type of parents (that is those items that contain other items).
- * Must implement {@link GenericInflater.Parent}
- */
-abstract class GenericInflater<T, P extends GenericInflater.Parent> {
- private final boolean DEBUG = false;
-
- protected final Context mContext;
-
- // these are optional, set by the caller
- private boolean mFactorySet;
- private Factory<T> mFactory;
-
- private final Object[] mConstructorArgs = new Object[2];
-
- private static final Class[] mConstructorSignature = new Class[] {
- Context.class, AttributeSet.class};
-
- private static final HashMap sConstructorMap = new HashMap();
-
- private String mDefaultPackage;
-
- public interface Parent<T> {
- public void addItemFromInflater(T child);
- }
-
- public interface Factory<T> {
- /**
- * Hook you can supply that is called when inflating from a
- * inflater. You can use this to customize the tag
- * names available in your XML files.
- * <p>
- * Note that it is good practice to prefix these custom names with your
- * package (i.e., com.coolcompany.apps) to avoid conflicts with system
- * names.
- *
- * @param name Tag name to be inflated.
- * @param context The context the item is being created in.
- * @param attrs Inflation attributes as specified in XML file.
- * @return Newly created item. Return null for the default behavior.
- */
- public T onCreateItem(String name, Context context, AttributeSet attrs);
- }
-
- private static class FactoryMerger<T> implements Factory<T> {
- private final Factory<T> mF1, mF2;
-
- FactoryMerger(Factory<T> f1, Factory<T> f2) {
- mF1 = f1;
- mF2 = f2;
- }
-
- public T onCreateItem(String name, Context context, AttributeSet attrs) {
- T v = mF1.onCreateItem(name, context, attrs);
- if (v != null) return v;
- return mF2.onCreateItem(name, context, attrs);
- }
- }
-
- /**
- * Create a new inflater instance associated with a
- * particular Context.
- *
- * @param context The Context in which this inflater will
- * create its items; most importantly, this supplies the theme
- * from which the default values for their attributes are
- * retrieved.
- */
- protected GenericInflater(Context context) {
- mContext = context;
- }
-
- /**
- * Create a new inflater instance that is a copy of an
- * existing inflater, optionally with its Context
- * changed. For use in implementing {@link #cloneInContext}.
- *
- * @param original The original inflater to copy.
- * @param newContext The new Context to use.
- */
- protected GenericInflater(GenericInflater<T,P> original, Context newContext) {
- mContext = newContext;
- mFactory = original.mFactory;
- }
-
- /**
- * Create a copy of the existing inflater object, with the copy
- * pointing to a different Context than the original. This is used by
- * {@link ContextThemeWrapper} to create a new inflater to go along
- * with the new Context theme.
- *
- * @param newContext The new Context to associate with the new inflater.
- * May be the same as the original Context if desired.
- *
- * @return Returns a brand spanking new inflater object associated with
- * the given Context.
- */
- public abstract GenericInflater cloneInContext(Context newContext);
-
- /**
- * Sets the default package that will be searched for classes to construct
- * for tag names that have no explicit package.
- *
- * @param defaultPackage The default package. This will be prepended to the
- * tag name, so it should end with a period.
- */
- public void setDefaultPackage(String defaultPackage) {
- mDefaultPackage = defaultPackage;
- }
-
- /**
- * Returns the default package, or null if it is not set.
- *
- * @see #setDefaultPackage(String)
- * @return The default package.
- */
- public String getDefaultPackage() {
- return mDefaultPackage;
- }
-
- /**
- * Return the context we are running in, for access to resources, class
- * loader, etc.
- */
- public Context getContext() {
- return mContext;
- }
-
- /**
- * Return the current factory (or null). This is called on each element
- * name. If the factory returns an item, add that to the hierarchy. If it
- * returns null, proceed to call onCreateItem(name).
- */
- public final Factory<T> getFactory() {
- return mFactory;
- }
-
- /**
- * Attach a custom Factory interface for creating items while using this
- * inflater. This must not be null, and can only be set
- * once; after setting, you can not change the factory. This is called on
- * each element name as the XML is parsed. If the factory returns an item,
- * that is added to the hierarchy. If it returns null, the next factory
- * default {@link #onCreateItem} method is called.
- * <p>
- * If you have an existing inflater and want to add your
- * own factory to it, use {@link #cloneInContext} to clone the existing
- * instance and then you can use this function (once) on the returned new
- * instance. This will merge your own factory with whatever factory the
- * original instance is using.
- */
- public void setFactory(Factory<T> factory) {
- if (mFactorySet) {
- throw new IllegalStateException("" +
- "A factory has already been set on this inflater");
- }
- if (factory == null) {
- throw new NullPointerException("Given factory can not be null");
- }
- mFactorySet = true;
- if (mFactory == null) {
- mFactory = factory;
- } else {
- mFactory = new FactoryMerger<T>(factory, mFactory);
- }
- }
-
-
- /**
- * Inflate a new item hierarchy from the specified xml resource. Throws
- * InflaterException if there is an error.
- *
- * @param resource ID for an XML resource to load (e.g.,
- * <code>R.layout.main_page</code>)
- * @param root Optional parent of the generated hierarchy.
- * @return The root of the inflated hierarchy. If root was supplied,
- * this is the root item; otherwise it is the root of the inflated
- * XML file.
- */
- public T inflate(int resource, P root) {
- return inflate(resource, root, root != null);
- }
-
- /**
- * Inflate a new hierarchy from the specified xml node. Throws
- * InflaterException if there is an error. *
- * <p>
- * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance
- * reasons, inflation relies heavily on pre-processing of XML files
- * that is done at build time. Therefore, it is not currently possible to
- * use inflater with an XmlPullParser over a plain XML file at runtime.
- *
- * @param parser XML dom node containing the description of the
- * hierarchy.
- * @param root Optional parent of the generated hierarchy.
- * @return The root of the inflated hierarchy. If root was supplied,
- * this is the that; otherwise it is the root of the inflated
- * XML file.
- */
- public T inflate(XmlPullParser parser, P root) {
- return inflate(parser, root, root != null);
- }
-
- /**
- * Inflate a new hierarchy from the specified xml resource. Throws
- * InflaterException if there is an error.
- *
- * @param resource ID for an XML resource to load (e.g.,
- * <code>R.layout.main_page</code>)
- * @param root Optional root to be the parent of the generated hierarchy (if
- * <em>attachToRoot</em> is true), or else simply an object that
- * provides a set of values for root of the returned
- * hierarchy (if <em>attachToRoot</em> is false.)
- * @param attachToRoot Whether the inflated hierarchy should be attached to
- * the root parameter?
- * @return The root of the inflated hierarchy. If root was supplied and
- * attachToRoot is true, this is root; otherwise it is the root of
- * the inflated XML file.
- */
- public T inflate(int resource, P root, boolean attachToRoot) {
- if (DEBUG) System.out.println("INFLATING from resource: " + resource);
- XmlResourceParser parser = getContext().getResources().getXml(resource);
- try {
- return inflate(parser, root, attachToRoot);
- } finally {
- parser.close();
- }
- }
-
- /**
- * Inflate a new hierarchy from the specified XML node. Throws
- * InflaterException if there is an error.
- * <p>
- * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance
- * reasons, inflation relies heavily on pre-processing of XML files
- * that is done at build time. Therefore, it is not currently possible to
- * use inflater with an XmlPullParser over a plain XML file at runtime.
- *
- * @param parser XML dom node containing the description of the
- * hierarchy.
- * @param root Optional to be the parent of the generated hierarchy (if
- * <em>attachToRoot</em> is true), or else simply an object that
- * provides a set of values for root of the returned
- * hierarchy (if <em>attachToRoot</em> is false.)
- * @param attachToRoot Whether the inflated hierarchy should be attached to
- * the root parameter?
- * @return The root of the inflated hierarchy. If root was supplied and
- * attachToRoot is true, this is root; otherwise it is the root of
- * the inflated XML file.
- */
- public T inflate(XmlPullParser parser, P root,
- boolean attachToRoot) {
- synchronized (mConstructorArgs) {
- final AttributeSet attrs = Xml.asAttributeSet(parser);
- mConstructorArgs[0] = mContext;
- T result = (T) root;
-
- try {
- // Look for the root node.
- int type;
- while ((type = parser.next()) != parser.START_TAG
- && type != parser.END_DOCUMENT) {
- ;
- }
-
- if (type != parser.START_TAG) {
- throw new InflateException(parser.getPositionDescription()
- + ": No start tag found!");
- }
-
- if (DEBUG) {
- System.out.println("**************************");
- System.out.println("Creating root: "
- + parser.getName());
- System.out.println("**************************");
- }
- // Temp is the root that was found in the xml
- T xmlRoot = createItemFromTag(parser, parser.getName(),
- attrs);
-
- result = (T) onMergeRoots(root, attachToRoot, (P) xmlRoot);
-
- if (DEBUG) {
- System.out.println("-----> start inflating children");
- }
- // Inflate all children under temp
- rInflate(parser, result, attrs);
- if (DEBUG) {
- System.out.println("-----> done inflating children");
- }
-
- } catch (InflateException e) {
- throw e;
-
- } catch (XmlPullParserException e) {
- InflateException ex = new InflateException(e.getMessage());
- ex.initCause(e);
- throw ex;
- } catch (IOException e) {
- InflateException ex = new InflateException(
- parser.getPositionDescription()
- + ": " + e.getMessage());
- ex.initCause(e);
- throw ex;
- }
-
- return result;
- }
- }
-
- /**
- * Low-level function for instantiating by name. This attempts to
- * instantiate class of the given <var>name</var> found in this
- * inflater's ClassLoader.
- *
- * <p>
- * There are two things that can happen in an error case: either the
- * exception describing the error will be thrown, or a null will be
- * returned. You must deal with both possibilities -- the former will happen
- * the first time createItem() is called for a class of a particular name,
- * the latter every time there-after for that class name.
- *
- * @param name The full name of the class to be instantiated.
- * @param attrs The XML attributes supplied for this instance.
- *
- * @return The newly instantied item, or null.
- */
- public final T createItem(String name, String prefix, AttributeSet attrs)
- throws ClassNotFoundException, InflateException {
- Constructor constructor = (Constructor) sConstructorMap.get(name);
-
- try {
- if (null == constructor) {
- // Class not found in the cache, see if it's real,
- // and try to add it
- Class clazz = mContext.getClassLoader().loadClass(
- prefix != null ? (prefix + name) : name);
- constructor = clazz.getConstructor(mConstructorSignature);
- sConstructorMap.put(name, constructor);
- }
-
- Object[] args = mConstructorArgs;
- args[1] = attrs;
- return (T) constructor.newInstance(args);
-
- } catch (NoSuchMethodException e) {
- InflateException ie = new InflateException(attrs
- .getPositionDescription()
- + ": Error inflating class "
- + (prefix != null ? (prefix + name) : name));
- ie.initCause(e);
- throw ie;
-
- } catch (ClassNotFoundException e) {
- // If loadClass fails, we should propagate the exception.
- throw e;
- } catch (Exception e) {
- InflateException ie = new InflateException(attrs
- .getPositionDescription()
- + ": Error inflating class "
- + constructor.getClass().getName());
- ie.initCause(e);
- throw ie;
- }
- }
-
- /**
- * This routine is responsible for creating the correct subclass of item
- * given the xml element name. Override it to handle custom item objects. If
- * you override this in your subclass be sure to call through to
- * super.onCreateItem(name) for names you do not recognize.
- *
- * @param name The fully qualified class name of the item to be create.
- * @param attrs An AttributeSet of attributes to apply to the item.
- * @return The item created.
- */
- protected T onCreateItem(String name, AttributeSet attrs) throws ClassNotFoundException {
- return createItem(name, mDefaultPackage, attrs);
- }
-
- private final T createItemFromTag(XmlPullParser parser, String name, AttributeSet attrs) {
- if (DEBUG) System.out.println("******** Creating item: " + name);
-
- try {
- T item = (mFactory == null) ? null : mFactory.onCreateItem(name, mContext, attrs);
-
- if (item == null) {
- if (-1 == name.indexOf('.')) {
- item = onCreateItem(name, attrs);
- } else {
- item = createItem(name, null, attrs);
- }
- }
-
- if (DEBUG) System.out.println("Created item is: " + item);
- return item;
-
- } catch (InflateException e) {
- throw e;
-
- } catch (ClassNotFoundException e) {
- InflateException ie = new InflateException(attrs
- .getPositionDescription()
- + ": Error inflating class " + name);
- ie.initCause(e);
- throw ie;
-
- } catch (Exception e) {
- InflateException ie = new InflateException(attrs
- .getPositionDescription()
- + ": Error inflating class " + name);
- ie.initCause(e);
- throw ie;
- }
- }
-
- /**
- * Recursive method used to descend down the xml hierarchy and instantiate
- * items, instantiate their children, and then call onFinishInflate().
- */
- private void rInflate(XmlPullParser parser, T parent, final AttributeSet attrs)
- throws XmlPullParserException, IOException {
- final int depth = parser.getDepth();
-
- int type;
- while (((type = parser.next()) != parser.END_TAG ||
- parser.getDepth() > depth) && type != parser.END_DOCUMENT) {
-
- if (type != parser.START_TAG) {
- continue;
- }
-
- if (onCreateCustomFromTag(parser, parent, attrs)) {
- continue;
- }
-
- if (DEBUG) {
- System.out.println("Now inflating tag: " + parser.getName());
- }
- String name = parser.getName();
-
- T item = createItemFromTag(parser, name, attrs);
-
- if (DEBUG) {
- System.out
- .println("Creating params from parent: " + parent);
- }
-
- ((P) parent).addItemFromInflater(item);
-
- if (DEBUG) {
- System.out.println("-----> start inflating children");
- }
- rInflate(parser, item, attrs);
- if (DEBUG) {
- System.out.println("-----> done inflating children");
- }
- }
-
- }
-
- /**
- * Before this inflater tries to create an item from the tag, this method
- * will be called. The parser will be pointing to the start of a tag, you
- * must stop parsing and return when you reach the end of this element!
- *
- * @param parser XML dom node containing the description of the hierarchy.
- * @param parent The item that should be the parent of whatever you create.
- * @param attrs An AttributeSet of attributes to apply to the item.
- * @return Whether you created a custom object (true), or whether this
- * inflater should proceed to create an item.
- */
- protected boolean onCreateCustomFromTag(XmlPullParser parser, T parent,
- final AttributeSet attrs) throws XmlPullParserException {
- return false;
- }
-
- protected P onMergeRoots(P givenRoot, boolean attachToGivenRoot, P xmlRoot) {
- return xmlRoot;
- }
-}
diff --git a/core/java/android/preference/ListPreference.java b/core/java/android/preference/ListPreference.java
deleted file mode 100644
index f842d75..0000000
--- a/core/java/android/preference/ListPreference.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-
-import android.app.AlertDialog.Builder;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.res.TypedArray;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-
-/**
- * A {@link Preference} that displays a list of entries as
- * a dialog.
- * <p>
- * This preference will store a string into the SharedPreferences. This string will be the value
- * from the {@link #setEntryValues(CharSequence[])} array.
- *
- * @attr ref android.R.styleable#ListPreference_entries
- * @attr ref android.R.styleable#ListPreference_entryValues
- */
-public class ListPreference extends DialogPreference {
- private CharSequence[] mEntries;
- private CharSequence[] mEntryValues;
- private String mValue;
- private int mClickedDialogEntryIndex;
-
- public ListPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.ListPreference, 0, 0);
- mEntries = a.getTextArray(com.android.internal.R.styleable.ListPreference_entries);
- mEntryValues = a.getTextArray(com.android.internal.R.styleable.ListPreference_entryValues);
- a.recycle();
- }
-
- public ListPreference(Context context) {
- this(context, null);
- }
-
- /**
- * Sets the human-readable entries to be shown in the list. This will be
- * shown in subsequent dialogs.
- * <p>
- * Each entry must have a corresponding index in
- * {@link #setEntryValues(CharSequence[])}.
- *
- * @param entries The entries.
- * @see #setEntryValues(CharSequence[])
- */
- public void setEntries(CharSequence[] entries) {
- mEntries = entries;
- }
-
- /**
- * @see #setEntries(CharSequence[])
- * @param entriesResId The entries array as a resource.
- */
- public void setEntries(int entriesResId) {
- setEntries(getContext().getResources().getTextArray(entriesResId));
- }
-
- /**
- * The list of entries to be shown in the list in subsequent dialogs.
- *
- * @return The list as an array.
- */
- public CharSequence[] getEntries() {
- return mEntries;
- }
-
- /**
- * The array to find the value to save for a preference when an entry from
- * entries is selected. If a user clicks on the second item in entries, the
- * second item in this array will be saved to the preference.
- *
- * @param entryValues The array to be used as values to save for the preference.
- */
- public void setEntryValues(CharSequence[] entryValues) {
- mEntryValues = entryValues;
- }
-
- /**
- * @see #setEntryValues(CharSequence[])
- * @param entryValuesResId The entry values array as a resource.
- */
- public void setEntryValues(int entryValuesResId) {
- setEntryValues(getContext().getResources().getTextArray(entryValuesResId));
- }
-
- /**
- * Returns the array of values to be saved for the preference.
- *
- * @return The array of values.
- */
- public CharSequence[] getEntryValues() {
- return mEntryValues;
- }
-
- /**
- * Sets the value of the key. This should be one of the entries in
- * {@link #getEntryValues()}.
- *
- * @param value The value to set for the key.
- */
- public void setValue(String value) {
- mValue = value;
-
- persistString(value);
- }
-
- /**
- * Sets the value to the given index from the entry values.
- *
- * @param index The index of the value to set.
- */
- public void setValueIndex(int index) {
- if (mEntryValues != null) {
- setValue(mEntryValues[index].toString());
- }
- }
-
- /**
- * Returns the value of the key. This should be one of the entries in
- * {@link #getEntryValues()}.
- *
- * @return The value of the key.
- */
- public String getValue() {
- return mValue;
- }
-
- /**
- * Returns the entry corresponding to the current value.
- *
- * @return The entry corresponding to the current value, or null.
- */
- public CharSequence getEntry() {
- int index = getValueIndex();
- return index >= 0 && mEntries != null ? mEntries[index] : null;
- }
-
- /**
- * Returns the index of the given value (in the entry values array).
- *
- * @param value The value whose index should be returned.
- * @return The index of the value, or -1 if not found.
- */
- public int findIndexOfValue(String value) {
- if (value != null && mEntryValues != null) {
- for (int i = mEntryValues.length - 1; i >= 0; i--) {
- if (mEntryValues[i].equals(value)) {
- return i;
- }
- }
- }
- return -1;
- }
-
- private int getValueIndex() {
- return findIndexOfValue(mValue);
- }
-
- @Override
- protected void onPrepareDialogBuilder(Builder builder) {
- super.onPrepareDialogBuilder(builder);
-
- if (mEntries == null || mEntryValues == null) {
- throw new IllegalStateException(
- "ListPreference requires an entries array and an entryValues array.");
- }
-
- mClickedDialogEntryIndex = getValueIndex();
- builder.setSingleChoiceItems(mEntries, mClickedDialogEntryIndex,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- mClickedDialogEntryIndex = which;
-
- /*
- * Clicking on an item simulates the positive button
- * click, and dismisses the dialog.
- */
- ListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
- dialog.dismiss();
- }
- });
-
- /*
- * The typical interaction for list-based dialogs is to have
- * click-on-an-item dismiss the dialog instead of the user having to
- * press 'Ok'.
- */
- builder.setPositiveButton(null, null);
- }
-
- @Override
- protected void onDialogClosed(boolean positiveResult) {
- super.onDialogClosed(positiveResult);
-
- if (positiveResult && mClickedDialogEntryIndex >= 0 && mEntryValues != null) {
- String value = mEntryValues[mClickedDialogEntryIndex].toString();
- if (callChangeListener(value)) {
- setValue(value);
- }
- }
- }
-
- @Override
- protected Object onGetDefaultValue(TypedArray a, int index) {
- return a.getString(index);
- }
-
- @Override
- protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
- setValue(restoreValue ? getPersistedString(mValue) : (String) defaultValue);
- }
-
- @Override
- protected Parcelable onSaveInstanceState() {
- final Parcelable superState = super.onSaveInstanceState();
- if (isPersistent()) {
- // No need to save instance state since it's persistent
- return superState;
- }
-
- final SavedState myState = new SavedState(superState);
- myState.value = getValue();
- return myState;
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- if (state == null || !state.getClass().equals(SavedState.class)) {
- // Didn't save state for us in onSaveInstanceState
- super.onRestoreInstanceState(state);
- return;
- }
-
- SavedState myState = (SavedState) state;
- super.onRestoreInstanceState(myState.getSuperState());
- setValue(myState.value);
- }
-
- private static class SavedState extends BaseSavedState {
- String value;
-
- public SavedState(Parcel source) {
- super(source);
- value = source.readString();
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeString(value);
- }
-
- public SavedState(Parcelable superState) {
- super(superState);
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR =
- new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
-}
diff --git a/core/java/android/preference/OnDependencyChangeListener.java b/core/java/android/preference/OnDependencyChangeListener.java
deleted file mode 100644
index ce25e34..0000000
--- a/core/java/android/preference/OnDependencyChangeListener.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-/**
- * Interface definition for a callback to be invoked when this
- * {@link Preference} changes with respect to enabling/disabling
- * dependents.
- */
-interface OnDependencyChangeListener {
- /**
- * Called when this preference has changed in a way that dependents should
- * care to change their state.
- *
- * @param disablesDependent Whether the dependent should be disabled.
- */
- void onDependencyChanged(Preference dependency, boolean disablesDependent);
-}
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
deleted file mode 100644
index a255438..0000000
--- a/core/java/android/preference/Preference.java
+++ /dev/null
@@ -1,1586 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.res.TypedArray;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import com.android.internal.util.CharSequences;
-import android.view.AbsSavedState;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ListView;
-import android.widget.TextView;
-
-/**
- * Represents the basic Preference UI building
- * block displayed by a {@link PreferenceActivity} in the form of a
- * {@link ListView}. This class provides the {@link View} to be displayed in
- * the activity and associates with a {@link SharedPreferences} to
- * store/retrieve the preference data.
- * <p>
- * When specifying a preference hierarchy in XML, each element can point to a
- * subclass of {@link Preference}, similar to the view hierarchy and layouts.
- * <p>
- * This class contains a {@code key} that will be used as the key into the
- * {@link SharedPreferences}. It is up to the subclass to decide how to store
- * the value.
- *
- * @attr ref android.R.styleable#Preference_key
- * @attr ref android.R.styleable#Preference_title
- * @attr ref android.R.styleable#Preference_summary
- * @attr ref android.R.styleable#Preference_order
- * @attr ref android.R.styleable#Preference_layout
- * @attr ref android.R.styleable#Preference_widgetLayout
- * @attr ref android.R.styleable#Preference_enabled
- * @attr ref android.R.styleable#Preference_selectable
- * @attr ref android.R.styleable#Preference_dependency
- * @attr ref android.R.styleable#Preference_persistent
- * @attr ref android.R.styleable#Preference_defaultValue
- * @attr ref android.R.styleable#Preference_shouldDisableView
- */
-public class Preference implements Comparable<Preference>, OnDependencyChangeListener {
- /**
- * Specify for {@link #setOrder(int)} if a specific order is not required.
- */
- public static final int DEFAULT_ORDER = Integer.MAX_VALUE;
-
- private Context mContext;
- private PreferenceManager mPreferenceManager;
-
- /**
- * Set when added to hierarchy since we need a unique ID within that
- * hierarchy.
- */
- private long mId;
-
- private OnPreferenceChangeListener mOnChangeListener;
- private OnPreferenceClickListener mOnClickListener;
-
- private int mOrder = DEFAULT_ORDER;
- private CharSequence mTitle;
- private CharSequence mSummary;
- private String mKey;
- private Intent mIntent;
- private boolean mEnabled = true;
- private boolean mSelectable = true;
- private boolean mRequiresKey;
- private boolean mPersistent = true;
- private String mDependencyKey;
- private Object mDefaultValue;
-
- /**
- * @see #setShouldDisableView(boolean)
- */
- private boolean mShouldDisableView = true;
-
- private int mLayoutResId = com.android.internal.R.layout.preference;
- private int mWidgetLayoutResId;
- private boolean mHasSpecifiedLayout = false;
-
- private OnPreferenceChangeInternalListener mListener;
-
- private List<Preference> mDependents;
-
- private boolean mBaseMethodCalled;
-
- /**
- * Interface definition for a callback to be invoked when the value of this
- * {@link Preference} has been changed by the user and is
- * about to be set and/or persisted. This gives the client a chance
- * to prevent setting and/or persisting the value.
- */
- public interface OnPreferenceChangeListener {
- /**
- * Called when a Preference has been changed by the user. This is
- * called before the state of the Preference is about to be updated and
- * before the state is persisted.
- *
- * @param preference The changed Preference.
- * @param newValue The new value of the Preference.
- * @return True to update the state of the Preference with the new value.
- */
- boolean onPreferenceChange(Preference preference, Object newValue);
- }
-
- /**
- * Interface definition for a callback to be invoked when a {@link Preference} is
- * clicked.
- */
- public interface OnPreferenceClickListener {
- /**
- * Called when a Preference has been clicked.
- *
- * @param preference The Preference that was clicked.
- * @return True if the click was handled.
- */
- boolean onPreferenceClick(Preference preference);
- }
-
- /**
- * Interface definition for a callback to be invoked when this
- * {@link Preference} is changed or, if this is a group, there is an
- * addition/removal of {@link Preference}(s). This is used internally.
- */
- interface OnPreferenceChangeInternalListener {
- /**
- * Called when this Preference has changed.
- *
- * @param preference This preference.
- */
- void onPreferenceChange(Preference preference);
-
- /**
- * Called when this group has added/removed {@link Preference}(s).
- *
- * @param preference This Preference.
- */
- void onPreferenceHierarchyChange(Preference preference);
- }
-
- /**
- * Perform inflation from XML and apply a class-specific base style. This
- * constructor of Preference allows subclasses to use their own base
- * style when they are inflating. For example, a {@link CheckBoxPreference}
- * constructor calls this version of the super class constructor and
- * supplies {@code android.R.attr.checkBoxPreferenceStyle} for <var>defStyle</var>.
- * This allows the theme's checkbox preference style to modify all of the base
- * preference attributes as well as the {@link CheckBoxPreference} class's
- * attributes.
- *
- * @param context The Context this is associated with, through which it can
- * access the current theme, resources, {@link SharedPreferences},
- * etc.
- * @param attrs The attributes of the XML tag that is inflating the preference.
- * @param defStyle The default style to apply to this preference. If 0, no style
- * will be applied (beyond what is included in the theme). This
- * may either be an attribute resource, whose value will be
- * retrieved from the current theme, or an explicit style
- * resource.
- * @see #Preference(Context, AttributeSet)
- */
- public Preference(Context context, AttributeSet attrs, int defStyle) {
- mContext = context;
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.Preference);
- if (a.hasValue(com.android.internal.R.styleable.Preference_layout) ||
- a.hasValue(com.android.internal.R.styleable.Preference_widgetLayout)) {
- // This preference has a custom layout defined (not one taken from
- // the default style)
- mHasSpecifiedLayout = true;
- }
- a.recycle();
-
- a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Preference,
- defStyle, 0);
- for (int i = a.getIndexCount(); i >= 0; i--) {
- int attr = a.getIndex(i);
- switch (attr) {
- case com.android.internal.R.styleable.Preference_key:
- mKey = a.getString(attr);
- break;
-
- case com.android.internal.R.styleable.Preference_title:
- mTitle = a.getString(attr);
- break;
-
- case com.android.internal.R.styleable.Preference_summary:
- mSummary = a.getString(attr);
- break;
-
- case com.android.internal.R.styleable.Preference_order:
- mOrder = a.getInt(attr, mOrder);
- break;
-
- case com.android.internal.R.styleable.Preference_layout:
- mLayoutResId = a.getResourceId(attr, mLayoutResId);
- break;
-
- case com.android.internal.R.styleable.Preference_widgetLayout:
- mWidgetLayoutResId = a.getResourceId(attr, mWidgetLayoutResId);
- break;
-
- case com.android.internal.R.styleable.Preference_enabled:
- mEnabled = a.getBoolean(attr, true);
- break;
-
- case com.android.internal.R.styleable.Preference_selectable:
- mSelectable = a.getBoolean(attr, true);
- break;
-
- case com.android.internal.R.styleable.Preference_persistent:
- mPersistent = a.getBoolean(attr, mPersistent);
- break;
-
- case com.android.internal.R.styleable.Preference_dependency:
- mDependencyKey = a.getString(attr);
- break;
-
- case com.android.internal.R.styleable.Preference_defaultValue:
- mDefaultValue = onGetDefaultValue(a, attr);
- break;
-
- case com.android.internal.R.styleable.Preference_shouldDisableView:
- mShouldDisableView = a.getBoolean(attr, mShouldDisableView);
- break;
- }
- }
- a.recycle();
- }
-
- /**
- * Constructor that is called when inflating a Preference from XML. This is
- * called when a Preference is being constructed from an XML file, supplying
- * attributes that were specified in the XML file. This version uses a
- * default style of 0, so the only attribute values applied are those in the
- * Context's Theme and the given AttributeSet.
- *
- * @param context The Context this is associated with, through which it can
- * access the current theme, resources, {@link SharedPreferences},
- * etc.
- * @param attrs The attributes of the XML tag that is inflating the
- * preference.
- * @see #Preference(Context, AttributeSet, int)
- */
- public Preference(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- /**
- * Constructor to create a Preference.
- *
- * @param context The Context in which to store Preference values.
- */
- public Preference(Context context) {
- this(context, null);
- }
-
- /**
- * Called when a Preference is being inflated and the default value
- * attribute needs to be read. Since different Preference types have
- * different value types, the subclass should get and return the default
- * value which will be its value type.
- * <p>
- * For example, if the value type is String, the body of the method would
- * proxy to {@link TypedArray#getString(int)}.
- *
- * @param a The set of attributes.
- * @param index The index of the default value attribute.
- * @return The default value of this preference type.
- */
- protected Object onGetDefaultValue(TypedArray a, int index) {
- return null;
- }
-
- /**
- * Sets an {@link Intent} to be used for
- * {@link Context#startActivity(Intent)} when this Preference is clicked.
- *
- * @param intent The intent associated with this Preference.
- */
- public void setIntent(Intent intent) {
- mIntent = intent;
- }
-
- /**
- * Return the {@link Intent} associated with this Preference.
- *
- * @return The {@link Intent} last set via {@link #setIntent(Intent)} or XML.
- */
- public Intent getIntent() {
- return mIntent;
- }
-
- /**
- * Sets the layout resource that is inflated as the {@link View} to be shown
- * for this Preference. In most cases, the default layout is sufficient for
- * custom Preference objects and only the widget layout needs to be changed.
- * <p>
- * This layout should contain a {@link ViewGroup} with ID
- * {@link android.R.id#widget_frame} to be the parent of the specific widget
- * for this Preference. It should similarly contain
- * {@link android.R.id#title} and {@link android.R.id#summary}.
- *
- * @param layoutResId The layout resource ID to be inflated and returned as
- * a {@link View}.
- * @see #setWidgetLayoutResource(int)
- */
- public void setLayoutResource(int layoutResId) {
-
- if (!mHasSpecifiedLayout) {
- mHasSpecifiedLayout = true;
- }
-
- mLayoutResId = layoutResId;
- }
-
- /**
- * Gets the layout resource that will be shown as the {@link View} for this Preference.
- *
- * @return The layout resource ID.
- */
- public int getLayoutResource() {
- return mLayoutResId;
- }
-
- /**
- * Sets The layout for the controllable widget portion of this Preference. This
- * is inflated into the main layout. For example, a {@link CheckBoxPreference}
- * would specify a custom layout (consisting of just the CheckBox) here,
- * instead of creating its own main layout.
- *
- * @param widgetLayoutResId The layout resource ID to be inflated into the
- * main layout.
- * @see #setLayoutResource(int)
- */
- public void setWidgetLayoutResource(int widgetLayoutResId) {
- mWidgetLayoutResId = widgetLayoutResId;
- }
-
- /**
- * Gets the layout resource for the controllable widget portion of this Preference.
- *
- * @return The layout resource ID.
- */
- public int getWidgetLayoutResource() {
- return mWidgetLayoutResId;
- }
-
- /**
- * Gets the View that will be shown in the {@link PreferenceActivity}.
- *
- * @param convertView The old View to reuse, if possible. Note: You should
- * check that this View is non-null and of an appropriate type
- * before using. If it is not possible to convert this View to
- * display the correct data, this method can create a new View.
- * @param parent The parent that this View will eventually be attached to.
- * @return Returns the same Preference object, for chaining multiple calls
- * into a single statement.
- * @see #onCreateView(ViewGroup)
- * @see #onBindView(View)
- */
- public View getView(View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = onCreateView(parent);
- }
- onBindView(convertView);
- return convertView;
- }
-
- /**
- * Creates the View to be shown for this Preference in the
- * {@link PreferenceActivity}. The default behavior is to inflate the main
- * layout of this Preference (see {@link #setLayoutResource(int)}. If
- * changing this behavior, please specify a {@link ViewGroup} with ID
- * {@link android.R.id#widget_frame}.
- * <p>
- * Make sure to call through to the superclass's implementation.
- *
- * @param parent The parent that this View will eventually be attached to.
- * @return The View that displays this Preference.
- * @see #onBindView(View)
- */
- protected View onCreateView(ViewGroup parent) {
- final LayoutInflater layoutInflater =
- (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- final View layout = layoutInflater.inflate(mLayoutResId, parent, false);
-
- if (mWidgetLayoutResId != 0) {
- final ViewGroup widgetFrame = (ViewGroup)layout.findViewById(com.android.internal.R.id.widget_frame);
- layoutInflater.inflate(mWidgetLayoutResId, widgetFrame);
- }
-
- return layout;
- }
-
- /**
- * Binds the created View to the data for this Preference.
- * <p>
- * This is a good place to grab references to custom Views in the layout and
- * set properties on them.
- * <p>
- * Make sure to call through to the superclass's implementation.
- *
- * @param view The View that shows this Preference.
- * @see #onCreateView(ViewGroup)
- */
- protected void onBindView(View view) {
- TextView textView = (TextView) view.findViewById(com.android.internal.R.id.title);
- if (textView != null) {
- textView.setText(getTitle());
- }
-
- textView = (TextView) view.findViewById(com.android.internal.R.id.summary);
- if (textView != null) {
- final CharSequence summary = getSummary();
- if (!TextUtils.isEmpty(summary)) {
- if (textView.getVisibility() != View.VISIBLE) {
- textView.setVisibility(View.VISIBLE);
- }
-
- textView.setText(getSummary());
- } else {
- if (textView.getVisibility() != View.GONE) {
- textView.setVisibility(View.GONE);
- }
- }
- }
-
- if (mShouldDisableView) {
- setEnabledStateOnViews(view, isEnabled());
- }
- }
-
- /**
- * Makes sure the view (and any children) get the enabled state changed.
- */
- private void setEnabledStateOnViews(View v, boolean enabled) {
- v.setEnabled(enabled);
-
- if (v instanceof ViewGroup) {
- final ViewGroup vg = (ViewGroup) v;
- for (int i = vg.getChildCount() - 1; i >= 0; i--) {
- setEnabledStateOnViews(vg.getChildAt(i), enabled);
- }
- }
- }
-
- /**
- * Sets the order of this Preference with respect to other
- * Preference objects on the same level. If this is not specified, the
- * default behavior is to sort alphabetically. The
- * {@link PreferenceGroup#setOrderingAsAdded(boolean)} can be used to order
- * Preference objects based on the order they appear in the XML.
- *
- * @param order The order for this Preference. A lower value will be shown
- * first. Use {@link #DEFAULT_ORDER} to sort alphabetically or
- * allow ordering from XML.
- * @see PreferenceGroup#setOrderingAsAdded(boolean)
- * @see #DEFAULT_ORDER
- */
- public void setOrder(int order) {
- if (order != mOrder) {
- mOrder = order;
-
- // Reorder the list
- notifyHierarchyChanged();
- }
- }
-
- /**
- * Gets the order of this Preference with respect to other Preference objects
- * on the same level.
- *
- * @return The order of this Preference.
- * @see #setOrder(int)
- */
- public int getOrder() {
- return mOrder;
- }
-
- /**
- * Sets the title for this Preference with a CharSequence.
- * This title will be placed into the ID
- * {@link android.R.id#title} within the View created by
- * {@link #onCreateView(ViewGroup)}.
- *
- * @param title The title for this Preference.
- */
- public void setTitle(CharSequence title) {
- if (title == null && mTitle != null || title != null && !title.equals(mTitle)) {
- mTitle = title;
- notifyChanged();
- }
- }
-
- /**
- * Sets the title for this Preference with a resource ID.
- *
- * @see #setTitle(CharSequence)
- * @param titleResId The title as a resource ID.
- */
- public void setTitle(int titleResId) {
- setTitle(mContext.getString(titleResId));
- }
-
- /**
- * Returns the title of this Preference.
- *
- * @return The title.
- * @see #setTitle(CharSequence)
- */
- public CharSequence getTitle() {
- return mTitle;
- }
-
- /**
- * Returns the summary of this Preference.
- *
- * @return The summary.
- * @see #setSummary(CharSequence)
- */
- public CharSequence getSummary() {
- return mSummary;
- }
-
- /**
- * Sets the summary for this Preference with a CharSequence.
- *
- * @param summary The summary for the preference.
- */
- public void setSummary(CharSequence summary) {
- if (summary == null && mSummary != null || summary != null && !summary.equals(mSummary)) {
- mSummary = summary;
- notifyChanged();
- }
- }
-
- /**
- * Sets the summary for this Preference with a resource ID.
- *
- * @see #setSummary(CharSequence)
- * @param summaryResId The summary as a resource.
- */
- public void setSummary(int summaryResId) {
- setSummary(mContext.getString(summaryResId));
- }
-
- /**
- * Sets whether this Preference is enabled. If disabled, it will
- * not handle clicks.
- *
- * @param enabled Set true to enable it.
- */
- public void setEnabled(boolean enabled) {
- if (mEnabled != enabled) {
- mEnabled = enabled;
-
- // Enabled state can change dependent preferences' states, so notify
- notifyDependencyChange(shouldDisableDependents());
-
- notifyChanged();
- }
- }
-
- /**
- * Checks whether this Preference should be enabled in the list.
- *
- * @return True if this Preference is enabled, false otherwise.
- */
- public boolean isEnabled() {
- return mEnabled;
- }
-
- /**
- * Sets whether this Preference is selectable.
- *
- * @param selectable Set true to make it selectable.
- */
- public void setSelectable(boolean selectable) {
- if (mSelectable != selectable) {
- mSelectable = selectable;
- notifyChanged();
- }
- }
-
- /**
- * Checks whether this Preference should be selectable in the list.
- *
- * @return True if it is selectable, false otherwise.
- */
- public boolean isSelectable() {
- return mSelectable;
- }
-
- /**
- * Sets whether this Preference should disable its view when it gets
- * disabled.
- * <p>
- * For example, set this and {@link #setEnabled(boolean)} to false for
- * preferences that are only displaying information and 1) should not be
- * clickable 2) should not have the view set to the disabled state.
- *
- * @param shouldDisableView Set true if this preference should disable its view
- * when the preference is disabled.
- */
- public void setShouldDisableView(boolean shouldDisableView) {
- mShouldDisableView = shouldDisableView;
- notifyChanged();
- }
-
- /**
- * Checks whether this Preference should disable its view when it's action is disabled.
- * @see #setShouldDisableView(boolean)
- * @return True if it should disable the view.
- */
- public boolean getShouldDisableView() {
- return mShouldDisableView;
- }
-
- /**
- * Returns a unique ID for this Preference. This ID should be unique across all
- * Preference objects in a hierarchy.
- *
- * @return A unique ID for this Preference.
- */
- long getId() {
- return mId;
- }
-
- /**
- * Processes a click on the preference. This includes saving the value to
- * the {@link SharedPreferences}. However, the overridden method should
- * call {@link #callChangeListener(Object)} to make sure the client wants to
- * update the preference's state with the new value.
- */
- protected void onClick() {
- }
-
- /**
- * Sets the key for this Preference, which is used as a key to the
- * {@link SharedPreferences}. This should be unique for the package.
- *
- * @param key The key for the preference.
- */
- public void setKey(String key) {
- mKey = key;
-
- if (mRequiresKey && !hasKey()) {
- requireKey();
- }
- }
-
- /**
- * Gets the key for this Preference, which is also the key used for storing
- * values into SharedPreferences.
- *
- * @return The key.
- */
- public String getKey() {
- return mKey;
- }
-
- /**
- * Checks whether the key is present, and if it isn't throws an
- * exception. This should be called by subclasses that store preferences in
- * the {@link SharedPreferences}.
- *
- * @throws IllegalStateException If there is no key assigned.
- */
- void requireKey() {
- if (mKey == null) {
- throw new IllegalStateException("Preference does not have a key assigned.");
- }
-
- mRequiresKey = true;
- }
-
- /**
- * Checks whether this Preference has a valid key.
- *
- * @return True if the key exists and is not a blank string, false otherwise.
- */
- public boolean hasKey() {
- return !TextUtils.isEmpty(mKey);
- }
-
- /**
- * Checks whether this Preference is persistent. If it is, it stores its value(s) into
- * the persistent {@link SharedPreferences} storage.
- *
- * @return True if it is persistent.
- */
- public boolean isPersistent() {
- return mPersistent;
- }
-
- /**
- * Checks whether, at the given time this method is called,
- * this Preference should store/restore its value(s) into the
- * {@link SharedPreferences}. This, at minimum, checks whether this
- * Preference is persistent and it currently has a key. Before you
- * save/restore from the {@link SharedPreferences}, check this first.
- *
- * @return True if it should persist the value.
- */
- protected boolean shouldPersist() {
- return mPreferenceManager != null && isPersistent() && hasKey();
- }
-
- /**
- * Sets whether this Preference is persistent. When persistent,
- * it stores its value(s) into the persistent {@link SharedPreferences}
- * storage.
- *
- * @param persistent Set true if it should store its value(s) into the {@link SharedPreferences}.
- */
- public void setPersistent(boolean persistent) {
- mPersistent = persistent;
- }
-
- /**
- * Call this method after the user changes the preference, but before the
- * internal state is set. This allows the client to ignore the user value.
- *
- * @param newValue The new value of this Preference.
- * @return True if the user value should be set as the preference
- * value (and persisted).
- */
- protected boolean callChangeListener(Object newValue) {
- return mOnChangeListener == null ? true : mOnChangeListener.onPreferenceChange(this, newValue);
- }
-
- /**
- * Sets the callback to be invoked when this Preference is changed by the
- * user (but before the internal state has been updated).
- *
- * @param onPreferenceChangeListener The callback to be invoked.
- */
- public void setOnPreferenceChangeListener(OnPreferenceChangeListener onPreferenceChangeListener) {
- mOnChangeListener = onPreferenceChangeListener;
- }
-
- /**
- * Returns the callback to be invoked when this Preference is changed by the
- * user (but before the internal state has been updated).
- *
- * @return The callback to be invoked.
- */
- public OnPreferenceChangeListener getOnPreferenceChangeListener() {
- return mOnChangeListener;
- }
-
- /**
- * Sets the callback to be invoked when this Preference is clicked.
- *
- * @param onPreferenceClickListener The callback to be invoked.
- */
- public void setOnPreferenceClickListener(OnPreferenceClickListener onPreferenceClickListener) {
- mOnClickListener = onPreferenceClickListener;
- }
-
- /**
- * Returns the callback to be invoked when this Preference is clicked.
- *
- * @return The callback to be invoked.
- */
- public OnPreferenceClickListener getOnPreferenceClickListener() {
- return mOnClickListener;
- }
-
- /**
- * Called when a click should be performed.
- *
- * @param preferenceScreen A {@link PreferenceScreen} whose hierarchy click
- * listener should be called in the proper order (between other
- * processing). May be null.
- */
- void performClick(PreferenceScreen preferenceScreen) {
-
- if (!isEnabled()) {
- return;
- }
-
- onClick();
-
- if (mOnClickListener != null && mOnClickListener.onPreferenceClick(this)) {
- return;
- }
-
- PreferenceManager preferenceManager = getPreferenceManager();
- if (preferenceManager != null) {
- PreferenceManager.OnPreferenceTreeClickListener listener = preferenceManager
- .getOnPreferenceTreeClickListener();
- if (preferenceScreen != null && listener != null
- && listener.onPreferenceTreeClick(preferenceScreen, this)) {
- return;
- }
- }
-
- if (mIntent != null) {
- Context context = getContext();
- context.startActivity(mIntent);
- }
- }
-
- /**
- * Returns the {@link android.content.Context} of this Preference.
- * Each Preference in a Preference hierarchy can be
- * from different Context (for example, if multiple activities provide preferences into a single
- * {@link PreferenceActivity}). This Context will be used to save the Preference values.
- *
- * @return The Context of this Preference.
- */
- public Context getContext() {
- return mContext;
- }
-
- /**
- * Returns the {@link SharedPreferences} where this Preference can read its
- * value(s). Usually, it's easier to use one of the helper read methods:
- * {@link #getPersistedBoolean(boolean)}, {@link #getPersistedFloat(float)},
- * {@link #getPersistedInt(int)}, {@link #getPersistedLong(long)},
- * {@link #getPersistedString(String)}. To save values, see
- * {@link #getEditor()}.
- * <p>
- * In some cases, writes to the {@link #getEditor()} will not be committed
- * right away and hence not show up in the returned
- * {@link SharedPreferences}, this is intended behavior to improve
- * performance.
- *
- * @return The {@link SharedPreferences} where this Preference reads its
- * value(s), or null if it isn't attached to a Preference hierarchy.
- * @see #getEditor()
- */
- public SharedPreferences getSharedPreferences() {
- if (mPreferenceManager == null) {
- return null;
- }
-
- return mPreferenceManager.getSharedPreferences();
- }
-
- /**
- * Returns an {@link SharedPreferences.Editor} where this Preference can
- * save its value(s). Usually it's easier to use one of the helper save
- * methods: {@link #persistBoolean(boolean)}, {@link #persistFloat(float)},
- * {@link #persistInt(int)}, {@link #persistLong(long)},
- * {@link #persistString(String)}. To read values, see
- * {@link #getSharedPreferences()}. If {@link #shouldCommit()} returns
- * true, it is this Preference's responsibility to commit.
- * <p>
- * In some cases, writes to this will not be committed right away and hence
- * not show up in the SharedPreferences, this is intended behavior to
- * improve performance.
- *
- * @return A {@link SharedPreferences.Editor} where this preference saves
- * its value(s), or null if it isn't attached to a Preference
- * hierarchy.
- * @see #shouldCommit()
- * @see #getSharedPreferences()
- */
- public SharedPreferences.Editor getEditor() {
- if (mPreferenceManager == null) {
- return null;
- }
-
- return mPreferenceManager.getEditor();
- }
-
- /**
- * Returns whether the {@link Preference} should commit its saved value(s) in
- * {@link #getEditor()}. This may return false in situations where batch
- * committing is being done (by the manager) to improve performance.
- *
- * @return Whether the Preference should commit its saved value(s).
- * @see #getEditor()
- */
- public boolean shouldCommit() {
- if (mPreferenceManager == null) {
- return false;
- }
-
- return mPreferenceManager.shouldCommit();
- }
-
- /**
- * Compares Preference objects based on order (if set), otherwise alphabetically on the titles.
- *
- * @param another The Preference to compare to this one.
- * @return 0 if the same; less than 0 if this Preference sorts ahead of <var>another</var>;
- * greater than 0 if this Preference sorts after <var>another</var>.
- */
- public int compareTo(Preference another) {
- if (mOrder != DEFAULT_ORDER
- || (mOrder == DEFAULT_ORDER && another.mOrder != DEFAULT_ORDER)) {
- // Do order comparison
- return mOrder - another.mOrder;
- } else if (mTitle == null) {
- return 1;
- } else if (another.mTitle == null) {
- return -1;
- } else {
- // Do name comparison
- return CharSequences.compareToIgnoreCase(mTitle, another.mTitle);
- }
- }
-
- /**
- * Sets the internal change listener.
- *
- * @param listener The listener.
- * @see #notifyChanged()
- */
- final void setOnPreferenceChangeInternalListener(OnPreferenceChangeInternalListener listener) {
- mListener = listener;
- }
-
- /**
- * Should be called when the data of this {@link Preference} has changed.
- */
- protected void notifyChanged() {
- if (mListener != null) {
- mListener.onPreferenceChange(this);
- }
- }
-
- /**
- * Should be called when a Preference has been
- * added/removed from this group, or the ordering should be
- * re-evaluated.
- */
- protected void notifyHierarchyChanged() {
- if (mListener != null) {
- mListener.onPreferenceHierarchyChange(this);
- }
- }
-
- /**
- * Gets the {@link PreferenceManager} that manages this Preference object's tree.
- *
- * @return The {@link PreferenceManager}.
- */
- public PreferenceManager getPreferenceManager() {
- return mPreferenceManager;
- }
-
- /**
- * Called when this Preference has been attached to a Preference hierarchy.
- * Make sure to call the super implementation.
- *
- * @param preferenceManager The PreferenceManager of the hierarchy.
- */
- protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
- mPreferenceManager = preferenceManager;
-
- mId = preferenceManager.getNextId();
-
- dispatchSetInitialValue();
- }
-
- /**
- * Called when the Preference hierarchy has been attached to the
- * {@link PreferenceActivity}. This can also be called when this
- * Preference has been attached to a group that was already attached
- * to the {@link PreferenceActivity}.
- */
- protected void onAttachedToActivity() {
- // At this point, the hierarchy that this preference is in is connected
- // with all other preferences.
- registerDependency();
- }
-
- private void registerDependency() {
-
- if (TextUtils.isEmpty(mDependencyKey)) return;
-
- Preference preference = findPreferenceInHierarchy(mDependencyKey);
- if (preference != null) {
- preference.registerDependent(this);
- } else {
- throw new IllegalStateException("Dependency \"" + mDependencyKey
- + "\" not found for preference \"" + mKey + "\" (title: \"" + mTitle + "\"");
- }
- }
-
- private void unregisterDependency() {
- if (mDependencyKey != null) {
- final Preference oldDependency = findPreferenceInHierarchy(mDependencyKey);
- if (oldDependency != null) {
- oldDependency.unregisterDependent(this);
- }
- }
- }
-
- /**
- * Finds a Preference in this hierarchy (the whole thing,
- * even above/below your {@link PreferenceScreen} screen break) with the given
- * key.
- * <p>
- * This only functions after we have been attached to a hierarchy.
- *
- * @param key The key of the Preference to find.
- * @return The Preference that uses the given key.
- */
- protected Preference findPreferenceInHierarchy(String key) {
- if (TextUtils.isEmpty(key) || mPreferenceManager == null) {
- return null;
- }
-
- return mPreferenceManager.findPreference(key);
- }
-
- /**
- * Adds a dependent Preference on this Preference so we can notify it.
- * Usually, the dependent Preference registers itself (it's good for it to
- * know it depends on something), so please use
- * {@link Preference#setDependency(String)} on the dependent Preference.
- *
- * @param dependent The dependent Preference that will be enabled/disabled
- * according to the state of this Preference.
- */
- private void registerDependent(Preference dependent) {
- if (mDependents == null) {
- mDependents = new ArrayList<Preference>();
- }
-
- mDependents.add(dependent);
-
- dependent.onDependencyChanged(this, shouldDisableDependents());
- }
-
- /**
- * Removes a dependent Preference on this Preference.
- *
- * @param dependent The dependent Preference that will be enabled/disabled
- * according to the state of this Preference.
- * @return Returns the same Preference object, for chaining multiple calls
- * into a single statement.
- */
- private void unregisterDependent(Preference dependent) {
- if (mDependents != null) {
- mDependents.remove(dependent);
- }
- }
-
- /**
- * Notifies any listening dependents of a change that affects the
- * dependency.
- *
- * @param disableDependents Whether this Preference should disable
- * its dependents.
- */
- public void notifyDependencyChange(boolean disableDependents) {
- final List<Preference> dependents = mDependents;
-
- if (dependents == null) {
- return;
- }
-
- final int dependentsCount = dependents.size();
- for (int i = 0; i < dependentsCount; i++) {
- dependents.get(i).onDependencyChanged(this, disableDependents);
- }
- }
-
- /**
- * Called when the dependency changes.
- *
- * @param dependency The Preference that this Preference depends on.
- * @param disableDependent Set true to disable this Preference.
- */
- public void onDependencyChanged(Preference dependency, boolean disableDependent) {
- setEnabled(!disableDependent);
- }
-
- /**
- * Checks whether this preference's dependents should currently be
- * disabled.
- *
- * @return True if the dependents should be disabled, otherwise false.
- */
- public boolean shouldDisableDependents() {
- return !isEnabled();
- }
-
- /**
- * Sets the key of a Preference that this Preference will depend on. If that
- * Preference is not set or is off, this Preference will be disabled.
- *
- * @param dependencyKey The key of the Preference that this depends on.
- */
- public void setDependency(String dependencyKey) {
- // Unregister the old dependency, if we had one
- unregisterDependency();
-
- // Register the new
- mDependencyKey = dependencyKey;
- registerDependency();
- }
-
- /**
- * Returns the key of the dependency on this Preference.
- *
- * @return The key of the dependency.
- * @see #setDependency(String)
- */
- public String getDependency() {
- return mDependencyKey;
- }
-
- /**
- * Called when this Preference is being removed from the hierarchy. You
- * should remove any references to this Preference that you know about. Make
- * sure to call through to the superclass implementation.
- */
- protected void onPrepareForRemoval() {
- unregisterDependency();
- }
-
- /**
- * Sets the default value for this Preference, which will be set either if
- * persistence is off or persistence is on and the preference is not found
- * in the persistent storage.
- *
- * @param defaultValue The default value.
- */
- public void setDefaultValue(Object defaultValue) {
- mDefaultValue = defaultValue;
- }
-
- private void dispatchSetInitialValue() {
- // By now, we know if we are persistent.
- final boolean shouldPersist = shouldPersist();
- if (!shouldPersist || !getSharedPreferences().contains(mKey)) {
- if (mDefaultValue != null) {
- onSetInitialValue(false, mDefaultValue);
- }
- } else {
- onSetInitialValue(true, null);
- }
- }
-
- /**
- * Implement this to set the initial value of the Preference.
- * <p>
- * If <var>restorePersistedValue</var> is true, you should restore the
- * Preference value from the {@link android.content.SharedPreferences}. If
- * <var>restorePersistedValue</var> is false, you should set the Preference
- * value to defaultValue that is given (and possibly store to SharedPreferences
- * if {@link #shouldPersist()} is true).
- * <p>
- * This may not always be called. One example is if it should not persist
- * but there is no default value given.
- *
- * @param restorePersistedValue True to restore the persisted value;
- * false to use the given <var>defaultValue</var>.
- * @param defaultValue The default value for this Preference. Only use this
- * if <var>restorePersistedValue</var> is false.
- */
- protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
- }
-
- private void tryCommit(SharedPreferences.Editor editor) {
- if (mPreferenceManager.shouldCommit()) {
- editor.commit();
- }
- }
-
- /**
- * Attempts to persist a String to the {@link android.content.SharedPreferences}.
- * <p>
- * This will check if this Preference is persistent, get an editor from
- * the {@link PreferenceManager}, put in the string, and check if we should commit (and
- * commit if so).
- *
- * @param value The value to persist.
- * @return True if the Preference is persistent. (This is not whether the
- * value was persisted, since we may not necessarily commit if there
- * will be a batch commit later.)
- * @see #getPersistedString(String)
- */
- protected boolean persistString(String value) {
- if (shouldPersist()) {
- // Shouldn't store null
- if (value == getPersistedString(null)) {
- // It's already there, so the same as persisting
- return true;
- }
-
- SharedPreferences.Editor editor = mPreferenceManager.getEditor();
- editor.putString(mKey, value);
- tryCommit(editor);
- return true;
- }
- return false;
- }
-
- /**
- * Attempts to get a persisted String from the {@link android.content.SharedPreferences}.
- * <p>
- * This will check if this Preference is persistent, get the SharedPreferences
- * from the {@link PreferenceManager}, and get the value.
- *
- * @param defaultReturnValue The default value to return if either the
- * Preference is not persistent or the Preference is not in the
- * shared preferences.
- * @return The value from the SharedPreferences or the default return
- * value.
- * @see #persistString(String)
- */
- protected String getPersistedString(String defaultReturnValue) {
- if (!shouldPersist()) {
- return defaultReturnValue;
- }
-
- return mPreferenceManager.getSharedPreferences().getString(mKey, defaultReturnValue);
- }
-
- /**
- * Attempts to persist an int to the {@link android.content.SharedPreferences}.
- *
- * @param value The value to persist.
- * @return True if the Preference is persistent. (This is not whether the
- * value was persisted, since we may not necessarily commit if there
- * will be a batch commit later.)
- * @see #persistString(String)
- * @see #getPersistedInt(int)
- */
- protected boolean persistInt(int value) {
- if (shouldPersist()) {
- if (value == getPersistedInt(~value)) {
- // It's already there, so the same as persisting
- return true;
- }
-
- SharedPreferences.Editor editor = mPreferenceManager.getEditor();
- editor.putInt(mKey, value);
- tryCommit(editor);
- return true;
- }
- return false;
- }
-
- /**
- * Attempts to get a persisted int from the {@link android.content.SharedPreferences}.
- *
- * @param defaultReturnValue The default value to return if either this
- * Preference is not persistent or this Preference is not in the
- * SharedPreferences.
- * @return The value from the SharedPreferences or the default return
- * value.
- * @see #getPersistedString(String)
- * @see #persistInt(int)
- */
- protected int getPersistedInt(int defaultReturnValue) {
- if (!shouldPersist()) {
- return defaultReturnValue;
- }
-
- return mPreferenceManager.getSharedPreferences().getInt(mKey, defaultReturnValue);
- }
-
- /**
- * Attempts to persist a float to the {@link android.content.SharedPreferences}.
- *
- * @param value The value to persist.
- * @return True if this Preference is persistent. (This is not whether the
- * value was persisted, since we may not necessarily commit if there
- * will be a batch commit later.)
- * @see #persistString(String)
- * @see #getPersistedFloat(float)
- */
- protected boolean persistFloat(float value) {
- if (shouldPersist()) {
- if (value == getPersistedFloat(Float.NaN)) {
- // It's already there, so the same as persisting
- return true;
- }
-
- SharedPreferences.Editor editor = mPreferenceManager.getEditor();
- editor.putFloat(mKey, value);
- tryCommit(editor);
- return true;
- }
- return false;
- }
-
- /**
- * Attempts to get a persisted float from the {@link android.content.SharedPreferences}.
- *
- * @param defaultReturnValue The default value to return if either this
- * Preference is not persistent or this Preference is not in the
- * SharedPreferences.
- * @return The value from the SharedPreferences or the default return
- * value.
- * @see #getPersistedString(String)
- * @see #persistFloat(float)
- */
- protected float getPersistedFloat(float defaultReturnValue) {
- if (!shouldPersist()) {
- return defaultReturnValue;
- }
-
- return mPreferenceManager.getSharedPreferences().getFloat(mKey, defaultReturnValue);
- }
-
- /**
- * Attempts to persist a long to the {@link android.content.SharedPreferences}.
- *
- * @param value The value to persist.
- * @return True if this Preference is persistent. (This is not whether the
- * value was persisted, since we may not necessarily commit if there
- * will be a batch commit later.)
- * @see #persistString(String)
- * @see #getPersistedLong(long)
- */
- protected boolean persistLong(long value) {
- if (shouldPersist()) {
- if (value == getPersistedLong(~value)) {
- // It's already there, so the same as persisting
- return true;
- }
-
- SharedPreferences.Editor editor = mPreferenceManager.getEditor();
- editor.putLong(mKey, value);
- tryCommit(editor);
- return true;
- }
- return false;
- }
-
- /**
- * Attempts to get a persisted long from the {@link android.content.SharedPreferences}.
- *
- * @param defaultReturnValue The default value to return if either this
- * Preference is not persistent or this Preference is not in the
- * SharedPreferences.
- * @return The value from the SharedPreferences or the default return
- * value.
- * @see #getPersistedString(String)
- * @see #persistLong(long)
- */
- protected long getPersistedLong(long defaultReturnValue) {
- if (!shouldPersist()) {
- return defaultReturnValue;
- }
-
- return mPreferenceManager.getSharedPreferences().getLong(mKey, defaultReturnValue);
- }
-
- /**
- * Attempts to persist a boolean to the {@link android.content.SharedPreferences}.
- *
- * @param value The value to persist.
- * @return True if this Preference is persistent. (This is not whether the
- * value was persisted, since we may not necessarily commit if there
- * will be a batch commit later.)
- * @see #persistString(String)
- * @see #getPersistedBoolean(boolean)
- */
- protected boolean persistBoolean(boolean value) {
- if (shouldPersist()) {
- if (value == getPersistedBoolean(!value)) {
- // It's already there, so the same as persisting
- return true;
- }
-
- SharedPreferences.Editor editor = mPreferenceManager.getEditor();
- editor.putBoolean(mKey, value);
- tryCommit(editor);
- return true;
- }
- return false;
- }
-
- /**
- * Attempts to get a persisted boolean from the {@link android.content.SharedPreferences}.
- *
- * @param defaultReturnValue The default value to return if either this
- * Preference is not persistent or this Preference is not in the
- * SharedPreferences.
- * @return The value from the SharedPreferences or the default return
- * value.
- * @see #getPersistedString(String)
- * @see #persistBoolean(boolean)
- */
- protected boolean getPersistedBoolean(boolean defaultReturnValue) {
- if (!shouldPersist()) {
- return defaultReturnValue;
- }
-
- return mPreferenceManager.getSharedPreferences().getBoolean(mKey, defaultReturnValue);
- }
-
- boolean hasSpecifiedLayout() {
- return mHasSpecifiedLayout;
- }
-
- @Override
- public String toString() {
- return getFilterableStringBuilder().toString();
- }
-
- /**
- * Returns the text that will be used to filter this Preference depending on
- * user input.
- * <p>
- * If overridding and calling through to the superclass, make sure to prepend
- * your additions with a space.
- *
- * @return Text as a {@link StringBuilder} that will be used to filter this
- * preference. By default, this is the title and summary
- * (concatenated with a space).
- */
- StringBuilder getFilterableStringBuilder() {
- StringBuilder sb = new StringBuilder();
- CharSequence title = getTitle();
- if (!TextUtils.isEmpty(title)) {
- sb.append(title).append(' ');
- }
- CharSequence summary = getSummary();
- if (!TextUtils.isEmpty(summary)) {
- sb.append(summary).append(' ');
- }
- // Drop the last space
- sb.setLength(sb.length() - 1);
- return sb;
- }
-
- /**
- * Store this Preference hierarchy's frozen state into the given container.
- *
- * @param container The Bundle in which to save the instance of this Preference.
- *
- * @see #restoreHierarchyState
- * @see #onSaveInstanceState
- */
- public void saveHierarchyState(Bundle container) {
- dispatchSaveInstanceState(container);
- }
-
- /**
- * Called by {@link #saveHierarchyState} to store the instance for this Preference and its children.
- * May be overridden to modify how the save happens for children. For example, some
- * Preference objects may want to not store an instance for their children.
- *
- * @param container The Bundle in which to save the instance of this Preference.
- *
- * @see #saveHierarchyState
- * @see #onSaveInstanceState
- */
- void dispatchSaveInstanceState(Bundle container) {
- if (hasKey()) {
- mBaseMethodCalled = false;
- Parcelable state = onSaveInstanceState();
- if (!mBaseMethodCalled) {
- throw new IllegalStateException(
- "Derived class did not call super.onSaveInstanceState()");
- }
- if (state != null) {
- container.putParcelable(mKey, state);
- }
- }
- }
-
- /**
- * Hook allowing a Preference to generate a representation of its internal
- * state that can later be used to create a new instance with that same
- * state. This state should only contain information that is not persistent
- * or can be reconstructed later.
- *
- * @return A Parcelable object containing the current dynamic state of
- * this Preference, or null if there is nothing interesting to save.
- * The default implementation returns null.
- * @see #onRestoreInstanceState
- * @see #saveHierarchyState
- */
- protected Parcelable onSaveInstanceState() {
- mBaseMethodCalled = true;
- return BaseSavedState.EMPTY_STATE;
- }
-
- /**
- * Restore this Preference hierarchy's previously saved state from the given container.
- *
- * @param container The Bundle that holds the previously saved state.
- *
- * @see #saveHierarchyState
- * @see #onRestoreInstanceState
- */
- public void restoreHierarchyState(Bundle container) {
- dispatchRestoreInstanceState(container);
- }
-
- /**
- * Called by {@link #restoreHierarchyState} to retrieve the saved state for this
- * Preference and its children. May be overridden to modify how restoring
- * happens to the children of a Preference. For example, some Preference objects may
- * not want to save state for their children.
- *
- * @param container The Bundle that holds the previously saved state.
- * @see #restoreHierarchyState
- * @see #onRestoreInstanceState
- */
- void dispatchRestoreInstanceState(Bundle container) {
- if (hasKey()) {
- Parcelable state = container.getParcelable(mKey);
- if (state != null) {
- mBaseMethodCalled = false;
- onRestoreInstanceState(state);
- if (!mBaseMethodCalled) {
- throw new IllegalStateException(
- "Derived class did not call super.onRestoreInstanceState()");
- }
- }
- }
- }
-
- /**
- * Hook allowing a Preference to re-apply a representation of its internal
- * state that had previously been generated by {@link #onSaveInstanceState}.
- * This function will never be called with a null state.
- *
- * @param state The saved state that had previously been returned by
- * {@link #onSaveInstanceState}.
- * @see #onSaveInstanceState
- * @see #restoreHierarchyState
- */
- protected void onRestoreInstanceState(Parcelable state) {
- mBaseMethodCalled = true;
- if (state != BaseSavedState.EMPTY_STATE && state != null) {
- throw new IllegalArgumentException("Wrong state class -- expecting Preference State");
- }
- }
-
- /**
- * A base class for managing the instance state of a {@link Preference}.
- */
- public static class BaseSavedState extends AbsSavedState {
- public BaseSavedState(Parcel source) {
- super(source);
- }
-
- public BaseSavedState(Parcelable superState) {
- super(superState);
- }
-
- public static final Parcelable.Creator<BaseSavedState> CREATOR =
- new Parcelable.Creator<BaseSavedState>() {
- public BaseSavedState createFromParcel(Parcel in) {
- return new BaseSavedState(in);
- }
-
- public BaseSavedState[] newArray(int size) {
- return new BaseSavedState[size];
- }
- };
- }
-
-}
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
deleted file mode 100644
index 837ce91..0000000
--- a/core/java/android/preference/PreferenceActivity.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-import android.app.Activity;
-import android.app.ListActivity;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.view.View;
-import android.view.Window;
-
-/**
- * Shows a hierarchy of {@link Preference} objects as
- * lists, possibly spanning multiple screens. These preferences will
- * automatically save to {@link SharedPreferences} as the user interacts with
- * them. To retrieve an instance of {@link SharedPreferences} that the
- * preference hierarchy in this activity will use, call
- * {@link PreferenceManager#getDefaultSharedPreferences(android.content.Context)}
- * with a context in the same package as this activity.
- * <p>
- * Furthermore, the preferences shown will follow the visual style of system
- * preferences. It is easy to create a hierarchy of preferences (that can be
- * shown on multiple screens) via XML. For these reasons, it is recommended to
- * use this activity (as a superclass) to deal with preferences in applications.
- * <p>
- * A {@link PreferenceScreen} object should be at the top of the preference
- * hierarchy. Furthermore, subsequent {@link PreferenceScreen} in the hierarchy
- * denote a screen break--that is the preferences contained within subsequent
- * {@link PreferenceScreen} should be shown on another screen. The preference
- * framework handles showing these other screens from the preference hierarchy.
- * <p>
- * The preference hierarchy can be formed in multiple ways:
- * <li> From an XML file specifying the hierarchy
- * <li> From different {@link Activity Activities} that each specify its own
- * preferences in an XML file via {@link Activity} meta-data
- * <li> From an object hierarchy rooted with {@link PreferenceScreen}
- * <p>
- * To inflate from XML, use the {@link #addPreferencesFromResource(int)}. The
- * root element should be a {@link PreferenceScreen}. Subsequent elements can point
- * to actual {@link Preference} subclasses. As mentioned above, subsequent
- * {@link PreferenceScreen} in the hierarchy will result in the screen break.
- * <p>
- * To specify an {@link Intent} to query {@link Activity Activities} that each
- * have preferences, use {@link #addPreferencesFromIntent}. Each
- * {@link Activity} can specify meta-data in the manifest (via the key
- * {@link PreferenceManager#METADATA_KEY_PREFERENCES}) that points to an XML
- * resource. These XML resources will be inflated into a single preference
- * hierarchy and shown by this activity.
- * <p>
- * To specify an object hierarchy rooted with {@link PreferenceScreen}, use
- * {@link #setPreferenceScreen(PreferenceScreen)}.
- * <p>
- * As a convenience, this activity implements a click listener for any
- * preference in the current hierarchy, see
- * {@link #onPreferenceTreeClick(PreferenceScreen, Preference)}.
- *
- * @see Preference
- * @see PreferenceScreen
- */
-public abstract class PreferenceActivity extends ListActivity implements
- PreferenceManager.OnPreferenceTreeClickListener {
-
- private static final String PREFERENCES_TAG = "android:preferences";
-
- private PreferenceManager mPreferenceManager;
-
- /**
- * The starting request code given out to preference framework.
- */
- private static final int FIRST_REQUEST_CODE = 100;
-
- private static final int MSG_BIND_PREFERENCES = 0;
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
-
- case MSG_BIND_PREFERENCES:
- bindPreferences();
- break;
- }
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(com.android.internal.R.layout.preference_list_content);
-
- mPreferenceManager = onCreatePreferenceManager();
- getListView().setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
- }
-
- @Override
- protected void onStop() {
- super.onStop();
-
- mPreferenceManager.dispatchActivityStop();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
-
- mPreferenceManager.dispatchActivityDestroy();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
-
- final PreferenceScreen preferenceScreen = getPreferenceScreen();
- if (preferenceScreen != null) {
- Bundle container = new Bundle();
- preferenceScreen.saveHierarchyState(container);
- outState.putBundle(PREFERENCES_TAG, container);
- }
- }
-
- @Override
- protected void onRestoreInstanceState(Bundle state) {
- super.onRestoreInstanceState(state);
-
- Bundle container = state.getBundle(PREFERENCES_TAG);
- if (container != null) {
- final PreferenceScreen preferenceScreen = getPreferenceScreen();
- if (preferenceScreen != null) {
- preferenceScreen.restoreHierarchyState(container);
- }
- }
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
-
- mPreferenceManager.dispatchActivityResult(requestCode, resultCode, data);
- }
-
- @Override
- public void onContentChanged() {
- super.onContentChanged();
- postBindPreferences();
- }
-
- /**
- * Posts a message to bind the preferences to the list view.
- * <p>
- * Binding late is preferred as any custom preference types created in
- * {@link #onCreate(Bundle)} are able to have their views recycled.
- */
- private void postBindPreferences() {
- if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
- mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
- }
-
- private void bindPreferences() {
- final PreferenceScreen preferenceScreen = getPreferenceScreen();
- if (preferenceScreen != null) {
- preferenceScreen.bind(getListView());
- }
- }
-
- /**
- * Creates the {@link PreferenceManager}.
- *
- * @return The {@link PreferenceManager} used by this activity.
- */
- private PreferenceManager onCreatePreferenceManager() {
- PreferenceManager preferenceManager = new PreferenceManager(this, FIRST_REQUEST_CODE);
- preferenceManager.setOnPreferenceTreeClickListener(this);
- return preferenceManager;
- }
-
- /**
- * Returns the {@link PreferenceManager} used by this activity.
- * @return The {@link PreferenceManager}.
- */
- public PreferenceManager getPreferenceManager() {
- return mPreferenceManager;
- }
-
- private void requirePreferenceManager() {
- if (mPreferenceManager == null) {
- throw new RuntimeException("This should be called after super.onCreate.");
- }
- }
-
- /**
- * Sets the root of the preference hierarchy that this activity is showing.
- *
- * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
- */
- public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
- if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) {
- postBindPreferences();
- CharSequence title = getPreferenceScreen().getTitle();
- // Set the title of the activity
- if (title != null) {
- setTitle(title);
- }
- }
- }
-
- /**
- * Gets the root of the preference hierarchy that this activity is showing.
- *
- * @return The {@link PreferenceScreen} that is the root of the preference
- * hierarchy.
- */
- public PreferenceScreen getPreferenceScreen() {
- return mPreferenceManager.getPreferenceScreen();
- }
-
- /**
- * Adds preferences from activities that match the given {@link Intent}.
- *
- * @param intent The {@link Intent} to query activities.
- */
- public void addPreferencesFromIntent(Intent intent) {
- requirePreferenceManager();
-
- setPreferenceScreen(mPreferenceManager.inflateFromIntent(intent, getPreferenceScreen()));
- }
-
- /**
- * Inflates the given XML resource and adds the preference hierarchy to the current
- * preference hierarchy.
- *
- * @param preferencesResId The XML resource ID to inflate.
- */
- public void addPreferencesFromResource(int preferencesResId) {
- requirePreferenceManager();
-
- setPreferenceScreen(mPreferenceManager.inflateFromResource(this, preferencesResId,
- getPreferenceScreen()));
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
- return false;
- }
-
- /**
- * Finds a {@link Preference} based on its key.
- *
- * @param key The key of the preference to retrieve.
- * @return The {@link Preference} with the key, or null.
- * @see PreferenceGroup#findPreference(CharSequence)
- */
- public Preference findPreference(CharSequence key) {
-
- if (mPreferenceManager == null) {
- return null;
- }
-
- return mPreferenceManager.findPreference(key);
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- if (mPreferenceManager != null) {
- mPreferenceManager.dispatchNewIntent(intent);
- }
- }
-
-}
diff --git a/core/java/android/preference/PreferenceCategory.java b/core/java/android/preference/PreferenceCategory.java
deleted file mode 100644
index 237c5ce..0000000
--- a/core/java/android/preference/PreferenceCategory.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-import java.util.Map;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-/**
- * Used to group {@link Preference} objects
- * and provide a disabled title above the group.
- */
-public class PreferenceCategory extends PreferenceGroup {
- private static final String TAG = "PreferenceCategory";
-
- public PreferenceCategory(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- public PreferenceCategory(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.preferenceCategoryStyle);
- }
-
- public PreferenceCategory(Context context) {
- this(context, null);
- }
-
- @Override
- protected boolean onPrepareAddPreference(Preference preference) {
- if (preference instanceof PreferenceCategory) {
- throw new IllegalArgumentException(
- "Cannot add a " + TAG + " directly to a " + TAG);
- }
-
- return super.onPrepareAddPreference(preference);
- }
-
- @Override
- public boolean isEnabled() {
- return false;
- }
-
-}
diff --git a/core/java/android/preference/PreferenceGroup.java b/core/java/android/preference/PreferenceGroup.java
deleted file mode 100644
index d008fd6..0000000
--- a/core/java/android/preference/PreferenceGroup.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-
-/**
- * A container for multiple
- * {@link Preference} objects. It is a base class for Preference objects that are
- * parents, such as {@link PreferenceCategory} and {@link PreferenceScreen}.
- *
- * @attr ref android.R.styleable#PreferenceGroup_orderingFromXml
- */
-public abstract class PreferenceGroup extends Preference implements GenericInflater.Parent<Preference> {
- /**
- * The container for child {@link Preference}s. This is sorted based on the
- * ordering, please use {@link #addPreference(Preference)} instead of adding
- * to this directly.
- */
- private List<Preference> mPreferenceList;
-
- private boolean mOrderingAsAdded = true;
-
- private int mCurrentPreferenceOrder = 0;
-
- private boolean mAttachedToActivity = false;
-
- public PreferenceGroup(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- mPreferenceList = new ArrayList<Preference>();
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.PreferenceGroup, defStyle, 0);
- mOrderingAsAdded = a.getBoolean(com.android.internal.R.styleable.PreferenceGroup_orderingFromXml,
- mOrderingAsAdded);
- a.recycle();
- }
-
- public PreferenceGroup(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- /**
- * Whether to order the {@link Preference} children of this group as they
- * are added. If this is false, the ordering will follow each Preference
- * order and default to alphabetic for those without an order.
- * <p>
- * If this is called after preferences are added, they will not be
- * re-ordered in the order they were added, hence call this method early on.
- *
- * @param orderingAsAdded Whether to order according to the order added.
- * @see Preference#setOrder(int)
- */
- public void setOrderingAsAdded(boolean orderingAsAdded) {
- mOrderingAsAdded = orderingAsAdded;
- }
-
- /**
- * Whether this group is ordering preferences in the order they are added.
- *
- * @return Whether this group orders based on the order the children are added.
- * @see #setOrderingAsAdded(boolean)
- */
- public boolean isOrderingAsAdded() {
- return mOrderingAsAdded;
- }
-
- /**
- * Called by the inflater to add an item to this group.
- */
- public void addItemFromInflater(Preference preference) {
- addPreference(preference);
- }
-
- /**
- * Returns the number of children {@link Preference}s.
- * @return The number of preference children in this group.
- */
- public int getPreferenceCount() {
- return mPreferenceList.size();
- }
-
- /**
- * Returns the {@link Preference} at a particular index.
- *
- * @param index The index of the {@link Preference} to retrieve.
- * @return The {@link Preference}.
- */
- public Preference getPreference(int index) {
- return mPreferenceList.get(index);
- }
-
- /**
- * Adds a {@link Preference} at the correct position based on the
- * preference's order.
- *
- * @param preference The preference to add.
- * @return Whether the preference is now in this group.
- */
- public boolean addPreference(Preference preference) {
- if (mPreferenceList.contains(preference)) {
- // Exists
- return true;
- }
-
- if (preference.getOrder() == Preference.DEFAULT_ORDER) {
- if (mOrderingAsAdded) {
- preference.setOrder(mCurrentPreferenceOrder++);
- }
-
- if (preference instanceof PreferenceGroup) {
- // TODO: fix (method is called tail recursively when inflating,
- // so we won't end up properly passing this flag down to children
- ((PreferenceGroup)preference).setOrderingAsAdded(mOrderingAsAdded);
- }
- }
-
- int insertionIndex = Collections.binarySearch(mPreferenceList, preference);
- if (insertionIndex < 0) {
- insertionIndex = insertionIndex * -1 - 1;
- }
-
- if (!onPrepareAddPreference(preference)) {
- return false;
- }
-
- synchronized(this) {
- mPreferenceList.add(insertionIndex, preference);
- }
-
- preference.onAttachedToHierarchy(getPreferenceManager());
-
- if (mAttachedToActivity) {
- preference.onAttachedToActivity();
- }
-
- notifyHierarchyChanged();
-
- return true;
- }
-
- /**
- * Removes a {@link Preference} from this group.
- *
- * @param preference The preference to remove.
- * @return Whether the preference was found and removed.
- */
- public boolean removePreference(Preference preference) {
- final boolean returnValue = removePreferenceInt(preference);
- notifyHierarchyChanged();
- return returnValue;
- }
-
- private boolean removePreferenceInt(Preference preference) {
- synchronized(this) {
- preference.onPrepareForRemoval();
- return mPreferenceList.remove(preference);
- }
- }
-
- /**
- * Removes all {@link Preference Preferences} from this group.
- */
- public void removeAll() {
- synchronized(this) {
- List<Preference> preferenceList = mPreferenceList;
- for (int i = preferenceList.size() - 1; i >= 0; i--) {
- removePreferenceInt(preferenceList.get(0));
- }
- }
- notifyHierarchyChanged();
- }
-
- /**
- * Prepares a {@link Preference} to be added to the group.
- *
- * @param preference The preference to add.
- * @return Whether to allow adding the preference (true), or not (false).
- */
- protected boolean onPrepareAddPreference(Preference preference) {
- if (!super.isEnabled()) {
- preference.setEnabled(false);
- }
-
- return true;
- }
-
- /**
- * Finds a {@link Preference} based on its key. If two {@link Preference}
- * share the same key (not recommended), the first to appear will be
- * returned (to retrieve the other preference with the same key, call this
- * method on the first preference). If this preference has the key, it will
- * not be returned.
- * <p>
- * This will recursively search for the preference into children that are
- * also {@link PreferenceGroup PreferenceGroups}.
- *
- * @param key The key of the preference to retrieve.
- * @return The {@link Preference} with the key, or null.
- */
- public Preference findPreference(CharSequence key) {
- if (TextUtils.equals(getKey(), key)) {
- return this;
- }
- final int preferenceCount = getPreferenceCount();
- for (int i = 0; i < preferenceCount; i++) {
- final Preference preference = getPreference(i);
- final String curKey = preference.getKey();
-
- if (curKey != null && curKey.equals(key)) {
- return preference;
- }
-
- if (preference instanceof PreferenceGroup) {
- final Preference returnedPreference = ((PreferenceGroup)preference)
- .findPreference(key);
- if (returnedPreference != null) {
- return returnedPreference;
- }
- }
- }
-
- return null;
- }
-
- /**
- * Whether this preference group should be shown on the same screen as its
- * contained preferences.
- *
- * @return True if the contained preferences should be shown on the same
- * screen as this preference.
- */
- protected boolean isOnSameScreenAsChildren() {
- return true;
- }
-
- @Override
- protected void onAttachedToActivity() {
- super.onAttachedToActivity();
-
- // Mark as attached so if a preference is later added to this group, we
- // can tell it we are already attached
- mAttachedToActivity = true;
-
- // Dispatch to all contained preferences
- final int preferenceCount = getPreferenceCount();
- for (int i = 0; i < preferenceCount; i++) {
- getPreference(i).onAttachedToActivity();
- }
- }
-
- @Override
- protected void onPrepareForRemoval() {
- super.onPrepareForRemoval();
-
- // We won't be attached to the activity anymore
- mAttachedToActivity = false;
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- super.setEnabled(enabled);
-
- // Dispatch to all contained preferences
- final int preferenceCount = getPreferenceCount();
- for (int i = 0; i < preferenceCount; i++) {
- getPreference(i).setEnabled(enabled);
- }
- }
-
- void sortPreferences() {
- synchronized (this) {
- Collections.sort(mPreferenceList);
- }
- }
-
- @Override
- protected void dispatchSaveInstanceState(Bundle container) {
- super.dispatchSaveInstanceState(container);
-
- // Dispatch to all contained preferences
- final int preferenceCount = getPreferenceCount();
- for (int i = 0; i < preferenceCount; i++) {
- getPreference(i).dispatchSaveInstanceState(container);
- }
- }
-
- @Override
- protected void dispatchRestoreInstanceState(Bundle container) {
- super.dispatchRestoreInstanceState(container);
-
- // Dispatch to all contained preferences
- final int preferenceCount = getPreferenceCount();
- for (int i = 0; i < preferenceCount; i++) {
- getPreference(i).dispatchRestoreInstanceState(container);
- }
- }
-
-}
diff --git a/core/java/android/preference/PreferenceGroupAdapter.java b/core/java/android/preference/PreferenceGroupAdapter.java
deleted file mode 100644
index 14c0054..0000000
--- a/core/java/android/preference/PreferenceGroupAdapter.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import android.os.Handler;
-import android.preference.Preference.OnPreferenceChangeInternalListener;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Adapter;
-import android.widget.BaseAdapter;
-import android.widget.ListView;
-
-/**
- * An adapter that returns the {@link Preference} contained in this group.
- * In most cases, this adapter should be the base class for any custom
- * adapters from {@link Preference#getAdapter()}.
- * <p>
- * This adapter obeys the
- * {@link Preference}'s adapter rule (the
- * {@link Adapter#getView(int, View, ViewGroup)} should be used instead of
- * {@link Preference#getView(ViewGroup)} if a {@link Preference} has an
- * adapter via {@link Preference#getAdapter()}).
- * <p>
- * This adapter also propagates data change/invalidated notifications upward.
- * <p>
- * This adapter does not include this {@link PreferenceGroup} in the returned
- * adapter, use {@link PreferenceCategoryAdapter} instead.
- *
- * @see PreferenceCategoryAdapter
- */
-class PreferenceGroupAdapter extends BaseAdapter implements OnPreferenceChangeInternalListener {
-
- private static final String TAG = "PreferenceGroupAdapter";
-
- /**
- * The group that we are providing data from.
- */
- private PreferenceGroup mPreferenceGroup;
-
- /**
- * Maps a position into this adapter -> {@link Preference}. These
- * {@link Preference}s don't have to be direct children of this
- * {@link PreferenceGroup}, they can be grand children or younger)
- */
- private List<Preference> mPreferenceList;
-
- /**
- * List of unique Preference and its subclasses' names. This is used to find
- * out how many types of views this adapter can return. Once the count is
- * returned, this cannot be modified (since the ListView only checks the
- * count once--when the adapter is being set). We will not recycle views for
- * Preference subclasses seen after the count has been returned.
- */
- private List<String> mPreferenceClassNames;
-
- /**
- * Blocks the mPreferenceClassNames from being changed anymore.
- */
- private boolean mHasReturnedViewTypeCount = false;
-
- private volatile boolean mIsSyncing = false;
-
- private Handler mHandler = new Handler();
-
- private Runnable mSyncRunnable = new Runnable() {
- public void run() {
- syncMyPreferences();
- }
- };
-
- public PreferenceGroupAdapter(PreferenceGroup preferenceGroup) {
- mPreferenceGroup = preferenceGroup;
- // If this group gets or loses any children, let us know
- mPreferenceGroup.setOnPreferenceChangeInternalListener(this);
-
- mPreferenceList = new ArrayList<Preference>();
- mPreferenceClassNames = new ArrayList<String>();
-
- syncMyPreferences();
- }
-
- private void syncMyPreferences() {
- synchronized(this) {
- if (mIsSyncing) {
- return;
- }
-
- mIsSyncing = true;
- }
-
- List<Preference> newPreferenceList = new ArrayList<Preference>(mPreferenceList.size());
- flattenPreferenceGroup(newPreferenceList, mPreferenceGroup);
- mPreferenceList = newPreferenceList;
-
- notifyDataSetChanged();
-
- synchronized(this) {
- mIsSyncing = false;
- notifyAll();
- }
- }
-
- private void flattenPreferenceGroup(List<Preference> preferences, PreferenceGroup group) {
- // TODO: shouldn't always?
- group.sortPreferences();
-
- final int groupSize = group.getPreferenceCount();
- for (int i = 0; i < groupSize; i++) {
- final Preference preference = group.getPreference(i);
-
- preferences.add(preference);
-
- if (!mHasReturnedViewTypeCount) {
- addPreferenceClassName(preference);
- }
-
- if (preference instanceof PreferenceGroup) {
- final PreferenceGroup preferenceAsGroup = (PreferenceGroup) preference;
- if (preferenceAsGroup.isOnSameScreenAsChildren()) {
- flattenPreferenceGroup(preferences, preferenceAsGroup);
- }
- }
-
- preference.setOnPreferenceChangeInternalListener(this);
- }
- }
-
- private void addPreferenceClassName(Preference preference) {
- final String name = preference.getClass().getName();
- int insertPos = Collections.binarySearch(mPreferenceClassNames, name);
-
- // Only insert if it doesn't exist (when it is negative).
- if (insertPos < 0) {
- // Convert to insert index
- insertPos = insertPos * -1 - 1;
- mPreferenceClassNames.add(insertPos, name);
- }
- }
-
- public int getCount() {
- return mPreferenceList.size();
- }
-
- public Preference getItem(int position) {
- if (position < 0 || position >= getCount()) return null;
- return mPreferenceList.get(position);
- }
-
- public long getItemId(int position) {
- if (position < 0 || position >= getCount()) return ListView.INVALID_ROW_ID;
- return this.getItem(position).getId();
- }
-
- public View getView(int position, View convertView, ViewGroup parent) {
- final Preference preference = this.getItem(position);
-
- if (preference.hasSpecifiedLayout()) {
- // If the preference had specified a layout (as opposed to the
- // default), don't use convert views.
- convertView = null;
- } else {
- // TODO: better way of doing this
- final String name = preference.getClass().getName();
- if (Collections.binarySearch(mPreferenceClassNames, name) < 0) {
- convertView = null;
- }
- }
-
- return preference.getView(convertView, parent);
- }
-
- @Override
- public boolean isEnabled(int position) {
- if (position < 0 || position >= getCount()) return true;
- return this.getItem(position).isSelectable();
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- // There should always be a preference group, and these groups are always
- // disabled
- return false;
- }
-
- public void onPreferenceChange(Preference preference) {
- notifyDataSetChanged();
- }
-
- public void onPreferenceHierarchyChange(Preference preference) {
- mHandler.removeCallbacks(mSyncRunnable);
- mHandler.post(mSyncRunnable);
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- @Override
- public int getItemViewType(int position) {
- if (!mHasReturnedViewTypeCount) {
- mHasReturnedViewTypeCount = true;
- }
-
- final Preference preference = this.getItem(position);
- if (preference.hasSpecifiedLayout()) {
- return IGNORE_ITEM_VIEW_TYPE;
- }
-
- final String name = preference.getClass().getName();
- int viewType = Collections.binarySearch(mPreferenceClassNames, name);
- if (viewType < 0) {
- // This is a class that was seen after we returned the count, so
- // don't recycle it.
- return IGNORE_ITEM_VIEW_TYPE;
- } else {
- return viewType;
- }
- }
-
- @Override
- public int getViewTypeCount() {
- if (!mHasReturnedViewTypeCount) {
- mHasReturnedViewTypeCount = true;
- }
-
- return Math.max(1, mPreferenceClassNames.size());
- }
-
-}
diff --git a/core/java/android/preference/PreferenceInflater.java b/core/java/android/preference/PreferenceInflater.java
deleted file mode 100644
index 779e746..0000000
--- a/core/java/android/preference/PreferenceInflater.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.app.AliasActivity;
-import android.content.Context;
-import android.content.Intent;
-import android.util.AttributeSet;
-import android.util.Log;
-
-/**
- * The {@link PreferenceInflater} is used to inflate preference hierarchies from
- * XML files.
- * <p>
- * Do not construct this directly, instead use
- * {@link Context#getSystemService(String)} with
- * {@link Context#PREFERENCE_INFLATER_SERVICE}.
- */
-class PreferenceInflater extends GenericInflater<Preference, PreferenceGroup> {
- private static final String TAG = "PreferenceInflater";
- private static final String INTENT_TAG_NAME = "intent";
-
- private PreferenceManager mPreferenceManager;
-
- public PreferenceInflater(Context context, PreferenceManager preferenceManager) {
- super(context);
- init(preferenceManager);
- }
-
- PreferenceInflater(GenericInflater<Preference, PreferenceGroup> original, PreferenceManager preferenceManager, Context newContext) {
- super(original, newContext);
- init(preferenceManager);
- }
-
- @Override
- public GenericInflater<Preference, PreferenceGroup> cloneInContext(Context newContext) {
- return new PreferenceInflater(this, mPreferenceManager, newContext);
- }
-
- private void init(PreferenceManager preferenceManager) {
- mPreferenceManager = preferenceManager;
- setDefaultPackage("android.preference.");
- }
-
- @Override
- protected boolean onCreateCustomFromTag(XmlPullParser parser, Preference parentPreference,
- AttributeSet attrs) throws XmlPullParserException {
- final String tag = parser.getName();
-
- if (tag.equals(INTENT_TAG_NAME)) {
- Intent intent = null;
-
- try {
- intent = Intent.parseIntent(getContext().getResources(), parser, attrs);
- } catch (IOException e) {
- Log.w(TAG, "Could not parse Intent.");
- Log.w(TAG, e);
- }
-
- if (intent != null) {
- parentPreference.setIntent(intent);
- }
-
- return true;
- }
-
- return false;
- }
-
- @Override
- protected PreferenceGroup onMergeRoots(PreferenceGroup givenRoot, boolean attachToGivenRoot,
- PreferenceGroup xmlRoot) {
- // If we were given a Preferences, use it as the root (ignoring the root
- // Preferences from the XML file).
- if (givenRoot == null) {
- xmlRoot.onAttachedToHierarchy(mPreferenceManager);
- return xmlRoot;
- } else {
- return givenRoot;
- }
- }
-
-}
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
deleted file mode 100644
index a7a3eef..0000000
--- a/core/java/android/preference/PreferenceManager.java
+++ /dev/null
@@ -1,799 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.XmlResourceParser;
-import android.os.Bundle;
-import android.util.Log;
-
-/**
- * Used to help create {@link Preference} hierarchies
- * from activities or XML.
- * <p>
- * In most cases, clients should use
- * {@link PreferenceActivity#addPreferencesFromIntent} or
- * {@link PreferenceActivity#addPreferencesFromResource(int)}.
- *
- * @see PreferenceActivity
- */
-public class PreferenceManager {
-
- private static final String TAG = "PreferenceManager";
-
- /**
- * The Activity meta-data key for its XML preference hierarchy.
- */
- public static final String METADATA_KEY_PREFERENCES = "android.preference";
-
- public static final String KEY_HAS_SET_DEFAULT_VALUES = "_has_set_default_values";
-
- /**
- * @see #getActivity()
- */
- private Activity mActivity;
-
- /**
- * The context to use. This should always be set.
- *
- * @see #mActivity
- */
- private Context mContext;
-
- /**
- * The counter for unique IDs.
- */
- private long mNextId = 0;
-
- /**
- * The counter for unique request codes.
- */
- private int mNextRequestCode;
-
- /**
- * Cached shared preferences.
- */
- private SharedPreferences mSharedPreferences;
-
- /**
- * If in no-commit mode, the shared editor to give out (which will be
- * committed when exiting no-commit mode).
- */
- private SharedPreferences.Editor mEditor;
-
- /**
- * Blocks commits from happening on the shared editor. This is used when
- * inflating the hierarchy. Do not set this directly, use {@link #setNoCommit(boolean)}
- */
- private boolean mNoCommit;
-
- /**
- * The SharedPreferences name that will be used for all {@link Preference}s
- * managed by this instance.
- */
- private String mSharedPreferencesName;
-
- /**
- * The SharedPreferences mode that will be used for all {@link Preference}s
- * managed by this instance.
- */
- private int mSharedPreferencesMode;
-
- /**
- * The {@link PreferenceScreen} at the root of the preference hierarchy.
- */
- private PreferenceScreen mPreferenceScreen;
-
- /**
- * List of activity result listeners.
- */
- private List<OnActivityResultListener> mActivityResultListeners;
-
- /**
- * List of activity stop listeners.
- */
- private List<OnActivityStopListener> mActivityStopListeners;
-
- /**
- * List of activity destroy listeners.
- */
- private List<OnActivityDestroyListener> mActivityDestroyListeners;
-
- /**
- * List of dialogs that should be dismissed when we receive onNewIntent in
- * our PreferenceActivity.
- */
- private List<DialogInterface> mPreferencesScreens;
-
- private OnPreferenceTreeClickListener mOnPreferenceTreeClickListener;
-
- PreferenceManager(Activity activity, int firstRequestCode) {
- mActivity = activity;
- mNextRequestCode = firstRequestCode;
-
- init(activity);
- }
-
- /**
- * This constructor should ONLY be used when getting default values from
- * an XML preference hierarchy.
- * <p>
- * The {@link PreferenceManager#PreferenceManager(Activity)}
- * should be used ANY time a preference will be displayed, since some preference
- * types need an Activity for managed queries.
- */
- private PreferenceManager(Context context) {
- init(context);
- }
-
- private void init(Context context) {
- mContext = context;
-
- setSharedPreferencesName(getDefaultSharedPreferencesName(context));
- }
-
- /**
- * Returns a list of {@link Activity} (indirectly) that match a given
- * {@link Intent}.
- *
- * @param queryIntent The Intent to match.
- * @return The list of {@link ResolveInfo} that point to the matched
- * activities.
- */
- private List<ResolveInfo> queryIntentActivities(Intent queryIntent) {
- return mContext.getPackageManager().queryIntentActivities(queryIntent,
- PackageManager.GET_META_DATA);
- }
-
- /**
- * Inflates a preference hierarchy from the preference hierarchies of
- * {@link Activity Activities} that match the given {@link Intent}. An
- * {@link Activity} defines its preference hierarchy with meta-data using
- * the {@link #METADATA_KEY_PREFERENCES} key.
- * <p>
- * If a preference hierarchy is given, the new preference hierarchies will
- * be merged in.
- *
- * @param queryIntent The intent to match activities.
- * @param rootPreferences Optional existing hierarchy to merge the new
- * hierarchies into.
- * @return The root hierarchy (if one was not provided, the new hierarchy's
- * root).
- */
- PreferenceScreen inflateFromIntent(Intent queryIntent, PreferenceScreen rootPreferences) {
- final List<ResolveInfo> activities = queryIntentActivities(queryIntent);
- final HashSet<String> inflatedRes = new HashSet<String>();
-
- for (int i = activities.size() - 1; i >= 0; i--) {
- final ActivityInfo activityInfo = activities.get(i).activityInfo;
- final Bundle metaData = activityInfo.metaData;
-
- if ((metaData == null) || !metaData.containsKey(METADATA_KEY_PREFERENCES)) {
- continue;
- }
-
- // Need to concat the package with res ID since the same res ID
- // can be re-used across contexts
- final String uniqueResId = activityInfo.packageName + ":"
- + activityInfo.metaData.getInt(METADATA_KEY_PREFERENCES);
-
- if (!inflatedRes.contains(uniqueResId)) {
- inflatedRes.add(uniqueResId);
-
- final Context context;
- try {
- context = mContext.createPackageContext(activityInfo.packageName, 0);
- } catch (NameNotFoundException e) {
- Log.w(TAG, "Could not create context for " + activityInfo.packageName + ": "
- + Log.getStackTraceString(e));
- continue;
- }
-
- final PreferenceInflater inflater = new PreferenceInflater(context, this);
- final XmlResourceParser parser = activityInfo.loadXmlMetaData(context
- .getPackageManager(), METADATA_KEY_PREFERENCES);
- rootPreferences = (PreferenceScreen) inflater
- .inflate(parser, rootPreferences, true);
- parser.close();
- }
- }
-
- rootPreferences.onAttachedToHierarchy(this);
-
- return rootPreferences;
- }
-
- /**
- * Inflates a preference hierarchy from XML. If a preference hierarchy is
- * given, the new preference hierarchies will be merged in.
- *
- * @param context The context of the resource.
- * @param resId The resource ID of the XML to inflate.
- * @param rootPreferences Optional existing hierarchy to merge the new
- * hierarchies into.
- * @return The root hierarchy (if one was not provided, the new hierarchy's
- * root).
- */
- PreferenceScreen inflateFromResource(Context context, int resId,
- PreferenceScreen rootPreferences) {
- // Block commits
- setNoCommit(true);
-
- final PreferenceInflater inflater = new PreferenceInflater(context, this);
- rootPreferences = (PreferenceScreen) inflater.inflate(resId, rootPreferences, true);
- rootPreferences.onAttachedToHierarchy(this);
-
- // Unblock commits
- setNoCommit(false);
-
- return rootPreferences;
- }
-
- public PreferenceScreen createPreferenceScreen(Context context) {
- final PreferenceScreen preferenceScreen = new PreferenceScreen(context, null);
- preferenceScreen.onAttachedToHierarchy(this);
- return preferenceScreen;
- }
-
- /**
- * Called by a preference to get a unique ID in its hierarchy.
- *
- * @return A unique ID.
- */
- long getNextId() {
- synchronized (this) {
- return mNextId++;
- }
- }
-
- /**
- * Returns the current name of the SharedPreferences file that preferences managed by
- * this will use.
- *
- * @return The name that can be passed to {@link Context#getSharedPreferences(String, int)}.
- * @see Context#getSharedPreferences(String, int)
- */
- public String getSharedPreferencesName() {
- return mSharedPreferencesName;
- }
-
- /**
- * Sets the name of the SharedPreferences file that preferences managed by this
- * will use.
- *
- * @param sharedPreferencesName The name of the SharedPreferences file.
- * @see Context#getSharedPreferences(String, int)
- */
- public void setSharedPreferencesName(String sharedPreferencesName) {
- mSharedPreferencesName = sharedPreferencesName;
- mSharedPreferences = null;
- }
-
- /**
- * Returns the current mode of the SharedPreferences file that preferences managed by
- * this will use.
- *
- * @return The mode that can be passed to {@link Context#getSharedPreferences(String, int)}.
- * @see Context#getSharedPreferences(String, int)
- */
- public int getSharedPreferencesMode() {
- return mSharedPreferencesMode;
- }
-
- /**
- * Sets the mode of the SharedPreferences file that preferences managed by this
- * will use.
- *
- * @param sharedPreferencesMode The mode of the SharedPreferences file.
- * @see Context#getSharedPreferences(String, int)
- */
- public void setSharedPreferencesMode(int sharedPreferencesMode) {
- mSharedPreferencesMode = sharedPreferencesMode;
- mSharedPreferences = null;
- }
-
- /**
- * Gets a SharedPreferences instance that preferences managed by this will
- * use.
- *
- * @return A SharedPreferences instance pointing to the file that contains
- * the values of preferences that are managed by this.
- */
- public SharedPreferences getSharedPreferences() {
- if (mSharedPreferences == null) {
- mSharedPreferences = mContext.getSharedPreferences(mSharedPreferencesName,
- mSharedPreferencesMode);
- }
-
- return mSharedPreferences;
- }
-
- /**
- * Gets a SharedPreferences instance that points to the default file that is
- * used by the preference framework in the given context.
- *
- * @param context The context of the preferences whose values are wanted.
- * @return A SharedPreferences instance that can be used to retrieve and
- * listen to values of the preferences.
- */
- public static SharedPreferences getDefaultSharedPreferences(Context context) {
- return context.getSharedPreferences(getDefaultSharedPreferencesName(context),
- getDefaultSharedPreferencesMode());
- }
-
- private static String getDefaultSharedPreferencesName(Context context) {
- return context.getPackageName() + "_preferences";
- }
-
- private static int getDefaultSharedPreferencesMode() {
- return Context.MODE_PRIVATE;
- }
-
- /**
- * Returns the root of the preference hierarchy managed by this class.
- *
- * @return The {@link PreferenceScreen} object that is at the root of the hierarchy.
- */
- PreferenceScreen getPreferenceScreen() {
- return mPreferenceScreen;
- }
-
- /**
- * Sets the root of the preference hierarchy.
- *
- * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
- * @return Whether the {@link PreferenceScreen} given is different than the previous.
- */
- boolean setPreferences(PreferenceScreen preferenceScreen) {
- if (preferenceScreen != mPreferenceScreen) {
- mPreferenceScreen = preferenceScreen;
- return true;
- }
-
- return false;
- }
-
- /**
- * Finds a {@link Preference} based on its key.
- *
- * @param key The key of the preference to retrieve.
- * @return The {@link Preference} with the key, or null.
- * @see PreferenceGroup#findPreference(CharSequence)
- */
- public Preference findPreference(CharSequence key) {
- if (mPreferenceScreen == null) {
- return null;
- }
-
- return mPreferenceScreen.findPreference(key);
- }
-
- /**
- * Sets the default values from a preference hierarchy in XML. This should
- * be called by the application's main activity.
- * <p>
- * If {@code readAgain} is false, this will only set the default values if this
- * method has never been called in the past (or the
- * {@link #KEY_HAS_SET_DEFAULT_VALUES} in the default value shared
- * preferences file is false). To attempt to set the default values again
- * bypassing this check, set {@code readAgain} to true.
- *
- * @param context The context of the shared preferences.
- * @param resId The resource ID of the preference hierarchy XML file.
- * @param readAgain Whether to re-read the default values.
- * <p>
- * Note: this will NOT reset preferences back to their default
- * values. For that functionality, use
- * {@link PreferenceManager#getDefaultSharedPreferences(Context)}
- * and clear it followed by a call to this method with this
- * parameter set to true.
- */
- public static void setDefaultValues(Context context, int resId, boolean readAgain) {
-
- // Use the default shared preferences name and mode
- setDefaultValues(context, getDefaultSharedPreferencesName(context),
- getDefaultSharedPreferencesMode(), resId, readAgain);
- }
-
- /**
- * Similar to {@link #setDefaultValues(Context, int, boolean)} but allows
- * the client to provide the filename and mode of the shared preferences
- * file.
- *
- * @see #setDefaultValues(Context, int, boolean)
- * @see #setSharedPreferencesName(String)
- * @see #setSharedPreferencesMode(int)
- */
- public static void setDefaultValues(Context context, String sharedPreferencesName,
- int sharedPreferencesMode, int resId, boolean readAgain) {
- final SharedPreferences defaultValueSp = context.getSharedPreferences(
- KEY_HAS_SET_DEFAULT_VALUES, Context.MODE_PRIVATE);
-
- if (readAgain || !defaultValueSp.getBoolean(KEY_HAS_SET_DEFAULT_VALUES, false)) {
- final PreferenceManager pm = new PreferenceManager(context);
- pm.setSharedPreferencesName(sharedPreferencesName);
- pm.setSharedPreferencesMode(sharedPreferencesMode);
- pm.inflateFromResource(context, resId, null);
-
- defaultValueSp.edit().putBoolean(KEY_HAS_SET_DEFAULT_VALUES, true).commit();
- }
- }
-
- /**
- * Returns an editor to use when modifying the shared preferences.
- * <p>
- * Do NOT commit unless {@link #shouldCommit()} returns true.
- *
- * @return An editor to use to write to shared preferences.
- * @see #shouldCommit()
- */
- SharedPreferences.Editor getEditor() {
-
- if (mNoCommit) {
- if (mEditor == null) {
- mEditor = getSharedPreferences().edit();
- }
-
- return mEditor;
- } else {
- return getSharedPreferences().edit();
- }
- }
-
- /**
- * Whether it is the client's responsibility to commit on the
- * {@link #getEditor()}. This will return false in cases where the writes
- * should be batched, for example when inflating preferences from XML.
- *
- * @return Whether the client should commit.
- */
- boolean shouldCommit() {
- return !mNoCommit;
- }
-
- private void setNoCommit(boolean noCommit) {
- if (!noCommit && mEditor != null) {
- mEditor.commit();
- }
-
- mNoCommit = noCommit;
- }
-
- /**
- * Returns the activity that shows the preferences. This is useful for doing
- * managed queries, but in most cases the use of {@link #getContext()} is
- * preferred.
- * <p>
- * This will return null if this class was instantiated with a Context
- * instead of Activity. For example, when setting the default values.
- *
- * @return The activity that shows the preferences.
- * @see #mContext
- */
- Activity getActivity() {
- return mActivity;
- }
-
- /**
- * Returns the context. This is preferred over {@link #getActivity()} when
- * possible.
- *
- * @return The context.
- */
- Context getContext() {
- return mContext;
- }
-
- /**
- * Registers a listener.
- *
- * @see OnActivityResultListener
- */
- void registerOnActivityResultListener(OnActivityResultListener listener) {
- synchronized (this) {
- if (mActivityResultListeners == null) {
- mActivityResultListeners = new ArrayList<OnActivityResultListener>();
- }
-
- if (!mActivityResultListeners.contains(listener)) {
- mActivityResultListeners.add(listener);
- }
- }
- }
-
- /**
- * Unregisters a listener.
- *
- * @see OnActivityResultListener
- */
- void unregisterOnActivityResultListener(OnActivityResultListener listener) {
- synchronized (this) {
- if (mActivityResultListeners != null) {
- mActivityResultListeners.remove(listener);
- }
- }
- }
-
- /**
- * Called by the {@link PreferenceManager} to dispatch a subactivity result.
- */
- void dispatchActivityResult(int requestCode, int resultCode, Intent data) {
- List<OnActivityResultListener> list;
-
- synchronized (this) {
- if (mActivityResultListeners == null) return;
- list = new ArrayList<OnActivityResultListener>(mActivityResultListeners);
- }
-
- final int N = list.size();
- for (int i = 0; i < N; i++) {
- if (list.get(i).onActivityResult(requestCode, resultCode, data)) {
- break;
- }
- }
- }
-
- /**
- * Registers a listener.
- *
- * @see OnActivityStopListener
- */
- void registerOnActivityStopListener(OnActivityStopListener listener) {
- synchronized (this) {
- if (mActivityStopListeners == null) {
- mActivityStopListeners = new ArrayList<OnActivityStopListener>();
- }
-
- if (!mActivityStopListeners.contains(listener)) {
- mActivityStopListeners.add(listener);
- }
- }
- }
-
- /**
- * Unregisters a listener.
- *
- * @see OnActivityStopListener
- */
- void unregisterOnActivityStopListener(OnActivityStopListener listener) {
- synchronized (this) {
- if (mActivityStopListeners != null) {
- mActivityStopListeners.remove(listener);
- }
- }
- }
-
- /**
- * Called by the {@link PreferenceManager} to dispatch the activity stop
- * event.
- */
- void dispatchActivityStop() {
- List<OnActivityStopListener> list;
-
- synchronized (this) {
- if (mActivityStopListeners == null) return;
- list = new ArrayList<OnActivityStopListener>(mActivityStopListeners);
- }
-
- final int N = list.size();
- for (int i = 0; i < N; i++) {
- list.get(i).onActivityStop();
- }
- }
-
- /**
- * Registers a listener.
- *
- * @see OnActivityDestroyListener
- */
- void registerOnActivityDestroyListener(OnActivityDestroyListener listener) {
- synchronized (this) {
- if (mActivityDestroyListeners == null) {
- mActivityDestroyListeners = new ArrayList<OnActivityDestroyListener>();
- }
-
- if (!mActivityDestroyListeners.contains(listener)) {
- mActivityDestroyListeners.add(listener);
- }
- }
- }
-
- /**
- * Unregisters a listener.
- *
- * @see OnActivityDestroyListener
- */
- void unregisterOnActivityDestroyListener(OnActivityDestroyListener listener) {
- synchronized (this) {
- if (mActivityDestroyListeners != null) {
- mActivityDestroyListeners.remove(listener);
- }
- }
- }
-
- /**
- * Called by the {@link PreferenceManager} to dispatch the activity destroy
- * event.
- */
- void dispatchActivityDestroy() {
- List<OnActivityDestroyListener> list = null;
-
- synchronized (this) {
- if (mActivityDestroyListeners != null) {
- list = new ArrayList<OnActivityDestroyListener>(mActivityDestroyListeners);
- }
- }
-
- if (list != null) {
- final int N = list.size();
- for (int i = 0; i < N; i++) {
- list.get(i).onActivityDestroy();
- }
- }
-
- // Dismiss any PreferenceScreens still showing
- dismissAllScreens();
- }
-
- /**
- * Returns a request code that is unique for the activity. Each subsequent
- * call to this method should return another unique request code.
- *
- * @return A unique request code that will never be used by anyone other
- * than the caller of this method.
- */
- int getNextRequestCode() {
- synchronized (this) {
- return mNextRequestCode++;
- }
- }
-
- void addPreferencesScreen(DialogInterface screen) {
- synchronized (this) {
-
- if (mPreferencesScreens == null) {
- mPreferencesScreens = new ArrayList<DialogInterface>();
- }
-
- mPreferencesScreens.add(screen);
- }
- }
-
- void removePreferencesScreen(DialogInterface screen) {
- synchronized (this) {
-
- if (mPreferencesScreens == null) {
- return;
- }
-
- mPreferencesScreens.remove(screen);
- }
- }
-
- /**
- * Called by {@link PreferenceActivity} to dispatch the new Intent event.
- *
- * @param intent The new Intent.
- */
- void dispatchNewIntent(Intent intent) {
- dismissAllScreens();
- }
-
- private void dismissAllScreens() {
- // Remove any of the previously shown preferences screens
- ArrayList<DialogInterface> screensToDismiss;
-
- synchronized (this) {
-
- if (mPreferencesScreens == null) {
- return;
- }
-
- screensToDismiss = new ArrayList<DialogInterface>(mPreferencesScreens);
- mPreferencesScreens.clear();
- }
-
- for (int i = screensToDismiss.size() - 1; i >= 0; i--) {
- screensToDismiss.get(i).dismiss();
- }
- }
-
- /**
- * Sets the callback to be invoked when a {@link Preference} in the
- * hierarchy rooted at this {@link PreferenceManager} is clicked.
- *
- * @param listener The callback to be invoked.
- */
- void setOnPreferenceTreeClickListener(OnPreferenceTreeClickListener listener) {
- mOnPreferenceTreeClickListener = listener;
- }
-
- OnPreferenceTreeClickListener getOnPreferenceTreeClickListener() {
- return mOnPreferenceTreeClickListener;
- }
-
- /**
- * Interface definition for a callback to be invoked when a
- * {@link Preference} in the hierarchy rooted at this {@link PreferenceScreen} is
- * clicked.
- */
- interface OnPreferenceTreeClickListener {
- /**
- * Called when a preference in the tree rooted at this
- * {@link PreferenceScreen} has been clicked.
- *
- * @param preferenceScreen The {@link PreferenceScreen} that the
- * preference is located in.
- * @param preference The preference that was clicked.
- * @return Whether the click was handled.
- */
- boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference);
- }
-
- /**
- * Interface definition for a class that will be called when the container's activity
- * receives an activity result.
- */
- public interface OnActivityResultListener {
-
- /**
- * See Activity's onActivityResult.
- *
- * @return Whether the request code was handled (in which case
- * subsequent listeners will not be called.
- */
- boolean onActivityResult(int requestCode, int resultCode, Intent data);
- }
-
- /**
- * Interface definition for a class that will be called when the container's activity
- * is stopped.
- */
- public interface OnActivityStopListener {
-
- /**
- * See Activity's onStop.
- */
- void onActivityStop();
- }
-
- /**
- * Interface definition for a class that will be called when the container's activity
- * is destroyed.
- */
- public interface OnActivityDestroyListener {
-
- /**
- * See Activity's onDestroy.
- */
- void onActivityDestroy();
- }
-
-}
diff --git a/core/java/android/preference/PreferenceScreen.java b/core/java/android/preference/PreferenceScreen.java
deleted file mode 100644
index 5353b53..0000000
--- a/core/java/android/preference/PreferenceScreen.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.Adapter;
-import android.widget.AdapterView;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-
-/**
- * Represents a top-level {@link Preference} that
- * is the root of a Preference hierarchy. A {@link PreferenceActivity}
- * points to an instance of this class to show the preferences. To instantiate
- * this class, use {@link PreferenceManager#createPreferenceScreen(Context)}.
- * <ul>
- * This class can appear in two places:
- * <li> When a {@link PreferenceActivity} points to this, it is used as the root
- * and is not shown (only the contained preferences are shown).
- * <li> When it appears inside another preference hierarchy, it is shown and
- * serves as the gateway to another screen of preferences (either by showing
- * another screen of preferences as a {@link Dialog} or via a
- * {@link Context#startActivity(android.content.Intent)} from the
- * {@link Preference#getIntent()}). The children of this {@link PreferenceScreen}
- * are NOT shown in the screen that this {@link PreferenceScreen} is shown in.
- * Instead, a separate screen will be shown when this preference is clicked.
- * </ul>
- * <p>Here's an example XML layout of a PreferenceScreen:</p>
- * <pre>
-&lt;PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:key="first_preferencescreen"&gt;
- &lt;CheckBoxPreference
- android:key="wifi enabled"
- android:title="WiFi" /&gt;
- &lt;PreferenceScreen
- android:key="second_preferencescreen"
- android:title="WiFi settings"&gt;
- &lt;CheckBoxPreference
- android:key="prefer wifi"
- android:title="Prefer WiFi" /&gt;
- ... other preferences here ...
- &lt;/PreferenceScreen&gt;
-&lt;/PreferenceScreen&gt; </pre>
- * <p>
- * In this example, the "first_preferencescreen" will be used as the root of the
- * hierarchy and given to a {@link PreferenceActivity}. The first screen will
- * show preferences "WiFi" (which can be used to quickly enable/disable WiFi)
- * and "WiFi settings". The "WiFi settings" is the "second_preferencescreen" and when
- * clicked will show another screen of preferences such as "Prefer WiFi" (and
- * the other preferences that are children of the "second_preferencescreen" tag).
- *
- * @see PreferenceCategory
- */
-public final class PreferenceScreen extends PreferenceGroup implements AdapterView.OnItemClickListener,
- DialogInterface.OnDismissListener {
-
- private ListAdapter mRootAdapter;
-
- private Dialog mDialog;
-
- /**
- * Do NOT use this constructor, use {@link PreferenceManager#createPreferenceScreen(Context)}.
- * @hide-
- */
- public PreferenceScreen(Context context, AttributeSet attrs) {
- super(context, attrs, com.android.internal.R.attr.preferenceScreenStyle);
- }
-
- /**
- * Returns an adapter that can be attached to a {@link PreferenceActivity}
- * to show the preferences contained in this {@link PreferenceScreen}.
- * <p>
- * This {@link PreferenceScreen} will NOT appear in the returned adapter, instead
- * it appears in the hierarchy above this {@link PreferenceScreen}.
- * <p>
- * This adapter's {@link Adapter#getItem(int)} should always return a
- * subclass of {@link Preference}.
- *
- * @return An adapter that provides the {@link Preference} contained in this
- * {@link PreferenceScreen}.
- */
- public ListAdapter getRootAdapter() {
- if (mRootAdapter == null) {
- mRootAdapter = onCreateRootAdapter();
- }
-
- return mRootAdapter;
- }
-
- /**
- * Creates the root adapter.
- *
- * @return An adapter that contains the preferences contained in this {@link PreferenceScreen}.
- * @see #getRootAdapter()
- */
- protected ListAdapter onCreateRootAdapter() {
- return new PreferenceGroupAdapter(this);
- }
-
- /**
- * Binds a {@link ListView} to the preferences contained in this {@link PreferenceScreen} via
- * {@link #getRootAdapter()}. It also handles passing list item clicks to the corresponding
- * {@link Preference} contained by this {@link PreferenceScreen}.
- *
- * @param listView The list view to attach to.
- */
- public void bind(ListView listView) {
- listView.setOnItemClickListener(this);
- listView.setAdapter(getRootAdapter());
-
- onAttachedToActivity();
- }
-
- @Override
- protected void onClick() {
- if (getIntent() != null || getPreferenceCount() == 0) {
- return;
- }
-
- showDialog(null);
- }
-
- private void showDialog(Bundle state) {
- Context context = getContext();
- ListView listView = new ListView(context);
- bind(listView);
-
- Dialog dialog = mDialog = new Dialog(context, com.android.internal.R.style.Theme_NoTitleBar);
- dialog.setContentView(listView);
- dialog.setOnDismissListener(this);
- if (state != null) {
- dialog.onRestoreInstanceState(state);
- }
-
- // Add the screen to the list of preferences screens opened as dialogs
- getPreferenceManager().addPreferencesScreen(dialog);
-
- dialog.show();
- }
-
- public void onDismiss(DialogInterface dialog) {
- mDialog = null;
- getPreferenceManager().removePreferencesScreen(dialog);
- }
-
- /**
- * Used to get a handle to the dialog.
- * This is useful for cases where we want to manipulate the dialog
- * as we would with any other activity or view.
- */
- public Dialog getDialog() {
- return mDialog;
- }
-
- public void onItemClick(AdapterView parent, View view, int position, long id) {
- Object item = getRootAdapter().getItem(position);
- if (!(item instanceof Preference)) return;
-
- final Preference preference = (Preference) item;
- preference.performClick(this);
- }
-
- @Override
- protected boolean isOnSameScreenAsChildren() {
- return false;
- }
-
- @Override
- protected Parcelable onSaveInstanceState() {
- final Parcelable superState = super.onSaveInstanceState();
- final Dialog dialog = mDialog;
- if (dialog == null || !dialog.isShowing()) {
- return superState;
- }
-
- final SavedState myState = new SavedState(superState);
- myState.isDialogShowing = true;
- myState.dialogBundle = dialog.onSaveInstanceState();
- return myState;
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- if (state == null || !state.getClass().equals(SavedState.class)) {
- // Didn't save state for us in onSaveInstanceState
- super.onRestoreInstanceState(state);
- return;
- }
-
- SavedState myState = (SavedState) state;
- super.onRestoreInstanceState(myState.getSuperState());
- if (myState.isDialogShowing) {
- showDialog(myState.dialogBundle);
- }
- }
-
- private static class SavedState extends BaseSavedState {
- boolean isDialogShowing;
- Bundle dialogBundle;
-
- public SavedState(Parcel source) {
- super(source);
- isDialogShowing = source.readInt() == 1;
- dialogBundle = source.readBundle();
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(isDialogShowing ? 1 : 0);
- dest.writeBundle(dialogBundle);
- }
-
- public SavedState(Parcelable superState) {
- super(superState);
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR =
- new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
-}
diff --git a/core/java/android/preference/RingtonePreference.java b/core/java/android/preference/RingtonePreference.java
deleted file mode 100644
index 6beb06d..0000000
--- a/core/java/android/preference/RingtonePreference.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.TypedArray;
-import android.media.RingtoneManager;
-import android.net.Uri;
-import android.provider.Settings.System;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-
-/**
- * A {@link Preference} that allows the user to choose a ringtone from those on the device.
- * The chosen ringtone's URI will be persisted as a string.
- * <p>
- * If the user chooses the "Default" item, the saved string will be one of
- * {@link System#DEFAULT_RINGTONE_URI} or
- * {@link System#DEFAULT_NOTIFICATION_URI}. If the user chooses the "Silent"
- * item, the saved string will be an empty string.
- *
- * @attr ref android.R.styleable#RingtonePreference_ringtoneType
- * @attr ref android.R.styleable#RingtonePreference_showDefault
- * @attr ref android.R.styleable#RingtonePreference_showSilent
- */
-public class RingtonePreference extends Preference implements
- PreferenceManager.OnActivityResultListener {
-
- private static final String TAG = "RingtonePreference";
-
- private int mRingtoneType;
- private boolean mShowDefault;
- private boolean mShowSilent;
-
- private int mRequestCode;
-
- public RingtonePreference(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.RingtonePreference, defStyle, 0);
- mRingtoneType = a.getInt(com.android.internal.R.styleable.RingtonePreference_ringtoneType,
- RingtoneManager.TYPE_RINGTONE);
- mShowDefault = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showDefault,
- true);
- mShowSilent = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showSilent,
- true);
- a.recycle();
- }
-
- public RingtonePreference(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.ringtonePreferenceStyle);
- }
-
- public RingtonePreference(Context context) {
- this(context, null);
- }
-
- /**
- * Returns the sound type(s) that are shown in the picker.
- *
- * @return The sound type(s) that are shown in the picker.
- * @see #setRingtoneType(int)
- */
- public int getRingtoneType() {
- return mRingtoneType;
- }
-
- /**
- * Sets the sound type(s) that are shown in the picker.
- *
- * @param type The sound type(s) that are shown in the picker.
- * @see RingtoneManager#EXTRA_RINGTONE_TYPE
- */
- public void setRingtoneType(int type) {
- mRingtoneType = type;
- }
-
- /**
- * Returns whether to a show an item for the default sound/ringtone.
- *
- * @return Whether to show an item for the default sound/ringtone.
- */
- public boolean getShowDefault() {
- return mShowDefault;
- }
-
- /**
- * Sets whether to show an item for the default sound/ringtone. The default
- * to use will be deduced from the sound type(s) being shown.
- *
- * @param showDefault Whether to show the default or not.
- * @see RingtoneManager#EXTRA_RINGTONE_SHOW_DEFAULT
- */
- public void setShowDefault(boolean showDefault) {
- mShowDefault = showDefault;
- }
-
- /**
- * Returns whether to a show an item for 'Silent'.
- *
- * @return Whether to show an item for 'Silent'.
- */
- public boolean getShowSilent() {
- return mShowSilent;
- }
-
- /**
- * Sets whether to show an item for 'Silent'.
- *
- * @param showSilent Whether to show 'Silent'.
- * @see RingtoneManager#EXTRA_RINGTONE_SHOW_SILENT
- */
- public void setShowSilent(boolean showSilent) {
- mShowSilent = showSilent;
- }
-
- @Override
- protected void onClick() {
- // Launch the ringtone picker
- Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
- onPrepareRingtonePickerIntent(intent);
- getPreferenceManager().getActivity().startActivityForResult(intent, mRequestCode);
- }
-
- /**
- * Prepares the intent to launch the ringtone picker. This can be modified
- * to adjust the parameters of the ringtone picker.
- *
- * @param ringtonePickerIntent The ringtone picker intent that can be
- * modified by putting extras.
- */
- protected void onPrepareRingtonePickerIntent(Intent ringtonePickerIntent) {
-
- ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI,
- onRestoreRingtone());
-
- ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, mShowDefault);
- if (mShowDefault) {
- ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI,
- RingtoneManager.getDefaultUri(getRingtoneType()));
- }
-
- ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, mShowSilent);
- ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, mRingtoneType);
- }
-
- /**
- * Called when a ringtone is chosen.
- * <p>
- * By default, this saves the ringtone URI to the persistent storage as a
- * string.
- *
- * @param ringtoneUri The chosen ringtone's {@link Uri}. Can be null.
- */
- protected void onSaveRingtone(Uri ringtoneUri) {
- persistString(ringtoneUri != null ? ringtoneUri.toString() : "");
- }
-
- /**
- * Called when the chooser is about to be shown and the current ringtone
- * should be marked. Can return null to not mark any ringtone.
- * <p>
- * By default, this restores the previous ringtone URI from the persistent
- * storage.
- *
- * @return The ringtone to be marked as the current ringtone.
- */
- protected Uri onRestoreRingtone() {
- final String uriString = getPersistedString(null);
- return !TextUtils.isEmpty(uriString) ? Uri.parse(uriString) : null;
- }
-
- @Override
- protected Object onGetDefaultValue(TypedArray a, int index) {
- return a.getString(index);
- }
-
- @Override
- protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValueObj) {
- String defaultValue = (String) defaultValueObj;
-
- /*
- * This method is normally to make sure the internal state and UI
- * matches either the persisted value or the default value. Since we
- * don't show the current value in the UI (until the dialog is opened)
- * and we don't keep local state, if we are restoring the persisted
- * value we don't need to do anything.
- */
- if (restorePersistedValue) {
- return;
- }
-
- // If we are setting to the default value, we should persist it.
- if (!TextUtils.isEmpty(defaultValue)) {
- onSaveRingtone(Uri.parse(defaultValue));
- }
- }
-
- @Override
- protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
- super.onAttachedToHierarchy(preferenceManager);
-
- preferenceManager.registerOnActivityResultListener(this);
- mRequestCode = preferenceManager.getNextRequestCode();
- }
-
- public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
-
- if (requestCode == mRequestCode) {
-
- if (data != null) {
- Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
-
- if (callChangeListener(uri != null ? uri.toString() : "")) {
- onSaveRingtone(uri);
- }
- }
-
- return true;
- }
-
- return false;
- }
-
-}
diff --git a/core/java/android/preference/SeekBarPreference.java b/core/java/android/preference/SeekBarPreference.java
deleted file mode 100644
index 658c2a7..0000000
--- a/core/java/android/preference/SeekBarPreference.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.preference.DialogPreference;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.SeekBar;
-
-/**
- * @hide
- */
-public class SeekBarPreference extends DialogPreference {
- private static final String TAG = "SeekBarPreference";
-
- private Drawable mMyIcon;
-
- public SeekBarPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- setDialogLayoutResource(com.android.internal.R.layout.seekbar_dialog);
- setPositiveButtonText(android.R.string.ok);
- setNegativeButtonText(android.R.string.cancel);
-
- // Steal the XML dialogIcon attribute's value
- mMyIcon = getDialogIcon();
- setDialogIcon(null);
- }
-
- @Override
- protected void onBindDialogView(View view) {
- super.onBindDialogView(view);
-
- final ImageView iconView = (ImageView) view.findViewById(android.R.id.icon);
- if (mMyIcon != null) {
- iconView.setImageDrawable(mMyIcon);
- } else {
- iconView.setVisibility(View.GONE);
- }
- }
-
- protected static SeekBar getSeekBar(View dialogView) {
- return (SeekBar) dialogView.findViewById(com.android.internal.R.id.seekbar);
- }
-}
diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java
deleted file mode 100644
index 6e215dc..0000000
--- a/core/java/android/preference/VolumePreference.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.preference;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.database.ContentObserver;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
-import android.media.AudioManager;
-import android.os.Handler;
-import android.preference.PreferenceManager;
-import android.provider.Settings;
-import android.provider.Settings.System;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
-
-/**
- * @hide
- */
-public class VolumePreference extends SeekBarPreference implements
- PreferenceManager.OnActivityStopListener {
-
- private static final String TAG = "VolumePreference";
-
- private int mStreamType;
-
- /** May be null if the dialog isn't visible. */
- private SeekBarVolumizer mSeekBarVolumizer;
-
- public VolumePreference(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.VolumePreference, 0, 0);
- mStreamType = a.getInt(android.R.styleable.VolumePreference_streamType, 0);
- a.recycle();
- }
-
- public void setStreamType(int streamType) {
- mStreamType = streamType;
- }
-
- @Override
- protected void onBindDialogView(View view) {
- super.onBindDialogView(view);
-
- final SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
- mSeekBarVolumizer = new SeekBarVolumizer(getContext(), seekBar, mStreamType);
-
- getPreferenceManager().registerOnActivityStopListener(this);
- }
-
- @Override
- protected void onDialogClosed(boolean positiveResult) {
- super.onDialogClosed(positiveResult);
-
- if (!positiveResult && mSeekBarVolumizer != null) {
- mSeekBarVolumizer.revertVolume();
- }
-
- cleanup();
- }
-
- public void onActivityStop() {
- cleanup();
- }
-
- /**
- * Do clean up. This can be called multiple times!
- */
- private void cleanup() {
- getPreferenceManager().unregisterOnActivityStopListener(this);
-
- if (mSeekBarVolumizer != null) {
- mSeekBarVolumizer.stop();
- mSeekBarVolumizer = null;
- }
- }
-
- protected void onSampleStarting(SeekBarVolumizer volumizer) {
- if (mSeekBarVolumizer != null && volumizer != mSeekBarVolumizer) {
- mSeekBarVolumizer.stopSample();
- }
- }
-
- /**
- * Turns a {@link SeekBar} into a volume control.
- */
- public class SeekBarVolumizer implements OnSeekBarChangeListener, Runnable {
-
- private Context mContext;
- private Handler mHandler = new Handler();
-
- private AudioManager mAudioManager;
- private int mStreamType;
- private int mOriginalStreamVolume;
- private Ringtone mRingtone;
-
- private int mLastProgress;
- private SeekBar mSeekBar;
-
- private ContentObserver mVolumeObserver = new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
-
- if (mSeekBar != null) {
- mSeekBar.setProgress(System.getInt(mContext.getContentResolver(),
- System.VOLUME_SETTINGS[mStreamType], 0));
- }
- }
- };
-
- public SeekBarVolumizer(Context context, SeekBar seekBar, int streamType) {
- mContext = context;
- mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- mStreamType = streamType;
- mSeekBar = seekBar;
-
- initSeekBar(seekBar);
- }
-
- private void initSeekBar(SeekBar seekBar) {
- seekBar.setMax(mAudioManager.getStreamMaxVolume(mStreamType));
- mOriginalStreamVolume = mAudioManager.getStreamVolume(mStreamType);
- seekBar.setProgress(mOriginalStreamVolume);
- seekBar.setOnSeekBarChangeListener(this);
-
- mContext.getContentResolver().registerContentObserver(
- System.getUriFor(System.VOLUME_SETTINGS[mStreamType]),
- false, mVolumeObserver);
-
- mRingtone = RingtoneManager.getRingtone(mContext,
- mStreamType == AudioManager.STREAM_NOTIFICATION
- ? Settings.System.DEFAULT_NOTIFICATION_URI
- : Settings.System.DEFAULT_RINGTONE_URI);
- mRingtone.setStreamType(mStreamType);
- }
-
- public void stop() {
- stopSample();
- mContext.getContentResolver().unregisterContentObserver(mVolumeObserver);
- mSeekBar.setOnSeekBarChangeListener(null);
- }
-
- public void revertVolume() {
- mAudioManager.setStreamVolume(mStreamType, mOriginalStreamVolume, 0);
- }
-
- public void onProgressChanged(SeekBar seekBar, int progress,
- boolean fromTouch) {
- if (!fromTouch) {
- return;
- }
-
- postSetVolume(progress);
- }
-
- private void postSetVolume(int progress) {
- // Do the volume changing separately to give responsive UI
- mLastProgress = progress;
- mHandler.removeCallbacks(this);
- mHandler.post(this);
- }
-
- public void onStartTrackingTouch(SeekBar seekBar) {
- }
-
- public void onStopTrackingTouch(SeekBar seekBar) {
- if (mRingtone != null && !mRingtone.isPlaying()) {
- sample();
- }
- }
-
- public void run() {
- mAudioManager.setStreamVolume(mStreamType, mLastProgress, 0);
- }
-
- private void sample() {
-
- // Only play a preview sample when controlling the ringer stream
- if (mStreamType != AudioManager.STREAM_RING
- && mStreamType != AudioManager.STREAM_NOTIFICATION) {
- return;
- }
-
- onSampleStarting(this);
- mRingtone.play();
- }
-
- public void stopSample() {
- if (mRingtone != null) {
- mRingtone.stop();
- }
- }
-
- public SeekBar getSeekBar() {
- return mSeekBar;
- }
-
- }
-}
diff --git a/core/java/android/preference/package.html b/core/java/android/preference/package.html
deleted file mode 100644
index d24d5bb..0000000
--- a/core/java/android/preference/package.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<HTML>
-<BODY>
-Provides classes that manage application preferences and implement the preferences UI.
-Using these ensures that all the preferences within each application are maintained
-in the same manner and the user experience is consistent with that of the system and
-other applications.
-<p>
-The preferences portion of an application
-should be ran as a separate {@link android.app.Activity} that extends
-the {@link android.preference.PreferenceActivity} class. In the PreferenceActivity, a
-{@link android.preference.PreferenceScreen} object should be the root element of the layout.
-The PreferenceScreen contains {@link android.preference.Preference} elements such as a
-{@link android.preference.CheckBoxPreference}, {@link android.preference.EditTextPreference},
-{@link android.preference.ListPreference}, {@link android.preference.PreferenceCategory},
-or {@link android.preference.RingtonePreference}. </p>
-<p>
-All settings made for a given {@link android.preference.Preference} will be automatically saved
-to the application's instance of {@link android.content.SharedPreferences}. Access to the
-SharedPreferences is simple with {@link android.preference.Preference#getSharedPreferences()}.</p>
-<p>
-Note that saved preferences are accessible only to the application that created them.</p>
-</BODY>
-</HTML>
diff --git a/core/java/android/provider/BaseColumns.java b/core/java/android/provider/BaseColumns.java
deleted file mode 100644
index f594c19..0000000
--- a/core/java/android/provider/BaseColumns.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-public interface BaseColumns
-{
- /**
- * The unique ID for a row.
- * <P>Type: INTEGER (long)</P>
- */
- public static final String _ID = "_id";
-
- /**
- * The count of rows in a directory.
- * <P>Type: INTEGER</P>
- */
- public static final String _COUNT = "_count";
-}
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
deleted file mode 100644
index 76aa51d..0000000
--- a/core/java/android/provider/Browser.java
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.net.Uri;
-import android.util.Log;
-import android.webkit.WebIconDatabase;
-
-import java.util.Date;
-
-public class Browser {
- private static final String LOGTAG = "browser";
- public static final Uri BOOKMARKS_URI =
- Uri.parse("content://browser/bookmarks");
-
- /**
- * The name of extra data when starting Browser with ACTION_VIEW or
- * ACTION_SEARCH intent.
- * <p>
- * The value should be an integer between 0 and 1000. If not set or set to
- * 0, the Browser will use default. If set to 100, the Browser will start
- * with 100%.
- */
- public static final String INITIAL_ZOOM_LEVEL = "browser.initialZoomLevel";
-
- /* if you change column order you must also change indices
- below */
- public static final String[] HISTORY_PROJECTION = new String[] {
- BookmarkColumns._ID, BookmarkColumns.URL, BookmarkColumns.VISITS,
- BookmarkColumns.DATE, BookmarkColumns.BOOKMARK, BookmarkColumns.TITLE,
- BookmarkColumns.FAVICON };
-
- /* these indices dependent on HISTORY_PROJECTION */
- public static final int HISTORY_PROJECTION_ID_INDEX = 0;
- public static final int HISTORY_PROJECTION_URL_INDEX = 1;
- public static final int HISTORY_PROJECTION_VISITS_INDEX = 2;
- public static final int HISTORY_PROJECTION_DATE_INDEX = 3;
- public static final int HISTORY_PROJECTION_BOOKMARK_INDEX = 4;
- public static final int HISTORY_PROJECTION_TITLE_INDEX = 5;
- public static final int HISTORY_PROJECTION_FAVICON_INDEX = 6;
-
- /* columns needed to determine whether to truncate history */
- public static final String[] TRUNCATE_HISTORY_PROJECTION = new String[] {
- BookmarkColumns._ID, BookmarkColumns.DATE, };
- public static final int TRUNCATE_HISTORY_PROJECTION_ID_INDEX = 0;
-
- /* truncate this many history items at a time */
- public static final int TRUNCATE_N_OLDEST = 5;
-
- public static final Uri SEARCHES_URI =
- Uri.parse("content://browser/searches");
-
- /* if you change column order you must also change indices
- below */
- public static final String[] SEARCHES_PROJECTION = new String[] {
- SearchColumns._ID, SearchColumns.SEARCH, SearchColumns.DATE };
-
- /* these indices dependent on SEARCHES_PROJECTION */
- public static final int SEARCHES_PROJECTION_SEARCH_INDEX = 1;
- public static final int SEARCHES_PROJECTION_DATE_INDEX = 2;
-
- private static final String SEARCHES_WHERE_CLAUSE = "search = ?";
-
- /* Set a cap on the count of history items in the history/bookmark
- table, to prevent db and layout operations from dragging to a
- crawl. Revisit this cap when/if db/layout performance
- improvements are made. Note: this does not affect bookmark
- entries -- if the user wants more bookmarks than the cap, they
- get them. */
- private static final int MAX_HISTORY_COUNT = 250;
-
- /**
- * Open the AddBookmark activity to save a bookmark. Launch with
- * and/or url, which can be edited by the user before saving.
- * @param c Context used to launch the AddBookmark activity.
- * @param title Title for the bookmark. Can be null or empty string.
- * @param url Url for the bookmark. Can be null or empty string.
- */
- public static final void saveBookmark(Context c,
- String title,
- String url) {
- Intent i = new Intent(Intent.ACTION_INSERT, Browser.BOOKMARKS_URI);
- i.putExtra("title", title);
- i.putExtra("url", url);
- c.startActivity(i);
- }
-
- public static final void sendString(Context c, String s) {
- Intent send = new Intent(Intent.ACTION_SEND);
- send.setType("text/plain");
- send.putExtra(Intent.EXTRA_TEXT, s);
-
- try {
- c.startActivity(Intent.createChooser(send,
- c.getText(com.android.internal.R.string.sendText)));
- } catch(android.content.ActivityNotFoundException ex) {
- // if no app handles it, do nothing
- }
- }
-
- /**
- * Return a cursor pointing to a list of all the bookmarks.
- * @param cr The ContentResolver used to access the database.
- */
- public static final Cursor getAllBookmarks(ContentResolver cr) throws
- IllegalStateException {
- return cr.query(BOOKMARKS_URI,
- new String[] { BookmarkColumns.URL },
- "bookmark = 1", null, null);
- }
-
- /**
- * Return a cursor pointing to a list of all visited site urls.
- * @param cr The ContentResolver used to access the database.
- */
- public static final Cursor getAllVisitedUrls(ContentResolver cr) throws
- IllegalStateException {
- return cr.query(BOOKMARKS_URI,
- new String[] { BookmarkColumns.URL }, null, null, null);
- }
-
- /**
- * Update the visited history to acknowledge that a site has been
- * visited.
- * @param cr The ContentResolver used to access the database.
- * @param url The site being visited.
- * @param real Whether this is an actual visit, and should be added to the
- * number of visits.
- */
- public static final void updateVisitedHistory(ContentResolver cr,
- String url, boolean real) {
- long now = new Date().getTime();
- try {
- StringBuilder sb = new StringBuilder(BookmarkColumns.URL + " = ");
- DatabaseUtils.appendEscapedSQLString(sb, url);
- Cursor c = cr.query(
- BOOKMARKS_URI,
- HISTORY_PROJECTION,
- sb.toString(),
- null,
- null);
- /* We should only get one answer that is exactly the same. */
- if (c.moveToFirst()) {
- ContentValues map = new ContentValues();
- if (real) {
- map.put(BookmarkColumns.VISITS, c
- .getInt(HISTORY_PROJECTION_VISITS_INDEX) + 1);
- }
- map.put(BookmarkColumns.DATE, now);
- cr.update(BOOKMARKS_URI, map, "_id = " + c.getInt(0), null);
- } else {
- truncateHistory(cr);
- ContentValues map = new ContentValues();
- map.put(BookmarkColumns.URL, url);
- map.put(BookmarkColumns.VISITS, real ? 1 : 0);
- map.put(BookmarkColumns.DATE, now);
- map.put(BookmarkColumns.BOOKMARK, 0);
- map.put(BookmarkColumns.TITLE, url);
- map.put(BookmarkColumns.CREATED, 0);
- cr.insert(BOOKMARKS_URI, map);
- }
- c.deactivate();
- } catch (IllegalStateException e) {
- return;
- }
- }
-
- /**
- * If there are more than MAX_HISTORY_COUNT non-bookmark history
- * items in the bookmark/history table, delete TRUNCATE_N_OLDEST
- * of them. This is used to keep our history table to a
- * reasonable size. Note: it does not prune bookmarks. If the
- * user wants 1000 bookmarks, the user gets 1000 bookmarks.
- *
- * @param cr The ContentResolver used to access the database.
- */
- public static final void truncateHistory(ContentResolver cr) {
- try {
- // Select non-bookmark history, ordered by date
- Cursor c = cr.query(
- BOOKMARKS_URI,
- TRUNCATE_HISTORY_PROJECTION,
- "bookmark = 0",
- null,
- BookmarkColumns.DATE);
- // Log.v(LOGTAG, "history count " + c.count());
- if (c.moveToFirst() && c.getCount() >= MAX_HISTORY_COUNT) {
- /* eliminate oldest history items */
- for (int i = 0; i < TRUNCATE_N_OLDEST; i++) {
- // Log.v(LOGTAG, "truncate history " +
- // c.getInt(TRUNCATE_HISTORY_PROJECTION_ID_INDEX));
- deleteHistoryWhere(
- cr, "_id = " +
- c.getInt(TRUNCATE_HISTORY_PROJECTION_ID_INDEX));
- if (!c.moveToNext()) break;
- }
- }
- c.deactivate();
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "truncateHistory", e);
- return;
- }
- }
-
- /**
- * Returns whether there is any history to clear.
- * @param cr The ContentResolver used to access the database.
- * @return boolean True if the history can be cleared.
- */
- public static final boolean canClearHistory(ContentResolver cr) {
- try {
- Cursor c = cr.query(
- BOOKMARKS_URI,
- new String [] { BookmarkColumns._ID,
- BookmarkColumns.BOOKMARK,
- BookmarkColumns.VISITS },
- "bookmark = 0 OR visits > 0",
- null,
- null
- );
- boolean ret = c.moveToFirst();
- c.deactivate();
- return ret;
- } catch (IllegalStateException e) {
- return false;
- }
- }
-
- /**
- * Delete all entries from the bookmarks/history table which are
- * not bookmarks. Also set all visited bookmarks to unvisited.
- * @param cr The ContentResolver used to access the database.
- */
- public static final void clearHistory(ContentResolver cr) {
- deleteHistoryWhere(cr, null);
- }
-
- /**
- * Helper function to delete all history items and revert all
- * bookmarks to zero visits which meet the criteria provided.
- * @param cr The ContentResolver used to access the database.
- * @param whereClause String to limit the items affected.
- * null means all items.
- */
- private static final void deleteHistoryWhere(ContentResolver cr,
- String whereClause) {
- try {
- Cursor c = cr.query(BOOKMARKS_URI,
- HISTORY_PROJECTION,
- whereClause,
- null,
- null);
- if (!c.moveToFirst()) {
- c.deactivate();
- return;
- }
-
- final WebIconDatabase iconDb = WebIconDatabase.getInstance();
- /* Delete favicons, and revert bookmarks which have been visited
- * to simply bookmarks.
- */
- StringBuffer sb = new StringBuffer();
- boolean firstTime = true;
- do {
- String url = c.getString(HISTORY_PROJECTION_URL_INDEX);
- boolean isBookmark =
- c.getInt(HISTORY_PROJECTION_BOOKMARK_INDEX) == 1;
- if (isBookmark) {
- if (firstTime) {
- firstTime = false;
- } else {
- sb.append(" OR ");
- }
- sb.append("( _id = ");
- sb.append(c.getInt(0));
- sb.append(" )");
- } else {
- iconDb.releaseIconForPageUrl(url);
- }
- } while (c.moveToNext());
- c.deactivate();
-
- if (!firstTime) {
- ContentValues map = new ContentValues();
- map.put(BookmarkColumns.VISITS, 0);
- map.put(BookmarkColumns.DATE, 0);
- /* FIXME: Should I also remove the title? */
- cr.update(BOOKMARKS_URI, map, sb.toString(), null);
- }
-
- String deleteWhereClause = BookmarkColumns.BOOKMARK + " = 0";
- if (whereClause != null) {
- deleteWhereClause += " AND " + whereClause;
- }
- cr.delete(BOOKMARKS_URI, deleteWhereClause, null);
- } catch (IllegalStateException e) {
- return;
- }
- }
-
- /**
- * Delete all history items from begin to end.
- * @param cr The ContentResolver used to access the database.
- * @param begin First date to remove. If -1, all dates before end.
- * Inclusive.
- * @param end Last date to remove. If -1, all dates after begin.
- * Non-inclusive.
- */
- public static final void deleteHistoryTimeFrame(ContentResolver cr,
- long begin, long end) {
- String whereClause;
- String date = BookmarkColumns.DATE;
- if (-1 == begin) {
- if (-1 == end) {
- clearHistory(cr);
- return;
- }
- whereClause = date + " < " + Long.toString(end);
- } else if (-1 == end) {
- whereClause = date + " >= " + Long.toString(begin);
- } else {
- whereClause = date + " >= " + Long.toString(begin) + " AND " + date
- + " < " + Long.toString(end);
- }
- deleteHistoryWhere(cr, whereClause);
- }
-
- /**
- * Remove a specific url from the history database.
- * @param cr The ContentResolver used to access the database.
- * @param url url to remove.
- */
- public static final void deleteFromHistory(ContentResolver cr,
- String url) {
- StringBuilder sb = new StringBuilder(BookmarkColumns.URL + " = ");
- DatabaseUtils.appendEscapedSQLString(sb, url);
- String matchesUrl = sb.toString();
- deleteHistoryWhere(cr, matchesUrl);
- }
-
- /**
- * Add a search string to the searches database.
- * @param cr The ContentResolver used to access the database.
- * @param search The string to add to the searches database.
- */
- public static final void addSearchUrl(ContentResolver cr, String search) {
- long now = new Date().getTime();
- try {
- Cursor c = cr.query(
- SEARCHES_URI,
- SEARCHES_PROJECTION,
- SEARCHES_WHERE_CLAUSE,
- new String [] { search },
- null);
- ContentValues map = new ContentValues();
- map.put(SearchColumns.SEARCH, search);
- map.put(SearchColumns.DATE, now);
- /* We should only get one answer that is exactly the same. */
- if (c.moveToFirst()) {
- cr.update(SEARCHES_URI, map, "_id = " + c.getInt(0), null);
- } else {
- cr.insert(SEARCHES_URI, map);
- }
- c.deactivate();
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "addSearchUrl", e);
- return;
- }
- }
- /**
- * Remove all searches from the search database.
- * @param cr The ContentResolver used to access the database.
- */
- public static final void clearSearches(ContentResolver cr) {
- // FIXME: Should this clear the urls to which these searches lead?
- // (i.e. remove google.com/query= blah blah blah)
- try {
- cr.delete(SEARCHES_URI, null, null);
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "clearSearches", e);
- }
- }
-
- /**
- * Request all icons from the database.
- * @param cr The ContentResolver used to access the database.
- * @param where Clause to be used to limit the query from the database.
- * Must be an allowable string to be passed into a database query.
- * @param listener IconListener that gets the icons once they are
- * retrieved.
- */
- public static final void requestAllIcons(ContentResolver cr, String where,
- WebIconDatabase.IconListener listener) {
- try {
- final Cursor c = cr.query(
- BOOKMARKS_URI,
- HISTORY_PROJECTION,
- where, null, null);
- if (c.moveToFirst()) {
- final WebIconDatabase db = WebIconDatabase.getInstance();
- do {
- db.requestIconForPageUrl(
- c.getString(HISTORY_PROJECTION_URL_INDEX),
- listener);
- } while (c.moveToNext());
- }
- c.deactivate();
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "requestAllIcons", e);
- }
- }
-
- public static class BookmarkColumns implements BaseColumns {
- public static final String URL = "url";
- public static final String VISITS = "visits";
- public static final String DATE = "date";
- public static final String BOOKMARK = "bookmark";
- public static final String TITLE = "title";
- public static final String CREATED = "created";
- public static final String FAVICON = "favicon";
- }
-
- public static class SearchColumns implements BaseColumns {
- public static final String URL = "url";
- public static final String SEARCH = "search";
- public static final String DATE = "date";
- }
-}
diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java
deleted file mode 100644
index d75a25f..0000000
--- a/core/java/android/provider/Calendar.java
+++ /dev/null
@@ -1,1143 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.net.Uri;
-import android.pim.ICalendar;
-import android.pim.RecurrenceSet;
-import android.text.TextUtils;
-import android.text.format.DateUtils;
-import android.text.format.Time;
-import android.util.Config;
-import android.util.Log;
-import com.android.internal.database.ArrayListCursor;
-import com.google.android.gdata.client.AndroidGDataClient;
-import com.google.android.gdata.client.AndroidXmlParserFactory;
-import com.google.wireless.gdata.calendar.client.CalendarClient;
-import com.google.wireless.gdata.calendar.data.EventEntry;
-import com.google.wireless.gdata.calendar.data.Who;
-import com.google.wireless.gdata.calendar.parser.xml.XmlCalendarGDataParserFactory;
-import com.google.wireless.gdata.data.StringUtils;
-
-import java.util.ArrayList;
-import java.util.Vector;
-
-/**
- * The Calendar provider contains all calendar events.
- *
- * @hide
- */
-public final class Calendar {
-
- public static final String TAG = "Calendar";
-
- /**
- * Broadcast Action: An event reminder.
- */
- public static final String
- EVENT_REMINDER_ACTION = "android.intent.action.EVENT_REMINDER";
-
- /**
- * These are the symbolic names for the keys used in the extra data
- * passed in the intent for event reminders.
- */
- public static final String EVENT_BEGIN_TIME = "beginTime";
- public static final String EVENT_END_TIME = "endTime";
-
- public static final String AUTHORITY = "calendar";
-
- /**
- * The content:// style URL for the top-level calendar authority
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://" + AUTHORITY);
-
- /**
- * Columns from the Calendars table that other tables join into themselves.
- */
- public interface CalendarsColumns
- {
- /**
- * The color of the calendar
- * <P>Type: INTEGER (color value)</P>
- */
- public static final String COLOR = "color";
-
- /**
- * The level of access that the user has for the calendar
- * <P>Type: INTEGER (one of the values below)</P>
- */
- public static final String ACCESS_LEVEL = "access_level";
-
- /** Cannot access the calendar */
- public static final int NO_ACCESS = 0;
- /** Can only see free/busy information about the calendar */
- public static final int FREEBUSY_ACCESS = 100;
- /** Can read all event details */
- public static final int READ_ACCESS = 200;
- public static final int RESPOND_ACCESS = 300;
- public static final int OVERRIDE_ACCESS = 400;
- /** Full access to modify the calendar, but not the access control settings */
- public static final int CONTRIBUTOR_ACCESS = 500;
- public static final int EDITOR_ACCESS = 600;
- /** Full access to the calendar */
- public static final int OWNER_ACCESS = 700;
- public static final int ROOT_ACCESS = 800;
-
- /**
- * Is the calendar selected to be displayed?
- * <P>Type: INTEGER (boolean)</P>
- */
- public static final String SELECTED = "selected";
-
- /**
- * The timezone the calendar's events occurs in
- * <P>Type: TEXT</P>
- */
- public static final String TIMEZONE = "timezone";
-
- /**
- * If this calendar is in the list of calendars that are selected for
- * syncing then "sync_events" is 1, otherwise 0.
- * <p>Type: INTEGER (boolean)</p>
- */
- public static final String SYNC_EVENTS = "sync_events";
- }
-
- /**
- * Contains a list of available calendars.
- */
- public static class Calendars implements BaseColumns, SyncConstValue, CalendarsColumns
- {
- public static final Cursor query(ContentResolver cr, String[] projection,
- String where, String orderBy)
- {
- return cr.query(CONTENT_URI, projection, where,
- null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
- }
-
- /**
- * Convenience method perform a delete on the Calendar provider
- *
- * @param cr the ContentResolver
- * @param selection the rows to delete
- * @return the count of rows that were deleted
- */
- public static int delete(ContentResolver cr, String selection, String[] selectionArgs)
- {
- return cr.delete(CONTENT_URI, selection, selectionArgs);
- }
-
- /**
- * Convenience method to delete all calendars that match the account.
- *
- * @param cr the ContentResolver
- * @param account the account whose rows should be deleted
- * @return the count of rows that were deleted
- */
- public static int deleteCalendarsForAccount(ContentResolver cr,
- String account) {
- // delete all calendars that match this account
- return Calendar.Calendars.delete(cr, Calendar.Calendars._SYNC_ACCOUNT + "=?",
- new String[] {account});
- }
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://calendar/calendars");
-
- public static final Uri LIVE_CONTENT_URI =
- Uri.parse("content://calendar/calendars?update=1");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "displayName";
-
- /**
- * The URL to the calendar
- * <P>Type: TEXT (URL)</P>
- */
- public static final String URL = "url";
-
- /**
- * The name of the calendar
- * <P>Type: TEXT</P>
- */
- public static final String NAME = "name";
-
- /**
- * The display name of the calendar
- * <P>Type: TEXT</P>
- */
- public static final String DISPLAY_NAME = "displayName";
-
- /**
- * The location the of the events in the calendar
- * <P>Type: TEXT</P>
- */
- public static final String LOCATION = "location";
-
- /**
- * Should the calendar be hidden in the calendar selection panel?
- * <P>Type: INTEGER (boolean)</P>
- */
- public static final String HIDDEN = "hidden";
- }
-
- public interface AttendeesColumns {
-
- /**
- * The id of the event.
- * <P>Type: INTEGER</P>
- */
- public static final String EVENT_ID = "event_id";
-
- /**
- * The name of the attendee.
- * <P>Type: STRING</P>
- */
- public static final String ATTENDEE_NAME = "attendeeName";
-
- /**
- * The email address of the attendee.
- * <P>Type: STRING</P>
- */
- public static final String ATTENDEE_EMAIL = "attendeeEmail";
-
- /**
- * The relationship of the attendee to the user.
- * <P>Type: INTEGER (one of {@link #RELATIONSHIP_ATTENDEE}, ...}.
- */
- public static final String ATTENDEE_RELATIONSHIP = "attendeeRelationship";
-
- public static final int RELATIONSHIP_NONE = 0;
- public static final int RELATIONSHIP_ATTENDEE = 1;
- public static final int RELATIONSHIP_ORGANIZER = 2;
- public static final int RELATIONSHIP_PERFORMER = 3;
- public static final int RELATIONSHIP_SPEAKER = 4;
-
- /**
- * The type of attendee.
- * <P>Type: Integer (one of {@link #TYPE_REQUIRED}, {@link #TYPE_OPTIONAL})
- */
- public static final String ATTENDEE_TYPE = "attendeeType";
-
- public static final int TYPE_NONE = 0;
- public static final int TYPE_REQUIRED = 1;
- public static final int TYPE_OPTIONAL = 2;
-
- /**
- * The attendance status of the attendee.
- * <P>Type: Integer (one of {@link #ATTENDEE_STATUS_ACCEPTED}, ...}.
- */
- public static final String ATTENDEE_STATUS = "attendeeStatus";
-
- public static final int ATTENDEE_STATUS_NONE = 0;
- public static final int ATTENDEE_STATUS_ACCEPTED = 1;
- public static final int ATTENDEE_STATUS_DECLINED = 2;
- public static final int ATTENDEE_STATUS_INVITED = 3;
- public static final int ATTENDEE_STATUS_TENTATIVE = 4;
- }
-
- public static final class Attendees implements BaseColumns,
- AttendeesColumns, EventsColumns {
- public static final Uri CONTENT_URI =
- Uri.parse("content://calendar/attendees");
-
- // TODO: fill out this class when we actually start utilizing attendees
- // in the calendar application.
- }
-
- /**
- * Columns from the Events table that other tables join into themselves.
- */
- public interface EventsColumns
- {
- /**
- * The calendar the event belongs to
- * <P>Type: INTEGER (foreign key to the Calendars table)</P>
- */
- public static final String CALENDAR_ID = "calendar_id";
-
- /**
- * The URI for an HTML version of this event.
- * <P>Type: TEXT</P>
- */
- public static final String HTML_URI = "htmlUri";
-
- /**
- * The title of the event
- * <P>Type: TEXT</P>
- */
- public static final String TITLE = "title";
-
- /**
- * The description of the event
- * <P>Type: TEXT</P>
- */
- public static final String DESCRIPTION = "description";
-
- /**
- * Where the event takes place.
- * <P>Type: TEXT</P>
- */
- public static final String EVENT_LOCATION = "eventLocation";
-
- /**
- * The event status
- * <P>Type: INTEGER (int)</P>
- */
- public static final String STATUS = "eventStatus";
-
- public static final int STATUS_TENTATIVE = 0;
- public static final int STATUS_CONFIRMED = 1;
- public static final int STATUS_CANCELED = 2;
-
- /**
- * This is a copy of the attendee status for the owner of this event.
- * This field is copied here so that we can efficiently filter out
- * events that are declined without having to look in the Attendees
- * table.
- *
- * <P>Type: INTEGER (int)</P>
- */
- public static final String SELF_ATTENDEE_STATUS = "selfAttendeeStatus";
-
- /**
- * The comments feed uri.
- * <P>Type: TEXT</P>
- */
- public static final String COMMENTS_URI = "commentsUri";
-
- /**
- * The time the event starts
- * <P>Type: INTEGER (long; millis since epoch)</P>
- */
- public static final String DTSTART = "dtstart";
-
- /**
- * The time the event ends
- * <P>Type: INTEGER (long; millis since epoch)</P>
- */
- public static final String DTEND = "dtend";
-
- /**
- * The duration of the event
- * <P>Type: TEXT (duration in RFC2445 format)</P>
- */
- public static final String DURATION = "duration";
-
- /**
- * The timezone for the event.
- * <P>Type: TEXT
- */
- public static final String EVENT_TIMEZONE = "eventTimezone";
-
- /**
- * Whether the event lasts all day or not
- * <P>Type: INTEGER (boolean)</P>
- */
- public static final String ALL_DAY = "allDay";
-
- /**
- * Visibility for the event.
- * <P>Type: INTEGER</P>
- */
- public static final String VISIBILITY = "visibility";
-
- public static final int VISIBILITY_DEFAULT = 0;
- public static final int VISIBILITY_CONFIDENTIAL = 1;
- public static final int VISIBILITY_PRIVATE = 2;
- public static final int VISIBILITY_PUBLIC = 3;
-
- /**
- * Transparency for the event -- does the event consume time on the calendar?
- * <P>Type: INTEGER</P>
- */
- public static final String TRANSPARENCY = "transparency";
-
- public static final int TRANSPARENCY_OPAQUE = 0;
-
- public static final int TRANSPARENCY_TRANSPARENT = 1;
-
- /**
- * Whether the event has an alarm or not
- * <P>Type: INTEGER (boolean)</P>
- */
- public static final String HAS_ALARM = "hasAlarm";
-
- /**
- * Whether the event has extended properties or not
- * <P>Type: INTEGER (boolean)</P>
- */
- public static final String HAS_EXTENDED_PROPERTIES = "hasExtendedProperties";
-
- /**
- * The recurrence rule for the event.
- * than one.
- * <P>Type: TEXT</P>
- */
- public static final String RRULE = "rrule";
-
- /**
- * The recurrence dates for the event.
- * <P>Type: TEXT</P>
- */
- public static final String RDATE = "rdate";
-
- /**
- * The recurrence exception rule for the event.
- * <P>Type: TEXT</P>
- */
- public static final String EXRULE = "exrule";
-
- /**
- * The recurrence exception dates for the event.
- * <P>Type: TEXT</P>
- */
- public static final String EXDATE = "exdate";
-
- /**
- * The _sync_id of the original recurring event for which this event is
- * an exception.
- * <P>Type: TEXT</P>
- */
- public static final String ORIGINAL_EVENT = "originalEvent";
-
- /**
- * The original instance time of the recurring event for which this
- * event is an exception.
- * <P>Type: INTEGER (long; millis since epoch)</P>
- */
- public static final String ORIGINAL_INSTANCE_TIME = "originalInstanceTime";
-
- /**
- * The allDay status (true or false) of the original recurring event
- * for which this event is an exception.
- * <P>Type: INTEGER (boolean)</P>
- */
- public static final String ORIGINAL_ALL_DAY = "originalAllDay";
-
- /**
- * The last date this event repeats on, or NULL if it never ends
- * <P>Type: INTEGER (long; millis since epoch)</P>
- */
- public static final String LAST_DATE = "lastDate";
- }
-
- /**
- * Contains one entry per calendar event. Recurring events show up as a single entry.
- */
- public static final class Events implements BaseColumns, SyncConstValue,
- EventsColumns, CalendarsColumns {
-
- private static final String[] FETCH_ENTRY_COLUMNS =
- new String[] { Events._SYNC_ACCOUNT, Events._SYNC_ID };
-
- private static final String[] ATTENDEES_COLUMNS =
- new String[] { AttendeesColumns.ATTENDEE_NAME,
- AttendeesColumns.ATTENDEE_EMAIL,
- AttendeesColumns.ATTENDEE_RELATIONSHIP,
- AttendeesColumns.ATTENDEE_TYPE,
- AttendeesColumns.ATTENDEE_STATUS };
-
- private static CalendarClient sCalendarClient = null;
-
- public static final Cursor query(ContentResolver cr, String[] projection) {
- return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
- }
-
- public static final Cursor query(ContentResolver cr, String[] projection,
- String where, String orderBy) {
- return cr.query(CONTENT_URI, projection, where,
- null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
- }
-
- private static String extractValue(ICalendar.Component component,
- String propertyName) {
- ICalendar.Property property =
- component.getFirstProperty(propertyName);
- if (property != null) {
- return property.getValue();
- }
- return null;
- }
-
- public static final Uri insertVEvent(ContentResolver cr,
- ICalendar.Component event, long calendarId, int status,
- ContentValues values) {
-
- // TODO: define VEVENT component names as constants in some
- // appropriate class (ICalendar.Component?).
-
- values.clear();
-
- // title
- String title = extractValue(event, "SUMMARY");
- if (TextUtils.isEmpty(title)) {
- if (Config.LOGD) {
- Log.d(TAG, "No SUMMARY provided for event. "
- + "Cannot import.");
- }
- return null;
- }
- values.put(TITLE, title);
-
- // status
- values.put(STATUS, status);
-
- // description
- String description = extractValue(event, "DESCRIPTION");
- if (!TextUtils.isEmpty(description)) {
- values.put(DESCRIPTION, description);
- }
-
- // where
- String where = extractValue(event, "LOCATION");
- if (!StringUtils.isEmpty(where)) {
- values.put(EVENT_LOCATION, where);
- }
-
- // Calendar ID
- values.put(CALENDAR_ID, calendarId);
-
- boolean timesSet = false;
-
- // TODO: deal with VALARMs
-
- // dtstart & dtend
- Time time = new Time(Time.TIMEZONE_UTC);
- String dtstart = null;
- String dtend = null;
- String duration = null;
- ICalendar.Property dtstartProp = event.getFirstProperty("DTSTART");
- // TODO: handle "floating" timezone (no timezone specified).
- if (dtstartProp != null) {
- dtstart = dtstartProp.getValue();
- if (!TextUtils.isEmpty(dtstart)) {
- ICalendar.Parameter tzidParam =
- dtstartProp.getFirstParameter("TZID");
- if (tzidParam != null && tzidParam.value != null) {
- time.clear(tzidParam.value);
- }
- try {
- time.parse(dtstart);
- } catch (Exception e) {
- if (Config.LOGD) {
- Log.d(TAG, "Cannot parse dtstart " + dtstart, e);
- }
- return null;
- }
- if (time.allDay) {
- values.put(ALL_DAY, 1);
- }
- values.put(DTSTART, time.toMillis(false /* use isDst */));
- values.put(EVENT_TIMEZONE, time.timezone);
- }
-
- ICalendar.Property dtendProp = event.getFirstProperty("DTEND");
- if (dtendProp != null) {
- dtend = dtendProp.getValue();
- if (!TextUtils.isEmpty(dtend)) {
- // TODO: make sure the timezones are the same for
- // start, end.
- try {
- time.parse(dtend);
- } catch (Exception e) {
- if (Config.LOGD) {
- Log.d(TAG, "Cannot parse dtend " + dtend, e);
- }
- return null;
- }
- values.put(DTEND, time.toMillis(false /* use isDst */));
- }
- } else {
- // look for a duration
- ICalendar.Property durationProp =
- event.getFirstProperty("DURATION");
- if (durationProp != null) {
- duration = durationProp.getValue();
- if (!TextUtils.isEmpty(duration)) {
- // TODO: check that it is valid?
- values.put(DURATION, duration);
- }
- }
- }
- }
- if (TextUtils.isEmpty(dtstart) ||
- (TextUtils.isEmpty(dtend) && TextUtils.isEmpty(duration))) {
- if (Config.LOGD) {
- Log.d(TAG, "No DTSTART or DTEND/DURATION defined.");
- }
- return null;
- }
-
- // rrule
- if (!RecurrenceSet.populateContentValues(event, values)) {
- return null;
- }
-
- return cr.insert(CONTENT_URI, values);
- }
-
- /**
- * Returns a singleton instance of the CalendarClient used to fetch entries from the
- * calendar server.
- * @param cr The ContentResolver used to lookup the address of the calendar server in the
- * settings database.
- * @return The singleton instance of the CalendarClient used to fetch entries from the
- * calendar server.
- */
- private static synchronized CalendarClient getCalendarClient(ContentResolver cr) {
- if (sCalendarClient == null) {
- sCalendarClient = new CalendarClient(
- new AndroidGDataClient(cr),
- new XmlCalendarGDataParserFactory(new AndroidXmlParserFactory()));
- }
- return sCalendarClient;
- }
-
- /**
- * Extracts the attendees information out of event and adds it to a new ArrayList of columns
- * within the supplied ArrayList of rows. These rows are expected to be used within an
- * {@link ArrayListCursor}.
- */
- private static final void extractAttendeesIntoArrayList(EventEntry event,
- ArrayList<ArrayList> rows) {
- Log.d(TAG, "EVENT: " + event.toString());
- Vector<Who> attendees = (Vector<Who>) event.getAttendees();
-
- int numAttendees = attendees == null ? 0 : attendees.size();
-
- for (int i = 0; i < numAttendees; ++i) {
- Who attendee = attendees.elementAt(i);
- ArrayList row = new ArrayList();
- row.add(attendee.getValue());
- row.add(attendee.getEmail());
- row.add(attendee.getRelationship());
- row.add(attendee.getType());
- row.add(attendee.getStatus());
- rows.add(row);
- }
- }
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://calendar/events");
-
- public static final Uri DELETED_CONTENT_URI =
- Uri.parse("content://calendar/deleted_events");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "";
- }
-
- /**
- * Contains one entry per calendar event instance. Recurring events show up every time
- * they occur.
- */
- public static final class Instances implements BaseColumns, EventsColumns, CalendarsColumns {
-
- public static final Cursor query(ContentResolver cr, String[] projection,
- long begin, long end) {
- Uri.Builder builder = CONTENT_URI.buildUpon();
- ContentUris.appendId(builder, begin);
- ContentUris.appendId(builder, end);
- return cr.query(builder.build(), projection, Calendars.SELECTED + "=1",
- null, DEFAULT_SORT_ORDER);
- }
-
- public static final Cursor query(ContentResolver cr, String[] projection,
- long begin, long end, String where, String orderBy) {
- Uri.Builder builder = CONTENT_URI.buildUpon();
- ContentUris.appendId(builder, begin);
- ContentUris.appendId(builder, end);
- if (TextUtils.isEmpty(where)) {
- where = Calendars.SELECTED + "=1";
- } else {
- where = "(" + where + ") AND " + Calendars.SELECTED + "=1";
- }
- return cr.query(builder.build(), projection, where,
- null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
- }
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI = Uri.parse("content://calendar/instances/when");
-
- /**
- * The default sort order for this table.
- */
- public static final String DEFAULT_SORT_ORDER = "begin ASC";
-
- /**
- * The sort order is: events with an earlier start time occur
- * first and if the start times are the same, then events with
- * a later end time occur first. The later end time is ordered
- * first so that long-running events in the calendar views appear
- * first. If the start and end times of two events are
- * the same then we sort alphabetically on the title. This isn't
- * required for correctness, it just adds a nice touch.
- */
- public static final String SORT_CALENDAR_VIEW = "begin ASC, end DESC, title ASC";
-
- /**
- * The beginning time of the instance, in UTC milliseconds
- * <P>Type: INTEGER (long; millis since epoch)</P>
- */
- public static final String BEGIN = "begin";
-
- /**
- * The ending time of the instance, in UTC milliseconds
- * <P>Type: INTEGER (long; millis since epoch)</P>
- */
- public static final String END = "end";
-
- /**
- * The event for this instance
- * <P>Type: INTEGER (long, foreign key to the Events table)</P>
- */
- public static final String EVENT_ID = "event_id";
-
- /**
- * The Julian start day of the instance, relative to the local timezone
- * <P>Type: INTEGER (int)</P>
- */
- public static final String START_DAY = "startDay";
-
- /**
- * The Julian end day of the instance, relative to the local timezone
- * <P>Type: INTEGER (int)</P>
- */
- public static final String END_DAY = "endDay";
-
- /**
- * The start minute of the instance measured from midnight in the
- * local timezone.
- * <P>Type: INTEGER (int)</P>
- */
- public static final String START_MINUTE = "startMinute";
-
- /**
- * The end minute of the instance measured from midnight in the
- * local timezone.
- * <P>Type: INTEGER (int)</P>
- */
- public static final String END_MINUTE = "endMinute";
- }
-
- /**
- * A few Calendar globals are needed in the CalendarProvider for expanding
- * the Instances table and these are all stored in the first (and only)
- * row of the CalendarMetaData table.
- */
- public interface CalendarMetaDataColumns {
- /**
- * The local timezone that was used for precomputing the fields
- * in the Instances table.
- */
- public static final String LOCAL_TIMEZONE = "localTimezone";
-
- /**
- * The minimum time used in expanding the Instances table,
- * in UTC milliseconds.
- * <P>Type: INTEGER</P>
- */
- public static final String MIN_INSTANCE = "minInstance";
-
- /**
- * The maximum time used in expanding the Instances table,
- * in UTC milliseconds.
- * <P>Type: INTEGER</P>
- */
- public static final String MAX_INSTANCE = "maxInstance";
-
- /**
- * The minimum Julian day in the BusyBits table.
- * <P>Type: INTEGER</P>
- */
- public static final String MIN_BUSYBITS = "minBusyBits";
-
- /**
- * The maximum Julian day in the BusyBits table.
- * <P>Type: INTEGER</P>
- */
- public static final String MAX_BUSYBITS = "maxBusyBits";
- }
-
- public static final class CalendarMetaData implements CalendarMetaDataColumns {
- }
-
- public interface BusyBitsColumns {
- /**
- * The Julian day number.
- * <P>Type: INTEGER (int)</P>
- */
- public static final String DAY = "day";
-
- /**
- * The 24 bits representing the 24 1-hour time slots in a day.
- * If an event in the Instances table overlaps part of a 1-hour
- * time slot then the corresponding bit is set. The first time slot
- * (12am to 1am) is bit 0. The last time slot (11pm to midnight)
- * is bit 23.
- * <P>Type: INTEGER (int)</P>
- */
- public static final String BUSYBITS = "busyBits";
-
- /**
- * The number of all-day events that occur on this day.
- * <P>Type: INTEGER (int)</P>
- */
- public static final String ALL_DAY_COUNT = "allDayCount";
- }
-
- public static final class BusyBits implements BusyBitsColumns {
- public static final Uri CONTENT_URI = Uri.parse("content://calendar/busybits/when");
-
- public static final String[] PROJECTION = { DAY, BUSYBITS, ALL_DAY_COUNT };
-
- // The number of minutes represented by one busy bit
- public static final int MINUTES_PER_BUSY_INTERVAL = 60;
-
- // The number of intervals in a day
- public static final int INTERVALS_PER_DAY = 24 * 60 / MINUTES_PER_BUSY_INTERVAL;
-
- /**
- * Retrieves the busy bits for the Julian days starting at "startDay"
- * for "numDays".
- *
- * @param cr the ContentResolver
- * @param startDay the first Julian day in the range
- * @param numDays the number of days to load (must be at least 1)
- * @return a database cursor
- */
- public static final Cursor query(ContentResolver cr, int startDay, int numDays) {
- if (numDays < 1) {
- return null;
- }
- int endDay = startDay + numDays - 1;
- Uri.Builder builder = CONTENT_URI.buildUpon();
- ContentUris.appendId(builder, startDay);
- ContentUris.appendId(builder, endDay);
- return cr.query(builder.build(), PROJECTION, null /* selection */,
- null /* selection args */, DAY);
- }
- }
-
- public interface RemindersColumns {
- /**
- * The event the reminder belongs to
- * <P>Type: INTEGER (foreign key to the Events table)</P>
- */
- public static final String EVENT_ID = "event_id";
-
- /**
- * The minutes prior to the event that the alarm should ring. -1
- * specifies that we should use the default value for the system.
- * <P>Type: INTEGER</P>
- */
- public static final String MINUTES = "minutes";
-
- public static final int MINUTES_DEFAULT = -1;
-
- /**
- * The alarm method, as set on the server. DEFAULT, ALERT, EMAIL, and
- * SMS are possible values; the device will only process DEFAULT and
- * ALERT reminders (the other types are simply stored so we can send the
- * same reminder info back to the server when we make changes).
- */
- public static final String METHOD = "method";
-
- public static final int METHOD_DEFAULT = 0;
- public static final int METHOD_ALERT = 1;
- public static final int METHOD_EMAIL = 2;
- public static final int METHOD_SMS = 3;
- }
-
- public static final class Reminders implements BaseColumns, RemindersColumns, EventsColumns {
- public static final String TABLE_NAME = "Reminders";
- public static final Uri CONTENT_URI = Uri.parse("content://calendar/reminders");
- }
-
- public interface CalendarAlertsColumns {
- /**
- * The event that the alert belongs to
- * <P>Type: INTEGER (foreign key to the Events table)</P>
- */
- public static final String EVENT_ID = "event_id";
-
- /**
- * The start time of the event, in UTC
- * <P>Type: INTEGER (long; millis since epoch)</P>
- */
- public static final String BEGIN = "begin";
-
- /**
- * The end time of the event, in UTC
- * <P>Type: INTEGER (long; millis since epoch)</P>
- */
- public static final String END = "end";
-
- /**
- * The alarm time of the event, in UTC
- * <P>Type: INTEGER (long; millis since epoch)</P>
- */
- public static final String ALARM_TIME = "alarmTime";
-
- /**
- * The creation time of this database entry, in UTC.
- * (Useful for debugging missed reminders.)
- * <P>Type: INTEGER (long; millis since epoch)</P>
- */
- public static final String CREATION_TIME = "creationTime";
-
- /**
- * The time that the alarm broadcast was received by the Calendar app,
- * in UTC. (Useful for debugging missed reminders.)
- * <P>Type: INTEGER (long; millis since epoch)</P>
- */
- public static final String RECEIVED_TIME = "receivedTime";
-
- /**
- * The time that the notification was created by the Calendar app,
- * in UTC. (Useful for debugging missed reminders.)
- * <P>Type: INTEGER (long; millis since epoch)</P>
- */
- public static final String NOTIFY_TIME = "notifyTime";
-
- /**
- * The state of this alert. It starts out as SCHEDULED, then when
- * the alarm goes off, it changes to FIRED, and then when the user
- * dismisses the alarm it changes to DISMISSED.
- * <P>Type: INTEGER</P>
- */
- public static final String STATE = "state";
-
- public static final int SCHEDULED = 0;
- public static final int FIRED = 1;
- public static final int DISMISSED = 2;
-
- /**
- * The number of minutes that this alarm precedes the start time
- * <P>Type: INTEGER </P>
- */
- public static final String MINUTES = "minutes";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "alarmTime ASC,begin ASC,title ASC";
- }
-
- public static final class CalendarAlerts implements BaseColumns,
- CalendarAlertsColumns, EventsColumns, CalendarsColumns {
- public static final String TABLE_NAME = "CalendarAlerts";
- public static final Uri CONTENT_URI = Uri.parse("content://calendar/calendar_alerts");
-
- /**
- * This URI is for grouping the query results by event_id and begin
- * time. This will return one result per instance of an event. So
- * events with multiple alarms will appear just once, but multiple
- * instances of a repeating event will show up multiple times.
- */
- public static final Uri CONTENT_URI_BY_INSTANCE =
- Uri.parse("content://calendar/calendar_alerts/by_instance");
-
- public static final Uri insert(ContentResolver cr, long eventId,
- long begin, long end, long alarmTime, int minutes) {
- ContentValues values = new ContentValues();
- values.put(CalendarAlerts.EVENT_ID, eventId);
- values.put(CalendarAlerts.BEGIN, begin);
- values.put(CalendarAlerts.END, end);
- values.put(CalendarAlerts.ALARM_TIME, alarmTime);
- long currentTime = System.currentTimeMillis();
- values.put(CalendarAlerts.CREATION_TIME, currentTime);
- values.put(CalendarAlerts.RECEIVED_TIME, 0);
- values.put(CalendarAlerts.NOTIFY_TIME, 0);
- values.put(CalendarAlerts.STATE, SCHEDULED);
- values.put(CalendarAlerts.MINUTES, minutes);
- return cr.insert(CONTENT_URI, values);
- }
-
- public static final Cursor query(ContentResolver cr, String[] projection,
- String selection, String[] selectionArgs) {
- return cr.query(CONTENT_URI, projection, selection, selectionArgs,
- DEFAULT_SORT_ORDER);
- }
-
- /**
- * Finds the next alarm after (or equal to) the given time and returns
- * the time of that alarm or -1 if no such alarm exists.
- *
- * @param cr the ContentResolver
- * @param millis the time in UTC milliseconds
- * @return the next alarm time greater than or equal to "millis", or -1
- * if no such alarm exists.
- */
- public static final long findNextAlarmTime(ContentResolver cr, long millis) {
- String selection = ALARM_TIME + ">=" + millis;
- // TODO: construct an explicit SQL query so that we can add
- // "LIMIT 1" to the end and get just one result.
- String[] projection = new String[] { ALARM_TIME };
- Cursor cursor = query(cr, projection, selection, null);
- long alarmTime = -1;
- try {
- if (cursor != null && cursor.moveToFirst()) {
- alarmTime = cursor.getLong(0);
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- return alarmTime;
- }
-
- /**
- * Searches the CalendarAlerts table for alarms that should have fired
- * but have not and then reschedules them. This method can be called
- * at boot time to restore alarms that may have been lost due to a
- * phone reboot.
- *
- * @param cr the ContentResolver
- * @param context the Context
- * @param manager the AlarmManager
- */
- public static final void rescheduleMissedAlarms(ContentResolver cr,
- Context context, AlarmManager manager) {
- // Get all the alerts that have been scheduled but have not fired
- // and should have fired by now and are not too old.
- long now = System.currentTimeMillis();
- long ancient = now - 24 * DateUtils.HOUR_IN_MILLIS;
- String selection = CalendarAlerts.STATE + "=" + CalendarAlerts.SCHEDULED
- + " AND " + CalendarAlerts.ALARM_TIME + "<" + now
- + " AND " + CalendarAlerts.ALARM_TIME + ">" + ancient
- + " AND " + CalendarAlerts.END + ">=" + now;
- String[] projection = new String[] {
- _ID,
- BEGIN,
- END,
- ALARM_TIME,
- };
- Cursor cursor = CalendarAlerts.query(cr, projection, selection, null);
- if (cursor == null) {
- return;
- }
-
- try {
- while (cursor.moveToNext()) {
- long id = cursor.getLong(0);
- long begin = cursor.getLong(1);
- long end = cursor.getLong(2);
- long alarmTime = cursor.getLong(3);
- Uri uri = ContentUris.withAppendedId(CONTENT_URI, id);
- Intent intent = new Intent(android.provider.Calendar.EVENT_REMINDER_ACTION);
- intent.setData(uri);
- intent.putExtra(android.provider.Calendar.EVENT_BEGIN_TIME, begin);
- intent.putExtra(android.provider.Calendar.EVENT_END_TIME, end);
- PendingIntent sender = PendingIntent.getBroadcast(context,
- 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
- manager.set(AlarmManager.RTC_WAKEUP, alarmTime, sender);
- }
- } finally {
- cursor.close();
- }
-
- }
-
- /**
- * Searches for an entry in the CalendarAlerts table that matches
- * the given event id, begin time and alarm time. If one is found
- * then this alarm already exists and this method returns true.
- *
- * @param cr the ContentResolver
- * @param eventId the event id to match
- * @param begin the start time of the event in UTC millis
- * @param alarmTime the alarm time of the event in UTC millis
- * @return true if there is already an alarm for the given event
- * with the same start time and alarm time.
- */
- public static final boolean alarmExists(ContentResolver cr, long eventId,
- long begin, long alarmTime) {
- String selection = CalendarAlerts.EVENT_ID + "=" + eventId
- + " AND " + CalendarAlerts.BEGIN + "=" + begin
- + " AND " + CalendarAlerts.ALARM_TIME + "=" + alarmTime;
- // TODO: construct an explicit SQL query so that we can add
- // "LIMIT 1" to the end and get just one result.
- String[] projection = new String[] { CalendarAlerts.ALARM_TIME };
- Cursor cursor = query(cr, projection, selection, null);
- boolean found = false;
- try {
- if (cursor != null && cursor.getCount() > 0) {
- found = true;
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- return found;
- }
- }
-
- public interface ExtendedPropertiesColumns {
- /**
- * The event the extended property belongs to
- * <P>Type: INTEGER (foreign key to the Events table)</P>
- */
- public static final String EVENT_ID = "event_id";
-
- /**
- * The name of the extended property. This is a uri of the form
- * {scheme}#{local-name} convention.
- * <P>Type: TEXT</P>
- */
- public static final String NAME = "name";
-
- /**
- * The value of the extended property.
- * <P>Type: TEXT</P>
- */
- public static final String VALUE = "value";
- }
-
- public static final class ExtendedProperties implements BaseColumns,
- ExtendedPropertiesColumns, EventsColumns {
- public static final Uri CONTENT_URI =
- Uri.parse("content://calendar/extendedproperties");
-
- // TODO: fill out this class when we actually start utilizing extendedproperties
- // in the calendar application.
- }
-}
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
deleted file mode 100644
index 10fe3f5..0000000
--- a/core/java/android/provider/CallLog.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.net.Uri;
-import android.provider.Contacts.People;
-import com.android.internal.telephony.CallerInfo;
-import android.text.TextUtils;
-import android.util.Log;
-
-/**
- * The CallLog provider contains information about placed and received calls.
- */
-public class CallLog {
- public static final String AUTHORITY = "call_log";
-
- /**
- * The content:// style URL for this provider
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://" + AUTHORITY);
-
- /**
- * Contains the recent calls.
- */
- public static class Calls implements BaseColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://call_log/calls");
-
- /**
- * The content:// style URL for filtering this table on phone numbers
- */
- public static final Uri CONTENT_FILTER_URI =
- Uri.parse("content://call_log/calls/filter");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "date DESC";
-
- /**
- * The MIME type of {@link #CONTENT_URI} and {@link #CONTENT_FILTER_URI}
- * providing a directory of calls.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/calls";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} sub-directory of a single
- * call.
- */
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/calls";
-
- /**
- * The type of the the phone number.
- * <P>Type: INTEGER (int)</P>
- */
- public static final String TYPE = "type";
-
- public static final int INCOMING_TYPE = 1;
- public static final int OUTGOING_TYPE = 2;
- public static final int MISSED_TYPE = 3;
-
- /**
- * The phone number as the user entered it.
- * <P>Type: TEXT</P>
- */
- public static final String NUMBER = "number";
-
- /**
- * The date the call occured, in milliseconds since the epoch
- * <P>Type: INTEGER (long)</P>
- */
- public static final String DATE = "date";
-
- /**
- * The duration of the call in seconds
- * <P>Type: INTEGER (long)</P>
- */
- public static final String DURATION = "duration";
-
- /**
- * Whether or not the call has been acknowledged
- * <P>Type: INTEGER (boolean)</P>
- */
- public static final String NEW = "new";
-
- /**
- * The cached name associated with the phone number, if it exists.
- * This value is not guaranteed to be current, if the contact information
- * associated with this number has changed.
- * <P>Type: TEXT</P>
- */
- public static final String CACHED_NAME = "name";
-
- /**
- * The cached number type (Home, Work, etc) associated with the
- * phone number, if it exists.
- * This value is not guaranteed to be current, if the contact information
- * associated with this number has changed.
- * <P>Type: INTEGER</P>
- */
- public static final String CACHED_NUMBER_TYPE = "numbertype";
-
- /**
- * The cached number label, for a custom number type, associated with the
- * phone number, if it exists.
- * This value is not guaranteed to be current, if the contact information
- * associated with this number has changed.
- * <P>Type: TEXT</P>
- */
- public static final String CACHED_NUMBER_LABEL = "numberlabel";
-
- /**
- * Adds a call to the call log.
- *
- * @param ci the CallerInfo object to get the target contact from. Can be null
- * if the contact is unknown.
- * @param context the context used to get the ContentResolver
- * @param number the phone number to be added to the calls db
- * @param isPrivateNumber <code>true</code> if the call was marked as private by the network
- * @param callType enumerated values for "incoming", "outgoing", or "missed"
- * @param start time stamp for the call in milliseconds
- * @param duration call duration in seconds
- *
- * {@hide}
- */
- public static Uri addCall(CallerInfo ci, Context context, String number,
- boolean isPrivateNumber, int callType, long start, int duration) {
- final ContentResolver resolver = context.getContentResolver();
-
- if (TextUtils.isEmpty(number)) {
- if (isPrivateNumber) {
- number = CallerInfo.PRIVATE_NUMBER;
- } else {
- number = CallerInfo.UNKNOWN_NUMBER;
- }
- }
-
- ContentValues values = new ContentValues(5);
-
- values.put(NUMBER, number);
- values.put(TYPE, Integer.valueOf(callType));
- values.put(DATE, Long.valueOf(start));
- values.put(DURATION, Long.valueOf(duration));
- values.put(NEW, Integer.valueOf(1));
- if (ci != null) {
- values.put(CACHED_NAME, ci.name);
- values.put(CACHED_NUMBER_TYPE, ci.numberType);
- values.put(CACHED_NUMBER_LABEL, ci.numberLabel);
- }
-
- if ((ci != null) && (ci.person_id > 0)) {
- People.markAsContacted(resolver, ci.person_id);
- }
-
- Uri result = resolver.insert(CONTENT_URI, values);
-
- removeExpiredEntries(context);
-
- return result;
- }
-
- private static void removeExpiredEntries(Context context) {
- final ContentResolver resolver = context.getContentResolver();
- resolver.delete(CONTENT_URI, "_id IN " +
- "(SELECT _id FROM calls ORDER BY " + DEFAULT_SORT_ORDER
- + " LIMIT -1 OFFSET 500)", null);
- }
- }
-}
diff --git a/core/java/android/provider/Checkin.java b/core/java/android/provider/Checkin.java
deleted file mode 100644
index 0cdac53..0000000
--- a/core/java/android/provider/Checkin.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import org.apache.commons.codec.binary.Base64;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.database.SQLException;
-import android.net.Uri;
-import android.os.SystemClock;
-import android.server.data.CrashData;
-import android.util.Log;
-
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-
-/**
- * Contract class for the checkin provider, used to store events and
- * statistics that will be uploaded to a checkin server eventually.
- * Describes the exposed database schema, and offers methods to add
- * events and statistics to be uploaded.
- *
- * TODO: Move this to vendor/google when we have a home for it.
- *
- * @hide
- */
-public final class Checkin {
- public static final String AUTHORITY = "android.server.checkin";
-
- /**
- * The events table is a log of important timestamped occurrences.
- * Each event has a type tag and an optional string value.
- * If too many events are added before they can be reported, the
- * content provider will erase older events to limit the table size.
- */
- public interface Events extends BaseColumns {
- public static final String TABLE_NAME = "events";
- public static final Uri CONTENT_URI =
- Uri.parse("content://" + AUTHORITY + "/" + TABLE_NAME);
-
- public static final String TAG = "tag"; // TEXT
- public static final String VALUE = "value"; // TEXT
- public static final String DATE = "date"; // INTEGER
-
- /** Valid tag values. Extend as necessary for your needs. */
- public enum Tag {
- AUTOTEST_FAILURE,
- AUTOTEST_SEQUENCE_BEGIN,
- AUTOTEST_SUITE_BEGIN,
- AUTOTEST_TEST_BEGIN,
- AUTOTEST_TEST_FAILURE,
- AUTOTEST_TEST_SUCCESS,
- BROWSER_BUG_REPORT,
- CARRIER_BUG_REPORT,
- CHECKIN_FAILURE,
- CHECKIN_SUCCESS,
- FOTA_BEGIN,
- FOTA_FAILURE,
- FOTA_INSTALL,
- FOTA_PROMPT,
- FOTA_PROMPT_ACCEPT,
- FOTA_PROMPT_REJECT,
- FOTA_PROMPT_SKIPPED,
- GSERVICES_ERROR,
- GSERVICES_UPDATE,
- LOGIN_SERVICE_ACCOUNT_TRIED,
- LOGIN_SERVICE_ACCOUNT_SAVED,
- LOGIN_SERVICE_AUTHENTICATE,
- LOGIN_SERVICE_CAPTCHA_ANSWERED,
- LOGIN_SERVICE_CAPTCHA_SHOWN,
- LOGIN_SERVICE_PASSWORD_ENTERED,
- LOGIN_SERVICE_SWITCH_GOOGLE_MAIL,
- NETWORK_DOWN,
- NETWORK_UP,
- PHONE_UI,
- RADIO_BUG_REPORT,
- SETUP_COMPLETED,
- SETUP_INITIATED,
- SETUP_IO_ERROR,
- SETUP_NETWORK_ERROR,
- SETUP_REQUIRED_CAPTCHA,
- SETUP_RETRIES_EXHAUSTED,
- SETUP_SERVER_ERROR,
- SETUP_SERVER_TIMEOUT,
- SETUP_NO_DATA_NETWORK,
- SYSTEM_APP_NOT_RESPONDING,
- SYSTEM_BOOT,
- SYSTEM_LAST_KMSG,
- SYSTEM_RECOVERY_LOG,
- SYSTEM_RESTART,
- SYSTEM_SERVICE_LOOPING,
- SYSTEM_TOMBSTONE,
- TEST,
- }
- }
-
- /**
- * The stats table is a list of counter values indexed by a tag name.
- * Each statistic has a count and sum fields, so it can track averages.
- * When multiple statistics are inserted with the same tag, the count
- * and sum fields are added together into a single entry in the database.
- */
- public interface Stats extends BaseColumns {
- public static final String TABLE_NAME = "stats";
- public static final Uri CONTENT_URI =
- Uri.parse("content://" + AUTHORITY + "/" + TABLE_NAME);
-
- public static final String TAG = "tag"; // TEXT UNIQUE
- public static final String COUNT = "count"; // INTEGER
- public static final String SUM = "sum"; // REAL
-
- /** Valid tag values. Extend as necessary for your needs. */
- public enum Tag {
- BROWSER_SNAP_CENTER,
- BROWSER_TEXT_SIZE_CHANGE,
- BROWSER_ZOOM_OVERVIEW,
- BROWSER_ZOOM_RING,
- BROWSER_ZOOM_RING_DRAG,
- CRASHES_REPORTED,
- CRASHES_TRUNCATED,
- ELAPSED_REALTIME_SEC,
- ELAPSED_UPTIME_SEC,
- HTTP_STATUS,
- PHONE_GSM_REGISTERED,
- PHONE_GPRS_ATTEMPTED,
- PHONE_GPRS_CONNECTED,
- PHONE_RADIO_RESETS,
- TEST,
- NETWORK_RX_MOBILE,
- NETWORK_TX_MOBILE,
- }
- }
-
- /**
- * The properties table is a set of tagged values sent with every checkin.
- * Unlike statistics or events, they are not cleared after being uploaded.
- * Multiple properties inserted with the same tag overwrite each other.
- */
- public interface Properties extends BaseColumns {
- public static final String TABLE_NAME = "properties";
- public static final Uri CONTENT_URI =
- Uri.parse("content://" + AUTHORITY + "/" + TABLE_NAME);
-
- public static final String TAG = "tag"; // TEXT UNIQUE
- public static final String VALUE = "value"; // TEXT
-
- /** Valid tag values, to be extended as necessary. */
- public enum Tag {
- DESIRED_BUILD,
- MARKET_CHECKIN,
- }
- }
-
- /**
- * The crashes table is a log of crash reports, kept separate from the
- * general event log because crashes are large, important, and bursty.
- * Like the events table, the crashes table is pruned on insert.
- */
- public interface Crashes extends BaseColumns {
- public static final String TABLE_NAME = "crashes";
- public static final Uri CONTENT_URI =
- Uri.parse("content://" + AUTHORITY + "/" + TABLE_NAME);
-
- // TODO: one or both of these should be a file attachment, not a column
- public static final String DATA = "data"; // TEXT
- public static final String LOGS = "logs"; // TEXT
- }
-
- /**
- * Intents with this action cause a checkin attempt. Normally triggered by
- * a periodic alarm, these may be sent directly to force immediate checkin.
- */
- public interface TriggerIntent {
- public static final String ACTION = "android.server.checkin.CHECKIN";
-
- // The category is used for GTalk service messages
- public static final String CATEGORY = "android.server.checkin.CHECKIN";
- }
-
- private static final String TAG = "Checkin";
-
- /**
- * Helper function to log an event to the database.
- *
- * @param resolver from {@link android.content.Context#getContentResolver}
- * @param tag identifying the type of event being recorded
- * @param value associated with event, if any
- * @return URI of the event that was added
- */
- static public Uri logEvent(ContentResolver resolver,
- Events.Tag tag, String value) {
- try {
- // Don't specify the date column; the content provider will add that.
- ContentValues values = new ContentValues();
- values.put(Events.TAG, tag.toString());
- if (value != null) values.put(Events.VALUE, value);
- return resolver.insert(Events.CONTENT_URI, values);
- } catch (IllegalArgumentException e) { // thrown when provider is unavailable.
- Log.w(TAG, "Can't log event " + tag + ": " + e);
- return null;
- } catch (SQLException e) {
- Log.e(TAG, "Can't log event " + tag, e); // Database errors are not fatal.
- return null;
- }
- }
-
- /**
- * Helper function to update statistics in the database.
- * Note that multiple updates to the same tag will be combined.
- *
- * @param tag identifying what is being observed
- * @param count of occurrences
- * @param sum of some value over these occurrences
- * @return URI of the statistic that was returned
- */
- static public Uri updateStats(ContentResolver resolver,
- Stats.Tag tag, int count, double sum) {
- try {
- ContentValues values = new ContentValues();
- values.put(Stats.TAG, tag.toString());
- if (count != 0) values.put(Stats.COUNT, count);
- if (sum != 0.0) values.put(Stats.SUM, sum);
- return resolver.insert(Stats.CONTENT_URI, values);
- } catch (IllegalArgumentException e) { // thrown when provider is unavailable.
- Log.w(TAG, "Can't update stat " + tag + ": " + e);
- return null;
- } catch (SQLException e) {
- Log.e(TAG, "Can't update stat " + tag, e); // Database errors are not fatal.
- return null;
- }
- }
-
- /** Minimum time to wait after a crash failure before trying again. */
- static private final long MIN_CRASH_FAILURE_RETRY = 10000; // 10 seconds
-
- /** {@link SystemClock#elapsedRealtime} of the last time a crash report failed. */
- static private volatile long sLastCrashFailureRealtime = -MIN_CRASH_FAILURE_RETRY;
-
- /**
- * Helper function to report a crash.
- *
- * @param resolver from {@link android.content.Context#getContentResolver}
- * @param crash data from {@link android.server.data.CrashData}
- * @return URI of the crash report that was added
- */
- static public Uri reportCrash(ContentResolver resolver, byte[] crash) {
- try {
- // If we are in a situation where crash reports fail (such as a full disk),
- // it's important that we don't get into a loop trying to report failures.
- // So discard all crash reports for a few seconds after reporting fails.
- long realtime = SystemClock.elapsedRealtime();
- if (realtime - sLastCrashFailureRealtime < MIN_CRASH_FAILURE_RETRY) {
- Log.e(TAG, "Crash logging skipped, too soon after logging failure");
- return null;
- }
-
- // HACK: we don't support BLOB values, so base64 encode it.
- byte[] encoded = Base64.encodeBase64(crash);
- ContentValues values = new ContentValues();
- values.put(Crashes.DATA, new String(encoded));
- Uri uri = resolver.insert(Crashes.CONTENT_URI, values);
- if (uri == null) {
- Log.e(TAG, "Error reporting crash");
- sLastCrashFailureRealtime = SystemClock.elapsedRealtime();
- }
- return uri;
- } catch (Throwable t) {
- // To avoid an infinite crash-reporting loop, swallow all errors and exceptions.
- Log.e(TAG, "Error reporting crash: " + t);
- sLastCrashFailureRealtime = SystemClock.elapsedRealtime();
- return null;
- }
- }
-
- /**
- * Report a crash in CrashData format.
- *
- * @param resolver from {@link android.content.Context#getContentResolver}
- * @param crash data to report
- * @return URI of the crash report that was added
- */
- static public Uri reportCrash(ContentResolver resolver, CrashData crash) {
- try {
- ByteArrayOutputStream data = new ByteArrayOutputStream();
- crash.write(new DataOutputStream(data));
- return reportCrash(resolver, data.toByteArray());
- } catch (Throwable t) {
- // Swallow all errors and exceptions when writing crash report
- Log.e(TAG, "Error writing crash: " + t);
- return null;
- }
- }
-}
diff --git a/core/java/android/provider/Contacts.java b/core/java/android/provider/Contacts.java
deleted file mode 100644
index 3bffaec..0000000
--- a/core/java/android/provider/Contacts.java
+++ /dev/null
@@ -1,1678 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import com.android.internal.R;
-
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.net.Uri;
-import android.text.TextUtils;
-import android.util.Log;
-import android.widget.ImageView;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-
-/**
- * The Contacts provider stores all information about contacts.
- */
-public class Contacts {
- private static final String TAG = "Contacts";
-
- public static final String AUTHORITY = "contacts";
-
- /**
- * The content:// style URL for this provider
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://" + AUTHORITY);
-
- /** Signifies an email address row that is stored in the ContactMethods table */
- public static final int KIND_EMAIL = 1;
- /** Signifies a postal address row that is stored in the ContactMethods table */
- public static final int KIND_POSTAL = 2;
- /** Signifies an IM address row that is stored in the ContactMethods table */
- public static final int KIND_IM = 3;
- /** Signifies an Organization row that is stored in the Organizations table */
- public static final int KIND_ORGANIZATION = 4;
- /** Signifies an Phone row that is stored in the Phones table */
- public static final int KIND_PHONE = 5;
-
- /**
- * no public constructor since this is a utility class
- */
- private Contacts() {}
-
- /**
- * Columns from the Settings table that other columns join into themselves.
- */
- public interface SettingsColumns {
- /**
- * The _SYNC_ACCOUNT to which this setting corresponds. This may be null.
- * <P>Type: TEXT</P>
- */
- public static final String _SYNC_ACCOUNT = "_sync_account";
-
- /**
- * The key of this setting.
- * <P>Type: TEXT</P>
- */
- public static final String KEY = "key";
-
- /**
- * The value of this setting.
- * <P>Type: TEXT</P>
- */
- public static final String VALUE = "value";
- }
-
- /**
- * The settings over all of the people
- */
- public static final class Settings implements BaseColumns, SettingsColumns {
- /**
- * no public constructor since this is a utility class
- */
- private Settings() {}
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://contacts/settings");
-
- /**
- * The directory twig for this sub-table
- */
- public static final String CONTENT_DIRECTORY = "settings";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "key ASC";
-
- /**
- * A setting that is used to indicate if we should sync down all groups for the
- * specified account. For this setting the _SYNC_ACCOUNT column must be set.
- * If this isn't set then we will only sync the groups whose SHOULD_SYNC column
- * is set to true.
- * <p>
- * This is a boolean setting. It is true if it is set and it is anything other than the
- * emptry string or "0".
- */
- public static final String SYNC_EVERYTHING = "syncEverything";
-
- public static String getSetting(ContentResolver cr, String account, String key) {
- // For now we only support a single account and the UI doesn't know what
- // the account name is, so we're using a global setting for SYNC_EVERYTHING.
- // Some day when we add multiple accounts to the UI this should honor the account
- // that was asked for.
- String selectString;
- String[] selectArgs;
- if (false) {
- selectString = (account == null)
- ? "_sync_account is null AND key=?"
- : "_sync_account=? AND key=?";
- selectArgs = (account == null)
- ? new String[]{key}
- : new String[]{account, key};
- } else {
- selectString = "key=?";
- selectArgs = new String[] {key};
- }
- Cursor cursor = cr.query(Settings.CONTENT_URI, new String[]{VALUE},
- selectString, selectArgs, null);
- try {
- if (!cursor.moveToNext()) return null;
- return cursor.getString(0);
- } finally {
- cursor.close();
- }
- }
-
- public static void setSetting(ContentResolver cr, String account, String key,
- String value) {
- ContentValues values = new ContentValues();
- // For now we only support a single account and the UI doesn't know what
- // the account name is, so we're using a global setting for SYNC_EVERYTHING.
- // Some day when we add multiple accounts to the UI this should honor the account
- // that was asked for.
- //values.put(_SYNC_ACCOUNT, account);
- values.put(KEY, key);
- values.put(VALUE, value);
- cr.update(Settings.CONTENT_URI, values, null, null);
- }
- }
-
- /**
- * Columns from the People table that other tables join into themselves.
- */
- public interface PeopleColumns {
- /**
- * The person's name.
- * <P>Type: TEXT</P>
- */
- public static final String NAME = "name";
-
- /**
- * Phonetic equivalent of the person's name, in a locale-dependent
- * character set (e.g. hiragana for Japanese).
- * Used for pronunciation and/or collation in some languages.
- * <p>Type: TEXT</P>
- */
- public static final String PHONETIC_NAME = "phonetic_name";
-
- /**
- * The display name. If name is not null name, else if number is not null number,
- * else if email is not null email.
- * <P>Type: TEXT</P>
- */
- public static final String DISPLAY_NAME = "display_name";
-
- /**
- * Notes about the person.
- * <P>Type: TEXT</P>
- */
- public static final String NOTES = "notes";
-
- /**
- * The number of times a person has been contacted
- * <P>Type: INTEGER</P>
- */
- public static final String TIMES_CONTACTED = "times_contacted";
-
- /**
- * The last time a person was contacted.
- * <P>Type: INTEGER</P>
- */
- public static final String LAST_TIME_CONTACTED = "last_time_contacted";
-
- /**
- * A custom ringtone associated with a person. Not always present.
- * <P>Type: TEXT (URI to the ringtone)</P>
- */
- public static final String CUSTOM_RINGTONE = "custom_ringtone";
-
- /**
- * Whether the person should always be sent to voicemail. Not always
- * present.
- * <P>Type: INTEGER (0 for false, 1 for true)</P>
- */
- public static final String SEND_TO_VOICEMAIL = "send_to_voicemail";
-
- /**
- * Is the contact starred?
- * <P>Type: INTEGER (boolean)</P>
- */
- public static final String STARRED = "starred";
-
- /**
- * The server version of the photo
- * <P>Type: TEXT (the version number portion of the photo URI)</P>
- */
- public static final String PHOTO_VERSION = "photo_version";
- }
-
- /**
- * This table contains people.
- */
- public static final class People implements BaseColumns, SyncConstValue, PeopleColumns,
- PhonesColumns, PresenceColumns {
- /**
- * no public constructor since this is a utility class
- */
- private People() {}
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://contacts/people");
-
- /**
- * The content:// style URL for filtering people by name. The filter
- * argument should be passed as an additional path segment after this URI.
- */
- public static final Uri CONTENT_FILTER_URI =
- Uri.parse("content://contacts/people/filter");
-
- /**
- * The content:// style URL for the table that holds the deleted
- * contacts.
- */
- public static final Uri DELETED_CONTENT_URI =
- Uri.parse("content://contacts/deleted_people");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * people.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/person";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * person.
- */
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/person";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = People.NAME + " ASC";
-
- /**
- * The ID of the persons preferred phone number.
- * <P>Type: INTEGER (foreign key to phones table on the _ID field)</P>
- */
- public static final String PRIMARY_PHONE_ID = "primary_phone";
-
- /**
- * The ID of the persons preferred email.
- * <P>Type: INTEGER (foreign key to contact_methods table on the
- * _ID field)</P>
- */
- public static final String PRIMARY_EMAIL_ID = "primary_email";
-
- /**
- * The ID of the persons preferred organization.
- * <P>Type: INTEGER (foreign key to organizations table on the
- * _ID field)</P>
- */
- public static final String PRIMARY_ORGANIZATION_ID = "primary_organization";
-
- /**
- * Mark a person as having been contacted.
- *
- * @param resolver the ContentResolver to use
- * @param personId the person who was contacted
- */
- public static void markAsContacted(ContentResolver resolver, long personId) {
- Uri uri = ContentUris.withAppendedId(CONTENT_URI, personId);
- uri = Uri.withAppendedPath(uri, "update_contact_time");
- ContentValues values = new ContentValues();
- // There is a trigger in place that will update TIMES_CONTACTED when
- // LAST_TIME_CONTACTED is modified.
- values.put(LAST_TIME_CONTACTED, System.currentTimeMillis());
- resolver.update(uri, values, null, null);
- }
-
- /**
- * Adds a person to the My Contacts group.
- *
- * @param resolver the resolver to use
- * @param personId the person to add to the group
- * @return the URI of the group membership row
- * @throws IllegalStateException if the My Contacts group can't be found
- */
- public static Uri addToMyContactsGroup(ContentResolver resolver, long personId) {
- long groupId = 0;
- Cursor groupsCursor = resolver.query(Groups.CONTENT_URI, GROUPS_PROJECTION,
- Groups.SYSTEM_ID + "='" + Groups.GROUP_MY_CONTACTS + "'", null, null);
- if (groupsCursor != null) {
- try {
- if (groupsCursor.moveToFirst()) {
- groupId = groupsCursor.getLong(0);
- }
- } finally {
- groupsCursor.close();
- }
- }
-
- if (groupId == 0) {
- throw new IllegalStateException("Failed to find the My Contacts group");
- }
-
- return addToGroup(resolver, personId, groupId);
- }
-
- /**
- * Adds a person to a group referred to by name.
- *
- * @param resolver the resolver to use
- * @param personId the person to add to the group
- * @param groupName the name of the group to add the contact to
- * @return the URI of the group membership row
- * @throws IllegalStateException if the group can't be found
- */
- public static Uri addToGroup(ContentResolver resolver, long personId, String groupName) {
- long groupId = 0;
- Cursor groupsCursor = resolver.query(Groups.CONTENT_URI, GROUPS_PROJECTION,
- Groups.NAME + "=?", new String[] { groupName }, null);
- if (groupsCursor != null) {
- try {
- if (groupsCursor.moveToFirst()) {
- groupId = groupsCursor.getLong(0);
- }
- } finally {
- groupsCursor.close();
- }
- }
-
- if (groupId == 0) {
- throw new IllegalStateException("Failed to find the My Contacts group");
- }
-
- return addToGroup(resolver, personId, groupId);
- }
-
- /**
- * Adds a person to a group.
- *
- * @param resolver the resolver to use
- * @param personId the person to add to the group
- * @param groupId the group to add the person to
- * @return the URI of the group membership row
- */
- public static Uri addToGroup(ContentResolver resolver, long personId, long groupId) {
- ContentValues values = new ContentValues();
- values.put(GroupMembership.PERSON_ID, personId);
- values.put(GroupMembership.GROUP_ID, groupId);
- return resolver.insert(GroupMembership.CONTENT_URI, values);
- }
-
- private static final String[] GROUPS_PROJECTION = new String[] {
- Groups._ID,
- };
-
- /**
- * Creates a new contacts and adds it to the "My Contacts" group.
- *
- * @param resolver the ContentResolver to use
- * @param values the values to use when creating the contact
- * @return the URI of the contact, or null if the operation fails
- */
- public static Uri createPersonInMyContactsGroup(ContentResolver resolver,
- ContentValues values) {
-
- Uri contactUri = resolver.insert(People.CONTENT_URI, values);
- if (contactUri == null) {
- Log.e(TAG, "Failed to create the contact");
- return null;
- }
-
- if (addToMyContactsGroup(resolver, ContentUris.parseId(contactUri)) == null) {
- resolver.delete(contactUri, null, null);
- return null;
- }
- return contactUri;
- }
-
- public static Cursor queryGroups(ContentResolver resolver, long person) {
- return resolver.query(GroupMembership.CONTENT_URI, null, "person=?",
- new String[]{String.valueOf(person)}, Groups.DEFAULT_SORT_ORDER);
- }
-
- /**
- * Set the photo for this person. data may be null
- * @param cr the ContentResolver to use
- * @param person the Uri of the person whose photo is to be updated
- * @param data the byte[] that represents the photo
- */
- public static void setPhotoData(ContentResolver cr, Uri person, byte[] data) {
- Uri photoUri = Uri.withAppendedPath(person, Contacts.Photos.CONTENT_DIRECTORY);
- ContentValues values = new ContentValues();
- values.put(Photos.DATA, data);
- cr.update(photoUri, values, null, null);
- }
-
- /**
- * Opens an InputStream for the person's photo and returns the photo as a Bitmap.
- * If the person's photo isn't present returns the placeholderImageResource instead.
- * @param person the person whose photo should be used
- */
- public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri person) {
- Uri photoUri = Uri.withAppendedPath(person, Contacts.Photos.CONTENT_DIRECTORY);
- Cursor cursor = cr.query(photoUri, new String[]{Photos.DATA}, null, null, null);
- try {
- if (!cursor.moveToNext()) {
- return null;
- }
- byte[] data = cursor.getBlob(0);
- if (data == null) {
- return null;
- }
- return new ByteArrayInputStream(data);
- } finally {
- cursor.close();
- }
- }
-
- /**
- * Opens an InputStream for the person's photo and returns the photo as a Bitmap.
- * If the person's photo isn't present returns the placeholderImageResource instead.
- * @param context the Context
- * @param person the person whose photo should be used
- * @param placeholderImageResource the image resource to use if the person doesn't
- * have a photo
- * @param options the decoding options, can be set to null
- */
- public static Bitmap loadContactPhoto(Context context, Uri person,
- int placeholderImageResource, BitmapFactory.Options options) {
- if (person == null) {
- return loadPlaceholderPhoto(placeholderImageResource, context, options);
- }
-
- InputStream stream = openContactPhotoInputStream(context.getContentResolver(), person);
- Bitmap bm = stream != null ? BitmapFactory.decodeStream(stream, null, options) : null;
- if (bm == null) {
- bm = loadPlaceholderPhoto(placeholderImageResource, context, options);
- }
- return bm;
- }
-
- private static Bitmap loadPlaceholderPhoto(int placeholderImageResource, Context context,
- BitmapFactory.Options options) {
- if (placeholderImageResource == 0) {
- return null;
- }
- return BitmapFactory.decodeResource(context.getResources(),
- placeholderImageResource, options);
- }
-
- /**
- * A sub directory of a single person that contains all of their Phones.
- */
- public static final class Phones implements BaseColumns, PhonesColumns,
- PeopleColumns {
- /**
- * no public constructor since this is a utility class
- */
- private Phones() {}
-
- /**
- * The directory twig for this sub-table
- */
- public static final String CONTENT_DIRECTORY = "phones";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "number ASC";
- }
-
- /**
- * A subdirectory of a single person that contains all of their
- * ContactMethods.
- */
- public static final class ContactMethods
- implements BaseColumns, ContactMethodsColumns, PeopleColumns {
- /**
- * no public constructor since this is a utility class
- */
- private ContactMethods() {}
-
- /**
- * The directory twig for this sub-table
- */
- public static final String CONTENT_DIRECTORY = "contact_methods";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "data ASC";
- }
-
- /**
- * The extensions for a person
- */
- public static class Extensions implements BaseColumns, ExtensionsColumns {
- /**
- * no public constructor since this is a utility class
- */
- private Extensions() {}
-
- /**
- * The directory twig for this sub-table
- */
- public static final String CONTENT_DIRECTORY = "extensions";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "name ASC";
-
- /**
- * The ID of the person this phone number is assigned to.
- * <P>Type: INTEGER (long)</P>
- */
- public static final String PERSON_ID = "person";
- }
- }
-
- /**
- * Columns from the groups table.
- */
- public interface GroupsColumns {
- /**
- * The group name.
- * <P>Type: TEXT</P>
- */
- public static final String NAME = "name";
-
- /**
- * Notes about the group.
- * <P>Type: TEXT</P>
- */
- public static final String NOTES = "notes";
-
- /**
- * Whether this group should be synced if the SYNC_EVERYTHING settings is false
- * for this group's account.
- * <P>Type: INTEGER (boolean)</P>
- */
- public static final String SHOULD_SYNC = "should_sync";
-
- /**
- * The ID of this group if it is a System Group, null otherwise.
- * <P>Type: TEXT</P>
- */
- public static final String SYSTEM_ID = "system_id";
- }
-
- /**
- * This table contains the groups for an account.
- */
- public static final class Groups
- implements BaseColumns, SyncConstValue, GroupsColumns {
- /**
- * no public constructor since this is a utility class
- */
- private Groups() {}
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://contacts/groups");
-
- /**
- * The content:// style URL for the table that holds the deleted
- * groups.
- */
- public static final Uri DELETED_CONTENT_URI =
- Uri.parse("content://contacts/deleted_groups");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * groups.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contactsgroup";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * group.
- */
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contactsgroup";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = NAME + " ASC";
-
- /**
- *
- */
- public static final String GROUP_ANDROID_STARRED = "Starred in Android";
-
- /**
- * The "My Contacts" system group.
- */
- public static final String GROUP_MY_CONTACTS = "Contacts";
- }
-
- /**
- * Columns from the Phones table that other columns join into themselves.
- */
- public interface PhonesColumns {
- /**
- * The type of the the phone number.
- * <P>Type: INTEGER (one of the constants below)</P>
- */
- public static final String TYPE = "type";
-
- public static final int TYPE_CUSTOM = 0;
- public static final int TYPE_HOME = 1;
- public static final int TYPE_MOBILE = 2;
- public static final int TYPE_WORK = 3;
- public static final int TYPE_FAX_WORK = 4;
- public static final int TYPE_FAX_HOME = 5;
- public static final int TYPE_PAGER = 6;
- public static final int TYPE_OTHER = 7;
-
- /**
- * The user provided label for the phone number, only used if TYPE is TYPE_CUSTOM.
- * <P>Type: TEXT</P>
- */
- public static final String LABEL = "label";
-
- /**
- * The phone number as the user entered it.
- * <P>Type: TEXT</P>
- */
- public static final String NUMBER = "number";
-
- /**
- * The normalized phone number
- * <P>Type: TEXT</P>
- */
- public static final String NUMBER_KEY = "number_key";
-
- /**
- * Whether this is the primary phone number
- * <P>Type: INTEGER (if set, non-0 means true)</P>
- */
- public static final String ISPRIMARY = "isprimary";
- }
-
- /**
- * This table stores phone numbers and a reference to the person that the
- * contact method belongs to. Phone numbers are stored separately from
- * other contact methods to make caller ID lookup more efficient.
- */
- public static final class Phones
- implements BaseColumns, PhonesColumns, PeopleColumns {
- /**
- * no public constructor since this is a utility class
- */
- private Phones() {}
-
- public static final CharSequence getDisplayLabel(Context context, int type,
- CharSequence label, CharSequence[] labelArray) {
- CharSequence display = "";
-
- if (type != People.Phones.TYPE_CUSTOM) {
- CharSequence[] labels = labelArray != null? labelArray
- : context.getResources().getTextArray(
- com.android.internal.R.array.phoneTypes);
- try {
- display = labels[type - 1];
- } catch (ArrayIndexOutOfBoundsException e) {
- display = labels[People.Phones.TYPE_HOME - 1];
- }
- } else {
- if (!TextUtils.isEmpty(label)) {
- display = label;
- }
- }
- return display;
- }
-
- public static final CharSequence getDisplayLabel(Context context, int type,
- CharSequence label) {
- return getDisplayLabel(context, type, label, null);
- }
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://contacts/phones");
-
- /**
- * The content:// style URL for filtering phone numbers
- */
- public static final Uri CONTENT_FILTER_URL =
- Uri.parse("content://contacts/phones/filter");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * phones.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * phone.
- */
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "name ASC";
-
- /**
- * The ID of the person this phone number is assigned to.
- * <P>Type: INTEGER (long)</P>
- */
- public static final String PERSON_ID = "person";
- }
-
- public static final class GroupMembership implements BaseColumns, GroupsColumns {
- /**
- * no public constructor since this is a utility class
- */
- private GroupMembership() {}
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://contacts/groupmembership");
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri RAW_CONTENT_URI =
- Uri.parse("content://contacts/groupmembershipraw");
-
- /**
- * The directory twig for this sub-table
- */
- public static final String CONTENT_DIRECTORY = "groupmembership";
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of all
- * person groups.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contactsgroupmembership";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * person group.
- */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/contactsgroupmembership";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "group_id ASC";
-
- /**
- * The row id of the accounts group.
- * <P>Type: TEXT</P>
- */
- public static final String GROUP_ID = "group_id";
-
- /**
- * The sync id of the group.
- * <P>Type: TEXT</P>
- */
- public static final String GROUP_SYNC_ID = "group_sync_id";
-
- /**
- * The account of the group.
- * <P>Type: TEXT</P>
- */
- public static final String GROUP_SYNC_ACCOUNT = "group_sync_account";
-
- /**
- * The row id of the person.
- * <P>Type: TEXT</P>
- */
- public static final String PERSON_ID = "person";
- }
-
- /**
- * Columns from the ContactMethods table that other tables join into
- * themseleves.
- */
- public interface ContactMethodsColumns {
- /**
- * The kind of the the contact method. For example, email address,
- * postal address, etc.
- * <P>Type: INTEGER (one of the values below)</P>
- */
- public static final String KIND = "kind";
-
- /**
- * The type of the contact method, must be one of the types below.
- * <P>Type: INTEGER (one of the values below)</P>
- */
- public static final String TYPE = "type";
- public static final int TYPE_CUSTOM = 0;
- public static final int TYPE_HOME = 1;
- public static final int TYPE_WORK = 2;
- public static final int TYPE_OTHER = 3;
-
- /**
- * The user defined label for the the contact method.
- * <P>Type: TEXT</P>
- */
- public static final String LABEL = "label";
-
- /**
- * The data for the contact method.
- * <P>Type: TEXT</P>
- */
- public static final String DATA = "data";
-
- /**
- * Auxiliary data for the contact method.
- * <P>Type: TEXT</P>
- */
- public static final String AUX_DATA = "aux_data";
-
- /**
- * Whether this is the primary organization
- * <P>Type: INTEGER (if set, non-0 means true)</P>
- */
- public static final String ISPRIMARY = "isprimary";
- }
-
- /**
- * This table stores all non-phone contact methods and a reference to the
- * person that the contact method belongs to.
- */
- public static final class ContactMethods
- implements BaseColumns, ContactMethodsColumns, PeopleColumns {
- /**
- * The column with latitude data for postal locations
- * <P>Type: REAL</P>
- */
- public static final String POSTAL_LOCATION_LATITUDE = DATA;
-
- /**
- * The column with longitude data for postal locations
- * <P>Type: REAL</P>
- */
- public static final String POSTAL_LOCATION_LONGITUDE = AUX_DATA;
-
- /**
- * The predefined IM protocol types. The protocol can either be non-present, one
- * of these types, or a free-form string. These cases are encoded in the AUX_DATA
- * column as:
- * - null
- * - pre:<an integer, one of the protocols below>
- * - custom:<a string>
- */
- public static final int PROTOCOL_AIM = 0;
- public static final int PROTOCOL_MSN = 1;
- public static final int PROTOCOL_YAHOO = 2;
- public static final int PROTOCOL_SKYPE = 3;
- public static final int PROTOCOL_QQ = 4;
- public static final int PROTOCOL_GOOGLE_TALK = 5;
- public static final int PROTOCOL_ICQ = 6;
- public static final int PROTOCOL_JABBER = 7;
-
- public static String encodePredefinedImProtocol(int protocol) {
- return "pre:" + protocol;
- }
-
- public static String encodeCustomImProtocol(String protocolString) {
- return "custom:" + protocolString;
- }
-
- public static Object decodeImProtocol(String encodedString) {
- if (encodedString == null) {
- return null;
- }
-
- if (encodedString.startsWith("pre:")) {
- return Integer.parseInt(encodedString.substring(4));
- }
-
- if (encodedString.startsWith("custom:")) {
- return encodedString.substring(7);
- }
-
- throw new IllegalArgumentException(
- "the value is not a valid encoded protocol, " + encodedString);
- }
-
- /**
- * This looks up the provider name defined in
- * {@link android.provider.Im.ProviderNames} from the predefined IM protocol id.
- * This is used for interacting with the IM application.
- *
- * @param protocol the protocol ID
- * @return the provider name the IM app uses for the given protocol, or null if no
- * provider is defined for the given protocol
- * @hide
- */
- public static String lookupProviderNameFromId(int protocol) {
- switch (protocol) {
- case PROTOCOL_GOOGLE_TALK:
- return Im.ProviderNames.GTALK;
- case PROTOCOL_AIM:
- return Im.ProviderNames.AIM;
- case PROTOCOL_MSN:
- return Im.ProviderNames.MSN;
- case PROTOCOL_YAHOO:
- return Im.ProviderNames.YAHOO;
- case PROTOCOL_ICQ:
- return Im.ProviderNames.ICQ;
- case PROTOCOL_JABBER:
- return Im.ProviderNames.JABBER;
- case PROTOCOL_SKYPE:
- return Im.ProviderNames.SKYPE;
- case PROTOCOL_QQ:
- return Im.ProviderNames.QQ;
- }
- return null;
- }
-
- /**
- * no public constructor since this is a utility class
- */
- private ContactMethods() {}
-
- public static final CharSequence getDisplayLabel(Context context, int kind,
- int type, CharSequence label) {
- CharSequence display = "";
- switch (kind) {
- case KIND_EMAIL: {
- if (type != People.ContactMethods.TYPE_CUSTOM) {
- CharSequence[] labels = context.getResources().getTextArray(
- com.android.internal.R.array.emailAddressTypes);
- try {
- display = labels[type - 1];
- } catch (ArrayIndexOutOfBoundsException e) {
- display = labels[ContactMethods.TYPE_HOME - 1];
- }
- } else {
- if (!TextUtils.isEmpty(label)) {
- display = label;
- }
- }
- break;
- }
-
- case KIND_POSTAL: {
- if (type != People.ContactMethods.TYPE_CUSTOM) {
- CharSequence[] labels = context.getResources().getTextArray(
- com.android.internal.R.array.postalAddressTypes);
- try {
- display = labels[type - 1];
- } catch (ArrayIndexOutOfBoundsException e) {
- display = labels[ContactMethods.TYPE_HOME - 1];
- }
- } else {
- if (!TextUtils.isEmpty(label)) {
- display = label;
- }
- }
- break;
- }
-
- default:
- display = context.getString(R.string.untitled);
- }
- return display;
- }
-
- /**
- * Add a longitude and latitude location to a postal address.
- *
- * @param context the context to use when updating the database
- * @param postalId the address to update
- * @param latitude the latitude for the address
- * @param longitude the longitude for the address
- */
- public void addPostalLocation(Context context, long postalId,
- double latitude, double longitude) {
- final ContentResolver resolver = context.getContentResolver();
- // Insert the location
- ContentValues values = new ContentValues(2);
- values.put(POSTAL_LOCATION_LATITUDE, latitude);
- values.put(POSTAL_LOCATION_LONGITUDE, longitude);
- Uri loc = resolver.insert(CONTENT_URI, values);
- long locId = ContentUris.parseId(loc);
-
- // Update the postal address
- values.clear();
- values.put(AUX_DATA, locId);
- resolver.update(ContentUris.withAppendedId(CONTENT_URI, postalId), values, null, null);
- }
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://contacts/contact_methods");
-
- /**
- * The content:// style URL for sub-directory of e-mail addresses.
- */
- public static final Uri CONTENT_EMAIL_URI =
- Uri.parse("content://contacts/contact_methods/email");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * phones.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact-methods";
-
- /**
- * The MIME type of a {@link #CONTENT_EMAIL_URI} sub-directory of\
- * multiple {@link Contacts#KIND_EMAIL} entries.
- */
- public static final String CONTENT_EMAIL_TYPE = "vnd.android.cursor.dir/email";
-
- /**
- * The MIME type of a {@link #CONTENT_EMAIL_URI} sub-directory of\
- * multiple {@link Contacts#KIND_POSTAL} entries.
- */
- public static final String CONTENT_POSTAL_TYPE = "vnd.android.cursor.dir/postal-address";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} sub-directory of a single
- * {@link Contacts#KIND_EMAIL} entry.
- */
- public static final String CONTENT_EMAIL_ITEM_TYPE = "vnd.android.cursor.item/email";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} sub-directory of a single
- * {@link Contacts#KIND_POSTAL} entry.
- */
- public static final String CONTENT_POSTAL_ITEM_TYPE
- = "vnd.android.cursor.item/postal-address";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} sub-directory of a single
- * {@link Contacts#KIND_IM} entry.
- */
- public static final String CONTENT_IM_ITEM_TYPE = "vnd.android.cursor.item/jabber-im";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "name ASC";
-
- /**
- * The ID of the person this contact method is assigned to.
- * <P>Type: INTEGER (long)</P>
- */
- public static final String PERSON_ID = "person";
- }
-
- /**
- * The IM presence columns with some contacts specific columns mixed in.
- */
- public interface PresenceColumns extends Im.CommonPresenceColumns {
- /**
- * The IM service the presence is coming from. Formatted using either
- * {@link Contacts.ContactMethods#encodePredefinedImProtocol} or
- * {@link Contacts.ContactMethods#encodeCustomImProtocol}.
- * <P>Type: STRING</P>
- */
- public static final String IM_PROTOCOL = "im_protocol";
-
- /**
- * The IM handle the presence item is for. The handle is scoped to
- * the {@link #IM_PROTOCOL}.
- * <P>Type: STRING</P>
- */
- public static final String IM_HANDLE = "im_handle";
-
- /**
- * The IM account for the local user that the presence data came from.
- * <P>Type: STRING</P>
- */
- public static final String IM_ACCOUNT = "im_account";
- }
-
- /**
- * Contains presence information about contacts.
- * @hide
- */
- public static final class Presence
- implements BaseColumns, PresenceColumns, PeopleColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://contacts/presence");
-
- /**
- * The ID of the person this presence item is assigned to.
- * <P>Type: INTEGER (long)</P>
- */
- public static final String PERSON_ID = "person";
-
- /**
- * Gets the resource ID for the proper presence icon.
- *
- * @param status the status to get the icon for
- * @return the resource ID for the proper presence icon
- */
- public static final int getPresenceIconResourceId(int status) {
- switch (status) {
- case Contacts.People.AVAILABLE:
- return com.android.internal.R.drawable.presence_online;
-
- case Contacts.People.IDLE:
- case Contacts.People.AWAY:
- return com.android.internal.R.drawable.presence_away;
-
- case Contacts.People.DO_NOT_DISTURB:
- return com.android.internal.R.drawable.presence_busy;
-
- case Contacts.People.INVISIBLE:
- return com.android.internal.R.drawable.presence_invisible;
-
- case Contacts.People.OFFLINE:
- default:
- return com.android.internal.R.drawable.presence_offline;
- }
- }
-
- /**
- * Sets a presence icon to the proper graphic
- *
- * @param icon the icon to to set
- * @param serverStatus that status
- */
- public static final void setPresenceIcon(ImageView icon, int serverStatus) {
- icon.setImageResource(getPresenceIconResourceId(serverStatus));
- }
- }
-
- /**
- * Columns from the Organizations table that other columns join into themselves.
- */
- public interface OrganizationColumns {
- /**
- * The type of the the phone number.
- * <P>Type: INTEGER (one of the constants below)</P>
- */
- public static final String TYPE = "type";
-
- public static final int TYPE_CUSTOM = 0;
- public static final int TYPE_WORK = 1;
- public static final int TYPE_OTHER = 2;
-
- /**
- * The user provided label, only used if TYPE is TYPE_CUSTOM.
- * <P>Type: TEXT</P>
- */
- public static final String LABEL = "label";
-
- /**
- * The name of the company for this organization.
- * <P>Type: TEXT</P>
- */
- public static final String COMPANY = "company";
-
- /**
- * The title within this organization.
- * <P>Type: TEXT</P>
- */
- public static final String TITLE = "title";
-
- /**
- * The person this organization is tied to.
- * <P>Type: TEXT</P>
- */
- public static final String PERSON_ID = "person";
-
- /**
- * Whether this is the primary organization
- * <P>Type: INTEGER (if set, non-0 means true)</P>
- */
- public static final String ISPRIMARY = "isprimary";
- }
-
- /**
- * A sub directory of a single person that contains all of their Phones.
- */
- public static final class Organizations implements BaseColumns, OrganizationColumns {
- /**
- * no public constructor since this is a utility class
- */
- private Organizations() {}
-
- public static final CharSequence getDisplayLabel(Context context, int type,
- CharSequence label) {
- CharSequence display = "";
-
- if (type != TYPE_CUSTOM) {
- CharSequence[] labels = context.getResources().getTextArray(
- com.android.internal.R.array.organizationTypes);
- try {
- display = labels[type - 1];
- } catch (ArrayIndexOutOfBoundsException e) {
- display = labels[Organizations.TYPE_WORK - 1];
- }
- } else {
- if (!TextUtils.isEmpty(label)) {
- display = label;
- }
- }
- return display;
- }
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://contacts/organizations");
-
- /**
- * The directory twig for this sub-table
- */
- public static final String CONTENT_DIRECTORY = "organizations";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "company, title, isprimary ASC";
- }
-
- /**
- * Columns from the Photos table that other columns join into themselves.
- */
- public interface PhotosColumns {
- /**
- * The _SYNC_VERSION of the photo that was last downloaded
- * <P>Type: TEXT</P>
- */
- public static final String LOCAL_VERSION = "local_version";
-
- /**
- * The person this photo is associated with.
- * <P>Type: TEXT</P>
- */
- public static final String PERSON_ID = "person";
-
- /**
- * non-zero if a download is required and the photo isn't marked as a bad resource.
- * You must specify this in the columns in order to use it in the where clause.
- * <P>Type: INTEGER(boolean)</P>
- */
- public static final String DOWNLOAD_REQUIRED = "download_required";
-
- /**
- * non-zero if this photo is known to exist on the server
- * <P>Type: INTEGER(boolean)</P>
- */
- public static final String EXISTS_ON_SERVER = "exists_on_server";
-
- /**
- * Contains the description of the upload or download error from
- * the previous attempt. If null then the previous attempt succeeded.
- * <P>Type: TEXT</P>
- */
- public static final String SYNC_ERROR = "sync_error";
-
- /**
- * The image data, or null if there is no image.
- * <P>Type: BLOB</P>
- */
- public static final String DATA = "data";
-
- }
-
- /**
- * The photos over all of the people
- */
- public static final class Photos implements BaseColumns, PhotosColumns, SyncConstValue {
- /**
- * no public constructor since this is a utility class
- */
- private Photos() {}
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://contacts/photos");
-
- /**
- * The directory twig for this sub-table
- */
- public static final String CONTENT_DIRECTORY = "photo";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "person ASC";
- }
-
- public interface ExtensionsColumns {
- /**
- * The name of this extension. May not be null. There may be at most one row for each name.
- * <P>Type: TEXT</P>
- */
- public static final String NAME = "name";
-
- /**
- * The value of this extension. May not be null.
- * <P>Type: TEXT</P>
- */
- public static final String VALUE = "value";
- }
-
- /**
- * The extensions for a person
- */
- public static final class Extensions implements BaseColumns, ExtensionsColumns {
- /**
- * no public constructor since this is a utility class
- */
- private Extensions() {}
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://contacts/extensions");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * phones.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_extensions";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * phone.
- */
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_extensions";
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "person, name ASC";
-
- /**
- * The ID of the person this phone number is assigned to.
- * <P>Type: INTEGER (long)</P>
- */
- public static final String PERSON_ID = "person";
- }
-
- /**
- * Contains helper classes used to create or manage {@link android.content.Intent Intents}
- * that involve contacts.
- */
- public static final class Intents {
- /**
- * This is the intent that is fired when a search suggestion is clicked on.
- */
- public static final String SEARCH_SUGGESTION_CLICKED =
- "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED";
-
- /**
- * This is the intent that is fired when a search suggestion for dialing a number
- * is clicked on.
- */
- public static final String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED =
- "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED";
-
- /**
- * This is the intent that is fired when a search suggestion for creating a contact
- * is clicked on.
- */
- public static final String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED =
- "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED";
-
- /**
- * Starts an Activity that lets the user pick a contact to attach an image to.
- * After picking the contact it launches the image cropper in face detection mode.
- */
- public static final String ATTACH_IMAGE =
- "com.android.contacts.action.ATTACH_IMAGE";
-
- /**
- * Intents related to the Contacts app UI.
- */
- public static final class UI {
- /**
- * The action for the default contacts list tab.
- */
- public static final String LIST_DEFAULT =
- "com.android.contacts.action.LIST_DEFAULT";
-
- /**
- * The action for the contacts list tab.
- */
- public static final String LIST_GROUP_ACTION =
- "com.android.contacts.action.LIST_GROUP";
-
- /**
- * When in LIST_GROUP_ACTION mode, this is the group to display.
- */
- public static final String GROUP_NAME_EXTRA_KEY = "com.android.contacts.extra.GROUP";
-
- /**
- * The action for the all contacts list tab.
- */
- public static final String LIST_ALL_CONTACTS_ACTION =
- "com.android.contacts.action.LIST_ALL_CONTACTS";
-
- /**
- * The action for the contacts with phone numbers list tab.
- */
- public static final String LIST_CONTACTS_WITH_PHONES_ACTION =
- "com.android.contacts.action.LIST_CONTACTS_WITH_PHONES";
-
- /**
- * The action for the starred contacts list tab.
- */
- public static final String LIST_STARRED_ACTION =
- "com.android.contacts.action.LIST_STARRED";
-
- /**
- * The action for the frequent contacts list tab.
- */
- public static final String LIST_FREQUENT_ACTION =
- "com.android.contacts.action.LIST_FREQUENT";
-
- /**
- * The action for the "strequent" contacts list tab. It first lists the starred
- * contacts in alphabetical order and then the frequent contacts in descending
- * order of the number of times they have been contacted.
- */
- public static final String LIST_STREQUENT_ACTION =
- "com.android.contacts.action.LIST_STREQUENT";
-
- /**
- * A key for to be used as an intent extra to set the activity
- * title to a custom String value.
- */
- public static final String TITLE_EXTRA_KEY =
- "com.android.contacts.extra.TITLE_EXTRA";
-
- /**
- * Activity Action: Display a filtered list of contacts
- * <p>
- * Input: Extra field {@link #FILTER_TEXT_EXTRA_KEY} is the text to use for
- * filtering
- * <p>
- * Output: Nothing.
- */
- public static final String FILTER_CONTACTS_ACTION =
- "com.android.contacts.action.FILTER_CONTACTS";
-
- /**
- * Used as an int extra field in {@link #FILTER_CONTACTS_ACTION}
- * intents to supply the text on which to filter.
- */
- public static final String FILTER_TEXT_EXTRA_KEY =
- "com.android.contacts.extra.FILTER_TEXT";
- }
-
- /**
- * Convenience class that contains string constants used
- * to create contact {@link android.content.Intent Intents}.
- */
- public static final class Insert {
- /** The action code to use when adding a contact */
- public static final String ACTION = Intent.ACTION_INSERT;
-
- /**
- * If present, forces a bypass of quick insert mode.
- */
- public static final String FULL_MODE = "full_mode";
-
- /**
- * The extra field for the contact name.
- * <P>Type: String</P>
- */
- public static final String NAME = "name";
-
- /**
- * The extra field for the contact phonetic name.
- * <P>Type: String</P>
- */
- public static final String PHONETIC_NAME = "phonetic_name";
-
- /**
- * The extra field for the contact company.
- * <P>Type: String</P>
- */
- public static final String COMPANY = "company";
-
- /**
- * The extra field for the contact job title.
- * <P>Type: String</P>
- */
- public static final String JOB_TITLE = "job_title";
-
- /**
- * The extra field for the contact notes.
- * <P>Type: String</P>
- */
- public static final String NOTES = "notes";
-
- /**
- * The extra field for the contact phone number.
- * <P>Type: String</P>
- */
- public static final String PHONE = "phone";
-
- /**
- * The extra field for the contact phone number type.
- * <P>Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns},
- * or a string specifying a custom label.</P>
- */
- public static final String PHONE_TYPE = "phone_type";
-
- /**
- * The extra field for the phone isprimary flag.
- * <P>Type: boolean</P>
- */
- public static final String PHONE_ISPRIMARY = "phone_isprimary";
-
- /**
- * The extra field for an optional second contact phone number.
- * <P>Type: String</P>
- */
- public static final String SECONDARY_PHONE = "secondary_phone";
-
- /**
- * The extra field for an optional second contact phone number type.
- * <P>Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns},
- * or a string specifying a custom label.</P>
- */
- public static final String SECONDARY_PHONE_TYPE = "secondary_phone_type";
-
- /**
- * The extra field for an optional third contact phone number.
- * <P>Type: String</P>
- */
- public static final String TERTIARY_PHONE = "tertiary_phone";
-
- /**
- * The extra field for an optional third contact phone number type.
- * <P>Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns},
- * or a string specifying a custom label.</P>
- */
- public static final String TERTIARY_PHONE_TYPE = "tertiary_phone_type";
-
- /**
- * The extra field for the contact email address.
- * <P>Type: String</P>
- */
- public static final String EMAIL = "email";
-
- /**
- * The extra field for the contact email type.
- * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
- * or a string specifying a custom label.</P>
- */
- public static final String EMAIL_TYPE = "email_type";
-
- /**
- * The extra field for the email isprimary flag.
- * <P>Type: boolean</P>
- */
- public static final String EMAIL_ISPRIMARY = "email_isprimary";
-
- /**
- * The extra field for an optional second contact email address.
- * <P>Type: String</P>
- */
- public static final String SECONDARY_EMAIL = "secondary_email";
-
- /**
- * The extra field for an optional second contact email type.
- * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
- * or a string specifying a custom label.</P>
- */
- public static final String SECONDARY_EMAIL_TYPE = "secondary_email_type";
-
- /**
- * The extra field for an optional third contact email address.
- * <P>Type: String</P>
- */
- public static final String TERTIARY_EMAIL = "tertiary_email";
-
- /**
- * The extra field for an optional third contact email type.
- * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
- * or a string specifying a custom label.</P>
- */
- public static final String TERTIARY_EMAIL_TYPE = "tertiary_email_type";
-
- /**
- * The extra field for the contact postal address.
- * <P>Type: String</P>
- */
- public static final String POSTAL = "postal";
-
- /**
- * The extra field for the contact postal address type.
- * <P>Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}
- * or a string specifying a custom label.</P>
- */
- public static final String POSTAL_TYPE = "postal_type";
-
- /**
- * The extra field for the postal isprimary flag.
- * <P>Type: boolean</P>
- */
- public static final String POSTAL_ISPRIMARY = "postal_isprimary";
-
- /**
- * The extra field for an IM handle.
- * <P>Type: String</P>
- */
- public static final String IM_HANDLE = "im_handle";
-
- /**
- * The extra field for the IM protocol
- * <P>Type: the result of {@link Contacts.ContactMethods#encodePredefinedImProtocol}
- * or {@link Contacts.ContactMethods#encodeCustomImProtocol}.</P>
- */
- public static final String IM_PROTOCOL = "im_protocol";
-
- /**
- * The extra field for the IM isprimary flag.
- * <P>Type: boolean</P>
- */
- public static final String IM_ISPRIMARY = "im_isprimary";
- }
- }
-}
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
deleted file mode 100644
index 4c58e0d..0000000
--- a/core/java/android/provider/Downloads.java
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import android.net.Uri;
-
-/**
- * Exposes constants used to interact with the download manager's
- * content provider.
- * The constants URI ... STATUS are the names of columns in the downloads table.
- *
- * @hide
- */
-// For 1.0 the download manager can't deal with abuse from untrusted apps, so
-// this API is hidden.
-public final class Downloads implements BaseColumns {
- private Downloads() {}
-
- /**
- * The permission to access the download manager
- */
- public static final String PERMISSION_ACCESS = "android.permission.ACCESS_DOWNLOAD_MANAGER";
-
- /**
- * The permission to access the download manager's advanced functions
- */
- public static final String PERMISSION_ACCESS_ADVANCED =
- "android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED";
-
- /**
- * The permission to directly access the download manager's cache directory
- */
- public static final String PERMISSION_CACHE = "android.permission.ACCESS_CACHE_FILESYSTEM";
-
- /**
- * The permission to send broadcasts on download completion
- */
- public static final String PERMISSION_SEND_INTENTS =
- "android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS";
-
- /**
- * The content:// URI for the data table in the provider
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://downloads/download");
-
- /**
- * Broadcast Action: this is sent by the download manager to the app
- * that had initiated a download when that download completes. The
- * download's content: uri is specified in the intent's data.
- */
- public static final String DOWNLOAD_COMPLETED_ACTION =
- "android.intent.action.DOWNLOAD_COMPLETED";
-
- /**
- * Broadcast Action: this is sent by the download manager to the app
- * that had initiated a download when the user selects the notification
- * associated with that download. The download's content: uri is specified
- * in the intent's data if the click is associated with a single download,
- * or Downloads.CONTENT_URI if the notification is associated with
- * multiple downloads.
- * Note: this is not currently sent for downloads that have completed
- * successfully.
- */
- public static final String NOTIFICATION_CLICKED_ACTION =
- "android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED";
-
- /**
- * The name of the column containing the URI of the data being downloaded.
- * <P>Type: TEXT</P>
- * <P>Owner can Init/Read</P>
- */
- public static final String URI = "uri";
-
- /**
- * The name of the column containing application-specific data.
- * <P>Type: TEXT</P>
- * <P>Owner can Init/Read/Write</P>
- */
- public static final String APP_DATA = "entity";
-
- /**
- * The name of the column containing the flags that indicates whether
- * the initiating application is capable of verifying the integrity of
- * the downloaded file. When this flag is set, the download manager
- * performs downloads and reports success even in some situations where
- * it can't guarantee that the download has completed (e.g. when doing
- * a byte-range request without an ETag, or when it can't determine
- * whether a download fully completed).
- * <P>Type: BOOLEAN</P>
- * <P>Owner can Init</P>
- */
- public static final String NO_INTEGRITY = "no_integrity";
-
- /**
- * The name of the column containing the filename that the initiating
- * application recommends. When possible, the download manager will attempt
- * to use this filename, or a variation, as the actual name for the file.
- * <P>Type: TEXT</P>
- * <P>Owner can Init</P>
- */
- public static final String FILENAME_HINT = "hint";
-
- /**
- * The name of the column containing the filename where the downloaded data
- * was actually stored.
- * <P>Type: TEXT</P>
- * <P>Owner can Read</P>
- */
- public static final String _DATA = "_data";
-
- /**
- * The name of the column containing the MIME type of the downloaded data.
- * <P>Type: TEXT</P>
- * <P>Owner can Init/Read</P>
- */
- public static final String MIMETYPE = "mimetype";
-
- /**
- * The name of the column containing the flag that controls the destination
- * of the download. See the DESTINATION_* constants for a list of legal values.
- * <P>Type: INTEGER</P>
- * <P>Owner can Init</P>
- */
- public static final String DESTINATION = "destination";
-
- /**
- * The name of the column containing the flags that controls whether the
- * download is displayed by the UI. See the VISIBILITY_* constants for
- * a list of legal values.
- * <P>Type: INTEGER</P>
- * <P>Owner can Init/Read/Write</P>
- */
- public static final String VISIBILITY = "visibility";
-
- /**
- * The name of the column containing the current control state of the download.
- * Applications can write to this to control (pause/resume) the download.
- * the CONTROL_* constants for a list of legal values.
- * <P>Type: INTEGER</P>
- * <P>Owner can Read</P>
- */
- public static final String CONTROL = "control";
-
- /**
- * The name of the column containing the current status of the download.
- * Applications can read this to follow the progress of each download. See
- * the STATUS_* constants for a list of legal values.
- * <P>Type: INTEGER</P>
- * <P>Owner can Read</P>
- */
- public static final String STATUS = "status";
-
- /**
- * The name of the column containing the date at which some interesting
- * status changed in the download. Stored as a System.currentTimeMillis()
- * value.
- * <P>Type: BIGINT</P>
- * <P>Owner can Read</P>
- */
- public static final String LAST_MODIFICATION = "lastmod";
-
- /**
- * The name of the column containing the package name of the application
- * that initiating the download. The download manager will send
- * notifications to a component in this package when the download completes.
- * <P>Type: TEXT</P>
- * <P>Owner can Init/Read</P>
- */
- public static final String NOTIFICATION_PACKAGE = "notificationpackage";
-
- /**
- * The name of the column containing the component name of the class that
- * will receive notifications associated with the download. The
- * package/class combination is passed to
- * Intent.setClassName(String,String).
- * <P>Type: TEXT</P>
- * <P>Owner can Init/Read</P>
- */
- public static final String NOTIFICATION_CLASS = "notificationclass";
-
- /**
- * If extras are specified when requesting a download they will be provided in the intent that
- * is sent to the specified class and package when a download has finished.
- * <P>Type: TEXT</P>
- * <P>Owner can Init</P>
- */
- public static final String NOTIFICATION_EXTRAS = "notificationextras";
-
- /**
- * The name of the column contain the values of the cookie to be used for
- * the download. This is used directly as the value for the Cookie: HTTP
- * header that gets sent with the request.
- * <P>Type: TEXT</P>
- * <P>Owner can Init</P>
- */
- public static final String COOKIE_DATA = "cookiedata";
-
- /**
- * The name of the column containing the user agent that the initiating
- * application wants the download manager to use for this download.
- * <P>Type: TEXT</P>
- * <P>Owner can Init</P>
- */
- public static final String USER_AGENT = "useragent";
-
- /**
- * The name of the column containing the referer (sic) that the initiating
- * application wants the download manager to use for this download.
- * <P>Type: TEXT</P>
- * <P>Owner can Init</P>
- */
- public static final String REFERER = "referer";
-
- /**
- * The name of the column containing the total size of the file being
- * downloaded.
- * <P>Type: INTEGER</P>
- * <P>Owner can Read</P>
- */
- public static final String TOTAL_BYTES = "total_bytes";
-
- /**
- * The name of the column containing the size of the part of the file that
- * has been downloaded so far.
- * <P>Type: INTEGER</P>
- * <P>Owner can Read</P>
- */
- public static final String CURRENT_BYTES = "current_bytes";
-
- /**
- * The name of the column where the initiating application can provide the
- * UID of another application that is allowed to access this download. If
- * multiple applications share the same UID, all those applications will be
- * allowed to access this download. This column can be updated after the
- * download is initiated. This requires the permission
- * android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED.
- * <P>Type: INTEGER</P>
- * <P>Owner can Init</P>
- */
- public static final String OTHER_UID = "otheruid";
-
- /**
- * The name of the column where the initiating application can provided the
- * title of this download. The title will be displayed ito the user in the
- * list of downloads.
- * <P>Type: TEXT</P>
- * <P>Owner can Init/Read/Write</P>
- */
- public static final String TITLE = "title";
-
- /**
- * The name of the column where the initiating application can provide the
- * description of this download. The description will be displayed to the
- * user in the list of downloads.
- * <P>Type: TEXT</P>
- * <P>Owner can Init/Read/Write</P>
- */
- public static final String DESCRIPTION = "description";
-
- /*
- * Lists the destinations that an application can specify for a download.
- */
-
- /**
- * This download will be saved to the external storage. This is the
- * default behavior, and should be used for any file that the user
- * can freely access, copy, delete. Even with that destination,
- * unencrypted DRM files are saved in secure internal storage.
- * Downloads to the external destination only write files for which
- * there is a registered handler. The resulting files are accessible
- * by filename to all applications.
- */
- public static final int DESTINATION_EXTERNAL = 0;
-
- /**
- * This download will be saved to the download manager's private
- * partition. This is the behavior used by applications that want to
- * download private files that are used and deleted soon after they
- * get downloaded. All file types are allowed, and only the initiating
- * application can access the file (indirectly through a content
- * provider). This requires the
- * android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED permission.
- */
- public static final int DESTINATION_CACHE_PARTITION = 1;
-
- /**
- * This download will be saved to the download manager's private
- * partition and will be purged as necessary to make space. This is
- * for private files (similar to CACHE_PARTITION) that aren't deleted
- * immediately after they are used, and are kept around by the download
- * manager as long as space is available.
- */
- public static final int DESTINATION_CACHE_PARTITION_PURGEABLE = 2;
-
- /**
- * This download will be saved to the download manager's private
- * partition, as with DESTINATION_CACHE_PARTITION, but the download
- * will not proceed if the user is on a roaming data connection.
- */
- public static final int DESTINATION_CACHE_PARTITION_NOROAMING = 3;
-
- /**
- * This download is allowed to run.
- */
- public static final int CONTROL_RUN = 0;
-
- /**
- * This download must pause at the first opportunity.
- */
- public static final int CONTROL_PAUSED = 1;
-
- /*
- * Lists the states that the download manager can set on a download
- * to notify applications of the download progress.
- * The codes follow the HTTP families:<br>
- * 1xx: informational<br>
- * 2xx: success<br>
- * 3xx: redirects (not used by the download manager)<br>
- * 4xx: client errors<br>
- * 5xx: server errors
- */
-
- /**
- * Returns whether the status is informational (i.e. 1xx).
- */
- public static boolean isStatusInformational(int status) {
- return (status >= 100 && status < 200);
- }
-
- /**
- * Returns whether the download is suspended. (i.e. whether the download
- * won't complete without some action from outside the download
- * manager).
- */
- public static boolean isStatusSuspended(int status) {
- return (status == STATUS_PENDING_PAUSED || status == STATUS_RUNNING_PAUSED);
- }
-
- /**
- * Returns whether the status is a success (i.e. 2xx).
- */
- public static boolean isStatusSuccess(int status) {
- return (status >= 200 && status < 300);
- }
-
- /**
- * Returns whether the status is an error (i.e. 4xx or 5xx).
- */
- public static boolean isStatusError(int status) {
- return (status >= 400 && status < 600);
- }
-
- /**
- * Returns whether the status is a client error (i.e. 4xx).
- */
- public static boolean isStatusClientError(int status) {
- return (status >= 400 && status < 500);
- }
-
- /**
- * Returns whether the status is a server error (i.e. 5xx).
- */
- public static boolean isStatusServerError(int status) {
- return (status >= 500 && status < 600);
- }
-
- /**
- * Returns whether the download has completed (either with success or
- * error).
- */
- public static boolean isStatusCompleted(int status) {
- return (status >= 200 && status < 300) || (status >= 400 && status < 600);
- }
-
- /**
- * This download hasn't stated yet
- */
- public static final int STATUS_PENDING = 190;
-
- /**
- * This download hasn't stated yet and is paused
- */
- public static final int STATUS_PENDING_PAUSED = 191;
-
- /**
- * This download has started
- */
- public static final int STATUS_RUNNING = 192;
-
- /**
- * This download has started and is paused
- */
- public static final int STATUS_RUNNING_PAUSED = 193;
-
- /**
- * This download has successfully completed.
- * Warning: there might be other status values that indicate success
- * in the future.
- * Use isSucccess() to capture the entire category.
- */
- public static final int STATUS_SUCCESS = 200;
-
- /**
- * This request couldn't be parsed. This is also used when processing
- * requests with unknown/unsupported URI schemes.
- */
- public static final int STATUS_BAD_REQUEST = 400;
-
- /**
- * This download can't be performed because the content type cannot be
- * handled.
- */
- public static final int STATUS_NOT_ACCEPTABLE = 406;
-
- /**
- * This download cannot be performed because the length cannot be
- * determined accurately. This is the code for the HTTP error "Length
- * Required", which is typically used when making requests that require
- * a content length but don't have one, and it is also used in the
- * client when a response is received whose length cannot be determined
- * accurately (therefore making it impossible to know when a download
- * completes).
- */
- public static final int STATUS_LENGTH_REQUIRED = 411;
-
- /**
- * This download was interrupted and cannot be resumed.
- * This is the code for the HTTP error "Precondition Failed", and it is
- * also used in situations where the client doesn't have an ETag at all.
- */
- public static final int STATUS_PRECONDITION_FAILED = 412;
-
- /**
- * This download was canceled
- */
- public static final int STATUS_CANCELED = 490;
-
- /**
- * This download has completed with an error.
- * Warning: there will be other status values that indicate errors in
- * the future. Use isStatusError() to capture the entire category.
- */
- public static final int STATUS_UNKNOWN_ERROR = 491;
-
- /**
- * This download couldn't be completed because of a storage issue.
- * Typically, that's because the filesystem is missing or full.
- */
- public static final int STATUS_FILE_ERROR = 492;
-
- /**
- * This download couldn't be completed because of an HTTP
- * redirect response that the download manager couldn't
- * handle.
- */
- public static final int STATUS_UNHANDLED_REDIRECT = 493;
-
- /**
- * This download couldn't be completed because of an
- * unspecified unhandled HTTP code.
- */
- public static final int STATUS_UNHANDLED_HTTP_CODE = 494;
-
- /**
- * This download couldn't be completed because of an
- * error receiving or processing data at the HTTP level.
- */
- public static final int STATUS_HTTP_DATA_ERROR = 495;
-
- /**
- * This download couldn't be completed because of an
- * HttpException while setting up the request.
- */
- public static final int STATUS_HTTP_EXCEPTION = 496;
-
- /**
- * This download couldn't be completed because there were
- * too many redirects.
- */
- public static final int STATUS_TOO_MANY_REDIRECTS = 497;
-
- /**
- * This download is visible but only shows in the notifications
- * while it's in progress.
- */
- public static final int VISIBILITY_VISIBLE = 0;
-
- /**
- * This download is visible and shows in the notifications while
- * in progress and after completion.
- */
- public static final int VISIBILITY_VISIBLE_NOTIFY_COMPLETED = 1;
-
- /**
- * This download doesn't show in the UI or in the notifications.
- */
- public static final int VISIBILITY_HIDDEN = 2;
-}
diff --git a/core/java/android/provider/DrmStore.java b/core/java/android/provider/DrmStore.java
deleted file mode 100644
index db71854..0000000
--- a/core/java/android/provider/DrmStore.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.drm.mobile1.DrmRawContent;
-import android.drm.mobile1.DrmRights;
-import android.drm.mobile1.DrmRightsManager;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.net.Uri;
-import android.util.Log;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * The DRM provider contains forward locked DRM content.
- *
- * @hide
- */
-public final class DrmStore
-{
- private static final String TAG = "DrmStore";
-
- public static final String AUTHORITY = "drm";
-
- /**
- * This is in the Manifest class of the drm provider, but that isn't visible
- * in the framework.
- */
- private static final String ACCESS_DRM_PERMISSION = "android.permission.ACCESS_DRM";
-
- /**
- * Fields for DRM database
- */
-
- public interface Columns extends BaseColumns {
- /**
- * The data stream for the file
- * <P>Type: DATA STREAM</P>
- */
- public static final String DATA = "_data";
-
- /**
- * The size of the file in bytes
- * <P>Type: INTEGER (long)</P>
- */
- public static final String SIZE = "_size";
-
- /**
- * The title of the file content
- * <P>Type: TEXT</P>
- */
- public static final String TITLE = "title";
-
- /**
- * The MIME type of the file
- * <P>Type: TEXT</P>
- */
- public static final String MIME_TYPE = "mime_type";
-
- }
-
- public interface Images extends Columns {
-
- public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/images");
- }
-
- public interface Audio extends Columns {
-
- public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/audio");
- }
-
- /**
- * Utility function for inserting a file into the DRM content provider.
- *
- * @param cr The content resolver to use
- * @param file The file to insert
- * @param title The title for the content (or null)
- * @return uri to the DRM record or null
- */
- public static final Intent addDrmFile(ContentResolver cr, File file, String title) {
- FileInputStream fis = null;
- OutputStream os = null;
- Intent result = null;
-
- try {
- fis = new FileInputStream(file);
- DrmRawContent content = new DrmRawContent(fis, (int) file.length(),
- DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING);
- String mimeType = content.getContentType();
-
- DrmRightsManager manager = manager = DrmRightsManager.getInstance();
- DrmRights rights = manager.queryRights(content);
- InputStream stream = content.getContentInputStream(rights);
- long size = stream.available();
-
- Uri contentUri = null;
- if (mimeType.startsWith("audio/")) {
- contentUri = DrmStore.Audio.CONTENT_URI;
- } else if (mimeType.startsWith("image/")) {
- contentUri = DrmStore.Images.CONTENT_URI;
- } else {
- Log.w(TAG, "unsupported mime type " + mimeType);
- }
-
- if (contentUri != null) {
- ContentValues values = new ContentValues(3);
- // compute title from file name, if it is not specified
- if (title == null) {
- title = file.getName();
- int lastDot = title.lastIndexOf('.');
- if (lastDot > 0) {
- title = title.substring(0, lastDot);
- }
- }
- values.put(DrmStore.Columns.TITLE, title);
- values.put(DrmStore.Columns.SIZE, size);
- values.put(DrmStore.Columns.MIME_TYPE, mimeType);
-
- Uri uri = cr.insert(contentUri, values);
- if (uri != null) {
- os = cr.openOutputStream(uri);
-
- byte[] buffer = new byte[1000];
- int count;
-
- while ((count = stream.read(buffer)) != -1) {
- os.write(buffer, 0, count);
- }
- result = new Intent();
- result.setDataAndType(uri, mimeType);
-
- }
- }
- } catch (Exception e) {
- Log.e(TAG, "pushing file failed", e);
- } finally {
- try {
- if (fis != null)
- fis.close();
- if (os != null)
- os.close();
- } catch (IOException e) {
- Log.e(TAG, "IOException in DrmTest.onCreate()", e);
- }
- }
-
- return result;
- }
-
- /**
- * Utility function to enforce any permissions required to access DRM
- * content.
- *
- * @param context A context used for checking calling permission.
- */
- public static void enforceAccessDrmPermission(Context context) {
- if (context.checkCallingOrSelfPermission(ACCESS_DRM_PERMISSION) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires DRM permission");
- }
- }
-
-}
diff --git a/core/java/android/provider/Gmail.java b/core/java/android/provider/Gmail.java
deleted file mode 100644
index 5b3c223..0000000
--- a/core/java/android/provider/Gmail.java
+++ /dev/null
@@ -1,2453 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-import com.google.android.collect.Sets;
-
-import android.content.AsyncQueryHandler;
-import android.content.ContentQueryMap;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.database.DataSetObserver;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.text.Html;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-import android.text.TextUtils;
-import android.text.TextUtils.SimpleStringSplitter;
-import android.text.style.CharacterStyle;
-import android.text.util.Regex;
-import android.util.Config;
-import android.util.Log;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Observable;
-import java.util.Observer;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * A thin wrapper over the content resolver for accessing the gmail provider.
- *
- * @hide
- */
-public final class Gmail {
- public static final String GMAIL_AUTH_SERVICE = "mail";
- // These constants come from google3/java/com/google/caribou/backend/MailLabel.java.
- public static final String LABEL_SENT = "^f";
- public static final String LABEL_INBOX = "^i";
- public static final String LABEL_DRAFT = "^r";
- public static final String LABEL_UNREAD = "^u";
- public static final String LABEL_TRASH = "^k";
- public static final String LABEL_SPAM = "^s";
- public static final String LABEL_STARRED = "^t";
- public static final String LABEL_CHAT = "^b"; // 'b' for 'buzz'
- public static final String LABEL_VOICEMAIL = "^vm";
- public static final String LABEL_IGNORED = "^g";
- public static final String LABEL_ALL = "^all";
- // These constants (starting with "^^") are only used locally and are not understood by the
- // server.
- public static final String LABEL_VOICEMAIL_INBOX = "^^vmi";
- public static final String LABEL_CACHED = "^^cached";
- public static final String LABEL_OUTBOX = "^^out";
-
- public static final String AUTHORITY = "gmail-ls";
- private static final String TAG = "gmail-ls";
- private static final String AUTHORITY_PLUS_CONVERSATIONS =
- "content://" + AUTHORITY + "/conversations/";
- private static final String AUTHORITY_PLUS_LABELS =
- "content://" + AUTHORITY + "/labels/";
- private static final String AUTHORITY_PLUS_MESSAGES =
- "content://" + AUTHORITY + "/messages/";
- private static final String AUTHORITY_PLUS_SETTINGS =
- "content://" + AUTHORITY + "/settings/";
-
- public static final Uri BASE_URI = Uri.parse(
- "content://" + AUTHORITY);
- private static final Uri LABELS_URI =
- Uri.parse(AUTHORITY_PLUS_LABELS);
- private static final Uri CONVERSATIONS_URI =
- Uri.parse(AUTHORITY_PLUS_CONVERSATIONS);
- private static final Uri SETTINGS_URI =
- Uri.parse(AUTHORITY_PLUS_SETTINGS);
-
- /** Separates email addresses in strings in the database. */
- public static final String EMAIL_SEPARATOR = "\n";
- public static final Pattern EMAIL_SEPARATOR_PATTERN = Pattern.compile(EMAIL_SEPARATOR);
-
- /**
- * Space-separated lists have separators only between items.
- */
- private static final char SPACE_SEPARATOR = ' ';
- public static final Pattern SPACE_SEPARATOR_PATTERN = Pattern.compile(" ");
-
- /**
- * Comma-separated lists have separators between each item, before the first and after the last
- * item. The empty list is <tt>,</tt>.
- *
- * <p>This makes them easier to modify with SQL since it is not a special case to add or
- * remove the last item. Having a separator on each side of each value also makes it safe to use
- * SQL's REPLACE to remove an item from a string by using REPLACE(',value,', ',').
- *
- * <p>We could use the same separator for both lists but this makes it easier to remember which
- * kind of list one is dealing with.
- */
- private static final char COMMA_SEPARATOR = ',';
- public static final Pattern COMMA_SEPARATOR_PATTERN = Pattern.compile(",");
-
- /** Separates attachment info parts in strings in the database. */
- public static final String ATTACHMENT_INFO_SEPARATOR = "\n";
- public static final Pattern ATTACHMENT_INFO_SEPARATOR_PATTERN =
- Pattern.compile(ATTACHMENT_INFO_SEPARATOR);
-
- public static final Character SENDER_LIST_SEPARATOR = '\n';
- public static final String SENDER_LIST_TOKEN_ELIDED = "e";
- public static final String SENDER_LIST_TOKEN_NUM_MESSAGES = "n";
- public static final String SENDER_LIST_TOKEN_NUM_DRAFTS = "d";
- public static final String SENDER_LIST_TOKEN_LITERAL = "l";
- public static final String SENDER_LIST_TOKEN_SENDING = "s";
- public static final String SENDER_LIST_TOKEN_SEND_FAILED = "f";
-
- /** Used for finding status in a cursor's extras. */
- public static final String EXTRA_STATUS = "status";
-
- public static final String RESPOND_INPUT_COMMAND = "command";
- public static final String COMMAND_RETRY = "retry";
- public static final String COMMAND_ACTIVATE = "activate";
- public static final String COMMAND_SET_VISIBLE = "setVisible";
- public static final String SET_VISIBLE_PARAM_VISIBLE = "visible";
- public static final String RESPOND_OUTPUT_COMMAND_RESPONSE = "commandResponse";
- public static final String COMMAND_RESPONSE_OK = "ok";
- public static final String COMMAND_RESPONSE_UNKNOWN = "unknownCommand";
-
- public static final String INSERT_PARAM_ATTACHMENT_ORIGIN = "origin";
- public static final String INSERT_PARAM_ATTACHMENT_ORIGIN_EXTRAS = "originExtras";
-
- private static final Pattern NAME_ADDRESS_PATTERN = Pattern.compile("\"(.*)\"");
- private static final Pattern UNNAMED_ADDRESS_PATTERN = Pattern.compile("([^<]+)@");
-
- private static final Map<Integer, Integer> sPriorityToLength = Maps.newHashMap();
- public static final SimpleStringSplitter sSenderListSplitter =
- new SimpleStringSplitter(SENDER_LIST_SEPARATOR);
- public static String[] sSenderFragments = new String[8];
-
- /**
- * Returns the name in an address string
- * @param addressString such as &quot;bobby&quot; &lt;bob@example.com&gt;
- * @return returns the quoted name in the addressString, otherwise the username from the email
- * address
- */
- public static String getNameFromAddressString(String addressString) {
- Matcher namedAddressMatch = NAME_ADDRESS_PATTERN.matcher(addressString);
- if (namedAddressMatch.find()) {
- String name = namedAddressMatch.group(1);
- if (name.length() > 0) return name;
- addressString =
- addressString.substring(namedAddressMatch.end(), addressString.length());
- }
-
- Matcher unnamedAddressMatch = UNNAMED_ADDRESS_PATTERN.matcher(addressString);
- if (unnamedAddressMatch.find()) {
- return unnamedAddressMatch.group(1);
- }
-
- return addressString;
- }
-
- /**
- * Returns the email address in an address string
- * @param addressString such as &quot;bobby&quot; &lt;bob@example.com&gt;
- * @return returns the email address, such as bob@example.com from the example above
- */
- public static String getEmailFromAddressString(String addressString) {
- String result = addressString;
- Matcher match = Regex.EMAIL_ADDRESS_PATTERN.matcher(addressString);
- if (match.find()) {
- result = addressString.substring(match.start(), match.end());
- }
-
- return result;
- }
-
- /**
- * Returns whether the label is user-defined (versus system-defined labels such as inbox, whose
- * names start with "^").
- */
- public static boolean isLabelUserDefined(String label) {
- // TODO: label should never be empty so we should be able to say [label.charAt(0) != '^'].
- // However, it's a release week and I'm too scared to make that change.
- return !label.startsWith("^");
- }
-
- private static final Set<String> USER_SETTABLE_BUILTIN_LABELS = Sets.newHashSet(
- Gmail.LABEL_INBOX,
- Gmail.LABEL_UNREAD,
- Gmail.LABEL_TRASH,
- Gmail.LABEL_SPAM,
- Gmail.LABEL_STARRED,
- Gmail.LABEL_IGNORED);
-
- /**
- * Returns whether the label is user-settable. For example, labels such as LABEL_DRAFT should
- * only be set internally.
- */
- public static boolean isLabelUserSettable(String label) {
- return USER_SETTABLE_BUILTIN_LABELS.contains(label) || isLabelUserDefined(label);
- }
-
- /**
- * Returns the set of labels using the raw labels from a previous getRawLabels()
- * as input.
- * @return a copy of the set of labels. To add or remove labels call
- * MessageCursor.addOrRemoveLabel on each message in the conversation.
- */
- public static Set<Long> getLabelIdsFromLabelIdsString(
- TextUtils.StringSplitter splitter) {
- Set<Long> labelIds = Sets.newHashSet();
- for (String labelIdString : splitter) {
- labelIds.add(Long.valueOf(labelIdString));
- }
- return labelIds;
- }
-
- /**
- * @deprecated remove when the activities stop using canonical names to identify labels
- */
- public static Set<String> getCanonicalNamesFromLabelIdsString(
- LabelMap labelMap, TextUtils.StringSplitter splitter) {
- Set<String> canonicalNames = Sets.newHashSet();
- for (long labelId : getLabelIdsFromLabelIdsString(splitter)) {
- final String canonicalName = labelMap.getCanonicalName(labelId);
- // We will sometimes see labels that the label map does not yet know about or that
- // do not have names yet.
- if (!TextUtils.isEmpty(canonicalName)) {
- canonicalNames.add(canonicalName);
- } else {
- Log.w(TAG, "getCanonicalNamesFromLabelIdsString skipping label id: " + labelId);
- }
- }
- return canonicalNames;
- }
-
- /**
- * @return a StringSplitter that is configured to split message label id strings
- */
- public static TextUtils.StringSplitter newMessageLabelIdsSplitter() {
- return new TextUtils.SimpleStringSplitter(SPACE_SEPARATOR);
- }
-
- /**
- * @return a StringSplitter that is configured to split conversation label id strings
- */
- public static TextUtils.StringSplitter newConversationLabelIdsSplitter() {
- return new CommaStringSplitter();
- }
-
- /**
- * A splitter for strings of the form described in the docs for COMMA_SEPARATOR.
- */
- private static class CommaStringSplitter extends TextUtils.SimpleStringSplitter {
-
- public CommaStringSplitter() {
- super(COMMA_SEPARATOR);
- }
-
- @Override
- public void setString(String string) {
- // The string should always be at least a single comma.
- super.setString(string.substring(1));
- }
- }
-
- /**
- * Creates a single string of the form that getLabelIdsFromLabelIdsString can split.
- */
- public static String getLabelIdsStringFromLabelIds(Set<Long> labelIds) {
- StringBuilder sb = new StringBuilder();
- sb.append(COMMA_SEPARATOR);
- for (Long labelId : labelIds) {
- sb.append(labelId);
- sb.append(COMMA_SEPARATOR);
- }
- return sb.toString();
- }
-
- public static final class ConversationColumns {
- public static final String ID = "_id";
- public static final String SUBJECT = "subject";
- public static final String SNIPPET = "snippet";
- public static final String FROM = "fromAddress";
- public static final String DATE = "date";
- public static final String PERSONAL_LEVEL = "personalLevel";
- /** A list of label names with a space after each one (including the last one). This makes
- * it easier remove individual labels from this list using SQL. */
- public static final String LABEL_IDS = "labelIds";
- public static final String NUM_MESSAGES = "numMessages";
- public static final String MAX_MESSAGE_ID = "maxMessageId";
- public static final String HAS_ATTACHMENTS = "hasAttachments";
- public static final String HAS_MESSAGES_WITH_ERRORS = "hasMessagesWithErrors";
- public static final String FORCE_ALL_UNREAD = "forceAllUnread";
-
- private ConversationColumns() {}
- }
-
- public static final class MessageColumns {
-
- public static final String ID = "_id";
- public static final String MESSAGE_ID = "messageId";
- public static final String CONVERSATION_ID = "conversation";
- public static final String SUBJECT = "subject";
- public static final String SNIPPET = "snippet";
- public static final String FROM = "fromAddress";
- public static final String TO = "toAddresses";
- public static final String CC = "ccAddresses";
- public static final String BCC = "bccAddresses";
- public static final String REPLY_TO = "replyToAddresses";
- public static final String DATE_SENT_MS = "dateSentMs";
- public static final String DATE_RECEIVED_MS = "dateReceivedMs";
- public static final String LIST_INFO = "listInfo";
- public static final String PERSONAL_LEVEL = "personalLevel";
- public static final String BODY = "body";
- public static final String EMBEDS_EXTERNAL_RESOURCES = "bodyEmbedsExternalResources";
- public static final String LABEL_IDS = "labelIds";
- public static final String JOINED_ATTACHMENT_INFOS = "joinedAttachmentInfos";
- public static final String ERROR = "error";
- // TODO: add a method for accessing this
- public static final String REF_MESSAGE_ID = "refMessageId";
-
- // Fake columns used only for saving or sending messages.
- public static final String FAKE_SAVE = "save";
- public static final String FAKE_REF_MESSAGE_ID = "refMessageId";
-
- private MessageColumns() {}
- }
-
- public static final class LabelColumns {
- public static final String CANONICAL_NAME = "canonicalName";
- public static final String NAME = "name";
- public static final String NUM_CONVERSATIONS = "numConversations";
- public static final String NUM_UNREAD_CONVERSATIONS =
- "numUnreadConversations";
-
- private LabelColumns() {}
- }
-
- public static final class SettingsColumns {
- public static final String LABELS_INCLUDED = "labelsIncluded";
- public static final String LABELS_PARTIAL = "labelsPartial";
- public static final String CONVERSATION_AGE_DAYS =
- "conversationAgeDays";
- public static final String MAX_ATTACHMENET_SIZE_MB =
- "maxAttachmentSize";
- }
-
- /**
- * These flags can be included as Selection Arguments when
- * querying the provider.
- */
- public static class SelectionArguments {
- private SelectionArguments() {
- // forbid instantiation
- }
-
- /**
- * Specifies that you do NOT wish the returned cursor to
- * become the Active Network Cursor. If you do not include
- * this flag as a selectionArg, the new cursor will become the
- * Active Network Cursor by default.
- */
- public static final String DO_NOT_BECOME_ACTIVE_NETWORK_CURSOR =
- "SELECTION_ARGUMENT_DO_NOT_BECOME_ACTIVE_NETWORK_CURSOR";
- }
-
- // These are the projections that we need when getting cursors from the
- // content provider.
- private static String[] CONVERSATION_PROJECTION = {
- ConversationColumns.ID,
- ConversationColumns.SUBJECT,
- ConversationColumns.SNIPPET,
- ConversationColumns.FROM,
- ConversationColumns.DATE,
- ConversationColumns.PERSONAL_LEVEL,
- ConversationColumns.LABEL_IDS,
- ConversationColumns.NUM_MESSAGES,
- ConversationColumns.MAX_MESSAGE_ID,
- ConversationColumns.HAS_ATTACHMENTS,
- ConversationColumns.HAS_MESSAGES_WITH_ERRORS,
- ConversationColumns.FORCE_ALL_UNREAD};
- private static String[] MESSAGE_PROJECTION = {
- MessageColumns.ID,
- MessageColumns.MESSAGE_ID,
- MessageColumns.CONVERSATION_ID,
- MessageColumns.SUBJECT,
- MessageColumns.SNIPPET,
- MessageColumns.FROM,
- MessageColumns.TO,
- MessageColumns.CC,
- MessageColumns.BCC,
- MessageColumns.REPLY_TO,
- MessageColumns.DATE_SENT_MS,
- MessageColumns.DATE_RECEIVED_MS,
- MessageColumns.LIST_INFO,
- MessageColumns.PERSONAL_LEVEL,
- MessageColumns.BODY,
- MessageColumns.EMBEDS_EXTERNAL_RESOURCES,
- MessageColumns.LABEL_IDS,
- MessageColumns.JOINED_ATTACHMENT_INFOS,
- MessageColumns.ERROR};
- private static String[] LABEL_PROJECTION = {
- BaseColumns._ID,
- LabelColumns.CANONICAL_NAME,
- LabelColumns.NAME,
- LabelColumns.NUM_CONVERSATIONS,
- LabelColumns.NUM_UNREAD_CONVERSATIONS};
- private static String[] SETTINGS_PROJECTION = {
- SettingsColumns.LABELS_INCLUDED,
- SettingsColumns.LABELS_PARTIAL,
- SettingsColumns.CONVERSATION_AGE_DAYS,
- SettingsColumns.MAX_ATTACHMENET_SIZE_MB,
- };
-
- private ContentResolver mContentResolver;
-
- public Gmail(ContentResolver contentResolver) {
- mContentResolver = contentResolver;
- }
-
- /**
- * Returns source if source is non-null. Returns the empty string otherwise.
- */
- private static String toNonnullString(String source) {
- if (source == null) {
- return "";
- } else {
- return source;
- }
- }
-
- /**
- * Behavior for a new cursor: should it become the Active Network
- * Cursor? This could potentially lead to bad behavior if someone
- * else is using the Active Network Cursor, since theirs will stop
- * being the Active Network Cursor.
- */
- public static enum BecomeActiveNetworkCursor {
- /**
- * The new cursor should become the one and only Active
- * Network Cursor. Any other cursor that might already be the
- * Active Network Cursor will cease to be so.
- */
- YES,
-
- /**
- * The new cursor should not become the Active Network
- * Cursor. Any other cursor that might already be the Active
- * Network Cursor will continue to be so.
- */
- NO
- }
-
- /**
- * Wraps a Cursor in a ConversationCursor
- *
- * @param account the account the cursor is associated with
- * @param cursor The Cursor to wrap
- * @return a new ConversationCursor
- */
- public ConversationCursor getConversationCursorForCursor(String account, Cursor cursor) {
- if (TextUtils.isEmpty(account)) {
- throw new IllegalArgumentException("account is empty");
- }
- return new ConversationCursor(this, account, cursor);
- }
-
- /**
- * Creates an array of SelectionArguments suitable for passing to the provider's query.
- * Currently this only handles one flag, but it could be expanded in the future.
- */
- private static String[] getSelectionArguments(
- BecomeActiveNetworkCursor becomeActiveNetworkCursor) {
- if (BecomeActiveNetworkCursor.NO == becomeActiveNetworkCursor) {
- return new String[] {SelectionArguments.DO_NOT_BECOME_ACTIVE_NETWORK_CURSOR};
- } else {
- // Default behavior; no args required.
- return null;
- }
- }
-
- /**
- * Asynchronously gets a cursor over all conversations matching a query. The
- * query is in Gmail's query syntax. When the operation is complete the handler's
- * onQueryComplete() method is called with the resulting Cursor.
- *
- * @param account run the query on this account
- * @param handler An AsyncQueryHanlder that will be used to run the query
- * @param token The token to pass to startQuery, which will be passed back to onQueryComplete
- * @param query a query in Gmail's query syntax
- * @param becomeActiveNetworkCursor whether or not the returned
- * cursor should become the Active Network Cursor
- */
- public void runQueryForConversations(String account, AsyncQueryHandler handler, int token,
- String query, BecomeActiveNetworkCursor becomeActiveNetworkCursor) {
- if (TextUtils.isEmpty(account)) {
- throw new IllegalArgumentException("account is empty");
- }
- String[] selectionArgs = getSelectionArguments(becomeActiveNetworkCursor);
- handler.startQuery(token, null, Uri.withAppendedPath(CONVERSATIONS_URI, account),
- CONVERSATION_PROJECTION, query, selectionArgs, null);
- }
-
- /**
- * Synchronously gets a cursor over all conversations matching a query. The
- * query is in Gmail's query syntax.
- *
- * @param account run the query on this account
- * @param query a query in Gmail's query syntax
- * @param becomeActiveNetworkCursor whether or not the returned
- * cursor should become the Active Network Cursor
- */
- public ConversationCursor getConversationCursorForQuery(
- String account, String query, BecomeActiveNetworkCursor becomeActiveNetworkCursor) {
- String[] selectionArgs = getSelectionArguments(becomeActiveNetworkCursor);
- Cursor cursor = mContentResolver.query(
- Uri.withAppendedPath(CONVERSATIONS_URI, account), CONVERSATION_PROJECTION,
- query, selectionArgs, null);
- return new ConversationCursor(this, account, cursor);
- }
-
- /**
- * Gets a message cursor over the single message with the given id.
- *
- * @param account get the cursor for messages in this account
- * @param messageId the id of the message
- * @return a cursor over the message
- */
- public MessageCursor getMessageCursorForMessageId(String account, long messageId) {
- if (TextUtils.isEmpty(account)) {
- throw new IllegalArgumentException("account is empty");
- }
- Uri uri = Uri.parse(AUTHORITY_PLUS_MESSAGES + account + "/" + messageId);
- Cursor cursor = mContentResolver.query(uri, MESSAGE_PROJECTION, null, null, null);
- return new MessageCursor(this, mContentResolver, account, cursor);
- }
-
- /**
- * Gets a message cursor over the messages that match the query. Note that
- * this simply finds all of the messages that match and returns them. It
- * does not return all messages in conversations where any message matches.
- *
- * @param account get the cursor for messages in this account
- * @param query a query in GMail's query syntax. Currently only queries of
- * the form [label:<label>] are supported
- * @return a cursor over the messages
- */
- public MessageCursor getLocalMessageCursorForQuery(String account, String query) {
- if (TextUtils.isEmpty(account)) {
- throw new IllegalArgumentException("account is empty");
- }
- Uri uri = Uri.parse(AUTHORITY_PLUS_MESSAGES + account + "/");
- Cursor cursor = mContentResolver.query(uri, MESSAGE_PROJECTION, query, null, null);
- return new MessageCursor(this, mContentResolver, account, cursor);
- }
-
- /**
- * Gets a cursor over all of the messages in a conversation.
- *
- * @param account get the cursor for messages in this account
- * @param conversationId the id of the converstion to fetch messages for
- * @return a cursor over messages in the conversation
- */
- public MessageCursor getMessageCursorForConversationId(String account, long conversationId) {
- if (TextUtils.isEmpty(account)) {
- throw new IllegalArgumentException("account is empty");
- }
- Uri uri = Uri.parse(
- AUTHORITY_PLUS_CONVERSATIONS + account + "/" + conversationId + "/messages");
- Cursor cursor = mContentResolver.query(
- uri, MESSAGE_PROJECTION, null, null, null);
- return new MessageCursor(this, mContentResolver, account, cursor);
- }
-
- /**
- * Expunge the indicated message. One use of this is to discard drafts.
- *
- * @param account the account of the message id
- * @param messageId the id of the message to expunge
- */
- public void expungeMessage(String account, long messageId) {
- if (TextUtils.isEmpty(account)) {
- throw new IllegalArgumentException("account is empty");
- }
- Uri uri = Uri.parse(AUTHORITY_PLUS_MESSAGES + account + "/" + messageId);
- mContentResolver.delete(uri, null, null);
- }
-
- /**
- * Adds or removes the label on the conversation.
- *
- * @param account the account of the conversation
- * @param conversationId the conversation
- * @param maxServerMessageId the highest message id to whose labels should be changed. Note that
- * everywhere else in this file messageId means local message id but here you need to use a
- * server message id.
- * @param label the label to add or remove
- * @param add true to add the label, false to remove it
- */
- public void addOrRemoveLabelOnConversation(
- String account, long conversationId, long maxServerMessageId, String label,
- boolean add) {
- if (TextUtils.isEmpty(account)) {
- throw new IllegalArgumentException("account is empty");
- }
- if (add) {
- Uri uri = Uri.parse(
- AUTHORITY_PLUS_CONVERSATIONS + account + "/" + conversationId + "/labels");
- ContentValues values = new ContentValues();
- values.put(LabelColumns.CANONICAL_NAME, label);
- values.put(ConversationColumns.MAX_MESSAGE_ID, maxServerMessageId);
- mContentResolver.insert(uri, values);
- } else {
- String encodedLabel;
- try {
- encodedLabel = URLEncoder.encode(label, "utf-8");
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e);
- }
- Uri uri = Uri.parse(
- AUTHORITY_PLUS_CONVERSATIONS + account + "/"
- + conversationId + "/labels/" + encodedLabel);
- mContentResolver.delete(
- uri, ConversationColumns.MAX_MESSAGE_ID, new String[]{"" + maxServerMessageId});
- }
- }
-
- /**
- * Adds or removes the label on the message.
- *
- * @param contentResolver the content resolver.
- * @param account the account of the message
- * @param conversationId the conversation containing the message
- * @param messageId the id of the message to whose labels should be changed
- * @param label the label to add or remove
- * @param add true to add the label, false to remove it
- */
- public static void addOrRemoveLabelOnMessage(ContentResolver contentResolver, String account,
- long conversationId, long messageId, String label, boolean add) {
-
- // conversationId is unused but we want to start passing it whereever we pass a message id.
- if (add) {
- Uri uri = Uri.parse(
- AUTHORITY_PLUS_MESSAGES + account + "/" + messageId + "/labels");
- ContentValues values = new ContentValues();
- values.put(LabelColumns.CANONICAL_NAME, label);
- contentResolver.insert(uri, values);
- } else {
- String encodedLabel;
- try {
- encodedLabel = URLEncoder.encode(label, "utf-8");
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e);
- }
- Uri uri = Uri.parse(
- AUTHORITY_PLUS_MESSAGES + account + "/" + messageId
- + "/labels/" + encodedLabel);
- contentResolver.delete(uri, null, null);
- }
- }
-
- /**
- * The mail provider will send an intent when certain changes happen in certain labels.
- * Currently those labels are inbox and voicemail.
- *
- * <p>The intent will have the action ACTION_PROVIDER_CHANGED and the extras mentioned below.
- * The data for the intent will be content://gmail-ls/unread/<name of label>.
- *
- * <p>The goal is to support the following user experience:<ul>
- * <li>When present the new mail indicator reports the number of unread conversations in the
- * inbox (or some other label).</li>
- * <li>When the user views the inbox the indicator is removed immediately. They do not have to
- * read all of the conversations.</li>
- * <li>If more mail arrives the indicator reappears and shows the total number of unread
- * conversations in the inbox.</li>
- * <li>If the user reads the new conversations on the web the indicator disappears on the
- * phone since there is no unread mail in the inbox that the user hasn't seen.</li>
- * <li>The phone should vibrate/etc when it transitions from having no unseen unread inbox
- * mail to having some.</li>
- */
-
- /** The account in which the change occurred. */
- static public final String PROVIDER_CHANGED_EXTRA_ACCOUNT = "account";
-
- /** The number of unread conversations matching the label. */
- static public final String PROVIDER_CHANGED_EXTRA_COUNT = "count";
-
- /** Whether to get the user's attention, perhaps by vibrating. */
- static public final String PROVIDER_CHANGED_EXTRA_GET_ATTENTION = "getAttention";
-
- /**
- * A label that is attached to all of the conversations being notified about. This enables the
- * receiver of a notification to get a list of matching conversations.
- */
- static public final String PROVIDER_CHANGED_EXTRA_TAG_LABEL = "tagLabel";
-
- /**
- * Settings for which conversations should be synced to the phone.
- * Conversations are synced if any message matches any of the following
- * criteria:
- *
- * <ul>
- * <li>the message has a label in the include set</li>
- * <li>the message is no older than conversationAgeDays and has a label in the partial set.
- * </li>
- * <li>also, pending changes on the server: the message has no user-controllable labels.</li>
- * </ul>
- *
- * <p>A user-controllable label is a user-defined label or star, inbox,
- * trash, spam, etc. LABEL_UNREAD is not considered user-controllable.
- */
- public static class Settings {
- public long conversationAgeDays;
- public long maxAttachmentSizeMb;
- public String[] labelsIncluded;
- public String[] labelsPartial;
- }
-
- /**
- * Returns the settings.
- * @param account the account whose setting should be retrieved
- */
- public Settings getSettings(String account) {
- if (TextUtils.isEmpty(account)) {
- throw new IllegalArgumentException("account is empty");
- }
- Settings settings = new Settings();
- Cursor cursor = mContentResolver.query(
- Uri.withAppendedPath(SETTINGS_URI, account), SETTINGS_PROJECTION, null, null, null);
- cursor.moveToNext();
- settings.labelsIncluded = TextUtils.split(cursor.getString(0), SPACE_SEPARATOR_PATTERN);
- settings.labelsPartial = TextUtils.split(cursor.getString(1), SPACE_SEPARATOR_PATTERN);
- settings.conversationAgeDays = Long.parseLong(cursor.getString(2));
- settings.maxAttachmentSizeMb = Long.parseLong(cursor.getString(3));
- cursor.close();
- return settings;
- }
-
- /**
- * Sets the settings. A sync will be scheduled automatically.
- */
- public void setSettings(String account, Settings settings) {
- if (TextUtils.isEmpty(account)) {
- throw new IllegalArgumentException("account is empty");
- }
- ContentValues values = new ContentValues();
- values.put(
- SettingsColumns.LABELS_INCLUDED,
- TextUtils.join(" ", settings.labelsIncluded));
- values.put(
- SettingsColumns.LABELS_PARTIAL,
- TextUtils.join(" ", settings.labelsPartial));
- values.put(
- SettingsColumns.CONVERSATION_AGE_DAYS,
- settings.conversationAgeDays);
- values.put(
- SettingsColumns.MAX_ATTACHMENET_SIZE_MB,
- settings.maxAttachmentSizeMb);
- mContentResolver.update(Uri.withAppendedPath(SETTINGS_URI, account), values, null, null);
- }
-
- /**
- * Uses sender instructions to build a formatted string.
- *
- * <p>Sender list instructions contain compact information about the sender list. Most work that
- * can be done without knowing how much room will be availble for the sender list is done when
- * creating the instructions.
- *
- * <p>The instructions string consists of tokens separated by SENDER_LIST_SEPARATOR. Here are
- * the tokens, one per line:<ul>
- * <li><tt>n</tt></li>
- * <li><em>int</em>, the number of non-draft messages in the conversation</li>
- * <li><tt>d</tt</li>
- * <li><em>int</em>, the number of drafts in the conversation</li>
- * <li><tt>l</tt></li>
- * <li><em>literal html to be included in the output</em></li>
- * <li><tt>s</tt> indicates that the message is sending (in the outbox without errors)</li>
- * <li><tt>f</tt> indicates that the message failed to send (in the outbox with errors)</li>
- * <li><em>for each message</em><ul>
- * <li><em>int</em>, 0 for read, 1 for unread</li>
- * <li><em>int</em>, the priority of the message. Zero is the most important</li>
- * <li><em>text</em>, the sender text or blank for messages from 'me'</li>
- * </ul></li>
- * <li><tt>e</tt> to indicate that one or more messages have been elided</li>
- *
- * <p>The instructions indicate how many messages and drafts are in the conversation and then
- * describe the most important messages in order, indicating the priority of each message and
- * whether the message is unread.
- *
- * @param instructions instructions as described above
- * @param sb the SpannableStringBuilder to append to
- * @param maxChars the number of characters available to display the text
- * @param unreadStyle the CharacterStyle for unread messages, or null
- * @param draftsStyle the CharacterStyle for draft messages, or null
- * @param sendingString the string to use when there are messages scheduled to be sent
- * @param sendFailedString the string to use when there are messages that mailed to send
- * @param meString the string to use for messages sent by this user
- * @param draftString the string to use for "Draft"
- * @param draftPluralString the string to use for "Drafts"
- */
- public static void getSenderSnippet(
- String instructions, SpannableStringBuilder sb, int maxChars,
- CharacterStyle unreadStyle,
- CharacterStyle draftsStyle,
- CharSequence meString, CharSequence draftString, CharSequence draftPluralString,
- CharSequence sendingString, CharSequence sendFailedString,
- boolean forceAllUnread, boolean forceAllRead) {
- assert !(forceAllUnread && forceAllRead);
- boolean unreadStatusIsForced = forceAllUnread || forceAllRead;
- boolean forcedUnreadStatus = forceAllUnread;
-
- // Measure each fragment. It's ok to iterate over the entire set of fragments because it is
- // never a long list, even if there are many senders.
- final Map<Integer, Integer> priorityToLength = sPriorityToLength;
- priorityToLength.clear();
-
- int maxFoundPriority = Integer.MIN_VALUE;
- int numMessages = 0;
- int numDrafts = 0;
- CharSequence draftsFragment = "";
- CharSequence sendingFragment = "";
- CharSequence sendFailedFragment = "";
-
- sSenderListSplitter.setString(instructions);
- int numFragments = 0;
- String[] fragments = sSenderFragments;
- int currentSize = fragments.length;
- while (sSenderListSplitter.hasNext()) {
- fragments[numFragments++] = sSenderListSplitter.next();
- if (numFragments == currentSize) {
- sSenderFragments = new String[2 * currentSize];
- System.arraycopy(fragments, 0, sSenderFragments, 0, currentSize);
- currentSize *= 2;
- fragments = sSenderFragments;
- }
- }
-
- for (int i = 0; i < numFragments;) {
- String fragment0 = fragments[i++];
- if ("".equals(fragment0)) {
- // This should be the final fragment.
- } else if (Gmail.SENDER_LIST_TOKEN_ELIDED.equals(fragment0)) {
- // ignore
- } else if (Gmail.SENDER_LIST_TOKEN_NUM_MESSAGES.equals(fragment0)) {
- numMessages = Integer.valueOf(fragments[i++]);
- } else if (Gmail.SENDER_LIST_TOKEN_NUM_DRAFTS.equals(fragment0)) {
- String numDraftsString = fragments[i++];
- numDrafts = Integer.parseInt(numDraftsString);
- draftsFragment = numDrafts == 1 ? draftString :
- draftPluralString + " (" + numDraftsString + ")";
- } else if (Gmail.SENDER_LIST_TOKEN_LITERAL.equals(fragment0)) {
- sb.append(Html.fromHtml(fragments[i++]));
- return;
- } else if (Gmail.SENDER_LIST_TOKEN_SENDING.equals(fragment0)) {
- sendingFragment = sendingString;
- } else if (Gmail.SENDER_LIST_TOKEN_SEND_FAILED.equals(fragment0)) {
- sendFailedFragment = sendFailedString;
- } else {
- String priorityString = fragments[i++];
- CharSequence nameString = fragments[i++];
- if (nameString.length() == 0) nameString = meString;
- int priority = Integer.parseInt(priorityString);
- priorityToLength.put(priority, nameString.length());
- maxFoundPriority = Math.max(maxFoundPriority, priority);
- }
- }
- String numMessagesFragment =
- (numMessages != 0) ? " (" + Integer.toString(numMessages + numDrafts) + ")" : "";
-
- // Don't allocate fixedFragment unless we need it
- SpannableStringBuilder fixedFragment = null;
- int fixedFragmentLength = 0;
- if (draftsFragment.length() != 0) {
- if (fixedFragment == null) {
- fixedFragment = new SpannableStringBuilder();
- }
- fixedFragment.append(draftsFragment);
- if (draftsStyle != null) {
- fixedFragment.setSpan(
- CharacterStyle.wrap(draftsStyle),
- 0, fixedFragment.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- if (sendingFragment.length() != 0) {
- if (fixedFragment == null) {
- fixedFragment = new SpannableStringBuilder();
- }
- if (fixedFragment.length() != 0) fixedFragment.append(", ");
- fixedFragment.append(sendingFragment);
- }
- if (sendFailedFragment.length() != 0) {
- if (fixedFragment == null) {
- fixedFragment = new SpannableStringBuilder();
- }
- if (fixedFragment.length() != 0) fixedFragment.append(", ");
- fixedFragment.append(sendFailedFragment);
- }
-
- if (fixedFragment != null) {
- fixedFragmentLength = fixedFragment.length();
- }
-
- final boolean normalMessagesExist =
- numMessagesFragment.length() != 0 || maxFoundPriority != Integer.MIN_VALUE;
- String preFixedFragement = "";
- if (normalMessagesExist && fixedFragmentLength != 0) {
- preFixedFragement = ", ";
- }
- int maxPriorityToInclude = -1; // inclusive
- int numCharsUsed =
- numMessagesFragment.length() + preFixedFragement.length() + fixedFragmentLength;
- int numSendersUsed = 0;
- while (maxPriorityToInclude < maxFoundPriority) {
- if (priorityToLength.containsKey(maxPriorityToInclude + 1)) {
- int length = numCharsUsed + priorityToLength.get(maxPriorityToInclude + 1);
- if (numCharsUsed > 0) length += 2;
- // We must show at least two senders if they exist. If we don't have space for both
- // then we will truncate names.
- if (length > maxChars && numSendersUsed >= 2) {
- break;
- }
- numCharsUsed = length;
- numSendersUsed++;
- }
- maxPriorityToInclude++;
- }
-
- int numCharsToRemovePerWord = 0;
- if (numCharsUsed > maxChars) {
- numCharsToRemovePerWord = (numCharsUsed - maxChars) / numSendersUsed;
- }
-
- boolean elided = false;
- for (int i = 0; i < numFragments;) {
- String fragment0 = fragments[i++];
- if ("".equals(fragment0)) {
- // This should be the final fragment.
- } else if (SENDER_LIST_TOKEN_ELIDED.equals(fragment0)) {
- elided = true;
- } else if (SENDER_LIST_TOKEN_NUM_MESSAGES.equals(fragment0)) {
- i++;
- } else if (SENDER_LIST_TOKEN_NUM_DRAFTS.equals(fragment0)) {
- i++;
- } else if (SENDER_LIST_TOKEN_SENDING.equals(fragment0)) {
- } else if (SENDER_LIST_TOKEN_SEND_FAILED.equals(fragment0)) {
- } else {
- final String unreadString = fragment0;
- final String priorityString = fragments[i++];
- String nameString = fragments[i++];
- if (nameString.length() == 0) nameString = meString.toString();
- if (numCharsToRemovePerWord != 0) {
- nameString = nameString.substring(
- 0, Math.max(nameString.length() - numCharsToRemovePerWord, 0));
- }
- final boolean unread = unreadStatusIsForced
- ? forcedUnreadStatus : Integer.parseInt(unreadString) != 0;
- final int priority = Integer.parseInt(priorityString);
- if (priority <= maxPriorityToInclude) {
- if (sb.length() != 0) {
- sb.append(elided ? " .. " : ", ");
- }
- elided = false;
- int pos = sb.length();
- sb.append(nameString);
- if (unread && unreadStyle != null) {
- sb.setSpan(CharacterStyle.wrap(unreadStyle),
- pos, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- } else {
- elided = true;
- }
- }
- }
- sb.append(numMessagesFragment);
- if (fixedFragmentLength != 0) {
- sb.append(preFixedFragement);
- sb.append(fixedFragment);
- }
- }
-
- /**
- * This is a cursor that only defines methods to move throught the results
- * and register to hear about changes. All access to the data is left to
- * subinterfaces.
- */
- public static class MailCursor extends ContentObserver {
-
- // A list of observers of this cursor.
- private Set<MailCursorObserver> mObservers;
-
- // Updated values are accumulated here before being written out if the
- // cursor is asked to persist the changes.
- private ContentValues mUpdateValues;
-
- protected Cursor mCursor;
- protected String mAccount;
-
- public Cursor getCursor() {
- return mCursor;
- }
-
- /**
- * Constructs the MailCursor given a regular cursor, registering as a
- * change observer of the cursor.
- * @param account the account the cursor is associated with
- * @param cursor the underlying cursor
- */
- protected MailCursor(String account, Cursor cursor) {
- super(new Handler());
- mObservers = new HashSet<MailCursorObserver>();
- mCursor = cursor;
- mAccount = account;
- if (mCursor != null) mCursor.registerContentObserver(this);
- }
-
- /**
- * Gets the account associated with this cursor.
- * @return the account.
- */
- public String getAccount() {
- return mAccount;
- }
-
- protected void checkThread() {
- // Turn this on when activity code no longer runs in the sync thread
- // after notifications of changes.
-// Thread currentThread = Thread.currentThread();
-// if (currentThread != mThread) {
-// throw new RuntimeException("Accessed from the wrong thread");
-// }
- }
-
- /**
- * Lazily constructs a map of update values to apply to the database
- * if requested. This map is cleared out when we move to a different
- * item in the result set.
- *
- * @return a map of values to be applied by an update.
- */
- protected ContentValues getUpdateValues() {
- if (mUpdateValues == null) {
- mUpdateValues = new ContentValues();
- }
- return mUpdateValues;
- }
-
- /**
- * Called whenever mCursor is changed to point to a different row.
- * Subclasses should override this if they need to clear out state
- * when this happens.
- *
- * Subclasses must call the inherited version if they override this.
- */
- protected void onCursorPositionChanged() {
- mUpdateValues = null;
- }
-
- // ********* MailCursor
-
- /**
- * Returns the numbers of rows in the cursor.
- *
- * @return the number of rows in the cursor.
- */
- final public int count() {
- if (mCursor != null) {
- return mCursor.getCount();
- } else {
- return 0;
- }
- }
-
- /**
- * @return the current position of this cursor, or -1 if this cursor
- * has not been initialized.
- */
- final public int position() {
- if (mCursor != null) {
- return mCursor.getPosition();
- } else {
- return -1;
- }
- }
-
- /**
- * Move the cursor to an absolute position. The valid
- * range of vaues is -1 &lt;= position &lt;= count.
- *
- * <p>This method will return true if the request destination was
- * reachable, otherwise it returns false.
- *
- * @param position the zero-based position to move to.
- * @return whether the requested move fully succeeded.
- */
- final public boolean moveTo(int position) {
- checkCursor();
- checkThread();
- boolean moved = mCursor.moveToPosition(position);
- if (moved) onCursorPositionChanged();
- return moved;
- }
-
- /**
- * Move the cursor to the next row.
- *
- * <p>This method will return false if the cursor is already past the
- * last entry in the result set.
- *
- * @return whether the move succeeded.
- */
- final public boolean next() {
- checkCursor();
- checkThread();
- boolean moved = mCursor.moveToNext();
- if (moved) onCursorPositionChanged();
- return moved;
- }
-
- /**
- * Release all resources and locks associated with the cursor. The
- * cursor will not be valid after this function is called.
- */
- final public void release() {
- if (mCursor != null) {
- mCursor.unregisterContentObserver(this);
- mCursor.deactivate();
- }
- }
-
- final public void registerContentObserver(ContentObserver observer) {
- mCursor.registerContentObserver(observer);
- }
-
- final public void unregisterContentObserver(ContentObserver observer) {
- mCursor.unregisterContentObserver(observer);
- }
-
- final public void registerDataSetObserver(DataSetObserver observer) {
- mCursor.registerDataSetObserver(observer);
- }
-
- final public void unregisterDataSetObserver(DataSetObserver observer) {
- mCursor.unregisterDataSetObserver(observer);
- }
-
- /**
- * Register an observer to hear about changes to the cursor.
- *
- * @param observer the observer to register
- */
- final public void registerObserver(MailCursorObserver observer) {
- mObservers.add(observer);
- }
-
- /**
- * Unregister an observer.
- *
- * @param observer the observer to unregister
- */
- final public void unregisterObserver(MailCursorObserver observer) {
- mObservers.remove(observer);
- }
-
- // ********* ContentObserver
-
- @Override
- final public boolean deliverSelfNotifications() {
- return false;
- }
-
- @Override
- public void onChange(boolean selfChange) {
- if (Config.DEBUG) {
- Log.d(TAG, "MailCursor is notifying " + mObservers.size() + " observers");
- }
- for (MailCursorObserver o: mObservers) {
- o.onCursorChanged(this);
- }
- }
-
- protected void checkCursor() {
- if (mCursor == null) {
- throw new IllegalStateException(
- "cannot read from an insertion cursor");
- }
- }
-
- /**
- * Returns the string value of the column, or "" if the value is null.
- */
- protected String getStringInColumn(int columnIndex) {
- checkCursor();
- return toNonnullString(mCursor.getString(columnIndex));
- }
- }
-
- /**
- * A MailCursor observer is notified of changes to the result set of a
- * cursor.
- */
- public interface MailCursorObserver {
-
- /**
- * Called when the result set of a cursor has changed.
- *
- * @param cursor the cursor whose result set has changed.
- */
- void onCursorChanged(MailCursor cursor);
- }
-
- /**
- * A cursor over labels.
- */
- public final class LabelCursor extends MailCursor {
-
- private int mNameIndex;
- private int mNumConversationsIndex;
- private int mNumUnreadConversationsIndex;
-
- private LabelCursor(String account, Cursor cursor) {
- super(account, cursor);
-
- mNameIndex = mCursor.getColumnIndexOrThrow(LabelColumns.CANONICAL_NAME);
- mNumConversationsIndex =
- mCursor.getColumnIndexOrThrow(LabelColumns.NUM_CONVERSATIONS);
- mNumUnreadConversationsIndex = mCursor.getColumnIndexOrThrow(
- LabelColumns.NUM_UNREAD_CONVERSATIONS);
- }
-
- /**
- * Gets the canonical name of the current label.
- *
- * @return the current label's name.
- */
- public String getName() {
- return getStringInColumn(mNameIndex);
- }
-
- /**
- * Gets the number of conversations with this label.
- *
- * @return the number of conversations with this label.
- */
- public int getNumConversations() {
- return mCursor.getInt(mNumConversationsIndex);
- }
-
- /**
- * Gets the number of unread conversations with this label.
- *
- * @return the number of unread conversations with this label.
- */
- public int getNumUnreadConversations() {
- return mCursor.getInt(mNumUnreadConversationsIndex);
- }
- }
-
- /**
- * This is a map of labels. TODO: make it observable.
- */
- public static final class LabelMap extends Observable {
- private final static ContentValues EMPTY_CONTENT_VALUES = new ContentValues();
-
- private ContentQueryMap mQueryMap;
- private SortedSet<String> mSortedUserLabels;
- private Map<String, Long> mCanonicalNameToId;
-
- private long mLabelIdSent;
- private long mLabelIdInbox;
- private long mLabelIdDraft;
- private long mLabelIdUnread;
- private long mLabelIdTrash;
- private long mLabelIdSpam;
- private long mLabelIdStarred;
- private long mLabelIdChat;
- private long mLabelIdVoicemail;
- private long mLabelIdIgnored;
- private long mLabelIdVoicemailInbox;
- private long mLabelIdCached;
- private long mLabelIdOutbox;
-
- private boolean mLabelsSynced = false;
-
- public LabelMap(ContentResolver contentResolver, String account, boolean keepUpdated) {
- if (TextUtils.isEmpty(account)) {
- throw new IllegalArgumentException("account is empty");
- }
- Cursor cursor = contentResolver.query(
- Uri.withAppendedPath(LABELS_URI, account), LABEL_PROJECTION, null, null, null);
- init(cursor, keepUpdated);
- }
-
- public LabelMap(Cursor cursor, boolean keepUpdated) {
- init(cursor, keepUpdated);
- }
-
- private void init(Cursor cursor, boolean keepUpdated) {
- mQueryMap = new ContentQueryMap(cursor, BaseColumns._ID, keepUpdated, null);
- mSortedUserLabels = new TreeSet<String>(java.text.Collator.getInstance());
- mCanonicalNameToId = Maps.newHashMap();
- updateDataStructures();
- mQueryMap.addObserver(new Observer() {
- public void update(Observable observable, Object data) {
- updateDataStructures();
- setChanged();
- notifyObservers();
- }
- });
- }
-
- /**
- * @return whether at least some labels have been synced.
- */
- public boolean labelsSynced() {
- return mLabelsSynced;
- }
-
- /**
- * Updates the data structures that are maintained separately from mQueryMap after the query
- * map has changed.
- */
- private void updateDataStructures() {
- mSortedUserLabels.clear();
- mCanonicalNameToId.clear();
- for (Map.Entry<String, ContentValues> row : mQueryMap.getRows().entrySet()) {
- long labelId = Long.valueOf(row.getKey());
- String canonicalName = row.getValue().getAsString(LabelColumns.CANONICAL_NAME);
- if (isLabelUserDefined(canonicalName)) {
- mSortedUserLabels.add(canonicalName);
- }
- mCanonicalNameToId.put(canonicalName, labelId);
-
- if (LABEL_SENT.equals(canonicalName)) {
- mLabelIdSent = labelId;
- } else if (LABEL_INBOX.equals(canonicalName)) {
- mLabelIdInbox = labelId;
- } else if (LABEL_DRAFT.equals(canonicalName)) {
- mLabelIdDraft = labelId;
- } else if (LABEL_UNREAD.equals(canonicalName)) {
- mLabelIdUnread = labelId;
- } else if (LABEL_TRASH.equals(canonicalName)) {
- mLabelIdTrash = labelId;
- } else if (LABEL_SPAM.equals(canonicalName)) {
- mLabelIdSpam = labelId;
- } else if (LABEL_STARRED.equals(canonicalName)) {
- mLabelIdStarred = labelId;
- } else if (LABEL_CHAT.equals(canonicalName)) {
- mLabelIdChat = labelId;
- } else if (LABEL_IGNORED.equals(canonicalName)) {
- mLabelIdIgnored = labelId;
- } else if (LABEL_VOICEMAIL.equals(canonicalName)) {
- mLabelIdVoicemail = labelId;
- } else if (LABEL_VOICEMAIL_INBOX.equals(canonicalName)) {
- mLabelIdVoicemailInbox = labelId;
- } else if (LABEL_CACHED.equals(canonicalName)) {
- mLabelIdCached = labelId;
- } else if (LABEL_OUTBOX.equals(canonicalName)) {
- mLabelIdOutbox = labelId;
- }
- mLabelsSynced = mLabelIdSent != 0
- && mLabelIdInbox != 0
- && mLabelIdDraft != 0
- && mLabelIdUnread != 0
- && mLabelIdTrash != 0
- && mLabelIdSpam != 0
- && mLabelIdStarred != 0
- && mLabelIdChat != 0
- && mLabelIdIgnored != 0
- && mLabelIdVoicemail != 0;
- }
- }
-
- public long getLabelIdSent() {
- checkLabelsSynced();
- return mLabelIdSent;
- }
-
- public long getLabelIdInbox() {
- checkLabelsSynced();
- return mLabelIdInbox;
- }
-
- public long getLabelIdDraft() {
- checkLabelsSynced();
- return mLabelIdDraft;
- }
-
- public long getLabelIdUnread() {
- checkLabelsSynced();
- return mLabelIdUnread;
- }
-
- public long getLabelIdTrash() {
- checkLabelsSynced();
- return mLabelIdTrash;
- }
-
- public long getLabelIdSpam() {
- checkLabelsSynced();
- return mLabelIdSpam;
- }
-
- public long getLabelIdStarred() {
- checkLabelsSynced();
- return mLabelIdStarred;
- }
-
- public long getLabelIdChat() {
- checkLabelsSynced();
- return mLabelIdChat;
- }
-
- public long getLabelIdIgnored() {
- checkLabelsSynced();
- return mLabelIdIgnored;
- }
-
- public long getLabelIdVoicemail() {
- checkLabelsSynced();
- return mLabelIdVoicemail;
- }
-
- public long getLabelIdVoicemailInbox() {
- checkLabelsSynced();
- return mLabelIdVoicemailInbox;
- }
-
- public long getLabelIdCached() {
- checkLabelsSynced();
- return mLabelIdCached;
- }
-
- public long getLabelIdOutbox() {
- checkLabelsSynced();
- return mLabelIdOutbox;
- }
-
- private void checkLabelsSynced() {
- if (!labelsSynced()) {
- throw new IllegalStateException("LabelMap not initalized");
- }
- }
-
- /** Returns the list of user-defined labels in alphabetical order. */
- public SortedSet<String> getSortedUserLabels() {
- return mSortedUserLabels;
- }
-
- private static final List<String> SORTED_USER_MEANINGFUL_SYSTEM_LABELS =
- Lists.newArrayList(
- LABEL_INBOX, LABEL_STARRED, LABEL_CHAT, LABEL_SENT,
- LABEL_OUTBOX, LABEL_DRAFT, LABEL_ALL,
- LABEL_SPAM, LABEL_TRASH);
-
-
- private static final Set<String> USER_MEANINGFUL_SYSTEM_LABELS_SET =
- Sets.newHashSet(
- SORTED_USER_MEANINGFUL_SYSTEM_LABELS.toArray(
- new String[]{}));
-
- public static List<String> getSortedUserMeaningfulSystemLabels() {
- return SORTED_USER_MEANINGFUL_SYSTEM_LABELS;
- }
-
- public static Set<String> getUserMeaningfulSystemLabelsSet() {
- return USER_MEANINGFUL_SYSTEM_LABELS_SET;
- }
-
- /**
- * If you are ever tempted to remove outbox or draft from this set make sure you have a
- * way to stop draft and outbox messages from getting purged before they are sent to the
- * server.
- */
- private static final Set<String> FORCED_INCLUDED_LABELS =
- Sets.newHashSet(LABEL_OUTBOX, LABEL_DRAFT);
-
- public static Set<String> getForcedIncludedLabels() {
- return FORCED_INCLUDED_LABELS;
- }
-
- private static final Set<String> FORCED_INCLUDED_OR_PARTIAL_LABELS =
- Sets.newHashSet(LABEL_INBOX);
-
- public static Set<String> getForcedIncludedOrPartialLabels() {
- return FORCED_INCLUDED_OR_PARTIAL_LABELS;
- }
-
- private static final Set<String> FORCED_UNSYNCED_LABELS =
- Sets.newHashSet(LABEL_ALL, LABEL_CHAT, LABEL_SPAM, LABEL_TRASH);
-
- public static Set<String> getForcedUnsyncedLabels() {
- return FORCED_UNSYNCED_LABELS;
- }
-
- /**
- * Returns the number of conversation with a given label.
- * @deprecated
- */
- public int getNumConversations(String label) {
- return getNumConversations(getLabelId(label));
- }
-
- /** Returns the number of conversation with a given label. */
- public int getNumConversations(long labelId) {
- return getLabelIdValues(labelId).getAsInteger(LabelColumns.NUM_CONVERSATIONS);
- }
-
- /**
- * Returns the number of unread conversation with a given label.
- * @deprecated
- */
- public int getNumUnreadConversations(String label) {
- return getNumUnreadConversations(getLabelId(label));
- }
-
- /** Returns the number of unread conversation with a given label. */
- public int getNumUnreadConversations(long labelId) {
- return getLabelIdValues(labelId).getAsInteger(LabelColumns.NUM_UNREAD_CONVERSATIONS);
- }
-
- /**
- * @return the canonical name for a label
- */
- public String getCanonicalName(long labelId) {
- return getLabelIdValues(labelId).getAsString(LabelColumns.CANONICAL_NAME);
- }
-
- /**
- * @return the human name for a label
- */
- public String getName(long labelId) {
- return getLabelIdValues(labelId).getAsString(LabelColumns.NAME);
- }
-
- /**
- * @return whether a given label is known
- */
- public boolean hasLabel(long labelId) {
- return mQueryMap.getRows().containsKey(Long.toString(labelId));
- }
-
- /**
- * @return returns the id of a label given the canonical name
- * @deprecated this is only needed because most of the UI uses label names instead of ids
- */
- public long getLabelId(String canonicalName) {
- if (mCanonicalNameToId.containsKey(canonicalName)) {
- return mCanonicalNameToId.get(canonicalName);
- } else {
- throw new IllegalArgumentException("Unknown canonical name: " + canonicalName);
- }
- }
-
- private ContentValues getLabelIdValues(long labelId) {
- final ContentValues values = mQueryMap.getValues(Long.toString(labelId));
- if (values != null) {
- return values;
- } else {
- return EMPTY_CONTENT_VALUES;
- }
- }
-
- /** Force the map to requery. This should not be necessary outside tests. */
- public void requery() {
- mQueryMap.requery();
- }
-
- public void close() {
- mQueryMap.close();
- }
- }
-
- private Map<String, Gmail.LabelMap> mLabelMaps = Maps.newHashMap();
-
- public LabelMap getLabelMap(String account) {
- Gmail.LabelMap labelMap = mLabelMaps.get(account);
- if (labelMap == null) {
- labelMap = new Gmail.LabelMap(mContentResolver, account, true /* keepUpdated */);
- mLabelMaps.put(account, labelMap);
- }
- return labelMap;
- }
-
- public enum PersonalLevel {
- NOT_TO_ME(0),
- TO_ME_AND_OTHERS(1),
- ONLY_TO_ME(2);
-
- private int mLevel;
-
- PersonalLevel(int level) {
- mLevel = level;
- }
-
- public int toInt() {
- return mLevel;
- }
-
- public static PersonalLevel fromInt(int level) {
- switch (level) {
- case 0: return NOT_TO_ME;
- case 1: return TO_ME_AND_OTHERS;
- case 2: return ONLY_TO_ME;
- default:
- throw new IllegalArgumentException(
- level + " is not a personal level");
- }
- }
- }
-
- /**
- * Indicates a version of an attachment.
- */
- public enum AttachmentRendition {
- /**
- * The full version of an attachment if it can be handled on the device, otherwise the
- * preview.
- */
- BEST,
-
- /** A smaller or simpler version of the attachment, such as a scaled-down image or an HTML
- * version of a document. Not always available.
- */
- SIMPLE,
- }
-
- /**
- * The columns that can be requested when querying an attachment's download URI. See
- * getAttachmentDownloadUri.
- */
- public static final class AttachmentColumns implements BaseColumns {
-
- /** Contains a STATUS value from {@link android.provider.Downloads} */
- public static final String STATUS = "status";
-
- /**
- * The name of the file to open (with ContentProvider.open). If this is empty then continue
- * to use the attachment's URI.
- *
- * TODO: I'm not sure that we need this. See the note in CL 66853-p9.
- */
- public static final String FILENAME = "filename";
- }
-
- /**
- * We track where an attachment came from so that we know how to download it and include it
- * in new messages.
- */
- public enum AttachmentOrigin {
- /** Extras are "<conversationId>-<messageId>-<partId>". */
- SERVER_ATTACHMENT,
- /** Extras are "<path>". */
- LOCAL_FILE;
-
- private static final String SERVER_EXTRAS_SEPARATOR = "_";
-
- public static String serverExtras(
- long conversationId, long messageId, String partId) {
- return conversationId + SERVER_EXTRAS_SEPARATOR
- + messageId + SERVER_EXTRAS_SEPARATOR + partId;
- }
-
- /**
- * @param extras extras as returned by serverExtras
- * @return an array of conversationId, messageId, partId (all as strings)
- */
- public static String[] splitServerExtras(String extras) {
- return TextUtils.split(extras, SERVER_EXTRAS_SEPARATOR);
- }
-
- public static String localFileExtras(Uri path) {
- return path.toString();
- }
- }
-
- public static final class Attachment {
- /** Identifies the attachment uniquely when combined wih a message id.*/
- public String partId;
-
- /** The intended filename of the attachment.*/
- public String name;
-
- /** The native content type.*/
- public String contentType;
-
- /** The size of the attachment in its native form.*/
- public int size;
-
- /**
- * The content type of the simple version of the attachment. Blank if no simple version is
- * available.
- */
- public String simpleContentType;
-
- public AttachmentOrigin origin;
-
- public String originExtras;
-
- public String toJoinedString() {
- return TextUtils.join(
- "|", Lists.newArrayList(partId == null ? "" : partId,
- name.replace("|", ""), contentType,
- size, simpleContentType,
- origin.toString(), originExtras));
- }
-
- public static Attachment parseJoinedString(String joinedString) {
- String[] fragments = TextUtils.split(joinedString, "\\|");
- int i = 0;
- Attachment attachment = new Attachment();
- attachment.partId = fragments[i++];
- if (TextUtils.isEmpty(attachment.partId)) {
- attachment.partId = null;
- }
- attachment.name = fragments[i++];
- attachment.contentType = fragments[i++];
- attachment.size = Integer.parseInt(fragments[i++]);
- attachment.simpleContentType = fragments[i++];
- attachment.origin = AttachmentOrigin.valueOf(fragments[i++]);
- attachment.originExtras = fragments[i++];
- return attachment;
- }
- }
-
- /**
- * Any given attachment can come in two different renditions (see
- * {@link android.provider.Gmail.AttachmentRendition}) and can be saved to the sd card or to a
- * cache. The gmail provider automatically syncs some attachments to the cache. Other
- * attachments can be downloaded on demand. Attachments in the cache will be purged as needed to
- * save space. Attachments on the SD card must be managed by the user or other software.
- *
- * @param account which account to use
- * @param messageId the id of the mesage with the attachment
- * @param attachment the attachment
- * @param rendition the desired rendition
- * @param saveToSd whether the attachment should be saved to (or loaded from) the sd card or
- * @return the URI to ask the content provider to open in order to open an attachment.
- */
- public static Uri getAttachmentUri(
- String account, long messageId, Attachment attachment,
- AttachmentRendition rendition, boolean saveToSd) {
- if (TextUtils.isEmpty(account)) {
- throw new IllegalArgumentException("account is empty");
- }
- if (attachment.origin == AttachmentOrigin.LOCAL_FILE) {
- return Uri.parse(attachment.originExtras);
- } else {
- return Uri.parse(
- AUTHORITY_PLUS_MESSAGES).buildUpon()
- .appendPath(account).appendPath(Long.toString(messageId))
- .appendPath("attachments").appendPath(attachment.partId)
- .appendPath(rendition.toString())
- .appendPath(Boolean.toString(saveToSd))
- .build();
- }
- }
-
- /**
- * Return the URI to query in order to find out whether an attachment is downloaded.
- *
- * <p>Querying this will also start a download if necessary. The cursor returned by querying
- * this URI can contain the columns in {@link android.provider.Gmail.AttachmentColumns}.
- *
- * <p>Deleting this URI will cancel the download if it was not started automatically by the
- * provider. It will also remove bookkeeping for saveToSd downloads.
- *
- * @param attachmentUri the attachment URI as returned by getAttachmentUri. The URI's authority
- * Gmail.AUTHORITY. If it is not then you should open the file directly.
- */
- public static Uri getAttachmentDownloadUri(Uri attachmentUri) {
- if (!"content".equals(attachmentUri.getScheme())) {
- throw new IllegalArgumentException("Uri's scheme must be 'content': " + attachmentUri);
- }
- return attachmentUri.buildUpon().appendPath("download").build();
- }
-
- public enum CursorStatus {
- LOADED,
- LOADING,
- ERROR, // A network error occurred.
- }
-
- /**
- * A cursor over messages.
- */
- public static final class MessageCursor extends MailCursor {
-
- private LabelMap mLabelMap;
-
- private ContentResolver mContentResolver;
-
- /**
- * Only valid if mCursor == null, in which case we are inserting a new
- * message.
- */
- long mInReplyToLocalMessageId;
- boolean mPreserveAttachments;
-
- private int mIdIndex;
- private int mConversationIdIndex;
- private int mSubjectIndex;
- private int mSnippetIndex;
- private int mFromIndex;
- private int mToIndex;
- private int mCcIndex;
- private int mBccIndex;
- private int mReplyToIndex;
- private int mDateSentMsIndex;
- private int mDateReceivedMsIndex;
- private int mListInfoIndex;
- private int mPersonalLevelIndex;
- private int mBodyIndex;
- private int mBodyEmbedsExternalResourcesIndex;
- private int mLabelIdsIndex;
- private int mJoinedAttachmentInfosIndex;
- private int mErrorIndex;
-
- private TextUtils.StringSplitter mLabelIdsSplitter = newMessageLabelIdsSplitter();
-
- public MessageCursor(Gmail gmail, ContentResolver cr, String account, Cursor cursor) {
- super(account, cursor);
- mLabelMap = gmail.getLabelMap(account);
- if (cursor == null) {
- throw new IllegalArgumentException(
- "null cursor passed to MessageCursor()");
- }
-
- mContentResolver = cr;
-
- mIdIndex = mCursor.getColumnIndexOrThrow(MessageColumns.ID);
- mConversationIdIndex =
- mCursor.getColumnIndexOrThrow(MessageColumns.CONVERSATION_ID);
- mSubjectIndex = mCursor.getColumnIndexOrThrow(MessageColumns.SUBJECT);
- mSnippetIndex = mCursor.getColumnIndexOrThrow(MessageColumns.SNIPPET);
- mFromIndex = mCursor.getColumnIndexOrThrow(MessageColumns.FROM);
- mToIndex = mCursor.getColumnIndexOrThrow(MessageColumns.TO);
- mCcIndex = mCursor.getColumnIndexOrThrow(MessageColumns.CC);
- mBccIndex = mCursor.getColumnIndexOrThrow(MessageColumns.BCC);
- mReplyToIndex = mCursor.getColumnIndexOrThrow(MessageColumns.REPLY_TO);
- mDateSentMsIndex =
- mCursor.getColumnIndexOrThrow(MessageColumns.DATE_SENT_MS);
- mDateReceivedMsIndex =
- mCursor.getColumnIndexOrThrow(MessageColumns.DATE_RECEIVED_MS);
- mListInfoIndex = mCursor.getColumnIndexOrThrow(MessageColumns.LIST_INFO);
- mPersonalLevelIndex =
- mCursor.getColumnIndexOrThrow(MessageColumns.PERSONAL_LEVEL);
- mBodyIndex = mCursor.getColumnIndexOrThrow(MessageColumns.BODY);
- mBodyEmbedsExternalResourcesIndex =
- mCursor.getColumnIndexOrThrow(MessageColumns.EMBEDS_EXTERNAL_RESOURCES);
- mLabelIdsIndex = mCursor.getColumnIndexOrThrow(MessageColumns.LABEL_IDS);
- mJoinedAttachmentInfosIndex =
- mCursor.getColumnIndexOrThrow(MessageColumns.JOINED_ATTACHMENT_INFOS);
- mErrorIndex = mCursor.getColumnIndexOrThrow(MessageColumns.ERROR);
-
- mInReplyToLocalMessageId = 0;
- mPreserveAttachments = false;
- }
-
- protected MessageCursor(ContentResolver cr, String account, long inReplyToMessageId,
- boolean preserveAttachments) {
- super(account, null);
- mContentResolver = cr;
- mInReplyToLocalMessageId = inReplyToMessageId;
- mPreserveAttachments = preserveAttachments;
- }
-
- @Override
- protected void onCursorPositionChanged() {
- super.onCursorPositionChanged();
- }
-
- public CursorStatus getStatus() {
- Bundle extras = mCursor.getExtras();
- String stringStatus = extras.getString(EXTRA_STATUS);
- return CursorStatus.valueOf(stringStatus);
- }
-
- /** Retry a network request after errors. */
- public void retry() {
- Bundle input = new Bundle();
- input.putString(RESPOND_INPUT_COMMAND, COMMAND_RETRY);
- Bundle output = mCursor.respond(input);
- String response = output.getString(RESPOND_OUTPUT_COMMAND_RESPONSE);
- assert COMMAND_RESPONSE_OK.equals(response);
- }
-
- /**
- * Gets the message id of the current message. Note that this is an
- * immutable local message (not, for example, GMail's message id, which
- * is immutable).
- *
- * @return the message's id
- */
- public long getMessageId() {
- checkCursor();
- return mCursor.getLong(mIdIndex);
- }
-
- /**
- * Gets the message's conversation id. This must be immutable. (For
- * example, with GMail this should be the original conversation id
- * rather than the default notion of converation id.)
- *
- * @return the message's conversation id
- */
- public long getConversationId() {
- checkCursor();
- return mCursor.getLong(mConversationIdIndex);
- }
-
- /**
- * Gets the message's subject.
- *
- * @return the message's subject
- */
- public String getSubject() {
- return getStringInColumn(mSubjectIndex);
- }
-
- /**
- * Gets the message's snippet (the short piece of the body). The snippet
- * is generated from the body and cannot be set directly.
- *
- * @return the message's snippet
- */
- public String getSnippet() {
- return getStringInColumn(mSnippetIndex);
- }
-
- /**
- * Gets the message's from address.
- *
- * @return the message's from address
- */
- public String getFromAddress() {
- return getStringInColumn(mFromIndex);
- }
-
- /**
- * Returns the addresses for the key, if it has been updated, or index otherwise.
- */
- private String[] getAddresses(String key, int index) {
- ContentValues updated = getUpdateValues();
- String addresses;
- if (updated.containsKey(key)) {
- addresses = (String)getUpdateValues().get(key);
- } else {
- addresses = getStringInColumn(index);
- }
-
- return TextUtils.split(addresses, EMAIL_SEPARATOR_PATTERN);
- }
-
- /**
- * Gets the message's to addresses.
- * @return the message's to addresses
- */
- public String[] getToAddresses() {
- return getAddresses(MessageColumns.TO, mToIndex);
- }
-
- /**
- * Gets the message's cc addresses.
- * @return the message's cc addresses
- */
- public String[] getCcAddresses() {
- return getAddresses(MessageColumns.CC, mCcIndex);
- }
-
- /**
- * Gets the message's bcc addresses.
- * @return the message's bcc addresses
- */
- public String[] getBccAddresses() {
- return getAddresses(MessageColumns.BCC, mBccIndex);
- }
-
- /**
- * Gets the message's replyTo address.
- *
- * @return the message's replyTo address
- */
- public String[] getReplyToAddress() {
- return TextUtils.split(getStringInColumn(mReplyToIndex), EMAIL_SEPARATOR_PATTERN);
- }
-
- public long getDateSentMs() {
- checkCursor();
- return mCursor.getLong(mDateSentMsIndex);
- }
-
- public long getDateReceivedMs() {
- checkCursor();
- return mCursor.getLong(mDateReceivedMsIndex);
- }
-
- public String getListInfo() {
- return getStringInColumn(mListInfoIndex);
- }
-
- public PersonalLevel getPersonalLevel() {
- checkCursor();
- int personalLevelInt = mCursor.getInt(mPersonalLevelIndex);
- return PersonalLevel.fromInt(personalLevelInt);
- }
-
- /**
- * @deprecated
- */
- public boolean getExpanded() {
- return true;
- }
-
- /**
- * Gets the message's body.
- *
- * @return the message's body
- */
- public String getBody() {
- return getStringInColumn(mBodyIndex);
- }
-
- /**
- * @return whether the message's body contains embedded references to external resources. In
- * that case the resources should only be displayed if the user explicitly asks for them to
- * be
- */
- public boolean getBodyEmbedsExternalResources() {
- checkCursor();
- return mCursor.getInt(mBodyEmbedsExternalResourcesIndex) != 0;
- }
-
- /**
- * @return a copy of the set of label ids
- */
- public Set<Long> getLabelIds() {
- String labelNames = mCursor.getString(mLabelIdsIndex);
- mLabelIdsSplitter.setString(labelNames);
- return getLabelIdsFromLabelIdsString(mLabelIdsSplitter);
- }
-
- /**
- * @return a joined string of labels separated by spaces.
- */
- public String getRawLabelIds() {
- return mCursor.getString(mLabelIdsIndex);
- }
-
- /**
- * Adds a label to a message (if add is true) or removes it (if add is
- * false).
- *
- * @param label the label to add or remove
- * @param add whether to add or remove the label
- */
- public void addOrRemoveLabel(String label, boolean add) {
- addOrRemoveLabelOnMessage(mContentResolver, mAccount, getConversationId(),
- getMessageId(), label, add);
- }
-
- public ArrayList<Attachment> getAttachmentInfos() {
- ArrayList<Attachment> attachments = Lists.newArrayList();
-
- String joinedAttachmentInfos = mCursor.getString(mJoinedAttachmentInfosIndex);
- if (joinedAttachmentInfos != null) {
- for (String joinedAttachmentInfo :
- TextUtils.split(joinedAttachmentInfos, ATTACHMENT_INFO_SEPARATOR_PATTERN)) {
-
- Attachment attachment = Attachment.parseJoinedString(joinedAttachmentInfo);
- attachments.add(attachment);
- }
- }
- return attachments;
- }
-
- /**
- * @return the error text for the message. Error text gets set if the server rejects a
- * message that we try to save or send. If there is error text then the message is no longer
- * scheduled to be saved or sent. Calling save() or send() will clear any error as well as
- * scheduling another atempt to save or send the message.
- */
- public String getErrorText() {
- return mCursor.getString(mErrorIndex);
- }
- }
-
- /**
- * A helper class for creating or updating messags. Use the putXxx methods to provide initial or
- * new values for the message. Then save or send the message. To save or send an existing
- * message without making other changes to it simply provide an emty ContentValues.
- */
- public static class MessageModification {
-
- /**
- * Sets the message's subject. Only valid for drafts.
- *
- * @param values the ContentValues that will be used to create or update the message
- * @param subject the new subject
- */
- public static void putSubject(ContentValues values, String subject) {
- values.put(MessageColumns.SUBJECT, subject);
- }
-
- /**
- * Sets the message's to address. Only valid for drafts.
- *
- * @param values the ContentValues that will be used to create or update the message
- * @param toAddresses the new to addresses
- */
- public static void putToAddresses(ContentValues values, String[] toAddresses) {
- values.put(MessageColumns.TO, TextUtils.join(EMAIL_SEPARATOR, toAddresses));
- }
-
- /**
- * Sets the message's cc address. Only valid for drafts.
- *
- * @param values the ContentValues that will be used to create or update the message
- * @param ccAddresses the new cc addresses
- */
- public static void putCcAddresses(ContentValues values, String[] ccAddresses) {
- values.put(MessageColumns.CC, TextUtils.join(EMAIL_SEPARATOR, ccAddresses));
- }
-
- /**
- * Sets the message's bcc address. Only valid for drafts.
- *
- * @param values the ContentValues that will be used to create or update the message
- * @param bccAddresses the new bcc addresses
- */
- public static void putBccAddresses(ContentValues values, String[] bccAddresses) {
- values.put(MessageColumns.BCC, TextUtils.join(EMAIL_SEPARATOR, bccAddresses));
- }
-
- /**
- * Saves a new body for the message. Only valid for drafts.
- *
- * @param values the ContentValues that will be used to create or update the message
- * @param body the new body of the message
- */
- public static void putBody(ContentValues values, String body) {
- values.put(MessageColumns.BODY, body);
- }
-
- /**
- * Sets the attachments on a message. Only valid for drafts.
- *
- * @param values the ContentValues that will be used to create or update the message
- * @param attachments
- */
- public static void putAttachments(ContentValues values, List<Attachment> attachments) {
- values.put(
- MessageColumns.JOINED_ATTACHMENT_INFOS, joinedAttachmentsString(attachments));
- }
-
- /**
- * Create a new message and save it as a draft or send it.
- *
- * @param contentResolver the content resolver to use
- * @param account the account to use
- * @param values the values for the new message
- * @param refMessageId the message that is being replied to or forwarded
- * @param save whether to save or send the message
- * @return the id of the new message
- */
- public static long sendOrSaveNewMessage(
- ContentResolver contentResolver, String account,
- ContentValues values, long refMessageId, boolean save) {
- values.put(MessageColumns.FAKE_SAVE, save);
- values.put(MessageColumns.FAKE_REF_MESSAGE_ID, refMessageId);
- Uri uri = Uri.parse(AUTHORITY_PLUS_MESSAGES + account + "/");
- Uri result = contentResolver.insert(uri, values);
- return ContentUris.parseId(result);
- }
-
- /**
- * Update an existing draft and save it as a new draft or send it.
- *
- * @param contentResolver the content resolver to use
- * @param account the account to use
- * @param messageId the id of the message to update
- * @param updateValues the values to change. Unspecified fields will not be altered
- * @param save whether to resave the message as a draft or send it
- */
- public static void sendOrSaveExistingMessage(
- ContentResolver contentResolver, String account, long messageId,
- ContentValues updateValues, boolean save) {
- updateValues.put(MessageColumns.FAKE_SAVE, save);
- updateValues.put(MessageColumns.FAKE_REF_MESSAGE_ID, 0);
- Uri uri = Uri.parse(
- AUTHORITY_PLUS_MESSAGES + account + "/" + messageId);
- contentResolver.update(uri, updateValues, null, null);
- }
-
- /**
- * The string produced here is parsed by Gmail.MessageCursor#getAttachmentInfos.
- */
- public static String joinedAttachmentsString(List<Gmail.Attachment> attachments) {
- StringBuilder attachmentsSb = new StringBuilder();
- for (Gmail.Attachment attachment : attachments) {
- if (attachmentsSb.length() != 0) {
- attachmentsSb.append(Gmail.ATTACHMENT_INFO_SEPARATOR);
- }
- attachmentsSb.append(attachment.toJoinedString());
- }
- return attachmentsSb.toString();
- }
-
- }
-
- /**
- * A cursor over conversations.
- *
- * "Conversation" refers to the information needed to populate a list of
- * conversations, not all of the messages in a conversation.
- */
- public static final class ConversationCursor extends MailCursor {
-
- private LabelMap mLabelMap;
-
- private int mConversationIdIndex;
- private int mSubjectIndex;
- private int mSnippetIndex;
- private int mFromIndex;
- private int mDateIndex;
- private int mPersonalLevelIndex;
- private int mLabelIdsIndex;
- private int mNumMessagesIndex;
- private int mMaxMessageIdIndex;
- private int mHasAttachmentsIndex;
- private int mHasMessagesWithErrorsIndex;
- private int mForceAllUnreadIndex;
-
- private TextUtils.StringSplitter mLabelIdsSplitter = newConversationLabelIdsSplitter();
-
- private ConversationCursor(Gmail gmail, String account, Cursor cursor) {
- super(account, cursor);
- mLabelMap = gmail.getLabelMap(account);
-
- mConversationIdIndex =
- mCursor.getColumnIndexOrThrow(ConversationColumns.ID);
- mSubjectIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.SUBJECT);
- mSnippetIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.SNIPPET);
- mFromIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.FROM);
- mDateIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.DATE);
- mPersonalLevelIndex =
- mCursor.getColumnIndexOrThrow(ConversationColumns.PERSONAL_LEVEL);
- mLabelIdsIndex =
- mCursor.getColumnIndexOrThrow(ConversationColumns.LABEL_IDS);
- mNumMessagesIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.NUM_MESSAGES);
- mMaxMessageIdIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.MAX_MESSAGE_ID);
- mHasAttachmentsIndex =
- mCursor.getColumnIndexOrThrow(ConversationColumns.HAS_ATTACHMENTS);
- mHasMessagesWithErrorsIndex =
- mCursor.getColumnIndexOrThrow(ConversationColumns.HAS_MESSAGES_WITH_ERRORS);
- mForceAllUnreadIndex =
- mCursor.getColumnIndexOrThrow(ConversationColumns.FORCE_ALL_UNREAD);
- }
-
- @Override
- protected void onCursorPositionChanged() {
- super.onCursorPositionChanged();
- }
-
- public CursorStatus getStatus() {
- Bundle extras = mCursor.getExtras();
- String stringStatus = extras.getString(EXTRA_STATUS);
- return CursorStatus.valueOf(stringStatus);
- }
-
- /** Retry a network request after errors. */
- public void retry() {
- Bundle input = new Bundle();
- input.putString(RESPOND_INPUT_COMMAND, COMMAND_RETRY);
- Bundle output = mCursor.respond(input);
- String response = output.getString(RESPOND_OUTPUT_COMMAND_RESPONSE);
- assert COMMAND_RESPONSE_OK.equals(response);
- }
-
- /**
- * When a conversation cursor is created it becomes the active network cursor, which means
- * that it will fetch results from the network if it needs to in order to show all mail that
- * matches its query. If you later want to requery an older cursor and would like that
- * cursor to be the active cursor you need to call this method before requerying.
- */
- public void becomeActiveNetworkCursor() {
- Bundle input = new Bundle();
- input.putString(RESPOND_INPUT_COMMAND, COMMAND_ACTIVATE);
- Bundle output = mCursor.respond(input);
- String response = output.getString(RESPOND_OUTPUT_COMMAND_RESPONSE);
- assert COMMAND_RESPONSE_OK.equals(response);
- }
-
- /**
- * Tells the cursor whether its contents are visible to the user. The cursor will
- * automatically broadcast intents to remove any matching new-mail notifications when this
- * cursor's results become visible and, if they are visible, when the cursor is requeried.
- *
- * Note that contents shown in an activity that is resumed but not focused
- * (onWindowFocusChanged/hasWindowFocus) then results shown in that activity do not count
- * as visible. (This happens when the activity is behind the lock screen or a dialog.)
- *
- * @param visible whether the contents of this cursor are visible to the user.
- */
- public void setContentsVisibleToUser(boolean visible) {
- Bundle input = new Bundle();
- input.putString(RESPOND_INPUT_COMMAND, COMMAND_SET_VISIBLE);
- input.putBoolean(SET_VISIBLE_PARAM_VISIBLE, visible);
- Bundle output = mCursor.respond(input);
- String response = output.getString(RESPOND_OUTPUT_COMMAND_RESPONSE);
- assert COMMAND_RESPONSE_OK.equals(response);
- }
-
- /**
- * Gets the conversation id. This is immutable. (The server calls it the original
- * conversation id.)
- *
- * @return the conversation id
- */
- public long getConversationId() {
- return mCursor.getLong(mConversationIdIndex);
- }
-
- /**
- * Returns the instructions for building from snippets. Pass this to getFromSnippetHtml
- * in order to actually build the snippets.
- * @return snippet instructions for use by getFromSnippetHtml()
- */
- public String getFromSnippetInstructions() {
- return getStringInColumn(mFromIndex);
- }
-
- /**
- * Gets the conversation's subject.
- *
- * @return the subject
- */
- public String getSubject() {
- return getStringInColumn(mSubjectIndex);
- }
-
- /**
- * Gets the conversation's snippet.
- *
- * @return the snippet
- */
- public String getSnippet() {
- return getStringInColumn(mSnippetIndex);
- }
-
- /**
- * Get's the conversation's personal level.
- *
- * @return the personal level.
- */
- public PersonalLevel getPersonalLevel() {
- int personalLevelInt = mCursor.getInt(mPersonalLevelIndex);
- return PersonalLevel.fromInt(personalLevelInt);
- }
-
- /**
- * @return a copy of the set of labels. To add or remove labels call
- * MessageCursor.addOrRemoveLabel on each message in the conversation.
- * @deprecated use getLabelIds
- */
- public Set<String> getLabels() {
- return getLabels(getRawLabelIds(), mLabelMap);
- }
-
- /**
- * @return a copy of the set of labels. To add or remove labels call
- * MessageCursor.addOrRemoveLabel on each message in the conversation.
- */
- public Set<Long> getLabelIds() {
- mLabelIdsSplitter.setString(getRawLabelIds());
- return getLabelIdsFromLabelIdsString(mLabelIdsSplitter);
- }
-
- /**
- * Returns the set of labels using the raw labels from a previous getRawLabels()
- * as input.
- * @return a copy of the set of labels. To add or remove labels call
- * MessageCursor.addOrRemoveLabel on each message in the conversation.
- */
- public Set<String> getLabels(String rawLabelIds, LabelMap labelMap) {
- mLabelIdsSplitter.setString(rawLabelIds);
- return getCanonicalNamesFromLabelIdsString(labelMap, mLabelIdsSplitter);
- }
-
- /**
- * @return a joined string of labels separated by spaces. Use
- * getLabels(rawLabels) to convert this to a Set of labels.
- */
- public String getRawLabelIds() {
- return mCursor.getString(mLabelIdsIndex);
- }
-
- /**
- * @return the number of messages in the conversation
- */
- public int getNumMessages() {
- return mCursor.getInt(mNumMessagesIndex);
- }
-
- /**
- * @return the max message id in the conversation
- */
- public long getMaxServerMessageId() {
- return mCursor.getLong(mMaxMessageIdIndex);
- }
-
- public long getDateMs() {
- return mCursor.getLong(mDateIndex);
- }
-
- public boolean hasAttachments() {
- return mCursor.getInt(mHasAttachmentsIndex) != 0;
- }
-
- public boolean hasMessagesWithErrors() {
- return mCursor.getInt(mHasMessagesWithErrorsIndex) != 0;
- }
-
- public boolean getForceAllUnread() {
- return !mCursor.isNull(mForceAllUnreadIndex)
- && mCursor.getInt(mForceAllUnreadIndex) != 0;
- }
- }
-}
diff --git a/core/java/android/provider/Im.java b/core/java/android/provider/Im.java
deleted file mode 100644
index bea857f..0000000
--- a/core/java/android/provider/Im.java
+++ /dev/null
@@ -1,2047 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import android.content.ContentQueryMap;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Handler;
-
-import java.util.HashMap;
-
-/**
- * The IM provider stores all information about roster contacts, chat messages, presence, etc.
- *
- * @hide
- */
-public class Im {
- /**
- * no public constructor since this is a utility class
- */
- private Im() {}
-
- /**
- * The Columns for IM providers (i.e. AIM, Y!, GTalk)
- */
- public interface ProviderColumns {
- /**
- * The name of the IM provider
- * <P>Type: TEXT</P>
- */
- String NAME = "name";
-
- /**
- * The full name of the provider
- * <P>Type: TEXT</P>
- */
- String FULLNAME = "fullname";
-
- /**
- * The category for the provider, used to form intent.
- * <P>Type: TEXT</P>
- */
- String CATEGORY = "category";
-
- /**
- * The url users should visit to create a new account for this provider
- * <P>Type: TEXT</P>
- */
- String SIGNUP_URL = "signup_url";
- }
-
- /**
- * Known names corresponding to the {@link ProviderColumns#NAME} column
- */
- public interface ProviderNames {
- //
- //NOTE: update Contacts.java with new providers when they're added.
- //
- String YAHOO = "Yahoo";
- String GTALK = "GTalk";
- String MSN = "MSN";
- String ICQ = "ICQ";
- String AIM = "AIM";
- String XMPP = "XMPP";
- String JABBER = "JABBER";
- String SKYPE = "SKYPE";
- String QQ = "QQ";
- }
-
- /**
- * This table contains the IM providers
- */
- public static final class Provider implements BaseColumns, ProviderColumns {
- private Provider() {}
-
- public static final long getProviderIdForName(ContentResolver cr, String providerName) {
- String[] selectionArgs = new String[1];
- selectionArgs[0] = providerName;
-
- Cursor cursor = cr.query(CONTENT_URI,
- PROVIDER_PROJECTION,
- NAME+"=?",
- selectionArgs, null);
-
- long retVal = 0;
- try {
- if (cursor.moveToFirst()) {
- retVal = cursor.getLong(cursor.getColumnIndexOrThrow(_ID));
- }
- } finally {
- cursor.close();
- }
-
- return retVal;
- }
-
- public static final String getProviderNameForId(ContentResolver cr, long providerId) {
- Cursor cursor = cr.query(CONTENT_URI,
- PROVIDER_PROJECTION,
- _ID + "=" + providerId,
- null, null);
-
- String retVal = null;
- try {
- if (cursor.moveToFirst()) {
- retVal = cursor.getString(cursor.getColumnIndexOrThrow(NAME));
- }
- } finally {
- cursor.close();
- }
-
- return retVal;
- }
-
- private static final String[] PROVIDER_PROJECTION = new String[] {
- _ID,
- NAME
- };
-
- public static final String ACTIVE_ACCOUNT_ID = "account_id";
- public static final String ACTIVE_ACCOUNT_USERNAME = "account_username";
- public static final String ACTIVE_ACCOUNT_PW = "account_pw";
- public static final String ACTIVE_ACCOUNT_LOCKED = "account_locked";
- public static final String ACCOUNT_PRESENCE_STATUS = "account_presenceStatus";
- public static final String ACCOUNT_CONNECTION_STATUS = "account_connStatus";
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://im/providers");
-
- public static final Uri CONTENT_URI_WITH_ACCOUNT =
- Uri.parse("content://im/providers/account");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * people.
- */
- public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-providers";
-
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-providers";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "name ASC";
- }
-
- /**
- * The columns for IM accounts. There can be more than one account for each IM provider.
- */
- public interface AccountColumns {
- /**
- * The name of the account
- * <P>Type: TEXT</P>
- */
- String NAME = "name";
-
- /**
- * The IM provider for this account
- * <P>Type: INTEGER</P>
- */
- String PROVIDER = "provider";
-
- /**
- * The username for this account
- * <P>Type: TEXT</P>
- */
- String USERNAME = "username";
-
- /**
- * The password for this account
- * <P>Type: TEXT</P>
- */
- String PASSWORD = "pw";
-
- /**
- * A boolean value indicates if the account is active.
- * <P>Type: INTEGER</P>
- */
- String ACTIVE = "active";
-
- /**
- * A boolean value indicates if the account is locked (not editable)
- * <P>Type: INTEGER</P>
- */
- String LOCKED = "locked";
-
- /**
- * A boolean value to indicate whether this account is kept signed in.
- * <P>Type: INTEGER</P>
- */
- String KEEP_SIGNED_IN = "keep_signed_in";
-
- /**
- * A boolean value indiciating the last login state for this account
- * <P>Type: INTEGER</P>
- */
- String LAST_LOGIN_STATE = "last_login_state";
- }
-
- /**
- * This table contains the IM accounts.
- */
- public static final class Account implements BaseColumns, AccountColumns {
- private Account() {}
-
- public static final long getProviderIdForAccount(ContentResolver cr, long accountId) {
- Cursor cursor = cr.query(CONTENT_URI,
- PROVIDER_PROJECTION,
- _ID + "=" + accountId,
- null /* selection args */,
- null /* sort order */);
-
- long providerId = 0;
-
- try {
- if (cursor.moveToFirst()) {
- providerId = cursor.getLong(PROVIDER_COLUMN);
- }
- } finally {
- cursor.close();
- }
-
- return providerId;
- }
-
- private static final String[] PROVIDER_PROJECTION = new String[] { PROVIDER };
- private static final int PROVIDER_COLUMN = 0;
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://im/accounts");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * account.
- */
- public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-accounts";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * account.
- */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-accounts";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "name ASC";
-
- }
-
- /**
- * Connection status
- */
- public interface ConnectionStatus {
- /**
- * The connection is offline, not logged in.
- */
- int OFFLINE = 0;
-
- /**
- * The connection is attempting to connect.
- */
- int CONNECTING = 1;
-
- /**
- * The connection is suspended due to network not available.
- */
- int SUSPENDED = 2;
-
- /**
- * The connection is logged in and online.
- */
- int ONLINE = 3;
- }
-
- public interface AccountStatusColumns {
- /**
- * account id
- * <P>Type: INTEGER</P>
- */
- String ACCOUNT = "account";
-
- /**
- * User's presence status, see definitions in {#link CommonPresenceColumn}
- * <P>Type: INTEGER</P>
- */
- String PRESENCE_STATUS = "presenceStatus";
-
- /**
- * The connection status of this account, see {#link ConnectionStatus}
- * <P>Type: INTEGER</P>
- */
- String CONNECTION_STATUS = "connStatus";
- }
-
- public static final class AccountStatus implements BaseColumns, AccountStatusColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://im/accountStatus");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of account status.
- */
- public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-account-status";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single account status.
- */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-account-status";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "name ASC";
- }
-
- /**
- * Columns from the Contacts table.
- */
- public interface ContactsColumns {
- /**
- * The username
- * <P>Type: TEXT</P>
- */
- String USERNAME = "username";
-
- /**
- * The nickname or display name
- * <P>Type: TEXT</P>
- */
- String NICKNAME = "nickname";
-
- /**
- * The IM provider for this contact
- * <P>Type: INTEGER</P>
- */
- String PROVIDER = "provider";
-
- /**
- * The account (within a IM provider) for this contact
- * <P>Type: INTEGER</P>
- */
- String ACCOUNT = "account";
-
- /**
- * The contactList this contact belongs to
- * <P>Type: INTEGER</P>
- */
- String CONTACTLIST = "contactList";
-
- /**
- * Contact type
- * <P>Type: INTEGER</P>
- */
- String TYPE = "type";
-
- /**
- * normal IM contact
- */
- int TYPE_NORMAL = 0;
- /**
- * temporary contact, someone not in the list of contacts that we
- * subscribe presence for. Usually created because of the user is
- * having a chat session with this contact.
- */
- int TYPE_TEMPORARY = 1;
- /**
- * temporary contact created for group chat.
- */
- int TYPE_GROUP = 2;
- /**
- * blocked contact.
- */
- int TYPE_BLOCKED = 3;
- /**
- * the contact is hidden. The client should always display this contact to the user.
- */
- int TYPE_HIDDEN = 4;
- /**
- * the contact is pinned. The client should always display this contact to the user.
- */
- int TYPE_PINNED = 5;
-
- /**
- * Contact subscription status
- * <P>Type: INTEGER</P>
- */
- String SUBSCRIPTION_STATUS = "subscriptionStatus";
-
- /**
- * no pending subscription
- */
- int SUBSCRIPTION_STATUS_NONE = 0;
- /**
- * requested to subscribe
- */
- int SUBSCRIPTION_STATUS_SUBSCRIBE_PENDING = 1;
- /**
- * requested to unsubscribe
- */
- int SUBSCRIPTION_STATUS_UNSUBSCRIBE_PENDING = 2;
-
- /**
- * Contact subscription type
- * <P>Type: INTEGER </P>
- */
- String SUBSCRIPTION_TYPE = "subscriptionType";
-
- /**
- * The user and contact have no interest in each other's presence.
- */
- int SUBSCRIPTION_TYPE_NONE = 0;
- /**
- * The user wishes to stop receiving presence updates from the contact.
- */
- int SUBSCRIPTION_TYPE_REMOVE = 1;
- /**
- * The user is interested in receiving presence updates from the contact.
- */
- int SUBSCRIPTION_TYPE_TO = 2;
- /**
- * The contact is interested in receiving presence updates from the user.
- */
- int SUBSCRIPTION_TYPE_FROM = 3;
- /**
- * The user and contact have a mutual interest in each other's presence.
- */
- int SUBSCRIPTION_TYPE_BOTH = 4;
- /**
- * This is a special type reserved for pending subscription requests
- */
- int SUBSCRIPTION_TYPE_INVITATIONS = 5;
-
- /**
- * Quick Contact: derived from Google Contact Extension's "message_count" attribute.
- * <P>Type: INTEGER</P>
- */
- String QUICK_CONTACT = "qc";
-
- /**
- * Google Contact Extension attribute
- *
- * Rejected: a boolean value indicating whether a subscription request from
- * this client was ever rejected by the user. "true" indicates that it has.
- * This is provided so that a client can block repeated subscription requests.
- * <P>Type: INTEGER</P>
- */
- String REJECTED = "rejected";
-
- /**
- * Off The Record status: 0 for disabled, 1 for enabled
- * <P>Type: INTEGER </P>
- */
- String OTR = "otr";
- }
-
- /**
- * This defines the different type of values of {@link ContactsColumns#OTR}
- */
- public interface OffTheRecordType {
- /*
- * Off the record not turned on
- */
- int DISABLED = 0;
- /**
- * Off the record turned on, but we don't know who turned it on
- */
- int ENABLED = 1;
- /**
- * Off the record turned on by the user
- */
- int ENABLED_BY_USER = 2;
- /**
- * Off the record turned on by the buddy
- */
- int ENABLED_BY_BUDDY = 3;
- };
-
- /**
- * This table contains contacts.
- */
- public static final class Contacts implements BaseColumns,
- ContactsColumns, PresenceColumns, ChatsColumns {
- /**
- * no public constructor since this is a utility class
- */
- private Contacts() {}
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://im/contacts");
-
- /**
- * The content:// style URL for contacts joined with presence
- */
- public static final Uri CONTENT_URI_WITH_PRESENCE =
- Uri.parse("content://im/contactsWithPresence");
-
- /**
- * The content:// style URL for barebone contacts, not joined with any other table
- */
- public static final Uri CONTENT_URI_CONTACTS_BAREBONE =
- Uri.parse("content://im/contactsBarebone");
-
- /**
- * The content:// style URL for contacts who have an open chat session
- */
- public static final Uri CONTENT_URI_CHAT_CONTACTS =
- Uri.parse("content://im/contacts/chatting");
-
- /**
- * The content:// style URL for contacts who have been blocked
- */
- public static final Uri CONTENT_URI_BLOCKED_CONTACTS =
- Uri.parse("content://im/contacts/blocked");
-
- /**
- * The content:// style URL for contacts by provider and account
- */
- public static final Uri CONTENT_URI_CONTACTS_BY =
- Uri.parse("content://im/contacts");
-
- /**
- * The content:// style URL for contacts by provider and account,
- * and who have an open chat session
- */
- public static final Uri CONTENT_URI_CHAT_CONTACTS_BY =
- Uri.parse("content://im/contacts/chatting");
-
- /**
- * The content:// style URL for contacts by provider and account,
- * and who are online
- */
- public static final Uri CONTENT_URI_ONLINE_CONTACTS_BY =
- Uri.parse("content://im/contacts/online");
-
- /**
- * The content:// style URL for contacts by provider and account,
- * and who are offline
- */
- public static final Uri CONTENT_URI_OFFLINE_CONTACTS_BY =
- Uri.parse("content://im/contacts/offline");
-
- /**
- * The content:// style URL for operations on bulk contacts
- */
- public static final Uri BULK_CONTENT_URI =
- Uri.parse("content://im/bulk_contacts");
-
- /**
- * The content:// style URL for the count of online contacts in each
- * contact list by provider and account.
- */
- public static final Uri CONTENT_URI_ONLINE_COUNT =
- Uri.parse("content://im/contacts/onlineCount");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * people.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-contacts";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * person.
- */
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im-contacts";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER =
- "subscriptionType DESC, last_message_date DESC," +
- " mode DESC, nickname COLLATE UNICODE ASC";
-
- public static final String CHATS_CONTACT = "chats_contact";
-
- public static final String AVATAR_HASH = "avatars_hash";
-
- public static final String AVATAR_DATA = "avatars_data";
- }
-
- /**
- * Columns from the ContactList table.
- */
- public interface ContactListColumns {
- String NAME = "name";
- String PROVIDER = "provider";
- String ACCOUNT = "account";
- }
-
- /**
- * This table contains the contact lists.
- */
- public static final class ContactList implements BaseColumns,
- ContactListColumns {
- private ContactList() {}
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://im/contactLists");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * people.
- */
- public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-contactLists";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * person.
- */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-contactLists";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "name COLLATE UNICODE ASC";
-
- public static final String PROVIDER_NAME = "provider_name";
-
- public static final String ACCOUNT_NAME = "account_name";
- }
-
- /**
- * Columns from the BlockedList table.
- */
- public interface BlockedListColumns {
- /**
- * The username of the blocked contact.
- * <P>Type: TEXT</P>
- */
- String USERNAME = "username";
-
- /**
- * The nickname of the blocked contact.
- * <P>Type: TEXT</P>
- */
- String NICKNAME = "nickname";
-
- /**
- * The provider id of the blocked contact.
- * <P>Type: INT</P>
- */
- String PROVIDER = "provider";
-
- /**
- * The account id of the blocked contact.
- * <P>Type: INT</P>
- */
- String ACCOUNT = "account";
- }
-
- /**
- * This table contains blocked lists
- */
- public static final class BlockedList implements BaseColumns, BlockedListColumns {
- private BlockedList() {}
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://im/blockedList");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * people.
- */
- public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-blockedList";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * person.
- */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-blockedList";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "nickname ASC";
-
- public static final String PROVIDER_NAME = "provider_name";
-
- public static final String ACCOUNT_NAME = "account_name";
-
- public static final String AVATAR_DATA = "avatars_data";
- }
-
- /**
- * Columns from the contactsEtag table
- */
- public interface ContactsEtagColumns {
- /**
- * The roster etag, computed by the server, stored on the client. There is one etag
- * per account roster.
- * <P>Type: TEXT</P>
- */
- String ETAG = "etag";
-
- /**
- * The OTR etag, computed by the server, stored on the client. There is one OTR etag
- * per account roster.
- * <P>Type: TEXT</P>
- */
- String OTR_ETAG = "otr_etag";
-
- /**
- * The account id for the etag.
- * <P> Type: INTEGER </P>
- */
- String ACCOUNT = "account";
- }
-
- public static final class ContactsEtag implements BaseColumns, ContactsEtagColumns {
- private ContactsEtag() {}
-
- public static final Cursor query(ContentResolver cr,
- String[] projection) {
- return cr.query(CONTENT_URI, projection, null, null, null);
- }
-
- public static final Cursor query(ContentResolver cr,
- String[] projection, String where, String orderBy) {
- return cr.query(CONTENT_URI, projection, where,
- null, orderBy == null ? null : orderBy);
- }
-
- public static final String getRosterEtag(ContentResolver resolver, long accountId) {
- String retVal = null;
-
- Cursor c = resolver.query(CONTENT_URI,
- CONTACT_ETAG_PROJECTION,
- ACCOUNT + "=" + accountId,
- null /* selection args */,
- null /* sort order */);
-
- try {
- if (c.moveToFirst()) {
- retVal = c.getString(COLUMN_ETAG);
- }
- } finally {
- c.close();
- }
-
- return retVal;
- }
-
- public static final String getOtrEtag(ContentResolver resolver, long accountId) {
- String retVal = null;
-
- Cursor c = resolver.query(CONTENT_URI,
- CONTACT_OTR_ETAG_PROJECTION,
- ACCOUNT + "=" + accountId,
- null /* selection args */,
- null /* sort order */);
-
- try {
- if (c.moveToFirst()) {
- retVal = c.getString(COLUMN_OTR_ETAG);
- }
- } finally {
- c.close();
- }
-
- return retVal;
- }
-
- private static final String[] CONTACT_ETAG_PROJECTION = new String[] {
- Im.ContactsEtag.ETAG // 0
- };
-
- private static int COLUMN_ETAG = 0;
-
- private static final String[] CONTACT_OTR_ETAG_PROJECTION = new String[] {
- Im.ContactsEtag.OTR_ETAG // 0
- };
-
- private static int COLUMN_OTR_ETAG = 0;
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://im/contactsEtag");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * people.
- */
- public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-contactsEtag";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * person.
- */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-contactsEtag";
- }
-
- /**
- * Message type definition
- */
- public interface MessageType {
- /* sent message */
- int OUTGOING = 0;
- /* received message */
- int INCOMING = 1;
- /* presence became available */
- int PRESENCE_AVAILABLE = 2;
- /* presence became away */
- int PRESENCE_AWAY = 3;
- /* presence became DND (busy) */
- int PRESENCE_DND = 4;
- /* presence became unavailable */
- int PRESENCE_UNAVAILABLE = 5;
- /* the message is converted to a group chat */
- int CONVERT_TO_GROUPCHAT = 6;
- /* generic status */
- int STATUS = 7;
- /* the message cannot be sent now, but will be sent later */
- int POSTPONED = 8;
- /* off The Record status is turned off */
- int OTR_IS_TURNED_OFF = 9;
- /* off the record status is turned on */
- int OTR_IS_TURNED_ON = 10;
- /* off the record status turned on by user */
- int OTR_TURNED_ON_BY_USER = 11;
- /* off the record status turned on by buddy */
- int OTR_TURNED_ON_BY_BUDDY = 12;
- }
-
- /**
- * The common columns for both one-to-one chat messages or group chat messages.
- */
- public interface BaseMessageColumns {
- /**
- * The user this message belongs to
- * <P>Type: TEXT</P>
- */
- String CONTACT = "contact";
-
- /**
- * The body
- * <P>Type: TEXT</P>
- */
- String BODY = "body";
-
- /**
- * The date this message is sent or received
- * <P>Type: INTEGER</P>
- */
- String DATE = "date";
-
- /**
- * Message Type, see {@link MessageType}
- * <P>Type: INTEGER</P>
- */
- String TYPE = "type";
-
- /**
- * Error Code: 0 means no error.
- * <P>Type: INTEGER </P>
- */
- String ERROR_CODE = "err_code";
-
- /**
- * Error Message
- * <P>Type: TEXT</P>
- */
- String ERROR_MESSAGE = "err_msg";
-
- /**
- * Packet ID, auto assigned by the GTalkService for outgoing messages or the
- * GTalk server for incoming messages. The packet id field is optional for messages,
- * so it could be null.
- * <P>Type: STRING</P>
- */
- String PACKET_ID = "packet_id";
- }
-
- /**
- * Columns from the Messages table.
- */
- public interface MessagesColumns extends BaseMessageColumns{
- /**
- * The provider id
- * <P> Type: INTEGER </P>
- */
- String PROVIDER = "provider";
-
- /**
- * The account id
- * <P> Type: INTEGER </P>
- */
- String ACCOUNT = "account";
- }
-
- /**
- * This table contains messages.
- */
- public static final class Messages implements BaseColumns, MessagesColumns {
- /**
- * no public constructor since this is a utility class
- */
- private Messages() {}
-
- /**
- * Gets the Uri to query messages by contact.
- *
- * @param providerId the provider id of the contact.
- * @param accountId the account id of the contact.
- * @param username the user name of the contact.
- * @return the Uri
- */
- public static final Uri getContentUriByContact(long providerId,
- long accountId, String username) {
- Uri.Builder builder = CONTENT_URI_MESSAGES_BY.buildUpon();
- ContentUris.appendId(builder, providerId);
- ContentUris.appendId(builder, accountId);
- builder.appendPath(username);
- return builder.build();
- }
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://im/messages");
-
- /**
- * The content:// style URL for messages by provider and account
- */
- public static final Uri CONTENT_URI_MESSAGES_BY =
- Uri.parse("content://im/messagesBy");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * people.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-messages";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * person.
- */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-messages";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "date ASC";
-
- }
-
- /**
- * Columns for the GroupMember table.
- */
- public interface GroupMemberColumns {
- /**
- * The id of the group this member belongs to.
- * <p>Type: INTEGER</p>
- */
- String GROUP = "groupId";
-
- /**
- * The full name of this member.
- * <p>Type: TEXT</p>
- */
- String USERNAME = "username";
-
- /**
- * The nick name of this member.
- * <p>Type: TEXT</p>
- */
- String NICKNAME = "nickname";
- }
-
- public final static class GroupMembers implements GroupMemberColumns {
- private GroupMembers(){}
-
- public static final Uri CONTENT_URI =
- Uri.parse("content://im/groupMembers");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * group members.
- */
- public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-groupMembers";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * group member.
- */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-groupMembers";
- }
-
- /**
- * Columns from the Invitation table.
- */
- public interface InvitationColumns {
- /**
- * The provider id.
- * <p>Type: INTEGER</p>
- */
- String PROVIDER = "providerId";
-
- /**
- * The account id.
- * <p>Type: INTEGER</p>
- */
- String ACCOUNT = "accountId";
-
- /**
- * The invitation id.
- * <p>Type: TEXT</p>
- */
- String INVITE_ID = "inviteId";
-
- /**
- * The name of the sender of the invitation.
- * <p>Type: TEXT</p>
- */
- String SENDER = "sender";
-
- /**
- * The name of the group which the sender invite you to join.
- * <p>Type: TEXT</p>
- */
- String GROUP_NAME = "groupName";
-
- /**
- * A note
- * <p>Type: TEXT</p>
- */
- String NOTE = "note";
-
- /**
- * The current status of the invitation.
- * <p>Type: TEXT</p>
- */
- String STATUS = "status";
-
- int STATUS_PENDING = 0;
- int STATUS_ACCEPTED = 1;
- int STATUS_REJECTED = 2;
- }
-
- /**
- * This table contains the invitations received from others.
- */
- public final static class Invitation implements InvitationColumns,
- BaseColumns {
- private Invitation() {
- }
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://im/invitations");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * invitations.
- */
- public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/im-invitations";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * invitation.
- */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-invitations";
- }
-
- /**
- * Columns from the GroupMessages table
- */
- public interface GroupMessageColumns extends BaseMessageColumns {
- /**
- * The group this message belongs to
- * <p>Type: TEXT</p>
- */
- String GROUP = "groupId";
- }
-
- /**
- * This table contains group messages.
- */
- public final static class GroupMessages implements BaseColumns,
- GroupMessageColumns {
- private GroupMessages() {}
-
- /**
- * Gets the Uri to query group messages by group.
- *
- * @param groupId the group id.
- * @return the Uri
- */
- public static final Uri getContentUriByGroup(long groupId) {
- Uri.Builder builder = CONTENT_URI_GROUP_MESSAGES_BY.buildUpon();
- ContentUris.appendId(builder, groupId);
- return builder.build();
- }
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://im/groupMessages");
-
- /**
- * The content:// style URL for group messages by provider and account
- */
- public static final Uri CONTENT_URI_GROUP_MESSAGES_BY =
- Uri.parse("content://im/groupMessagesBy");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * group messages.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-groupMessages";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * group message.
- */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-groupMessages";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "date ASC";
- }
-
- /**
- * Columns from the Avatars table
- */
- public interface AvatarsColumns {
- /**
- * The contact this avatar belongs to
- * <P>Type: TEXT</P>
- */
- String CONTACT = "contact";
-
- String PROVIDER = "provider_id";
-
- String ACCOUNT = "account_id";
-
- /**
- * The hash of the image data
- * <P>Type: TEXT</P>
- */
- String HASH = "hash";
-
- /**
- * raw image data
- * <P>Type: BLOB</P>
- */
- String DATA = "data";
- }
-
- /**
- * This table contains avatars.
- */
- public static final class Avatars implements BaseColumns, AvatarsColumns {
- /**
- * no public constructor since this is a utility class
- */
- private Avatars() {}
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI = Uri.parse("content://im/avatars");
-
- /**
- * The content:// style URL for avatars by provider, account and contact
- */
- public static final Uri CONTENT_URI_AVATARS_BY =
- Uri.parse("content://im/avatarsBy");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing the avatars
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-avatars";
-
- /**
- * The MIME type of a {@link #CONTENT_URI}
- */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/im-avatars";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "contact ASC";
-
- }
-
- /**
- * Common presence columns shared between the IM and contacts presence tables
- */
- public interface CommonPresenceColumns {
- /**
- * The priority, an integer, used by XMPP presence
- * <P>Type: INTEGER</P>
- */
- String PRIORITY = "priority";
-
- /**
- * The server defined status.
- * <P>Type: INTEGER (one of the values below)</P>
- */
- String PRESENCE_STATUS = "mode";
-
- /**
- * Presence Status definition
- */
- int OFFLINE = 0;
- int INVISIBLE = 1;
- int AWAY = 2;
- int IDLE = 3;
- int DO_NOT_DISTURB = 4;
- int AVAILABLE = 5;
-
- /**
- * The user defined status line.
- * <P>Type: TEXT</P>
- */
- String PRESENCE_CUSTOM_STATUS = "status";
- }
-
- /**
- * Columns from the Presence table.
- */
- public interface PresenceColumns extends CommonPresenceColumns {
- /**
- * The contact id
- * <P>Type: INTEGER</P>
- */
- String CONTACT_ID = "contact_id";
-
- /**
- * The contact's JID resource, only relevant for XMPP contact
- * <P>Type: TEXT</P>
- */
- String JID_RESOURCE = "jid_resource";
-
- /**
- * The contact's client type
- */
- String CLIENT_TYPE = "client_type";
-
- /**
- * client type definitions
- */
- int CLIENT_TYPE_DEFAULT = 0;
- int CLIENT_TYPE_MOBILE = 1;
- int CLIENT_TYPE_ANDROID = 2;
- }
-
- /**
- * Contains presence infomation for contacts.
- */
- public static final class Presence implements BaseColumns, PresenceColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI = Uri.parse("content://im/presence");
-
- /**
- * The content URL for IM presences for an account
- */
- public static final Uri CONTENT_URI_BY_ACCOUNT = Uri.parse("content://im/presence/account");
-
- /**
- * The content:// style URL for operations on bulk contacts
- */
- public static final Uri BULK_CONTENT_URI = Uri.parse("content://im/bulk_presence");
-
- /**
- * The content:// style URL for seeding presences for a given account id.
- */
- public static final Uri SEED_PRESENCE_BY_ACCOUNT_CONTENT_URI =
- Uri.parse("content://im/seed_presence/account");
-
- /**
- * The MIME type of a {@link #CONTENT_URI} providing a directory of presence
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-presence";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "mode DESC";
- }
-
- /**
- * Columns from the Chats table.
- */
- public interface ChatsColumns {
- /**
- * The contact ID this chat belongs to. The value is a long.
- * <P>Type: INT</P>
- */
- String CONTACT_ID = "contact_id";
-
- /**
- * The GTalk JID resource. The value is a string.
- * <P>Type: TEXT</P>
- */
- String JID_RESOURCE = "jid_resource";
-
- /**
- * Whether this is a groupchat or not.
- * <P>Type: INT</P>
- */
- String GROUP_CHAT = "groupchat";
-
- /**
- * The last unread message. This both indicates that there is an
- * unread message, and what the message is.
- * <P>Type: TEXT</P>
- */
- String LAST_UNREAD_MESSAGE = "last_unread_message";
-
- /**
- * The last message timestamp
- * <P>Type: INT</P>
- */
- String LAST_MESSAGE_DATE = "last_message_date";
-
- /**
- * A message that is being composed. This indicates that there was a
- * message being composed when the chat screen was shutdown, and what the
- * message is.
- * <P>Type: TEXT</P>
- */
- String UNSENT_COMPOSED_MESSAGE = "unsent_composed_message";
-
- /**
- * A value from 0-9 indicating which quick-switch chat screen slot this
- * chat is occupying. If none (for instance, this is the 12th active chat)
- * then the value is -1.
- * <P>Type: INT</P>
- */
- String SHORTCUT = "shortcut";
- }
-
- /**
- * Contains ongoing chat sessions.
- */
- public static final class Chats implements BaseColumns, ChatsColumns {
- /**
- * no public constructor since this is a utility class
- */
- private Chats() {}
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://im/chats");
-
- /**
- * The content URL for all chats that belong to the account
- */
- public static final Uri CONTENT_URI_BY_ACCOUNT = Uri.parse("content://im/chats/account");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of chats.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/im-chats";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single chat.
- */
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im-chats";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "last_message_date ASC";
- }
-
- /**
- * Columns from session cookies table. Used for IMPS.
- */
- public static interface SessionCookiesColumns {
- String NAME = "name";
- String VALUE = "value";
- String PROVIDER = "provider";
- String ACCOUNT = "account";
- }
-
- /**
- * Contains IMPS session cookies.
- */
- public static class SessionCookies implements SessionCookiesColumns, BaseColumns {
- private SessionCookies() {
- }
-
- /**
- * The content:// style URI for this table
- */
- public static final Uri CONTENT_URI = Uri.parse("content://im/sessionCookies");
-
- /**
- * The content:// style URL for session cookies by provider and account
- */
- public static final Uri CONTENT_URI_SESSION_COOKIES_BY =
- Uri.parse("content://im/sessionCookiesBy");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * people.
- */
- public static final String CONTENT_TYPE = "vnd.android-dir/im-sessionCookies";
- }
-
- /**
- * Columns from ProviderSettings table
- */
- public static interface ProviderSettingsColumns {
- /**
- * The id in database of the related provider
- *
- * <P>Type: INT</P>
- */
- String PROVIDER = "provider";
-
- /**
- * The name of the setting
- * <P>Type: TEXT</P>
- */
- String NAME = "name";
-
- /**
- * The value of the setting
- * <P>Type: TEXT</P>
- */
- String VALUE = "value";
- }
-
- public static class ProviderSettings implements ProviderSettingsColumns {
- private ProviderSettings() {
- }
-
- /**
- * The content:// style URI for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://im/providerSettings");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing provider settings
- */
- public static final String CONTENT_TYPE = "vnd.android-dir/im-providerSettings";
-
- /**
- * A boolean value to indicate whether this provider should show the offline contacts
- */
- public static final String SHOW_OFFLINE_CONTACTS = "show_offline_contacts";
-
- /** controls whether or not the GTalk service automatically connect to server. */
- public static final String SETTING_AUTOMATICALLY_CONNECT_GTALK = "gtalk_auto_connect";
-
- /** controls whether or not the IM service will be automatically started after boot */
- public static final String SETTING_AUTOMATICALLY_START_SERVICE = "auto_start_service";
-
- /** controls whether or not the offline contacts will be hided */
- public static final String SETTING_HIDE_OFFLINE_CONTACTS = "hide_offline_contacts";
-
- /** controls whether or not enable the IM notification */
- public static final String SETTING_ENABLE_NOTIFICATION = "enable_notification";
-
- /** specifies whether or not to vibrate */
- public static final String SETTING_VIBRATE = "vibrate";
-
- /** specifies the Uri string of the ringtone */
- public static final String SETTING_RINGTONE = "ringtone";
-
- /** specifies the Uri of the default ringtone */
- public static final String SETTING_RINGTONE_DEFAULT =
- "content://settings/system/notification_sound";
-
- /** specifies whether or not to show mobile indicator to friends */
- public static final String SETTING_SHOW_MOBILE_INDICATOR = "mobile_indicator";
-
- /**
- * Used for reliable message queue (RMQ). This is for storing the last rmq id received
- * from the GTalk server
- */
- public static final String LAST_RMQ_RECEIVED = "last_rmq_rec";
-
- /**
- * Query the settings of the provider specified by id
- *
- * @param cr
- * the relative content resolver
- * @param providerId
- * the specified id of provider
- * @return a HashMap which contains all the settings for the specified
- * provider
- */
- public static HashMap<String, String> queryProviderSettings(ContentResolver cr,
- long providerId) {
- HashMap<String, String> settings = new HashMap<String, String>();
-
- String[] projection = { NAME, VALUE };
- Cursor c = cr.query(ContentUris.withAppendedId(CONTENT_URI, providerId), projection, null, null, null);
- if (c == null) {
- return null;
- }
-
- while(c.moveToNext()) {
- settings.put(c.getString(0), c.getString(1));
- }
-
- c.close();
-
- return settings;
- }
-
- /**
- * Get the string value of setting which is specified by provider id and the setting name.
- *
- * @param cr The ContentResolver to use to access the settings table.
- * @param providerId The id of the provider.
- * @param settingName The name of the setting.
- * @return The value of the setting if the setting exist, otherwise return null.
- */
- public static String getStringValue(ContentResolver cr, long providerId, String settingName) {
- String ret = null;
- Cursor c = getSettingValue(cr, providerId, settingName);
- if (c != null) {
- ret = c.getString(0);
- c.close();
- }
-
- return ret;
- }
-
- /**
- * Get the boolean value of setting which is specified by provider id and the setting name.
- *
- * @param cr The ContentResolver to use to access the settings table.
- * @param providerId The id of the provider.
- * @param settingName The name of the setting.
- * @return The value of the setting if the setting exist, otherwise return false.
- */
- public static boolean getBooleanValue(ContentResolver cr, long providerId, String settingName) {
- boolean ret = false;
- Cursor c = getSettingValue(cr, providerId, settingName);
- if (c != null) {
- ret = c.getInt(0) != 0;
- c.close();
- }
- return ret;
- }
-
- private static Cursor getSettingValue(ContentResolver cr, long providerId, String settingName) {
- Cursor c = cr.query(ContentUris.withAppendedId(CONTENT_URI, providerId), new String[]{VALUE}, NAME + "=?",
- new String[]{settingName}, null);
- if (c != null) {
- if (!c.moveToFirst()) {
- c.close();
- return null;
- }
- }
- return c;
- }
-
- /**
- * Save a long value of setting in the table providerSetting.
- *
- * @param cr The ContentProvider used to access the providerSetting table.
- * @param providerId The id of the provider.
- * @param name The name of the setting.
- * @param value The value of the setting.
- */
- public static void putLongValue(ContentResolver cr, long providerId, String name,
- long value) {
- ContentValues v = new ContentValues(3);
- v.put(PROVIDER, providerId);
- v.put(NAME, name);
- v.put(VALUE, value);
-
- cr.insert(CONTENT_URI, v);
- }
-
- /**
- * Save a boolean value of setting in the table providerSetting.
- *
- * @param cr The ContentProvider used to access the providerSetting table.
- * @param providerId The id of the provider.
- * @param name The name of the setting.
- * @param value The value of the setting.
- */
- public static void putBooleanValue(ContentResolver cr, long providerId, String name,
- boolean value) {
- ContentValues v = new ContentValues(3);
- v.put(PROVIDER, providerId);
- v.put(NAME, name);
- v.put(VALUE, Boolean.toString(value));
-
- cr.insert(CONTENT_URI, v);
- }
-
- /**
- * Save a string value of setting in the table providerSetting.
- *
- * @param cr The ContentProvider used to access the providerSetting table.
- * @param providerId The id of the provider.
- * @param name The name of the setting.
- * @param value The value of the setting.
- */
- public static void putStringValue(ContentResolver cr, long providerId, String name,
- String value) {
- ContentValues v = new ContentValues(3);
- v.put(PROVIDER, providerId);
- v.put(NAME, name);
- v.put(VALUE, value);
-
- cr.insert(CONTENT_URI, v);
- }
-
- /**
- * A convenience method to set whether or not the GTalk service should be started
- * automatically.
- *
- * @param contentResolver The ContentResolver to use to access the settings table
- * @param autoConnect Whether the GTalk service should be started automatically.
- */
- public static void setAutomaticallyConnectGTalk(ContentResolver contentResolver,
- long providerId, boolean autoConnect) {
- putBooleanValue(contentResolver, providerId, SETTING_AUTOMATICALLY_CONNECT_GTALK,
- autoConnect);
- }
-
- /**
- * A convenience method to set whether or not the offline contacts should be hided
- *
- * @param contentResolver The ContentResolver to use to access the setting table
- * @param hideOfflineContacts Whether the offline contacts should be hided
- */
- public static void setHideOfflineContacts(ContentResolver contentResolver,
- long providerId, boolean hideOfflineContacts) {
- putBooleanValue(contentResolver, providerId, SETTING_HIDE_OFFLINE_CONTACTS,
- hideOfflineContacts);
- }
-
- /**
- * A convenience method to set whether or not enable the IM notification.
- *
- * @param contentResolver The ContentResolver to use to access the setting table.
- * @param enable Whether enable the IM notification
- */
- public static void setEnableNotification(ContentResolver contentResolver, long providerId,
- boolean enable) {
- putBooleanValue(contentResolver, providerId, SETTING_ENABLE_NOTIFICATION, enable);
- }
-
- /**
- * A convenience method to set whether or not to vibrate.
- *
- * @param contentResolver The ContentResolver to use to access the setting table.
- * @param vibrate Whether or not to vibrate
- */
- public static void setVibrate(ContentResolver contentResolver, long providerId,
- boolean vibrate) {
- putBooleanValue(contentResolver, providerId, SETTING_VIBRATE, vibrate);
- }
-
- /**
- * A convenience method to set the Uri String of the ringtone.
- *
- * @param contentResolver The ContentResolver to use to access the setting table.
- * @param ringtoneUri The Uri String of the ringtone to be set.
- */
- public static void setRingtoneURI(ContentResolver contentResolver, long providerId,
- String ringtoneUri) {
- putStringValue(contentResolver, providerId, SETTING_RINGTONE, ringtoneUri);
- }
-
- /**
- * A convenience method to set whether or not to show mobile indicator.
- *
- * @param contentResolver The ContentResolver to use to access the setting table.
- * @param showMobileIndicator Whether or not to show mobile indicator.
- */
- public static void setShowMobileIndicator(ContentResolver contentResolver, long providerId,
- boolean showMobileIndicator) {
- putBooleanValue(contentResolver, providerId, SETTING_SHOW_MOBILE_INDICATOR,
- showMobileIndicator);
- }
-
- public static class QueryMap extends ContentQueryMap {
- private ContentResolver mContentResolver;
- private long mProviderId;
-
- public QueryMap(ContentResolver contentResolver, long providerId, boolean keepUpdated,
- Handler handlerForUpdateNotifications) {
- super(contentResolver.query(CONTENT_URI,
- new String[] {NAME,VALUE},
- PROVIDER + "=" + providerId,
- null, // no selection args
- null), // no sort order
- NAME, keepUpdated, handlerForUpdateNotifications);
- mContentResolver = contentResolver;
- mProviderId = providerId;
- }
-
- /**
- * Set if the GTalk service should automatically connect to server.
- *
- * @param autoConnect if the GTalk service should auto connect to server.
- */
- public void setAutomaticallyConnectToGTalkServer(boolean autoConnect) {
- ProviderSettings.setAutomaticallyConnectGTalk(mContentResolver, mProviderId,
- autoConnect);
- }
-
- /**
- * Check if the GTalk service should automatically connect to server.
- * @return if the GTalk service should automatically connect to server.
- */
- public boolean getAutomaticallyConnectToGTalkServer() {
- return getBoolean(SETTING_AUTOMATICALLY_CONNECT_GTALK,
- true /* default to automatically sign in */);
- }
-
- /**
- * Set whether or not the offline contacts should be hided.
- *
- * @param hideOfflineContacts Whether or not the offline contacts should be hided.
- */
- public void setHideOfflineContacts(boolean hideOfflineContacts) {
- ProviderSettings.setHideOfflineContacts(mContentResolver, mProviderId,
- hideOfflineContacts);
- }
-
- /**
- * Check if the offline contacts should be hided.
- *
- * @return Whether or not the offline contacts should be hided.
- */
- public boolean getHideOfflineContacts() {
- return getBoolean(SETTING_HIDE_OFFLINE_CONTACTS,
- false/* by default not hide the offline contacts*/);
- }
-
- /**
- * Set whether or not enable the IM notification.
- *
- * @param enable Whether or not enable the IM notification.
- */
- public void setEnableNotification(boolean enable) {
- ProviderSettings.setEnableNotification(mContentResolver, mProviderId, enable);
- }
-
- /**
- * Check if the IM notification is enabled.
- *
- * @return Whether or not enable the IM notification.
- */
- public boolean getEnableNotification() {
- return getBoolean(SETTING_ENABLE_NOTIFICATION,
- true/* by default enable the notification */);
- }
-
- /**
- * Set whether or not to vibrate on IM notification.
- *
- * @param vibrate Whether or not to vibrate.
- */
- public void setVibrate(boolean vibrate) {
- ProviderSettings.setVibrate(mContentResolver, mProviderId, vibrate);
- }
-
- /**
- * Gets whether or not to vibrate on IM notification.
- *
- * @return Whether or not to vibrate.
- */
- public boolean getVibrate() {
- return getBoolean(SETTING_VIBRATE, false /* by default disable vibrate */);
- }
-
- /**
- * Set the Uri for the ringtone.
- *
- * @param ringtoneUri The Uri of the ringtone to be set.
- */
- public void setRingtoneURI(String ringtoneUri) {
- ProviderSettings.setRingtoneURI(mContentResolver, mProviderId, ringtoneUri);
- }
-
- /**
- * Get the Uri String of the current ringtone.
- *
- * @return The Uri String of the current ringtone.
- */
- public String getRingtoneURI() {
- return getString(SETTING_RINGTONE, SETTING_RINGTONE_DEFAULT);
- }
-
- /**
- * Set whether or not to show mobile indicator to friends.
- *
- * @param showMobile whether or not to show mobile indicator.
- */
- public void setShowMobileIndicator(boolean showMobile) {
- ProviderSettings.setShowMobileIndicator(mContentResolver, mProviderId, showMobile);
- }
-
- /**
- * Gets whether or not to show mobile indicator.
- *
- * @return Whether or not to show mobile indicator.
- */
- public boolean getShowMobileIndicator() {
- return getBoolean(SETTING_SHOW_MOBILE_INDICATOR,
- true /* by default show mobile indicator */);
- }
-
- /**
- * Convenience function for retrieving a single settings value
- * as a boolean.
- *
- * @param name The name of the setting to retrieve.
- * @param def Value to return if the setting is not defined.
- * @return The setting's current value, or 'def' if it is not defined.
- */
- private boolean getBoolean(String name, boolean def) {
- ContentValues values = getValues(name);
- return values != null ? values.getAsBoolean(VALUE) : def;
- }
-
- /**
- * Convenience function for retrieving a single settings value
- * as a String.
- *
- * @param name The name of the setting to retrieve.
- * @param def The value to return if the setting is not defined.
- * @return The setting's current value or 'def' if it is not defined.
- */
- private String getString(String name, String def) {
- ContentValues values = getValues(name);
- return values != null ? values.getAsString(VALUE) : def;
- }
-
- /**
- * Convenience function for retrieving a single settings value
- * as an Integer.
- *
- * @param name The name of the setting to retrieve.
- * @param def The value to return if the setting is not defined.
- * @return The setting's current value or 'def' if it is not defined.
- */
- private int getInteger(String name, int def) {
- ContentValues values = getValues(name);
- return values != null ? values.getAsInteger(VALUE) : def;
- }
- }
-
- }
-
- /**
- * Columns from OutgoingRmq table
- */
- public interface OutgoingRmqColumns {
- String RMQ_ID = "rmq_id";
- String TYPE = "type";
- String TIMESTAMP = "ts";
- String DATA = "data";
- }
-
- /**
- * The table for storing outgoing rmq packets.
- */
- public static final class OutgoingRmq implements BaseColumns, OutgoingRmqColumns {
- private static String[] RMQ_ID_PROJECTION = new String[] {
- RMQ_ID,
- };
-
- /**
- * queryHighestRmqId
- *
- * @param resolver the content resolver
- * @return the highest rmq id assigned to the rmq packet, or 0 if there are no rmq packets
- * in the OutgoingRmq table.
- */
- public static final long queryHighestRmqId(ContentResolver resolver) {
- Cursor cursor = resolver.query(Im.OutgoingRmq.CONTENT_URI_FOR_HIGHEST_RMQ_ID,
- RMQ_ID_PROJECTION,
- null, // selection
- null, // selection args
- null // sort
- );
-
- long retVal = 0;
- try {
- //if (DBG) log("initializeRmqid: cursor.count= " + cursor.count());
-
- if (cursor.moveToFirst()) {
- retVal = cursor.getLong(cursor.getColumnIndexOrThrow(RMQ_ID));
- }
- } finally {
- cursor.close();
- }
-
- return retVal;
- }
-
- /**
- * The content:// style URL for this table.
- */
- public static final Uri CONTENT_URI = Uri.parse("content://im/outgoingRmqMessages");
-
- /**
- * The content:// style URL for the highest rmq id for the outgoing rmq messages
- */
- public static final Uri CONTENT_URI_FOR_HIGHEST_RMQ_ID =
- Uri.parse("content://im/outgoingHighestRmqId");
-
- /**
- * The default sort order for this table.
- */
- public static final String DEFAULT_SORT_ORDER = "rmq_id ASC";
- }
-
- /**
- * Columns for the LastRmqId table, which stores a single row for the last client rmq id
- * sent to the server.
- */
- public interface LastRmqIdColumns {
- String RMQ_ID = "rmq_id";
- }
-
- /**
- * The table for storing the last client rmq id sent to the server.
- */
- public static final class LastRmqId implements BaseColumns, LastRmqIdColumns {
- private static String[] PROJECTION = new String[] {
- RMQ_ID,
- };
-
- /**
- * queryLastRmqId
- *
- * queries the last rmq id saved in the LastRmqId table.
- *
- * @param resolver the content resolver.
- * @return the last rmq id stored in the LastRmqId table, or 0 if not found.
- */
- public static final long queryLastRmqId(ContentResolver resolver) {
- Cursor cursor = resolver.query(Im.LastRmqId.CONTENT_URI,
- PROJECTION,
- null, // selection
- null, // selection args
- null // sort
- );
-
- long retVal = 0;
- try {
- if (cursor.moveToFirst()) {
- retVal = cursor.getLong(cursor.getColumnIndexOrThrow(RMQ_ID));
- }
- } finally {
- cursor.close();
- }
-
- return retVal;
- }
-
- /**
- * saveLastRmqId
- *
- * saves the rmqId to the lastRmqId table. This will override the existing row if any,
- * as we only keep one row of data in this table.
- *
- * @param resolver the content resolver.
- * @param rmqId the rmq id to be saved.
- */
- public static final void saveLastRmqId(ContentResolver resolver, long rmqId) {
- ContentValues values = new ContentValues();
-
- // always replace the first row.
- values.put(_ID, 1);
- values.put(RMQ_ID, rmqId);
- resolver.insert(CONTENT_URI, values);
- }
-
- /**
- * The content:// style URL for this table.
- */
- public static final Uri CONTENT_URI = Uri.parse("content://im/lastRmqId");
- }
-}
diff --git a/core/java/android/provider/LiveFolders.java b/core/java/android/provider/LiveFolders.java
deleted file mode 100644
index 6e95fb7..0000000
--- a/core/java/android/provider/LiveFolders.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import android.annotation.SdkConstant;
-
-/**
- * <p>A LiveFolder is a special folder whose content is provided by a
- * {@link android.content.ContentProvider}. To create a live folder, two components
- * are required:</p>
- * <ul>
- * <li>An activity that can respond to the intent action {@link #ACTION_CREATE_LIVE_FOLDER}. The
- * activity is responsible for creating the live folder.</li>
- * <li>A {@link android.content.ContentProvider} to provide the live folder items.</li>
- * </ul>
- *
- * <h3>Lifecycle</h3>
- * <p>When a user wants to create a live folder, the system looks for all activities with the
- * intent filter action {@link #ACTION_CREATE_LIVE_FOLDER} and presents the list to the user.
- * When the user chooses one of the activities, the activity is invoked with the
- * {@link #ACTION_CREATE_LIVE_FOLDER} action. The activity then creates the live folder and
- * passes it back to the system by setting it as an
- * {@link android.app.Activity#setResult(int, android.content.Intent) activity result}. The
- * live folder is described by a content provider URI, a name, an icon and a display mode.
- * Finally, when the user opens the live folder, the system queries the content provider
- * to retrieve the folder's content.</p>
- *
- * <h3>Setting up the live folder activity</h3>
- * <p>The following code sample shows how to write an activity that creates a live fodler:</p>
- * <pre>
- * public static class MyLiveFolder extends Activity {
- * public static final Uri CONTENT_URI = Uri.parse("content://my.app/live");
- *
- * @Override
- * protected void onCreate(Bundle savedInstanceState) {
- * super.onCreate(savedInstanceState);
- *
- * final Intent intent = getIntent();
- * final String action = intent.getAction();
- *
- * if (LiveFolders.ACTION_CREATE_LIVE_FOLDER.equals(action)) {
- * setResult(RESULT_OK, createLiveFolder(this, CONTENT_URI, "My LiveFolder",
- * R.drawable.ic_launcher_contacts_phones));
- * } else {
- * setResult(RESULT_CANCELED);
- * }
- *
- * finish();
- * }
- *
- * private static Intent createLiveFolder(Context context, Uri uri, String name,
- * int icon) {
- *
- * final Intent intent = new Intent();
- *
- * intent.setData(uri);
- * intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, name);
- * intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON,
- * Intent.ShortcutIconResource.fromContext(context, icon));
- * intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE, LiveFolders.DISPLAY_MODE_LIST);
- *
- * return intent;
- * }
- * }
- * </pre>
- * <p>The live folder is described by an {@link android.content.Intent} as follows:</p>
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
- * <thead>
- * <tr><th>Component</th> <th>Type</th> <th>Description</th> <th>Required</th></tr>
- * </thead>
- *
- * <tbody>
- * <tr><th>URI</th>
- * <td>URI</td>
- * <td>The ContentProvider URI</td>
- * <td align="center">Yes</td>
- * </tr>
- * <tr><th>{@link #EXTRA_LIVE_FOLDER_NAME}</th>
- * <td>Extra String</td>
- * <td>The name of the live folder</td>
- * <td align="center">Yes</td>
- * </tr>
- * <tr><th>{@link #EXTRA_LIVE_FOLDER_ICON}</th>
- * <td>Extra {@link android.content.Intent.ShortcutIconResource}</td>
- * <td>The icon of the live folder</td>
- * <td align="center">Yes</td>
- * </tr>
- * <tr><th>{@link #EXTRA_LIVE_FOLDER_DISPLAY_MODE}</th>
- * <td>Extra int</td>
- * <td>The display mode of the live folder. The value must be either
- * {@link #DISPLAY_MODE_GRID} or {@link #DISPLAY_MODE_LIST}.</td>
- * <td align="center">Yes</td>
- * </tr>
- * <tr><th>{@link #EXTRA_LIVE_FOLDER_BASE_INTENT}</th>
- * <td>Extra Intent</td>
- * <td>When the user clicks an item inside a live folder, the system will either fire
- * the intent associated with that item or, if present, the live folder's base intent
- * with the id of the item appended to the base intent's URI.</td>
- * <td align="center">No</td>
- * </tr>
- * </tbody>
- * </table>
- *
- * <h3>Setting up the content provider</h3>
- * <p>The live folder's content provider must, upon query, return a {@link android.database.Cursor}
- * whose columns match the following names:</p>
- * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
- * <thead>
- * <tr><th>Column</th> <th>Type</th> <th>Description</th> <th>Required</th></tr>
- * </thead>
- *
- * <tbody>
- * <tr><th>{@link #NAME}</th>
- * <td>String</td>
- * <td>The name of the item</td>
- * <td align="center">Yes</td>
- * </tr>
- * <tr><th>{@link #DESCRIPTION}</th>
- * <td>String</td>
- * <td>The description of the item. The description is ignored when the live folder's
- * display mode is {@link #DISPLAY_MODE_GRID}.</td>
- * <td align="center">No</td>
- * </tr>
- * <tr><th>{@link #INTENT}</th>
- * <td>{@link android.content.Intent}</td>
- * <td>The intent to fire when the item is clicked. Ignored when the live folder defines
- * a base intent.</td>
- * <td align="center">No</td>
- * </tr>
- * <tr><th>{@link #ICON_BITMAP}</th>
- * <td>Bitmap</td>
- * <td>The icon for the item. When this column value is not null, the values for the
- * columns {@link #ICON_PACKAGE} and {@link #ICON_RESOURCE} must be null.</td>
- * <td align="center">No</td>
- * </tr>
- * <tr><th>{@link #ICON_PACKAGE}</th>
- * <td>String</td>
- * <td>The package of the item's icon. When this value is not null, the value for the
- * column {@link #ICON_RESOURCE} must be specified and the value for the column
- * {@link #ICON_BITMAP} must be null.</td>
- * <td align="center">No</td>
- * </tr>
- * <tr><th>{@link #ICON_RESOURCE}</th>
- * <td>String</td>
- * <td>The resource name of the item's icon. When this value is not null, the value for the
- * column {@link #ICON_PACKAGE} must be specified and the value for the column
- * {@link #ICON_BITMAP} must be null.</td>
- * <td align="center">No</td>
- * </tr>
- * </tbody>
- * </table>
- */
-public final class LiveFolders implements BaseColumns {
- /**
- * <p>Content provider column.</p>
- * <p>Name of the live folder item.</p>
- * <p>Required.</p>
- * <p>Type: String.</p>
- */
- public static final String NAME = "name";
-
- /**
- * <p>Content provider column.</p>
- * <p>Description of the live folder item. This value is ignored if the
- * live folder's display mode is {@link LiveFolders#DISPLAY_MODE_GRID}.</p>
- * <p>Optional.</p>
- * <p>Type: String.</p>
- *
- * @see LiveFolders#EXTRA_LIVE_FOLDER_DISPLAY_MODE
- */
- public static final String DESCRIPTION = "description";
-
- /**
- * <p>Content provider column.</p>
- * <p>Intent of the live folder item.</p>
- * <p>Optional if the live folder has a base intent.</p>
- * <p>Type: {@link android.content.Intent}.</p>
- *
- * @see LiveFolders#EXTRA_LIVE_FOLDER_BASE_INTENT
- */
- public static final String INTENT = "intent";
-
- /**
- * <p>Content provider column.</p>
- * <p>Icon of the live folder item, as a custom bitmap.</p>
- * <p>Optional.</p>
- * <p>Type: {@link android.graphics.Bitmap}.</p>
- */
- public static final String ICON_BITMAP = "icon_bitmap";
-
- /**
- * <p>Content provider column.</p>
- * <p>Package where to find the icon of the live folder item. This value can be
- * obtained easily using
- * {@link android.content.Intent.ShortcutIconResource#fromContext(android.content.Context, int)}.</p>
- * <p>Optional.</p>
- * <p>Type: String.</p>
- *
- * @see #ICON_RESOURCE
- * @see android.content.Intent.ShortcutIconResource
- */
- public static final String ICON_PACKAGE = "icon_package";
-
- /**
- * <p>Content provider column.</p>
- * <p>Resource name of the live folder item. This value can be obtained easily using
- * {@link android.content.Intent.ShortcutIconResource#fromContext(android.content.Context, int)}.</p>
- * <p>Optional.</p>
- * <p>Type: String.</p>
- *
- * @see #ICON_PACKAGE
- * @see android.content.Intent.ShortcutIconResource
- */
- public static final String ICON_RESOURCE = "icon_resource";
-
- /**
- * Displays a live folder's content in a grid.
- *
- * @see LiveFolders#EXTRA_LIVE_FOLDER_DISPLAY_MODE
- */
- public static final int DISPLAY_MODE_GRID = 0x1;
-
- /**
- * Displays a live folder's content in a list.
- *
- * @see LiveFolders#EXTRA_LIVE_FOLDER_DISPLAY_MODE
- */
- public static final int DISPLAY_MODE_LIST = 0x2;
-
- /**
- * The name of the extra used to define the name of a live folder.
- *
- * @see #ACTION_CREATE_LIVE_FOLDER
- */
- public static final String EXTRA_LIVE_FOLDER_NAME = "android.intent.extra.livefolder.NAME";
-
- /**
- * The name of the extra used to define the icon of a live folder.
- *
- * @see #ACTION_CREATE_LIVE_FOLDER
- */
- public static final String EXTRA_LIVE_FOLDER_ICON = "android.intent.extra.livefolder.ICON";
-
- /**
- * The name of the extra used to define the display mode of a live folder.
- *
- * @see #ACTION_CREATE_LIVE_FOLDER
- * @see #DISPLAY_MODE_GRID
- * @see #DISPLAY_MODE_LIST
- */
- public static final String EXTRA_LIVE_FOLDER_DISPLAY_MODE =
- "android.intent.extra.livefolder.DISPLAY_MODE";
-
- /**
- * The name of the extra used to define the base Intent of a live folder.
- *
- * @see #ACTION_CREATE_LIVE_FOLDER
- */
- public static final String EXTRA_LIVE_FOLDER_BASE_INTENT =
- "android.intent.extra.livefolder.BASE_INTENT";
-
- /**
- * Activity Action: Creates a live folder.
- * <p>Input: Nothing.</p>
- * <p>Output: An Intent representing the live folder. The intent must contain four
- * extras: EXTRA_LIVE_FOLDER_NAME (value: String),
- * EXTRA_LIVE_FOLDER_ICON (value: ShortcutIconResource),
- * EXTRA_LIVE_FOLDER_URI (value: String) and
- * EXTRA_LIVE_FOLDER_DISPLAY_MODE (value: int). The Intent can optionnally contain
- * EXTRA_LIVE_FOLDER_BASE_INTENT (value: Intent).</p>
- *
- * @see #EXTRA_LIVE_FOLDER_NAME
- * @see #EXTRA_LIVE_FOLDER_ICON
- * @see #EXTRA_LIVE_FOLDER_DISPLAY_MODE
- * @see #EXTRA_LIVE_FOLDER_BASE_INTENT
- * @see android.content.Intent.ShortcutIconResource
- */
- @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_CREATE_LIVE_FOLDER =
- "android.intent.action.CREATE_LIVE_FOLDER";
-
- private LiveFolders() {
- }
-}
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
deleted file mode 100644
index b91bc9d..0000000
--- a/core/java/android/provider/MediaStore.java
+++ /dev/null
@@ -1,1396 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.ContentUris;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
-import android.net.Uri;
-import android.os.Environment;
-import android.util.Log;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.text.Collator;
-
-/**
- * The Media provider contains meta data for all available media on both internal
- * and external storage devices.
- */
-public final class MediaStore
-{
- private final static String TAG = "MediaStore";
-
- public static final String AUTHORITY = "media";
-
- private static final String CONTENT_AUTHORITY_SLASH = "content://" + AUTHORITY + "/";
-
- /**
- * Activity Action: Perform a search for media.
- * Contains at least the {@link android.app.SearchManager#QUERY} extra.
- * May also contain any combination of the following extras:
- * EXTRA_MEDIA_ARTIST, EXTRA_MEDIA_ALBUM, EXTRA_MEDIA_TITLE, EXTRA_MEDIA_FOCUS
- *
- * @see android.provider.MediaStore#EXTRA_MEDIA_ARTIST
- * @see android.provider.MediaStore#EXTRA_MEDIA_ALBUM
- * @see android.provider.MediaStore#EXTRA_MEDIA_TITLE
- * @see android.provider.MediaStore#EXTRA_MEDIA_FOCUS
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String INTENT_ACTION_MEDIA_SEARCH = "android.intent.action.MEDIA_SEARCH";
-
- /**
- * The name of the Intent-extra used to define the artist
- */
- public static final String EXTRA_MEDIA_ARTIST = "android.intent.extra.artist";
- /**
- * The name of the Intent-extra used to define the album
- */
- public static final String EXTRA_MEDIA_ALBUM = "android.intent.extra.album";
- /**
- * The name of the Intent-extra used to define the song title
- */
- public static final String EXTRA_MEDIA_TITLE = "android.intent.extra.title";
- /**
- * The name of the Intent-extra used to define the search focus. The search focus
- * indicates whether the search should be for things related to the artist, album
- * or song that is identified by the other extras.
- */
- public static final String EXTRA_MEDIA_FOCUS = "android.intent.extra.focus";
-
- /**
- * The name of the Intent-extra used to control the orientation of a ViewImage or a MovieView.
- * This is an int property that overrides the activity's requestedOrientation.
- * @see android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
- */
- public static final String EXTRA_SCREEN_ORIENTATION = "android.intent.extra.screenOrientation";
-
- /**
- * The name of an Intent-extra used to control the UI of a ViewImage.
- * This is a boolean property that overrides the activity's default fullscreen state.
- * @hide
- */
- public static final String EXTRA_FULL_SCREEN = "android.intent.extra.fullScreen";
-
- /**
- * The name of an Intent-extra used to control the UI of a ViewImage.
- * This is a boolean property that specifies whether or not to show action icons.
- * @hide
- */
- public static final String EXTRA_SHOW_ACTION_ICONS = "android.intent.extra.showActionIcons";
-
- /**
- * The name of the Intent-extra used to control the onCompletion behavior of a MovieView.
- * This is a boolean property that specifies whether or not to finish the MovieView activity
- * when the movie completes playing. The default value is true, which means to automatically
- * exit the movie player activity when the movie completes playing.
- */
- public static final String EXTRA_FINISH_ON_COMPLETION = "android.intent.extra.finishOnCompletion";
-
- /**
- * The name of the Intent action used to launch a camera in still image mode.
- */
- public static final String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
-
- /**
- * The name of the Intent action used to launch a camera in video mode.
- */
- public static final String INTENT_ACTION_VIDEO_CAMERA = "android.media.action.VIDEO_CAMERA";
-
- /**
- * Standard Intent action that can be sent to have the camera application
- * capture an image and return it.
- * <p>
- * The caller may pass an extra EXTRA_OUTPUT to control where this image will be written.
- * If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap
- * object in the extra field. This is useful for applications that only need a small image.
- * If the EXTRA_OUTPUT is present, then the full-sized image will be written to the Uri
- * value of EXTRA_OUTPUT.
- * @see #EXTRA_OUTPUT
- * @see #EXTRA_VIDEO_QUALITY
- */
- public final static String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
-
- /**
- * Standard Intent action that can be sent to have the camera application
- * capture an video and return it.
- * <p>
- * The caller may pass in an extra EXTRA_VIDEO_QUALITY to control the video quality.
- * <p>
- * The caller may pass in an extra EXTRA_OUTPUT to control
- * where the video is written. If EXTRA_OUTPUT is not present the video will be
- * written to the standard location for videos, and the Uri of that location will be
- * returned in the data field of the Uri.
- * @see #EXTRA_OUTPUT
- */
- public final static String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE";
-
- /**
- * The name of the Intent-extra used to control the quality of a recorded video. This is an
- * integer property. Currently value 0 means low quality, suitable for MMS messages, and
- * value 1 means high quality. In the future other quality levels may be added.
- */
- public final static String EXTRA_VIDEO_QUALITY = "android.intent.extra.videoQuality";
-
- /**
- * Specify the maximum allowed size.
- * @hide
- */
- public final static String EXTRA_SIZE_LIMIT = "android.intent.extra.sizeLimit";
-
- /**
- * The name of the Intent-extra used to indicate a content resolver Uri to be used to
- * store the requested image or video.
- */
- public final static String EXTRA_OUTPUT = "output";
-
- /**
- * Common fields for most MediaProvider tables
- */
-
- public interface MediaColumns extends BaseColumns {
- /**
- * The data stream for the file
- * <P>Type: DATA STREAM</P>
- */
- public static final String DATA = "_data";
-
- /**
- * The size of the file in bytes
- * <P>Type: INTEGER (long)</P>
- */
- public static final String SIZE = "_size";
-
- /**
- * The display name of the file
- * <P>Type: TEXT</P>
- */
- public static final String DISPLAY_NAME = "_display_name";
-
- /**
- * The title of the content
- * <P>Type: TEXT</P>
- */
- public static final String TITLE = "title";
-
- /**
- * The time the file was added to the media provider
- * Units are seconds since 1970.
- * <P>Type: INTEGER (long)</P>
- */
- public static final String DATE_ADDED = "date_added";
-
- /**
- * The time the file was last modified
- * Units are seconds since 1970.
- * NOTE: This is for internal use by the media scanner. Do not modify this field.
- * <P>Type: INTEGER (long)</P>
- */
- public static final String DATE_MODIFIED = "date_modified";
-
- /**
- * The MIME type of the file
- * <P>Type: TEXT</P>
- */
- public static final String MIME_TYPE = "mime_type";
- }
-
- /**
- * Contains meta data for all available images.
- */
- public static final class Images
- {
- public interface ImageColumns extends MediaColumns {
- /**
- * The description of the image
- * <P>Type: TEXT</P>
- */
- public static final String DESCRIPTION = "description";
-
- /**
- * The picasa id of the image
- * <P>Type: TEXT</P>
- */
- public static final String PICASA_ID = "picasa_id";
-
- /**
- * Whether the video should be published as public or private
- * <P>Type: INTEGER</P>
- */
- public static final String IS_PRIVATE = "isprivate";
-
- /**
- * The latitude where the image was captured.
- * <P>Type: DOUBLE</P>
- */
- public static final String LATITUDE = "latitude";
-
- /**
- * The longitude where the image was captured.
- * <P>Type: DOUBLE</P>
- */
- public static final String LONGITUDE = "longitude";
-
- /**
- * The date & time that the image was taken in units
- * of milliseconds since jan 1, 1970.
- * <P>Type: INTEGER</P>
- */
- public static final String DATE_TAKEN = "datetaken";
-
- /**
- * The orientation for the image expressed as degrees.
- * Only degrees 0, 90, 180, 270 will work.
- * <P>Type: INTEGER</P>
- */
- public static final String ORIENTATION = "orientation";
-
- /**
- * The mini thumb id.
- * <P>Type: INTEGER</P>
- */
- public static final String MINI_THUMB_MAGIC = "mini_thumb_magic";
-
- /**
- * The bucket id of the image. This is a read-only property that
- * is automatically computed from the DATA column.
- * <P>Type: TEXT</P>
- */
- public static final String BUCKET_ID = "bucket_id";
-
- /**
- * The bucket display name of the image. This is a read-only property that
- * is automatically computed from the DATA column.
- * <P>Type: TEXT</P>
- */
- public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
- }
-
- public static final class Media implements ImageColumns {
- public static final Cursor query(ContentResolver cr, Uri uri, String[] projection)
- {
- return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
- }
-
- public static final Cursor query(ContentResolver cr, Uri uri, String[] projection,
- String where, String orderBy)
- {
- return cr.query(uri, projection, where,
- null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
- }
-
- public static final Cursor query(ContentResolver cr, Uri uri, String[] projection,
- String selection, String [] selectionArgs, String orderBy)
- {
- return cr.query(uri, projection, selection,
- selectionArgs, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
- }
-
- /**
- * Retrieves an image for the given url as a {@link Bitmap}.
- *
- * @param cr The content resolver to use
- * @param url The url of the image
- * @throws FileNotFoundException
- * @throws IOException
- */
- public static final Bitmap getBitmap(ContentResolver cr, Uri url)
- throws FileNotFoundException, IOException
- {
- InputStream input = cr.openInputStream(url);
- Bitmap bitmap = BitmapFactory.decodeStream(input);
- input.close();
- return bitmap;
- }
-
- /**
- * Insert an image and create a thumbnail for it.
- *
- * @param cr The content resolver to use
- * @param imagePath The path to the image to insert
- * @param name The name of the image
- * @param description The description of the image
- * @return The URL to the newly created image
- * @throws FileNotFoundException
- */
- public static final String insertImage(ContentResolver cr, String imagePath, String name,
- String description) throws FileNotFoundException
- {
- // Check if file exists with a FileInputStream
- FileInputStream stream = new FileInputStream(imagePath);
- try {
- return insertImage(cr, BitmapFactory.decodeFile(imagePath), name, description);
- } finally {
- try {
- stream.close();
- } catch (IOException e) {
- }
- }
- }
-
- private static final Bitmap StoreThumbnail(
- ContentResolver cr,
- Bitmap source,
- long id,
- float width, float height,
- int kind) {
- // create the matrix to scale it
- Matrix matrix = new Matrix();
-
- float scaleX = width / source.getWidth();
- float scaleY = height / source.getHeight();
-
- matrix.setScale(scaleX, scaleY);
-
- Bitmap thumb = Bitmap.createBitmap(source, 0, 0,
- source.getWidth(),
- source.getHeight(), matrix,
- true);
-
- ContentValues values = new ContentValues(4);
- values.put(Images.Thumbnails.KIND, kind);
- values.put(Images.Thumbnails.IMAGE_ID, (int)id);
- values.put(Images.Thumbnails.HEIGHT, thumb.getHeight());
- values.put(Images.Thumbnails.WIDTH, thumb.getWidth());
-
- Uri url = cr.insert(Images.Thumbnails.EXTERNAL_CONTENT_URI, values);
-
- try {
- OutputStream thumbOut = cr.openOutputStream(url);
-
- thumb.compress(Bitmap.CompressFormat.JPEG, 100, thumbOut);
- thumbOut.close();
- return thumb;
- }
- catch (FileNotFoundException ex) {
- return null;
- }
- catch (IOException ex) {
- return null;
- }
- }
-
- /**
- * Insert an image and create a thumbnail for it.
- *
- * @param cr The content resolver to use
- * @param source The stream to use for the image
- * @param title The name of the image
- * @param description The description of the image
- * @return The URL to the newly created image, or <code>null</code> if the image failed to be stored
- * for any reason.
- */
- public static final String insertImage(ContentResolver cr, Bitmap source,
- String title, String description)
- {
- ContentValues values = new ContentValues();
- values.put(Images.Media.TITLE, title);
- values.put(Images.Media.DESCRIPTION, description);
- values.put(Images.Media.MIME_TYPE, "image/jpeg");
-
- Uri url = null;
- String stringUrl = null; /* value to be returned */
-
- try
- {
- url = cr.insert(EXTERNAL_CONTENT_URI, values);
-
- if (source != null) {
- OutputStream imageOut = cr.openOutputStream(url);
- try {
- source.compress(Bitmap.CompressFormat.JPEG, 50, imageOut);
- } finally {
- imageOut.close();
- }
-
- long id = ContentUris.parseId(url);
- Bitmap miniThumb = StoreThumbnail(cr, source, id, 320F, 240F, Images.Thumbnails.MINI_KIND);
- Bitmap microThumb = StoreThumbnail(cr, miniThumb, id, 50F, 50F, Images.Thumbnails.MICRO_KIND);
- } else {
- Log.e(TAG, "Failed to create thumbnail, removing original");
- cr.delete(url, null, null);
- url = null;
- }
- } catch (Exception e) {
- Log.e(TAG, "Failed to insert image", e);
- if (url != null) {
- cr.delete(url, null, null);
- url = null;
- }
- }
-
- if (url != null) {
- stringUrl = url.toString();
- }
-
- return stringUrl;
- }
-
- /**
- * Get the content:// style URI for the image media table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the image media table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
- "/images/media");
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The MIME type of of this directory of
- * images. Note that each entry in this directory will have a standard
- * image MIME type as appropriate -- for example, image/jpeg.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/image";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = ImageColumns.BUCKET_DISPLAY_NAME;
- }
-
- public static class Thumbnails implements BaseColumns
- {
- public static final Cursor query(ContentResolver cr, Uri uri, String[] projection)
- {
- return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
- }
-
- public static final Cursor queryMiniThumbnails(ContentResolver cr, Uri uri, int kind, String[] projection)
- {
- return cr.query(uri, projection, "kind = " + kind, null, DEFAULT_SORT_ORDER);
- }
-
- public static final Cursor queryMiniThumbnail(ContentResolver cr, long origId, int kind, String[] projection)
- {
- return cr.query(EXTERNAL_CONTENT_URI, projection,
- IMAGE_ID + " = " + origId + " AND " + KIND + " = " +
- kind, null, null);
- }
-
- /**
- * Get the content:// style URI for the image media table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the image media table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
- "/images/thumbnails");
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "image_id ASC";
-
- /**
- * The data stream for the thumbnail
- * <P>Type: DATA STREAM</P>
- */
- public static final String DATA = "_data";
-
- /**
- * The original image for the thumbnal
- * <P>Type: INTEGER (ID from Images table)</P>
- */
- public static final String IMAGE_ID = "image_id";
-
- /**
- * The kind of the thumbnail
- * <P>Type: INTEGER (One of the values below)</P>
- */
- public static final String KIND = "kind";
-
- public static final int MINI_KIND = 1;
- public static final int FULL_SCREEN_KIND = 2;
- public static final int MICRO_KIND = 3;
-
- /**
- * The width of the thumbnal
- * <P>Type: INTEGER (long)</P>
- */
- public static final String WIDTH = "width";
-
- /**
- * The height of the thumbnail
- * <P>Type: INTEGER (long)</P>
- */
- public static final String HEIGHT = "height";
- }
- }
-
- /**
- * Container for all audio content.
- */
- public static final class Audio {
- /**
- * Columns for audio file that show up in multiple tables.
- */
- public interface AudioColumns extends MediaColumns {
-
- /**
- * A non human readable key calculated from the TITLE, used for
- * searching, sorting and grouping
- * <P>Type: TEXT</P>
- */
- public static final String TITLE_KEY = "title_key";
-
- /**
- * The duration of the audio file, in ms
- * <P>Type: INTEGER (long)</P>
- */
- public static final String DURATION = "duration";
-
- /**
- * The position, in ms, playback was at when playback for this file
- * was last stopped.
- * <P>Type: INTEGER (long)</P>
- * @hide
- */
- public static final String BOOKMARK = "bookmark";
-
- /**
- * The id of the artist who created the audio file, if any
- * <P>Type: INTEGER (long)</P>
- */
- public static final String ARTIST_ID = "artist_id";
-
- /**
- * The artist who created the audio file, if any
- * <P>Type: TEXT</P>
- */
- public static final String ARTIST = "artist";
-
- /**
- * A non human readable key calculated from the ARTIST, used for
- * searching, sorting and grouping
- * <P>Type: TEXT</P>
- */
- public static final String ARTIST_KEY = "artist_key";
-
- /**
- * The composer of the audio file, if any
- * <P>Type: TEXT</P>
- */
- public static final String COMPOSER = "composer";
-
- /**
- * The id of the album the audio file is from, if any
- * <P>Type: INTEGER (long)</P>
- */
- public static final String ALBUM_ID = "album_id";
-
- /**
- * The album the audio file is from, if any
- * <P>Type: TEXT</P>
- */
- public static final String ALBUM = "album";
-
- /**
- * A non human readable key calculated from the ALBUM, used for
- * searching, sorting and grouping
- * <P>Type: TEXT</P>
- */
- public static final String ALBUM_KEY = "album_key";
-
- /**
- * A URI to the album art, if any
- * <P>Type: TEXT</P>
- */
- public static final String ALBUM_ART = "album_art";
-
- /**
- * The track number of this song on the album, if any.
- * This number encodes both the track number and the
- * disc number. For multi-disc sets, this number will
- * be 1xxx for tracks on the first disc, 2xxx for tracks
- * on the second disc, etc.
- * <P>Type: INTEGER</P>
- */
- public static final String TRACK = "track";
-
- /**
- * The year the audio file was recorded, if any
- * <P>Type: INTEGER</P>
- */
- public static final String YEAR = "year";
-
- /**
- * Non-zero if the audio file is music
- * <P>Type: INTEGER (boolean)</P>
- */
- public static final String IS_MUSIC = "is_music";
-
- /**
- * Non-zero if the audio file is a podcast
- * <P>Type: INTEGER (boolean)</P>
- * @hide
- */
- public static final String IS_PODCAST = "is_podcast";
-
- /**
- * Non-zero id the audio file may be a ringtone
- * <P>Type: INTEGER (boolean)</P>
- */
- public static final String IS_RINGTONE = "is_ringtone";
-
- /**
- * Non-zero id the audio file may be an alarm
- * <P>Type: INTEGER (boolean)</P>
- */
- public static final String IS_ALARM = "is_alarm";
-
- /**
- * Non-zero id the audio file may be a notification sound
- * <P>Type: INTEGER (boolean)</P>
- */
- public static final String IS_NOTIFICATION = "is_notification";
- }
-
- /**
- * Converts a name to a "key" that can be used for grouping, sorting
- * and searching.
- * The rules that govern this conversion are:
- * - remove 'special' characters like ()[]'!?.,
- * - remove leading/trailing spaces
- * - convert everything to lowercase
- * - remove leading "the ", "an " and "a "
- * - remove trailing ", the|an|a"
- * - remove accents. This step leaves us with CollationKey data,
- * which is not human readable
- *
- * @param name The artist or album name to convert
- * @return The "key" for the given name.
- */
- public static String keyFor(String name) {
- if (name != null) {
- if (name.equals(android.media.MediaFile.UNKNOWN_STRING)) {
- return "\001";
- }
- name = name.trim().toLowerCase();
- if (name.startsWith("the ")) {
- name = name.substring(4);
- }
- if (name.startsWith("an ")) {
- name = name.substring(3);
- }
- if (name.startsWith("a ")) {
- name = name.substring(2);
- }
- if (name.endsWith(", the") || name.endsWith(",the") ||
- name.endsWith(", an") || name.endsWith(",an") ||
- name.endsWith(", a") || name.endsWith(",a")) {
- name = name.substring(0, name.lastIndexOf(','));
- }
- name = name.replaceAll("[\\[\\]\\(\\)'.,?!]", "").trim();
- if (name.length() > 0) {
- // Insert a separator between the characters to avoid
- // matches on a partial character. If we ever change
- // to start-of-word-only matches, this can be removed.
- StringBuilder b = new StringBuilder();
- b.append('.');
- int nl = name.length();
- for (int i = 0; i < nl; i++) {
- b.append(name.charAt(i));
- b.append('.');
- }
- name = b.toString();
- return DatabaseUtils.getCollationKey(name);
- } else {
- return "";
- }
- }
- return null;
- }
-
- public static final class Media implements AudioColumns {
- /**
- * Get the content:// style URI for the audio media table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the audio media table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
- "/audio/media");
- }
-
- public static Uri getContentUriForPath(String path) {
- return (path.startsWith(Environment.getExternalStorageDirectory().getPath()) ?
- EXTERNAL_CONTENT_URI : INTERNAL_CONTENT_URI);
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The MIME type for this table.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/audio";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = TITLE;
-
- /**
- * Activity Action: Start SoundRecorder application.
- * <p>Input: nothing.
- * <p>Output: An uri to the recorded sound stored in the Media Library
- * if the recording was successful.
- * May also contain the extra EXTRA_MAX_BYTES.
- * @see #EXTRA_MAX_BYTES
- */
- public static final String RECORD_SOUND_ACTION =
- "android.provider.MediaStore.RECORD_SOUND";
-
- /**
- * The name of the Intent-extra used to define a maximum file size for
- * a recording made by the SoundRecorder application.
- *
- * @see #RECORD_SOUND_ACTION
- */
- public static final String EXTRA_MAX_BYTES =
- "android.provider.MediaStore.extra.MAX_BYTES";
- }
-
- /**
- * Columns representing an audio genre
- */
- public interface GenresColumns {
- /**
- * The name of the genre
- * <P>Type: TEXT</P>
- */
- public static final String NAME = "name";
- }
-
- /**
- * Contains all genres for audio files
- */
- public static final class Genres implements BaseColumns, GenresColumns {
- /**
- * Get the content:// style URI for the audio genres table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the audio genres table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
- "/audio/genres");
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The MIME type for this table.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/genre";
-
- /**
- * The MIME type for entries in this table.
- */
- public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/genre";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = NAME;
-
- /**
- * Sub-directory of each genre containing all members.
- */
- public static final class Members implements AudioColumns {
-
- public static final Uri getContentUri(String volumeName,
- long genreId) {
- return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName
- + "/audio/genres/" + genreId + "/members");
- }
-
- /**
- * A subdirectory of each genre containing all member audio files.
- */
- public static final String CONTENT_DIRECTORY = "members";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = TITLE;
-
- /**
- * The ID of the audio file
- * <P>Type: INTEGER (long)</P>
- */
- public static final String AUDIO_ID = "audio_id";
-
- /**
- * The ID of the genre
- * <P>Type: INTEGER (long)</P>
- */
- public static final String GENRE_ID = "genre_id";
- }
- }
-
- /**
- * Columns representing a playlist
- */
- public interface PlaylistsColumns {
- /**
- * The name of the playlist
- * <P>Type: TEXT</P>
- */
- public static final String NAME = "name";
-
- /**
- * The data stream for the playlist file
- * <P>Type: DATA STREAM</P>
- */
- public static final String DATA = "_data";
-
- /**
- * The time the file was added to the media provider
- * Units are seconds since 1970.
- * <P>Type: INTEGER (long)</P>
- */
- public static final String DATE_ADDED = "date_added";
-
- /**
- * The time the file was last modified
- * Units are seconds since 1970.
- * NOTE: This is for internal use by the media scanner. Do not modify this field.
- * <P>Type: INTEGER (long)</P>
- */
- public static final String DATE_MODIFIED = "date_modified";
- }
-
- /**
- * Contains playlists for audio files
- */
- public static final class Playlists implements BaseColumns,
- PlaylistsColumns {
- /**
- * Get the content:// style URI for the audio playlists table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the audio playlists table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
- "/audio/playlists");
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The MIME type for this table.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/playlist";
-
- /**
- * The MIME type for entries in this table.
- */
- public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/playlist";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = NAME;
-
- /**
- * Sub-directory of each playlist containing all members.
- */
- public static final class Members implements AudioColumns {
- public static final Uri getContentUri(String volumeName,
- long playlistId) {
- return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName
- + "/audio/playlists/" + playlistId + "/members");
- }
-
- /**
- * The ID within the playlist.
- */
- public static final String _ID = "_id";
-
- /**
- * A subdirectory of each playlist containing all member audio
- * files.
- */
- public static final String CONTENT_DIRECTORY = "members";
-
- /**
- * The ID of the audio file
- * <P>Type: INTEGER (long)</P>
- */
- public static final String AUDIO_ID = "audio_id";
-
- /**
- * The ID of the playlist
- * <P>Type: INTEGER (long)</P>
- */
- public static final String PLAYLIST_ID = "playlist_id";
-
- /**
- * The order of the songs in the playlist
- * <P>Type: INTEGER (long)></P>
- */
- public static final String PLAY_ORDER = "play_order";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = PLAY_ORDER;
- }
- }
-
- /**
- * Columns representing an artist
- */
- public interface ArtistColumns {
- /**
- * The artist who created the audio file, if any
- * <P>Type: TEXT</P>
- */
- public static final String ARTIST = "artist";
-
- /**
- * A non human readable key calculated from the ARTIST, used for
- * searching, sorting and grouping
- * <P>Type: TEXT</P>
- */
- public static final String ARTIST_KEY = "artist_key";
-
- /**
- * The number of albums in the database for this artist
- */
- public static final String NUMBER_OF_ALBUMS = "number_of_albums";
-
- /**
- * The number of albums in the database for this artist
- */
- public static final String NUMBER_OF_TRACKS = "number_of_tracks";
- }
-
- /**
- * Contains artists for audio files
- */
- public static final class Artists implements BaseColumns, ArtistColumns {
- /**
- * Get the content:// style URI for the artists table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the audio artists table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
- "/audio/artists");
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The MIME type for this table.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/artists";
-
- /**
- * The MIME type for entries in this table.
- */
- public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/artist";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = ARTIST_KEY;
-
- /**
- * Sub-directory of each artist containing all albums on which
- * a song by the artist appears.
- */
- public static final class Albums implements AlbumColumns {
- public static final Uri getContentUri(String volumeName,
- long artistId) {
- return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName
- + "/audio/artists/" + artistId + "/albums");
- }
- }
- }
-
- /**
- * Columns representing an album
- */
- public interface AlbumColumns {
-
- /**
- * The id for the album
- * <P>Type: INTEGER</P>
- */
- public static final String ALBUM_ID = "album_id";
-
- /**
- * The album on which the audio file appears, if any
- * <P>Type: TEXT</P>
- */
- public static final String ALBUM = "album";
-
- /**
- * The artist whose songs appear on this album
- * <P>Type: TEXT</P>
- */
- public static final String ARTIST = "artist";
-
- /**
- * The number of songs on this album
- * <P>Type: INTEGER</P>
- */
- public static final String NUMBER_OF_SONGS = "numsongs";
-
- /**
- * This column is available when getting album info via artist,
- * and indicates the number of songs on the album by the given
- * artist.
- * <P>Type: INTEGER</P>
- *
- * @hide pending API Council approval
- */
- public static final String NUMBER_OF_SONGS_FOR_ARTIST = "numsongs_by_artist";
-
- /**
- * The year in which the earliest and latest songs
- * on this album were released. These will often
- * be the same, but for compilation albums they
- * might differ.
- * <P>Type: INTEGER</P>
- */
- public static final String FIRST_YEAR = "minyear";
- public static final String LAST_YEAR = "maxyear";
-
- /**
- * A non human readable key calculated from the ALBUM, used for
- * searching, sorting and grouping
- * <P>Type: TEXT</P>
- */
- public static final String ALBUM_KEY = "album_key";
-
- /**
- * Cached album art.
- * <P>Type: TEXT</P>
- */
- public static final String ALBUM_ART = "album_art";
- }
-
- /**
- * Contains artists for audio files
- */
- public static final class Albums implements BaseColumns, AlbumColumns {
- /**
- * Get the content:// style URI for the albums table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the audio albums table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
- "/audio/albums");
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The MIME type for this table.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/albums";
-
- /**
- * The MIME type for entries in this table.
- */
- public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/album";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = ALBUM_KEY;
- }
- }
-
- public static final class Video {
-
- /**
- * The default sort order for this table.
- */
- public static final String DEFAULT_SORT_ORDER = MediaColumns.DISPLAY_NAME;
-
- public static final Cursor query(ContentResolver cr, Uri uri, String[] projection)
- {
- return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
- }
-
- public interface VideoColumns extends MediaColumns {
-
- /**
- * The duration of the video file, in ms
- * <P>Type: INTEGER (long)</P>
- */
- public static final String DURATION = "duration";
-
- /**
- * The artist who created the video file, if any
- * <P>Type: TEXT</P>
- */
- public static final String ARTIST = "artist";
-
- /**
- * The album the video file is from, if any
- * <P>Type: TEXT</P>
- */
- public static final String ALBUM = "album";
-
- /**
- * The resolution of the video file, formatted as "XxY"
- * <P>Type: TEXT</P>
- */
- public static final String RESOLUTION = "resolution";
-
- /**
- * The description of the video recording
- * <P>Type: TEXT</P>
- */
- public static final String DESCRIPTION = "description";
-
- /**
- * Whether the video should be published as public or private
- * <P>Type: INTEGER</P>
- */
- public static final String IS_PRIVATE = "isprivate";
-
- /**
- * The user-added tags associated with a video
- * <P>Type: TEXT</P>
- */
- public static final String TAGS = "tags";
-
- /**
- * The YouTube category of the video
- * <P>Type: TEXT</P>
- */
- public static final String CATEGORY = "category";
-
- /**
- * The language of the video
- * <P>Type: TEXT</P>
- */
- public static final String LANGUAGE = "language";
-
- /**
- * The latitude where the image was captured.
- * <P>Type: DOUBLE</P>
- */
- public static final String LATITUDE = "latitude";
-
- /**
- * The longitude where the image was captured.
- * <P>Type: DOUBLE</P>
- */
- public static final String LONGITUDE = "longitude";
-
- /**
- * The date & time that the image was taken in units
- * of milliseconds since jan 1, 1970.
- * <P>Type: INTEGER</P>
- */
- public static final String DATE_TAKEN = "datetaken";
-
- /**
- * The mini thumb id.
- * <P>Type: INTEGER</P>
- */
- public static final String MINI_THUMB_MAGIC = "mini_thumb_magic";
-
- /**
- * The bucket id of the video. This is a read-only property that
- * is automatically computed from the DATA column.
- * <P>Type: TEXT</P>
- */
- public static final String BUCKET_ID = "bucket_id";
-
- /**
- * The bucket display name of the video. This is a read-only property that
- * is automatically computed from the DATA column.
- * <P>Type: TEXT</P>
- */
- public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
-
- /**
- * The bookmark for the video. Time in ms. Represents the location in the video that the
- * video should start playing at the next time it is opened. If the value is null or
- * out of the range 0..DURATION-1 then the video should start playing from the
- * beginning.
- * <P>Type: INTEGER</P>
- */
- public static final String BOOKMARK = "bookmark";
- }
-
- public static final class Media implements VideoColumns {
- /**
- * Get the content:// style URI for the video media table on the
- * given volume.
- *
- * @param volumeName the name of the volume to get the URI for
- * @return the URI to the video media table on the given volume
- */
- public static Uri getContentUri(String volumeName) {
- return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
- "/video/media");
- }
-
- /**
- * The content:// style URI for the internal storage.
- */
- public static final Uri INTERNAL_CONTENT_URI =
- getContentUri("internal");
-
- /**
- * The content:// style URI for the "primary" external storage
- * volume.
- */
- public static final Uri EXTERNAL_CONTENT_URI =
- getContentUri("external");
-
- /**
- * The MIME type for this table.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/video";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = TITLE;
- }
- }
-
- /**
- * Uri for querying the state of the media scanner.
- */
- public static Uri getMediaScannerUri() {
- return Uri.parse(CONTENT_AUTHORITY_SLASH + "none/media_scanner");
- }
-
- /**
- * Name of current volume being scanned by the media scanner.
- */
- public static final String MEDIA_SCANNER_VOLUME = "volume";
-}
diff --git a/core/java/android/provider/OpenableColumns.java b/core/java/android/provider/OpenableColumns.java
deleted file mode 100644
index f548bae..0000000
--- a/core/java/android/provider/OpenableColumns.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-/**
- * These are standard columns for openable URIs. (See
- * {@link android.content.Intent#CATEGORY_OPENABLE}.) If possible providers that have openable URIs
- * should support these columns. To find the content type of a URI use
- * {@link android.content.ContentResolver#getType(android.net.Uri)} as normal.
- */
-public interface OpenableColumns {
-
- /**
- * The human-friendly name of file. If this is not provided then the name should default to the
- * the last segment of the file's URI.
- */
- public static final String DISPLAY_NAME = "_display_name";
-
- /**
- * The number of bytes in the file identified by the openable URI. Null if unknown.
- */
- public static final String SIZE = "_size";
-}
diff --git a/core/java/android/provider/SearchRecentSuggestions.java b/core/java/android/provider/SearchRecentSuggestions.java
deleted file mode 100644
index 0632d94..0000000
--- a/core/java/android/provider/SearchRecentSuggestions.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.SearchRecentSuggestionsProvider;
-import android.database.Cursor;
-import android.net.Uri;
-import android.text.TextUtils;
-import android.util.Log;
-
-/**
- * This is a utility class providing access to
- * {@link android.content.SearchRecentSuggestionsProvider}.
- *
- * <p>Unlike some utility classes, this one must be instantiated and properly initialized, so that
- * it can be configured to operate with the search suggestions provider that you have created.
- *
- * <p>Typically, you will do this in your searchable activity, each time you receive an incoming
- * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} Intent. The code to record each
- * incoming query is as follows:
- * <pre class="prettyprint">
- * SearchSuggestions suggestions = new SearchSuggestions(this,
- * MySuggestionsProvider.AUTHORITY, MySuggestionsProvider.MODE);
- * suggestions.saveRecentQuery(queryString, null);
- * </pre>
- *
- * <p>For a working example, see SearchSuggestionSampleProvider and SearchQueryResults in
- * samples/ApiDemos/app.
- */
-public class SearchRecentSuggestions {
- // debugging support
- private static final String LOG_TAG = "SearchSuggestions";
- // DELETE ME (eventually)
- private static final int DBG_SUGGESTION_TIMESTAMPS = 0;
-
- // This is a superset of all possible column names (need not all be in table)
- private static class SuggestionColumns implements BaseColumns {
- public static final String DISPLAY1 = "display1";
- public static final String DISPLAY2 = "display2";
- public static final String QUERY = "query";
- public static final String DATE = "date";
- }
-
- /* if you change column order you must also change indices below */
- /**
- * This is the database projection that can be used to view saved queries, when
- * configured for one-line operation.
- */
- public static final String[] QUERIES_PROJECTION_1LINE = new String[] {
- SuggestionColumns._ID,
- SuggestionColumns.DATE,
- SuggestionColumns.QUERY,
- SuggestionColumns.DISPLAY1,
- };
- /* if you change column order you must also change indices below */
- /**
- * This is the database projection that can be used to view saved queries, when
- * configured for two-line operation.
- */
- public static final String[] QUERIES_PROJECTION_2LINE = new String[] {
- SuggestionColumns._ID,
- SuggestionColumns.DATE,
- SuggestionColumns.QUERY,
- SuggestionColumns.DISPLAY1,
- SuggestionColumns.DISPLAY2,
- };
-
- /* these indices depend on QUERIES_PROJECTION_xxx */
- /** Index into the provided query projections. For use with Cursor.update methods. */
- public static final int QUERIES_PROJECTION_DATE_INDEX = 1;
- /** Index into the provided query projections. For use with Cursor.update methods. */
- public static final int QUERIES_PROJECTION_QUERY_INDEX = 2;
- /** Index into the provided query projections. For use with Cursor.update methods. */
- public static final int QUERIES_PROJECTION_DISPLAY1_INDEX = 3;
- /** Index into the provided query projections. For use with Cursor.update methods. */
- public static final int QUERIES_PROJECTION_DISPLAY2_INDEX = 4; // only when 2line active
-
- /* columns needed to determine whether to truncate history */
- private static final String[] TRUNCATE_HISTORY_PROJECTION = new String[] {
- SuggestionColumns._ID, SuggestionColumns.DATE
- };
-
- /*
- * Set a cap on the count of items in the suggestions table, to
- * prevent db and layout operations from dragging to a crawl. Revisit this
- * cap when/if db/layout performance improvements are made.
- */
- private static final int MAX_HISTORY_COUNT = 250;
-
- // client-provided configuration values
- private Context mContext;
- private String mAuthority;
- private boolean mTwoLineDisplay;
- private Uri mSuggestionsUri;
- private String[] mQueriesProjection;
-
- /**
- * Although provider utility classes are typically static, this one must be constructed
- * because it needs to be initialized using the same values that you provided in your
- * {@link android.content.SearchRecentSuggestionsProvider}.
- *
- * @param authority This must match the authority that you've declared in your manifest.
- * @param mode You can use mode flags here to determine certain functional aspects of your
- * database. Note, this value should not change from run to run, because when it does change,
- * your suggestions database may be wiped.
- *
- * @see android.content.SearchRecentSuggestionsProvider
- * @see android.content.SearchRecentSuggestionsProvider#setupSuggestions
- */
- public SearchRecentSuggestions(Context context, String authority, int mode) {
- if (TextUtils.isEmpty(authority) ||
- ((mode & SearchRecentSuggestionsProvider.DATABASE_MODE_QUERIES) == 0)) {
- throw new IllegalArgumentException();
- }
- // unpack mode flags
- mTwoLineDisplay = (0 != (mode & SearchRecentSuggestionsProvider.DATABASE_MODE_2LINES));
-
- // saved values
- mContext = context;
- mAuthority = new String(authority);
-
- // derived values
- mSuggestionsUri = Uri.parse("content://" + mAuthority + "/suggestions");
-
- if (mTwoLineDisplay) {
- mQueriesProjection = QUERIES_PROJECTION_2LINE;
- } else {
- mQueriesProjection = QUERIES_PROJECTION_1LINE;
- }
- }
-
- /**
- * Add a query to the recent queries list.
- *
- * @param queryString The string as typed by the user. This string will be displayed as
- * the suggestion, and if the user clicks on the suggestion, this string will be sent to your
- * searchable activity (as a new search query).
- * @param line2 If you have configured your recent suggestions provider with
- * {@link android.content.SearchRecentSuggestionsProvider#DATABASE_MODE_2LINES}, you can
- * pass a second line of text here. It will be shown in a smaller font, below the primary
- * suggestion. When typing, matches in either line of text will be displayed in the list.
- * If you did not configure two-line mode, or if a given suggestion does not have any
- * additional text to display, you can pass null here.
- */
- public void saveRecentQuery(String queryString, String line2) {
- if (TextUtils.isEmpty(queryString)) {
- return;
- }
- if (!mTwoLineDisplay && !TextUtils.isEmpty(line2)) {
- throw new IllegalArgumentException();
- }
-
- ContentResolver cr = mContext.getContentResolver();
- long now = System.currentTimeMillis();
-
- // Use content resolver (not cursor) to insert/update this query
- try {
- ContentValues values = new ContentValues();
- values.put(SuggestionColumns.DISPLAY1, queryString);
- if (mTwoLineDisplay) {
- values.put(SuggestionColumns.DISPLAY2, line2);
- }
- values.put(SuggestionColumns.QUERY, queryString);
- values.put(SuggestionColumns.DATE, now);
- cr.insert(mSuggestionsUri, values);
- } catch (RuntimeException e) {
- Log.e(LOG_TAG, "saveRecentQuery", e);
- }
-
- // Shorten the list (if it has become too long)
- truncateHistory(cr, MAX_HISTORY_COUNT);
- }
-
- /**
- * Completely delete the history. Use this call to implement a "clear history" UI.
- *
- * Any application that implements search suggestions based on previous actions (such as
- * recent queries, page/items viewed, etc.) should provide a way for the user to clear the
- * history. This gives the user a measure of privacy, if they do not wish for their recent
- * searches to be replayed by other users of the device (via suggestions).
- */
- public void clearHistory() {
- ContentResolver cr = mContext.getContentResolver();
- truncateHistory(cr, 0);
- }
-
- /**
- * Reduces the length of the history table, to prevent it from growing too large.
- *
- * @param cr Convenience copy of the content resolver.
- * @param maxEntries Max entries to leave in the table. 0 means remove all entries.
- */
- protected void truncateHistory(ContentResolver cr, int maxEntries) {
- if (maxEntries < 0) {
- throw new IllegalArgumentException();
- }
-
- try {
- // null means "delete all". otherwise "delete but leave n newest"
- String selection = null;
- if (maxEntries > 0) {
- selection = "_id IN " +
- "(SELECT _id FROM suggestions" +
- " ORDER BY " + SuggestionColumns.DATE + " DESC" +
- " LIMIT -1 OFFSET " + String.valueOf(maxEntries) + ")";
- }
- cr.delete(mSuggestionsUri, selection, null);
- } catch (RuntimeException e) {
- Log.e(LOG_TAG, "truncateHistory", e);
- }
- }
-}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
deleted file mode 100644
index 4a784c8..0000000
--- a/core/java/android/provider/Settings.java
+++ /dev/null
@@ -1,3078 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import com.google.android.collect.Maps;
-
-import org.apache.commons.codec.binary.Base64;
-
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.content.ContentQueryMap;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.database.SQLException;
-import android.net.Uri;
-import android.os.*;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-import android.util.AndroidException;
-import android.util.Log;
-
-import java.net.URISyntaxException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.HashMap;
-import java.util.HashSet;
-
-
-/**
- * The Settings provider contains global system-level device preferences.
- */
-public final class Settings {
-
- // Intent actions for Settings
-
- /**
- * Activity Action: Show system settings.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_SETTINGS = "android.settings.SETTINGS";
-
- /**
- * Activity Action: Show settings to allow configuration of APNs.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_APN_SETTINGS = "android.settings.APN_SETTINGS";
-
- /**
- * Activity Action: Show settings to allow configuration of current location
- * sources.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_LOCATION_SOURCE_SETTINGS =
- "android.settings.LOCATION_SOURCE_SETTINGS";
-
- /**
- * Activity Action: Show settings to allow configuration of wireless controls
- * such as Wi-Fi, Bluetooth and Mobile networks.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_WIRELESS_SETTINGS =
- "android.settings.WIRELESS_SETTINGS";
-
- /**
- * Activity Action: Show settings to allow entering/exiting airplane mode.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_AIRPLANE_MODE_SETTINGS =
- "android.settings.AIRPLANE_MODE_SETTINGS";
-
- /**
- * Activity Action: Show settings to allow configuration of security and
- * location privacy.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_SECURITY_SETTINGS =
- "android.settings.SECURITY_SETTINGS";
-
- /**
- * Activity Action: Show settings to allow configuration of Wi-Fi.
-
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
-
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_WIFI_SETTINGS =
- "android.settings.WIFI_SETTINGS";
-
- /**
- * Activity Action: Show settings to allow configuration of a static IP
- * address for Wi-Fi.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you safeguard
- * against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_WIFI_IP_SETTINGS =
- "android.settings.WIFI_IP_SETTINGS";
-
- /**
- * Activity Action: Show settings to allow configuration of Bluetooth.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_BLUETOOTH_SETTINGS =
- "android.settings.BLUETOOTH_SETTINGS";
-
- /**
- * Activity Action: Show settings to allow configuration of date and time.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_DATE_SETTINGS =
- "android.settings.DATE_SETTINGS";
-
- /**
- * Activity Action: Show settings to allow configuration of sound and volume.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_SOUND_SETTINGS =
- "android.settings.SOUND_SETTINGS";
-
- /**
- * Activity Action: Show settings to allow configuration of display.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_DISPLAY_SETTINGS =
- "android.settings.DISPLAY_SETTINGS";
-
- /**
- * Activity Action: Show settings to allow configuration of locale.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_LOCALE_SETTINGS =
- "android.settings.LOCALE_SETTINGS";
-
- /**
- * Activity Action: Show settings to configure input methods, in particular
- * allowing the user to enable input methods.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_INPUT_METHOD_SETTINGS =
- "android.settings.INPUT_METHOD_SETTINGS";
-
- /**
- * Activity Action: Show settings to manage the user input dictionary.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_USER_DICTIONARY_SETTINGS =
- "android.settings.USER_DICTIONARY_SETTINGS";
-
- /**
- * Activity Action: Show settings to allow configuration of application-related settings.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_APPLICATION_SETTINGS =
- "android.settings.APPLICATION_SETTINGS";
-
- /**
- * Activity Action: Show settings to allow configuration of application
- * development-related settings.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you safeguard
- * against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_APPLICATION_DEVELOPMENT_SETTINGS =
- "android.settings.APPLICATION_DEVELOPMENT_SETTINGS";
-
- /**
- * Activity Action: Show settings to allow configuration of quick launch shortcuts.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_QUICK_LAUNCH_SETTINGS =
- "android.settings.QUICK_LAUNCH_SETTINGS";
-
- /**
- * Activity Action: Show settings to manage installed applications.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_MANAGE_APPLICATIONS_SETTINGS =
- "android.settings.MANAGE_APPLICATIONS_SETTINGS";
-
- /**
- * Activity Action: Show settings for system update functionality.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- *
- * @hide
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_SYSTEM_UPDATE_SETTINGS =
- "android.settings.SYSTEM_UPDATE_SETTINGS";
-
- /**
- * Activity Action: Show settings to allow configuration of sync settings.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_SYNC_SETTINGS =
- "android.settings.SYNC_SETTINGS";
-
- /**
- * Activity Action: Show settings for selecting the network operator.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_NETWORK_OPERATOR_SETTINGS =
- "android.settings.NETWORK_OPERATOR_SETTINGS";
-
- /**
- * Activity Action: Show settings for selection of 2G/3G.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_DATA_ROAMING_SETTINGS =
- "android.settings.DATA_ROAMING_SETTINGS";
-
- /**
- * Activity Action: Show settings for internal storage.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_INTERNAL_STORAGE_SETTINGS =
- "android.settings.INTERNAL_STORAGE_SETTINGS";
- /**
- * Activity Action: Show settings for memory card storage.
- * <p>
- * In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
- * <p>
- * Input: Nothing.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_MEMORY_CARD_SETTINGS =
- "android.settings.MEMORY_CARD_SETTINGS";
-
- // End of Intent actions for Settings
-
- private static final String JID_RESOURCE_PREFIX = "android";
-
- public static final String AUTHORITY = "settings";
-
- private static final String TAG = "Settings";
-
- private static String sJidResource = null;
-
- public static class SettingNotFoundException extends AndroidException {
- public SettingNotFoundException(String msg) {
- super(msg);
- }
- }
-
- /**
- * Common base for tables of name/value settings.
- */
- public static class NameValueTable implements BaseColumns {
- public static final String NAME = "name";
- public static final String VALUE = "value";
-
- protected static boolean putString(ContentResolver resolver, Uri uri,
- String name, String value) {
- // The database will take care of replacing duplicates.
- try {
- ContentValues values = new ContentValues();
- values.put(NAME, name);
- values.put(VALUE, value);
- resolver.insert(uri, values);
- return true;
- } catch (SQLException e) {
- Log.e(TAG, "Can't set key " + name + " in " + uri, e);
- return false;
- }
- }
-
- public static Uri getUriFor(Uri uri, String name) {
- return Uri.withAppendedPath(uri, name);
- }
- }
-
- private static class NameValueCache {
- private final String mVersionSystemProperty;
- private final HashMap<String, String> mValues = Maps.newHashMap();
- private long mValuesVersion = 0;
- private final Uri mUri;
-
- NameValueCache(String versionSystemProperty, Uri uri) {
- mVersionSystemProperty = versionSystemProperty;
- mUri = uri;
- }
-
- String getString(ContentResolver cr, String name) {
- long newValuesVersion = SystemProperties.getLong(mVersionSystemProperty, 0);
- if (mValuesVersion != newValuesVersion) {
- mValues.clear();
- mValuesVersion = newValuesVersion;
- }
- if (!mValues.containsKey(name)) {
- String value = null;
- Cursor c = null;
- try {
- c = cr.query(mUri, new String[] { Settings.NameValueTable.VALUE },
- Settings.NameValueTable.NAME + "=?", new String[]{name}, null);
- if (c != null && c.moveToNext()) value = c.getString(0);
- mValues.put(name, value);
- } catch (SQLException e) {
- // SQL error: return null, but don't cache it.
- Log.e(TAG, "Can't get key " + name + " from " + mUri, e);
- } finally {
- if (c != null) c.close();
- }
- return value;
- } else {
- return mValues.get(name);
- }
- }
- }
-
- /**
- * System settings, containing miscellaneous system preferences. This
- * table holds simple name/value pairs. There are convenience
- * functions for accessing individual settings entries.
- */
- public static final class System extends NameValueTable {
- public static final String SYS_PROP_SETTING_VERSION = "sys.settings_system_version";
-
- private static volatile NameValueCache mNameValueCache = null;
-
- private static final HashSet<String> MOVED_TO_SECURE;
- static {
- MOVED_TO_SECURE = new HashSet<String>(30);
- MOVED_TO_SECURE.add(Secure.ADB_ENABLED);
- MOVED_TO_SECURE.add(Secure.ANDROID_ID);
- MOVED_TO_SECURE.add(Secure.BLUETOOTH_ON);
- MOVED_TO_SECURE.add(Secure.DATA_ROAMING);
- MOVED_TO_SECURE.add(Secure.DEVICE_PROVISIONED);
- MOVED_TO_SECURE.add(Secure.HTTP_PROXY);
- MOVED_TO_SECURE.add(Secure.INSTALL_NON_MARKET_APPS);
- MOVED_TO_SECURE.add(Secure.LOCATION_PROVIDERS_ALLOWED);
- MOVED_TO_SECURE.add(Secure.LOGGING_ID);
- MOVED_TO_SECURE.add(Secure.PARENTAL_CONTROL_ENABLED);
- MOVED_TO_SECURE.add(Secure.PARENTAL_CONTROL_LAST_UPDATE);
- MOVED_TO_SECURE.add(Secure.PARENTAL_CONTROL_REDIRECT_URL);
- MOVED_TO_SECURE.add(Secure.SETTINGS_CLASSNAME);
- MOVED_TO_SECURE.add(Secure.USB_MASS_STORAGE_ENABLED);
- MOVED_TO_SECURE.add(Secure.USE_GOOGLE_MAIL);
- MOVED_TO_SECURE.add(Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON);
- MOVED_TO_SECURE.add(Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY);
- MOVED_TO_SECURE.add(Secure.WIFI_NUM_OPEN_NETWORKS_KEPT);
- MOVED_TO_SECURE.add(Secure.WIFI_ON);
- MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE);
- MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_AP_COUNT);
- MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS);
- MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED);
- MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS);
- MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT);
- MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_MAX_AP_CHECKS);
- MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_ON);
- MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_PING_COUNT);
- MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_PING_DELAY_MS);
- MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS);
- }
-
- /**
- * Look up a name in the database.
- * @param resolver to access the database with
- * @param name to look up in the table
- * @return the corresponding value, or null if not present
- */
- public synchronized static String getString(ContentResolver resolver, String name) {
- if (MOVED_TO_SECURE.contains(name)) {
- Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
- + " to android.provider.Settings.Secure, returning read-only value.");
- return Secure.getString(resolver, name);
- }
- if (mNameValueCache == null) {
- mNameValueCache = new NameValueCache(SYS_PROP_SETTING_VERSION, CONTENT_URI);
- }
- return mNameValueCache.getString(resolver, name);
- }
-
- /**
- * Store a name/value pair into the database.
- * @param resolver to access the database with
- * @param name to store
- * @param value to associate with the name
- * @return true if the value was set, false on database errors
- */
- public static boolean putString(ContentResolver resolver, String name, String value) {
- if (MOVED_TO_SECURE.contains(name)) {
- Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
- + " to android.provider.Settings.Secure, value is unchanged.");
- return false;
- }
- return putString(resolver, CONTENT_URI, name, value);
- }
-
- /**
- * Construct the content URI for a particular name/value pair,
- * useful for monitoring changes with a ContentObserver.
- * @param name to look up in the table
- * @return the corresponding content URI, or null if not present
- */
- public static Uri getUriFor(String name) {
- if (MOVED_TO_SECURE.contains(name)) {
- Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
- + " to android.provider.Settings.Secure, returning Secure URI.");
- return Secure.getUriFor(Secure.CONTENT_URI, name);
- }
- return getUriFor(CONTENT_URI, name);
- }
-
- /**
- * Convenience function for retrieving a single system settings value
- * as an integer. Note that internally setting values are always
- * stored as strings; this function converts the string to an integer
- * for you. The default value will be returned if the setting is
- * not defined or not an integer.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to retrieve.
- * @param def Value to return if the setting is not defined.
- *
- * @return The setting's current value, or 'def' if it is not defined
- * or not a valid integer.
- */
- public static int getInt(ContentResolver cr, String name, int def) {
- String v = getString(cr, name);
- try {
- return v != null ? Integer.parseInt(v) : def;
- } catch (NumberFormatException e) {
- return def;
- }
- }
-
- /**
- * Convenience function for retrieving a single system settings value
- * as an integer. Note that internally setting values are always
- * stored as strings; this function converts the string to an integer
- * for you.
- * <p>
- * This version does not take a default value. If the setting has not
- * been set, or the string value is not a number,
- * it throws {@link SettingNotFoundException}.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to retrieve.
- *
- * @throws SettingNotFoundException Thrown if a setting by the given
- * name can't be found or the setting value is not an integer.
- *
- * @return The setting's current value.
- */
- public static int getInt(ContentResolver cr, String name)
- throws SettingNotFoundException {
- String v = getString(cr, name);
- try {
- return Integer.parseInt(v);
- } catch (NumberFormatException e) {
- throw new SettingNotFoundException(name);
- }
- }
-
- /**
- * Convenience function for updating a single settings value as an
- * integer. This will either create a new entry in the table if the
- * given name does not exist, or modify the value of the existing row
- * with that name. Note that internally setting values are always
- * stored as strings, so this function converts the given value to a
- * string before storing it.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to modify.
- * @param value The new value for the setting.
- * @return true if the value was set, false on database errors
- */
- public static boolean putInt(ContentResolver cr, String name, int value) {
- return putString(cr, name, Integer.toString(value));
- }
-
- /**
- * Convenience function for retrieving a single system settings value
- * as a {@code long}. Note that internally setting values are always
- * stored as strings; this function converts the string to a {@code long}
- * for you. The default value will be returned if the setting is
- * not defined or not a {@code long}.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to retrieve.
- * @param def Value to return if the setting is not defined.
- *
- * @return The setting's current value, or 'def' if it is not defined
- * or not a valid {@code long}.
- */
- public static long getLong(ContentResolver cr, String name, long def) {
- String valString = getString(cr, name);
- long value;
- try {
- value = valString != null ? Long.parseLong(valString) : def;
- } catch (NumberFormatException e) {
- value = def;
- }
- return value;
- }
-
- /**
- * Convenience function for retrieving a single system settings value
- * as a {@code long}. Note that internally setting values are always
- * stored as strings; this function converts the string to a {@code long}
- * for you.
- * <p>
- * This version does not take a default value. If the setting has not
- * been set, or the string value is not a number,
- * it throws {@link SettingNotFoundException}.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to retrieve.
- *
- * @return The setting's current value.
- * @throws SettingNotFoundException Thrown if a setting by the given
- * name can't be found or the setting value is not an integer.
- */
- public static long getLong(ContentResolver cr, String name)
- throws SettingNotFoundException {
- String valString = getString(cr, name);
- try {
- return Long.parseLong(valString);
- } catch (NumberFormatException e) {
- throw new SettingNotFoundException(name);
- }
- }
-
- /**
- * Convenience function for updating a single settings value as a long
- * integer. This will either create a new entry in the table if the
- * given name does not exist, or modify the value of the existing row
- * with that name. Note that internally setting values are always
- * stored as strings, so this function converts the given value to a
- * string before storing it.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to modify.
- * @param value The new value for the setting.
- * @return true if the value was set, false on database errors
- */
- public static boolean putLong(ContentResolver cr, String name, long value) {
- return putString(cr, name, Long.toString(value));
- }
-
- /**
- * Convenience function for retrieving a single system settings value
- * as a floating point number. Note that internally setting values are
- * always stored as strings; this function converts the string to an
- * float for you. The default value will be returned if the setting
- * is not defined or not a valid float.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to retrieve.
- * @param def Value to return if the setting is not defined.
- *
- * @return The setting's current value, or 'def' if it is not defined
- * or not a valid float.
- */
- public static float getFloat(ContentResolver cr, String name, float def) {
- String v = getString(cr, name);
- try {
- return v != null ? Float.parseFloat(v) : def;
- } catch (NumberFormatException e) {
- return def;
- }
- }
-
- /**
- * Convenience function for retrieving a single system settings value
- * as a float. Note that internally setting values are always
- * stored as strings; this function converts the string to a float
- * for you.
- * <p>
- * This version does not take a default value. If the setting has not
- * been set, or the string value is not a number,
- * it throws {@link SettingNotFoundException}.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to retrieve.
- *
- * @throws SettingNotFoundException Thrown if a setting by the given
- * name can't be found or the setting value is not a float.
- *
- * @return The setting's current value.
- */
- public static float getFloat(ContentResolver cr, String name)
- throws SettingNotFoundException {
- String v = getString(cr, name);
- try {
- return Float.parseFloat(v);
- } catch (NumberFormatException e) {
- throw new SettingNotFoundException(name);
- }
- }
-
- /**
- * Convenience function for updating a single settings value as a
- * floating point number. This will either create a new entry in the
- * table if the given name does not exist, or modify the value of the
- * existing row with that name. Note that internally setting values
- * are always stored as strings, so this function converts the given
- * value to a string before storing it.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to modify.
- * @param value The new value for the setting.
- * @return true if the value was set, false on database errors
- */
- public static boolean putFloat(ContentResolver cr, String name, float value) {
- return putString(cr, name, Float.toString(value));
- }
-
- /**
- * Convenience function to read all of the current
- * configuration-related settings into a
- * {@link Configuration} object.
- *
- * @param cr The ContentResolver to access.
- * @param outConfig Where to place the configuration settings.
- */
- public static void getConfiguration(ContentResolver cr, Configuration outConfig) {
- outConfig.fontScale = Settings.System.getFloat(
- cr, FONT_SCALE, outConfig.fontScale);
- if (outConfig.fontScale < 0) {
- outConfig.fontScale = 1;
- }
- }
-
- /**
- * Convenience function to write a batch of configuration-related
- * settings from a {@link Configuration} object.
- *
- * @param cr The ContentResolver to access.
- * @param config The settings to write.
- * @return true if the values were set, false on database errors
- */
- public static boolean putConfiguration(ContentResolver cr, Configuration config) {
- return Settings.System.putFloat(cr, FONT_SCALE, config.fontScale);
- }
-
- public static boolean getShowGTalkServiceStatus(ContentResolver cr) {
- return getInt(cr, SHOW_GTALK_SERVICE_STATUS, 0) != 0;
- }
-
- public static void setShowGTalkServiceStatus(ContentResolver cr, boolean flag) {
- putInt(cr, SHOW_GTALK_SERVICE_STATUS, flag ? 1 : 0);
- }
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://" + AUTHORITY + "/system");
-
- /**
- * Whether we keep the device on while the device is plugged in.
- * Supported values are:
- * <ul>
- * <li>{@code 0} to never stay on while plugged in</li>
- * <li>{@link BatteryManager#BATTERY_PLUGGED_AC} to stay on for AC charger</li>
- * <li>{@link BatteryManager#BATTERY_PLUGGED_USB} to stay on for USB charger</li>
- * </ul>
- * These values can be OR-ed together.
- */
- public static final String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
-
- /**
- * What happens when the user presses the end call button if they're not
- * on a call.<br/>
- * <b>Values:</b><br/>
- * 0 - The end button does nothing.<br/>
- * 1 - The end button goes to the home screen.<br/>
- * 2 - The end button puts the device to sleep and locks the keyguard.<br/>
- * 3 - The end button goes to the home screen. If the user is already on the
- * home screen, it puts the device to sleep.
- */
- public static final String END_BUTTON_BEHAVIOR = "end_button_behavior";
-
- /**
- * Whether Airplane Mode is on.
- */
- public static final String AIRPLANE_MODE_ON = "airplane_mode_on";
-
- /**
- * Constant for use in AIRPLANE_MODE_RADIOS to specify Bluetooth radio.
- */
- public static final String RADIO_BLUETOOTH = "bluetooth";
-
- /**
- * Constant for use in AIRPLANE_MODE_RADIOS to specify Wi-Fi radio.
- */
- public static final String RADIO_WIFI = "wifi";
-
- /**
- * Constant for use in AIRPLANE_MODE_RADIOS to specify Cellular radio.
- */
- public static final String RADIO_CELL = "cell";
-
- /**
- * A comma separated list of radios that need to be disabled when airplane mode
- * is on. This overrides WIFI_ON and BLUETOOTH_ON, if Wi-Fi and bluetooth are
- * included in the comma separated list.
- */
- public static final String AIRPLANE_MODE_RADIOS = "airplane_mode_radios";
-
- /**
- * The policy for deciding when Wi-Fi should go to sleep (which will in
- * turn switch to using the mobile data as an Internet connection).
- * <p>
- * Set to one of {@link #WIFI_SLEEP_POLICY_DEFAULT},
- * {@link #WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED}, or
- * {@link #WIFI_SLEEP_POLICY_NEVER}.
- *
- * @hide pending API council
- */
- public static final String WIFI_SLEEP_POLICY = "wifi_sleep_policy";
-
- /**
- * Value for {@link #WIFI_SLEEP_POLICY} to use the default Wi-Fi sleep
- * policy, which is to sleep shortly after the turning off
- * according to the {@link #STAY_ON_WHILE_PLUGGED_IN} setting.
- *
- * @hide pending API council
- */
- public static final int WIFI_SLEEP_POLICY_DEFAULT = 0;
-
- /**
- * Value for {@link #WIFI_SLEEP_POLICY} to use the default policy when
- * the device is on battery, and never go to sleep when the device is
- * plugged in.
- *
- * @hide pending API council
- */
- public static final int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1;
-
- /**
- * Value for {@link #WIFI_SLEEP_POLICY} to never go to sleep.
- *
- * @hide pending API council
- */
- public static final int WIFI_SLEEP_POLICY_NEVER = 2;
-
- /**
- * Whether to use static IP and other static network attributes.
- * <p>
- * Set to 1 for true and 0 for false.
- */
- public static final String WIFI_USE_STATIC_IP = "wifi_use_static_ip";
-
- /**
- * The static IP address.
- * <p>
- * Example: "192.168.1.51"
- */
- public static final String WIFI_STATIC_IP = "wifi_static_ip";
-
- /**
- * If using static IP, the gateway's IP address.
- * <p>
- * Example: "192.168.1.1"
- */
- public static final String WIFI_STATIC_GATEWAY = "wifi_static_gateway";
-
- /**
- * If using static IP, the net mask.
- * <p>
- * Example: "255.255.255.0"
- */
- public static final String WIFI_STATIC_NETMASK = "wifi_static_netmask";
-
- /**
- * If using static IP, the primary DNS's IP address.
- * <p>
- * Example: "192.168.1.1"
- */
- public static final String WIFI_STATIC_DNS1 = "wifi_static_dns1";
-
- /**
- * If using static IP, the secondary DNS's IP address.
- * <p>
- * Example: "192.168.1.2"
- */
- public static final String WIFI_STATIC_DNS2 = "wifi_static_dns2";
-
- /**
- * The number of radio channels that are allowed in the local
- * 802.11 regulatory domain.
- * @hide
- */
- public static final String WIFI_NUM_ALLOWED_CHANNELS = "wifi_num_allowed_channels";
-
- /**
- * Determines whether remote devices may discover and/or connect to
- * this device.
- * <P>Type: INT</P>
- * 2 -- discoverable and connectable
- * 1 -- connectable but not discoverable
- * 0 -- neither connectable nor discoverable
- */
- public static final String BLUETOOTH_DISCOVERABILITY =
- "bluetooth_discoverability";
-
- /**
- * Bluetooth discoverability timeout. If this value is nonzero, then
- * Bluetooth becomes discoverable for a certain number of seconds,
- * after which is becomes simply connectable. The value is in seconds.
- */
- public static final String BLUETOOTH_DISCOVERABILITY_TIMEOUT =
- "bluetooth_discoverability_timeout";
-
- /**
- * Whether autolock is enabled (0 = false, 1 = true)
- */
- public static final String LOCK_PATTERN_ENABLED = "lock_pattern_autolock";
-
- /**
- * Whether lock pattern is visible as user enters (0 = false, 1 = true)
- */
- public static final String LOCK_PATTERN_VISIBLE = "lock_pattern_visible_pattern";
-
- /**
- * Whether lock pattern will vibrate as user enters (0 = false, 1 = true)
- */
- public static final String LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED =
- "lock_pattern_tactile_feedback_enabled";
-
-
- /**
- * A formatted string of the next alarm that is set, or the empty string
- * if there is no alarm set.
- */
- public static final String NEXT_ALARM_FORMATTED = "next_alarm_formatted";
-
- /**
- * Scaling factor for fonts, float.
- */
- public static final String FONT_SCALE = "font_scale";
-
- /**
- * Name of an application package to be debugged.
- */
- public static final String DEBUG_APP = "debug_app";
-
- /**
- * If 1, when launching DEBUG_APP it will wait for the debugger before
- * starting user code. If 0, it will run normally.
- */
- public static final String WAIT_FOR_DEBUGGER = "wait_for_debugger";
-
- /**
- * Whether or not to dim the screen. 0=no 1=yes
- */
- public static final String DIM_SCREEN = "dim_screen";
-
- /**
- * The timeout before the screen turns off.
- */
- public static final String SCREEN_OFF_TIMEOUT = "screen_off_timeout";
-
- /**
- * The screen backlight brightness between 0 and 255.
- */
- public static final String SCREEN_BRIGHTNESS = "screen_brightness";
-
- /**
- * Control whether the process CPU usage meter should be shown.
- */
- public static final String SHOW_PROCESSES = "show_processes";
-
- /**
- * If 1, the activity manager will aggressively finish activities and
- * processes as soon as they are no longer needed. If 0, the normal
- * extended lifetime is used.
- */
- public static final String ALWAYS_FINISH_ACTIVITIES =
- "always_finish_activities";
-
-
- /**
- * Ringer mode. This is used internally, changing this value will not
- * change the ringer mode. See AudioManager.
- */
- public static final String MODE_RINGER = "mode_ringer";
-
- /**
- * Determines which streams are affected by ringer mode changes. The
- * stream type's bit should be set to 1 if it should be muted when going
- * into an inaudible ringer mode.
- */
- public static final String MODE_RINGER_STREAMS_AFFECTED = "mode_ringer_streams_affected";
-
- /**
- * Determines which streams are affected by mute. The
- * stream type's bit should be set to 1 if it should be muted when a mute request
- * is received.
- */
- public static final String MUTE_STREAMS_AFFECTED = "mute_streams_affected";
-
- /**
- * Whether vibrate is on for different events. This is used internally,
- * changing this value will not change the vibrate. See AudioManager.
- */
- public static final String VIBRATE_ON = "vibrate_on";
-
- /**
- * Ringer volume. This is used internally, changing this value will not
- * change the volume. See AudioManager.
- */
- public static final String VOLUME_RING = "volume_ring";
-
- /**
- * System/notifications volume. This is used internally, changing this
- * value will not change the volume. See AudioManager.
- */
- public static final String VOLUME_SYSTEM = "volume_system";
-
- /**
- * Voice call volume. This is used internally, changing this value will
- * not change the volume. See AudioManager.
- */
- public static final String VOLUME_VOICE = "volume_voice";
-
- /**
- * Music/media/gaming volume. This is used internally, changing this
- * value will not change the volume. See AudioManager.
- */
- public static final String VOLUME_MUSIC = "volume_music";
-
- /**
- * Alarm volume. This is used internally, changing this
- * value will not change the volume. See AudioManager.
- */
- public static final String VOLUME_ALARM = "volume_alarm";
-
- /**
- * Notification volume. This is used internally, changing this
- * value will not change the volume. See AudioManager.
- */
- public static final String VOLUME_NOTIFICATION = "volume_notification";
-
- /**
- * Whether the notifications should use the ring volume (value of 1) or
- * a separate notification volume (value of 0). In most cases, users
- * will have this enabled so the notification and ringer volumes will be
- * the same. However, power users can disable this and use the separate
- * notification volume control.
- * <p>
- * Note: This is a one-off setting that will be removed in the future
- * when there is profile support. For this reason, it is kept hidden
- * from the public APIs.
- *
- * @hide
- */
- public static final String NOTIFICATIONS_USE_RING_VOLUME =
- "notifications_use_ring_volume";
-
- /**
- * The mapping of stream type (integer) to its setting.
- */
- public static final String[] VOLUME_SETTINGS = {
- VOLUME_VOICE, VOLUME_SYSTEM, VOLUME_RING, VOLUME_MUSIC,
- VOLUME_ALARM, VOLUME_NOTIFICATION
- };
-
- /**
- * Appended to various volume related settings to record the previous
- * values before they the settings were affected by a silent/vibrate
- * ringer mode change.
- */
- public static final String APPEND_FOR_LAST_AUDIBLE = "_last_audible";
-
- /**
- * Persistent store for the system-wide default ringtone URI.
- * <p>
- * If you need to play the default ringtone at any given time, it is recommended
- * you give {@link #DEFAULT_RINGTONE_URI} to the media player. It will resolve
- * to the set default ringtone at the time of playing.
- *
- * @see #DEFAULT_RINGTONE_URI
- */
- public static final String RINGTONE = "ringtone";
-
- /**
- * A {@link Uri} that will point to the current default ringtone at any
- * given time.
- * <p>
- * If the current default ringtone is in the DRM provider and the caller
- * does not have permission, the exception will be a
- * FileNotFoundException.
- */
- public static final Uri DEFAULT_RINGTONE_URI = getUriFor(RINGTONE);
-
- /**
- * Persistent store for the system-wide default notification sound.
- *
- * @see #RINGTONE
- * @see #DEFAULT_NOTIFICATION_URI
- */
- public static final String NOTIFICATION_SOUND = "notification_sound";
-
- /**
- * A {@link Uri} that will point to the current default notification
- * sound at any given time.
- *
- * @see #DEFAULT_RINGTONE_URI
- */
- public static final Uri DEFAULT_NOTIFICATION_URI = getUriFor(NOTIFICATION_SOUND);
-
- /**
- * Setting to enable Auto Replace (AutoText) in text editors. 1 = On, 0 = Off
- */
- public static final String TEXT_AUTO_REPLACE = "auto_replace";
-
- /**
- * Setting to enable Auto Caps in text editors. 1 = On, 0 = Off
- */
- public static final String TEXT_AUTO_CAPS = "auto_caps";
-
- /**
- * Setting to enable Auto Punctuate in text editors. 1 = On, 0 = Off. This
- * feature converts two spaces to a "." and space.
- */
- public static final String TEXT_AUTO_PUNCTUATE = "auto_punctuate";
-
- /**
- * Setting to showing password characters in text editors. 1 = On, 0 = Off
- */
- public static final String TEXT_SHOW_PASSWORD = "show_password";
-
- public static final String SHOW_GTALK_SERVICE_STATUS =
- "SHOW_GTALK_SERVICE_STATUS";
-
- /**
- * Name of activity to use for wallpaper on the home screen.
- */
- public static final String WALLPAPER_ACTIVITY = "wallpaper_activity";
-
- /**
- * Value to specify if the user prefers the date, time and time zone
- * to be automatically fetched from the network (NITZ). 1=yes, 0=no
- */
- public static final String AUTO_TIME = "auto_time";
-
- /**
- * Display times as 12 or 24 hours
- * 12
- * 24
- */
- public static final String TIME_12_24 = "time_12_24";
-
- /**
- * Date format string
- * mm/dd/yyyy
- * dd/mm/yyyy
- * yyyy/mm/dd
- */
- public static final String DATE_FORMAT = "date_format";
-
- /**
- * Whether the setup wizard has been run before (on first boot), or if
- * it still needs to be run.
- *
- * nonzero = it has been run in the past
- * 0 = it has not been run in the past
- */
- public static final String SETUP_WIZARD_HAS_RUN = "setup_wizard_has_run";
-
- /**
- * Scaling factor for normal window animations. Setting to 0 will disable window
- * animations.
- */
- public static final String WINDOW_ANIMATION_SCALE = "window_animation_scale";
-
- /**
- * Scaling factor for activity transition animations. Setting to 0 will disable window
- * animations.
- */
- public static final String TRANSITION_ANIMATION_SCALE = "transition_animation_scale";
-
- /**
- * Scaling factor for normal window animations. Setting to 0 will disable window
- * animations.
- * @hide
- */
- public static final String FANCY_IME_ANIMATIONS = "fancy_ime_animations";
-
- /**
- * Control whether the accelerometer will be used to change screen
- * orientation. If 0, it will not be used unless explicitly requested
- * by the application; if 1, it will be used by default unless explicitly
- * disabled by the application.
- */
- public static final String ACCELEROMETER_ROTATION = "accelerometer_rotation";
-
- /**
- * Whether the audible DTMF tones are played by the dialer when dialing. The value is
- * boolean (1 or 0).
- */
- public static final String DTMF_TONE_WHEN_DIALING = "dtmf_tone";
-
- /**
- * Whether the sounds effects (key clicks, lid open ...) are enabled. The value is
- * boolean (1 or 0).
- */
- public static final String SOUND_EFFECTS_ENABLED = "sound_effects_enabled";
-
- /**
- * Whether the haptic feedback (long presses, ...) are enabled. The value is
- * boolean (1 or 0).
- */
- public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
-
- // Settings moved to Settings.Secure
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#LOCATION_PROVIDERS_ALLOWED}
- * instead
- */
- @Deprecated
- public static final String ADB_ENABLED = Secure.ADB_ENABLED;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#ANDROID_ID} instead
- */
- @Deprecated
- public static final String ANDROID_ID = Secure.ANDROID_ID;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#BLUETOOTH_ON} instead
- */
- @Deprecated
- public static final String BLUETOOTH_ON = Secure.BLUETOOTH_ON;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#DATA_ROAMING} instead
- */
- @Deprecated
- public static final String DATA_ROAMING = Secure.DATA_ROAMING;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#DEVICE_PROVISIONED} instead
- */
- @Deprecated
- public static final String DEVICE_PROVISIONED = Secure.DEVICE_PROVISIONED;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#HTTP_PROXY} instead
- */
- @Deprecated
- public static final String HTTP_PROXY = Secure.HTTP_PROXY;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#INSTALL_NON_MARKET_APPS} instead
- */
- @Deprecated
- public static final String INSTALL_NON_MARKET_APPS = Secure.INSTALL_NON_MARKET_APPS;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#LOCATION_PROVIDERS_ALLOWED}
- * instead
- */
- @Deprecated
- public static final String LOCATION_PROVIDERS_ALLOWED = Secure.LOCATION_PROVIDERS_ALLOWED;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#LOGGING_ID} instead
- */
- @Deprecated
- public static final String LOGGING_ID = Secure.LOGGING_ID;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#NETWORK_PREFERENCE} instead
- */
- @Deprecated
- public static final String NETWORK_PREFERENCE = Secure.NETWORK_PREFERENCE;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#PARENTAL_CONTROL_ENABLED}
- * instead
- */
- @Deprecated
- public static final String PARENTAL_CONTROL_ENABLED = Secure.PARENTAL_CONTROL_ENABLED;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#PARENTAL_CONTROL_LAST_UPDATE}
- * instead
- */
- @Deprecated
- public static final String PARENTAL_CONTROL_LAST_UPDATE = Secure.PARENTAL_CONTROL_LAST_UPDATE;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#PARENTAL_CONTROL_REDIRECT_URL}
- * instead
- */
- @Deprecated
- public static final String PARENTAL_CONTROL_REDIRECT_URL =
- Secure.PARENTAL_CONTROL_REDIRECT_URL;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#SETTINGS_CLASSNAME} instead
- */
- @Deprecated
- public static final String SETTINGS_CLASSNAME = Secure.SETTINGS_CLASSNAME;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#USB_MASS_STORAGE_ENABLED} instead
- */
- @Deprecated
- public static final String USB_MASS_STORAGE_ENABLED = Secure.USB_MASS_STORAGE_ENABLED;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#USE_GOOGLE_MAIL} instead
- */
- @Deprecated
- public static final String USE_GOOGLE_MAIL = Secure.USE_GOOGLE_MAIL;
-
-// /**
-// * @deprecated Use {@link android.provider.Settings.Secure#WIFI_MAX_DHCP_RETRY_COUNT}
-// * instead
-// */
- @Deprecated
- public static final String WIFI_MAX_DHCP_RETRY_COUNT = Secure.WIFI_MAX_DHCP_RETRY_COUNT;
-
-// /**
-// * @deprecated Use
-// * {@link android.provider.Settings.Secure#WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS}
-// * instead
-// */
- @Deprecated
- public static final String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS =
- Secure.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS;
-
- /**
- * @deprecated Use
- * {@link android.provider.Settings.Secure#WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON} instead
- */
- @Deprecated
- public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
- Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON;
-
- /**
- * @deprecated Use
- * {@link android.provider.Settings.Secure#WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY} instead
- */
- @Deprecated
- public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY =
- Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#WIFI_NUM_OPEN_NETWORKS_KEPT}
- * instead
- */
- @Deprecated
- public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = Secure.WIFI_NUM_OPEN_NETWORKS_KEPT;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#WIFI_ON} instead
- */
- @Deprecated
- public static final String WIFI_ON = Secure.WIFI_ON;
-
- /**
- * @deprecated Use
- * {@link android.provider.Settings.Secure#WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE}
- * instead
- */
- @Deprecated
- public static final String WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE =
- Secure.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#WIFI_WATCHDOG_AP_COUNT} instead
- */
- @Deprecated
- public static final String WIFI_WATCHDOG_AP_COUNT = Secure.WIFI_WATCHDOG_AP_COUNT;
-
- /**
- * @deprecated Use
- * {@link android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS} instead
- */
- @Deprecated
- public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS =
- Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS;
-
- /**
- * @deprecated Use
- * {@link android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED} instead
- */
- @Deprecated
- public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED =
- Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED;
-
- /**
- * @deprecated Use
- * {@link android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS}
- * instead
- */
- @Deprecated
- public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS =
- Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS;
-
- /**
- * @deprecated Use
- * {@link android.provider.Settings.Secure#WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT} instead
- */
- @Deprecated
- public static final String WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT =
- Secure.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#WIFI_WATCHDOG_MAX_AP_CHECKS}
- * instead
- */
- @Deprecated
- public static final String WIFI_WATCHDOG_MAX_AP_CHECKS = Secure.WIFI_WATCHDOG_MAX_AP_CHECKS;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#WIFI_WATCHDOG_ON} instead
- */
- @Deprecated
- public static final String WIFI_WATCHDOG_ON = Secure.WIFI_WATCHDOG_ON;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#WIFI_WATCHDOG_PING_COUNT} instead
- */
- @Deprecated
- public static final String WIFI_WATCHDOG_PING_COUNT = Secure.WIFI_WATCHDOG_PING_COUNT;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#WIFI_WATCHDOG_PING_DELAY_MS}
- * instead
- */
- @Deprecated
- public static final String WIFI_WATCHDOG_PING_DELAY_MS = Secure.WIFI_WATCHDOG_PING_DELAY_MS;
-
- /**
- * @deprecated Use {@link android.provider.Settings.Secure#WIFI_WATCHDOG_PING_TIMEOUT_MS}
- * instead
- */
- @Deprecated
- public static final String WIFI_WATCHDOG_PING_TIMEOUT_MS =
- Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS;
- }
-
- /**
- * Secure system settings, containing system preferences that applications
- * can read but are not allowed to write. These are for preferences that
- * the user must explicitly modify through the system UI or specialized
- * APIs for those values, not modified directly by applications.
- */
- public static final class Secure extends NameValueTable {
- public static final String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version";
-
- private static volatile NameValueCache mNameValueCache = null;
-
- /**
- * Look up a name in the database.
- * @param resolver to access the database with
- * @param name to look up in the table
- * @return the corresponding value, or null if not present
- */
- public synchronized static String getString(ContentResolver resolver, String name) {
- if (mNameValueCache == null) {
- mNameValueCache = new NameValueCache(SYS_PROP_SETTING_VERSION, CONTENT_URI);
- }
- return mNameValueCache.getString(resolver, name);
- }
-
- /**
- * Store a name/value pair into the database.
- * @param resolver to access the database with
- * @param name to store
- * @param value to associate with the name
- * @return true if the value was set, false on database errors
- */
- public static boolean putString(ContentResolver resolver,
- String name, String value) {
- return putString(resolver, CONTENT_URI, name, value);
- }
-
- /**
- * Construct the content URI for a particular name/value pair,
- * useful for monitoring changes with a ContentObserver.
- * @param name to look up in the table
- * @return the corresponding content URI, or null if not present
- */
- public static Uri getUriFor(String name) {
- return getUriFor(CONTENT_URI, name);
- }
-
- /**
- * Convenience function for retrieving a single secure settings value
- * as an integer. Note that internally setting values are always
- * stored as strings; this function converts the string to an integer
- * for you. The default value will be returned if the setting is
- * not defined or not an integer.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to retrieve.
- * @param def Value to return if the setting is not defined.
- *
- * @return The setting's current value, or 'def' if it is not defined
- * or not a valid integer.
- */
- public static int getInt(ContentResolver cr, String name, int def) {
- String v = getString(cr, name);
- try {
- return v != null ? Integer.parseInt(v) : def;
- } catch (NumberFormatException e) {
- return def;
- }
- }
-
- /**
- * Convenience function for retrieving a single secure settings value
- * as an integer. Note that internally setting values are always
- * stored as strings; this function converts the string to an integer
- * for you.
- * <p>
- * This version does not take a default value. If the setting has not
- * been set, or the string value is not a number,
- * it throws {@link SettingNotFoundException}.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to retrieve.
- *
- * @throws SettingNotFoundException Thrown if a setting by the given
- * name can't be found or the setting value is not an integer.
- *
- * @return The setting's current value.
- */
- public static int getInt(ContentResolver cr, String name)
- throws SettingNotFoundException {
- String v = getString(cr, name);
- try {
- return Integer.parseInt(v);
- } catch (NumberFormatException e) {
- throw new SettingNotFoundException(name);
- }
- }
-
- /**
- * Convenience function for updating a single settings value as an
- * integer. This will either create a new entry in the table if the
- * given name does not exist, or modify the value of the existing row
- * with that name. Note that internally setting values are always
- * stored as strings, so this function converts the given value to a
- * string before storing it.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to modify.
- * @param value The new value for the setting.
- * @return true if the value was set, false on database errors
- */
- public static boolean putInt(ContentResolver cr, String name, int value) {
- return putString(cr, name, Integer.toString(value));
- }
-
- /**
- * Convenience function for retrieving a single secure settings value
- * as a {@code long}. Note that internally setting values are always
- * stored as strings; this function converts the string to a {@code long}
- * for you. The default value will be returned if the setting is
- * not defined or not a {@code long}.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to retrieve.
- * @param def Value to return if the setting is not defined.
- *
- * @return The setting's current value, or 'def' if it is not defined
- * or not a valid {@code long}.
- */
- public static long getLong(ContentResolver cr, String name, long def) {
- String valString = getString(cr, name);
- long value;
- try {
- value = valString != null ? Long.parseLong(valString) : def;
- } catch (NumberFormatException e) {
- value = def;
- }
- return value;
- }
-
- /**
- * Convenience function for retrieving a single secure settings value
- * as a {@code long}. Note that internally setting values are always
- * stored as strings; this function converts the string to a {@code long}
- * for you.
- * <p>
- * This version does not take a default value. If the setting has not
- * been set, or the string value is not a number,
- * it throws {@link SettingNotFoundException}.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to retrieve.
- *
- * @return The setting's current value.
- * @throws SettingNotFoundException Thrown if a setting by the given
- * name can't be found or the setting value is not an integer.
- */
- public static long getLong(ContentResolver cr, String name)
- throws SettingNotFoundException {
- String valString = getString(cr, name);
- try {
- return Long.parseLong(valString);
- } catch (NumberFormatException e) {
- throw new SettingNotFoundException(name);
- }
- }
-
- /**
- * Convenience function for updating a secure settings value as a long
- * integer. This will either create a new entry in the table if the
- * given name does not exist, or modify the value of the existing row
- * with that name. Note that internally setting values are always
- * stored as strings, so this function converts the given value to a
- * string before storing it.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to modify.
- * @param value The new value for the setting.
- * @return true if the value was set, false on database errors
- */
- public static boolean putLong(ContentResolver cr, String name, long value) {
- return putString(cr, name, Long.toString(value));
- }
-
- /**
- * Convenience function for retrieving a single secure settings value
- * as a floating point number. Note that internally setting values are
- * always stored as strings; this function converts the string to an
- * float for you. The default value will be returned if the setting
- * is not defined or not a valid float.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to retrieve.
- * @param def Value to return if the setting is not defined.
- *
- * @return The setting's current value, or 'def' if it is not defined
- * or not a valid float.
- */
- public static float getFloat(ContentResolver cr, String name, float def) {
- String v = getString(cr, name);
- try {
- return v != null ? Float.parseFloat(v) : def;
- } catch (NumberFormatException e) {
- return def;
- }
- }
-
- /**
- * Convenience function for retrieving a single secure settings value
- * as a float. Note that internally setting values are always
- * stored as strings; this function converts the string to a float
- * for you.
- * <p>
- * This version does not take a default value. If the setting has not
- * been set, or the string value is not a number,
- * it throws {@link SettingNotFoundException}.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to retrieve.
- *
- * @throws SettingNotFoundException Thrown if a setting by the given
- * name can't be found or the setting value is not a float.
- *
- * @return The setting's current value.
- */
- public static float getFloat(ContentResolver cr, String name)
- throws SettingNotFoundException {
- String v = getString(cr, name);
- try {
- return Float.parseFloat(v);
- } catch (NumberFormatException e) {
- throw new SettingNotFoundException(name);
- }
- }
-
- /**
- * Convenience function for updating a single settings value as a
- * floating point number. This will either create a new entry in the
- * table if the given name does not exist, or modify the value of the
- * existing row with that name. Note that internally setting values
- * are always stored as strings, so this function converts the given
- * value to a string before storing it.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to modify.
- * @param value The new value for the setting.
- * @return true if the value was set, false on database errors
- */
- public static boolean putFloat(ContentResolver cr, String name, float value) {
- return putString(cr, name, Float.toString(value));
- }
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://" + AUTHORITY + "/secure");
-
- /**
- * Whether ADB is enabled.
- */
- public static final String ADB_ENABLED = "adb_enabled";
-
- /**
- * Setting to allow mock locations and location provider status to be injected into the
- * LocationManager service for testing purposes during application development. These
- * locations and status values override actual location and status information generated
- * by network, gps, or other location providers.
- */
- public static final String ALLOW_MOCK_LOCATION = "mock_location";
-
- /**
- * The Android ID (a unique 64-bit value) as a hex string.
- * Identical to that obtained by calling
- * GoogleLoginService.getAndroidId(); it is also placed here
- * so you can get it without binding to a service.
- */
- public static final String ANDROID_ID = "android_id";
-
- /**
- * Whether bluetooth is enabled/disabled
- * 0=disabled. 1=enabled.
- */
- public static final String BLUETOOTH_ON = "bluetooth_on";
-
- /**
- * Get the key that retrieves a bluetooth headset's priority.
- * @hide
- */
- public static final String getBluetoothHeadsetPriorityKey(String address) {
- return ("bluetooth_headset_priority_" + address.toUpperCase());
- }
-
- /**
- * Get the key that retrieves a bluetooth a2dp sink's priority.
- * @hide
- */
- public static final String getBluetoothA2dpSinkPriorityKey(String address) {
- return ("bluetooth_a2dp_sink_priority_" + address.toUpperCase());
- }
-
- /**
- * Whether or not data roaming is enabled. (0 = false, 1 = true)
- */
- public static final String DATA_ROAMING = "data_roaming";
-
- /**
- * Setting to record the input method used by default, holding the ID
- * of the desired method.
- */
- public static final String DEFAULT_INPUT_METHOD = "default_input_method";
-
- /**
- * Whether the device has been provisioned (0 = false, 1 = true)
- */
- public static final String DEVICE_PROVISIONED = "device_provisioned";
-
- /**
- * List of input methods that are currently enabled. This is a string
- * containing the IDs of all enabled input methods, each ID separated
- * by ':'.
- */
- public static final String ENABLED_INPUT_METHODS = "enabled_input_methods";
-
- /**
- * Host name and port for a user-selected proxy.
- */
- public static final String HTTP_PROXY = "http_proxy";
-
- /**
- * Whether the package installer should allow installation of apps downloaded from
- * sources other than the Android Market (vending machine).
- *
- * 1 = allow installing from other sources
- * 0 = only allow installing from the Android Market
- */
- public static final String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
-
- /**
- * Comma-separated list of location providers that activities may access.
- */
- public static final String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed";
-
- /**
- * The Logging ID (a unique 64-bit value) as a hex string.
- * Used as a pseudonymous identifier for logging.
- * @deprecated This identifier is poorly initialized and has
- * many collisions. It should not be used.
- */
- @Deprecated
- public static final String LOGGING_ID = "logging_id";
-
- /**
- * The Logging ID (a unique 64-bit value) as a hex string.
- * Used as a pseudonymous identifier for logging.
- * @hide
- */
- public static final String LOGGING_ID2 = "logging_id2";
-
- /**
- * User preference for which network(s) should be used. Only the
- * connectivity service should touch this.
- */
- public static final String NETWORK_PREFERENCE = "network_preference";
-
- /**
- */
- public static final String PARENTAL_CONTROL_ENABLED = "parental_control_enabled";
-
- /**
- */
- public static final String PARENTAL_CONTROL_LAST_UPDATE = "parental_control_last_update";
-
- /**
- */
- public static final String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
-
- /**
- * Settings classname to launch when Settings is clicked from All
- * Applications. Needed because of user testing between the old
- * and new Settings apps.
- */
- // TODO: 881807
- public static final String SETTINGS_CLASSNAME = "settings_classname";
-
- /**
- * USB Mass Storage Enabled
- */
- public static final String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
-
- /**
- * If this setting is set (to anything), then all references
- * to Gmail on the device must change to Google Mail.
- */
- public static final String USE_GOOGLE_MAIL = "use_google_mail";
-
- /**
- * Whether to notify the user of open networks.
- * <p>
- * If not connected and the scan results have an open network, we will
- * put this notification up. If we attempt to connect to a network or
- * the open network(s) disappear, we remove the notification. When we
- * show the notification, we will not show it again for
- * {@link android.provider.Settings.Secure#WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY} time.
- */
- public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
- "wifi_networks_available_notification_on";
-
- /**
- * Delay (in seconds) before repeating the Wi-Fi networks available notification.
- * Connecting to a network will reset the timer.
- */
- public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY =
- "wifi_networks_available_repeat_delay";
-
- /**
- * The number of radio channels that are allowed in the local
- * 802.11 regulatory domain.
- * @hide
- */
- public static final String WIFI_NUM_ALLOWED_CHANNELS = "wifi_num_allowed_channels";
-
- /**
- * When the number of open networks exceeds this number, the
- * least-recently-used excess networks will be removed.
- */
- public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
-
- /**
- * Whether the Wi-Fi should be on. Only the Wi-Fi service should touch this.
- */
- public static final String WIFI_ON = "wifi_on";
-
- /**
- * The acceptable packet loss percentage (range 0 - 100) before trying
- * another AP on the same network.
- */
- public static final String WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE =
- "wifi_watchdog_acceptable_packet_loss_percentage";
-
- /**
- * The number of access points required for a network in order for the
- * watchdog to monitor it.
- */
- public static final String WIFI_WATCHDOG_AP_COUNT = "wifi_watchdog_ap_count";
-
- /**
- * The delay between background checks.
- */
- public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS =
- "wifi_watchdog_background_check_delay_ms";
-
- /**
- * Whether the Wi-Fi watchdog is enabled for background checking even
- * after it thinks the user has connected to a good access point.
- */
- public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED =
- "wifi_watchdog_background_check_enabled";
-
- /**
- * The timeout for a background ping
- */
- public static final String WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS =
- "wifi_watchdog_background_check_timeout_ms";
-
- /**
- * The number of initial pings to perform that *may* be ignored if they
- * fail. Again, if these fail, they will *not* be used in packet loss
- * calculation. For example, one network always seemed to time out for
- * the first couple pings, so this is set to 3 by default.
- */
- public static final String WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT =
- "wifi_watchdog_initial_ignored_ping_count";
-
- /**
- * The maximum number of access points (per network) to attempt to test.
- * If this number is reached, the watchdog will no longer monitor the
- * initial connection state for the network. This is a safeguard for
- * networks containing multiple APs whose DNS does not respond to pings.
- */
- public static final String WIFI_WATCHDOG_MAX_AP_CHECKS = "wifi_watchdog_max_ap_checks";
-
- /**
- * Whether the Wi-Fi watchdog is enabled.
- */
- public static final String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
-
- /**
- * A comma-separated list of SSIDs for which the Wi-Fi watchdog should be enabled.
- * @hide pending API council
- */
- public static final String WIFI_WATCHDOG_WATCH_LIST = "wifi_watchdog_watch_list";
-
- /**
- * The number of pings to test if an access point is a good connection.
- */
- public static final String WIFI_WATCHDOG_PING_COUNT = "wifi_watchdog_ping_count";
-
- /**
- * The delay between pings.
- */
- public static final String WIFI_WATCHDOG_PING_DELAY_MS = "wifi_watchdog_ping_delay_ms";
-
- /**
- * The timeout per ping.
- */
- public static final String WIFI_WATCHDOG_PING_TIMEOUT_MS = "wifi_watchdog_ping_timeout_ms";
-
- /**
- * The maximum number of times we will retry a connection to an access
- * point for which we have failed in acquiring an IP address from DHCP.
- * A value of N means that we will make N+1 connection attempts in all.
- *
- * @hide pending API Council approval
- */
- public static final String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
-
- /**
- * Maximum amount of time in milliseconds to hold a wakelock while waiting for mobile
- * data connectivity to be established after a disconnect from Wi-Fi.
- *
- * @hide pending API Council approval
- */
- public static final String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS =
- "wifi_mobile_data_transition_wakelock_timeout_ms";
-
- /**
- * Whether background data usage is allowed by the user. See
- * ConnectivityManager for more info.
- *
- * @hide pending API council
- */
- public static final String BACKGROUND_DATA = "background_data";
- }
-
- /**
- * Gservices settings, containing the network names for Google's
- * various services. This table holds simple name/addr pairs.
- * Addresses can be accessed through the getString() method.
- *
- * TODO: This should move to partner/google/... somewhere.
- *
- * @hide
- */
- public static final class Gservices extends NameValueTable {
- public static final String SYS_PROP_SETTING_VERSION = "sys.settings_gservices_version";
-
- /**
- * Intent action broadcast when the Gservices table is updated by the server.
- * This is broadcast once after settings change (so many values may have been updated).
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String CHANGED_ACTION =
- "com.google.gservices.intent.action.GSERVICES_CHANGED";
-
- private static volatile NameValueCache mNameValueCache = null;
- private static final Object mNameValueCacheLock = new Object();
-
- /**
- * Look up a name in the database.
- * @param resolver to access the database with
- * @param name to look up in the table
- * @return the corresponding value, or null if not present
- */
- public static String getString(ContentResolver resolver, String name) {
- synchronized (mNameValueCacheLock) {
- if (mNameValueCache == null) {
- mNameValueCache = new NameValueCache(SYS_PROP_SETTING_VERSION, CONTENT_URI);
- }
- return mNameValueCache.getString(resolver, name);
- }
- }
-
- /**
- * Store a name/value pair into the database.
- * @param resolver to access the database with
- * @param name to store
- * @param value to associate with the name
- * @return true if the value was set, false on database errors
- */
- public static boolean putString(ContentResolver resolver,
- String name, String value) {
- return putString(resolver, CONTENT_URI, name, value);
- }
-
- /**
- * Look up the value for name in the database, convert it to an int using Integer.parseInt
- * and return it. If it is null or if a NumberFormatException is caught during the
- * conversion then return defValue.
- */
- public static int getInt(ContentResolver resolver, String name, int defValue) {
- String valString = getString(resolver, name);
- int value;
- try {
- value = valString != null ? Integer.parseInt(valString) : defValue;
- } catch (NumberFormatException e) {
- value = defValue;
- }
- return value;
- }
-
- /**
- * Look up the value for name in the database, convert it to a long using Long.parseLong
- * and return it. If it is null or if a NumberFormatException is caught during the
- * conversion then return defValue.
- */
- public static long getLong(ContentResolver resolver, String name, long defValue) {
- String valString = getString(resolver, name);
- long value;
- try {
- value = valString != null ? Long.parseLong(valString) : defValue;
- } catch (NumberFormatException e) {
- value = defValue;
- }
- return value;
- }
-
- /**
- * Construct the content URI for a particular name/value pair,
- * useful for monitoring changes with a ContentObserver.
- * @param name to look up in the table
- * @return the corresponding content URI, or null if not present
- */
- public static Uri getUriFor(String name) {
- return getUriFor(CONTENT_URI, name);
- }
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://" + AUTHORITY + "/gservices");
-
- /**
- * MMS - URL to use for HTTP "x-wap-profile" header
- */
- public static final String MMS_X_WAP_PROFILE_URL
- = "mms_x_wap_profile_url";
-
- /**
- * YouTube - the flag to indicate whether to use proxy
- */
- public static final String YOUTUBE_USE_PROXY
- = "youtube_use_proxy";
-
- /**
- * MMS - maximum message size in bytes for a MMS message.
- */
- public static final String MMS_MAXIMUM_MESSAGE_SIZE
- = "mms_maximum_message_size";
-
- /**
- * Event tags from the kernel event log to upload during checkin.
- */
- public static final String CHECKIN_EVENTS = "checkin_events";
-
- /**
- * Event tags for list of services to upload during checkin.
- */
- public static final String CHECKIN_DUMPSYS_LIST = "checkin_dumpsys_list";
-
- /**
- * The interval (in seconds) between periodic checkin attempts.
- */
- public static final String CHECKIN_INTERVAL = "checkin_interval";
-
- /**
- * How frequently (in seconds) to check the memory status of the
- * device.
- */
- public static final String MEMCHECK_INTERVAL = "memcheck_interval";
-
- /**
- * Max frequency (in seconds) to log memory check stats, in realtime
- * seconds. This allows for throttling of logs when the device is
- * running for large amounts of time.
- */
- public static final String MEMCHECK_LOG_REALTIME_INTERVAL =
- "memcheck_log_realtime_interval";
-
- /**
- * Boolean indicating whether rebooting due to system memory checks
- * is enabled.
- */
- public static final String MEMCHECK_SYSTEM_ENABLED = "memcheck_system_enabled";
-
- /**
- * How many bytes the system process must be below to avoid scheduling
- * a soft reboot. This reboot will happen when it is next determined
- * to be a good time.
- */
- public static final String MEMCHECK_SYSTEM_SOFT_THRESHOLD = "memcheck_system_soft";
-
- /**
- * How many bytes the system process must be below to avoid scheduling
- * a hard reboot. This reboot will happen immediately.
- */
- public static final String MEMCHECK_SYSTEM_HARD_THRESHOLD = "memcheck_system_hard";
-
- /**
- * How many bytes the phone process must be below to avoid scheduling
- * a soft restart. This restart will happen when it is next determined
- * to be a good time.
- */
- public static final String MEMCHECK_PHONE_SOFT_THRESHOLD = "memcheck_phone_soft";
-
- /**
- * How many bytes the phone process must be below to avoid scheduling
- * a hard restart. This restart will happen immediately.
- */
- public static final String MEMCHECK_PHONE_HARD_THRESHOLD = "memcheck_phone_hard";
-
- /**
- * Boolean indicating whether restarting the phone process due to
- * memory checks is enabled.
- */
- public static final String MEMCHECK_PHONE_ENABLED = "memcheck_phone_enabled";
-
- /**
- * First time during the day it is okay to kill processes
- * or reboot the device due to low memory situations. This number is
- * in seconds since midnight.
- */
- public static final String MEMCHECK_EXEC_START_TIME = "memcheck_exec_start_time";
-
- /**
- * Last time during the day it is okay to kill processes
- * or reboot the device due to low memory situations. This number is
- * in seconds since midnight.
- */
- public static final String MEMCHECK_EXEC_END_TIME = "memcheck_exec_end_time";
-
- /**
- * How long the screen must have been off in order to kill processes
- * or reboot. This number is in seconds. A value of -1 means to
- * entirely disregard whether the screen is on.
- */
- public static final String MEMCHECK_MIN_SCREEN_OFF = "memcheck_min_screen_off";
-
- /**
- * How much time there must be until the next alarm in order to kill processes
- * or reboot. This number is in seconds. Note: this value must be
- * smaller than {@link #MEMCHECK_RECHECK_INTERVAL} or else it will
- * always see an alarm scheduled within its time.
- */
- public static final String MEMCHECK_MIN_ALARM = "memcheck_min_alarm";
-
- /**
- * How frequently to check whether it is a good time to restart things,
- * if the device is in a bad state. This number is in seconds. Note:
- * this value must be larger than {@link #MEMCHECK_MIN_ALARM} or else
- * the alarm to schedule the recheck will always appear within the
- * minimum "do not execute now" time.
- */
- public static final String MEMCHECK_RECHECK_INTERVAL = "memcheck_recheck_interval";
-
- /**
- * How frequently (in DAYS) to reboot the device. If 0, no reboots
- * will occur.
- */
- public static final String REBOOT_INTERVAL = "reboot_interval";
-
- /**
- * First time during the day it is okay to force a reboot of the
- * device (if REBOOT_INTERVAL is set). This number is
- * in seconds since midnight.
- */
- public static final String REBOOT_START_TIME = "reboot_start_time";
-
- /**
- * The window of time (in seconds) after each REBOOT_INTERVAL in which
- * a reboot can be executed. If 0, a reboot will always be executed at
- * exactly the given time. Otherwise, it will only be executed if
- * the device is idle within the window.
- */
- public static final String REBOOT_WINDOW = "reboot_window";
-
- /**
- * The minimum version of the server that is required in order for the device to accept
- * the server's recommendations about the initial sync settings to use. When this is unset,
- * blank or can't be interpreted as an integer then we will not ask the server for a
- * recommendation.
- */
- public static final String GMAIL_CONFIG_INFO_MIN_SERVER_VERSION =
- "gmail_config_info_min_server_version";
-
- /**
- * Controls whether Gmail offers a preview button for images.
- */
- public static final String GMAIL_DISALLOW_IMAGE_PREVIEWS = "gmail_disallow_image_previews";
-
- /**
- * The timeout in milliseconds that Gmail uses when opening a connection and reading
- * from it. A missing value or a value of -1 instructs Gmail to use the defaults provided
- * by GoogleHttpClient.
- */
- public static final String GMAIL_TIMEOUT_MS = "gmail_timeout_ms";
-
- /**
- * Controls whether Gmail will request an expedited sync when a message is sent. Value must
- * be an integer where non-zero means true. Defaults to 1.
- */
- public static final String GMAIL_SEND_IMMEDIATELY = "gmail_send_immediately";
-
- /**
- * Controls whether gmail buffers server responses. Possible values are "memory", for a
- * memory-based buffer, or "file", for a temp-file-based buffer. All other values
- * (including not set) disable buffering.
- */
- public static final String GMAIL_BUFFER_SERVER_RESPONSE = "gmail_buffer_server_response";
-
- /**
- * Hostname of the GTalk server.
- */
- public static final String GTALK_SERVICE_HOSTNAME = "gtalk_hostname";
-
- /**
- * Secure port of the GTalk server.
- */
- public static final String GTALK_SERVICE_SECURE_PORT = "gtalk_secure_port";
-
- /**
- * The server configurable RMQ acking interval
- */
- public static final String GTALK_SERVICE_RMQ_ACK_INTERVAL = "gtalk_rmq_ack_interval";
-
- /**
- * The minimum reconnect delay for short network outages or when the network is suspended
- * due to phone use.
- */
- public static final String GTALK_SERVICE_MIN_RECONNECT_DELAY_SHORT =
- "gtalk_min_reconnect_delay_short";
-
- /**
- * The reconnect variant range for short network outages or when the network is suspended
- * due to phone use. A random number between 0 and this constant is computed and
- * added to {@link #GTALK_SERVICE_MIN_RECONNECT_DELAY_SHORT} to form the initial reconnect
- * delay.
- */
- public static final String GTALK_SERVICE_RECONNECT_VARIANT_SHORT =
- "gtalk_reconnect_variant_short";
-
- /**
- * The minimum reconnect delay for long network outages
- */
- public static final String GTALK_SERVICE_MIN_RECONNECT_DELAY_LONG =
- "gtalk_min_reconnect_delay_long";
-
- /**
- * The reconnect variant range for long network outages. A random number between 0 and this
- * constant is computed and added to {@link #GTALK_SERVICE_MIN_RECONNECT_DELAY_LONG} to
- * form the initial reconnect delay.
- */
- public static final String GTALK_SERVICE_RECONNECT_VARIANT_LONG =
- "gtalk_reconnect_variant_long";
-
- /**
- * The maximum reconnect delay time, in milliseconds.
- */
- public static final String GTALK_SERVICE_MAX_RECONNECT_DELAY =
- "gtalk_max_reconnect_delay";
-
- /**
- * The network downtime that is considered "short" for the above calculations,
- * in milliseconds.
- */
- public static final String GTALK_SERVICE_SHORT_NETWORK_DOWNTIME =
- "gtalk_short_network_downtime";
-
- /**
- * How frequently we send heartbeat pings to the GTalk server. Receiving a server packet
- * will reset the heartbeat timer. The away heartbeat should be used when the user is
- * logged into the GTalk app, but not actively using it.
- */
- public static final String GTALK_SERVICE_AWAY_HEARTBEAT_INTERVAL_MS =
- "gtalk_heartbeat_ping_interval_ms"; // keep the string backward compatible
-
- /**
- * How frequently we send heartbeat pings to the GTalk server. Receiving a server packet
- * will reset the heartbeat timer. The active heartbeat should be used when the user is
- * actively using the GTalk app.
- */
- public static final String GTALK_SERVICE_ACTIVE_HEARTBEAT_INTERVAL_MS =
- "gtalk_active_heartbeat_ping_interval_ms";
-
- /**
- * How frequently we send heartbeat pings to the GTalk server. Receiving a server packet
- * will reset the heartbeat timer. The sync heartbeat should be used when the user isn't
- * logged into the GTalk app, but auto-sync is enabled.
- */
- public static final String GTALK_SERVICE_SYNC_HEARTBEAT_INTERVAL_MS =
- "gtalk_sync_heartbeat_ping_interval_ms";
-
- /**
- * How frequently we send heartbeat pings to the GTalk server. Receiving a server packet
- * will reset the heartbeat timer. The no sync heartbeat should be used when the user isn't
- * logged into the GTalk app, and auto-sync is not enabled.
- */
- public static final String GTALK_SERVICE_NOSYNC_HEARTBEAT_INTERVAL_MS =
- "gtalk_nosync_heartbeat_ping_interval_ms";
-
- /**
- * How long we wait to receive a heartbeat ping acknowledgement (or another packet)
- * from the GTalk server, before deeming the connection dead.
- */
- public static final String GTALK_SERVICE_HEARTBEAT_ACK_TIMEOUT_MS =
- "gtalk_heartbeat_ack_timeout_ms";
-
- /**
- * How long after screen is turned off before we consider the user to be idle.
- */
- public static final String GTALK_SERVICE_IDLE_TIMEOUT_MS =
- "gtalk_idle_timeout_ms";
-
- /**
- * By default, GTalkService will always connect to the server regardless of the auto-sync
- * setting. However, if this parameter is true, then GTalkService will only connect
- * if auto-sync is enabled. Using the GTalk app will trigger the connection too.
- */
- public static final String GTALK_SERVICE_CONNECT_ON_AUTO_SYNC =
- "gtalk_connect_on_auto_sync";
-
- /**
- * GTalkService holds a wakelock while broadcasting the intent for data message received.
- * It then automatically release the wakelock after a timeout. This setting controls what
- * the timeout should be.
- */
- public static final String GTALK_DATA_MESSAGE_WAKELOCK_MS =
- "gtalk_data_message_wakelock_ms";
-
- /**
- * The socket read timeout used to control how long ssl handshake wait for reads before
- * timing out. This is needed so the ssl handshake doesn't hang for a long time in some
- * circumstances.
- */
- public static final String GTALK_SSL_HANDSHAKE_TIMEOUT_MS =
- "gtalk_ssl_handshake_timeout_ms";
-
- /**
- * How many bytes long a message has to be, in order to be gzipped.
- */
- public static final String SYNC_MIN_GZIP_BYTES =
- "sync_min_gzip_bytes";
-
- /**
- * The hash value of the current provisioning settings
- */
- public static final String PROVISIONING_DIGEST = "digest";
-
- /**
- * Provisioning keys to block from server update
- */
- public static final String PROVISIONING_OVERRIDE = "override";
-
- /**
- * "Generic" service name for authentication requests.
- */
- public static final String GOOGLE_LOGIN_GENERIC_AUTH_SERVICE
- = "google_login_generic_auth_service";
-
- /**
- * Frequency in milliseconds at which we should sync the locally installed Vending Machine
- * content with the server.
- */
- public static final String VENDING_SYNC_FREQUENCY_MS = "vending_sync_frequency_ms";
-
- /**
- * Support URL that is opened in a browser when user clicks on 'Help and Info' in Vending
- * Machine.
- */
- public static final String VENDING_SUPPORT_URL = "vending_support_url";
-
- /**
- * Indicates if Vending Machine requires a SIM to be in the phone to allow a purchase.
- *
- * true = SIM is required
- * false = SIM is not required
- */
- public static final String VENDING_REQUIRE_SIM_FOR_PURCHASE =
- "vending_require_sim_for_purchase";
-
- /**
- * The current version id of the Vending Machine terms of service.
- */
- public static final String VENDING_TOS_VERSION = "vending_tos_version";
-
- /**
- * URL that points to the terms of service for Vending Machine.
- */
- public static final String VENDING_TOS_URL = "vending_tos_url";
-
- /**
- * Whether to use sierraqa instead of sierra tokens for the purchase flow in
- * Vending Machine.
- *
- * true = use sierraqa
- * false = use sierra (default)
- */
- public static final String VENDING_USE_CHECKOUT_QA_SERVICE =
- "vending_use_checkout_qa_service";
-
- /**
- * URL that points to the legal terms of service to display in Settings.
- * <p>
- * This should be a https URL. For a pretty user-friendly URL, use
- * {@link #SETTINGS_TOS_PRETTY_URL}.
- */
- public static final String SETTINGS_TOS_URL = "settings_tos_url";
-
- /**
- * URL that points to the legal terms of service to display in Settings.
- * <p>
- * This should be a pretty http URL. For the URL the device will access
- * via Settings, use {@link #SETTINGS_TOS_URL}.
- */
- public static final String SETTINGS_TOS_PRETTY_URL = "settings_tos_pretty_url";
-
- /**
- * URL that points to the contributors to display in Settings.
- * <p>
- * This should be a https URL. For a pretty user-friendly URL, use
- * {@link #SETTINGS_CONTRIBUTORS_PRETTY_URL}.
- */
- public static final String SETTINGS_CONTRIBUTORS_URL = "settings_contributors_url";
-
- /**
- * URL that points to the contributors to display in Settings.
- * <p>
- * This should be a pretty http URL. For the URL the device will access
- * via Settings, use {@link #SETTINGS_CONTRIBUTORS_URL}.
- */
- public static final String SETTINGS_CONTRIBUTORS_PRETTY_URL =
- "settings_contributors_pretty_url";
-
- /**
- * URL that points to the Terms Of Service for the device.
- * <p>
- * This should be a pretty http URL.
- */
- public static final String SETUP_GOOGLE_TOS_URL = "setup_google_tos_url";
-
- /**
- * URL that points to the Android privacy policy for the device.
- * <p>
- * This should be a pretty http URL.
- */
- public static final String SETUP_ANDROID_PRIVACY_URL = "setup_android_privacy_url";
-
- /**
- * URL that points to the Google privacy policy for the device.
- * <p>
- * This should be a pretty http URL.
- */
- public static final String SETUP_GOOGLE_PRIVACY_URL = "setup_google_privacy_url";
-
- /**
- * Request an MSISDN token for various Google services.
- */
- public static final String USE_MSISDN_TOKEN = "use_msisdn_token";
-
- /**
- * RSA public key used to encrypt passwords stored in the database.
- */
- public static final String GLS_PUBLIC_KEY = "google_login_public_key";
-
- /**
- * Only check parental control status if this is set to "true".
- */
- public static final String PARENTAL_CONTROL_CHECK_ENABLED =
- "parental_control_check_enabled";
-
- /**
- * The list of applications we need to block if parental control is
- * enabled.
- */
- public static final String PARENTAL_CONTROL_APPS_LIST =
- "parental_control_apps_list";
-
- /**
- * Duration in which parental control status is valid.
- */
- public static final String PARENTAL_CONTROL_TIMEOUT_IN_MS =
- "parental_control_timeout_in_ms";
-
- /**
- * When parental control is off, we expect to get this string from the
- * litmus url.
- */
- public static final String PARENTAL_CONTROL_EXPECTED_RESPONSE =
- "parental_control_expected_response";
-
- /**
- * When the litmus url returns a 302, declare parental control to be on
- * only if the redirect url matches this regular expression.
- */
- public static final String PARENTAL_CONTROL_REDIRECT_REGEX =
- "parental_control_redirect_regex";
-
- /**
- * Threshold for the amount of change in disk free space required to report the amount of
- * free space. Used to prevent spamming the logs when the disk free space isn't changing
- * frequently.
- */
- public static final String DISK_FREE_CHANGE_REPORTING_THRESHOLD =
- "disk_free_change_reporting_threshold";
-
- /**
- * Prefix for new Google services published by the checkin
- * server.
- */
- public static final String GOOGLE_SERVICES_PREFIX
- = "google_services:";
-
- /**
- * The maximum reconnect delay for short network outages or when the network is suspended
- * due to phone use.
- */
- public static final String SYNC_MAX_RETRY_DELAY_IN_SECONDS =
- "sync_max_retry_delay_in_seconds";
-
- /**
- * Minimum percentage of free storage on the device that is used to determine if
- * the device is running low on storage.
- * Say this value is set to 10, the device is considered running low on storage
- * if 90% or more of the device storage is filled up.
- */
- public static final String SYS_STORAGE_THRESHOLD_PERCENTAGE =
- "sys_storage_threshold_percentage";
-
- /**
- * The interval in minutes after which the amount of free storage left on the
- * device is logged to the event log
- */
- public static final String SYS_FREE_STORAGE_LOG_INTERVAL =
- "sys_free_storage_log_interval";
-
- /**
- * The interval in milliseconds at which to check the number of SMS sent
- * out without asking for use permit, to limit the un-authorized SMS
- * usage.
- */
- public static final String SMS_OUTGOING_CEHCK_INTERVAL_MS =
- "sms_outgoing_check_interval_ms";
-
- /**
- * The number of outgoing SMS sent without asking for user permit
- * (of {@link #SMS_OUTGOING_CEHCK_INTERVAL_MS}
- */
- public static final String SMS_OUTGOING_CEHCK_MAX_COUNT =
- "sms_outgoing_check_max_count";
-
- /**
- * The interval in milliseconds at which to check packet counts on the
- * mobile data interface when screen is on, to detect possible data
- * connection problems.
- */
- public static final String PDP_WATCHDOG_POLL_INTERVAL_MS =
- "pdp_watchdog_poll_interval_ms";
-
- /**
- * The interval in milliseconds at which to check packet counts on the
- * mobile data interface when screen is off, to detect possible data
- * connection problems.
- */
- public static final String PDP_WATCHDOG_LONG_POLL_INTERVAL_MS =
- "pdp_watchdog_long_poll_interval_ms";
-
- /**
- * The interval in milliseconds at which to check packet counts on the
- * mobile data interface after {@link #PDP_WATCHDOG_TRIGGER_PACKET_COUNT}
- * outgoing packets has been reached without incoming packets.
- */
- public static final String PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS =
- "pdp_watchdog_error_poll_interval_ms";
-
- /**
- * The number of outgoing packets sent without seeing an incoming packet
- * that triggers a countdown (of {@link #PDP_WATCHDOG_ERROR_POLL_COUNT}
- * device is logged to the event log
- */
- public static final String PDP_WATCHDOG_TRIGGER_PACKET_COUNT =
- "pdp_watchdog_trigger_packet_count";
-
- /**
- * The number of polls to perform (at {@link #PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS})
- * after hitting {@link #PDP_WATCHDOG_TRIGGER_PACKET_COUNT} before
- * attempting data connection recovery.
- */
- public static final String PDP_WATCHDOG_ERROR_POLL_COUNT =
- "pdp_watchdog_error_poll_count";
-
- /**
- * The number of failed PDP reset attempts before moving to something more
- * drastic: re-registering to the network.
- */
- public static final String PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT =
- "pdp_watchdog_max_pdp_reset_fail_count";
-
- /**
- * Address to ping as a last sanity check before attempting any recovery.
- * Unset or set to "0.0.0.0" to skip this check.
- */
- public static final String PDP_WATCHDOG_PING_ADDRESS = "pdp_watchdog_ping_address";
-
- /**
- * The "-w deadline" parameter for the ping, ie, the max time in
- * seconds to spend pinging.
- */
- public static final String PDP_WATCHDOG_PING_DEADLINE = "pdp_watchdog_ping_deadline";
-
- /**
- * The interval in milliseconds at which to check gprs registration
- * after the first registration mismatch of gprs and voice service,
- * to detect possible data network registration problems.
- *
- */
- public static final String GPRS_REGISTER_CHECK_PERIOD_MS =
- "gprs_register_check_period_ms";
-
- /**
- * The interval in milliseconds after which Wi-Fi is considered idle.
- * When idle, it is possible for the device to be switched from Wi-Fi to
- * the mobile data network.
- */
- public static final String WIFI_IDLE_MS = "wifi_idle_ms";
-
- /**
- * Screen timeout in milliseconds corresponding to the
- * PowerManager's POKE_LOCK_SHORT_TIMEOUT flag (i.e. the fastest
- * possible screen timeout behavior.)
- */
- public static final String SHORT_KEYLIGHT_DELAY_MS =
- "short_keylight_delay_ms";
-
- /**
- * URL that points to the voice search servers. To be factored out of this class.
- */
- public static final String VOICE_SEARCH_URL = "voice_search_url";
-
- /**
- * Speech encoding used with voice search on 3G networks. To be factored out of this class.
- */
- public static final String VOICE_SEARCH_ENCODING_THREE_G = "voice_search_encoding_three_g";
-
- /**
- * Speech encoding used with voice search on WIFI networks. To be factored out of this class.
- */
- public static final String VOICE_SEARCH_ENCODING_WIFI = "voice_search_encoding_wifi";
-
- /**
- * Prefix for rules that launch automatic instrumentation test cycles.
- * The format is the InstrumentationTestRunner (or compatible) package and class,
- * followed optionally by space-separated key value pairs to pass to it.
- */
- public static final String AUTOTEST_PREFIX = "autotest:";
-
- /**
- * Interval between synchronous checkins forced by the automatic test runner.
- * If you set this to a value smaller than CHECKIN_INTERVAL, then the test runner's
- * frequent checkins will prevent asynchronous background checkins from interfering
- * with any performance measurements.
- */
- public static final String AUTOTEST_CHECKIN_SECONDS = "autotest_checkin_seconds";
-
- /**
- * Interval between reboots forced by the automatic test runner.
- */
- public static final String AUTOTEST_REBOOT_SECONDS = "autotest_reboot_seconds";
-
- /**
- * @deprecated
- * @hide
- */
- @Deprecated // Obviated by NameValueCache: just fetch the value directly.
- public static class QueryMap extends ContentQueryMap {
-
- public QueryMap(ContentResolver contentResolver, Cursor cursor, boolean keepUpdated,
- Handler handlerForUpdateNotifications) {
- super(cursor, NAME, keepUpdated, handlerForUpdateNotifications);
- }
-
- public QueryMap(ContentResolver contentResolver, boolean keepUpdated,
- Handler handlerForUpdateNotifications) {
- this(contentResolver,
- contentResolver.query(CONTENT_URI, null, null, null, null),
- keepUpdated, handlerForUpdateNotifications);
- }
-
- public String getString(String name) {
- ContentValues cv = getValues(name);
- if (cv == null) return null;
- return cv.getAsString(VALUE);
- }
- }
-
- }
-
- /**
- * User-defined bookmarks and shortcuts. The target of each bookmark is an
- * Intent URL, allowing it to be either a web page or a particular
- * application activity.
- *
- * @hide
- */
- public static final class Bookmarks implements BaseColumns
- {
- private static final String TAG = "Bookmarks";
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://" + AUTHORITY + "/bookmarks");
-
- /**
- * The row ID.
- * <p>Type: INTEGER</p>
- */
- public static final String ID = "_id";
-
- /**
- * Descriptive name of the bookmark that can be displayed to the user.
- * If this is empty, the title should be resolved at display time (use
- * {@link #getTitle(Context, Cursor)} any time you want to display the
- * title of a bookmark.)
- * <P>
- * Type: TEXT
- * </P>
- */
- public static final String TITLE = "title";
-
- /**
- * Arbitrary string (displayed to the user) that allows bookmarks to be
- * organized into categories. There are some special names for
- * standard folders, which all start with '@'. The label displayed for
- * the folder changes with the locale (via {@link #labelForFolder}) but
- * the folder name does not change so you can consistently query for
- * the folder regardless of the current locale.
- *
- * <P>Type: TEXT</P>
- *
- */
- public static final String FOLDER = "folder";
-
- /**
- * The Intent URL of the bookmark, describing what it points to. This
- * value is given to {@link android.content.Intent#getIntent} to create
- * an Intent that can be launched.
- * <P>Type: TEXT</P>
- */
- public static final String INTENT = "intent";
-
- /**
- * Optional shortcut character associated with this bookmark.
- * <P>Type: INTEGER</P>
- */
- public static final String SHORTCUT = "shortcut";
-
- /**
- * The order in which the bookmark should be displayed
- * <P>Type: INTEGER</P>
- */
- public static final String ORDERING = "ordering";
-
- private static final String[] sIntentProjection = { INTENT };
- private static final String[] sShortcutProjection = { ID, SHORTCUT };
- private static final String sShortcutSelection = SHORTCUT + "=?";
-
- /**
- * Convenience function to retrieve the bookmarked Intent for a
- * particular shortcut key.
- *
- * @param cr The ContentResolver to query.
- * @param shortcut The shortcut key.
- *
- * @return Intent The bookmarked URL, or null if there is no bookmark
- * matching the given shortcut.
- */
- public static Intent getIntentForShortcut(ContentResolver cr, char shortcut)
- {
- Intent intent = null;
-
- Cursor c = cr.query(CONTENT_URI,
- sIntentProjection, sShortcutSelection,
- new String[] { String.valueOf((int) shortcut) }, ORDERING);
- // Keep trying until we find a valid shortcut
- try {
- while (intent == null && c.moveToNext()) {
- try {
- String intentURI = c.getString(c.getColumnIndexOrThrow(INTENT));
- intent = Intent.getIntent(intentURI);
- } catch (java.net.URISyntaxException e) {
- // The stored URL is bad... ignore it.
- } catch (IllegalArgumentException e) {
- // Column not found
- Log.e(TAG, "Intent column not found", e);
- }
- }
- } finally {
- if (c != null) c.close();
- }
-
- return intent;
- }
-
- /**
- * Add a new bookmark to the system.
- *
- * @param cr The ContentResolver to query.
- * @param intent The desired target of the bookmark.
- * @param title Bookmark title that is shown to the user; null if none
- * or it should be resolved to the intent's title.
- * @param folder Folder in which to place the bookmark; null if none.
- * @param shortcut Shortcut that will invoke the bookmark; 0 if none. If
- * this is non-zero and there is an existing bookmark entry
- * with this same shortcut, then that existing shortcut is
- * cleared (the bookmark is not removed).
- * @return The unique content URL for the new bookmark entry.
- */
- public static Uri add(ContentResolver cr,
- Intent intent,
- String title,
- String folder,
- char shortcut,
- int ordering)
- {
- // If a shortcut is supplied, and it is already defined for
- // another bookmark, then remove the old definition.
- if (shortcut != 0) {
- Cursor c = cr.query(CONTENT_URI,
- sShortcutProjection, sShortcutSelection,
- new String[] { String.valueOf((int) shortcut) }, null);
- try {
- if (c.moveToFirst()) {
- while (c.getCount() > 0) {
- if (!c.deleteRow()) {
- Log.w(TAG, "Could not delete existing shortcut row");
- }
- }
- }
- } finally {
- if (c != null) c.close();
- }
- }
-
- ContentValues values = new ContentValues();
- if (title != null) values.put(TITLE, title);
- if (folder != null) values.put(FOLDER, folder);
- values.put(INTENT, intent.toURI());
- if (shortcut != 0) values.put(SHORTCUT, (int) shortcut);
- values.put(ORDERING, ordering);
- return cr.insert(CONTENT_URI, values);
- }
-
- /**
- * Return the folder name as it should be displayed to the user. This
- * takes care of localizing special folders.
- *
- * @param r Resources object for current locale; only need access to
- * system resources.
- * @param folder The value found in the {@link #FOLDER} column.
- *
- * @return CharSequence The label for this folder that should be shown
- * to the user.
- */
- public static CharSequence getLabelForFolder(Resources r, String folder) {
- return folder;
- }
-
- /**
- * Return the title as it should be displayed to the user. This takes
- * care of localizing bookmarks that point to activities.
- *
- * @param context A context.
- * @param cursor A cursor pointing to the row whose title should be
- * returned. The cursor must contain at least the {@link #TITLE}
- * and {@link #INTENT} columns.
- * @return A title that is localized and can be displayed to the user,
- * or the empty string if one could not be found.
- */
- public static CharSequence getTitle(Context context, Cursor cursor) {
- int titleColumn = cursor.getColumnIndex(TITLE);
- int intentColumn = cursor.getColumnIndex(INTENT);
- if (titleColumn == -1 || intentColumn == -1) {
- throw new IllegalArgumentException(
- "The cursor must contain the TITLE and INTENT columns.");
- }
-
- String title = cursor.getString(titleColumn);
- if (!TextUtils.isEmpty(title)) {
- return title;
- }
-
- String intentUri = cursor.getString(intentColumn);
- if (TextUtils.isEmpty(intentUri)) {
- return "";
- }
-
- Intent intent;
- try {
- intent = Intent.getIntent(intentUri);
- } catch (URISyntaxException e) {
- return "";
- }
-
- PackageManager packageManager = context.getPackageManager();
- ResolveInfo info = packageManager.resolveActivity(intent, 0);
- return info != null ? info.loadLabel(packageManager) : "";
- }
- }
-
- /**
- * Returns the GTalk JID resource associated with this device.
- *
- * @return String the JID resource of the device. It uses the device IMEI in the computation
- * of the JID resource. If IMEI is not ready (i.e. telephony module not ready), we'll return
- * an empty string.
- * @hide
- */
- // TODO: we shouldn't not have a permenant Jid resource, as that's an easy target for
- // spams. We should change it once a while, like when we resubscribe to the subscription feeds
- // server.
- // (also, should this live in GTalkService?)
- public static synchronized String getJidResource() {
- if (sJidResource != null) {
- return sJidResource;
- }
-
- MessageDigest digest;
- try {
- digest = MessageDigest.getInstance("SHA-1");
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException("this should never happen");
- }
-
- String imei = TelephonyManager.getDefault().getDeviceId();
- if (TextUtils.isEmpty(imei)) {
- return "";
- }
-
- byte[] hashedImei = digest.digest(imei.getBytes());
- String id = new String(Base64.encodeBase64(hashedImei), 0, 12);
- id = id.replaceAll("/", "_");
- sJidResource = JID_RESOURCE_PREFIX + id;
- return sJidResource;
- }
-
- /**
- * Returns the device ID that we should use when connecting to the mobile gtalk server.
- * This is a string like "android-0x1242", where the hex string is the Android ID obtained
- * from the GoogleLoginService.
- *
- * @param androidId The Android ID for this device.
- * @return The device ID that should be used when connecting to the mobile gtalk server.
- * @hide
- */
- public static String getGTalkDeviceId(long androidId) {
- return "android-" + Long.toHexString(androidId);
- }
-}
diff --git a/core/java/android/provider/SubscribedFeeds.java b/core/java/android/provider/SubscribedFeeds.java
deleted file mode 100644
index 4d430d5..0000000
--- a/core/java/android/provider/SubscribedFeeds.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-
-/**
- * The SubscribedFeeds provider stores all information about subscribed feeds.
- *
- * @hide
- */
-public class SubscribedFeeds {
- private SubscribedFeeds() {}
-
- /**
- * Columns from the Feed table that other tables join into themselves.
- */
- public interface FeedColumns {
- /**
- * The feed url.
- * <P>Type: TEXT</P>
- */
- public static final String FEED = "feed";
-
- /**
- * The authority that cares about the feed.
- * <P>Type: TEXT</P>
- */
- public static final String AUTHORITY = "authority";
-
- /**
- * The gaia service this feed is for (used for authentication).
- * <P>Type: TEXT</P>
- */
- public static final String SERVICE = "service";
- }
-
- /**
- * Provides constants to access the Feeds table and some utility methods
- * to ease using the Feeds content provider.
- */
- public static final class Feeds implements BaseColumns, SyncConstValue,
- FeedColumns {
- private Feeds() {}
-
- public static Cursor query(ContentResolver cr, String[] projection) {
- return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
- }
-
- public static Cursor query(ContentResolver cr, String[] projection,
- String where, String[] whereArgs, String orderBy) {
- return cr.query(CONTENT_URI, projection, where,
- whereArgs, (orderBy == null) ? DEFAULT_SORT_ORDER : orderBy);
- }
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://subscribedfeeds/feeds");
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri DELETED_CONTENT_URI =
- Uri.parse("content://subscribedfeeds/deleted_feeds");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * subscribed feeds.
- */
- public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/subscribedfeeds";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * subscribed feed.
- */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/subscribedfeed";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "_SYNC_ACCOUNT ASC";
- }
-
- /**
- * A convenience method to add a feed to the SubscribedFeeds
- * content provider. The user specifies the values of the FEED,
- * _SYNC_ACCOUNT, AUTHORITY. SERVICE, and ROUTING_INFO.
- * @param resolver used to access the underlying content provider
- * @param feed corresponds to the FEED column
- * @param account corresponds to the _SYNC_ACCOUNT column
- * @param authority corresponds to the AUTHORITY column
- * @param service corresponds to the SERVICE column
- * @return the Uri of the feed that was added
- */
- public static Uri addFeed(ContentResolver resolver,
- String feed, String account,
- String authority, String service) {
- ContentValues values = new ContentValues();
- values.put(SubscribedFeeds.Feeds.FEED, feed);
- values.put(SubscribedFeeds.Feeds._SYNC_ACCOUNT, account);
- values.put(SubscribedFeeds.Feeds.AUTHORITY, authority);
- values.put(SubscribedFeeds.Feeds.SERVICE, service);
- return resolver.insert(SubscribedFeeds.Feeds.CONTENT_URI, values);
- }
-
- public static int deleteFeed(ContentResolver resolver,
- String feed, String account, String authority) {
- StringBuilder where = new StringBuilder();
- where.append(SubscribedFeeds.Feeds._SYNC_ACCOUNT + "=?");
- where.append(" AND " + SubscribedFeeds.Feeds.FEED + "=?");
- where.append(" AND " + SubscribedFeeds.Feeds.AUTHORITY + "=?");
- return resolver.delete(SubscribedFeeds.Feeds.CONTENT_URI,
- where.toString(), new String[] {account, feed, authority});
- }
-
- public static int deleteFeeds(ContentResolver resolver,
- String account, String authority) {
- StringBuilder where = new StringBuilder();
- where.append(SubscribedFeeds.Feeds._SYNC_ACCOUNT + "=?");
- where.append(" AND " + SubscribedFeeds.Feeds.AUTHORITY + "=?");
- return resolver.delete(SubscribedFeeds.Feeds.CONTENT_URI,
- where.toString(), new String[] {account, authority});
- }
-
- public static String gtalkServiceRoutingInfoFromAccountAndResource(
- String account, String res) {
- return Uri.parse("gtalk://" + account + "/" + res).toString();
- }
-
- /**
- * Columns from the Accounts table.
- */
- public interface AccountColumns {
- /**
- * The account.
- * <P>Type: TEXT</P>
- */
- public static final String _SYNC_ACCOUNT = SyncConstValue._SYNC_ACCOUNT;
- }
-
- /**
- * Provides constants to access the Accounts table and some utility methods
- * to ease using it.
- */
- public static final class Accounts implements BaseColumns, AccountColumns {
- private Accounts() {}
-
- public static Cursor query(ContentResolver cr, String[] projection) {
- return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
- }
-
- public static Cursor query(ContentResolver cr, String[] projection,
- String where, String orderBy) {
- return cr.query(CONTENT_URI, projection, where,
- null, (orderBy == null) ? DEFAULT_SORT_ORDER : orderBy);
- }
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://subscribedfeeds/accounts");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of
- * accounts that have subscribed feeds.
- */
- public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/subscribedfeedaccounts";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * account in the subscribed feeds.
- */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/subscribedfeedaccount";
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "_SYNC_ACCOUNT ASC";
- }
-}
diff --git a/core/java/android/provider/Sync.java b/core/java/android/provider/Sync.java
deleted file mode 100644
index 628852f..0000000
--- a/core/java/android/provider/Sync.java
+++ /dev/null
@@ -1,633 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import android.content.ContentQueryMap;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Handler;
-
-import java.util.Map;
-
-/**
- * The Sync provider stores information used in managing the syncing of the device,
- * including the history and pending syncs.
- *
- * @hide
- */
-public final class Sync {
- // utility class
- private Sync() {}
-
- /**
- * The content url for this provider.
- */
- public static final Uri CONTENT_URI = Uri.parse("content://sync");
-
- /**
- * Columns from the stats table.
- */
- public interface StatsColumns {
- /**
- * The sync account.
- * <P>Type: TEXT</P>
- */
- public static final String ACCOUNT = "account";
-
- /**
- * The content authority (contacts, calendar, etc.).
- * <P>Type: TEXT</P>
- */
- public static final String AUTHORITY = "authority";
- }
-
- /**
- * Provides constants and utility methods to access and use the stats table.
- */
- public static final class Stats implements BaseColumns, StatsColumns {
-
- // utility class
- private Stats() {}
-
- /**
- * The content url for this table.
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://sync/stats");
-
- /** Projection for the _id column in the stats table. */
- public static final String[] SYNC_STATS_PROJECTION = {_ID};
- }
-
- /**
- * Columns from the history table.
- */
- public interface HistoryColumns {
- /**
- * The ID of the stats row corresponding to this event.
- * <P>Type: INTEGER</P>
- */
- public static final String STATS_ID = "stats_id";
-
- /**
- * The source of the sync event (LOCAL, POLL, USER, SERVER).
- * <P>Type: INTEGER</P>
- */
- public static final String SOURCE = "source";
-
- /**
- * The type of sync event (START, STOP).
- * <P>Type: INTEGER</P>
- */
- public static final String EVENT = "event";
-
- /**
- * The time of the event.
- * <P>Type: INTEGER</P>
- */
- public static final String EVENT_TIME = "eventTime";
-
- /**
- * How long this event took. This is only valid if the EVENT is EVENT_STOP.
- * <P>Type: INTEGER</P>
- */
- public static final String ELAPSED_TIME = "elapsedTime";
-
- /**
- * Any additional message associated with this event.
- * <P>Type: TEXT</P>
- */
- public static final String MESG = "mesg";
-
- /**
- * How much activity was performed sending data to the server. This is sync adapter
- * specific, but usually is something like how many record update/insert/delete attempts
- * were carried out. This is only valid if the EVENT is EVENT_STOP.
- * <P>Type: INTEGER</P>
- */
- public static final String UPSTREAM_ACTIVITY = "upstreamActivity";
-
- /**
- * How much activity was performed while receiving data from the server.
- * This is sync adapter specific, but usually is something like how many
- * records were received from the server. This is only valid if the
- * EVENT is EVENT_STOP.
- * <P>Type: INTEGER</P>
- */
- public static final String DOWNSTREAM_ACTIVITY = "downstreamActivity";
- }
-
- /**
- * Columns from the history table.
- */
- public interface StatusColumns {
- /**
- * How many syncs were completed for this account and authority.
- * <P>Type: INTEGER</P>
- */
- public static final String NUM_SYNCS = "numSyncs";
-
- /**
- * How long all the events for this account and authority took.
- * <P>Type: INTEGER</P>
- */
- public static final String TOTAL_ELAPSED_TIME = "totalElapsedTime";
-
- /**
- * The number of syncs with SOURCE_POLL.
- * <P>Type: INTEGER</P>
- */
- public static final String NUM_SOURCE_POLL = "numSourcePoll";
-
- /**
- * The number of syncs with SOURCE_SERVER.
- * <P>Type: INTEGER</P>
- */
- public static final String NUM_SOURCE_SERVER = "numSourceServer";
-
- /**
- * The number of syncs with SOURCE_LOCAL.
- * <P>Type: INTEGER</P>
- */
- public static final String NUM_SOURCE_LOCAL = "numSourceLocal";
-
- /**
- * The number of syncs with SOURCE_USER.
- * <P>Type: INTEGER</P>
- */
- public static final String NUM_SOURCE_USER = "numSourceUser";
-
- /**
- * The time in ms that the last successful sync ended. Will be null if
- * there are no successful syncs. A successful sync is defined as one having
- * MESG=MESG_SUCCESS.
- * <P>Type: INTEGER</P>
- */
- public static final String LAST_SUCCESS_TIME = "lastSuccessTime";
-
- /**
- * The SOURCE of the last successful sync. Will be null if
- * there are no successful syncs. A successful sync is defined
- * as one having MESG=MESG_SUCCESS.
- * <P>Type: INTEGER</P>
- */
- public static final String LAST_SUCCESS_SOURCE = "lastSuccessSource";
-
- /**
- * The end time in ms of the last sync that failed since the last successful sync.
- * Will be null if there are no syncs or if the last one succeeded. A failed
- * sync is defined as one where MESG isn't MESG_SUCCESS or MESG_CANCELED.
- * <P>Type: INTEGER</P>
- */
- public static final String LAST_FAILURE_TIME = "lastFailureTime";
-
- /**
- * The SOURCE of the last sync that failed since the last successful sync.
- * Will be null if there are no syncs or if the last one succeeded. A failed
- * sync is defined as one where MESG isn't MESG_SUCCESS or MESG_CANCELED.
- * <P>Type: INTEGER</P>
- */
- public static final String LAST_FAILURE_SOURCE = "lastFailureSource";
-
- /**
- * The MESG of the last sync that failed since the last successful sync.
- * Will be null if there are no syncs or if the last one succeeded. A failed
- * sync is defined as one where MESG isn't MESG_SUCCESS or MESG_CANCELED.
- * <P>Type: STRING</P>
- */
- public static final String LAST_FAILURE_MESG = "lastFailureMesg";
-
- /**
- * Is set to 1 if a sync is pending, 0 if not.
- * <P>Type: INTEGER</P>
- */
- public static final String PENDING = "pending";
- }
-
- /**
- * Provides constants and utility methods to access and use the history
- * table.
- */
- public static class History implements BaseColumns,
- StatsColumns,
- HistoryColumns {
-
- /**
- * The content url for this table.
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://sync/history");
-
- /** Enum value for a sync start event. */
- public static final int EVENT_START = 0;
-
- /** Enum value for a sync stop event. */
- public static final int EVENT_STOP = 1;
-
- // TODO: i18n -- grab these out of resources.
- /** String names for the sync event types. */
- public static final String[] EVENTS = { "START", "STOP" };
-
- /** Enum value for a server-initiated sync. */
- public static final int SOURCE_SERVER = 0;
-
- /** Enum value for a local-initiated sync. */
- public static final int SOURCE_LOCAL = 1;
- /**
- * Enum value for a poll-based sync (e.g., upon connection to
- * network)
- */
- public static final int SOURCE_POLL = 2;
-
- /** Enum value for a user-initiated sync. */
- public static final int SOURCE_USER = 3;
-
- // TODO: i18n -- grab these out of resources.
- /** String names for the sync source types. */
- public static final String[] SOURCES = { "SERVER",
- "LOCAL",
- "POLL",
- "USER" };
-
- // Error types
- public static final int ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
- public static final int ERROR_AUTHENTICATION = 2;
- public static final int ERROR_IO = 3;
- public static final int ERROR_PARSE = 4;
- public static final int ERROR_CONFLICT = 5;
- public static final int ERROR_TOO_MANY_DELETIONS = 6;
- public static final int ERROR_TOO_MANY_RETRIES = 7;
- public static final int ERROR_INTERNAL = 8;
-
- // The MESG column will contain one of these or one of the Error types.
- public static final String MESG_SUCCESS = "success";
- public static final String MESG_CANCELED = "canceled";
-
- private static final String FINISHED_SINCE_WHERE_CLAUSE = EVENT + "=" + EVENT_STOP
- + " AND " + EVENT_TIME + ">? AND " + ACCOUNT + "=? AND " + AUTHORITY + "=?";
-
- public static String mesgToString(String mesg) {
- if (MESG_SUCCESS.equals(mesg)) return mesg;
- if (MESG_CANCELED.equals(mesg)) return mesg;
- switch (Integer.parseInt(mesg)) {
- case ERROR_SYNC_ALREADY_IN_PROGRESS: return "already in progress";
- case ERROR_AUTHENTICATION: return "bad authentication";
- case ERROR_IO: return "network error";
- case ERROR_PARSE: return "parse error";
- case ERROR_CONFLICT: return "conflict detected";
- case ERROR_TOO_MANY_DELETIONS: return "too many deletions";
- case ERROR_TOO_MANY_RETRIES: return "too many retries";
- case ERROR_INTERNAL: return "internal error";
- default: return "unknown error";
- }
- }
-
- // utility class
- private History() {}
-
- /**
- * returns a cursor that queries the sync history in descending event time order
- * @param contentResolver the ContentResolver to use for the query
- * @return the cursor on the History table
- */
- public static Cursor query(ContentResolver contentResolver) {
- return contentResolver.query(CONTENT_URI, null, null, null, EVENT_TIME + " desc");
- }
-
- public static boolean hasNewerSyncFinished(ContentResolver contentResolver,
- String account, String authority, long when) {
- Cursor c = contentResolver.query(CONTENT_URI, new String[]{_ID},
- FINISHED_SINCE_WHERE_CLAUSE,
- new String[]{Long.toString(when), account, authority}, null);
- try {
- return c.getCount() > 0;
- } finally {
- c.close();
- }
- }
- }
-
- /**
- * Provides constants and utility methods to access and use the authority history
- * table, which contains information about syncs aggregated by account and authority.
- * All the HistoryColumns except for EVENT are present, plus the AuthorityHistoryColumns.
- */
- public static class Status extends History implements StatusColumns {
-
- /**
- * The content url for this table.
- */
- public static final Uri CONTENT_URI = Uri.parse("content://sync/status");
-
- // utility class
- private Status() {}
-
- /**
- * returns a cursor that queries the authority sync history in descending event order of
- * ACCOUNT, AUTHORITY
- * @param contentResolver the ContentResolver to use for the query
- * @return the cursor on the AuthorityHistory table
- */
- public static Cursor query(ContentResolver contentResolver) {
- return contentResolver.query(CONTENT_URI, null, null, null, ACCOUNT + ", " + AUTHORITY);
- }
-
- public static class QueryMap extends ContentQueryMap {
- public QueryMap(ContentResolver contentResolver,
- boolean keepUpdated,
- Handler handlerForUpdateNotifications) {
- super(contentResolver.query(CONTENT_URI, null, null, null, null),
- _ID, keepUpdated, handlerForUpdateNotifications);
- }
-
- public ContentValues get(String account, String authority) {
- Map<String, ContentValues> rows = getRows();
- for (ContentValues values : rows.values()) {
- if (values.getAsString(ACCOUNT).equals(account)
- && values.getAsString(AUTHORITY).equals(authority)) {
- return values;
- }
- }
- return null;
- }
- }
- }
-
- /**
- * Provides constants and utility methods to access and use the pending syncs table
- */
- public static final class Pending implements BaseColumns,
- StatsColumns {
-
- /**
- * The content url for this table.
- */
- public static final Uri CONTENT_URI = Uri.parse("content://sync/pending");
-
- // utility class
- private Pending() {}
-
- public static class QueryMap extends ContentQueryMap {
- public QueryMap(ContentResolver contentResolver, boolean keepUpdated,
- Handler handlerForUpdateNotifications) {
- super(contentResolver.query(CONTENT_URI, null, null, null, null), _ID, keepUpdated,
- handlerForUpdateNotifications);
- }
-
- public boolean isPending(String account, String authority) {
- Map<String, ContentValues> rows = getRows();
- for (ContentValues values : rows.values()) {
- if (values.getAsString(ACCOUNT).equals(account)
- && values.getAsString(AUTHORITY).equals(authority)) {
- return true;
- }
- }
- return false;
- }
- }
- }
-
- /**
- * Columns from the history table.
- */
- public interface ActiveColumns {
- /**
- * The wallclock time of when the active sync started.
- * <P>Type: INTEGER</P>
- */
- public static final String START_TIME = "startTime";
- }
-
- /**
- * Provides constants and utility methods to access and use the pending syncs table
- */
- public static final class Active implements BaseColumns,
- StatsColumns,
- ActiveColumns {
-
- /**
- * The content url for this table.
- */
- public static final Uri CONTENT_URI = Uri.parse("content://sync/active");
-
- // utility class
- private Active() {}
-
- public static class QueryMap extends ContentQueryMap {
- public QueryMap(ContentResolver contentResolver, boolean keepUpdated,
- Handler handlerForUpdateNotifications) {
- super(contentResolver.query(CONTENT_URI, null, null, null, null), _ID, keepUpdated,
- handlerForUpdateNotifications);
- }
-
- public ContentValues getActiveSyncInfo() {
- Map<String, ContentValues> rows = getRows();
- for (ContentValues values : rows.values()) {
- return values;
- }
- return null;
- }
-
- public String getSyncingAccount() {
- ContentValues values = getActiveSyncInfo();
- return (values == null) ? null : values.getAsString(ACCOUNT);
- }
-
- public String getSyncingAuthority() {
- ContentValues values = getActiveSyncInfo();
- return (values == null) ? null : values.getAsString(AUTHORITY);
- }
-
- public long getSyncStartTime() {
- ContentValues values = getActiveSyncInfo();
- return (values == null) ? -1 : values.getAsLong(START_TIME);
- }
- }
- }
-
- /**
- * Columns in the settings table, which holds key/value pairs of settings.
- */
- public interface SettingsColumns {
- /**
- * The key of the setting
- * <P>Type: TEXT</P>
- */
- public static final String KEY = "name";
-
- /**
- * The value of the settings
- * <P>Type: TEXT</P>
- */
- public static final String VALUE = "value";
- }
-
- /**
- * Provides constants and utility methods to access and use the settings
- * table.
- */
- public static final class Settings implements BaseColumns, SettingsColumns {
- /**
- * The Uri of the settings table. This table behaves a little differently than
- * normal tables. Updates are not allowed, only inserts, and inserts cause a replace
- * to be performed, which first deletes the row if it is already present.
- */
- public static final Uri CONTENT_URI = Uri.parse("content://sync/settings");
-
- /** controls whether or not the device listens for sync tickles */
- public static final String SETTING_LISTEN_FOR_TICKLES = "listen_for_tickles";
-
- /** controls whether or not the individual provider is synced when tickles are received */
- public static final String SETTING_SYNC_PROVIDER_PREFIX = "sync_provider_";
-
- /** query column project */
- private static final String[] PROJECTION = { KEY, VALUE };
-
- /**
- * Convenience function for updating a single settings value as a
- * boolean. This will either create a new entry in the table if the
- * given name does not exist, or modify the value of the existing row
- * with that name. Note that internally setting values are always
- * stored as strings, so this function converts the given value to a
- * string before storing it.
- *
- * @param contentResolver the ContentResolver to use to access the settings table
- * @param name The name of the setting to modify.
- * @param val The new value for the setting.
- */
- static private void putBoolean(ContentResolver contentResolver, String name, boolean val) {
- ContentValues values = new ContentValues();
- values.put(KEY, name);
- values.put(VALUE, Boolean.toString(val));
- // this insert is translated into an update by the underlying Sync provider
- contentResolver.insert(CONTENT_URI, values);
- }
-
- /**
- * Convenience function for getting a setting value as a boolean without using the
- * QueryMap for light-weight setting querying.
- * @param contentResolver The ContentResolver for querying the setting.
- * @param name The name of the setting to query
- * @param def The default value for the setting.
- * @return The value of the setting.
- */
- static public boolean getBoolean(ContentResolver contentResolver,
- String name, boolean def) {
- Cursor cursor = contentResolver.query(
- CONTENT_URI,
- PROJECTION,
- KEY + "=?",
- new String[] { name },
- null);
- try {
- if (cursor != null && cursor.moveToFirst()) {
- return Boolean.parseBoolean(cursor.getString(1));
- }
- } finally {
- if (cursor != null) cursor.close();
- }
- return def;
- }
-
- /**
- * A convenience method to set whether or not the provider is synced when
- * it receives a network tickle.
- *
- * @param contentResolver the ContentResolver to use to access the settings table
- * @param providerName the provider whose behavior is being controlled
- * @param sync true if the provider should be synced when tickles are received for it
- */
- static public void setSyncProviderAutomatically(ContentResolver contentResolver,
- String providerName, boolean sync) {
- putBoolean(contentResolver, SETTING_SYNC_PROVIDER_PREFIX + providerName, sync);
- }
-
- /**
- * A convenience method to set whether or not the device should listen to tickles.
- *
- * @param contentResolver the ContentResolver to use to access the settings table
- * @param flag true if it should listen.
- */
- static public void setListenForNetworkTickles(ContentResolver contentResolver,
- boolean flag) {
- putBoolean(contentResolver, SETTING_LISTEN_FOR_TICKLES, flag);
- }
-
- public static class QueryMap extends ContentQueryMap {
- private ContentResolver mContentResolver;
-
- public QueryMap(ContentResolver contentResolver, boolean keepUpdated,
- Handler handlerForUpdateNotifications) {
- super(contentResolver.query(CONTENT_URI, null, null, null, null), KEY, keepUpdated,
- handlerForUpdateNotifications);
- mContentResolver = contentResolver;
- }
-
- /**
- * Check if the provider should be synced when a network tickle is received
- * @param providerName the provider whose setting we are querying
- * @return true of the provider should be synced when a network tickle is received
- */
- public boolean getSyncProviderAutomatically(String providerName) {
- return getBoolean(SETTING_SYNC_PROVIDER_PREFIX + providerName, true);
- }
-
- /**
- * Set whether or not the provider is synced when it receives a network tickle.
- *
- * @param providerName the provider whose behavior is being controlled
- * @param sync true if the provider should be synced when tickles are received for it
- */
- public void setSyncProviderAutomatically(String providerName, boolean sync) {
- Settings.setSyncProviderAutomatically(mContentResolver, providerName, sync);
- }
-
- /**
- * Set whether or not the device should listen for tickles.
- *
- * @param flag true if it should listen.
- */
- public void setListenForNetworkTickles(boolean flag) {
- Settings.setListenForNetworkTickles(mContentResolver, flag);
- }
-
- /**
- * Check if the device should listen to tickles.
-
- * @return true if it should
- */
- public boolean getListenForNetworkTickles() {
- return getBoolean(SETTING_LISTEN_FOR_TICKLES, true);
- }
-
- /**
- * Convenience function for retrieving a single settings value
- * as a boolean.
- *
- * @param name The name of the setting to retrieve.
- * @param def Value to return if the setting is not defined.
- * @return The setting's current value, or 'def' if it is not defined.
- */
- private boolean getBoolean(String name, boolean def) {
- ContentValues values = getValues(name);
- return values != null ? values.getAsBoolean(VALUE) : def;
- }
- }
- }
-}
diff --git a/core/java/android/provider/SyncConstValue.java b/core/java/android/provider/SyncConstValue.java
deleted file mode 100644
index 6eb4398..0000000
--- a/core/java/android/provider/SyncConstValue.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-/**
- * Columns for tables that are synced to a server.
- * @hide
- */
-public interface SyncConstValue
-{
- /**
- * The account that was used to sync the entry to the device.
- * <P>Type: TEXT</P>
- */
- public static final String _SYNC_ACCOUNT = "_sync_account";
-
- /**
- * The unique ID for a row assigned by the sync source. NULL if the row has never been synced.
- * <P>Type: TEXT</P>
- */
- public static final String _SYNC_ID = "_sync_id";
-
- /**
- * The last time, from the sync source's point of view, that this row has been synchronized.
- * <P>Type: INTEGER (long)</P>
- */
- public static final String _SYNC_TIME = "_sync_time";
-
- /**
- * The version of the row, as assigned by the server.
- * <P>Type: TEXT</P>
- */
- public static final String _SYNC_VERSION = "_sync_version";
-
- /**
- * Used in temporary provider while syncing, always NULL for rows in persistent providers.
- * <P>Type: INTEGER (long)</P>
- */
- public static final String _SYNC_LOCAL_ID = "_sync_local_id";
-
- /**
- * Used only in persistent providers, and only during merging.
- * <P>Type: INTEGER (long)</P>
- */
- public static final String _SYNC_MARK = "_sync_mark";
-
- /**
- * Used to indicate that local, unsynced, changes are present.
- * <P>Type: INTEGER (long)</P>
- */
- public static final String _SYNC_DIRTY = "_sync_dirty";
-
- /**
- * Used to indicate that this account is not synced
- */
- public static final String NON_SYNCABLE_ACCOUNT = "non_syncable";
-}
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
deleted file mode 100644
index 18c64ed..0000000
--- a/core/java/android/provider/Telephony.java
+++ /dev/null
@@ -1,1574 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import com.google.android.mms.util.SqliteWrapper;
-
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.net.Uri;
-import android.telephony.gsm.SmsMessage;
-import android.text.TextUtils;
-import android.text.util.Regex;
-import android.util.Config;
-
-import java.util.HashSet;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * The Telephony provider contains data related to phone operation.
- *
- * @hide
- */
-public final class Telephony {
- private static final String TAG = "Telephony";
- private static final boolean DEBUG = false;
- private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
-
- /**
- * Base columns for tables that contain text based SMSs.
- */
- public interface TextBasedSmsColumns {
- /**
- * The type of the message
- * <P>Type: INTEGER</P>
- */
- public static final String TYPE = "type";
-
- public static final int MESSAGE_TYPE_ALL = 0;
- public static final int MESSAGE_TYPE_INBOX = 1;
- public static final int MESSAGE_TYPE_SENT = 2;
- public static final int MESSAGE_TYPE_DRAFT = 3;
- public static final int MESSAGE_TYPE_OUTBOX = 4;
- public static final int MESSAGE_TYPE_FAILED = 5; // for failed outgoing messages
- public static final int MESSAGE_TYPE_QUEUED = 6; // for messages to send later
-
-
- /**
- * The thread ID of the message
- * <P>Type: INTEGER</P>
- */
- public static final String THREAD_ID = "thread_id";
-
- /**
- * The address of the other party
- * <P>Type: TEXT</P>
- */
- public static final String ADDRESS = "address";
-
- /**
- * The person ID of the sender
- * <P>Type: INTEGER (long)</P>
- */
- public static final String PERSON_ID = "person";
-
- /**
- * The date the message was sent
- * <P>Type: INTEGER (long)</P>
- */
- public static final String DATE = "date";
-
- /**
- * Has the message been read
- * <P>Type: INTEGER (boolean)</P>
- */
- public static final String READ = "read";
-
- /**
- * The TP-Status value for the message, or -1 if no status has
- * been received
- */
- public static final String STATUS = "status";
-
- public static final int STATUS_NONE = -1;
- public static final int STATUS_COMPLETE = 0;
- public static final int STATUS_PENDING = 64;
- public static final int STATUS_FAILED = 128;
-
- /**
- * The subject of the message, if present
- * <P>Type: TEXT</P>
- */
- public static final String SUBJECT = "subject";
-
- /**
- * The body of the message
- * <P>Type: TEXT</P>
- */
- public static final String BODY = "body";
-
- /**
- * The id of the sender of the conversation, if present
- * <P>Type: INTEGER (reference to item in content://contacts/people)</P>
- */
- public static final String PERSON = "person";
-
- /**
- * The protocol identifier code
- * <P>Type: INTEGER</P>
- */
- public static final String PROTOCOL = "protocol";
-
- /**
- * Whether the <code>TP-Reply-Path</code> bit was set on this message
- * <P>Type: BOOLEAN</P>
- */
- public static final String REPLY_PATH_PRESENT = "reply_path_present";
-
- /**
- * The service center (SC) through which to send the message, if present
- * <P>Type: TEXT</P>
- */
- public static final String SERVICE_CENTER = "service_center";
- }
-
- /**
- * Contains all text based SMS messages.
- */
- public static final class Sms implements BaseColumns, TextBasedSmsColumns {
- public static final Cursor query(ContentResolver cr, String[] projection) {
- return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
- }
-
- public static final Cursor query(ContentResolver cr, String[] projection,
- String where, String orderBy) {
- return cr.query(CONTENT_URI, projection, where,
- null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
- }
-
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://sms");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "date DESC";
-
- /**
- * Add an SMS to the given URI.
- *
- * @param resolver the content resolver to use
- * @param uri the URI to add the message to
- * @param address the address of the sender
- * @param body the body of the message
- * @param subject the psuedo-subject of the message
- * @param date the timestamp for the message
- * @param read true if the message has been read, false if not
- * @param deliveryReport true if a delivery report was requested, false if not
- * @return the URI for the new message
- */
- public static Uri addMessageToUri(ContentResolver resolver,
- Uri uri, String address, String body, String subject,
- Long date, boolean read, boolean deliveryReport) {
- return addMessageToUri(resolver, uri, address, body, subject,
- date, read, deliveryReport, -1L);
- }
-
- /**
- * Add an SMS to the given URI with thread_id specified.
- *
- * @param resolver the content resolver to use
- * @param uri the URI to add the message to
- * @param address the address of the sender
- * @param body the body of the message
- * @param subject the psuedo-subject of the message
- * @param date the timestamp for the message
- * @param read true if the message has been read, false if not
- * @param deliveryReport true if a delivery report was requested, false if not
- * @param threadId the thread_id of the message
- * @return the URI for the new message
- */
- public static Uri addMessageToUri(ContentResolver resolver,
- Uri uri, String address, String body, String subject,
- Long date, boolean read, boolean deliveryReport, long threadId) {
- ContentValues values = new ContentValues(7);
-
- values.put(ADDRESS, address);
- if (date != null) {
- values.put(DATE, date);
- }
- values.put(READ, read ? Integer.valueOf(1) : Integer.valueOf(0));
- values.put(SUBJECT, subject);
- values.put(BODY, body);
- if (deliveryReport) {
- values.put(STATUS, STATUS_PENDING);
- }
- if (threadId != -1L) {
- values.put(THREAD_ID, threadId);
- }
- return resolver.insert(uri, values);
- }
-
- /**
- * Move a message to the given folder.
- *
- * @param context the context to use
- * @param uri the message to move
- * @param folder the folder to move to
- * @return true if the operation succeeded
- */
- public static boolean moveMessageToFolder(Context context,
- Uri uri, int folder) {
- if ((uri == null) || ((folder != MESSAGE_TYPE_INBOX)
- && (folder != MESSAGE_TYPE_OUTBOX)
- && (folder != MESSAGE_TYPE_SENT)
- && (folder != MESSAGE_TYPE_DRAFT)
- && (folder != MESSAGE_TYPE_FAILED)
- && (folder != MESSAGE_TYPE_QUEUED))) {
- return false;
- }
-
- ContentValues values = new ContentValues(1);
-
- values.put(TYPE, folder);
- return 1 == SqliteWrapper.update(context, context.getContentResolver(),
- uri, values, null, null);
- }
-
- /**
- * Returns true iff the folder (message type) identifies an
- * outgoing message.
- */
- public static boolean isOutgoingFolder(int messageType) {
- return (messageType == MESSAGE_TYPE_FAILED)
- || (messageType == MESSAGE_TYPE_OUTBOX)
- || (messageType == MESSAGE_TYPE_SENT)
- || (messageType == MESSAGE_TYPE_QUEUED);
- }
-
- /**
- * Contains all text based SMS messages in the SMS app's inbox.
- */
- public static final class Inbox implements BaseColumns, TextBasedSmsColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://sms/inbox");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "date DESC";
-
- /**
- * Add an SMS to the Draft box.
- *
- * @param resolver the content resolver to use
- * @param address the address of the sender
- * @param body the body of the message
- * @param subject the psuedo-subject of the message
- * @param date the timestamp for the message
- * @param read true if the message has been read, false if not
- * @return the URI for the new message
- */
- public static Uri addMessage(ContentResolver resolver,
- String address, String body, String subject, Long date,
- boolean read) {
- return addMessageToUri(resolver, CONTENT_URI, address, body,
- subject, date, read, false);
- }
- }
-
- /**
- * Contains all sent text based SMS messages in the SMS app's.
- */
- public static final class Sent implements BaseColumns, TextBasedSmsColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://sms/sent");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "date DESC";
-
- /**
- * Add an SMS to the Draft box.
- *
- * @param resolver the content resolver to use
- * @param address the address of the sender
- * @param body the body of the message
- * @param subject the psuedo-subject of the message
- * @param date the timestamp for the message
- * @return the URI for the new message
- */
- public static Uri addMessage(ContentResolver resolver,
- String address, String body, String subject, Long date) {
- return addMessageToUri(resolver, CONTENT_URI, address, body,
- subject, date, true, false);
- }
- }
-
- /**
- * Contains all sent text based SMS messages in the SMS app's.
- */
- public static final class Draft implements BaseColumns, TextBasedSmsColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://sms/draft");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "date DESC";
-
- /**
- * Add an SMS to the Draft box.
- *
- * @param resolver the content resolver to use
- * @param address the address of the sender
- * @param body the body of the message
- * @param subject the psuedo-subject of the message
- * @param date the timestamp for the message
- * @return the URI for the new message
- */
- public static Uri addMessage(ContentResolver resolver,
- String address, String body, String subject, Long date) {
- return addMessageToUri(resolver, CONTENT_URI, address, body,
- subject, date, true, false);
- }
-
- /**
- * Save over an existing draft message.
- *
- * @param resolver the content resolver to use
- * @param uri of existing message
- * @param body the new body for the draft message
- * @return true is successful, false otherwise
- */
- public static boolean saveMessage(ContentResolver resolver,
- Uri uri, String body) {
- ContentValues values = new ContentValues(2);
- values.put(BODY, body);
- values.put(DATE, System.currentTimeMillis());
- return resolver.update(uri, values, null, null) == 1;
- }
- }
-
- /**
- * Contains all pending outgoing text based SMS messages.
- */
- public static final class Outbox implements BaseColumns, TextBasedSmsColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://sms/outbox");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "date DESC";
-
- /**
- * Add an SMS to the Out box.
- *
- * @param resolver the content resolver to use
- * @param address the address of the sender
- * @param body the body of the message
- * @param subject the psuedo-subject of the message
- * @param date the timestamp for the message
- * @param deliveryReport whether a delivery report was requested for the message
- * @return the URI for the new message
- */
- public static Uri addMessage(ContentResolver resolver,
- String address, String body, String subject, Long date,
- boolean deliveryReport, long threadId) {
- return addMessageToUri(resolver, CONTENT_URI, address, body,
- subject, date, true, deliveryReport, threadId);
- }
- }
-
- /**
- * Contains all sent text-based SMS messages in the SMS app's.
- */
- public static final class Conversations
- implements BaseColumns, TextBasedSmsColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://sms/conversations");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "date DESC";
-
- /**
- * The first 45 characters of the body of the message
- * <P>Type: TEXT</P>
- */
- public static final String SNIPPET = "snippet";
-
- /**
- * The number of messages in the conversation
- * <P>Type: INTEGER</P>
- */
- public static final String MESSAGE_COUNT = "msg_count";
- }
-
- /**
- * Contains info about SMS related Intents that are broadcast.
- */
- public static final class Intents {
- /**
- * Broadcast Action: A new text based SMS message has been received
- * by the device. The intent will have the following extra
- * values:</p>
- *
- * <ul>
- * <li><em>pdus</em> - An Object[] od byte[]s containing the PDUs
- * that make up the message.</li>
- * </ul>
- *
- * <p>The extra values can be extracted using
- * {@link #getMessagesFromIntent(Intent)}</p>
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String SMS_RECEIVED_ACTION =
- "android.provider.Telephony.SMS_RECEIVED";
-
- /**
- * Broadcast Action: A new data based SMS message has been received
- * by the device. The intent will have the following extra
- * values:</p>
- *
- * <ul>
- * <li><em>pdus</em> - An Object[] od byte[]s containing the PDUs
- * that make up the message.</li>
- * </ul>
- *
- * <p>The extra values can be extracted using
- * {@link #getMessagesFromIntent(Intent)}</p>
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String DATA_SMS_RECEIVED_ACTION =
- "android.intent.action.DATA_SMS_RECEIVED";
-
- /**
- * Broadcast Action: A new WAP PUSH message has been received by the
- * device. The intent will have the following extra
- * values:</p>
- *
- * <ul>
- * <li><em>transactionId (Integer)</em> - The WAP transaction
- * ID</li>
- * <li><em>pduType (Integer)</em> - The WAP PDU type</li>
- * <li><em>data</em> - The data payload of the message</li>
- * </ul>
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String WAP_PUSH_RECEIVED_ACTION =
- "android.provider.Telephony.WAP_PUSH_RECEIVED";
-
- /**
- * Broadcast Action: The SIM storage for SMS messages is full. If
- * space is not freed, messages targeted for the SIM (class 2) may
- * not be saved.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String SIM_FULL_ACTION =
- "android.provider.Telephony.SIM_FULL";
-
- /**
- * Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a
- * {@link #DATA_SMS_RECEIVED_ACTION} intent.
- *
- * @param intent the intent to read from
- * @return an array of SmsMessages for the PDUs
- */
- public static final SmsMessage[] getMessagesFromIntent(
- Intent intent) {
- Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
- byte[][] pduObjs = new byte[messages.length][];
-
- for (int i = 0; i < messages.length; i++) {
- pduObjs[i] = (byte[]) messages[i];
- }
- byte[][] pdus = new byte[pduObjs.length][];
- int pduCount = pdus.length;
- SmsMessage[] msgs = new SmsMessage[pduCount];
- for (int i = 0; i < pduCount; i++) {
- pdus[i] = pduObjs[i];
- msgs[i] = SmsMessage.createFromPdu(pdus[i]);
- }
- return msgs;
- }
- }
- }
-
- /**
- * Base columns for tables that contain MMSs.
- */
- public interface BaseMmsColumns extends BaseColumns {
-
- public static final int MESSAGE_BOX_ALL = 0;
- public static final int MESSAGE_BOX_INBOX = 1;
- public static final int MESSAGE_BOX_SENT = 2;
- public static final int MESSAGE_BOX_DRAFTS = 3;
- public static final int MESSAGE_BOX_OUTBOX = 4;
-
- /**
- * The date the message was sent.
- * <P>Type: INTEGER (long)</P>
- */
- public static final String DATE = "date";
-
- /**
- * The box which the message belong to, for example, MESSAGE_BOX_INBOX.
- * <P>Type: INTEGER</P>
- */
- public static final String MESSAGE_BOX = "msg_box";
-
- /**
- * Has the message been read.
- * <P>Type: INTEGER (boolean)</P>
- */
- public static final String READ = "read";
-
- /**
- * The Message-ID of the message.
- * <P>Type: TEXT</P>
- */
- public static final String MESSAGE_ID = "m_id";
-
- /**
- * The subject of the message, if present.
- * <P>Type: TEXT</P>
- */
- public static final String SUBJECT = "sub";
-
- /**
- * The character set of the subject, if present.
- * <P>Type: INTEGER</P>
- */
- public static final String SUBJECT_CHARSET = "sub_cs";
-
- /**
- * The Content-Type of the message.
- * <P>Type: TEXT</P>
- */
- public static final String CONTENT_TYPE = "ct_t";
-
- /**
- * The Content-Location of the message.
- * <P>Type: TEXT</P>
- */
- public static final String CONTENT_LOCATION = "ct_l";
-
- /**
- * The address of the sender.
- * <P>Type: TEXT</P>
- */
- public static final String FROM = "from";
-
- /**
- * The address of the recipients.
- * <P>Type: TEXT</P>
- */
- public static final String TO = "to";
-
- /**
- * The address of the cc. recipients.
- * <P>Type: TEXT</P>
- */
- public static final String CC = "cc";
-
- /**
- * The address of the bcc. recipients.
- * <P>Type: TEXT</P>
- */
- public static final String BCC = "bcc";
-
- /**
- * The expiry time of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String EXPIRY = "exp";
-
- /**
- * The class of the message.
- * <P>Type: TEXT</P>
- */
- public static final String MESSAGE_CLASS = "m_cls";
-
- /**
- * The type of the message defined by MMS spec.
- * <P>Type: INTEGER</P>
- */
- public static final String MESSAGE_TYPE = "m_type";
-
- /**
- * The version of specification that this message conform.
- * <P>Type: INTEGER</P>
- */
- public static final String MMS_VERSION = "v";
-
- /**
- * The size of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String MESSAGE_SIZE = "m_size";
-
- /**
- * The priority of the message.
- * <P>Type: TEXT</P>
- */
- public static final String PRIORITY = "pri";
-
- /**
- * The read-report of the message.
- * <P>Type: TEXT</P>
- */
- public static final String READ_REPORT = "rr";
-
- /**
- * Whether the report is allowed.
- * <P>Type: TEXT</P>
- */
- public static final String REPORT_ALLOWED = "rpt_a";
-
- /**
- * The response-status of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String RESPONSE_STATUS = "resp_st";
-
- /**
- * The status of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String STATUS = "st";
-
- /**
- * The transaction-id of the message.
- * <P>Type: TEXT</P>
- */
- public static final String TRANSACTION_ID = "tr_id";
-
- /**
- * The retrieve-status of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String RETRIEVE_STATUS = "retr_st";
-
- /**
- * The retrieve-text of the message.
- * <P>Type: TEXT</P>
- */
- public static final String RETRIEVE_TEXT = "retr_txt";
-
- /**
- * The character set of the retrieve-text.
- * <P>Type: TEXT</P>
- */
- public static final String RETRIEVE_TEXT_CHARSET = "retr_txt_cs";
-
- /**
- * The read-status of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String READ_STATUS = "read_status";
-
- /**
- * The content-class of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String CONTENT_CLASS = "ct_cls";
-
- /**
- * The delivery-report of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String DELIVERY_REPORT = "d_rpt";
-
- /**
- * The delivery-time-token of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String DELIVERY_TIME_TOKEN = "d_tm_tok";
-
- /**
- * The delivery-time of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String DELIVERY_TIME = "d_tm";
-
- /**
- * The response-text of the message.
- * <P>Type: TEXT</P>
- */
- public static final String RESPONSE_TEXT = "resp_txt";
-
- /**
- * The sender-visibility of the message.
- * <P>Type: TEXT</P>
- */
- public static final String SENDER_VISIBILITY = "s_vis";
-
- /**
- * The reply-charging of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String REPLY_CHARGING = "r_chg";
-
- /**
- * The reply-charging-deadline-token of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String REPLY_CHARGING_DEADLINE_TOKEN = "r_chg_dl_tok";
-
- /**
- * The reply-charging-deadline of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String REPLY_CHARGING_DEADLINE = "r_chg_dl";
-
- /**
- * The reply-charging-id of the message.
- * <P>Type: TEXT</P>
- */
- public static final String REPLY_CHARGING_ID = "r_chg_id";
-
- /**
- * The reply-charging-size of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String REPLY_CHARGING_SIZE = "r_chg_sz";
-
- /**
- * The previously-sent-by of the message.
- * <P>Type: TEXT</P>
- */
- public static final String PREVIOUSLY_SENT_BY = "p_s_by";
-
- /**
- * The previously-sent-date of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String PREVIOUSLY_SENT_DATE = "p_s_d";
-
- /**
- * The store of the message.
- * <P>Type: TEXT</P>
- */
- public static final String STORE = "store";
-
- /**
- * The mm-state of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String MM_STATE = "mm_st";
-
- /**
- * The mm-flags-token of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String MM_FLAGS_TOKEN = "mm_flg_tok";
-
- /**
- * The mm-flags of the message.
- * <P>Type: TEXT</P>
- */
- public static final String MM_FLAGS = "mm_flg";
-
- /**
- * The store-status of the message.
- * <P>Type: TEXT</P>
- */
- public static final String STORE_STATUS = "store_st";
-
- /**
- * The store-status-text of the message.
- * <P>Type: TEXT</P>
- */
- public static final String STORE_STATUS_TEXT = "store_st_txt";
-
- /**
- * The stored of the message.
- * <P>Type: TEXT</P>
- */
- public static final String STORED = "stored";
-
- /**
- * The totals of the message.
- * <P>Type: TEXT</P>
- */
- public static final String TOTALS = "totals";
-
- /**
- * The mbox-totals of the message.
- * <P>Type: TEXT</P>
- */
- public static final String MBOX_TOTALS = "mb_t";
-
- /**
- * The mbox-totals-token of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String MBOX_TOTALS_TOKEN = "mb_t_tok";
-
- /**
- * The quotas of the message.
- * <P>Type: TEXT</P>
- */
- public static final String QUOTAS = "qt";
-
- /**
- * The mbox-quotas of the message.
- * <P>Type: TEXT</P>
- */
- public static final String MBOX_QUOTAS = "mb_qt";
-
- /**
- * The mbox-quotas-token of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String MBOX_QUOTAS_TOKEN = "mb_qt_tok";
-
- /**
- * The message-count of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String MESSAGE_COUNT = "m_cnt";
-
- /**
- * The start of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String START = "start";
-
- /**
- * The distribution-indicator of the message.
- * <P>Type: TEXT</P>
- */
- public static final String DISTRIBUTION_INDICATOR = "d_ind";
-
- /**
- * The element-descriptor of the message.
- * <P>Type: TEXT</P>
- */
- public static final String ELEMENT_DESCRIPTOR = "e_des";
-
- /**
- * The limit of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String LIMIT = "limit";
-
- /**
- * The recommended-retrieval-mode of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String RECOMMENDED_RETRIEVAL_MODE = "r_r_mod";
-
- /**
- * The recommended-retrieval-mode-text of the message.
- * <P>Type: TEXT</P>
- */
- public static final String RECOMMENDED_RETRIEVAL_MODE_TEXT = "r_r_mod_txt";
-
- /**
- * The status-text of the message.
- * <P>Type: TEXT</P>
- */
- public static final String STATUS_TEXT = "st_txt";
-
- /**
- * The applic-id of the message.
- * <P>Type: TEXT</P>
- */
- public static final String APPLIC_ID = "apl_id";
-
- /**
- * The reply-applic-id of the message.
- * <P>Type: TEXT</P>
- */
- public static final String REPLY_APPLIC_ID = "r_apl_id";
-
- /**
- * The aux-applic-id of the message.
- * <P>Type: TEXT</P>
- */
- public static final String AUX_APPLIC_ID = "aux_apl_id";
-
- /**
- * The drm-content of the message.
- * <P>Type: TEXT</P>
- */
- public static final String DRM_CONTENT = "drm_c";
-
- /**
- * The adaptation-allowed of the message.
- * <P>Type: TEXT</P>
- */
- public static final String ADAPTATION_ALLOWED = "adp_a";
-
- /**
- * The replace-id of the message.
- * <P>Type: TEXT</P>
- */
- public static final String REPLACE_ID = "repl_id";
-
- /**
- * The cancel-id of the message.
- * <P>Type: TEXT</P>
- */
- public static final String CANCEL_ID = "cl_id";
-
- /**
- * The cancel-status of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String CANCEL_STATUS = "cl_st";
-
- /**
- * The thread ID of the message
- * <P>Type: INTEGER</P>
- */
- public static final String THREAD_ID = "thread_id";
- }
-
- /**
- * Columns for the "canonical_addresses" table used by MMS and
- * SMS."
- */
- public interface CanonicalAddressesColumns extends BaseColumns {
- /**
- * An address used in MMS or SMS. Email addresses are
- * converted to lower case and are compared by string
- * equality. Other addresses are compared using
- * PHONE_NUMBERS_EQUAL.
- * <P>Type: TEXT</P>
- */
- public static final String ADDRESS = "address";
- }
-
- /**
- * Columns for the "threads" table used by MMS and SMS.
- */
- public interface ThreadsColumns extends BaseColumns {
- /**
- * The date at which the thread was created.
- *
- * <P>Type: INTEGER (long)</P>
- */
- public static final String DATE = "date";
-
- /**
- * A string encoding of the recipient IDs of the recipients of
- * the message, in numerical order and separated by spaces.
- * <P>Type: TEXT</P>
- */
- public static final String RECIPIENT_IDS = "recipient_ids";
-
- /**
- * The message count of the thread.
- * <P>Type: INTEGER</P>
- */
- public static final String MESSAGE_COUNT = "message_count";
- /**
- * Indicates whether all messages of the thread have been read.
- * <P>Type: INTEGER</P>
- */
- public static final String READ = "read";
- /**
- * The snippet of the latest message in the thread.
- * <P>Type: TEXT</P>
- */
- public static final String SNIPPET = "snippet";
- /**
- * The charset of the snippet.
- * <P>Type: INTEGER</P>
- */
- public static final String SNIPPET_CHARSET = "snippet_cs";
- /**
- * Type of the thread, either Threads.COMMON_THREAD or
- * Threads.BROADCAST_THREAD.
- * <P>Type: INTEGER</P>
- */
- public static final String TYPE = "type";
- /**
- * Indicates whether there is a transmission error in the thread.
- * <P>Type: INTEGER</P>
- */
- public static final String ERROR = "error";
- }
-
- /**
- * Helper functions for the "threads" table used by MMS and SMS.
- */
- public static final class Threads implements ThreadsColumns {
- private static final String[] ID_PROJECTION = { BaseColumns._ID };
- private static final String STANDARD_ENCODING = "UTF-8";
- private static final Uri THREAD_ID_CONTENT_URI = Uri.parse(
- "content://mms-sms/threadID");
- public static final Uri CONTENT_URI = Uri.withAppendedPath(
- MmsSms.CONTENT_URI, "conversations");
- public static final Uri OBSOLETE_THREADS_URI = Uri.withAppendedPath(
- CONTENT_URI, "obsolete");
-
- public static final int COMMON_THREAD = 0;
- public static final int BROADCAST_THREAD = 1;
-
- // No one should construct an instance of this class.
- private Threads() {
- }
-
- /**
- * This is a single-recipient version of
- * getOrCreateThreadId. It's convenient for use with SMS
- * messages.
- */
- public static long getOrCreateThreadId(Context context, String recipient) {
- Set<String> recipients = new HashSet<String>();
-
- recipients.add(recipient);
- return getOrCreateThreadId(context, recipients);
- }
-
- /**
- * Given the recipients list and subject of an unsaved message,
- * return its thread ID. If the message starts a new thread,
- * allocate a new thread ID. Otherwise, use the appropriate
- * existing thread ID.
- *
- * Find the thread ID of the same set of recipients (in
- * any order, without any additions). If one
- * is found, return it. Otherwise, return a unique thread ID.
- */
- public static long getOrCreateThreadId(
- Context context, Set<String> recipients) {
- Uri.Builder uriBuilder = THREAD_ID_CONTENT_URI.buildUpon();
-
- for (String recipient : recipients) {
- if (Mms.isEmailAddress(recipient)) {
- recipient = Mms.extractAddrSpec(recipient);
- }
-
- uriBuilder.appendQueryParameter("recipient", recipient);
- }
-
- Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(),
- uriBuilder.build(), ID_PROJECTION, null, null, null);
- if (cursor != null) {
- try {
- if (cursor.moveToFirst()) {
- return cursor.getLong(0);
- }
- } finally {
- cursor.close();
- }
- }
-
- throw new IllegalArgumentException("Unable to find or allocate a thread ID.");
- }
- }
-
- /**
- * Contains all MMS messages.
- */
- public static final class Mms implements BaseMmsColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI = Uri.parse("content://mms");
-
- public static final Uri REPORT_REQUEST_URI = Uri.withAppendedPath(
- CONTENT_URI, "report-request");
-
- public static final Uri REPORT_STATUS_URI = Uri.withAppendedPath(
- CONTENT_URI, "report-status");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "date DESC";
-
- /**
- * mailbox = name-addr
- * name-addr = [display-name] angle-addr
- * angle-addr = [CFWS] "<" addr-spec ">" [CFWS]
- */
- public static final Pattern NAME_ADDR_EMAIL_PATTERN =
- Pattern.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*");
-
- /**
- * quoted-string = [CFWS]
- * DQUOTE *([FWS] qcontent) [FWS] DQUOTE
- * [CFWS]
- */
- public static final Pattern QUOTED_STRING_PATTERN =
- Pattern.compile("\\s*\"([^\"]*)\"\\s*");
-
- public static final Cursor query(
- ContentResolver cr, String[] projection) {
- return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
- }
-
- public static final Cursor query(
- ContentResolver cr, String[] projection,
- String where, String orderBy) {
- return cr.query(CONTENT_URI, projection,
- where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
- }
-
- public static final String getMessageBoxName(int msgBox) {
- switch (msgBox) {
- case MESSAGE_BOX_ALL:
- return "all";
- case MESSAGE_BOX_INBOX:
- return "inbox";
- case MESSAGE_BOX_SENT:
- return "sent";
- case MESSAGE_BOX_DRAFTS:
- return "drafts";
- case MESSAGE_BOX_OUTBOX:
- return "outbox";
- default:
- throw new IllegalArgumentException("Invalid message box: " + msgBox);
- }
- }
-
- public static String extractAddrSpec(String address) {
- Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(address);
-
- if (match.matches()) {
- return match.group(2);
- }
- return address;
- }
-
- /**
- * Returns true if the address is an email address
- *
- * @param address the input address to be tested
- * @return true if address is an email address
- */
- public static boolean isEmailAddress(String address) {
- if (TextUtils.isEmpty(address)) {
- return false;
- }
-
- String s = extractAddrSpec(address);
- Matcher match = Regex.EMAIL_ADDRESS_PATTERN.matcher(s);
- return match.matches();
- }
-
- /**
- * Contains all MMS messages in the MMS app's inbox.
- */
- public static final class Inbox implements BaseMmsColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri
- CONTENT_URI = Uri.parse("content://mms/inbox");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "date DESC";
- }
-
- /**
- * Contains all MMS messages in the MMS app's sent box.
- */
- public static final class Sent implements BaseMmsColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri
- CONTENT_URI = Uri.parse("content://mms/sent");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "date DESC";
- }
-
- /**
- * Contains all MMS messages in the MMS app's drafts box.
- */
- public static final class Draft implements BaseMmsColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri
- CONTENT_URI = Uri.parse("content://mms/drafts");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "date DESC";
- }
-
- /**
- * Contains all MMS messages in the MMS app's outbox.
- */
- public static final class Outbox implements BaseMmsColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri
- CONTENT_URI = Uri.parse("content://mms/outbox");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "date DESC";
- }
-
- public static final class Addr implements BaseColumns {
- /**
- * The ID of MM which this address entry belongs to.
- */
- public static final String MSG_ID = "msg_id";
-
- /**
- * The ID of contact entry in Phone Book.
- */
- public static final String CONTACT_ID = "contact_id";
-
- /**
- * The address text.
- */
- public static final String ADDRESS = "address";
-
- /**
- * Type of address, must be one of PduHeaders.BCC,
- * PduHeaders.CC, PduHeaders.FROM, PduHeaders.TO.
- */
- public static final String TYPE = "type";
-
- /**
- * Character set of this entry.
- */
- public static final String CHARSET = "charset";
- }
-
- public static final class Part implements BaseColumns {
- /**
- * The identifier of the message which this part belongs to.
- * <P>Type: INTEGER</P>
- */
- public static final String MSG_ID = "mid";
-
- /**
- * The order of the part.
- * <P>Type: INTEGER</P>
- */
- public static final String SEQ = "seq";
-
- /**
- * The content type of the part.
- * <P>Type: TEXT</P>
- */
- public static final String CONTENT_TYPE = "ct";
-
- /**
- * The name of the part.
- * <P>Type: TEXT</P>
- */
- public static final String NAME = "name";
-
- /**
- * The charset of the part.
- * <P>Type: TEXT</P>
- */
- public static final String CHARSET = "chset";
-
- /**
- * The file name of the part.
- * <P>Type: TEXT</P>
- */
- public static final String FILENAME = "fn";
-
- /**
- * The content disposition of the part.
- * <P>Type: TEXT</P>
- */
- public static final String CONTENT_DISPOSITION = "cd";
-
- /**
- * The content ID of the part.
- * <P>Type: INTEGER</P>
- */
- public static final String CONTENT_ID = "cid";
-
- /**
- * The content location of the part.
- * <P>Type: INTEGER</P>
- */
- public static final String CONTENT_LOCATION = "cl";
-
- /**
- * The start of content-type of the message.
- * <P>Type: INTEGER</P>
- */
- public static final String CT_START = "ctt_s";
-
- /**
- * The type of content-type of the message.
- * <P>Type: TEXT</P>
- */
- public static final String CT_TYPE = "ctt_t";
-
- /**
- * The location(on filesystem) of the binary data of the part.
- * <P>Type: INTEGER</P>
- */
- public static final String _DATA = "_data";
-
- }
-
- public static final class Rate {
- public static final Uri CONTENT_URI = Uri.withAppendedPath(
- Mms.CONTENT_URI, "rate");
- /**
- * When a message was successfully sent.
- * <P>Type: INTEGER</P>
- */
- public static final String SENT_TIME = "sent_time";
- }
-
- public static final class Intents {
- private Intents() {
- // Non-instantiatable.
- }
-
- /**
- * The extra field to store the contents of the Intent,
- * which should be an array of Uri.
- */
- public static final String EXTRA_CONTENTS = "contents";
- /**
- * The extra field to store the type of the contents,
- * which should be an array of String.
- */
- public static final String EXTRA_TYPES = "types";
- /**
- * The extra field to store the 'Cc' addresses.
- */
- public static final String EXTRA_CC = "cc";
- /**
- * The extra field to store the 'Bcc' addresses;
- */
- public static final String EXTRA_BCC = "bcc";
- /**
- * The extra field to store the 'Subject'.
- */
- public static final String EXTRA_SUBJECT = "subject";
- /**
- * Indicates that the contents of specified URIs were changed.
- * The application which is showing or caching these contents
- * should be updated.
- */
- public static final String
- CONTENT_CHANGED_ACTION = "android.intent.action.CONTENT_CHANGED";
- /**
- * An extra field which stores the URI of deleted contents.
- */
- public static final String DELETED_CONTENTS = "deleted_contents";
- }
- }
-
- /**
- * Contains all MMS and SMS messages.
- */
- public static final class MmsSms implements BaseColumns {
- /**
- * The column to distinguish SMS &amp; MMS messages in query results.
- */
- public static final String TYPE_DISCRIMINATOR_COLUMN =
- "transport_type";
-
- public static final Uri CONTENT_URI = Uri.parse("content://mms-sms/");
-
- public static final Uri CONTENT_CONVERSATIONS_URI = Uri.parse(
- "content://mms-sms/conversations");
-
- public static final Uri CONTENT_FILTER_BYPHONE_URI = Uri.parse(
- "content://mms-sms/messages/byphone");
-
- public static final Uri CONTENT_UNDELIVERED_URI = Uri.parse(
- "content://mms-sms/undelivered");
-
- public static final Uri CONTENT_DRAFT_URI = Uri.parse(
- "content://mms-sms/draft");
-
- // Constants for message protocol types.
- public static final int SMS_PROTO = 0;
- public static final int MMS_PROTO = 1;
-
- // Constants for error types of pending messages.
- public static final int NO_ERROR = 0;
- public static final int ERR_TYPE_GENERIC = 1;
- public static final int ERR_TYPE_SMS_PROTO_TRANSIENT = 2;
- public static final int ERR_TYPE_MMS_PROTO_TRANSIENT = 3;
- public static final int ERR_TYPE_TRANSPORT_FAILURE = 4;
- public static final int ERR_TYPE_GENERIC_PERMANENT = 10;
- public static final int ERR_TYPE_SMS_PROTO_PERMANENT = 11;
- public static final int ERR_TYPE_MMS_PROTO_PERMANENT = 12;
-
- public static final class PendingMessages implements BaseColumns {
- public static final Uri CONTENT_URI = Uri.withAppendedPath(
- MmsSms.CONTENT_URI, "pending");
- /**
- * The type of transport protocol(MMS or SMS).
- * <P>Type: INTEGER</P>
- */
- public static final String PROTO_TYPE = "proto_type";
- /**
- * The ID of the message to be sent or downloaded.
- * <P>Type: INTEGER</P>
- */
- public static final String MSG_ID = "msg_id";
- /**
- * The type of the message to be sent or downloaded.
- * This field is only valid for MM. For SM, its value is always
- * set to 0.
- */
- public static final String MSG_TYPE = "msg_type";
- /**
- * The type of the error code.
- * <P>Type: INTEGER</P>
- */
- public static final String ERROR_TYPE = "err_type";
- /**
- * The error code of sending/retrieving process.
- * <P>Type: INTEGER</P>
- */
- public static final String ERROR_CODE = "err_code";
- /**
- * How many times we tried to send or download the message.
- * <P>Type: INTEGER</P>
- */
- public static final String RETRY_INDEX = "retry_index";
- /**
- * The time to do next retry.
- */
- public static final String DUE_TIME = "due_time";
- /**
- * The time we last tried to send or download the message.
- */
- public static final String LAST_TRY = "last_try";
- }
- }
-
- public static final class Carriers implements BaseColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://telephony/carriers");
-
- /**
- * The default sort order for this table
- */
- public static final String DEFAULT_SORT_ORDER = "name ASC";
-
- public static final String NAME = "name";
-
- public static final String APN = "apn";
-
- public static final String PROXY = "proxy";
-
- public static final String PORT = "port";
-
- public static final String MMSPROXY = "mmsproxy";
-
- public static final String MMSPORT = "mmsport";
-
- public static final String SERVER = "server";
-
- public static final String USER = "user";
-
- public static final String PASSWORD = "password";
-
- public static final String MMSC = "mmsc";
-
- public static final String MCC = "mcc";
-
- public static final String MNC = "mnc";
-
- public static final String NUMERIC = "numeric";
-
- public static final String TYPE = "type";
-
- public static final String CURRENT = "current";
- }
-
- public static final class Intents {
- private Intents() {
- // Not instantiable
- }
-
- /**
- * Broadcast Action: A "secret code" has been entered in the dialer. Secret codes are
- * of the form *#*#<code>#*#*. The intent will have the data URI:</p>
- *
- * <p><code>android_secret_code://&lt;code&gt;</code></p>
- */
- public static final String SECRET_CODE_ACTION =
- "android.provider.Telephony.SECRET_CODE";
-
- /**
- * Broadcast Action: The Service Provider string(s) have been updated. Activities or
- * services that use these strings should update their display.
- * The intent will have the following extra values:</p>
- * <ul>
- * <li><em>showPlmn</em> - Boolean that indicates whether the PLMN should be shown.</li>
- * <li><em>plmn</em> - The operator name of the registered network, as a string.</li>
- * <li><em>showSpn</em> - Boolean that indicates whether the SPN should be shown.</li>
- * <li><em>spn</em> - The service provider name, as a string.</li>
- * </ul>
- * Note that <em>showPlmn</em> may indicate that <em>plmn</em> should be displayed, even
- * though the value for <em>plmn</em> is null. This can happen, for example, if the phone
- * has not registered to a network yet. In this case the receiver may substitute an
- * appropriate placeholder string (eg, "No service").
- *
- * It is recommended to display <em>plmn</em> before / above <em>spn</em> if
- * both are displayed.
- */
- public static final String SPN_STRINGS_UPDATED_ACTION =
- "android.provider.Telephony.SPN_STRINGS_UPDATED";
-
- public static final String EXTRA_SHOW_PLMN = "showPlmn";
- public static final String EXTRA_PLMN = "plmn";
- public static final String EXTRA_SHOW_SPN = "showSpn";
- public static final String EXTRA_SPN = "spn";
- }
-}
-
-
diff --git a/core/java/android/provider/UserDictionary.java b/core/java/android/provider/UserDictionary.java
deleted file mode 100644
index 5a7ef85..0000000
--- a/core/java/android/provider/UserDictionary.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import java.util.Locale;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.net.Uri;
-import android.text.TextUtils;
-
-/**
- * A provider of user defined words for input methods to use for predictive text input.
- * Applications and input methods may add words into the dictionary. Words can have associated
- * frequency information and locale information.
- */
-public class UserDictionary {
-
- /** Authority string for this provider. */
- public static final String AUTHORITY = "user_dictionary";
-
- /**
- * The content:// style URL for this provider
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://" + AUTHORITY);
-
- /**
- * Contains the user defined words.
- */
- public static class Words implements BaseColumns {
- /**
- * The content:// style URL for this table
- */
- public static final Uri CONTENT_URI =
- Uri.parse("content://" + AUTHORITY + "/words");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of words.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.userword";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} sub-directory of a single word.
- */
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.google.userword";
-
- public static final String _ID = BaseColumns._ID;
-
- /**
- * The word column.
- * <p>TYPE: TEXT</p>
- */
- public static final String WORD = "word";
-
- /**
- * The frequency column. A value between 1 and 255. Higher values imply higher frequency.
- * <p>TYPE: INTEGER</p>
- */
- public static final String FREQUENCY = "frequency";
-
- /**
- * The locale that this word belongs to. Null if it pertains to all
- * locales. Locale is as defined by the string returned by Locale.toString().
- * <p>TYPE: TEXT</p>
- */
- public static final String LOCALE = "locale";
-
- /**
- * The uid of the application that inserted the word.
- * <p>TYPE: INTEGER</p>
- */
- public static final String APP_ID = "appid";
-
- /** The locale type to specify that the word is common to all locales. */
- public static final int LOCALE_TYPE_ALL = 0;
-
- /** The locale type to specify that the word is for the current locale. */
- public static final int LOCALE_TYPE_CURRENT = 1;
-
- /**
- * Sort by descending order of frequency.
- */
- public static final String DEFAULT_SORT_ORDER = FREQUENCY + " DESC";
-
- /** Adds a word to the dictionary, with the given frequency and the specified
- * specified locale type.
- * @param context the current application context
- * @param word the word to add to the dictionary. This should not be null or
- * empty.
- * @param localeType the locale type for this word. It should be one of
- * {@link #LOCALE_TYPE_ALL} or {@link #LOCALE_TYPE_CURRENT}.
- */
- public static void addWord(Context context, String word,
- int frequency, int localeType) {
- final ContentResolver resolver = context.getContentResolver();
-
- if (TextUtils.isEmpty(word) || localeType < 0 || localeType > 1) {
- return;
- }
-
- if (frequency < 0) frequency = 0;
- if (frequency > 255) frequency = 255;
-
- String locale = null;
-
- // TODO: Verify if this is the best way to get the current locale
- if (localeType == LOCALE_TYPE_CURRENT) {
- locale = Locale.getDefault().toString();
- }
- ContentValues values = new ContentValues(4);
-
- values.put(WORD, word);
- values.put(FREQUENCY, frequency);
- values.put(LOCALE, locale);
- values.put(APP_ID, 0); // TODO: Get App UID
-
- Uri result = resolver.insert(CONTENT_URI, values);
- // It's ok if the insert doesn't succeed because the word
- // already exists.
- }
- }
-}
diff --git a/core/java/android/provider/package.html b/core/java/android/provider/package.html
deleted file mode 100644
index 055b037..0000000
--- a/core/java/android/provider/package.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<HTML>
-<BODY>
-Provides convenience classes to access the content providers supplied by
-Android.
-<p>Android ships with a number of content providers that store common data such
-as contact informations, calendar information, and media files. These classes
-provide simplified methods of adding or retrieving data from these content
-providers. For information about how to use a content provider, see <a
-href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.
-</BODY>
-</HTML>
diff --git a/core/java/android/security/Md5MessageDigest.java b/core/java/android/security/Md5MessageDigest.java
deleted file mode 100644
index 4fe0cb0..0000000
--- a/core/java/android/security/Md5MessageDigest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security;
-
-/**
- * Provides the MD5 hash encryption.
- */
-public class Md5MessageDigest extends MessageDigest
-{
- // ptr to native context
- private int mNativeMd5Context;
-
- public Md5MessageDigest()
- {
- init();
- }
-
- public byte[] digest(byte[] input)
- {
- update(input);
- return digest();
- }
-
- private native void init();
- public native void update(byte[] input);
- public native byte[] digest();
- native public void reset();
-}
diff --git a/core/java/android/security/MessageDigest.java b/core/java/android/security/MessageDigest.java
deleted file mode 100644
index cf2d0fe..0000000
--- a/core/java/android/security/MessageDigest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security;
-
-import java.security.NoSuchAlgorithmException;
-
-/**
- * Base class for producing a message digest from different hash encryptions.
- */
-public abstract class MessageDigest
-{
- /**
- * Returns a digest object of the specified type.
- *
- * @param algorithm The type of hash function to use. Valid values are
- * <em>SHA-1</em> and <em>MD5</em>.
- * @return The respective MessageDigest object. Either a
- * {@link android.security.Sha1MessageDigest} or
- * {@link android.security.Md5MessageDigest} object.
- * @throws NoSuchAlgorithmException If an invalid <var>algorithm</var>
- * is given.
- */
- public static MessageDigest getInstance(String algorithm)
- throws NoSuchAlgorithmException
- {
- if (algorithm == null) {
- return null;
- }
-
- if (algorithm.equals("SHA-1")) {
- return new Sha1MessageDigest();
- }
- else if (algorithm.equals("MD5")) {
- return new Md5MessageDigest();
- }
-
- throw new NoSuchAlgorithmException();
- }
-
- public abstract void update(byte[] input);
- public abstract byte[] digest();
-
- /**
- * Produces a message digest for the given input.
- *
- * @param input The message to encrypt.
- * @return The digest (hash sum).
- */
- public abstract byte[] digest(byte[] input);
-}
diff --git a/core/java/android/security/Sha1MessageDigest.java b/core/java/android/security/Sha1MessageDigest.java
deleted file mode 100644
index aa01fa6..0000000
--- a/core/java/android/security/Sha1MessageDigest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security;
-
-/**
- * Provides the SHA-1 hash encyption.
- */
-public class Sha1MessageDigest extends MessageDigest
-{
- // ptr to native context
- private int mNativeSha1Context;
-
- public Sha1MessageDigest()
- {
- init();
- }
-
- public byte[] digest(byte[] input)
- {
- update(input);
- return digest();
- }
-
- private native void init();
- public native void update(byte[] input);
- public native byte[] digest();
- native public void reset();
-}
diff --git a/core/java/android/security/package.html b/core/java/android/security/package.html
deleted file mode 100644
index dfc6303..0000000
--- a/core/java/android/security/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<HTML>
-<BODY>
-Utilities for encrypting messages from hash functions.
-{@hide}
-</BODY>
-</HTML>
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
deleted file mode 100644
index 58f9491..0000000
--- a/core/java/android/server/BluetoothA2dpService.java
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * TODO: Move this to
- * java/services/com/android/server/BluetoothA2dpService.java
- * and make the contructor package private again.
- * @hide
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothError;
-import android.bluetooth.BluetoothIntent;
-import android.bluetooth.IBluetoothA2dp;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.media.AudioManager;
-import android.os.Binder;
-import android.provider.Settings;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.HashMap;
-import java.util.Iterator;
-
-public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
- private static final String TAG = "BluetoothA2dpService";
- private static final boolean DBG = true;
-
- public static final String BLUETOOTH_A2DP_SERVICE = "bluetooth_a2dp";
-
- private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
- private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
-
- private static final String A2DP_SINK_ADDRESS = "a2dp_sink_address";
- private static final String BLUETOOTH_ENABLED = "bluetooth_enabled";
-
- private final Context mContext;
- private final IntentFilter mIntentFilter;
- private HashMap<String, SinkState> mAudioDevices;
- private final AudioManager mAudioManager;
-
- private class SinkState {
- public String address;
- public int state;
- public SinkState(String a, int s) {address = a; state = s;}
- }
-
- public BluetoothA2dpService(Context context) {
- mContext = context;
-
- mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-
- BluetoothDevice device =
- (BluetoothDevice)mContext.getSystemService(Context.BLUETOOTH_SERVICE);
- if (device == null) {
- throw new RuntimeException("Platform does not support Bluetooth");
- }
-
- if (!initNative()) {
- throw new RuntimeException("Could not init BluetoothA2dpService");
- }
-
- mIntentFilter = new IntentFilter(BluetoothIntent.ENABLED_ACTION);
- mIntentFilter.addAction(BluetoothIntent.DISABLED_ACTION);
- mIntentFilter.addAction(BluetoothIntent.BOND_STATE_CHANGED_ACTION);
- mContext.registerReceiver(mReceiver, mIntentFilter);
-
- if (device.isEnabled()) {
- onBluetoothEnable();
- }
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- cleanupNative();
- } finally {
- super.finalize();
- }
- }
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- String address = intent.getStringExtra(BluetoothIntent.ADDRESS);
- if (action.equals(BluetoothIntent.ENABLED_ACTION)) {
- onBluetoothEnable();
- } else if (action.equals(BluetoothIntent.DISABLED_ACTION)) {
- onBluetoothDisable();
- } else if (action.equals(BluetoothIntent.BOND_STATE_CHANGED_ACTION)) {
- int bondState = intent.getIntExtra(BluetoothIntent.BOND_STATE,
- BluetoothError.ERROR);
- switch(bondState) {
- case BluetoothDevice.BOND_BONDED:
- setSinkPriority(address, BluetoothA2dp.PRIORITY_AUTO);
- break;
- case BluetoothDevice.BOND_BONDING:
- case BluetoothDevice.BOND_NOT_BONDED:
- setSinkPriority(address, BluetoothA2dp.PRIORITY_OFF);
- break;
- }
- }
- }
- };
-
- private synchronized void onBluetoothEnable() {
- mAudioDevices = new HashMap<String, SinkState>();
- String[] paths = (String[])listHeadsetsNative();
- if (paths != null) {
- for (String path : paths) {
- mAudioDevices.put(path, new SinkState(getAddressNative(path),
- isSinkConnectedNative(path) ? BluetoothA2dp.STATE_CONNECTED :
- BluetoothA2dp.STATE_DISCONNECTED));
- }
- }
- mAudioManager.setParameter(BLUETOOTH_ENABLED, "true");
- }
-
- private synchronized void onBluetoothDisable() {
- if (mAudioDevices != null) {
- for (String path : mAudioDevices.keySet()) {
- switch (mAudioDevices.get(path).state) {
- case BluetoothA2dp.STATE_CONNECTING:
- case BluetoothA2dp.STATE_CONNECTED:
- case BluetoothA2dp.STATE_PLAYING:
- disconnectSinkNative(path);
- updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
- break;
- case BluetoothA2dp.STATE_DISCONNECTING:
- updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
- break;
- }
- }
- mAudioDevices = null;
- }
- mAudioManager.setBluetoothA2dpOn(false);
- mAudioManager.setParameter(BLUETOOTH_ENABLED, "false");
- }
-
- public synchronized int connectSink(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (DBG) log("connectSink(" + address + ")");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
- if (mAudioDevices == null) {
- return BluetoothError.ERROR;
- }
- String path = lookupPath(address);
- if (path == null) {
- path = createHeadsetNative(address);
- if (DBG) log("new bluez sink: " + address + " (" + path + ")");
- }
- if (path == null) {
- return BluetoothError.ERROR;
- }
-
- SinkState sink = mAudioDevices.get(path);
- int state = BluetoothA2dp.STATE_DISCONNECTED;
- if (sink != null) {
- state = sink.state;
- }
- switch (state) {
- case BluetoothA2dp.STATE_CONNECTED:
- case BluetoothA2dp.STATE_PLAYING:
- case BluetoothA2dp.STATE_DISCONNECTING:
- return BluetoothError.ERROR;
- case BluetoothA2dp.STATE_CONNECTING:
- return BluetoothError.SUCCESS;
- }
-
- // State is DISCONNECTED
- if (!connectSinkNative(path)) {
- return BluetoothError.ERROR;
- }
- updateState(path, BluetoothA2dp.STATE_CONNECTING);
- return BluetoothError.SUCCESS;
- }
-
- public synchronized int disconnectSink(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (DBG) log("disconnectSink(" + address + ")");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
- if (mAudioDevices == null) {
- return BluetoothError.ERROR;
- }
- String path = lookupPath(address);
- if (path == null) {
- return BluetoothError.ERROR;
- }
- switch (mAudioDevices.get(path).state) {
- case BluetoothA2dp.STATE_DISCONNECTED:
- return BluetoothError.ERROR;
- case BluetoothA2dp.STATE_DISCONNECTING:
- return BluetoothError.SUCCESS;
- }
-
- // State is CONNECTING or CONNECTED or PLAYING
- if (!disconnectSinkNative(path)) {
- return BluetoothError.ERROR;
- } else {
- updateState(path, BluetoothA2dp.STATE_DISCONNECTING);
- return BluetoothError.SUCCESS;
- }
- }
-
- public synchronized List<String> listConnectedSinks() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- List<String> connectedSinks = new ArrayList<String>();
- if (mAudioDevices == null) {
- return connectedSinks;
- }
- for (SinkState sink : mAudioDevices.values()) {
- if (sink.state == BluetoothA2dp.STATE_CONNECTED ||
- sink.state == BluetoothA2dp.STATE_PLAYING) {
- connectedSinks.add(sink.address);
- }
- }
- return connectedSinks;
- }
-
- public synchronized int getSinkState(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
- if (mAudioDevices == null) {
- return BluetoothA2dp.STATE_DISCONNECTED;
- }
- for (SinkState sink : mAudioDevices.values()) {
- if (address.equals(sink.address)) {
- return sink.state;
- }
- }
- return BluetoothA2dp.STATE_DISCONNECTED;
- }
-
- public synchronized int getSinkPriority(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
- return Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.getBluetoothA2dpSinkPriorityKey(address),
- BluetoothA2dp.PRIORITY_OFF);
- }
-
- public synchronized int setSinkPriority(String address, int priority) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
- return Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.getBluetoothA2dpSinkPriorityKey(address), priority) ?
- BluetoothError.SUCCESS : BluetoothError.ERROR;
- }
-
- private synchronized void onHeadsetCreated(String path) {
- updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
- }
-
- private synchronized void onHeadsetRemoved(String path) {
- if (mAudioDevices == null) return;
- mAudioDevices.remove(path);
- }
-
- private synchronized void onSinkConnected(String path) {
- if (mAudioDevices == null) return;
- // bluez 3.36 quietly disconnects the previous sink when a new sink
- // is connected, so we need to mark all previously connected sinks as
- // disconnected
- for (String oldPath : mAudioDevices.keySet()) {
- if (path.equals(oldPath)) {
- continue;
- }
- int state = mAudioDevices.get(oldPath).state;
- if (state == BluetoothA2dp.STATE_CONNECTED || state == BluetoothA2dp.STATE_PLAYING) {
- updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
- }
- }
-
- updateState(path, BluetoothA2dp.STATE_CONNECTING);
- mAudioManager.setParameter(A2DP_SINK_ADDRESS, lookupAddress(path));
- mAudioManager.setBluetoothA2dpOn(true);
- updateState(path, BluetoothA2dp.STATE_CONNECTED);
- }
-
- private synchronized void onSinkDisconnected(String path) {
- mAudioManager.setBluetoothA2dpOn(false);
- updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
- }
-
- private synchronized void onSinkPlaying(String path) {
- updateState(path, BluetoothA2dp.STATE_PLAYING);
- }
-
- private synchronized void onSinkStopped(String path) {
- updateState(path, BluetoothA2dp.STATE_CONNECTED);
- }
-
- private synchronized final String lookupAddress(String path) {
- if (mAudioDevices == null) return null;
- SinkState sink = mAudioDevices.get(path);
- if (sink == null) {
- Log.w(TAG, "lookupAddress() called for unknown device " + path);
- updateState(path, BluetoothA2dp.STATE_DISCONNECTED);
- }
- String address = mAudioDevices.get(path).address;
- if (address == null) Log.e(TAG, "Can't find address for " + path);
- return address;
- }
-
- private synchronized final String lookupPath(String address) {
- if (mAudioDevices == null) return null;
-
- for (String path : mAudioDevices.keySet()) {
- if (address.equals(mAudioDevices.get(path).address)) {
- return path;
- }
- }
- return null;
- }
-
- private synchronized void updateState(String path, int state) {
- if (mAudioDevices == null) return;
-
- SinkState s = mAudioDevices.get(path);
- int prevState;
- String address;
- if (s == null) {
- address = getAddressNative(path);
- mAudioDevices.put(path, new SinkState(address, state));
- prevState = BluetoothA2dp.STATE_DISCONNECTED;
- } else {
- address = lookupAddress(path);
- prevState = s.state;
- s.state = state;
- }
-
- if (state != prevState) {
- if (DBG) log("state " + address + " (" + path + ") " + prevState + "->" + state);
-
- Intent intent = new Intent(BluetoothA2dp.SINK_STATE_CHANGED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- intent.putExtra(BluetoothA2dp.SINK_PREVIOUS_STATE, prevState);
- intent.putExtra(BluetoothA2dp.SINK_STATE, state);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-
- if ((prevState == BluetoothA2dp.STATE_CONNECTED ||
- prevState == BluetoothA2dp.STATE_PLAYING) &&
- (state != BluetoothA2dp.STATE_CONNECTED &&
- state != BluetoothA2dp.STATE_PLAYING)) {
- // disconnected
- intent = new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
- mContext.sendBroadcast(intent);
- }
- }
- }
-
- @Override
- protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mAudioDevices == null) return;
- pw.println("Cached audio devices:");
- for (String path : mAudioDevices.keySet()) {
- SinkState sink = mAudioDevices.get(path);
- pw.println(path + " " + sink.address + " " + BluetoothA2dp.stateToString(sink.state));
- }
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-
- private native boolean initNative();
- private native void cleanupNative();
- private synchronized native String[] listHeadsetsNative();
- private synchronized native String createHeadsetNative(String address);
- private synchronized native boolean removeHeadsetNative(String path);
- private synchronized native String getAddressNative(String path);
- private synchronized native boolean connectSinkNative(String path);
- private synchronized native boolean disconnectSinkNative(String path);
- private synchronized native boolean isSinkConnectedNative(String path);
-}
diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java
deleted file mode 100644
index fa53a60..0000000
--- a/core/java/android/server/BluetoothDeviceService.java
+++ /dev/null
@@ -1,1107 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * TODO: Move this to
- * java/services/com/android/server/BluetoothDeviceService.java
- * and make the contructor package private again.
- *
- * @hide
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothError;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothIntent;
-import android.bluetooth.IBluetoothDevice;
-import android.bluetooth.IBluetoothDeviceCallback;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.SystemService;
-import android.provider.Settings;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-public class BluetoothDeviceService extends IBluetoothDevice.Stub {
- private static final String TAG = "BluetoothDeviceService";
- private static final boolean DBG = true;
-
- private int mNativeData;
- private BluetoothEventLoop mEventLoop;
- private IntentFilter mIntentFilter;
- private boolean mIsAirplaneSensitive;
- private final BondState mBondState = new BondState(); // local cache of bondings
- private volatile boolean mIsEnabled; // local cache of isEnabledNative()
- private boolean mIsDiscovering;
-
- private final Context mContext;
-
- private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
- private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
-
- static {
- classInitNative();
- }
- private native static void classInitNative();
-
- public BluetoothDeviceService(Context context) {
- mContext = context;
- }
-
- /** Must be called after construction, and before any other method.
- */
- public synchronized void init() {
- initializeNativeDataNative();
- mIsEnabled = (isEnabledNative() == 1);
- if (mIsEnabled) {
- mBondState.loadBondState();
- }
- mIsDiscovering = false;
- mEventLoop = new BluetoothEventLoop(mContext, this);
- registerForAirplaneMode();
- }
- private native void initializeNativeDataNative();
-
- @Override
- protected void finalize() throws Throwable {
- if (mIsAirplaneSensitive) {
- mContext.unregisterReceiver(mReceiver);
- }
- try {
- cleanupNativeDataNative();
- } finally {
- super.finalize();
- }
- }
- private native void cleanupNativeDataNative();
-
- public boolean isEnabled() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mIsEnabled;
- }
- private native int isEnabledNative();
-
- /**
- * Bring down bluetooth and disable BT in settings. Returns true on success.
- */
- public boolean disable() {
- return disable(true);
- }
-
- /**
- * Bring down bluetooth. Returns true on success.
- *
- * @param saveSetting If true, disable BT in settings
- *
- */
- public synchronized boolean disable(boolean saveSetting) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
-
- if (mEnableThread != null && mEnableThread.isAlive()) {
- return false;
- }
- if (!mIsEnabled) {
- return true;
- }
- mEventLoop.stop();
- disableNative();
-
- // mark in progress bondings as cancelled
- for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) {
- mBondState.setBondState(address, BluetoothDevice.BOND_NOT_BONDED,
- BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
- }
- // update mode
- Intent intent = new Intent(BluetoothIntent.SCAN_MODE_CHANGED_ACTION);
- intent.putExtra(BluetoothIntent.SCAN_MODE, BluetoothDevice.SCAN_MODE_NONE);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-
- mIsEnabled = false;
- if (saveSetting) {
- persistBluetoothOnSetting(false);
- }
- mIsDiscovering = false;
- intent = new Intent(BluetoothIntent.DISABLED_ACTION);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- return true;
- }
-
- /**
- * Bring up bluetooth, asynchronously, and enable BT in settings.
- * This turns on/off the underlying hardware.
- *
- * @return True on success (so far), guaranteeing the callback with be
- * notified when complete.
- */
- public boolean enable(IBluetoothDeviceCallback callback) {
- return enable(callback, true);
- }
-
- /**
- * Enable this Bluetooth device, asynchronously.
- * This turns on/off the underlying hardware.
- *
- * @param saveSetting If true, enable BT in settings
- *
- * @return True on success (so far), guaranteeing the callback with be
- * notified when complete.
- */
- public synchronized boolean enable(IBluetoothDeviceCallback callback,
- boolean saveSetting) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
-
- // Airplane mode can prevent Bluetooth radio from being turned on.
- if (mIsAirplaneSensitive && isAirplaneModeOn()) {
- return false;
- }
- if (mIsEnabled) {
- return false;
- }
- if (mEnableThread != null && mEnableThread.isAlive()) {
- return false;
- }
- mEnableThread = new EnableThread(callback, saveSetting);
- mEnableThread.start();
- return true;
- }
-
- private static final int REGISTER_SDP_RECORDS = 1;
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case REGISTER_SDP_RECORDS:
- //TODO: Don't assume HSP/HFP is running, don't use sdptool,
- if (isEnabled()) {
- SystemService.start("hsag");
- SystemService.start("hfag");
- }
- }
- }
- };
-
- private EnableThread mEnableThread;
-
- private class EnableThread extends Thread {
- private final IBluetoothDeviceCallback mEnableCallback;
- private final boolean mSaveSetting;
- public EnableThread(IBluetoothDeviceCallback callback, boolean saveSetting) {
- mEnableCallback = callback;
- mSaveSetting = saveSetting;
- }
- public void run() {
- boolean res = (enableNative() == 0);
- if (res) {
- mEventLoop.start();
- }
-
- if (mEnableCallback != null) {
- try {
- mEnableCallback.onEnableResult(res ?
- BluetoothDevice.RESULT_SUCCESS :
- BluetoothDevice.RESULT_FAILURE);
- } catch (RemoteException e) {}
- }
-
- if (res) {
- mIsEnabled = true;
- if (mSaveSetting) {
- persistBluetoothOnSetting(true);
- }
- mIsDiscovering = false;
- Intent intent = new Intent(BluetoothIntent.ENABLED_ACTION);
- mBondState.loadBondState();
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- mHandler.sendMessageDelayed(mHandler.obtainMessage(REGISTER_SDP_RECORDS), 3000);
-
- // Update mode
- mEventLoop.onModeChanged(getModeNative());
- }
- mEnableThread = null;
- }
- }
-
- private void persistBluetoothOnSetting(boolean bluetoothOn) {
- long origCallerIdentityToken = Binder.clearCallingIdentity();
- Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.BLUETOOTH_ON,
- bluetoothOn ? 1 : 0);
- Binder.restoreCallingIdentity(origCallerIdentityToken);
- }
-
- private native int enableNative();
- private native int disableNative();
-
- /* package */ BondState getBondState() {
- return mBondState;
- }
-
- /** local cache of bonding state.
- /* we keep our own state to track the intermediate state BONDING, which
- /* bluez does not track.
- * All addreses must be passed in upper case.
- */
- public class BondState {
- private final HashMap<String, Integer> mState = new HashMap<String, Integer>();
- private final HashMap<String, Integer> mPinAttempt = new HashMap<String, Integer>();
- private final ArrayList<String> mAutoPairingFailures = new ArrayList<String>();
- // List of all the vendor_id prefix of Bluetooth addresses for which
- // auto pairing is not attempted
- private final ArrayList<String> mAutoPairingBlacklisted =
- new ArrayList<String>(Arrays.asList(
- "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", //ALPS
- "00:21:4F", "00:23:06", "00:24:33", "00:A0:79", // ALPS
- "00:0E:6D", "00:13:E0", "00:21:E8", "00:60:57"// Murata for Prius 2007
- ));
-
- public synchronized void loadBondState() {
- if (!mIsEnabled) {
- return;
- }
- String[] bonds = listBondingsNative();
- if (bonds == null) {
- return;
- }
- mState.clear();
- if (DBG) log("found " + bonds.length + " bonded devices");
- for (String address : bonds) {
- mState.put(address.toUpperCase(), BluetoothDevice.BOND_BONDED);
- }
- }
-
- public synchronized void setBondState(String address, int state) {
- setBondState(address, state, 0);
- }
-
- /** reason is ignored unless state == BOND_NOT_BONDED */
- public synchronized void setBondState(String address, int state, int reason) {
- int oldState = getBondState(address);
- if (oldState == state) {
- return;
- }
- if (DBG) log(address + " bond state " + oldState + " -> " + state + " (" +
- reason + ")");
- Intent intent = new Intent(BluetoothIntent.BOND_STATE_CHANGED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- intent.putExtra(BluetoothIntent.BOND_STATE, state);
- intent.putExtra(BluetoothIntent.BOND_PREVIOUS_STATE, oldState);
- if (state == BluetoothDevice.BOND_NOT_BONDED) {
- if (reason <= 0) {
- Log.w(TAG, "setBondState() called to unbond device, but reason code is " +
- "invalid. Overriding reason code with BOND_RESULT_REMOVED");
- reason = BluetoothDevice.UNBOND_REASON_REMOVED;
- }
- intent.putExtra(BluetoothIntent.REASON, reason);
- mState.remove(address);
- } else {
- mState.put(address, state);
- }
-
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
-
- public boolean isAutoPairingBlacklisted(String address) {
- for (String blacklistAddress : mAutoPairingBlacklisted) {
- if (address.startsWith(blacklistAddress)) return true;
- }
- return false;
- }
-
- public synchronized int getBondState(String address) {
- Integer state = mState.get(address);
- if (state == null) {
- return BluetoothDevice.BOND_NOT_BONDED;
- }
- return state.intValue();
- }
-
- private synchronized String[] listInState(int state) {
- ArrayList<String> result = new ArrayList<String>(mState.size());
- for (Map.Entry<String, Integer> e : mState.entrySet()) {
- if (e.getValue().intValue() == state) {
- result.add(e.getKey());
- }
- }
- return result.toArray(new String[result.size()]);
- }
-
- public synchronized void addAutoPairingFailure(String address) {
- if (!mAutoPairingFailures.contains(address)) {
- mAutoPairingFailures.add(address);
- }
- }
-
- public synchronized boolean isAutoPairingAttemptsInProgress(String address) {
- return getAttempt(address) != 0;
- }
-
- public synchronized void clearPinAttempts(String address) {
- mPinAttempt.remove(address);
- }
-
- public synchronized boolean hasAutoPairingFailed(String address) {
- return mAutoPairingFailures.contains(address);
- }
-
- public synchronized int getAttempt(String address) {
- Integer attempt = mPinAttempt.get(address);
- if (attempt == null) {
- return 0;
- }
- return attempt.intValue();
- }
-
- public synchronized void attempt(String address) {
- Integer attempt = mPinAttempt.get(address);
- int newAttempt;
- if (attempt == null) {
- newAttempt = 1;
- } else {
- newAttempt = attempt.intValue() + 1;
- }
- mPinAttempt.put(address, new Integer(newAttempt));
- }
-
- }
- private native String[] listBondingsNative();
-
- private static String toBondStateString(int bondState) {
- switch (bondState) {
- case BluetoothDevice.BOND_NOT_BONDED:
- return "not bonded";
- case BluetoothDevice.BOND_BONDING:
- return "bonding";
- case BluetoothDevice.BOND_BONDED:
- return "bonded";
- default:
- return "??????";
- }
- }
-
- public synchronized String getAddress() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return getAddressNative();
- }
- private native String getAddressNative();
-
- public synchronized String getName() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return getNameNative();
- }
- private native String getNameNative();
-
- public synchronized boolean setName(String name) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (name == null) {
- return false;
- }
- // hcid handles persistance of the bluetooth name
- return setNameNative(name);
- }
- private native boolean setNameNative(String name);
-
- /**
- * Returns the user-friendly name of a remote device. This value is
- * retrned from our local cache, which is updated during device discovery.
- * Do not expect to retrieve the updated remote name immediately after
- * changing the name on the remote device.
- *
- * @param address Bluetooth address of remote device.
- *
- * @return The user-friendly name of the specified remote device.
- */
- public synchronized String getRemoteName(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return getRemoteNameNative(address);
- }
- private native String getRemoteNameNative(String address);
-
- /* pacakge */ native String getAdapterPathNative();
-
- public synchronized boolean startDiscovery(boolean resolveNames) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- return startDiscoveryNative(resolveNames);
- }
- private native boolean startDiscoveryNative(boolean resolveNames);
-
- public synchronized boolean cancelDiscovery() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- return cancelDiscoveryNative();
- }
- private native boolean cancelDiscoveryNative();
-
- public synchronized boolean isDiscovering() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mIsDiscovering;
- }
-
- /* package */ void setIsDiscovering(boolean isDiscovering) {
- mIsDiscovering = isDiscovering;
- }
-
- public synchronized boolean startPeriodicDiscovery() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- return startPeriodicDiscoveryNative();
- }
- private native boolean startPeriodicDiscoveryNative();
-
- public synchronized boolean stopPeriodicDiscovery() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- return stopPeriodicDiscoveryNative();
- }
- private native boolean stopPeriodicDiscoveryNative();
-
- public synchronized boolean isPeriodicDiscovery() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return isPeriodicDiscoveryNative();
- }
- private native boolean isPeriodicDiscoveryNative();
-
- /**
- * Set the discoverability window for the device. A timeout of zero
- * makes the device permanently discoverable (if the device is
- * discoverable). Setting the timeout to a nonzero value does not make
- * a device discoverable; you need to call setMode() to make the device
- * explicitly discoverable.
- *
- * @param timeout_s The discoverable timeout in seconds.
- */
- public synchronized boolean setDiscoverableTimeout(int timeout) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- return setDiscoverableTimeoutNative(timeout);
- }
- private native boolean setDiscoverableTimeoutNative(int timeout_s);
-
- /**
- * Get the discoverability window for the device. A timeout of zero
- * means that the device is permanently discoverable (if the device is
- * in the discoverable mode).
- *
- * @return The discoverability window of the device, in seconds. A negative
- * value indicates an error.
- */
- public synchronized int getDiscoverableTimeout() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return getDiscoverableTimeoutNative();
- }
- private native int getDiscoverableTimeoutNative();
-
- public synchronized boolean isAclConnected(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- return isConnectedNative(address);
- }
- private native boolean isConnectedNative(String address);
-
- public synchronized int getScanMode() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return bluezStringToScanMode(getModeNative());
- }
- private native String getModeNative();
-
- public synchronized boolean setScanMode(int mode) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- String bluezMode = scanModeToBluezString(mode);
- if (bluezMode != null) {
- return setModeNative(bluezMode);
- }
- return false;
- }
- private native boolean setModeNative(String mode);
-
- public synchronized boolean disconnectRemoteDeviceAcl(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- return disconnectRemoteDeviceNative(address);
- }
- private native boolean disconnectRemoteDeviceNative(String address);
-
- public synchronized boolean createBond(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- address = address.toUpperCase();
-
- // Check for bond state only if we are not performing auto
- // pairing exponential back-off attempts.
- if (!mBondState.isAutoPairingAttemptsInProgress(address) &&
- mBondState.getBondState(address) != BluetoothDevice.BOND_NOT_BONDED) {
- return false;
- }
-
- if (!createBondingNative(address, 60000 /* 1 minute */)) {
- return false;
- }
-
- mBondState.setBondState(address, BluetoothDevice.BOND_BONDING);
- return true;
- }
- private native boolean createBondingNative(String address, int timeout_ms);
-
- public synchronized boolean cancelBondProcess(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- address = address.toUpperCase();
- if (mBondState.getBondState(address) != BluetoothDevice.BOND_BONDING) {
- return false;
- }
-
- mBondState.setBondState(address, BluetoothDevice.BOND_NOT_BONDED,
- BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
- cancelBondingProcessNative(address);
- return true;
- }
- private native boolean cancelBondingProcessNative(String address);
-
- public synchronized boolean removeBond(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- return removeBondingNative(address);
- }
- private native boolean removeBondingNative(String address);
-
- public synchronized String[] listBonds() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mBondState.listInState(BluetoothDevice.BOND_BONDED);
- }
-
- public synchronized int getBondState(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
- return mBondState.getBondState(address.toUpperCase());
- }
-
- public synchronized String[] listAclConnections() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return listConnectionsNative();
- }
- private native String[] listConnectionsNative();
-
- /**
- * This method lists all remote devices that this adapter is aware of.
- * This is a list not only of all most-recently discovered devices, but of
- * all devices discovered by this adapter up to some point in the past.
- * Note that many of these devices may not be in the neighborhood anymore,
- * and attempting to connect to them will result in an error.
- *
- * @return An array of strings representing the Bluetooth addresses of all
- * remote devices that this adapter is aware of.
- */
- public synchronized String[] listRemoteDevices() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return listRemoteDevicesNative();
- }
- private native String[] listRemoteDevicesNative();
-
- /**
- * Returns the version of the Bluetooth chip. This version is compiled from
- * the LMP version. In case of EDR the features attribute must be checked.
- * Example: "Bluetooth 2.0 + EDR".
- *
- * @return a String representation of the this Adapter's underlying
- * Bluetooth-chip version.
- */
- public synchronized String getVersion() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return getVersionNative();
- }
- private native String getVersionNative();
-
- /**
- * Returns the revision of the Bluetooth chip. This is a vendor-specific
- * value and in most cases it represents the firmware version. This might
- * derive from the HCI revision and LMP subversion values or via extra
- * vendord specific commands.
- * In case the revision of a chip is not available. This method should
- * return the LMP subversion value as a string.
- * Example: "HCI 19.2"
- *
- * @return The HCI revision of this adapter.
- */
- public synchronized String getRevision() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return getRevisionNative();
- }
- private native String getRevisionNative();
-
- /**
- * Returns the manufacturer of the Bluetooth chip. If the company id is not
- * known the sting "Company ID %d" where %d should be replaced with the
- * numeric value from the manufacturer field.
- * Example: "Cambridge Silicon Radio"
- *
- * @return Manufacturer name.
- */
- public synchronized String getManufacturer() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return getManufacturerNative();
- }
- private native String getManufacturerNative();
-
- /**
- * Returns the company name from the OUI database of the Bluetooth device
- * address. This function will need a valid and up-to-date oui.txt from
- * the IEEE. This value will be different from the manufacturer string in
- * the most cases.
- * If the oui.txt file is not present or the OUI part of the Bluetooth
- * address is not listed, it should return the string "OUI %s" where %s is
- * the actual OUI.
- *
- * Example: "Apple Computer"
- *
- * @return company name
- */
- public synchronized String getCompany() {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return getCompanyNative();
- }
- private native String getCompanyNative();
-
- /**
- * Like getVersion(), but for a remote device.
- *
- * @param address The Bluetooth address of the remote device.
- *
- * @return remote-device Bluetooth version
- *
- * @see #getVersion
- */
- public synchronized String getRemoteVersion(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return getRemoteVersionNative(address);
- }
- private native String getRemoteVersionNative(String address);
-
- /**
- * Like getRevision(), but for a remote device.
- *
- * @param address The Bluetooth address of the remote device.
- *
- * @return remote-device HCI revision
- *
- * @see #getRevision
- */
- public synchronized String getRemoteRevision(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return getRemoteRevisionNative(address);
- }
- private native String getRemoteRevisionNative(String address);
-
- /**
- * Like getManufacturer(), but for a remote device.
- *
- * @param address The Bluetooth address of the remote device.
- *
- * @return remote-device Bluetooth chip manufacturer
- *
- * @see #getManufacturer
- */
- public synchronized String getRemoteManufacturer(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return getRemoteManufacturerNative(address);
- }
- private native String getRemoteManufacturerNative(String address);
-
- /**
- * Like getCompany(), but for a remote device.
- *
- * @param address The Bluetooth address of the remote device.
- *
- * @return remote-device company
- *
- * @see #getCompany
- */
- public synchronized String getRemoteCompany(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return getRemoteCompanyNative(address);
- }
- private native String getRemoteCompanyNative(String address);
-
- /**
- * Returns the date and time when the specified remote device has been seen
- * by a discover procedure.
- * Example: "2006-02-08 12:00:00 GMT"
- *
- * @return a String with the timestamp.
- */
- public synchronized String lastSeen(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return lastSeenNative(address);
- }
- private native String lastSeenNative(String address);
-
- /**
- * Returns the date and time when the specified remote device has last been
- * connected to
- * Example: "2006-02-08 12:00:00 GMT"
- *
- * @return a String with the timestamp.
- */
- public synchronized String lastUsed(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return lastUsedNative(address);
- }
- private native String lastUsedNative(String address);
-
- /**
- * Gets the remote major, minor, and service classes encoded as a 32-bit
- * integer.
- *
- * Note: this value is retrieved from cache, because we get it during
- * remote-device discovery.
- *
- * @return 32-bit integer encoding the remote major, minor, and service
- * classes.
- *
- * @see #getRemoteMajorClass
- * @see #getRemoteMinorClass
- * @see #getRemoteServiceClasses
- */
- public synchronized int getRemoteClass(String address) {
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return -1;
- }
- return getRemoteClassNative(address);
- }
- private native int getRemoteClassNative(String address);
-
- /**
- * Gets the remote features encoded as bit mask.
- *
- * Note: This method may be obsoleted soon.
- *
- * @return byte array of features.
- */
- public synchronized byte[] getRemoteFeatures(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return getRemoteFeaturesNative(address);
- }
- private native byte[] getRemoteFeaturesNative(String address);
-
- /**
- * This method and {@link #getRemoteServiceRecord} query the SDP service
- * on a remote device. They do not interpret the data, but simply return
- * it raw to the user. To read more about SDP service handles and records,
- * consult the Bluetooth core documentation (www.bluetooth.com).
- *
- * @param address Bluetooth address of remote device.
- * @param match a String match to narrow down the service-handle search.
- * The only supported value currently is "hsp" for the headset
- * profile. To retrieve all service handles, simply pass an empty
- * match string.
- *
- * @return all service handles corresponding to the string match.
- *
- * @see #getRemoteServiceRecord
- */
- public synchronized int[] getRemoteServiceHandles(String address, String match) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- if (match == null) {
- match = "";
- }
- return getRemoteServiceHandlesNative(address, match);
- }
- private native int[] getRemoteServiceHandlesNative(String address, String match);
-
- /**
- * This method retrieves the service records corresponding to a given
- * service handle (method {@link #getRemoteServiceHandles} retrieves the
- * service handles.)
- *
- * This method and {@link #getRemoteServiceHandles} do not interpret their
- * data, but simply return it raw to the user. To read more about SDP
- * service handles and records, consult the Bluetooth core documentation
- * (www.bluetooth.com).
- *
- * @param address Bluetooth address of remote device.
- * @param handle Service handle returned by {@link #getRemoteServiceHandles}
- *
- * @return a byte array of all service records corresponding to the
- * specified service handle.
- *
- * @see #getRemoteServiceHandles
- */
- public synchronized byte[] getRemoteServiceRecord(String address, int handle) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return null;
- }
- return getRemoteServiceRecordNative(address, handle);
- }
- private native byte[] getRemoteServiceRecordNative(String address, int handle);
-
- private static final int MAX_OUTSTANDING_ASYNC = 32;
-
- // AIDL does not yet support short's
- public synchronized boolean getRemoteServiceChannel(String address, int uuid16,
- IBluetoothDeviceCallback callback) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- HashMap<String, IBluetoothDeviceCallback> callbacks =
- mEventLoop.getRemoteServiceChannelCallbacks();
- if (callbacks.containsKey(address)) {
- Log.w(TAG, "SDP request already in progress for " + address);
- return false;
- }
- // Protect from malicious clients - only allow 32 bonding requests per minute.
- if (callbacks.size() > MAX_OUTSTANDING_ASYNC) {
- Log.w(TAG, "Too many outstanding SDP requests, dropping request for " + address);
- return false;
- }
- callbacks.put(address, callback);
-
- if (!getRemoteServiceChannelNative(address, (short)uuid16)) {
- callbacks.remove(address);
- return false;
- }
- return true;
- }
- private native boolean getRemoteServiceChannelNative(String address, short uuid16);
-
- public synchronized boolean setPin(String address, byte[] pin) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (pin == null || pin.length <= 0 || pin.length > 16 ||
- !BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- address = address.toUpperCase();
- Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
- if (data == null) {
- Log.w(TAG, "setPin(" + address + ") called but no native data available, " +
- "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
- " or by bluez.\n");
- return false;
- }
- // bluez API wants pin as a string
- String pinString;
- try {
- pinString = new String(pin, "UTF8");
- } catch (UnsupportedEncodingException uee) {
- Log.e(TAG, "UTF8 not supported?!?");
- return false;
- }
- return setPinNative(address, pinString, data.intValue());
- }
- private native boolean setPinNative(String address, String pin, int nativeData);
-
- public synchronized boolean cancelPin(String address) {
- mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return false;
- }
- address = address.toUpperCase();
- Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
- if (data == null) {
- Log.w(TAG, "cancelPin(" + address + ") called but no native data available, " +
- "ignoring. Maybe the PasskeyAgent Request was already cancelled by the remote " +
- "or by bluez.\n");
- return false;
- }
- return cancelPinNative(address, data.intValue());
- }
- private native boolean cancelPinNative(String address, int natveiData);
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
- ContentResolver resolver = context.getContentResolver();
- // Query the airplane mode from Settings.System just to make sure that
- // some random app is not sending this intent and disabling bluetooth
- boolean enabled = !isAirplaneModeOn();
- // If bluetooth is currently expected to be on, then enable or disable bluetooth
- if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) {
- if (enabled) {
- enable(null, false);
- } else {
- disable(false);
- }
- }
- }
- }
- };
-
- private void registerForAirplaneMode() {
- String airplaneModeRadios = Settings.System.getString(mContext.getContentResolver(),
- Settings.System.AIRPLANE_MODE_RADIOS);
- mIsAirplaneSensitive = airplaneModeRadios == null
- ? true : airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH);
- if (mIsAirplaneSensitive) {
- mIntentFilter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- mContext.registerReceiver(mReceiver, mIntentFilter);
- }
- }
-
- /* Returns true if airplane mode is currently on */
- private final boolean isAirplaneModeOn() {
- return Settings.System.getInt(mContext.getContentResolver(),
- Settings.System.AIRPLANE_MODE_ON, 0) == 1;
- }
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mIsEnabled) {
- pw.println("\nBluetooth ENABLED: " + getAddress() + " (" + getName() + ")");
- pw.println("\nisDiscovering() = " + isDiscovering());
-
- BluetoothHeadset headset = new BluetoothHeadset(mContext, null);
-
- String[] addresses = listRemoteDevices();
-
- pw.println("\n--Known devices--");
- for (String address : addresses) {
- pw.printf("%s %10s (%d) %s\n", address,
- toBondStateString(mBondState.getBondState(address)),
- mBondState.getAttempt(address),
- getRemoteName(address));
- }
-
- addresses = listAclConnections();
- pw.println("\n--ACL connected devices--");
- for (String address : addresses) {
- pw.println(address);
- }
-
- // Rather not do this from here, but no-where else and I need this
- // dump
- pw.println("\n--Headset Service--");
- switch (headset.getState()) {
- case BluetoothHeadset.STATE_DISCONNECTED:
- pw.println("getState() = STATE_DISCONNECTED");
- break;
- case BluetoothHeadset.STATE_CONNECTING:
- pw.println("getState() = STATE_CONNECTING");
- break;
- case BluetoothHeadset.STATE_CONNECTED:
- pw.println("getState() = STATE_CONNECTED");
- break;
- case BluetoothHeadset.STATE_ERROR:
- pw.println("getState() = STATE_ERROR");
- break;
- }
- pw.println("getHeadsetAddress() = " + headset.getHeadsetAddress());
- headset.close();
-
- } else {
- pw.println("\nBluetooth DISABLED");
- }
- pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive);
- }
-
- /* package */ static int bluezStringToScanMode(String mode) {
- if (mode == null) {
- return BluetoothError.ERROR;
- }
- mode = mode.toLowerCase();
- if (mode.equals("off")) {
- return BluetoothDevice.SCAN_MODE_NONE;
- } else if (mode.equals("connectable")) {
- return BluetoothDevice.SCAN_MODE_CONNECTABLE;
- } else if (mode.equals("discoverable")) {
- return BluetoothDevice.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
- } else {
- return BluetoothError.ERROR;
- }
- }
-
- /* package */ static String scanModeToBluezString(int mode) {
- switch (mode) {
- case BluetoothDevice.SCAN_MODE_NONE:
- return "off";
- case BluetoothDevice.SCAN_MODE_CONNECTABLE:
- return "connectable";
- case BluetoothDevice.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
- return "discoverable";
- }
- return null;
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
deleted file mode 100644
index 8b09583..0000000
--- a/core/java/android/server/BluetoothEventLoop.java
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server;
-
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothClass;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothError;
-import android.bluetooth.BluetoothIntent;
-import android.bluetooth.IBluetoothDeviceCallback;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.HashMap;
-
-/**
- * TODO: Move this to
- * java/services/com/android/server/BluetoothEventLoop.java
- * and make the contructor package private again.
- *
- * @hide
- */
-class BluetoothEventLoop {
- private static final String TAG = "BluetoothEventLoop";
- private static final boolean DBG = false;
-
- private int mNativeData;
- private Thread mThread;
- private boolean mInterrupted;
- private HashMap<String, Integer> mPasskeyAgentRequestData;
- private HashMap<String, IBluetoothDeviceCallback> mGetRemoteServiceChannelCallbacks;
- private BluetoothDeviceService mBluetoothService;
- private Context mContext;
-
- private static final int EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 1;
-
- // The time (in millisecs) to delay the pairing attempt after the first
- // auto pairing attempt fails. We use an exponential delay with
- // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the initial value and
- // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the max value.
- private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000;
- private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000;
-
- private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
- private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
-
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY:
- String address = (String)msg.obj;
- if (address != null) {
- mBluetoothService.createBond(address);
- return;
- }
- break;
- }
- }
- };
-
- static { classInitNative(); }
- private static native void classInitNative();
-
- /* pacakge */ BluetoothEventLoop(Context context, BluetoothDeviceService bluetoothService) {
- mBluetoothService = bluetoothService;
- mContext = context;
- mPasskeyAgentRequestData = new HashMap();
- mGetRemoteServiceChannelCallbacks = new HashMap();
- initializeNativeDataNative();
- }
- private native void initializeNativeDataNative();
-
- protected void finalize() throws Throwable {
- try {
- cleanupNativeDataNative();
- } finally {
- super.finalize();
- }
- }
- private native void cleanupNativeDataNative();
-
- /* pacakge */ HashMap<String, IBluetoothDeviceCallback> getRemoteServiceChannelCallbacks() {
- return mGetRemoteServiceChannelCallbacks;
- }
-
- /* pacakge */ HashMap<String, Integer> getPasskeyAgentRequestData() {
- return mPasskeyAgentRequestData;
- }
-
- private synchronized boolean waitForAndDispatchEvent(int timeout_ms) {
- return waitForAndDispatchEventNative(timeout_ms);
- }
- private native boolean waitForAndDispatchEventNative(int timeout_ms);
-
- /* package */ synchronized void start() {
-
- if (mThread != null) {
- // Already running.
- return;
- }
- mThread = new Thread("Bluetooth Event Loop") {
- @Override
- public void run() {
- try {
- if (setUpEventLoopNative()) {
- while (!mInterrupted) {
- waitForAndDispatchEvent(0);
- sleep(500);
- }
- tearDownEventLoopNative();
- }
- } catch (InterruptedException e) { }
- if (DBG) log("Event Loop thread finished");
- }
- };
- if (DBG) log("Starting Event Loop thread");
- mInterrupted = false;
- mThread.start();
- }
- private native boolean setUpEventLoopNative();
- private native void tearDownEventLoopNative();
-
- public synchronized void stop() {
- if (mThread != null) {
- mInterrupted = true;
- try {
- mThread.join();
- mThread = null;
- } catch (InterruptedException e) {
- Log.i(TAG, "Interrupted waiting for Event Loop thread to join");
- }
- }
- }
-
- public synchronized boolean isEventLoopRunning() {
- return mThread != null;
- }
-
- /*package*/ void onModeChanged(String bluezMode) {
- int mode = BluetoothDeviceService.bluezStringToScanMode(bluezMode);
- if (mode >= 0) {
- Intent intent = new Intent(BluetoothIntent.SCAN_MODE_CHANGED_ACTION);
- intent.putExtra(BluetoothIntent.SCAN_MODE, mode);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- }
-
- private void onDiscoveryStarted() {
- mBluetoothService.setIsDiscovering(true);
- Intent intent = new Intent(BluetoothIntent.DISCOVERY_STARTED_ACTION);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onDiscoveryCompleted() {
- mBluetoothService.setIsDiscovering(false);
- Intent intent = new Intent(BluetoothIntent.DISCOVERY_COMPLETED_ACTION);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
-
- private void onRemoteDeviceFound(String address, int deviceClass, short rssi) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_FOUND_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- intent.putExtra(BluetoothIntent.CLASS, deviceClass);
- intent.putExtra(BluetoothIntent.RSSI, rssi);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteDeviceDisappeared(String address) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_DISAPPEARED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteClassUpdated(String address, int deviceClass) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_CLASS_UPDATED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- intent.putExtra(BluetoothIntent.CLASS, deviceClass);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteDeviceConnected(String address) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_CONNECTED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteDeviceDisconnectRequested(String address) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_DISCONNECT_REQUESTED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteDeviceDisconnected(String address) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_DISCONNECTED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteNameUpdated(String address, String name) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_NAME_UPDATED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- intent.putExtra(BluetoothIntent.NAME, name);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteNameFailed(String address) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_NAME_FAILED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
- private void onRemoteNameChanged(String address, String name) {
- Intent intent = new Intent(BluetoothIntent.REMOTE_NAME_UPDATED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- intent.putExtra(BluetoothIntent.NAME, name);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
-
- private void onCreateBondingResult(String address, int result) {
- address = address.toUpperCase();
- if (result == BluetoothError.SUCCESS) {
- mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDED);
- if (mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) {
- mBluetoothService.getBondState().clearPinAttempts(address);
- }
- } else if (result == BluetoothDevice.UNBOND_REASON_AUTH_FAILED &&
- mBluetoothService.getBondState().getAttempt(address) == 1) {
- mBluetoothService.getBondState().addAutoPairingFailure(address);
- pairingAttempt(address, result);
- } else if (result == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN &&
- mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) {
- pairingAttempt(address, result);
- } else {
- mBluetoothService.getBondState().setBondState(address,
- BluetoothDevice.BOND_NOT_BONDED, result);
- if (mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) {
- mBluetoothService.getBondState().clearPinAttempts(address);
- }
- }
- }
-
- private void pairingAttempt(String address, int result) {
- // This happens when our initial guess of "0000" as the pass key
- // fails. Try to create the bond again and display the pin dialog
- // to the user. Use back-off while posting the delayed
- // message. The initial value is
- // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY and the max value is
- // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY. If the max value is
- // reached, display an error to the user.
- int attempt = mBluetoothService.getBondState().getAttempt(address);
- if (attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY >
- MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY) {
- mBluetoothService.getBondState().clearPinAttempts(address);
- mBluetoothService.getBondState().setBondState(address,
- BluetoothDevice.BOND_NOT_BONDED, result);
- return;
- }
-
- Message message = mHandler.obtainMessage(EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY);
- message.obj = address;
- boolean postResult = mHandler.sendMessageDelayed(message,
- attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY);
- if (!postResult) {
- mBluetoothService.getBondState().clearPinAttempts(address);
- mBluetoothService.getBondState().setBondState(address,
- BluetoothDevice.BOND_NOT_BONDED, result);
- return;
- }
- mBluetoothService.getBondState().attempt(address);
- }
-
- private void onBondingCreated(String address) {
- mBluetoothService.getBondState().setBondState(address.toUpperCase(),
- BluetoothDevice.BOND_BONDED);
- }
-
- private void onBondingRemoved(String address) {
- mBluetoothService.getBondState().setBondState(address.toUpperCase(),
- BluetoothDevice.BOND_NOT_BONDED, BluetoothDevice.UNBOND_REASON_REMOVED);
- }
-
- private void onNameChanged(String name) {
- Intent intent = new Intent(BluetoothIntent.NAME_CHANGED_ACTION);
- intent.putExtra(BluetoothIntent.NAME, name);
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
-
- private void onPasskeyAgentRequest(String address, int nativeData) {
- address = address.toUpperCase();
- mPasskeyAgentRequestData.put(address, new Integer(nativeData));
-
- if (mBluetoothService.getBondState().getBondState(address) ==
- BluetoothDevice.BOND_BONDING) {
- // we initiated the bonding
- int btClass = mBluetoothService.getRemoteClass(address);
-
- // try 0000 once if the device looks dumb
- switch (BluetoothClass.Device.getDevice(btClass)) {
- case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
- case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
- case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES:
- case BluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO:
- case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
- case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO:
- if (!mBluetoothService.getBondState().hasAutoPairingFailed(address) &&
- !mBluetoothService.getBondState().isAutoPairingBlacklisted(address)) {
- mBluetoothService.getBondState().attempt(address);
- mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes("0000"));
- return;
- }
- }
- }
- Intent intent = new Intent(BluetoothIntent.PAIRING_REQUEST_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
- }
-
- private void onPasskeyAgentCancel(String address) {
- address = address.toUpperCase();
- mPasskeyAgentRequestData.remove(address);
- Intent intent = new Intent(BluetoothIntent.PAIRING_CANCEL_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
- mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
- mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_NOT_BONDED,
- BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
- }
-
- private boolean onAuthAgentAuthorize(String address, String service, String uuid) {
- boolean authorized = false;
- if (service.endsWith("service_audio")) {
- BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
- authorized = a2dp.getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF;
- if (authorized) {
- Log.i(TAG, "Allowing incoming A2DP connection from " + address);
- } else {
- Log.i(TAG, "Rejecting incoming A2DP connection from " + address);
- }
- } else {
- Log.i(TAG, "Rejecting incoming " + service + " connection from " + address);
- }
- return authorized;
- }
-
- private void onAuthAgentCancel(String address, String service, String uuid) {
- // We immediately response to DBUS Authorize() so this should not
- // usually happen
- log("onAuthAgentCancel(" + address + ", " + service + ", " + uuid + ")");
- }
-
- private void onGetRemoteServiceChannelResult(String address, int channel) {
- IBluetoothDeviceCallback callback = mGetRemoteServiceChannelCallbacks.get(address);
- if (callback != null) {
- mGetRemoteServiceChannelCallbacks.remove(address);
- try {
- callback.onGetRemoteServiceChannelResult(address, channel);
- } catch (RemoteException e) {}
- }
- }
-
- private static void log(String msg) {
- Log.d(TAG, msg);
- }
-}
diff --git a/core/java/android/server/data/BuildData.java b/core/java/android/server/data/BuildData.java
deleted file mode 100644
index 53ffa3f..0000000
--- a/core/java/android/server/data/BuildData.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server.data;
-
-import android.os.Build;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-import static com.android.internal.util.Objects.nonNull;
-
-/**
- * Build data transfer object. Keep in sync. with the server side version.
- */
-public class BuildData {
-
- /** The version of the data returned by write() and understood by the constructor. */
- private static final int VERSION = 0;
-
- private final String fingerprint;
- private final String incrementalVersion;
- private final long time; // in *seconds* since the epoch (not msec!)
-
- public BuildData() {
- this.fingerprint = "android:" + Build.FINGERPRINT;
- this.incrementalVersion = Build.VERSION.INCREMENTAL;
- this.time = Build.TIME / 1000; // msec -> sec
- }
-
- public BuildData(String fingerprint, String incrementalVersion, long time) {
- this.fingerprint = nonNull(fingerprint);
- this.incrementalVersion = incrementalVersion;
- this.time = time;
- }
-
- /*package*/ BuildData(DataInput in) throws IOException {
- int dataVersion = in.readInt();
- if (dataVersion != VERSION) {
- throw new IOException("Expected " + VERSION + ". Got: " + dataVersion);
- }
-
- this.fingerprint = in.readUTF();
- this.incrementalVersion = Long.toString(in.readLong());
- this.time = in.readLong();
- }
-
- /*package*/ void write(DataOutput out) throws IOException {
- out.writeInt(VERSION);
- out.writeUTF(fingerprint);
-
- // TODO: change the format/version to expect a string for this field.
- // Version 0, still used by the server side, expects a long.
- long changelist;
- try {
- changelist = Long.parseLong(incrementalVersion);
- } catch (NumberFormatException ex) {
- changelist = -1;
- }
- out.writeLong(changelist);
- out.writeLong(time);
- }
-
- public String getFingerprint() {
- return fingerprint;
- }
-
- public String getIncrementalVersion() {
- return incrementalVersion;
- }
-
- public long getTime() {
- return time;
- }
-}
diff --git a/core/java/android/server/data/CrashData.java b/core/java/android/server/data/CrashData.java
deleted file mode 100644
index d652bb3..0000000
--- a/core/java/android/server/data/CrashData.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server.data;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-import static com.android.internal.util.Objects.nonNull;
-
-/**
- * Crash data transfer object. Keep in sync. with the server side version.
- */
-public class CrashData {
-
- final String id;
- final String activity;
- final long time;
- final BuildData buildData;
- final ThrowableData throwableData;
- final byte[] state;
-
- public CrashData(String id, String activity, BuildData buildData,
- ThrowableData throwableData) {
- this.id = nonNull(id);
- this.activity = nonNull(activity);
- this.buildData = nonNull(buildData);
- this.throwableData = nonNull(throwableData);
- this.time = System.currentTimeMillis();
- this.state = null;
- }
-
- public CrashData(String id, String activity, BuildData buildData,
- ThrowableData throwableData, byte[] state) {
- this.id = nonNull(id);
- this.activity = nonNull(activity);
- this.buildData = nonNull(buildData);
- this.throwableData = nonNull(throwableData);
- this.time = System.currentTimeMillis();
- this.state = state;
- }
-
- public CrashData(DataInput in) throws IOException {
- int dataVersion = in.readInt();
- if (dataVersion != 0 && dataVersion != 1) {
- throw new IOException("Expected 0 or 1. Got: " + dataVersion);
- }
-
- this.id = in.readUTF();
- this.activity = in.readUTF();
- this.time = in.readLong();
- this.buildData = new BuildData(in);
- this.throwableData = new ThrowableData(in);
- if (dataVersion == 1) {
- int len = in.readInt();
- if (len == 0) {
- this.state = null;
- } else {
- this.state = new byte[len];
- in.readFully(this.state, 0, len);
- }
- } else {
- this.state = null;
- }
- }
-
- public CrashData(String tag, Throwable throwable) {
- id = "";
- activity = tag;
- buildData = new BuildData();
- throwableData = new ThrowableData(throwable);
- time = System.currentTimeMillis();
- state = null;
- }
-
- public void write(DataOutput out) throws IOException {
- // version
- if (this.state == null) {
- out.writeInt(0);
- } else {
- out.writeInt(1);
- }
-
- out.writeUTF(this.id);
- out.writeUTF(this.activity);
- out.writeLong(this.time);
- buildData.write(out);
- throwableData.write(out);
- if (this.state != null) {
- out.writeInt(this.state.length);
- out.write(this.state, 0, this.state.length);
- }
- }
-
- public BuildData getBuildData() {
- return buildData;
- }
-
- public ThrowableData getThrowableData() {
- return throwableData;
- }
-
- public String getId() {
- return id;
- }
-
- public String getActivity() {
- return activity;
- }
-
- public long getTime() {
- return time;
- }
-
- public byte[] getState() {
- return state;
- }
-
- /**
- * Return a brief description of this CrashData record. The details of the
- * representation are subject to change.
- *
- * @return Returns a String representing the contents of the object.
- */
- @Override
- public String toString() {
- return "[CrashData: id=" + id + " activity=" + activity + " time=" + time +
- " buildData=" + buildData.toString() +
- " throwableData=" + throwableData.toString() + "]";
- }
-}
diff --git a/core/java/android/server/data/StackTraceElementData.java b/core/java/android/server/data/StackTraceElementData.java
deleted file mode 100644
index 07185a0..0000000
--- a/core/java/android/server/data/StackTraceElementData.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server.data;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-/**
- * Stack trace element data transfer object. Keep in sync. with the server side
- * version.
- */
-public class StackTraceElementData {
-
- final String className;
- final String fileName;
- final String methodName;
- final int lineNumber;
-
- public StackTraceElementData(StackTraceElement element) {
- this.className = element.getClassName();
-
- String fileName = element.getFileName();
- this.fileName = fileName == null ? "[unknown source]" : fileName;
-
- this.methodName = element.getMethodName();
- this.lineNumber = element.getLineNumber();
- }
-
- public StackTraceElementData(DataInput in) throws IOException {
- int dataVersion = in.readInt();
- if (dataVersion != 0) {
- throw new IOException("Expected 0. Got: " + dataVersion);
- }
-
- this.className = in.readUTF();
- this.fileName = in.readUTF();
- this.methodName = in.readUTF();
- this.lineNumber = in.readInt();
- }
-
- void write(DataOutput out) throws IOException {
- out.writeInt(0); // version
-
- out.writeUTF(className);
- out.writeUTF(fileName);
- out.writeUTF(methodName);
- out.writeInt(lineNumber);
- }
-
- public String getClassName() {
- return className;
- }
-
- public String getFileName() {
- return fileName;
- }
-
- public String getMethodName() {
- return methodName;
- }
-
- public int getLineNumber() {
- return lineNumber;
- }
-}
diff --git a/core/java/android/server/data/ThrowableData.java b/core/java/android/server/data/ThrowableData.java
deleted file mode 100644
index e500aca..0000000
--- a/core/java/android/server/data/ThrowableData.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server.data;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-/**
- * Throwable data transfer object. Keep in sync. with the server side version.
- */
-public class ThrowableData {
-
- final String message;
- final String type;
- final StackTraceElementData[] stackTrace;
- final ThrowableData cause;
-
- public ThrowableData(Throwable throwable) {
- this.type = throwable.getClass().getName();
- String message = throwable.getMessage();
- this.message = message == null ? "" : message;
-
- StackTraceElement[] elements = throwable.getStackTrace();
- this.stackTrace = new StackTraceElementData[elements.length];
- for (int i = 0; i < elements.length; i++) {
- this.stackTrace[i] = new StackTraceElementData(elements[i]);
- }
-
- Throwable cause = throwable.getCause();
- this.cause = cause == null ? null : new ThrowableData(cause);
- }
-
- public ThrowableData(DataInput in) throws IOException {
- int dataVersion = in.readInt();
- if (dataVersion != 0) {
- throw new IOException("Expected 0. Got: " + dataVersion);
- }
-
- this.message = in.readUTF();
- this.type = in.readUTF();
-
- int count = in.readInt();
- this.stackTrace = new StackTraceElementData[count];
- for (int i = 0; i < count; i++) {
- this.stackTrace[i] = new StackTraceElementData(in);
- }
-
- this.cause = in.readBoolean() ? new ThrowableData(in) : null;
- }
-
- public void write(DataOutput out) throws IOException {
- out.writeInt(0); // version
-
- out.writeUTF(message);
- out.writeUTF(type);
-
- out.writeInt(stackTrace.length);
- for (StackTraceElementData elementData : stackTrace) {
- elementData.write(out);
- }
-
- out.writeBoolean(cause != null);
- if (cause != null) {
- cause.write(out);
- }
- }
-
- public String getMessage() {
- return message;
- }
-
- public String getType() {
- return type;
- }
-
- public StackTraceElementData[] getStackTrace() {
- return stackTrace;
- }
-
- public ThrowableData getCause() {
- return cause;
- }
-
-
- public String toString() {
- return toString(null);
- }
-
- public String toString(String prefix) {
- StringBuilder builder = new StringBuilder();
- append(prefix, builder, this);
- return builder.toString();
- }
-
- private static void append(String prefix, StringBuilder builder,
- ThrowableData throwableData) {
- if (prefix != null) builder.append(prefix);
- builder.append(throwableData.getType())
- .append(": ")
- .append(throwableData.getMessage())
- .append('\n');
- for (StackTraceElementData element : throwableData.getStackTrace()) {
- if (prefix != null ) builder.append(prefix);
- builder.append(" at ")
- .append(element.getClassName())
- .append('.')
- .append(element.getMethodName())
- .append("(")
- .append(element.getFileName())
- .append(':')
- .append(element.getLineNumber())
- .append(")\n");
-
- }
-
- ThrowableData cause = throwableData.getCause();
- if (cause != null) {
- if (prefix != null ) builder.append(prefix);
- builder.append("Caused by: ");
- append(prefix, builder, cause);
- }
- }
-}
diff --git a/core/java/android/server/data/package.html b/core/java/android/server/data/package.html
deleted file mode 100755
index 1c9bf9d..0000000
--- a/core/java/android/server/data/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body>
- {@hide}
-</body>
-</html>
diff --git a/core/java/android/server/package.html b/core/java/android/server/package.html
deleted file mode 100755
index c9f96a6..0000000
--- a/core/java/android/server/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
deleted file mode 100644
index fe15553..0000000
--- a/core/java/android/server/search/SearchManagerService.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server.search;
-
-import android.app.ISearchManager;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Handler;
-import android.util.Config;
-
-/**
- * This is a simplified version of the Search Manager service. It no longer handles
- * presentation (UI). Its function is to maintain the map & list of "searchable"
- * items, which provides a mapping from individual activities (where a user might have
- * invoked search) to specific searchable activities (where the search will be dispatched).
- */
-public class SearchManagerService extends ISearchManager.Stub
-{
- // general debugging support
- private static final String TAG = "SearchManagerService";
- private static final boolean DEBUG = false;
- private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
-
- // configuration choices
- private static final boolean IMMEDIATE_SEARCHABLES_UPDATE = true;
-
- // class maintenance and general shared data
- private final Context mContext;
- private final Handler mHandler;
- private boolean mSearchablesDirty;
-
- /**
- * Initialize the Search Manager service in the provided system context.
- * Only one instance of this object should be created!
- *
- * @param context to use for accessing DB, window manager, etc.
- */
- public SearchManagerService(Context context) {
- mContext = context;
- mHandler = new Handler();
-
- // Setup the infrastructure for updating and maintaining the list
- // of searchable activities.
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- filter.addDataScheme("package");
- mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
- mSearchablesDirty = true;
-
- // After startup settles down, preload the searchables list,
- // which will reduce the delay when the search UI is invoked.
- if (IMMEDIATE_SEARCHABLES_UPDATE) {
- mHandler.post(mRunUpdateSearchable);
- }
- }
-
- /**
- * Listens for intent broadcasts.
- *
- * The primary purpose here is to refresh the "searchables" list
- * if packages are added/removed.
- */
- private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
-
- // First, test for intents that matter at any time
- if (action.equals(Intent.ACTION_PACKAGE_ADDED) ||
- action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
- action.equals(Intent.ACTION_PACKAGE_CHANGED)) {
- mSearchablesDirty = true;
- if (IMMEDIATE_SEARCHABLES_UPDATE) {
- mHandler.post(mRunUpdateSearchable);
- }
- return;
- }
- }
- };
-
- /**
- * This runnable (for the main handler / UI thread) will update the searchables list.
- */
- private Runnable mRunUpdateSearchable = new Runnable() {
- public void run() {
- if (mSearchablesDirty) {
- updateSearchables();
- }
- }
- };
-
- /**
- * Update the list of searchables, either at startup or in response to
- * a package add/remove broadcast message.
- */
- private void updateSearchables() {
- SearchableInfo.buildSearchableList(mContext);
- mSearchablesDirty = false;
-
- // TODO This is a hack. This shouldn't be hardcoded here, it's probably
- // a policy.
-// ComponentName defaultSearch = new ComponentName(
-// "com.android.contacts",
-// "com.android.contacts.ContactsListActivity" );
- ComponentName defaultSearch = new ComponentName(
- "com.android.googlesearch",
- "com.android.googlesearch.GoogleSearch" );
- SearchableInfo.setDefaultSearchable(mContext, defaultSearch);
- }
-
- /**
- * Return the searchableinfo for a given activity
- *
- * @param launchActivity The activity from which we're launching this search.
- * @return Returns a SearchableInfo record describing the parameters of the search,
- * or null if no searchable metadata was available.
- * @param globalSearch If false, this will only launch the search that has been specifically
- * defined by the application (which is usually defined as a local search). If no default
- * search is defined in the current application or activity, no search will be launched.
- * If true, this will always launch a platform-global (e.g. web-based) search instead.
- */
- public SearchableInfo getSearchableInfo(ComponentName launchActivity, boolean globalSearch) {
- // final check. however we should try to avoid this, because
- // it slows down the entry into the UI.
- if (mSearchablesDirty) {
- updateSearchables();
- }
- SearchableInfo si = null;
- if (globalSearch) {
- si = SearchableInfo.getDefaultSearchable();
- } else {
- si = SearchableInfo.getSearchableInfo(mContext, launchActivity);
- }
-
- return si;
- }
-}
diff --git a/core/java/android/server/search/SearchableInfo.aidl b/core/java/android/server/search/SearchableInfo.aidl
deleted file mode 100644
index 9576c2b..0000000
--- a/core/java/android/server/search/SearchableInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2008, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server.search;
-
-parcelable SearchableInfo;
diff --git a/core/java/android/server/search/SearchableInfo.java b/core/java/android/server/search/SearchableInfo.java
deleted file mode 100644
index c18675e..0000000
--- a/core/java/android/server/search/SearchableInfo.java
+++ /dev/null
@@ -1,850 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.server.search;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ResolveInfo;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.InputType;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Xml;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-public final class SearchableInfo implements Parcelable {
-
- // general debugging support
- final static String LOG_TAG = "SearchableInfo";
-
- // set this flag to 1 to prevent any apps from providing suggestions
- final static int DBG_INHIBIT_SUGGESTIONS = 0;
-
- // static strings used for XML lookups, etc.
- // TODO how should these be documented for the developer, in a more structured way than
- // the current long wordy javadoc in SearchManager.java ?
- private static final String MD_LABEL_DEFAULT_SEARCHABLE = "android.app.default_searchable";
- private static final String MD_LABEL_SEARCHABLE = "android.app.searchable";
- private static final String MD_SEARCHABLE_SYSTEM_SEARCH = "*";
- private static final String MD_XML_ELEMENT_SEARCHABLE = "searchable";
- private static final String MD_XML_ELEMENT_SEARCHABLE_ACTION_KEY = "actionkey";
-
- // class maintenance and general shared data
- private static HashMap<ComponentName, SearchableInfo> sSearchablesMap = null;
- private static ArrayList<SearchableInfo> sSearchablesList = null;
- private static SearchableInfo sDefaultSearchable = null;
-
- // true member variables - what we know about the searchability
- // TO-DO replace public with getters
- public boolean mSearchable = false;
- private int mLabelId = 0;
- public ComponentName mSearchActivity = null;
- private int mHintId = 0;
- private int mSearchMode = 0;
- public boolean mBadgeLabel = false;
- public boolean mBadgeIcon = false;
- public boolean mQueryRewriteFromData = false;
- public boolean mQueryRewriteFromText = false;
- private int mIconId = 0;
- private int mSearchButtonText = 0;
- private int mSearchInputType = 0;
- private String mSuggestAuthority = null;
- private String mSuggestPath = null;
- private String mSuggestSelection = null;
- private String mSuggestIntentAction = null;
- private String mSuggestIntentData = null;
- private ActionKeyInfo mActionKeyList = null;
- private String mSuggestProviderPackage = null;
- private Context mCacheActivityContext = null; // use during setup only - don't hold memory!
-
- // Flag values for Searchable_voiceSearchMode
- private static int VOICE_SEARCH_SHOW_BUTTON = 1;
- private static int VOICE_SEARCH_LAUNCH_WEB_SEARCH = 2;
- private static int VOICE_SEARCH_LAUNCH_RECOGNIZER = 4;
- private int mVoiceSearchMode = 0;
- private int mVoiceLanguageModeId; // voiceLanguageModel
- private int mVoicePromptTextId; // voicePromptText
- private int mVoiceLanguageId; // voiceLanguage
- private int mVoiceMaxResults; // voiceMaxResults
-
- /**
- * Set the default searchable activity (when none is specified).
- */
- public static void setDefaultSearchable(Context context,
- ComponentName activity) {
- synchronized (SearchableInfo.class) {
- SearchableInfo si = null;
- if (activity != null) {
- si = getSearchableInfo(context, activity);
- if (si != null) {
- // move to front of list
- sSearchablesList.remove(si);
- sSearchablesList.add(0, si);
- }
- }
- sDefaultSearchable = si;
- }
- }
-
- /**
- * Provides the system-default search activity, which you can use
- * whenever getSearchableInfo() returns null;
- *
- * @return Returns the system-default search activity, null if never defined
- */
- public static SearchableInfo getDefaultSearchable() {
- synchronized (SearchableInfo.class) {
- return sDefaultSearchable;
- }
- }
-
- /**
- * Retrieve the authority for obtaining search suggestions.
- *
- * @return Returns a string containing the suggestions authority.
- */
- public String getSuggestAuthority() {
- return mSuggestAuthority;
- }
-
- /**
- * Retrieve the path for obtaining search suggestions.
- *
- * @return Returns a string containing the suggestions path, or null if not provided.
- */
- public String getSuggestPath() {
- return mSuggestPath;
- }
-
- /**
- * Retrieve the selection pattern for obtaining search suggestions. This must
- * include a single ? which will be used for the user-typed characters.
- *
- * @return Returns a string containing the suggestions authority.
- */
- public String getSuggestSelection() {
- return mSuggestSelection;
- }
-
- /**
- * Retrieve the (optional) intent action for use with these suggestions. This is
- * useful if all intents will have the same action (e.g. "android.intent.action.VIEW").
- *
- * Can be overriden in any given suggestion via the AUTOSUGGEST_COLUMN_INTENT_ACTION column.
- *
- * @return Returns a string containing the default intent action.
- */
- public String getSuggestIntentAction() {
- return mSuggestIntentAction;
- }
-
- /**
- * Retrieve the (optional) intent data for use with these suggestions. This is
- * useful if all intents will have similar data URIs (e.g. "android.intent.action.VIEW"),
- * but you'll likely need to provide a specific ID as well via the column
- * AUTOSUGGEST_COLUMN_INTENT_DATA_ID, which will be appended to the intent data URI.
- *
- * Can be overriden in any given suggestion via the AUTOSUGGEST_COLUMN_INTENT_DATA column.
- *
- * @return Returns a string containing the default intent data.
- */
- public String getSuggestIntentData() {
- return mSuggestIntentData;
- }
-
- /**
- * Get the context for the searchable activity.
- *
- * This is fairly expensive so do it on the original scan, or when an app is
- * selected, but don't hang on to the result forever.
- *
- * @param context You need to supply a context to start with
- * @return Returns a context related to the searchable activity
- */
- public Context getActivityContext(Context context) {
- Context theirContext = null;
- try {
- theirContext = context.createPackageContext(mSearchActivity.getPackageName(), 0);
- } catch (PackageManager.NameNotFoundException e) {
- // unexpected, but we deal with this by null-checking theirContext
- } catch (java.lang.SecurityException e) {
- // unexpected, but we deal with this by null-checking theirContext
- }
-
- return theirContext;
- }
-
- /**
- * Get the context for the suggestions provider.
- *
- * This is fairly expensive so do it on the original scan, or when an app is
- * selected, but don't hang on to the result forever.
- *
- * @param context You need to supply a context to start with
- * @param activityContext If we can determine that the provider and the activity are the
- * same, we'll just return this one.
- * @return Returns a context related to the context provider
- */
- public Context getProviderContext(Context context, Context activityContext) {
- Context theirContext = null;
- if (mSearchActivity.getPackageName().equals(mSuggestProviderPackage)) {
- return activityContext;
- }
- if (mSuggestProviderPackage != null)
- try {
- theirContext = context.createPackageContext(mSuggestProviderPackage, 0);
- } catch (PackageManager.NameNotFoundException e) {
- // unexpected, but we deal with this by null-checking theirContext
- } catch (java.lang.SecurityException e) {
- // unexpected, but we deal with this by null-checking theirContext
- }
-
- return theirContext;
- }
-
- /**
- * Factory. Look up, or construct, based on the activity.
- *
- * The activities fall into three cases, based on meta-data found in
- * the manifest entry:
- * <ol>
- * <li>The activity itself implements search. This is indicated by the
- * presence of a "android.app.searchable" meta-data attribute.
- * The value is a reference to an XML file containing search information.</li>
- * <li>A related activity implements search. This is indicated by the
- * presence of a "android.app.default_searchable" meta-data attribute.
- * The value is a string naming the activity implementing search. In this
- * case the factory will "redirect" and return the searchable data.</li>
- * <li>No searchability data is provided. We return null here and other
- * code will insert the "default" (e.g. contacts) search.
- *
- * TODO: cache the result in the map, and check the map first.
- * TODO: it might make sense to implement the searchable reference as
- * an application meta-data entry. This way we don't have to pepper each
- * and every activity.
- * TODO: can we skip the constructor step if it's a non-searchable?
- * TODO: does it make sense to plug the default into a slot here for
- * automatic return? Probably not, but it's one way to do it.
- *
- * @param activity The name of the current activity, or null if the
- * activity does not define any explicit searchable metadata.
- */
- public static SearchableInfo getSearchableInfo(Context context,
- ComponentName activity) {
- // Step 1. Is the result already hashed? (case 1)
- SearchableInfo result;
- synchronized (SearchableInfo.class) {
- result = sSearchablesMap.get(activity);
- if (result != null) return result;
- }
-
- // Step 2. See if the current activity references a searchable.
- // Note: Conceptually, this could be a while(true) loop, but there's
- // no point in implementing reference chaining here and risking a loop.
- // References must point directly to searchable activities.
-
- ActivityInfo ai = null;
- XmlPullParser xml = null;
- try {
- ai = context.getPackageManager().
- getActivityInfo(activity, PackageManager.GET_META_DATA );
- String refActivityName = null;
-
- // First look for activity-specific reference
- Bundle md = ai.metaData;
- if (md != null) {
- refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE);
- }
- // If not found, try for app-wide reference
- if (refActivityName == null) {
- md = ai.applicationInfo.metaData;
- if (md != null) {
- refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE);
- }
- }
-
- // Irrespective of source, if a reference was found, follow it.
- if (refActivityName != null)
- {
- // An app or activity can declare that we should simply launch
- // "system default search" if search is invoked.
- if (refActivityName.equals(MD_SEARCHABLE_SYSTEM_SEARCH)) {
- return getDefaultSearchable();
- }
- String pkg = activity.getPackageName();
- ComponentName referredActivity;
- if (refActivityName.charAt(0) == '.') {
- referredActivity = new ComponentName(pkg, pkg + refActivityName);
- } else {
- referredActivity = new ComponentName(pkg, refActivityName);
- }
-
- // Now try the referred activity, and if found, cache
- // it against the original name so we can skip the check
- synchronized (SearchableInfo.class) {
- result = sSearchablesMap.get(referredActivity);
- if (result != null) {
- sSearchablesMap.put(activity, result);
- return result;
- }
- }
- }
- } catch (PackageManager.NameNotFoundException e) {
- // case 3: no metadata
- }
-
- // Step 3. None found. Return null.
- return null;
-
- }
-
- /**
- * Super-factory. Builds an entire list (suitable for display) of
- * activities that are searchable, by iterating the entire set of
- * ACTION_SEARCH intents.
- *
- * Also clears the hash of all activities -> searches which will
- * refill as the user clicks "search".
- *
- * This should only be done at startup and again if we know that the
- * list has changed.
- *
- * TODO: every activity that provides a ACTION_SEARCH intent should
- * also provide searchability meta-data. There are a bunch of checks here
- * that, if data is not found, silently skip to the next activity. This
- * won't help a developer trying to figure out why their activity isn't
- * showing up in the list, but an exception here is too rough. I would
- * like to find a better notification mechanism.
- *
- * TODO: sort the list somehow? UI choice.
- *
- * @param context a context we can use during this work
- */
- public static void buildSearchableList(Context context) {
-
- // create empty hash & list
- HashMap<ComponentName, SearchableInfo> newSearchablesMap
- = new HashMap<ComponentName, SearchableInfo>();
- ArrayList<SearchableInfo> newSearchablesList
- = new ArrayList<SearchableInfo>();
-
- // use intent resolver to generate list of ACTION_SEARCH receivers
- final PackageManager pm = context.getPackageManager();
- List<ResolveInfo> infoList;
- final Intent intent = new Intent(Intent.ACTION_SEARCH);
- infoList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
-
- // analyze each one, generate a Searchables record, and record
- if (infoList != null) {
- int count = infoList.size();
- for (int ii = 0; ii < count; ii++) {
- // for each component, try to find metadata
- ResolveInfo info = infoList.get(ii);
- ActivityInfo ai = info.activityInfo;
- XmlResourceParser xml = ai.loadXmlMetaData(context.getPackageManager(),
- MD_LABEL_SEARCHABLE);
- if (xml == null) {
- continue;
- }
- ComponentName cName = new ComponentName(
- info.activityInfo.packageName,
- info.activityInfo.name);
-
- SearchableInfo searchable = getActivityMetaData(context, xml, cName);
- xml.close();
-
- if (searchable != null) {
- // no need to keep the context any longer. setup time is over.
- searchable.mCacheActivityContext = null;
-
- newSearchablesList.add(searchable);
- newSearchablesMap.put(cName, searchable);
- }
- }
- }
-
- // record the final values as a coherent pair
- synchronized (SearchableInfo.class) {
- sSearchablesList = newSearchablesList;
- sSearchablesMap = newSearchablesMap;
- }
- }
-
- /**
- * Constructor
- *
- * Given a ComponentName, get the searchability info
- * and build a local copy of it. Use the factory, not this.
- *
- * @param context runtime context
- * @param attr The attribute set we found in the XML file, contains the values that are used to
- * construct the object.
- * @param cName The component name of the searchable activity
- */
- private SearchableInfo(Context context, AttributeSet attr, final ComponentName cName) {
- // initialize as an "unsearchable" object
- mSearchable = false;
- mSearchActivity = cName;
-
- // to access another activity's resources, I need its context.
- // BE SURE to release the cache sometime after construction - it's a large object to hold
- mCacheActivityContext = getActivityContext(context);
- if (mCacheActivityContext != null) {
- TypedArray a = mCacheActivityContext.obtainStyledAttributes(attr,
- com.android.internal.R.styleable.Searchable);
- mSearchMode = a.getInt(com.android.internal.R.styleable.Searchable_searchMode, 0);
- mLabelId = a.getResourceId(com.android.internal.R.styleable.Searchable_label, 0);
- mHintId = a.getResourceId(com.android.internal.R.styleable.Searchable_hint, 0);
- mIconId = a.getResourceId(com.android.internal.R.styleable.Searchable_icon, 0);
- mSearchButtonText = a.getResourceId(
- com.android.internal.R.styleable.Searchable_searchButtonText, 0);
- mSearchInputType = a.getInt(com.android.internal.R.styleable.Searchable_inputType,
- InputType.TYPE_CLASS_TEXT |
- InputType.TYPE_TEXT_FLAG_SEARCH |
- InputType.TYPE_TEXT_VARIATION_NORMAL);
-
- setSearchModeFlags();
- if (DBG_INHIBIT_SUGGESTIONS == 0) {
- mSuggestAuthority = a.getString(
- com.android.internal.R.styleable.Searchable_searchSuggestAuthority);
- mSuggestPath = a.getString(
- com.android.internal.R.styleable.Searchable_searchSuggestPath);
- mSuggestSelection = a.getString(
- com.android.internal.R.styleable.Searchable_searchSuggestSelection);
- mSuggestIntentAction = a.getString(
- com.android.internal.R.styleable.Searchable_searchSuggestIntentAction);
- mSuggestIntentData = a.getString(
- com.android.internal.R.styleable.Searchable_searchSuggestIntentData);
- }
- mVoiceSearchMode =
- a.getInt(com.android.internal.R.styleable.Searchable_voiceSearchMode, 0);
- // TODO this didn't work - came back zero from YouTube
- mVoiceLanguageModeId =
- a.getResourceId(com.android.internal.R.styleable.Searchable_voiceLanguageModel, 0);
- mVoicePromptTextId =
- a.getResourceId(com.android.internal.R.styleable.Searchable_voicePromptText, 0);
- mVoiceLanguageId =
- a.getResourceId(com.android.internal.R.styleable.Searchable_voiceLanguage, 0);
- mVoiceMaxResults =
- a.getInt(com.android.internal.R.styleable.Searchable_voiceMaxResults, 0);
-
- a.recycle();
-
- // get package info for suggestions provider (if any)
- if (mSuggestAuthority != null) {
- ProviderInfo pi =
- context.getPackageManager().resolveContentProvider(mSuggestAuthority,
- 0);
- if (pi != null) {
- mSuggestProviderPackage = pi.packageName;
- }
- }
- }
-
- // for now, implement some form of rules - minimal data
- if (mLabelId != 0) {
- mSearchable = true;
- } else {
- // Provide some help for developers instead of just silently discarding
- Log.w(LOG_TAG, "Insufficient metadata to configure searchability for " +
- cName.flattenToShortString());
- }
- }
-
- /**
- * Convert searchmode to flags.
- */
- private void setSearchModeFlags() {
- mBadgeLabel = (0 != (mSearchMode & 4));
- mBadgeIcon = (0 != (mSearchMode & 8)) && (mIconId != 0);
- mQueryRewriteFromData = (0 != (mSearchMode & 0x10));
- mQueryRewriteFromText = (0 != (mSearchMode & 0x20));
- }
-
- /**
- * Private class used to hold the "action key" configuration
- */
- public class ActionKeyInfo implements Parcelable {
-
- public int mKeyCode = 0;
- public String mQueryActionMsg;
- public String mSuggestActionMsg;
- public String mSuggestActionMsgColumn;
- private ActionKeyInfo mNext;
-
- /**
- * Create one object using attributeset as input data.
- * @param context runtime context
- * @param attr The attribute set we found in the XML file, contains the values that are used to
- * construct the object.
- * @param next We'll build these up using a simple linked list (since there are usually
- * just zero or one).
- */
- public ActionKeyInfo(Context context, AttributeSet attr, ActionKeyInfo next) {
- TypedArray a = mCacheActivityContext.obtainStyledAttributes(attr,
- com.android.internal.R.styleable.SearchableActionKey);
-
- mKeyCode = a.getInt(
- com.android.internal.R.styleable.SearchableActionKey_keycode, 0);
- mQueryActionMsg = a.getString(
- com.android.internal.R.styleable.SearchableActionKey_queryActionMsg);
- if (DBG_INHIBIT_SUGGESTIONS == 0) {
- mSuggestActionMsg = a.getString(
- com.android.internal.R.styleable.SearchableActionKey_suggestActionMsg);
- mSuggestActionMsgColumn = a.getString(
- com.android.internal.R.styleable.SearchableActionKey_suggestActionMsgColumn);
- }
- a.recycle();
-
- // initialize any other fields
- mNext = next;
-
- // sanity check. must have at least one action message, or invalidate the object.
- if ((mQueryActionMsg == null) &&
- (mSuggestActionMsg == null) &&
- (mSuggestActionMsgColumn == null)) {
- mKeyCode = 0;
- }
- }
-
- /**
- * Instantiate a new ActionKeyInfo from the data in a Parcel that was
- * previously written with {@link #writeToParcel(Parcel, int)}.
- *
- * @param in The Parcel containing the previously written ActionKeyInfo,
- * positioned at the location in the buffer where it was written.
- * @param next The value to place in mNext, creating a linked list
- */
- public ActionKeyInfo(Parcel in, ActionKeyInfo next) {
- mKeyCode = in.readInt();
- mQueryActionMsg = in.readString();
- mSuggestActionMsg = in.readString();
- mSuggestActionMsgColumn = in.readString();
- mNext = next;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mKeyCode);
- dest.writeString(mQueryActionMsg);
- dest.writeString(mSuggestActionMsg);
- dest.writeString(mSuggestActionMsgColumn);
- }
- }
-
- /**
- * If any action keys were defined for this searchable activity, look up and return.
- *
- * @param keyCode The key that was pressed
- * @return Returns the ActionKeyInfo record, or null if none defined
- */
- public ActionKeyInfo findActionKey(int keyCode) {
- ActionKeyInfo info = mActionKeyList;
- while (info != null) {
- if (info.mKeyCode == keyCode) {
- return info;
- }
- info = info.mNext;
- }
- return null;
- }
-
- /**
- * Get the metadata for a given activity
- *
- * TODO: clean up where we return null vs. where we throw exceptions.
- *
- * @param context runtime context
- * @param xml XML parser for reading attributes
- * @param cName The component name of the searchable activity
- *
- * @result A completely constructed SearchableInfo, or null if insufficient XML data for it
- */
- private static SearchableInfo getActivityMetaData(Context context, XmlPullParser xml,
- final ComponentName cName) {
- SearchableInfo result = null;
-
- // in order to use the attributes mechanism, we have to walk the parser
- // forward through the file until it's reading the tag of interest.
- try {
- int tagType = xml.next();
- while (tagType != XmlPullParser.END_DOCUMENT) {
- if (tagType == XmlPullParser.START_TAG) {
- if (xml.getName().equals(MD_XML_ELEMENT_SEARCHABLE)) {
- AttributeSet attr = Xml.asAttributeSet(xml);
- if (attr != null) {
- result = new SearchableInfo(context, attr, cName);
- // if the constructor returned a bad object, exit now.
- if (! result.mSearchable) {
- return null;
- }
- }
- } else if (xml.getName().equals(MD_XML_ELEMENT_SEARCHABLE_ACTION_KEY)) {
- if (result == null) {
- // Can't process an embedded element if we haven't seen the enclosing
- return null;
- }
- AttributeSet attr = Xml.asAttributeSet(xml);
- if (attr != null) {
- ActionKeyInfo keyInfo = result.new ActionKeyInfo(context, attr,
- result.mActionKeyList);
- // only add to list if it is was useable
- if (keyInfo.mKeyCode != 0) {
- result.mActionKeyList = keyInfo;
- }
- }
- }
- }
- tagType = xml.next();
- }
- } catch (XmlPullParserException e) {
- throw new RuntimeException(e);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- return result;
- }
-
- /**
- * Return the "label" (user-visible name) of this searchable context. This must be
- * accessed using the target (searchable) Activity's resources, not simply the context of the
- * caller.
- *
- * @return Returns the resource Id
- */
- public int getLabelId() {
- return mLabelId;
- }
-
- /**
- * Return the resource Id of the hint text. This must be
- * accessed using the target (searchable) Activity's resources, not simply the context of the
- * caller.
- *
- * @return Returns the resource Id, or 0 if not specified by this package.
- */
- public int getHintId() {
- return mHintId;
- }
-
- /**
- * Return the icon Id specified by the Searchable_icon meta-data entry. This must be
- * accessed using the target (searchable) Activity's resources, not simply the context of the
- * caller.
- *
- * @return Returns the resource id.
- */
- public int getIconId() {
- return mIconId;
- }
-
- /**
- * @return true if android:voiceSearchMode="showVoiceSearchButton"
- */
- public boolean getVoiceSearchEnabled() {
- return 0 != (mVoiceSearchMode & VOICE_SEARCH_SHOW_BUTTON);
- }
-
- /**
- * @return true if android:voiceSearchMode="launchWebSearch"
- */
- public boolean getVoiceSearchLaunchWebSearch() {
- return 0 != (mVoiceSearchMode & VOICE_SEARCH_LAUNCH_WEB_SEARCH);
- }
-
- /**
- * @return true if android:voiceSearchMode="launchRecognizer"
- */
- public boolean getVoiceSearchLaunchRecognizer() {
- return 0 != (mVoiceSearchMode & VOICE_SEARCH_LAUNCH_RECOGNIZER);
- }
-
- /**
- * @return the resource Id of the language model string, if specified in the searchable
- * activity's metadata, or 0 if not specified.
- */
- public int getVoiceLanguageModeId() {
- return mVoiceLanguageModeId;
- }
-
- /**
- * @return the resource Id of the voice prompt text string, if specified in the searchable
- * activity's metadata, or 0 if not specified.
- */
- public int getVoicePromptTextId() {
- return mVoicePromptTextId;
- }
-
- /**
- * @return the resource Id of the spoken langauge, if specified in the searchable
- * activity's metadata, or 0 if not specified.
- */
- public int getVoiceLanguageId() {
- return mVoiceLanguageId;
- }
-
- /**
- * @return the max results count, if specified in the searchable
- * activity's metadata, or 0 if not specified.
- */
- public int getVoiceMaxResults() {
- return mVoiceMaxResults;
- }
-
- /**
- * Return the resource Id of replacement text for the "Search" button.
- *
- * @return Returns the resource Id, or 0 if not specified by this package.
- */
- public int getSearchButtonText() {
- return mSearchButtonText;
- }
-
- /**
- * Return the input type as specified in the searchable attributes. This will default to
- * InputType.TYPE_CLASS_TEXT if not specified (which is appropriate for free text input).
- *
- * @return the input type
- */
- public int getInputType() {
- return mSearchInputType;
- }
-
- /**
- * Return the list of searchable activities, for use in the drop-down.
- */
- public static ArrayList<SearchableInfo> getSearchablesList() {
- synchronized (SearchableInfo.class) {
- ArrayList<SearchableInfo> result = new ArrayList<SearchableInfo>(sSearchablesList);
- return result;
- }
- }
-
- /**
- * Support for parcelable and aidl operations.
- */
- public static final Parcelable.Creator<SearchableInfo> CREATOR
- = new Parcelable.Creator<SearchableInfo>() {
- public SearchableInfo createFromParcel(Parcel in) {
- return new SearchableInfo(in);
- }
-
- public SearchableInfo[] newArray(int size) {
- return new SearchableInfo[size];
- }
- };
-
- /**
- * Instantiate a new SearchableInfo from the data in a Parcel that was
- * previously written with {@link #writeToParcel(Parcel, int)}.
- *
- * @param in The Parcel containing the previously written SearchableInfo,
- * positioned at the location in the buffer where it was written.
- */
- public SearchableInfo(Parcel in) {
- mSearchable = in.readInt() != 0;
- mLabelId = in.readInt();
- mSearchActivity = ComponentName.readFromParcel(in);
- mHintId = in.readInt();
- mSearchMode = in.readInt();
- mIconId = in.readInt();
- mSearchButtonText = in.readInt();
- mSearchInputType = in.readInt();
- setSearchModeFlags();
-
- mSuggestAuthority = in.readString();
- mSuggestPath = in.readString();
- mSuggestSelection = in.readString();
- mSuggestIntentAction = in.readString();
- mSuggestIntentData = in.readString();
-
- mActionKeyList = null;
- int count = in.readInt();
- while (count-- > 0) {
- mActionKeyList = new ActionKeyInfo(in, mActionKeyList);
- }
-
- mSuggestProviderPackage = in.readString();
-
- mVoiceSearchMode = in.readInt();
- mVoiceLanguageModeId = in.readInt();
- mVoicePromptTextId = in.readInt();
- mVoiceLanguageId = in.readInt();
- mVoiceMaxResults = in.readInt();
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mSearchable ? 1 : 0);
- dest.writeInt(mLabelId);
- mSearchActivity.writeToParcel(dest, flags);
- dest.writeInt(mHintId);
- dest.writeInt(mSearchMode);
- dest.writeInt(mIconId);
- dest.writeInt(mSearchButtonText);
- dest.writeInt(mSearchInputType);
-
- dest.writeString(mSuggestAuthority);
- dest.writeString(mSuggestPath);
- dest.writeString(mSuggestSelection);
- dest.writeString(mSuggestIntentAction);
- dest.writeString(mSuggestIntentData);
-
- // This is usually a very short linked list so we'll just pre-count it
- ActionKeyInfo nextKeyInfo = mActionKeyList;
- int count = 0;
- while (nextKeyInfo != null) {
- ++count;
- nextKeyInfo = nextKeyInfo.mNext;
- }
- dest.writeInt(count);
- // Now write count of 'em
- nextKeyInfo = mActionKeyList;
- while (count-- > 0) {
- nextKeyInfo.writeToParcel(dest, flags);
- }
-
- dest.writeString(mSuggestProviderPackage);
-
- dest.writeInt(mVoiceSearchMode);
- dest.writeInt(mVoiceLanguageModeId);
- dest.writeInt(mVoicePromptTextId);
- dest.writeInt(mVoiceLanguageId);
- dest.writeInt(mVoiceMaxResults);
- }
-}
diff --git a/core/java/android/server/search/package.html b/core/java/android/server/search/package.html
deleted file mode 100644
index c9f96a6..0000000
--- a/core/java/android/server/search/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>
diff --git a/core/java/android/speech/RecognizerIntent.java b/core/java/android/speech/RecognizerIntent.java
deleted file mode 100644
index 987e763..0000000
--- a/core/java/android/speech/RecognizerIntent.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.speech;
-
-import android.app.Activity;
-import android.content.ActivityNotFoundException;
-import android.content.Intent;
-
-/**
- * Constants for supporting speech recognition through starting an {@link Intent}
- */
-public class RecognizerIntent {
- private RecognizerIntent() {
- // Not for instantiating.
- }
-
- /**
- * Starts an activity that will prompt the user for speech and sends it through a
- * speech recognizer. The results will be returned via activity results, or forwarded
- * via a PendingIntent if one is provided.
- *
- * <p>Required extras:
- * <ul>
- * <li>{@link #EXTRA_LANGUAGE_MODEL}
- * </ul>
- *
- * <p>Optional extras:
- * <ul>
- * <li>{@link #EXTRA_PROMPT}
- * <li>{@link #EXTRA_LANGUAGE}
- * <li>{@link #EXTRA_MAX_RESULTS}
- * <li>{@link #EXTRA_RESULTS_PENDINGINTENT}
- * <li>{@link #EXTRA_RESULTS_PENDINGINTENT_BUNDLE}
- * </ul>
- *
- * <p> Result extras:
- * <ul>
- * <li>{@link #EXTRA_RESULTS}
- * </ul>
- *
- * <p>NOTE: There may not be any applications installed to handle this action, so you should
- * make sure to catch {@link ActivityNotFoundException}.
- */
- public static final String ACTION_RECOGNIZE_SPEECH = "android.speech.action.RECOGNIZE_SPEECH";
-
- /**
- * Starts an activity that will prompt the user for speech, sends it through a
- * speech recognizer, and invokes and displays a web search result.
- *
- * <p>Required extras:
- * <ul>
- * <li>{@link #EXTRA_LANGUAGE_MODEL}
- * </ul>
- *
- * <p>Optional extras:
- * <ul>
- * <li>{@link #EXTRA_PROMPT}
- * <li>{@link #EXTRA_LANGUAGE}
- * <li>{@link #EXTRA_MAX_RESULTS}
- * </ul>
- *
- * <p> Result extras:
- * <ul>
- * <li>{@link #EXTRA_RESULTS}
- * </ul>
- *
- * <p>NOTE: There may not be any applications installed to handle this action, so you should
- * make sure to catch {@link ActivityNotFoundException}.
- */
- public static final String ACTION_WEB_SEARCH = "android.speech.action.WEB_SEARCH";
-
- /**
- * Informs the recognizer which speech model to prefer when performing
- * {@link #ACTION_RECOGNIZE_SPEECH}. The recognizer uses this
- * information to fine tune the results. This extra is required. Activities implementing
- * {@link #ACTION_RECOGNIZE_SPEECH} may interpret the values as they see fit.
- *
- * @see #LANGUAGE_MODEL_FREE_FORM
- * @see #LANGUAGE_MODEL_WEB_SEARCH
- */
- public static final String EXTRA_LANGUAGE_MODEL = "android.speech.extra.LANGUAGE_MODEL";
-
- /**
- * Use a language model based on free-form speech recognition. This is a value to use for
- * {@link #EXTRA_LANGUAGE_MODEL}.
- * @see #EXTRA_LANGUAGE_MODEL
- */
- public static final String LANGUAGE_MODEL_FREE_FORM = "free_form";
- /**
- * Use a language model based on web search terms. This is a value to use for
- * {@link #EXTRA_LANGUAGE_MODEL}.
- * @see #EXTRA_LANGUAGE_MODEL
- */
- public static final String LANGUAGE_MODEL_WEB_SEARCH = "web_search";
-
- /** Optional text prompt to show to the user when asking them to speak. */
- public static final String EXTRA_PROMPT = "android.speech.extra.PROMPT";
-
- /**
- * Optional language override to inform the recognizer that it should expect speech in
- * a language different than the one set in the {@link java.util.Locale#getDefault()}.
- */
- public static final String EXTRA_LANGUAGE = "android.speech.extra.LANGUAGE";
-
- /**
- * Optional limit on the maximum number of results to return. If omitted the recognizer
- * will choose how many results to return. Must be an integer.
- */
- public static final String EXTRA_MAX_RESULTS = "android.speech.extra.MAX_RESULTS";
-
- /**
- * When the intent is {@link #ACTION_RECOGNIZE_SPEECH}, the speech input activity will
- * return results to you via the activity results mechanism. Alternatively, if you use this
- * extra to supply a PendingIntent, the results will be added to its bundle and the
- * PendingIntent will be sent to its target.
- */
- public static final String EXTRA_RESULTS_PENDINGINTENT =
- "android.speech.extra.RESULTS_PENDINGINTENT";
- /**
- * If you use {@link #EXTRA_RESULTS_PENDINGINTENT} to supply a forwarding intent, you can
- * also use this extra to supply additional extras for the final intent. The search results
- * will be added to this bundle, and the combined bundle will be sent to the target.
- */
- public static final String EXTRA_RESULTS_PENDINGINTENT_BUNDLE =
- "android.speech.extra.RESULTS_PENDINGINTENT_BUNDLE";
-
- /** Result code returned when no matches are found for the given speech */
- public static final int RESULT_NO_MATCH = Activity.RESULT_FIRST_USER;
- /** Result code returned when there is a generic client error */
- public static final int RESULT_CLIENT_ERROR = Activity.RESULT_FIRST_USER + 1;
- /** Result code returned when the recognition server returns an error */
- public static final int RESULT_SERVER_ERROR = Activity.RESULT_FIRST_USER + 2;
- /** Result code returned when a network error was encountered */
- public static final int RESULT_NETWORK_ERROR = Activity.RESULT_FIRST_USER + 3;
- /** Result code returned when an audio error was encountered */
- public static final int RESULT_AUDIO_ERROR = Activity.RESULT_FIRST_USER + 4;
-
- /**
- * An ArrayList<String> of the potential results when performing
- * {@link #ACTION_RECOGNIZE_SPEECH}. Only present when {@link Activity#RESULT_OK} is returned.
- */
- public static final String EXTRA_RESULTS = "android.speech.extra.RESULTS";
-}
diff --git a/core/java/android/speech/srec/MicrophoneInputStream.java b/core/java/android/speech/srec/MicrophoneInputStream.java
deleted file mode 100644
index fab77a9..0000000
--- a/core/java/android/speech/srec/MicrophoneInputStream.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*---------------------------------------------------------------------------*
- * MicrophoneInputStream.java *
- * *
- * Copyright 2007 Nuance Communciations, Inc. *
- * *
- * Licensed under the Apache License, Version 2.0 (the 'License'); *
- * you may not use this file except in compliance with the License. *
- * *
- * You may obtain a copy of the License at *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, software *
- * distributed under the License is distributed on an 'AS IS' BASIS, *
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
- * See the License for the specific language governing permissions and *
- * limitations under the License. *
- * *
- *---------------------------------------------------------------------------*/
-
-
-package android.speech.srec;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.IllegalStateException;
-
-
-/**
- * PCM input stream from the microphone, 16 bits per sample.
- */
-public final class MicrophoneInputStream extends InputStream {
- static {
- System.loadLibrary("srec_jni");
- }
-
- private final static String TAG = "MicrophoneInputStream";
- private int mAudioRecord = 0;
- private byte[] mOneByte = new byte[1];
-
- /**
- * MicrophoneInputStream constructor.
- * @param sampleRate sample rate of the microphone, typically 11025 or 8000.
- * @param fifoDepth depth of the real time fifo, measured in sampleRate clock ticks.
- * This determines how long an application may delay before losing data.
- */
- public MicrophoneInputStream(int sampleRate, int fifoDepth) throws IOException {
- mAudioRecord = AudioRecordNew(sampleRate, fifoDepth);
- if (mAudioRecord == 0) throw new IOException("AudioRecord constructor failed - busy?");
- int status = AudioRecordStart(mAudioRecord);
- if (status != 0) {
- close();
- throw new IOException("AudioRecord start failed: " + status);
- }
- }
-
- @Override
- public int read() throws IOException {
- if (mAudioRecord == 0) throw new IllegalStateException("not open");
- int rtn = AudioRecordRead(mAudioRecord, mOneByte, 0, 1);
- return rtn == 1 ? ((int)mOneByte[0] & 0xff) : -1;
- }
-
- @Override
- public int read(byte[] b) throws IOException {
- if (mAudioRecord == 0) throw new IllegalStateException("not open");
- return AudioRecordRead(mAudioRecord, b, 0, b.length);
- }
-
- @Override
- public int read(byte[] b, int offset, int length) throws IOException {
- if (mAudioRecord == 0) throw new IllegalStateException("not open");
- // TODO: should we force all reads to be a multiple of the sample size?
- return AudioRecordRead(mAudioRecord, b, offset, length);
- }
-
- /**
- * Closes this stream.
- */
- @Override
- public void close() throws IOException {
- if (mAudioRecord != 0) {
- try {
- AudioRecordStop(mAudioRecord);
- } finally {
- try {
- AudioRecordDelete(mAudioRecord);
- } finally {
- mAudioRecord = 0;
- }
- }
- }
- }
-
- @Override
- protected void finalize() throws Throwable {
- if (mAudioRecord != 0) {
- close();
- throw new IOException("someone forgot to close MicrophoneInputStream");
- }
- }
-
- //
- // AudioRecord JNI interface
- //
- private static native int AudioRecordNew(int sampleRate, int fifoDepth);
- private static native int AudioRecordStart(int audioRecord);
- private static native int AudioRecordRead(int audioRecord, byte[] b, int offset, int length) throws IOException;
- private static native void AudioRecordStop(int audioRecord) throws IOException;
- private static native void AudioRecordDelete(int audioRecord) throws IOException;
-}
diff --git a/core/java/android/speech/srec/Recognizer.java b/core/java/android/speech/srec/Recognizer.java
deleted file mode 100644
index a03a36a..0000000
--- a/core/java/android/speech/srec/Recognizer.java
+++ /dev/null
@@ -1,719 +0,0 @@
-/*
- * ---------------------------------------------------------------------------
- * Recognizer.java
- *
- * Copyright 2007 Nuance Communciations, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the 'License'); you may not
- * use this file except in compliance with the License.
- *
- * You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- *
- * ---------------------------------------------------------------------------
- */
-
-
-package android.speech.srec;
-
-import android.util.Config;
-import android.util.Log;
-
-import java.io.File;
-import java.io.InputStream;
-import java.io.IOException;
-import java.util.Locale;
-
-/**
- * Simple, synchronous speech recognizer, using the Nuance SREC package.
- * Usages proceeds as follows:
- *
- * <ul>
- * <li>Create a <code>Recognizer</code>.
- * <li>Create a <code>Recognizer.Grammar</code>.
- * <li>Setup the <code>Recognizer.Grammar</code>.
- * <li>Reset the <code>Recognizer.Grammar</code> slots, if needed.
- * <li>Fill the <code>Recognizer.Grammar</code> slots, if needed.
- * <li>Compile the <code>Recognizer.Grammar</code>, if needed.
- * <li>Save the filled <code>Recognizer.Grammar</code>, if needed.
- * <li>Start the <code>Recognizer</code>.
- * <li>Loop over <code>advance</code> and <code>putAudio</code> until recognition complete.
- * <li>Fetch and process results, or notify of failure.
- * <li>Stop the <code>Recognizer</code>.
- * <li>Destroy the <code>Recognizer</code>.
- * </ul>
- *
- * <p>Below is example code</p>
- *
- * <pre class="prettyprint">
- *
- * // create and start audio input
- * InputStream audio = new MicrophoneInputStream(11025, 11025*5);
- * // create a Recognizer
- * String cdir = Recognizer.getConfigDir(null);
- * Recognizer recognizer = new Recognizer(cdir + "/baseline11k.par");
- * // create and load a Grammar
- * Recognizer.Grammar grammar = recognizer.new Grammar(cdir + "/grammars/VoiceDialer.g2g");
- * // setup the Grammar to work with the Recognizer
- * grammar.setupRecognizer();
- * // fill the Grammar slots with names and save, if required
- * grammar.resetAllSlots();
- * for (String name : names) grammar.addWordToSlot("@Names", name, null, 1, "V=1");
- * grammar.compile();
- * grammar.save(".../foo.g2g");
- * // start the Recognizer
- * recognizer.start();
- * // loop over Recognizer events
- * while (true) {
- * switch (recognizer.advance()) {
- * case Recognizer.EVENT_INCOMPLETE:
- * case Recognizer.EVENT_STARTED:
- * case Recognizer.EVENT_START_OF_VOICING:
- * case Recognizer.EVENT_END_OF_VOICING:
- * // let the Recognizer continue to run
- * continue;
- * case Recognizer.EVENT_RECOGNITION_RESULT:
- * // success, so fetch results here!
- * for (int i = 0; i < recognizer.getResultCount(); i++) {
- * String result = recognizer.getResult(i, Recognizer.KEY_LITERAL);
- * }
- * break;
- * case Recognizer.EVENT_NEED_MORE_AUDIO:
- * // put more audio in the Recognizer
- * recognizer.putAudio(audio);
- * continue;
- * default:
- * notifyFailure();
- * break;
- * }
- * break;
- * }
- * // stop the Recognizer
- * recognizer.stop();
- * // destroy the Recognizer
- * recognizer.destroy();
- * // stop the audio device
- * audio.close();
- *
- * </pre>
- */
-public final class Recognizer {
- static {
- System.loadLibrary("srec_jni");
- }
-
- private static String TAG = "Recognizer";
-
- /**
- * Result key corresponding to confidence score.
- */
- public static final String KEY_CONFIDENCE = "conf";
-
- /**
- * Result key corresponding to literal text.
- */
- public static final String KEY_LITERAL = "literal";
-
- /**
- * Result key corresponding to semantic meaning text.
- */
- public static final String KEY_MEANING = "meaning";
-
- // handle to SR_Vocabulary object
- private int mVocabulary = 0;
-
- // handle to SR_Recognizer object
- private int mRecognizer = 0;
-
- // Grammar currently associated with Recognizer via SR_GrammarSetupRecognizer
- private Grammar mActiveGrammar = null;
-
- /**
- * Get the pathname of the SREC configuration directory corresponding to the
- * language indicated by the Locale.
- * This directory contains dictionaries, speech models,
- * configuration files, and other data needed by the Recognizer.
- * @param locale <code>Locale</code> corresponding to the desired language,
- * or null for default, currently <code>Locale.US</code>.
- * @return Pathname of the configuration directory.
- */
- public static String getConfigDir(Locale locale) {
- if (locale == null) locale = Locale.US;
- String dir = "/system/usr/srec/config/" +
- locale.toString().replace('_', '.').toLowerCase();
- if ((new File(dir)).isDirectory()) return dir;
- return null;
- }
-
- /**
- * Create an instance of a SREC speech recognizer.
- *
- * @param configFile pathname of the baseline*.par configuration file,
- * which in turn contains references to dictionaries, speech models,
- * and other data needed to configure and operate the recognizer.
- * A separate config file is needed for each audio sample rate.
- * Two files, baseline11k.par and baseline8k.par, which correspond to
- * 11025 and 8000 hz, are present in the directory indicated by
- * {@link #getConfigDir}.
- * @throws IOException
- */
- public Recognizer(String configFile) throws IOException {
- PMemInit();
- SR_SessionCreate(configFile);
- mRecognizer = SR_RecognizerCreate();
- SR_RecognizerSetup(mRecognizer);
- mVocabulary = SR_VocabularyLoad();
- }
-
- /**
- * Represents a grammar loaded into the Recognizer.
- */
- public class Grammar {
- private int mGrammar = 0;
-
- /**
- * Create a <code>Grammar</code> instance.
- * @param g2gFileName pathname of g2g file.
- */
- public Grammar(String g2gFileName) throws IOException {
- mGrammar = SR_GrammarLoad(g2gFileName);
- SR_GrammarSetupVocabulary(mGrammar, mVocabulary);
- }
-
- /**
- * Reset all slots.
- */
- public void resetAllSlots() {
- SR_GrammarResetAllSlots(mGrammar);
- }
-
- /**
- * Add a word to a slot.
- *
- * @param slot slot name.
- * @param word word to insert.
- * @param pron pronunciation, or null to derive from word.
- * @param weight weight to give the word. One is normal, 50 is low.
- * @param tag semantic meaning tag string.
- */
- public void addWordToSlot(String slot, String word, String pron, int weight, String tag) {
- SR_GrammarAddWordToSlot(mGrammar, slot, word, pron, weight, tag);
- }
-
- /**
- * Compile all slots.
- */
- public void compile() {
- SR_GrammarCompile(mGrammar);
- }
-
- /**
- * Setup <code>Grammar</code> with <code>Recognizer</code>.
- */
- public void setupRecognizer() {
- SR_GrammarSetupRecognizer(mGrammar, mRecognizer);
- mActiveGrammar = this;
- }
-
- /**
- * Save <code>Grammar</code> to g2g file.
- *
- * @param g2gFileName
- * @throws IOException
- */
- public void save(String g2gFileName) throws IOException {
- SR_GrammarSave(mGrammar, g2gFileName);
- }
-
- /**
- * Release resources associated with this <code>Grammar</code>.
- */
- public void destroy() {
- // TODO: need to do cleanup and disassociation with Recognizer
- if (mGrammar != 0) {
- SR_GrammarDestroy(mGrammar);
- mGrammar = 0;
- }
- }
-
- /**
- * Clean up resources.
- */
- protected void finalize() {
- if (mGrammar != 0) {
- destroy();
- throw new IllegalStateException("someone forgot to destroy Grammar");
- }
- }
- }
-
- /**
- * Start recognition
- */
- public void start() {
- // TODO: shouldn't be here?
- SR_RecognizerActivateRule(mRecognizer, mActiveGrammar.mGrammar, "trash", 1);
- SR_RecognizerStart(mRecognizer);
- }
-
- /**
- * Process some audio and return the current status.
- * @return recognition event, one of:
- * <ul>
- * <li><code>EVENT_INVALID</code>
- * <li><code>EVENT_NO_MATCH</code>
- * <li><code>EVENT_INCOMPLETE</code>
- * <li><code>EVENT_STARTED</code>
- * <li><code>EVENT_STOPPED</code>
- * <li><code>EVENT_START_OF_VOICING</code>
- * <li><code>EVENT_END_OF_VOICING</code>
- * <li><code>EVENT_SPOKE_TOO_SOON</code>
- * <li><code>EVENT_RECOGNITION_RESULT</code>
- * <li><code>EVENT_START_OF_UTTERANCE_TIMEOUT</code>
- * <li><code>EVENT_RECOGNITION_TIMEOUT</code>
- * <li><code>EVENT_NEED_MORE_AUDIO</code>
- * <li><code>EVENT_MAX_SPEECH</code>
- * </ul>
- */
- public int advance() {
- return SR_RecognizerAdvance(mRecognizer);
- }
-
- /**
- * Put audio samples into the <code>Recognizer</code>.
- * @param buf holds the audio samples.
- * @param offset offset of the first sample.
- * @param length number of bytes containing samples.
- * @param isLast indicates no more audio data, normally false.
- * @return number of bytes accepted.
- */
- public int putAudio(byte[] buf, int offset, int length, boolean isLast) {
- return SR_RecognizerPutAudio(mRecognizer, buf, offset, length, isLast);
- }
-
- /**
- * Read audio samples from an <code>InputStream</code> and put them in the
- * <code>Recognizer</code>.
- * @param audio <code>InputStream</code> containing PCM audio samples.
- */
- public void putAudio(InputStream audio) throws IOException {
- // make sure the audio buffer is allocated
- if (mPutAudioBuffer == null) mPutAudioBuffer = new byte[512];
- // read some data
- int nbytes = audio.read(mPutAudioBuffer);
- // eof, so signal Recognizer
- if (nbytes == -1) {
- SR_RecognizerPutAudio(mRecognizer, mPutAudioBuffer, 0, 0, true);
- }
- // put it into the Recognizer
- else if (nbytes != SR_RecognizerPutAudio(mRecognizer, mPutAudioBuffer, 0, nbytes, false)) {
- throw new IOException("SR_RecognizerPutAudio failed nbytes=" + nbytes);
- }
- }
-
- // audio buffer for putAudio(InputStream)
- private byte[] mPutAudioBuffer = null;
-
- /**
- * Get the number of recognition results. Must be called after
- * <code>EVENT_RECOGNITION_RESULT</code> is returned by
- * <code>advance</code>, but before <code>stop</code>.
- *
- * @return number of results in nbest list.
- */
- public int getResultCount() {
- return SR_RecognizerResultGetSize(mRecognizer);
- }
-
- /**
- * Get a set of keys for the result. Must be called after
- * <code>EVENT_RECOGNITION_RESULT</code> is returned by
- * <code>advance</code>, but before <code>stop</code>.
- *
- * @param index index of result.
- * @return array of keys.
- */
- public String[] getResultKeys(int index) {
- return SR_RecognizerResultGetKeyList(mRecognizer, index);
- }
-
- /**
- * Get a result value. Must be called after
- * <code>EVENT_RECOGNITION_RESULT</code> is returned by
- * <code>advance</code>, but before <code>stop</code>.
- *
- * @param index index of the result.
- * @param key key of the result. This is typically one of
- * <code>KEY_CONFIDENCE</code>, <code>KEY_LITERAL</code>, or
- * <code>KEY_MEANING</code>, but the user can also define their own keys
- * in a grxml file, or in the <code>tag</code> slot of
- * <code>Grammar.addWordToSlot</code>.
- * @return the result.
- */
- public String getResult(int index, String key) {
- return SR_RecognizerResultGetValue(mRecognizer, index, key);
- }
-
- /**
- * Stop the <code>Recognizer</code>.
- */
- public void stop() {
- SR_RecognizerStop(mRecognizer);
- SR_RecognizerDeactivateRule(mRecognizer, mActiveGrammar.mGrammar, "trash");
- }
-
- /**
- * Reset the acoustic state vectorto it's default value.
- *
- * @hide
- */
- public void resetAcousticState() {
- SR_AcousticStateReset(mRecognizer);
- }
-
- /**
- * Set the acoustic state vector.
- * @param state String containing the acoustic state vector.
- *
- * @hide
- */
- public void setAcousticState(String state) {
- SR_AcousticStateSet(mRecognizer, state);
- }
-
- /**
- * Get the acoustic state vector.
- * @return String containing the acoustic state vector.
- *
- * @hide
- */
- public String getAcousticState() {
- return SR_AcousticStateGet(mRecognizer);
- }
-
- /**
- * Clean up resources.
- */
- public void destroy() {
- try {
- if (mVocabulary != 0) SR_VocabularyDestroy(mVocabulary);
- } finally {
- mVocabulary = 0;
- try {
- if (mRecognizer != 0) SR_RecognizerUnsetup(mRecognizer);
- } finally {
- try {
- if (mRecognizer != 0) SR_RecognizerDestroy(mRecognizer);
- } finally {
- mRecognizer = 0;
- try {
- SR_SessionDestroy();
- } finally {
- PMemShutdown();
- }
- }
- }
- }
- }
-
- /**
- * Clean up resources.
- */
- protected void finalize() throws Throwable {
- if (mVocabulary != 0 || mRecognizer != 0) {
- destroy();
- throw new IllegalStateException("someone forgot to destroy Recognizer");
- }
- }
-
- /* an example session captured, for reference
- void doall() {
- if (PMemInit ( )
- || lhs_audioinOpen ( WAVE_MAPPER, SREC_TEST_DEFAULT_AUDIO_FREQUENCY, &audio_in_handle )
- || srec_test_init_application_data ( &applicationData, argc, argv )
- || SR_SessionCreate ( "/system/usr/srec/config/en.us/baseline11k.par" )
- || SR_RecognizerCreate ( &applicationData.recognizer )
- || SR_RecognizerSetup ( applicationData.recognizer)
- || ESR_SessionGetLCHAR ( L("cmdline.vocabulary"), filename, &flen )
- || SR_VocabularyLoad ( filename, &applicationData.vocabulary )
- || SR_VocabularyGetLanguage ( applicationData.vocabulary, &applicationData.locale )
- || (applicationData.nametag = NULL)
- || SR_NametagsCreate ( &applicationData.nametags )
- || (LSTRCPY ( applicationData.grammars [0].grammar_path, "/system/usr/srec/config/en.us/grammars/VoiceDialer.g2g" ), 0)
- || (LSTRCPY ( applicationData.grammars [0].grammarID, "BothTags" ), 0)
- || (LSTRCPY ( applicationData.grammars [0].ruleName, "trash" ), 0)
- || (applicationData.grammars [0].is_ve_grammar = ESR_FALSE, 0)
- || SR_GrammarLoad (applicationData.grammars [0].grammar_path, &applicationData.grammars [applicationData.grammarCount].grammar )
- || SR_GrammarSetupVocabulary ( applicationData.grammars [0].grammar, applicationData.vocabulary )
- || SR_GrammarSetupRecognizer( applicationData.grammars [0].grammar, applicationData.recognizer )
- || SR_GrammarSetDispatchFunction ( applicationData.grammars [0].grammar, L("myDSMCallback"), NULL, myDSMCallback )
- || (applicationData.grammarCount++, 0)
- || SR_RecognizerActivateRule ( applicationData.recognizer, applicationData.grammars [0].grammar,
- applicationData.grammars [0].ruleName, 1 )
- || (applicationData.active_grammar_num = 0, 0)
- || lhs_audioinStart ( audio_in_handle )
- || SR_RecognizerStart ( applicationData.recognizer )
- || strl ( applicationData.grammars [0].grammar, &applicationData, audio_in_handle, &recognition_count )
- || SR_RecognizerStop ( applicationData.recognizer )
- || lhs_audioinStop ( audio_in_handle )
- || SR_RecognizerDeactivateRule ( applicationData.recognizer, applicationData.grammars [0].grammar, applicationData.grammars [0].ruleName )
- || (applicationData.active_grammar_num = -1, 0)
- || SR_GrammarDestroy ( applicationData.grammars [0].grammar )
- || (applicationData.grammarCount--, 0)
- || SR_NametagsDestroy ( applicationData.nametags )
- || (applicationData.nametags = NULL, 0)
- || SR_VocabularyDestroy ( applicationData.vocabulary )
- || (applicationData.vocabulary = NULL)
- || SR_RecognizerUnsetup ( applicationData.recognizer) // releases acoustic models
- || SR_RecognizerDestroy ( applicationData.recognizer )
- || (applicationData.recognizer = NULL)
- || SR_SessionDestroy ( )
- || srec_test_shutdown_application_data ( &applicationData )
- || lhs_audioinClose ( &audio_in_handle )
- || PMemShutdown ( )
- }
- */
-
-
- //
- // PMem native methods
- //
- private static native void PMemInit();
- private static native void PMemShutdown();
-
-
- //
- // SR_Session native methods
- //
- private static native void SR_SessionCreate(String filename);
- private static native void SR_SessionDestroy();
-
-
- //
- // SR_Recognizer native methods
- //
-
- /**
- * Reserved value.
- */
- public final static int EVENT_INVALID = 0;
-
- /**
- * <code>Recognizer</code> could not find a match for the utterance.
- */
- public final static int EVENT_NO_MATCH = 1;
-
- /**
- * <code>Recognizer</code> processed one frame of audio.
- */
- public final static int EVENT_INCOMPLETE = 2;
-
- /**
- * <code>Recognizer</code> has just been started.
- */
- public final static int EVENT_STARTED = 3;
-
- /**
- * <code>Recognizer</code> is stopped.
- */
- public final static int EVENT_STOPPED = 4;
-
- /**
- * Beginning of speech detected.
- */
- public final static int EVENT_START_OF_VOICING = 5;
-
- /**
- * End of speech detected.
- */
- public final static int EVENT_END_OF_VOICING = 6;
-
- /**
- * Beginning of utterance occured too soon.
- */
- public final static int EVENT_SPOKE_TOO_SOON = 7;
-
- /**
- * Recognition match detected.
- */
- public final static int EVENT_RECOGNITION_RESULT = 8;
-
- /**
- * Timeout occured before beginning of utterance.
- */
- public final static int EVENT_START_OF_UTTERANCE_TIMEOUT = 9;
-
- /**
- * Timeout occured before speech recognition could complete.
- */
- public final static int EVENT_RECOGNITION_TIMEOUT = 10;
-
- /**
- * Not enough samples to process one frame.
- */
- public final static int EVENT_NEED_MORE_AUDIO = 11;
-
- /**
- * More audio encountered than is allowed by 'swirec_max_speech_duration'.
- */
- public final static int EVENT_MAX_SPEECH = 12;
-
- /**
- * Produce a displayable string from an <code>advance</code> event.
- * @param event
- * @return String representing the event.
- */
- public static String eventToString(int event) {
- switch (event) {
- case EVENT_INVALID:
- return "EVENT_INVALID";
- case EVENT_NO_MATCH:
- return "EVENT_NO_MATCH";
- case EVENT_INCOMPLETE:
- return "EVENT_INCOMPLETE";
- case EVENT_STARTED:
- return "EVENT_STARTED";
- case EVENT_STOPPED:
- return "EVENT_STOPPED";
- case EVENT_START_OF_VOICING:
- return "EVENT_START_OF_VOICING";
- case EVENT_END_OF_VOICING:
- return "EVENT_END_OF_VOICING";
- case EVENT_SPOKE_TOO_SOON:
- return "EVENT_SPOKE_TOO_SOON";
- case EVENT_RECOGNITION_RESULT:
- return "EVENT_RECOGNITION_RESULT";
- case EVENT_START_OF_UTTERANCE_TIMEOUT:
- return "EVENT_START_OF_UTTERANCE_TIMEOUT";
- case EVENT_RECOGNITION_TIMEOUT:
- return "EVENT_RECOGNITION_TIMEOUT";
- case EVENT_NEED_MORE_AUDIO:
- return "EVENT_NEED_MORE_AUDIO";
- case EVENT_MAX_SPEECH:
- return "EVENT_MAX_SPEECH";
- }
- return "EVENT_" + event;
- }
-
- //
- // SR_Recognizer methods
- //
- private static native void SR_RecognizerStart(int recognizer);
- private static native void SR_RecognizerStop(int recognizer);
- private static native int SR_RecognizerCreate();
- private static native void SR_RecognizerDestroy(int recognizer);
- private static native void SR_RecognizerSetup(int recognizer);
- private static native void SR_RecognizerUnsetup(int recognizer);
- private static native boolean SR_RecognizerIsSetup(int recognizer);
- private static native String SR_RecognizerGetParameter(int recognizer, String key);
- private static native int SR_RecognizerGetSize_tParameter(int recognizer, String key);
- private static native boolean SR_RecognizerGetBoolParameter(int recognizer, String key);
- private static native void SR_RecognizerSetParameter(int recognizer, String key, String value);
- private static native void SR_RecognizerSetSize_tParameter(int recognizer,
- String key, int value);
- private static native void SR_RecognizerSetBoolParameter(int recognizer, String key,
- boolean value);
- private static native void SR_RecognizerSetupRule(int recognizer, int grammar,
- String ruleName);
- private static native boolean SR_RecognizerHasSetupRules(int recognizer);
- private static native void SR_RecognizerActivateRule(int recognizer, int grammar,
- String ruleName, int weight);
- private static native void SR_RecognizerDeactivateRule(int recognizer, int grammar,
- String ruleName);
- private static native void SR_RecognizerDeactivateAllRules(int recognizer);
- private static native boolean SR_RecognizerIsActiveRule(int recognizer, int grammar,
- String ruleName);
- private static native boolean SR_RecognizerCheckGrammarConsistency(int recognizer,
- int grammar);
- private static native int SR_RecognizerPutAudio(int recognizer, byte[] buffer, int offset,
- int length, boolean isLast);
- private static native int SR_RecognizerAdvance(int recognizer);
- // private static native void SR_RecognizerLoadUtterance(int recognizer,
- // const LCHAR* filename);
- // private static native void SR_RecognizerLoadWaveFile(int recognizer,
- // const LCHAR* filename);
- // private static native void SR_RecognizerSetLockFunction(int recognizer,
- // SR_RecognizerLockFunction function, void* data);
- private static native boolean SR_RecognizerIsSignalClipping(int recognizer);
- private static native boolean SR_RecognizerIsSignalDCOffset(int recognizer);
- private static native boolean SR_RecognizerIsSignalNoisy(int recognizer);
- private static native boolean SR_RecognizerIsSignalTooQuiet(int recognizer);
- private static native boolean SR_RecognizerIsSignalTooFewSamples(int recognizer);
- private static native boolean SR_RecognizerIsSignalTooManySamples(int recognizer);
- // private static native void SR_Recognizer_Change_Sample_Rate (size_t new_sample_rate);
-
-
- //
- // SR_AcousticState native methods
- //
- private static native void SR_AcousticStateReset(int recognizer);
- private static native void SR_AcousticStateSet(int recognizer, String state);
- private static native String SR_AcousticStateGet(int recognizer);
-
-
- //
- // SR_Grammar native methods
- //
- private static native void SR_GrammarCompile(int grammar);
- private static native void SR_GrammarAddWordToSlot(int grammar, String slot,
- String word, String pronunciation, int weight, String tag);
- private static native void SR_GrammarResetAllSlots(int grammar);
- // private static native void SR_GrammarAddNametagToSlot(int grammar, String slot,
- // const struct SR_Nametag_t* nametag, int weight, String tag);
- private static native void SR_GrammarSetupVocabulary(int grammar, int vocabulary);
- // private static native void SR_GrammarSetupModels(int grammar, SR_AcousticModels* models);
- private static native void SR_GrammarSetupRecognizer(int grammar, int recognizer);
- private static native void SR_GrammarUnsetupRecognizer(int grammar);
- // private static native void SR_GrammarGetModels(int grammar,SR_AcousticModels** models);
- private static native int SR_GrammarCreate();
- private static native void SR_GrammarDestroy(int grammar);
- private static native int SR_GrammarLoad(String filename);
- private static native void SR_GrammarSave(int grammar, String filename);
- // private static native void SR_GrammarSetDispatchFunction(int grammar,
- // const LCHAR* name, void* userData, SR_GrammarDispatchFunction function);
- // private static native void SR_GrammarSetParameter(int grammar, const
- // LCHAR* key, void* value);
- // private static native void SR_GrammarSetSize_tParameter(int grammar,
- // const LCHAR* key, size_t value);
- // private static native void SR_GrammarGetParameter(int grammar, const
- // LCHAR* key, void** value);
- // private static native void SR_GrammarGetSize_tParameter(int grammar,
- // const LCHAR* key, size_t* value);
- // private static native void SR_GrammarCheckParse(int grammar, const LCHAR*
- // transcription, SR_SemanticResult** result, size_t* resultCount);
- private static native void SR_GrammarAllowOnly(int grammar, String transcription);
- private static native void SR_GrammarAllowAll(int grammar);
-
-
- //
- // SR_Vocabulary native methods
- //
- // private static native int SR_VocabularyCreate();
- private static native int SR_VocabularyLoad();
- // private static native void SR_VocabularySave(SR_Vocabulary* self,
- // const LCHAR* filename);
- // private static native void SR_VocabularyAddWord(SR_Vocabulary* self,
- // const LCHAR* word);
- // private static native void SR_VocabularyGetLanguage(SR_Vocabulary* self,
- // ESR_Locale* locale);
- private static native void SR_VocabularyDestroy(int vocabulary);
- private static native String SR_VocabularyGetPronunciation(int vocabulary, String word);
-
-
- //
- // SR_RecognizerResult native methods
- //
- private static native byte[] SR_RecognizerResultGetWaveform(int recognizer);
- private static native int SR_RecognizerResultGetSize(int recognizer);
- private static native int SR_RecognizerResultGetKeyCount(int recognizer, int nbest);
- private static native String[] SR_RecognizerResultGetKeyList(int recognizer, int nbest);
- private static native String SR_RecognizerResultGetValue(int recognizer,
- int nbest, String key);
- // private static native void SR_RecognizerResultGetLocale(int recognizer, ESR_Locale* locale);
-}
diff --git a/core/java/android/speech/srec/UlawEncoderInputStream.java b/core/java/android/speech/srec/UlawEncoderInputStream.java
deleted file mode 100644
index 132fe027..0000000
--- a/core/java/android/speech/srec/UlawEncoderInputStream.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * ---------------------------------------------------------------------------
- * UlawEncoderInputStream.java
- *
- * Copyright 2008 Nuance Communciations, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the 'License'); you may not
- * use this file except in compliance with the License.
- *
- * You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- *
- * ---------------------------------------------------------------------------
- */
-
-package android.speech.srec;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * InputStream which transforms 16 bit pcm data to ulaw data.
- *
- * @hide pending API council approval
- */
-public final class UlawEncoderInputStream extends InputStream {
- private final static String TAG = "UlawEncoderInputStream";
-
- private final static int MAX_ULAW = 8192;
- private final static int SCALE_BITS = 16;
-
- private InputStream mIn;
-
- private int mMax = 0;
-
- private final byte[] mBuf = new byte[1024];
- private int mBufCount = 0; // should be 0 or 1
-
- private final byte[] mOneByte = new byte[1];
-
-
- public static void encode(byte[] pcmBuf, int pcmOffset,
- byte[] ulawBuf, int ulawOffset, int length, int max) {
-
- // from 'ulaw' in wikipedia
- // +8191 to +8159 0x80
- // +8158 to +4063 in 16 intervals of 256 0x80 + interval number
- // +4062 to +2015 in 16 intervals of 128 0x90 + interval number
- // +2014 to +991 in 16 intervals of 64 0xA0 + interval number
- // +990 to +479 in 16 intervals of 32 0xB0 + interval number
- // +478 to +223 in 16 intervals of 16 0xC0 + interval number
- // +222 to +95 in 16 intervals of 8 0xD0 + interval number
- // +94 to +31 in 16 intervals of 4 0xE0 + interval number
- // +30 to +1 in 15 intervals of 2 0xF0 + interval number
- // 0 0xFF
-
- // -1 0x7F
- // -31 to -2 in 15 intervals of 2 0x70 + interval number
- // -95 to -32 in 16 intervals of 4 0x60 + interval number
- // -223 to -96 in 16 intervals of 8 0x50 + interval number
- // -479 to -224 in 16 intervals of 16 0x40 + interval number
- // -991 to -480 in 16 intervals of 32 0x30 + interval number
- // -2015 to -992 in 16 intervals of 64 0x20 + interval number
- // -4063 to -2016 in 16 intervals of 128 0x10 + interval number
- // -8159 to -4064 in 16 intervals of 256 0x00 + interval number
- // -8192 to -8160 0x00
-
- // set scale factors
- if (max <= 0) max = MAX_ULAW;
-
- int coef = MAX_ULAW * (1 << SCALE_BITS) / max;
-
- for (int i = 0; i < length; i++) {
- int pcm = (0xff & pcmBuf[pcmOffset++]) + (pcmBuf[pcmOffset++] << 8);
- pcm = (pcm * coef) >> SCALE_BITS;
-
- int ulaw;
- if (pcm >= 0) {
- ulaw = pcm <= 0 ? 0xff :
- pcm <= 30 ? 0xf0 + (( 30 - pcm) >> 1) :
- pcm <= 94 ? 0xe0 + (( 94 - pcm) >> 2) :
- pcm <= 222 ? 0xd0 + (( 222 - pcm) >> 3) :
- pcm <= 478 ? 0xc0 + (( 478 - pcm) >> 4) :
- pcm <= 990 ? 0xb0 + (( 990 - pcm) >> 5) :
- pcm <= 2014 ? 0xa0 + ((2014 - pcm) >> 6) :
- pcm <= 4062 ? 0x90 + ((4062 - pcm) >> 7) :
- pcm <= 8158 ? 0x80 + ((8158 - pcm) >> 8) :
- 0x80;
- } else {
- ulaw = -1 <= pcm ? 0x7f :
- -31 <= pcm ? 0x70 + ((pcm - -31) >> 1) :
- -95 <= pcm ? 0x60 + ((pcm - -95) >> 2) :
- -223 <= pcm ? 0x50 + ((pcm - -223) >> 3) :
- -479 <= pcm ? 0x40 + ((pcm - -479) >> 4) :
- -991 <= pcm ? 0x30 + ((pcm - -991) >> 5) :
- -2015 <= pcm ? 0x20 + ((pcm - -2015) >> 6) :
- -4063 <= pcm ? 0x10 + ((pcm - -4063) >> 7) :
- -8159 <= pcm ? 0x00 + ((pcm - -8159) >> 8) :
- 0x00;
- }
- ulawBuf[ulawOffset++] = (byte)ulaw;
- }
- }
-
- /**
- * Compute the maximum of the absolute value of the pcm samples.
- * The return value can be used to set ulaw encoder scaling.
- * @param pcmBuf array containing 16 bit pcm data.
- * @param offset offset of start of 16 bit pcm data.
- * @param length number of pcm samples (not number of input bytes)
- * @return maximum abs of pcm data values
- */
- public static int maxAbsPcm(byte[] pcmBuf, int offset, int length) {
- int max = 0;
- for (int i = 0; i < length; i++) {
- int pcm = (0xff & pcmBuf[offset++]) + (pcmBuf[offset++] << 8);
- if (pcm < 0) pcm = -pcm;
- if (pcm > max) max = pcm;
- }
- return max;
- }
-
- /**
- * Create an InputStream which takes 16 bit pcm data and produces ulaw data.
- * @param in InputStream containing 16 bit pcm data.
- * @param max pcm value corresponding to maximum ulaw value.
- */
- public UlawEncoderInputStream(InputStream in, int max) {
- mIn = in;
- mMax = max;
- }
-
- @Override
- public int read(byte[] buf, int offset, int length) throws IOException {
- if (mIn == null) throw new IllegalStateException("not open");
-
- // return at least one byte, but try to fill 'length'
- while (mBufCount < 2) {
- int n = mIn.read(mBuf, mBufCount, Math.min(length * 2, mBuf.length - mBufCount));
- if (n == -1) return -1;
- mBufCount += n;
- }
-
- // compand data
- int n = Math.min(mBufCount / 2, length);
- encode(mBuf, 0, buf, offset, n, mMax);
-
- // move data to bottom of mBuf
- mBufCount -= n * 2;
- for (int i = 0; i < mBufCount; i++) mBuf[i] = mBuf[i + n * 2];
-
- return n;
- }
-
- @Override
- public int read(byte[] buf) throws IOException {
- return read(buf, 0, buf.length);
- }
-
- @Override
- public int read() throws IOException {
- int n = read(mOneByte, 0, 1);
- if (n == -1) return -1;
- return 0xff & (int)mOneByte[0];
- }
-
- @Override
- public void close() throws IOException {
- if (mIn != null) {
- InputStream in = mIn;
- mIn = null;
- in.close();
- }
- }
-
- @Override
- public int available() throws IOException {
- return (mIn.available() + mBufCount) / 2;
- }
-}
diff --git a/core/java/android/speech/srec/WaveHeader.java b/core/java/android/speech/srec/WaveHeader.java
deleted file mode 100644
index a99496d..0000000
--- a/core/java/android/speech/srec/WaveHeader.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.speech.srec;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * This class represents the header of a WAVE format audio file, which usually
- * have a .wav suffix. The following integer valued fields are contained:
- * <ul>
- * <li> format - usually PCM, ALAW or ULAW.
- * <li> numChannels - 1 for mono, 2 for stereo.
- * <li> sampleRate - usually 8000, 11025, 16000, 22050, or 44100 hz.
- * <li> bitsPerSample - usually 16 for PCM, 8 for ALAW, or 8 for ULAW.
- * <li> numBytes - size of audio data after this header, in bytes.
- * </ul>
- * @hide pending API council approval
- */
-public class WaveHeader {
-
- // follows WAVE format in http://ccrma.stanford.edu/courses/422/projects/WaveFormat
-
- private static final String TAG = "WaveHeader";
-
- private static final int HEADER_LENGTH = 44;
-
- /** Indicates PCM format. */
- public static final short FORMAT_PCM = 1;
- /** Indicates ALAW format. */
- public static final short FORMAT_ALAW = 6;
- /** Indicates ULAW format. */
- public static final short FORMAT_ULAW = 7;
-
- private short mFormat;
- private short mNumChannels;
- private int mSampleRate;
- private short mBitsPerSample;
- private int mNumBytes;
-
- /**
- * Construct a WaveHeader, with all fields defaulting to zero.
- */
- public WaveHeader() {
- }
-
- /**
- * Construct a WaveHeader, with fields initialized.
- * @param format format of audio data,
- * one of {@link #FORMAT_PCM}, {@link #FORMAT_ULAW}, or {@link #FORMAT_ALAW}.
- * @param numChannels 1 for mono, 2 for stereo.
- * @param sampleRate typically 8000, 11025, 16000, 22050, or 44100 hz.
- * @param bitsPerSample usually 16 for PCM, 8 for ULAW or 8 for ALAW.
- * @param numBytes size of audio data after this header, in bytes.
- */
- public WaveHeader(short format, short numChannels, int sampleRate, short bitsPerSample, int numBytes) {
- mFormat = format;
- mSampleRate = sampleRate;
- mNumChannels = numChannels;
- mBitsPerSample = bitsPerSample;
- mNumBytes = numBytes;
- }
-
- /**
- * Get the format field.
- * @return format field,
- * one of {@link #FORMAT_PCM}, {@link #FORMAT_ULAW}, or {@link #FORMAT_ALAW}.
- */
- public short getFormat() {
- return mFormat;
- }
-
- /**
- * Set the format field.
- * @param format
- * one of {@link #FORMAT_PCM}, {@link #FORMAT_ULAW}, or {@link #FORMAT_ALAW}.
- * @return reference to this WaveHeader instance.
- */
- public WaveHeader setFormat(short format) {
- mFormat = format;
- return this;
- }
-
- /**
- * Get the number of channels.
- * @return number of channels, 1 for mono, 2 for stereo.
- */
- public short getNumChannels() {
- return mNumChannels;
- }
-
- /**
- * Set the number of channels.
- * @param numChannels 1 for mono, 2 for stereo.
- * @return reference to this WaveHeader instance.
- */
- public WaveHeader setNumChannels(short numChannels) {
- mNumChannels = numChannels;
- return this;
- }
-
- /**
- * Get the sample rate.
- * @return sample rate, typically 8000, 11025, 16000, 22050, or 44100 hz.
- */
- public int getSampleRate() {
- return mSampleRate;
- }
-
- /**
- * Set the sample rate.
- * @param sampleRate sample rate, typically 8000, 11025, 16000, 22050, or 44100 hz.
- * @return reference to this WaveHeader instance.
- */
- public WaveHeader setSampleRate(int sampleRate) {
- mSampleRate = sampleRate;
- return this;
- }
-
- /**
- * Get the number of bits per sample.
- * @return number of bits per sample,
- * usually 16 for PCM, 8 for ULAW or 8 for ALAW.
- */
- public short getBitsPerSample() {
- return mBitsPerSample;
- }
-
- /**
- * Set the number of bits per sample.
- * @param bitsPerSample number of bits per sample,
- * usually 16 for PCM, 8 for ULAW or 8 for ALAW.
- * @return reference to this WaveHeader instance.
- */
- public WaveHeader setBitsPerSample(short bitsPerSample) {
- mBitsPerSample = bitsPerSample;
- return this;
- }
-
- /**
- * Get the size of audio data after this header, in bytes.
- * @return size of audio data after this header, in bytes.
- */
- public int getNumBytes() {
- return mNumBytes;
- }
-
- /**
- * Set the size of audio data after this header, in bytes.
- * @param numBytes size of audio data after this header, in bytes.
- * @return reference to this WaveHeader instance.
- */
- public WaveHeader setNumBytes(int numBytes) {
- mNumBytes = numBytes;
- return this;
- }
-
- /**
- * Read and initialize a WaveHeader.
- * @param in {@link java.io.InputStream} to read from.
- * @return number of bytes consumed.
- * @throws IOException
- */
- public int read(InputStream in) throws IOException {
- /* RIFF header */
- readId(in, "RIFF");
- int numBytes = readInt(in) - 36;
- readId(in, "WAVE");
-
- /* fmt chunk */
- readId(in, "fmt ");
- if (16 != readInt(in)) throw new IOException("fmt chunk length not 16");
- mFormat = readShort(in);
- mNumChannels = readShort(in);
- mSampleRate = readInt(in);
- int byteRate = readInt(in);
- short blockAlign = readShort(in);
- mBitsPerSample = readShort(in);
- if (byteRate != mNumChannels * mSampleRate * mBitsPerSample / 8) {
- throw new IOException("fmt.ByteRate field inconsistent");
- }
- if (blockAlign != mNumChannels * mBitsPerSample / 8) {
- throw new IOException("fmt.BlockAlign field inconsistent");
- }
-
- /* data chunk */
- readId(in, "data");
- mNumBytes = readInt(in);
-
- return HEADER_LENGTH;
- }
-
- private static void readId(InputStream in, String id) throws IOException {
- for (int i = 0; i < id.length(); i++) {
- if (id.charAt(i) != in.read()) throw new IOException( id + " tag not present");
- }
- }
-
- private static int readInt(InputStream in) throws IOException {
- return in.read() | (in.read() << 8) | (in.read() << 16) | (in.read() << 24);
- }
-
- private static short readShort(InputStream in) throws IOException {
- return (short)(in.read() | (in.read() << 8));
- }
-
- /**
- * Write a WAVE file header.
- * @param out {@link java.io.OutputStream} to receive the header.
- * @return number of bytes written.
- * @throws IOException
- */
- public int write(OutputStream out) throws IOException {
- /* RIFF header */
- writeId(out, "RIFF");
- writeInt(out, 36 + mNumBytes);
- writeId(out, "WAVE");
-
- /* fmt chunk */
- writeId(out, "fmt ");
- writeInt(out, 16);
- writeShort(out, mFormat);
- writeShort(out, mNumChannels);
- writeInt(out, mSampleRate);
- writeInt(out, mNumChannels * mSampleRate * mBitsPerSample / 8);
- writeShort(out, (short)(mNumChannels * mBitsPerSample / 8));
- writeShort(out, mBitsPerSample);
-
- /* data chunk */
- writeId(out, "data");
- writeInt(out, mNumBytes);
-
- return HEADER_LENGTH;
- }
-
- private static void writeId(OutputStream out, String id) throws IOException {
- for (int i = 0; i < id.length(); i++) out.write(id.charAt(i));
- }
-
- private static void writeInt(OutputStream out, int val) throws IOException {
- out.write(val >> 0);
- out.write(val >> 8);
- out.write(val >> 16);
- out.write(val >> 24);
- }
-
- private static void writeShort(OutputStream out, short val) throws IOException {
- out.write(val >> 0);
- out.write(val >> 8);
- }
-
- @Override
- public String toString() {
- return String.format(
- "WaveHeader format=%d numChannels=%d sampleRate=%d bitsPerSample=%d numBytes=%d",
- mFormat, mNumChannels, mSampleRate, mBitsPerSample, mNumBytes);
- }
-
-}
diff --git a/core/java/android/speech/srec/package.html b/core/java/android/speech/srec/package.html
deleted file mode 100644
index 723b30b..0000000
--- a/core/java/android/speech/srec/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<HTML>
-<BODY>
-Simple, synchronous SREC speech recognition API.
-</BODY>
-</HTML>
diff --git a/core/java/android/syncml/package.html b/core/java/android/syncml/package.html
deleted file mode 100644
index cb4ca46..0000000
--- a/core/java/android/syncml/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<HTML>
-<BODY>
-Support classes for SyncML.
-{@hide}
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/core/java/android/syncml/pim/PropertyNode.java b/core/java/android/syncml/pim/PropertyNode.java
deleted file mode 100644
index 13d4930..0000000
--- a/core/java/android/syncml/pim/PropertyNode.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-import android.content.ContentValues;
-
-public class PropertyNode {
-
- public String propName;
-
- public String propValue = "";
-
- public Collection<String> propValue_vector;
-
- /** Store value as byte[],after decode. */
- public byte[] propValue_byts;
-
- /** param store: key=paramType, value=paramValue */
- public ContentValues paraMap = new ContentValues();
-
- /** Only for TYPE=??? param store. */
- public ArrayList<String> paraMap_TYPE = new ArrayList<String>();
-}
diff --git a/core/java/android/syncml/pim/VBuilder.java b/core/java/android/syncml/pim/VBuilder.java
deleted file mode 100644
index 822c2ce..0000000
--- a/core/java/android/syncml/pim/VBuilder.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim;
-
-import java.util.Collection;
-
-public interface VBuilder {
- void start();
-
- void end();
-
- /**
- * @param type
- * VXX <br>
- * BEGIN:VXX
- */
- void startRecord(String type);
-
- /** END:VXX */
- void endRecord();
-
- void startProperty();
-
- void endProperty();
-
- /**
- * @param name
- * a.N <br>
- * a.N
- */
- void propertyName(String name);
-
- /**
- * @param type
- * LANGUAGE \ ENCODING <br>
- * ;LANGUage= \ ;ENCODING=
- */
- void propertyParamType(String type);
-
- /**
- * @param value
- * FR-EN \ GBK <br>
- * FR-EN \ GBK
- */
- void propertyParamValue(String value);
-
- void propertyValues(Collection<String> values);
-}
diff --git a/core/java/android/syncml/pim/VDataBuilder.java b/core/java/android/syncml/pim/VDataBuilder.java
deleted file mode 100644
index f0a0cb9..0000000
--- a/core/java/android/syncml/pim/VDataBuilder.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.codec.net.QuotedPrintableCodec;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-/**
- * Store the parse result to custom datastruct: VNode, PropertyNode
- * Maybe several vcard instance, so use vNodeList to store.
- * VNode: standy by a vcard instance.
- * PropertyNode: standy by a property line of a card.
- */
-public class VDataBuilder implements VBuilder {
-
- /** type=VNode */
- public ArrayList<VNode> vNodeList = new ArrayList<VNode>();
- int nodeListPos = 0;
- VNode curVNode;
- PropertyNode curPropNode;
- String curParamType;
-
- public void start() {
- }
-
- public void end() {
- }
-
- public void startRecord(String type) {
- VNode vnode = new VNode();
- vnode.parseStatus = 1;
- vnode.VName = type;
- vNodeList.add(vnode);
- nodeListPos = vNodeList.size()-1;
- curVNode = vNodeList.get(nodeListPos);
- }
-
- public void endRecord() {
- VNode endNode = vNodeList.get(nodeListPos);
- endNode.parseStatus = 0;
- while(nodeListPos > 0){
- nodeListPos--;
- if((vNodeList.get(nodeListPos)).parseStatus == 1)
- break;
- }
- curVNode = vNodeList.get(nodeListPos);
- }
-
- public void startProperty() {
- // System.out.println("+ startProperty. ");
- }
-
- public void endProperty() {
- // System.out.println("- endProperty. ");
- }
-
- public void propertyName(String name) {
- curPropNode = new PropertyNode();
- curPropNode.propName = name;
- }
-
- public void propertyParamType(String type) {
- curParamType = type;
- }
-
- public void propertyParamValue(String value) {
- if(curParamType == null)
- curPropNode.paraMap_TYPE.add(value);
- else if(curParamType.equalsIgnoreCase("TYPE"))
- curPropNode.paraMap_TYPE.add(value);
- else
- curPropNode.paraMap.put(curParamType, value);
-
- curParamType = null;
- }
-
- public void propertyValues(Collection<String> values) {
- curPropNode.propValue_vector = values;
- curPropNode.propValue = listToString(values);
- //decode value string to propValue_byts
- if(curPropNode.paraMap.containsKey("ENCODING")){
- if(curPropNode.paraMap.getAsString("ENCODING").
- equalsIgnoreCase("BASE64")){
- curPropNode.propValue_byts =
- Base64.decodeBase64(curPropNode.propValue.
- replaceAll(" ","").replaceAll("\t","").
- replaceAll("\r\n","").
- getBytes());
- }
- if(curPropNode.paraMap.getAsString("ENCODING").
- equalsIgnoreCase("QUOTED-PRINTABLE")){
- try{
- curPropNode.propValue_byts =
- QuotedPrintableCodec.decodeQuotedPrintable(
- curPropNode.propValue.
- replaceAll("= ", " ").replaceAll("=\t", "\t").
- getBytes() );
- curPropNode.propValue =
- new String(curPropNode.propValue_byts);
- }catch(Exception e){
- System.out.println("=Decode quoted-printable exception.");
- e.printStackTrace();
- }
- }
- }
- curVNode.propList.add(curPropNode);
- }
-
- private String listToString(Collection<String> list){
- StringBuilder typeListB = new StringBuilder();
- for (String type : list) {
- typeListB.append(type).append(";");
- }
- int len = typeListB.length();
- if (len > 0 && typeListB.charAt(len - 1) == ';') {
- return typeListB.substring(0, len - 1);
- }
- return typeListB.toString();
- }
-
- public String getResult(){
- return null;
- }
-}
-
diff --git a/core/java/android/syncml/pim/VNode.java b/core/java/android/syncml/pim/VNode.java
deleted file mode 100644
index 9015415..0000000
--- a/core/java/android/syncml/pim/VNode.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim;
-
-import java.util.ArrayList;
-
-public class VNode {
-
- public String VName;
-
- public ArrayList<PropertyNode> propList = new ArrayList<PropertyNode>();
-
- /** 0:parse over. 1:parsing. */
- public int parseStatus = 1;
-}
diff --git a/core/java/android/syncml/pim/VParser.java b/core/java/android/syncml/pim/VParser.java
deleted file mode 100644
index df93f38..0000000
--- a/core/java/android/syncml/pim/VParser.java
+++ /dev/null
@@ -1,723 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
-
-/**
- * This interface is used to parse the V format files, such as VCard & VCal
- *
- */
-abstract public class VParser {
-
- /**
- * The buffer used to store input stream
- */
- protected String mBuffer = null;
-
- /** The builder to build parsed data */
- protected VBuilder mBuilder = null;
-
- /** The encoding type */
- protected String mEncoding = null;
-
- protected final int PARSE_ERROR = -1;
-
- protected final String mDefaultEncoding = "8BIT";
-
- /**
- * If offset reach '\r\n' return 2. Else return PARSE_ERROR.
- */
- protected int parseCrlf(int offset) {
- if (offset >= mBuffer.length())
- return PARSE_ERROR;
- char ch = mBuffer.charAt(offset);
- if (ch == '\r') {
- offset++;
- ch = mBuffer.charAt(offset);
- if (ch == '\n') {
- return 2;
- }
- }
- return PARSE_ERROR;
- }
-
- /**
- * Parse the given stream
- *
- * @param is
- * The source to parse.
- * @param encoding
- * The encoding type.
- * @param builder
- * The v builder which used to construct data.
- * @return Return true for success, otherwise false.
- * @throws IOException
- */
- public boolean parse(InputStream is, String encoding, VBuilder builder)
- throws IOException {
- setInputStream(is, encoding);
- mBuilder = builder;
- int ret = 0, offset = 0, sum = 0;
-
- if (mBuilder != null) {
- mBuilder.start();
- }
- for (;;) {
- ret = parseVFile(offset); // for next property length
- if (PARSE_ERROR == ret) {
- break;
- } else {
- offset += ret;
- sum += ret;
- }
- }
- if (mBuilder != null) {
- mBuilder.end();
- }
- return (mBuffer.length() == sum);
- }
-
- /**
- * Copy the content of input stream and filter the "folding"
- */
- protected void setInputStream(InputStream is, String encoding)
- throws UnsupportedEncodingException {
- InputStreamReader reader = new InputStreamReader(is, encoding);
- StringBuilder b = new StringBuilder();
-
- int ch;
- try {
- while ((ch = reader.read()) != -1) {
- if (ch == '\r') {
- ch = reader.read();
- if (ch == '\n') {
- ch = reader.read();
- if (ch == ' ' || ch == '\t') {
- b.append((char) ch);
- continue;
- }
- b.append("\r\n");
- if (ch == -1) {
- break;
- }
- } else {
- b.append("\r");
- }
- }
- b.append((char) ch);
- }
- mBuffer = b.toString();
- } catch (Exception e) {
- return;
- }
- return;
- }
-
- /**
- * abstract function, waiting implement.<br>
- * analyse from offset, return the length of consumed property.
- */
- abstract protected int parseVFile(int offset);
-
- /**
- * From offset, jump ' ', '\t', '\r\n' sequence, return the length of jump.<br>
- * 1 * (SPACE / HTAB / CRLF)
- */
- protected int parseWsls(int offset) {
- int ret = 0, sum = 0;
-
- try {
- char ch = mBuffer.charAt(offset);
- if (ch == ' ' || ch == '\t') {
- sum++;
- offset++;
- } else if ((ret = parseCrlf(offset)) != PARSE_ERROR) {
- offset += ret;
- sum += ret;
- } else {
- return PARSE_ERROR;
- }
- for (;;) {
- ch = mBuffer.charAt(offset);
- if (ch == ' ' || ch == '\t') {
- sum++;
- offset++;
- } else if ((ret = parseCrlf(offset)) != PARSE_ERROR) {
- offset += ret;
- sum += ret;
- } else {
- break;
- }
- }
- } catch (IndexOutOfBoundsException e) {
- ;
- }
- if (sum > 0)
- return sum;
- return PARSE_ERROR;
- }
-
- /**
- * To determine if the given string equals to the start of the current
- * string.
- *
- * @param offset
- * The offset in buffer of current string
- * @param tar
- * The given string.
- * @param ignoreCase
- * To determine case sensitive or not.
- * @return The consumed characters, otherwise return PARSE_ERROR.
- */
- protected int parseString(int offset, final String tar, boolean ignoreCase) {
- int sum = 0;
- if (tar == null) {
- return PARSE_ERROR;
- }
-
- if (ignoreCase) {
- int len = tar.length();
- try {
- if (mBuffer.substring(offset, offset + len).equalsIgnoreCase(
- tar)) {
- sum = len;
- } else {
- return PARSE_ERROR;
- }
- } catch (IndexOutOfBoundsException e) {
- return PARSE_ERROR;
- }
-
- } else { /* case sensitive */
- if (mBuffer.startsWith(tar, offset)) {
- sum = tar.length();
- } else {
- return PARSE_ERROR;
- }
- }
- return sum;
- }
-
- /**
- * Skip the white space in string.
- */
- protected int removeWs(int offset) {
- if (offset >= mBuffer.length())
- return PARSE_ERROR;
- int sum = 0;
- char ch;
- while ((ch = mBuffer.charAt(offset)) == ' ' || ch == '\t') {
- offset++;
- sum++;
- }
- return sum;
- }
-
- /**
- * "X-" word, and its value. Return consumed length.
- */
- protected int parseXWord(int offset) {
- int ret = 0, sum = 0;
- ret = parseString(offset, "X-", true);
- if (PARSE_ERROR == ret)
- return PARSE_ERROR;
- offset += ret;
- sum += ret;
-
- ret = parseWord(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- sum += ret;
- return sum;
- }
-
- /**
- * From offset, parse as :mEncoding ?= 7bit / 8bit / quoted-printable /
- * base64
- */
- protected int parseValue(int offset) {
- int ret = 0;
-
- if (mEncoding == null || mEncoding.equalsIgnoreCase("7BIT")
- || mEncoding.equalsIgnoreCase("8BIT")
- || mEncoding.toUpperCase().startsWith("X-")) {
- ret = parse8bit(offset);
- if (ret != PARSE_ERROR) {
- return ret;
- }
- return PARSE_ERROR;
- }
-
- if (mEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) {
- ret = parseQuotedPrintable(offset);
- if (ret != PARSE_ERROR) {
- return ret;
- }
- return PARSE_ERROR;
- }
-
- if (mEncoding.equalsIgnoreCase("BASE64")) {
- ret = parseBase64(offset);
- if (ret != PARSE_ERROR) {
- return ret;
- }
- return PARSE_ERROR;
- }
- return PARSE_ERROR;
- }
-
- /**
- * Refer to RFC 1521, 8bit text
- */
- protected int parse8bit(int offset) {
- int index = 0;
-
- index = mBuffer.substring(offset).indexOf("\r\n");
-
- if (index == -1)
- return PARSE_ERROR;
- else
- return index;
-
- }
-
- /**
- * Refer to RFC 1521, quoted printable text ([*(ptext / SPACE / TAB) ptext]
- * ["="] CRLF)
- */
- protected int parseQuotedPrintable(int offset) {
- int ret = 0, sum = 0;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- for (;;) {
- ret = parsePtext(offset);
- if (PARSE_ERROR == ret)
- break;
- offset += ret;
- sum += ret;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
- }
-
- ret = parseString(offset, "=", false);
- if (ret != PARSE_ERROR) {
- // offset += ret;
- sum += ret;
- }
-
- return sum;
- }
-
- /**
- * return 1 or 3 <any ASCII character except "=", SPACE, or TAB>
- */
- protected int parsePtext(int offset) {
- int ret = 0;
-
- try {
- char ch = mBuffer.charAt(offset);
- if (isPrintable(ch) && ch != '=' && ch != ' ' && ch != '\t') {
- return 1;
- }
- } catch (IndexOutOfBoundsException e) {
- return PARSE_ERROR;
- }
-
- ret = parseOctet(offset);
- if (ret != PARSE_ERROR) {
- return ret;
- }
- return PARSE_ERROR;
- }
-
- /**
- * start with "=" two of (DIGIT / "A" / "B" / "C" / "D" / "E" / "F") <br>
- * So maybe return 3.
- */
- protected int parseOctet(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseString(offset, "=", false);
- if (PARSE_ERROR == ret)
- return PARSE_ERROR;
- offset += ret;
- sum += ret;
-
- try {
- int ch = mBuffer.charAt(offset);
- if (ch == ' ' || ch == '\t')
- return ++sum;
- if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F')) {
- offset++;
- sum++;
- ch = mBuffer.charAt(offset);
- if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F')) {
- sum++;
- return sum;
- }
- }
- } catch (IndexOutOfBoundsException e) {
- ;
- }
- return PARSE_ERROR;
- }
-
- /**
- * Refer to RFC 1521, base64 text The end of the text is marked with two
- * CRLF sequences
- */
- protected int parseBase64(int offset) {
- int sum = 0;
- try {
- for (;;) {
- char ch;
- ch = mBuffer.charAt(offset);
-
- if (ch == '\r') {
- int ret = parseString(offset, "\r\n\r\n", false);
- sum += ret;
- break;
- } else {
- /* ignore none base64 character */
- sum++;
- offset++;
- }
- }
- } catch (IndexOutOfBoundsException e) {
- return PARSE_ERROR;
- }
- sum -= 2;/* leave one CRLF to parse the end of this property */
- return sum;
- }
-
- /**
- * Any printable ASCII sequence except [ ]=:.,;
- */
- protected int parseWord(int offset) {
- int sum = 0;
- try {
- for (;;) {
- char ch = mBuffer.charAt(offset);
- if (!isPrintable(ch))
- break;
- if (ch == ' ' || ch == '=' || ch == ':' || ch == '.'
- || ch == ',' || ch == ';')
- break;
- if (ch == '\\') {
- ch = mBuffer.charAt(offset + 1);
- if (ch == ';') {
- offset++;
- sum++;
- }
- }
- offset++;
- sum++;
- }
- } catch (IndexOutOfBoundsException e) {
- ;
- }
- if (sum == 0)
- return PARSE_ERROR;
- return sum;
- }
-
- /**
- * If it is a letter or digit.
- */
- protected boolean isLetterOrDigit(char ch) {
- if (ch >= '0' && ch <= '9')
- return true;
- if (ch >= 'a' && ch <= 'z')
- return true;
- if (ch >= 'A' && ch <= 'Z')
- return true;
- return false;
- }
-
- /**
- * If it is printable in ASCII
- */
- protected boolean isPrintable(char ch) {
- if (ch >= ' ' && ch <= '~')
- return true;
- return false;
- }
-
- /**
- * If it is a letter.
- */
- protected boolean isLetter(char ch) {
- if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
- return true;
- }
- return false;
- }
-
- /**
- * Get a word from current position.
- */
- protected String getWord(int offset) {
- StringBuilder word = new StringBuilder();
- try {
- for (;;) {
- char ch = mBuffer.charAt(offset);
- if (isLetterOrDigit(ch) || ch == '-') {
- word.append(ch);
- offset++;
- } else {
- break;
- }
- }
- } catch (IndexOutOfBoundsException e) {
- ;
- }
- return word.toString();
- }
-
- /**
- * If is: "INLINE" / "URL" / "CONTENT-ID" / "CID" / "X-" word
- */
- protected int parsePValueVal(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseString(offset, "INLINE", true);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "URL", true);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "CONTENT-ID", true);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "CID", true);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "INLINE", true);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseXWord(offset);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- return PARSE_ERROR;
- }
-
- /**
- * If is: "7BIT" / "8BIT" / "QUOTED-PRINTABLE" / "BASE64" / "X-" word and
- * set mEncoding.
- */
- protected int parsePEncodingVal(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseString(offset, "7BIT", true);
- if (ret != PARSE_ERROR) {
- mEncoding = "7BIT";
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "8BIT", true);
- if (ret != PARSE_ERROR) {
- mEncoding = "8BIT";
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "QUOTED-PRINTABLE", true);
- if (ret != PARSE_ERROR) {
- mEncoding = "QUOTED-PRINTABLE";
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "BASE64", true);
- if (ret != PARSE_ERROR) {
- mEncoding = "BASE64";
- sum += ret;
- return sum;
- }
-
- ret = parseXWord(offset);
- if (ret != PARSE_ERROR) {
- mEncoding = mBuffer.substring(offset).substring(0, ret);
- sum += ret;
- return sum;
- }
-
- return PARSE_ERROR;
- }
-
- /**
- * Refer to RFC1521, section 7.1<br>
- * If is: "us-ascii" / "iso-8859-xxx" / "X-" word
- */
- protected int parseCharsetVal(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseString(offset, "us-ascii", true);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "iso-8859-1", true);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "iso-8859-2", true);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "iso-8859-3", true);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "iso-8859-4", true);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "iso-8859-5", true);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "iso-8859-6", true);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "iso-8859-7", true);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "iso-8859-8", true);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseString(offset, "iso-8859-9", true);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseXWord(offset);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- return PARSE_ERROR;
- }
-
- /**
- * Refer to RFC 1766<br>
- * like: XXX(sequence letters)-XXX(sequence letters)
- */
- protected int parseLangVal(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseTag(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- for (;;) {
- ret = parseString(offset, "-", false);
- if (PARSE_ERROR == ret) {
- break;
- }
- offset += ret;
- sum += ret;
-
- ret = parseTag(offset);
- if (PARSE_ERROR == ret) {
- break;
- }
- offset += ret;
- sum += ret;
- }
- return sum;
- }
-
- /**
- * From first 8 position, is sequence LETTER.
- */
- protected int parseTag(int offset) {
- int sum = 0, i = 0;
-
- try {
- for (i = 0; i < 8; i++) {
- char ch = mBuffer.charAt(offset);
- if (!isLetter(ch)) {
- break;
- }
- sum++;
- offset++;
- }
- } catch (IndexOutOfBoundsException e) {
- ;
- }
- if (i == 0) {
- return PARSE_ERROR;
- }
- return sum;
- }
-
-}
diff --git a/core/java/android/syncml/pim/package.html b/core/java/android/syncml/pim/package.html
deleted file mode 100644
index cb4ca46..0000000
--- a/core/java/android/syncml/pim/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<HTML>
-<BODY>
-Support classes for SyncML.
-{@hide}
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/core/java/android/syncml/pim/vcalendar/CalendarStruct.java b/core/java/android/syncml/pim/vcalendar/CalendarStruct.java
deleted file mode 100644
index 3388ada..0000000
--- a/core/java/android/syncml/pim/vcalendar/CalendarStruct.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim.vcalendar;
-
-import java.util.List;
-import java.util.ArrayList;
-
-/**
- * Same comment as ContactStruct.
- */
-public class CalendarStruct{
-
- public static class EventStruct{
- public String description;
- public String dtend;
- public String dtstart;
- public String duration;
- public String has_alarm;
- public String last_date;
- public String rrule;
- public String status;
- public String title;
- public String event_location;
- public String uid;
- public List<String> reminderList;
-
- public void addReminderList(String method){
- if(reminderList == null)
- reminderList = new ArrayList<String>();
- reminderList.add(method);
- }
- }
-
- public String timezone;
- public List<EventStruct> eventList;
-
- public void addEventList(EventStruct stru){
- if(eventList == null)
- eventList = new ArrayList<EventStruct>();
- eventList.add(stru);
- }
-}
diff --git a/core/java/android/syncml/pim/vcalendar/VCalComposer.java b/core/java/android/syncml/pim/vcalendar/VCalComposer.java
deleted file mode 100644
index 18b6719..0000000
--- a/core/java/android/syncml/pim/vcalendar/VCalComposer.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim.vcalendar;
-
-/**
- * vCalendar string composer class
- */
-public class VCalComposer {
-
- public final static String VERSION_VCALENDAR10 = "vcalendar1.0";
- public final static String VERSION_VCALENDAR20 = "vcalendar2.0";
-
- public final static int VERSION_VCAL10_INT = 1;
- public final static int VERSION_VCAL20_INT = 2;
-
- private static String mNewLine = "\r\n";
- private String mVersion = null;
-
- public VCalComposer() {
- }
-
- /**
- * Create a vCalendar String.
- * @param struct see more from CalendarStruct class
- * @param vcalversion MUST be VERSION_VCAL10 /VERSION_VCAL20
- * @return vCalendar string
- * @throws VcalException if version is invalid or create failed
- */
- public String createVCal(CalendarStruct struct, int vcalversion)
- throws VCalException{
-
- StringBuilder returnStr = new StringBuilder();
-
- //Version check
- if(vcalversion != 1 && vcalversion != 2)
- throw new VCalException("version not match 1.0 or 2.0.");
- if (vcalversion == 1)
- mVersion = VERSION_VCALENDAR10;
- else
- mVersion = VERSION_VCALENDAR20;
-
- //Build vCalendar:
- returnStr.append("BEGIN:VCALENDAR").append(mNewLine);
-
- if(vcalversion == VERSION_VCAL10_INT)
- returnStr.append("VERSION:1.0").append(mNewLine);
- else
- returnStr.append("VERSION:2.0").append(mNewLine);
-
- returnStr.append("PRODID:vCal ID default").append(mNewLine);
-
- if(!isNull(struct.timezone)){
- if(vcalversion == VERSION_VCAL10_INT)
- returnStr.append("TZ:").append(struct.timezone).append(mNewLine);
- else//down here MUST have
- returnStr.append("BEGIN:VTIMEZONE").append(mNewLine).
- append("TZID:vCal default").append(mNewLine).
- append("BEGIN:STANDARD").append(mNewLine).
- append("DTSTART:16010101T000000").append(mNewLine).
- append("TZOFFSETFROM:").append(struct.timezone).append(mNewLine).
- append("TZOFFSETTO:").append(struct.timezone).append(mNewLine).
- append("END:STANDARD").append(mNewLine).
- append("END:VTIMEZONE").append(mNewLine);
- }
- //Build VEVNET
- for(int i = 0; i < struct.eventList.size(); i++){
- String str = buildEventStr( struct.eventList.get(i) );
- returnStr.append(str);
- }
-
- //Build VTODO
- //TODO
-
- returnStr.append("END:VCALENDAR").append(mNewLine).append(mNewLine);
-
- return returnStr.toString();
- }
-
- private String buildEventStr(CalendarStruct.EventStruct stru){
-
- StringBuilder strbuf = new StringBuilder();
-
- strbuf.append("BEGIN:VEVENT").append(mNewLine);
-
- if(!isNull(stru.uid))
- strbuf.append("UID:").append(stru.uid).append(mNewLine);
-
- if(!isNull(stru.description))
- strbuf.append("DESCRIPTION:").
- append(foldingString(stru.description)).append(mNewLine);
-
- if(!isNull(stru.dtend))
- strbuf.append("DTEND:").append(stru.dtend).append(mNewLine);
-
- if(!isNull(stru.dtstart))
- strbuf.append("DTSTART:").append(stru.dtstart).append(mNewLine);
-
- if(!isNull(stru.duration))
- strbuf.append("DUE:").append(stru.duration).append(mNewLine);
-
- if(!isNull(stru.event_location))
- strbuf.append("LOCATION:").append(stru.event_location).append(mNewLine);
-
- if(!isNull(stru.last_date))
- strbuf.append("COMPLETED:").append(stru.last_date).append(mNewLine);
-
- if(!isNull(stru.rrule))
- strbuf.append("RRULE:").append(stru.rrule).append(mNewLine);
-
- if(!isNull(stru.title))
- strbuf.append("SUMMARY:").append(stru.title).append(mNewLine);
-
- if(!isNull(stru.status)){
- String stat = "TENTATIVE";
- switch (Integer.parseInt(stru.status)){
- case 0://Calendar.Calendars.STATUS_TENTATIVE
- stat = "TENTATIVE";
- break;
- case 1://Calendar.Calendars.STATUS_CONFIRMED
- stat = "CONFIRMED";
- break;
- case 2://Calendar.Calendars.STATUS_CANCELED
- stat = "CANCELLED";
- break;
- }
- strbuf.append("STATUS:").append(stat).append(mNewLine);
- }
- //Alarm
- if(!isNull(stru.has_alarm)
- && stru.reminderList != null
- && stru.reminderList.size() > 0){
-
- if (mVersion.equals(VERSION_VCALENDAR10)){
- String prefix = "";
- for(String method : stru.reminderList){
- switch (Integer.parseInt(method)){
- case 0:
- prefix = "DALARM";
- break;
- case 1:
- prefix = "AALARM";
- break;
- case 2:
- prefix = "MALARM";
- break;
- case 3:
- default:
- prefix = "DALARM";
- break;
- }
- strbuf.append(prefix).append(":default").append(mNewLine);
- }
- }else {//version 2.0 only support audio-method now.
- strbuf.append("BEGIN:VALARM").append(mNewLine).
- append("ACTION:AUDIO").append(mNewLine).
- append("TRIGGER:-PT10M").append(mNewLine).
- append("END:VALARM").append(mNewLine);
- }
- }
- strbuf.append("END:VEVENT").append(mNewLine);
- return strbuf.toString();
- }
-
- /** Alter str to folding supported format. */
- private String foldingString(String str){
- return str.replaceAll("\r\n", "\n").replaceAll("\n", "\r\n ");
- }
-
- /** is null */
- private boolean isNull(String str){
- if(str == null || str.trim().equals(""))
- return true;
- return false;
- }
-}
diff --git a/core/java/android/syncml/pim/vcalendar/VCalException.java b/core/java/android/syncml/pim/vcalendar/VCalException.java
deleted file mode 100644
index 48ea134..0000000
--- a/core/java/android/syncml/pim/vcalendar/VCalException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim.vcalendar;
-
-public class VCalException extends java.lang.Exception{
- // constructors
-
- /**
- * Constructs a VCalException object
- */
-
- public VCalException()
- {
- }
-
- /**
- * Constructs a VCalException object
- *
- * @param message the error message
- */
-
- public VCalException( String message )
- {
- super( message );
- }
-
-}
diff --git a/core/java/android/syncml/pim/vcalendar/VCalParser.java b/core/java/android/syncml/pim/vcalendar/VCalParser.java
deleted file mode 100644
index bc2d598..0000000
--- a/core/java/android/syncml/pim/vcalendar/VCalParser.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim.vcalendar;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import android.util.Config;
-import android.util.Log;
-
-import android.syncml.pim.VDataBuilder;
-import android.syncml.pim.VParser;
-
-public class VCalParser{
-
- private final static String TAG = "VCalParser";
-
- public final static String VERSION_VCALENDAR10 = "vcalendar1.0";
- public final static String VERSION_VCALENDAR20 = "vcalendar2.0";
-
- private VParser mParser = null;
- private String mVersion = null;
-
- public VCalParser() {
- }
-
- public boolean parse(String vcalendarStr, VDataBuilder builder)
- throws VCalException {
-
- vcalendarStr = verifyVCal(vcalendarStr);
- try{
- boolean isSuccess = mParser.parse(
- new ByteArrayInputStream(vcalendarStr.getBytes()),
- "US-ASCII", builder);
-
- if (!isSuccess) {
- if (mVersion.equals(VERSION_VCALENDAR10)) {
- if(Config.LOGD)
- Log.d(TAG, "Parse failed for vCal 1.0 parser."
- + " Try to use 2.0 parser.");
- mVersion = VERSION_VCALENDAR20;
- return parse(vcalendarStr, builder);
- }else
- throw new VCalException("parse failed.(even use 2.0 parser)");
- }
- }catch (IOException e){
- throw new VCalException(e.getMessage());
- }
- return true;
- }
-
- /**
- * Verify vCalendar string, and initialize mVersion according to it.
- * */
- private String verifyVCal(String vcalStr) {
-
- //Version check
- judgeVersion(vcalStr);
-
- vcalStr = vcalStr.replaceAll("\r\n", "\n");
- String[] strlist = vcalStr.split("\n");
-
- StringBuilder replacedStr = new StringBuilder();
-
- for (int i = 0; i < strlist.length; i++) {
- if (strlist[i].indexOf(":") < 0) {
- if (strlist[i].length() == 0 && strlist[i + 1].indexOf(":") > 0)
- replacedStr.append(strlist[i]).append("\r\n");
- else
- replacedStr.append(" ").append(strlist[i]).append("\r\n");
- } else
- replacedStr.append(strlist[i]).append("\r\n");
- }
- if(Config.LOGD)Log.d(TAG, "After verify:\r\n" + replacedStr.toString());
-
- return replacedStr.toString();
- }
-
- /**
- * If version not given. Search from vcal string of the VERSION property.
- * Then instance mParser to appropriate parser.
- */
- private void judgeVersion(String vcalStr) {
-
- if (mVersion == null) {
- int versionIdx = vcalStr.indexOf("\nVERSION:");
-
- mVersion = VERSION_VCALENDAR10;
-
- if (versionIdx != -1){
- String versionStr = vcalStr.substring(
- versionIdx, vcalStr.indexOf("\n", versionIdx + 1));
- if (versionStr.indexOf("2.0") > 0)
- mVersion = VERSION_VCALENDAR20;
- }
- }
- if (mVersion.equals(VERSION_VCALENDAR10))
- mParser = new VCalParser_V10();
- if (mVersion.equals(VERSION_VCALENDAR20))
- mParser = new VCalParser_V20();
- }
-}
-
diff --git a/core/java/android/syncml/pim/vcalendar/VCalParser_V10.java b/core/java/android/syncml/pim/vcalendar/VCalParser_V10.java
deleted file mode 100644
index 1b251f3..0000000
--- a/core/java/android/syncml/pim/vcalendar/VCalParser_V10.java
+++ /dev/null
@@ -1,1628 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim.vcalendar;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import android.syncml.pim.VParser;
-
-public class VCalParser_V10 extends VParser {
-
- /*
- * The names of the properties whose value are not separated by ";"
- */
- private static final HashSet<String> mEvtPropNameGroup1 = new HashSet<String>(
- Arrays.asList("ATTACH", "ATTENDEE", "DCREATED", "COMPLETED",
- "DESCRIPTION", "DUE", "DTEND", "EXRULE", "LAST-MODIFIED",
- "LOCATION", "RNUM", "PRIORITY", "RELATED-TO", "RRULE",
- "SEQUENCE", "DTSTART", "SUMMARY", "TRANSP", "URL", "UID",
- // above belong to simprop
- "CLASS", "STATUS"));
-
- /*
- * The names of properties whose value are separated by ";"
- */
- private static final HashSet<String> mEvtPropNameGroup2 = new HashSet<String>(
- Arrays.asList("AALARM", "CATEGORIES", "DALARM", "EXDATE", "MALARM",
- "PALARM", "RDATE", "RESOURCES"));
-
- private static final HashSet<String> mValueCAT = new HashSet<String>(Arrays
- .asList("APPOINTMENT", "BUSINESS", "EDUCATION", "HOLIDAY",
- "MEETING", "MISCELLANEOUS", "PERSONAL", "PHONE CALL",
- "SICK DAY", "SPECIAL OCCASION", "TRAVEL", "VACATION"));
-
- private static final HashSet<String> mValueCLASS = new HashSet<String>(Arrays
- .asList("PUBLIC", "PRIVATE", "CONFIDENTIAL"));
-
- private static final HashSet<String> mValueRES = new HashSet<String>(Arrays
- .asList("CATERING", "CHAIRS", "EASEL", "PROJECTOR", "VCR",
- "VEHICLE"));
-
- private static final HashSet<String> mValueSTAT = new HashSet<String>(Arrays
- .asList("ACCEPTED", "NEEDS ACTION", "SENT", "TENTATIVE",
- "CONFIRMED", "DECLINED", "COMPLETED", "DELEGATED"));
-
- /*
- * The names of properties whose value can contain escape characters
- */
- private static final HashSet<String> mEscAllowedProps = new HashSet<String>(
- Arrays.asList("DESCRIPTION", "SUMMARY", "AALARM", "DALARM",
- "MALARM", "PALARM"));
-
- private static final HashMap<String, HashSet<String>> mSpecialValueSetMap =
- new HashMap<String, HashSet<String>>();
-
- static {
- mSpecialValueSetMap.put("CATEGORIES", mValueCAT);
- mSpecialValueSetMap.put("CLASS", mValueCLASS);
- mSpecialValueSetMap.put("RESOURCES", mValueRES);
- mSpecialValueSetMap.put("STATUS", mValueSTAT);
- }
-
- public VCalParser_V10() {
- }
-
- protected int parseVFile(int offset) {
- return parseVCalFile(offset);
- }
-
- private int parseVCalFile(int offset) {
- int ret = 0, sum = 0;
-
- /* remove wsls */
- while (PARSE_ERROR != (ret = parseWsls(offset))) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseVCal(offset); // BEGIN:VCAL ... END:VCAL
- if (PARSE_ERROR != ret) {
- offset += ret;
- sum += ret;
- } else {
- return PARSE_ERROR;
- }
-
- /* remove wsls */
- while (PARSE_ERROR != (ret = parseWsls(offset))) {
- offset += ret;
- sum += ret;
- }
- return sum;
- }
-
- /**
- * "BEGIN" [ws] ":" [ws] "VCALENDAR" [ws] 1*crlf calprop calentities [ws]
- * *crlf "END" [ws] ":" [ws] "VCALENDAR" [ws] 1*CRLF
- */
- private int parseVCal(int offset) {
- int ret = 0, sum = 0;
-
- /* BEGIN */
- ret = parseString(offset, "BEGIN", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // ":"
- ret = parseString(offset, ":", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // "VCALENDAR
- ret = parseString(offset, "VCALENDAR", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.startRecord("VCALENDAR");
- }
-
- /* [ws] */
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // 1*CRLF
- ret = parseCrlf(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- while (PARSE_ERROR != (ret = parseCrlf(offset))) {
- offset += ret;
- sum += ret;
- }
-
- // calprop
- ret = parseCalprops(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // calentities
- ret = parseCalentities(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // *CRLF
- while (PARSE_ERROR != (ret = parseCrlf(offset))) {
- offset += ret;
- sum += ret;
- }
-
- // "END"
- ret = parseString(offset, "END", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // ":"
- // ":"
- ret = parseString(offset, ":", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // "VCALENDAR"
- ret = parseString(offset, "VCALENDAR", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.endRecord();
- }
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // 1 * CRLF
- ret = parseCrlf(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- while (PARSE_ERROR != (ret = parseCrlf(offset))) {
- offset += ret;
- sum += ret;
- }
-
- return sum;
- }
-
- /**
- * calprops * CRLF calprop / calprop
- */
- private int parseCalprops(int offset) {
- int ret = 0, sum = 0;
-
- if (mBuilder != null) {
- mBuilder.startProperty();
- }
- ret = parseCalprop(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.endProperty();
- }
-
- for (;;) {
- /* *CRLF */
- while (PARSE_ERROR != (ret = parseCrlf(offset))) {
- offset += ret;
- sum += ret;
- }
- // follow VEVENT ,it wont reach endProperty
- if (mBuilder != null) {
- mBuilder.startProperty();
- }
- ret = parseCalprop(offset);
- if (PARSE_ERROR == ret) {
- break;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.endProperty();
- }
- }
-
- return sum;
- }
-
- /**
- * calentities *CRLF calentity / calentity
- */
- private int parseCalentities(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseCalentity(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- for (;;) {
- /* *CRLF */
- while (PARSE_ERROR != (ret = parseCrlf(offset))) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseCalentity(offset);
- if (PARSE_ERROR == ret) {
- break;
- }
- offset += ret;
- sum += ret;
- }
-
- return sum;
- }
-
- /**
- * calprop = DAYLIGHT/ GEO/ PRODID/ TZ/ VERSION
- */
- private int parseCalprop(int offset) {
- int ret = 0;
-
- ret = parseCalprop0(offset, "DAYLIGHT");
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseCalprop0(offset, "GEO");
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseCalprop0(offset, "PRODID");
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseCalprop0(offset, "TZ");
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseCalprop1(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
- return PARSE_ERROR;
- }
-
- /**
- * evententity / todoentity
- */
- private int parseCalentity(int offset) {
- int ret = 0;
-
- ret = parseEvententity(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseTodoentity(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
- return PARSE_ERROR;
-
- }
-
- /**
- * propName [params] ":" value CRLF
- */
- private int parseCalprop0(int offset, String propName) {
- int ret = 0, sum = 0, start = 0;
-
- ret = parseString(offset, propName, true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyName(propName);
- }
-
- ret = parseParams(offset);
- if (PARSE_ERROR != ret) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseString(offset, ":", true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parseValue(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- ArrayList<String> v = new ArrayList<String>();
- v.add(mBuffer.substring(start, offset));
- mBuilder.propertyValues(v);
- }
-
- ret = parseCrlf(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- sum += ret;
-
- return sum;
- }
-
- /**
- * "VERSION" [params] ":" "1.0" CRLF
- */
- private int parseCalprop1(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseString(offset, "VERSION", true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyName("VERSION");
- }
-
- ret = parseParams(offset);
- if (PARSE_ERROR != ret) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseString(offset, ":", true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, "1.0", true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- ArrayList<String> v = new ArrayList<String>();
- v.add("1.0");
- mBuilder.propertyValues(v);
- }
- ret = parseCrlf(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- sum += ret;
-
- return sum;
- }
-
- /**
- * "BEGIN" [ws] ":" [ws] "VEVENT" [ws] 1*CRLF entprops [ws] *CRLF "END" [ws]
- * ":" [ws] "VEVENT" [ws] 1*CRLF
- */
- private int parseEvententity(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseString(offset, "BEGIN", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // ":"
- ret = parseString(offset, ":", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // "VEVNET"
- ret = parseString(offset, "VEVENT", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.startRecord("VEVENT");
- }
-
- /* [ws] */
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // 1*CRLF
- ret = parseCrlf(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- while (PARSE_ERROR != (ret = parseCrlf(offset))) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseEntprops(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // *CRLF
- while (PARSE_ERROR != (ret = parseCrlf(offset))) {
- offset += ret;
- sum += ret;
- }
-
- // "END"
- ret = parseString(offset, "END", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // ":"
- ret = parseString(offset, ":", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // "VEVENT"
- ret = parseString(offset, "VEVENT", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.endRecord();
- }
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // 1 * CRLF
- ret = parseCrlf(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- while (PARSE_ERROR != (ret = parseCrlf(offset))) {
- offset += ret;
- sum += ret;
- }
-
- return sum;
- }
-
- /**
- * "BEGIN" [ws] ":" [ws] "VTODO" [ws] 1*CRLF entprops [ws] *CRLF "END" [ws]
- * ":" [ws] "VTODO" [ws] 1*CRLF
- */
- private int parseTodoentity(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseString(offset, "BEGIN", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // ":"
- ret = parseString(offset, ":", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // "VTODO"
- ret = parseString(offset, "VTODO", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.startRecord("VTODO");
- }
-
- // 1*CRLF
- ret = parseCrlf(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- while (PARSE_ERROR != (ret = parseCrlf(offset))) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseEntprops(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // *CRLF
- while (PARSE_ERROR != (ret = parseCrlf(offset))) {
- offset += ret;
- sum += ret;
- }
-
- // "END"
- ret = parseString(offset, "END", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // ":"
- ret = parseString(offset, ":", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // "VTODO"
- ret = parseString(offset, "VTODO", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.endRecord();
- }
-
- // [ws]
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- // 1 * CRLF
- ret = parseCrlf(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- while (PARSE_ERROR != (ret = parseCrlf(offset))) {
- offset += ret;
- sum += ret;
- }
-
- return sum;
- }
-
- /**
- * entprops *CRLF entprop / entprop
- */
- private int parseEntprops(int offset) {
- int ret = 0, sum = 0;
- if (mBuilder != null) {
- mBuilder.startProperty();
- }
-
- ret = parseEntprop(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.endProperty();
- }
-
- for (;;) {
- while (PARSE_ERROR != (ret = parseCrlf(offset))) {
- offset += ret;
- sum += ret;
- }
- if (mBuilder != null) {
- mBuilder.startProperty();
- }
-
- ret = parseEntprop(offset);
- if (PARSE_ERROR == ret) {
- break;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.endProperty();
- }
- }
- return sum;
- }
-
- /**
- * for VEVENT,VTODO prop. entprop0 / entprop1
- */
- private int parseEntprop(int offset) {
- int ret = 0;
- ret = parseEntprop0(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseEntprop1(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
- return PARSE_ERROR;
- }
-
- /**
- * Same with card. ";" [ws] paramlist
- */
- private int parseParams(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseString(offset, ";", true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseParamlist(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- sum += ret;
-
- return sum;
- }
-
- /**
- * Same with card. paramlist [ws] ";" [ws] param / param
- */
- private int parseParamlist(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseParam(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- int offsetTemp = offset;
- int sumTemp = sum;
- for (;;) {
- ret = removeWs(offsetTemp);
- offsetTemp += ret;
- sumTemp += ret;
-
- ret = parseString(offsetTemp, ";", false);
- if (PARSE_ERROR == ret) {
- return sum;
- }
- offsetTemp += ret;
- sumTemp += ret;
-
- ret = removeWs(offsetTemp);
- offsetTemp += ret;
- sumTemp += ret;
-
- ret = parseParam(offsetTemp);
- if (PARSE_ERROR == ret) {
- break;
- }
- offsetTemp += ret;
- sumTemp += ret;
-
- // offset = offsetTemp;
- sum = sumTemp;
- }
- return sum;
- }
-
- /**
- * param0 - param7 / knowntype
- */
- private int parseParam(int offset) {
- int ret = 0;
-
- ret = parseParam0(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseParam1(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseParam2(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseParam3(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseParam4(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseParam5(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseParam6(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseParam7(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- int start = offset;
- ret = parseKnownType(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamType(null);
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
-
- return ret;
- }
-
- /**
- * simprop AND "CLASS" AND "STATUS" The value of these properties are not
- * seperated by ";"
- *
- * [ws] simprop [params] ":" value CRLF
- */
- private int parseEntprop0(int offset) {
- int ret = 0, sum = 0, start = 0;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- String propName = getWord(offset).toUpperCase();
- if (!mEvtPropNameGroup1.contains(propName)) {
- if (PARSE_ERROR == parseXWord(offset))
- return PARSE_ERROR;
- }
- ret = propName.length();
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyName(propName);
- }
-
- ret = parseParams(offset);
- if (PARSE_ERROR != ret) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseString(offset, ":", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parseValue(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- ArrayList<String> v = new ArrayList<String>();
- v.add(exportEntpropValue(propName, mBuffer.substring(start,
- offset)));
- mBuilder.propertyValues(v);
- // Filter value,match string, REFER:RFC
- if (PARSE_ERROR == valueFilter(propName, v))
- return PARSE_ERROR;
- }
-
- ret = parseCrlf(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- sum += ret;
- return sum;
- }
-
- /**
- * other event prop names except simprop AND "CLASS" AND "STATUS" The value
- * of these properties are seperated by ";" [ws] proper name [params] ":"
- * value CRLF
- */
- private int parseEntprop1(int offset) {
- int ret = 0, sum = 0;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- String propName = getWord(offset).toUpperCase();
- if (!mEvtPropNameGroup2.contains(propName)) {
- return PARSE_ERROR;
- }
- ret = propName.length();
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyName(propName);
- }
-
- ret = parseParams(offset);
- if (PARSE_ERROR != ret) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseString(offset, ":", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- int start = offset;
- ret = parseValue(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- // mutil-values
- if (mBuilder != null) {
- int end = 0;
- ArrayList<String> v = new ArrayList<String>();
- Pattern p = Pattern
- .compile("([^;\\\\]*(\\\\[\\\\;:,])*[^;\\\\]*)(;?)");
- Matcher m = p.matcher(mBuffer.substring(start, offset));
- while (m.find()) {
- String s = exportEntpropValue(propName, m.group(1));
- v.add(s);
- end = m.end();
- if (offset == start + end) {
- String endValue = m.group(3);
- if (";".equals(endValue)) {
- v.add("");
- }
- break;
- }
- }
- mBuilder.propertyValues(v);
- // Filter value,match string, REFER:RFC
- if (PARSE_ERROR == valueFilter(propName, v))
- return PARSE_ERROR;
- }
-
- ret = parseCrlf(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- sum += ret;
- return sum;
- }
-
- /**
- * "TYPE" [ws] = [ws] ptypeval
- */
- private int parseParam0(int offset) {
- int ret = 0, sum = 0, start = offset;
-
- ret = parseString(offset, "TYPE", true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamType(mBuffer.substring(start, offset));
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, "=", false);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parsePtypeval(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
- return sum;
- }
-
- /**
- * ["VALUE" [ws] "=" [ws]] pvalueval
- */
- private int parseParam1(int offset) {
- int ret = 0, sum = 0, start = offset;
- boolean flag = false;
-
- ret = parseString(offset, "VALUE", true);
- if (PARSE_ERROR != ret) {
- offset += ret;
- sum += ret;
- flag = true;
- }
- if (flag == true && mBuilder != null) {
- mBuilder.propertyParamType(mBuffer.substring(start, offset));
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, "=", true);
- if (PARSE_ERROR != ret) {
- if (flag == false) { // "VALUE" does not exist
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- } else {
- if (flag == true) { // "VALUE" exists
- return PARSE_ERROR;
- }
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parsePValueVal(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
-
- return sum;
- }
-
- /** ["ENCODING" [ws] "=" [ws]] pencodingval */
- private int parseParam2(int offset) {
- int ret = 0, sum = 0, start = offset;
- boolean flag = false;
-
- ret = parseString(offset, "ENCODING", true);
- if (PARSE_ERROR != ret) {
- offset += ret;
- sum += ret;
- flag = true;
- }
- if (flag == true && mBuilder != null) {
- mBuilder.propertyParamType(mBuffer.substring(start, offset));
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, "=", true);
- if (PARSE_ERROR != ret) {
- if (flag == false) { // "VALUE" does not exist
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- } else {
- if (flag == true) { // "VALUE" exists
- return PARSE_ERROR;
- }
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parsePEncodingVal(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
-
- return sum;
- }
-
- /**
- * "CHARSET" [WS] "=" [WS] charsetval
- */
- private int parseParam3(int offset) {
- int ret = 0, sum = 0, start = offset;
-
- ret = parseString(offset, "CHARSET", true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamType(mBuffer.substring(start, offset));
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, "=", true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parseCharsetVal(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
-
- return sum;
- }
-
- /**
- * "LANGUAGE" [ws] "=" [ws] langval
- */
- private int parseParam4(int offset) {
- int ret = 0, sum = 0, start = offset;
-
- ret = parseString(offset, "LANGUAGE", true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamType(mBuffer.substring(start, offset));
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, "=", true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parseLangVal(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
-
- return sum;
- }
-
- /**
- * "ROLE" [ws] "=" [ws] roleval
- */
- private int parseParam5(int offset) {
- int ret = 0, sum = 0, start = offset;
-
- ret = parseString(offset, "ROLE", true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamType(mBuffer.substring(start, offset));
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, "=", true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parseRoleVal(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
-
- return sum;
- }
-
- /**
- * "STATUS" [ws] = [ws] statuval
- */
- private int parseParam6(int offset) {
- int ret = 0, sum = 0, start = offset;
-
- ret = parseString(offset, "STATUS", true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamType(mBuffer.substring(start, offset));
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, "=", true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parseStatuVal(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
-
- return sum;
-
- }
-
- /**
- * XWord [ws] "=" [ws] word
- */
- private int parseParam7(int offset) {
- int ret = 0, sum = 0, start = offset;
-
- ret = parseXWord(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamType(mBuffer.substring(start, offset));
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, "=", true);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parseWord(offset);
- if (PARSE_ERROR == ret) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
-
- return sum;
-
- }
-
- /*
- * "WAVE" / "PCM" / "VCARD" / XWORD
- */
- private int parseKnownType(int offset) {
- int ret = 0;
-
- ret = parseString(offset, "WAVE", true);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseString(offset, "PCM", true);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseString(offset, "VCARD", true);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseXWord(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- return PARSE_ERROR;
- }
-
- /*
- * knowntype / Xword
- */
- private int parsePtypeval(int offset) {
- int ret = 0;
-
- ret = parseKnownType(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseXWord(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- return PARSE_ERROR;
- }
-
- /**
- * "ATTENDEE" / "ORGANIZER" / "OWNER" / XWORD
- */
- private int parseRoleVal(int offset) {
- int ret = 0;
-
- ret = parseString(offset, "ATTENDEE", true);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseString(offset, "ORGANIZER", true);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseString(offset, "OWNER", true);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseXWord(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- return PARSE_ERROR;
- }
-
- /**
- * "ACCEPTED" / "NEED ACTION" / "SENT" / "TENTATIVE" / "CONFIRMED" /
- * "DECLINED" / "COMPLETED" / "DELEGATED / XWORD
- */
- private int parseStatuVal(int offset) {
- int ret = 0;
-
- ret = parseString(offset, "ACCEPTED", true);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseString(offset, "NEED ACTION", true);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseString(offset, "TENTATIVE", true);
- if (PARSE_ERROR != ret) {
- return ret;
- }
- ret = parseString(offset, "CONFIRMED", true);
- if (PARSE_ERROR != ret) {
- return ret;
- }
- ret = parseString(offset, "DECLINED", true);
- if (PARSE_ERROR != ret) {
- return ret;
- }
- ret = parseString(offset, "COMPLETED", true);
- if (PARSE_ERROR != ret) {
- return ret;
- }
- ret = parseString(offset, "DELEGATED", true);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- ret = parseXWord(offset);
- if (PARSE_ERROR != ret) {
- return ret;
- }
-
- return PARSE_ERROR;
- }
-
- /**
- * Check 4 special propName and it's value to match Hash.
- *
- * @return PARSE_ERROR:value not match. 1:go on,like nothing happen.
- */
- private int valueFilter(String propName, ArrayList<String> values) {
- if (propName == null || propName.equals("") || values == null
- || values.isEmpty())
- return 1; // go on, like nothing happen.
-
- if (mSpecialValueSetMap.containsKey(propName)) {
- for (String value : values) {
- if (!mSpecialValueSetMap.get(propName).contains(value)) {
- if (!value.startsWith("X-"))
- return PARSE_ERROR;
- }
- }
- }
-
- return 1;
- }
-
- /**
- *
- * Translate escape characters("\\", "\;") which define in vcalendar1.0
- * spec. But for fault tolerance, we will translate "\:" and "\,", which
- * isn't define in vcalendar1.0 explicitly, as the same behavior as other
- * client.
- *
- * Though vcalendar1.0 spec does not defined the value of property
- * "description", "summary", "aalarm", "dalarm", "malarm" and "palarm" could
- * contain escape characters, we do support escape characters in these
- * properties.
- *
- * @param str:
- * the value string will be translated.
- * @return the string which do not contain any escape character in
- * vcalendar1.0
- */
- private String exportEntpropValue(String propName, String str) {
- if (null == propName || null == str)
- return null;
- if ("".equals(propName) || "".equals(str))
- return "";
-
- if (!mEscAllowedProps.contains(propName))
- return str;
-
- String tmp = str.replace("\\\\", "\n\r\n");
- tmp = tmp.replace("\\;", ";");
- tmp = tmp.replace("\\:", ":");
- tmp = tmp.replace("\\,", ",");
- tmp = tmp.replace("\n\r\n", "\\");
- return tmp;
- }
-}
diff --git a/core/java/android/syncml/pim/vcalendar/VCalParser_V20.java b/core/java/android/syncml/pim/vcalendar/VCalParser_V20.java
deleted file mode 100644
index 5748379..0000000
--- a/core/java/android/syncml/pim/vcalendar/VCalParser_V20.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim.vcalendar;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.HashSet;
-
-import android.syncml.pim.VBuilder;
-
-public class VCalParser_V20 extends VCalParser_V10 {
- private static final String V10LINEBREAKER = "\r\n";
-
- private static final HashSet<String> acceptableComponents = new HashSet<String>(
- Arrays.asList("VEVENT", "VTODO", "VALARM", "VTIMEZONE"));
-
- private static final HashSet<String> acceptableV20Props = new HashSet<String>(
- Arrays.asList("DESCRIPTION", "DTEND", "DTSTART", "DUE",
- "COMPLETED", "RRULE", "STATUS", "SUMMARY", "LOCATION"));
-
- private boolean hasTZ = false; // MUST only have one TZ property
-
- private String[] lines;
-
- private int index;
-
- @Override
- public boolean parse(InputStream is, String encoding, VBuilder builder)
- throws IOException {
- // get useful info for android calendar, and alter to vcal 1.0
- byte[] bytes = new byte[is.available()];
- is.read(bytes);
- String scStr = new String(bytes);
- StringBuilder v10str = new StringBuilder("");
-
- lines = splitProperty(scStr);
- index = 0;
-
- if ("BEGIN:VCALENDAR".equals(lines[index]))
- v10str.append("BEGIN:VCALENDAR" + V10LINEBREAKER);
- else
- return false;
- index++;
- if (false == parseV20Calbody(lines, v10str)
- || index > lines.length - 1)
- return false;
-
- if (lines.length - 1 == index && "END:VCALENDAR".equals(lines[index]))
- v10str.append("END:VCALENDAR" + V10LINEBREAKER);
- else
- return false;
-
- return super.parse(
- // use vCal 1.0 parser
- new ByteArrayInputStream(v10str.toString().getBytes()),
- encoding, builder);
- }
-
- /**
- * Parse and pick acceptable iCalendar body and translate it to
- * calendarV1.0 format.
- * @param lines iCalendar components/properties line list.
- * @param buffer calendarV10 format string buffer
- * @return true for success, or false
- */
- private boolean parseV20Calbody(String[] lines, StringBuilder buffer) {
- try {
- while (!"VERSION:2.0".equals(lines[index]))
- index++;
- buffer.append("VERSION:1.0" + V10LINEBREAKER);
-
- index++;
- for (; index < lines.length - 1; index++) {
- String[] keyAndValue = lines[index].split(":", 2);
- String key = keyAndValue[0];
- String value = keyAndValue[1];
-
- if ("BEGIN".equals(key.trim())) {
- if (!key.equals(key.trim()))
- return false; // MUST be "BEGIN:componentname"
- index++;
- if (false == parseV20Component(value, buffer))
- return false;
- }
- }
- } catch (ArrayIndexOutOfBoundsException e) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Parse and pick acceptable calendar V2.0's component and translate it to
- * V1.0 format.
- * @param compName component name
- * @param buffer calendarV10 format string buffer
- * @return true for success, or false
- * @throws ArrayIndexOutOfBoundsException
- */
- private boolean parseV20Component(String compName, StringBuilder buffer)
- throws ArrayIndexOutOfBoundsException {
- String endTag = "END:" + compName;
- String[] propAndValue;
- String propName, value;
-
- if (acceptableComponents.contains(compName)) {
- if ("VEVENT".equals(compName) || "VTODO".equals(compName)) {
- buffer.append("BEGIN:" + compName + V10LINEBREAKER);
- while (!endTag.equals(lines[index])) {
- propAndValue = lines[index].split(":", 2);
- propName = propAndValue[0].split(";", 2)[0];
- value = propAndValue[1];
-
- if ("".equals(lines[index]))
- buffer.append(V10LINEBREAKER);
- else if (acceptableV20Props.contains(propName)) {
- buffer.append(propName + ":" + value + V10LINEBREAKER);
- } else if ("BEGIN".equals(propName.trim())) {
- // MUST be BEGIN:VALARM
- if (propName.equals(propName.trim())
- && "VALARM".equals(value)) {
- buffer.append("AALARM:default" + V10LINEBREAKER);
- while (!"END:VALARM".equals(lines[index]))
- index++;
- } else
- return false;
- }
- index++;
- } // end while
- buffer.append(endTag + V10LINEBREAKER);
- } else if ("VALARM".equals(compName)) { // VALARM component MUST
- // only appear within either VEVENT or VTODO
- return false;
- } else if ("VTIMEZONE".equals(compName)) {
- do {
- if (false == hasTZ) {// MUST only have 1 time TZ property
- propAndValue = lines[index].split(":", 2);
- propName = propAndValue[0].split(";", 2)[0];
-
- if ("TZOFFSETFROM".equals(propName)) {
- value = propAndValue[1];
- buffer.append("TZ" + ":" + value + V10LINEBREAKER);
- hasTZ = true;
- }
- }
- index++;
- } while (!endTag.equals(lines[index]));
- } else
- return false;
- } else {
- while (!endTag.equals(lines[index]))
- index++;
- }
-
- return true;
- }
-
- /** split ever property line to String[], not split folding line. */
- private String[] splitProperty(String scStr) {
- /*
- * Property splitted by \n, and unfold folding lines by removing
- * CRLF+LWSP-char
- */
- scStr = scStr.replaceAll("\r\n", "\n").replaceAll("\n ", "")
- .replaceAll("\n\t", "");
- String[] strs = scStr.split("\n");
- return strs;
- }
-}
diff --git a/core/java/android/syncml/pim/vcalendar/package.html b/core/java/android/syncml/pim/vcalendar/package.html
deleted file mode 100644
index cb4ca46..0000000
--- a/core/java/android/syncml/pim/vcalendar/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<HTML>
-<BODY>
-Support classes for SyncML.
-{@hide}
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/core/java/android/syncml/pim/vcard/ContactStruct.java b/core/java/android/syncml/pim/vcard/ContactStruct.java
deleted file mode 100644
index 8d9b7fa..0000000
--- a/core/java/android/syncml/pim/vcard/ContactStruct.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim.vcard;
-
-import java.util.List;
-import java.util.ArrayList;
-
-/**
- * The parameter class of VCardCreator.
- * This class standy by the person-contact in
- * Android system, we must use this class instance as parameter to transmit to
- * VCardCreator so that create vCard string.
- */
-// TODO: rename the class name, next step
-public class ContactStruct {
- public String company;
- /** MUST exist */
- public String name;
- /** maybe folding */
- public String notes;
- /** maybe folding */
- public String title;
- /** binary bytes of pic. */
- public byte[] photoBytes;
- /** mime_type col of images table */
- public String photoType;
- /** Only for GET. Use addPhoneList() to PUT. */
- public List<PhoneData> phoneList;
- /** Only for GET. Use addContactmethodList() to PUT. */
- public List<ContactMethod> contactmethodList;
-
- public static class PhoneData{
- /** maybe folding */
- public String data;
- public String type;
- public String label;
- }
-
- public static class ContactMethod{
- public String kind;
- public String type;
- public String data;
- public String label;
- }
-
- /**
- * Add a phone info to phoneList.
- * @param data phone number
- * @param type type col of content://contacts/phones
- * @param label lable col of content://contacts/phones
- */
- public void addPhone(String data, String type, String label){
- if(phoneList == null)
- phoneList = new ArrayList<PhoneData>();
- PhoneData st = new PhoneData();
- st.data = data;
- st.type = type;
- st.label = label;
- phoneList.add(st);
- }
- /**
- * Add a contactmethod info to contactmethodList.
- * @param data contact data
- * @param type type col of content://contacts/contact_methods
- */
- public void addContactmethod(String kind, String data, String type,
- String label){
- if(contactmethodList == null)
- contactmethodList = new ArrayList<ContactMethod>();
- ContactMethod st = new ContactMethod();
- st.kind = kind;
- st.data = data;
- st.type = type;
- st.label = label;
- contactmethodList.add(st);
- }
-}
diff --git a/core/java/android/syncml/pim/vcard/VCardComposer.java b/core/java/android/syncml/pim/vcard/VCardComposer.java
deleted file mode 100644
index 05e8f40..0000000
--- a/core/java/android/syncml/pim/vcard/VCardComposer.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim.vcard;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.codec.binary.Base64;
-
-import android.provider.Contacts;
-import android.syncml.pim.vcard.ContactStruct.PhoneData;
-
-/**
- * Compose VCard string
- */
-public class VCardComposer {
- final public static int VERSION_VCARD21_INT = 1;
-
- final public static int VERSION_VCARD30_INT = 2;
-
- /**
- * A new line
- */
- private String mNewline;
-
- /**
- * The composed string
- */
- private StringBuilder mResult;
-
- /**
- * The email's type
- */
- static final private HashSet<String> emailTypes = new HashSet<String>(
- Arrays.asList("CELL", "AOL", "APPLELINK", "ATTMAIL", "CIS",
- "EWORLD", "INTERNET", "IBMMAIL", "MCIMAIL", "POWERSHARE",
- "PRODIGY", "TLX", "X400"));
-
- static final private HashSet<String> phoneTypes = new HashSet<String>(
- Arrays.asList("PREF", "WORK", "HOME", "VOICE", "FAX", "MSG",
- "CELL", "PAGER", "BBS", "MODEM", "CAR", "ISDN", "VIDEO"));
-
- static final private String TAG = "VCardComposer";
-
- public VCardComposer() {
- }
-
- private static final HashMap<Integer, String> phoneTypeMap = new HashMap<Integer, String>();
-
- private static final HashMap<Integer, String> emailTypeMap = new HashMap<Integer, String>();
-
- static {
- phoneTypeMap.put(Contacts.Phones.TYPE_HOME, "HOME");
- phoneTypeMap.put(Contacts.Phones.TYPE_MOBILE, "CELL");
- phoneTypeMap.put(Contacts.Phones.TYPE_WORK, "WORK");
- // FAX_WORK not exist in vcard spec. The approximate is the combine of
- // WORK and FAX, here only map to FAX
- phoneTypeMap.put(Contacts.Phones.TYPE_FAX_WORK, "WORK;FAX");
- phoneTypeMap.put(Contacts.Phones.TYPE_FAX_HOME, "HOME;FAX");
- phoneTypeMap.put(Contacts.Phones.TYPE_PAGER, "PAGER");
- phoneTypeMap.put(Contacts.Phones.TYPE_OTHER, "X-OTHER");
- emailTypeMap.put(Contacts.ContactMethods.TYPE_HOME, "HOME");
- emailTypeMap.put(Contacts.ContactMethods.TYPE_WORK, "WORK");
- }
-
- /**
- * Create a vCard String.
- *
- * @param struct
- * see more from ContactStruct class
- * @param vcardversion
- * MUST be VERSION_VCARD21 /VERSION_VCARD30
- * @return vCard string
- * @throws VCardException
- * struct.name is null /vcardversion not match
- */
- public String createVCard(ContactStruct struct, int vcardversion)
- throws VCardException {
-
- mResult = new StringBuilder();
- // check exception:
- if (struct.name == null || struct.name.trim().equals("")) {
- throw new VCardException(" struct.name MUST have value.");
- }
- if (vcardversion == VERSION_VCARD21_INT) {
- mNewline = "\r\n";
- } else if (vcardversion == VERSION_VCARD30_INT) {
- mNewline = "\n";
- } else {
- throw new VCardException(
- " version not match VERSION_VCARD21 or VERSION_VCARD30.");
- }
- // build vcard:
- mResult.append("BEGIN:VCARD").append(mNewline);
-
- if (vcardversion == VERSION_VCARD21_INT) {
- mResult.append("VERSION:2.1").append(mNewline);
- } else {
- mResult.append("VERSION:3.0").append(mNewline);
- }
-
- if (!isNull(struct.name)) {
- appendNameStr(struct.name);
- }
-
- if (!isNull(struct.company)) {
- mResult.append("ORG:").append(struct.company).append(mNewline);
- }
-
- if (!isNull(struct.notes)) {
- mResult.append("NOTE:").append(
- foldingString(struct.notes, vcardversion)).append(mNewline);
- }
-
- if (!isNull(struct.title)) {
- mResult.append("TITLE:").append(
- foldingString(struct.title, vcardversion)).append(mNewline);
- }
-
- if (struct.photoBytes != null) {
- appendPhotoStr(struct.photoBytes, struct.photoType, vcardversion);
- }
-
- if (struct.phoneList != null) {
- appendPhoneStr(struct.phoneList, vcardversion);
- }
-
- if (struct.contactmethodList != null) {
- appendContactMethodStr(struct.contactmethodList, vcardversion);
- }
-
- mResult.append("END:VCARD").append(mNewline);
- return mResult.toString();
- }
-
- /**
- * Alter str to folding supported format.
- *
- * @param str
- * the string to be folded
- * @param version
- * the vcard version
- * @return the folded string
- */
- private String foldingString(String str, int version) {
- if (str.endsWith("\r\n")) {
- str = str.substring(0, str.length() - 2);
- } else if (str.endsWith("\n")) {
- str = str.substring(0, str.length() - 1);
- } else {
- return null;
- }
-
- str = str.replaceAll("\r\n", "\n");
- if (version == VERSION_VCARD21_INT) {
- return str.replaceAll("\n", "\r\n ");
- } else if (version == VERSION_VCARD30_INT) {
- return str.replaceAll("\n", "\n ");
- } else {
- return null;
- }
- }
-
- /**
- * Build LOGO property. format LOGO's param and encode value as base64.
- *
- * @param bytes
- * the binary string to be converted
- * @param type
- * the type of the content
- * @param version
- * the version of vcard
- */
- private void appendPhotoStr(byte[] bytes, String type, int version)
- throws VCardException {
- String value, apptype, encodingStr;
- try {
- value = foldingString(new String(Base64.encodeBase64(bytes, true)),
- version);
- } catch (Exception e) {
- throw new VCardException(e.getMessage());
- }
-
- if (isNull(type)) {
- type = "image/jpeg";
- }
- if (type.indexOf("jpeg") > 0) {
- apptype = "JPEG";
- } else if (type.indexOf("gif") > 0) {
- apptype = "GIF";
- } else if (type.indexOf("bmp") > 0) {
- apptype = "BMP";
- } else {
- apptype = type.substring(type.indexOf("/")).toUpperCase();
- }
-
- mResult.append("LOGO;TYPE=").append(apptype);
- if (version == VERSION_VCARD21_INT) {
- encodingStr = ";ENCODING=BASE64:";
- value = value + mNewline;
- } else if (version == VERSION_VCARD30_INT) {
- encodingStr = ";ENCODING=b:";
- } else {
- return;
- }
- mResult.append(encodingStr).append(value).append(mNewline);
- }
-
- private boolean isNull(String str) {
- if (str == null || str.trim().equals("")) {
- return true;
- }
- return false;
- }
-
- /**
- * Build FN and N property. format N's value.
- *
- * @param name
- * the name of the contact
- */
- private void appendNameStr(String name) {
- mResult.append("FN:").append(name).append(mNewline);
- mResult.append("N:").append(name).append(mNewline);
- /*
- * if(name.indexOf(";") > 0)
- * mResult.append("N:").append(name).append(mNewline); else
- * if(name.indexOf(" ") > 0) mResult.append("N:").append(name.replace(' ',
- * ';')). append(mNewline); else
- * mResult.append("N:").append(name).append("; ").append(mNewline);
- */
- }
-
- /** Loop append TEL property. */
- private void appendPhoneStr(List<ContactStruct.PhoneData> phoneList,
- int version) {
- HashMap<String, String> numMap = new HashMap<String, String>();
- String joinMark = version == VERSION_VCARD21_INT ? ";" : ",";
-
- for (ContactStruct.PhoneData phone : phoneList) {
- String type;
- if (!isNull(phone.data)) {
- type = getPhoneTypeStr(phone);
- if (version == VERSION_VCARD30_INT && type.indexOf(";") != -1) {
- type = type.replace(";", ",");
- }
- if (numMap.containsKey(phone.data)) {
- type = numMap.get(phone.data) + joinMark + type;
- }
- numMap.put(phone.data, type);
- }
- }
-
- for (Map.Entry<String, String> num : numMap.entrySet()) {
- if (version == VERSION_VCARD21_INT) {
- mResult.append("TEL;");
- } else { // vcard3.0
- mResult.append("TEL;TYPE=");
- }
- mResult.append(num.getValue()).append(":").append(num.getKey())
- .append(mNewline);
- }
- }
-
- private String getPhoneTypeStr(PhoneData phone) {
-
- int phoneType = Integer.parseInt(phone.type);
- String typeStr, label;
-
- if (phoneTypeMap.containsKey(phoneType)) {
- typeStr = phoneTypeMap.get(phoneType);
- } else if (phoneType == Contacts.Phones.TYPE_CUSTOM) {
- label = phone.label.toUpperCase();
- if (phoneTypes.contains(label) || label.startsWith("X-")) {
- typeStr = label;
- } else {
- typeStr = "X-CUSTOM-" + label;
- }
- } else {
- // TODO: need be updated with the provider's future changes
- typeStr = "VOICE"; // the default type is VOICE in spec.
- }
- return typeStr;
- }
-
- /** Loop append ADR / EMAIL property. */
- private void appendContactMethodStr(
- List<ContactStruct.ContactMethod> contactMList, int version) {
-
- HashMap<String, String> emailMap = new HashMap<String, String>();
- String joinMark = version == VERSION_VCARD21_INT ? ";" : ",";
- for (ContactStruct.ContactMethod contactMethod : contactMList) {
- // same with v2.1 and v3.0
- switch (Integer.parseInt(contactMethod.kind)) {
- case Contacts.KIND_EMAIL:
- String mailType = "INTERNET";
- if (!isNull(contactMethod.data)) {
- int methodType = new Integer(contactMethod.type).intValue();
- if (emailTypeMap.containsKey(methodType)) {
- mailType = emailTypeMap.get(methodType);
- } else if (emailTypes.contains(contactMethod.label
- .toUpperCase())) {
- mailType = contactMethod.label.toUpperCase();
- }
- if (emailMap.containsKey(contactMethod.data)) {
- mailType = emailMap.get(contactMethod.data) + joinMark
- + mailType;
- }
- emailMap.put(contactMethod.data, mailType);
- }
- break;
- case Contacts.KIND_POSTAL:
- if (!isNull(contactMethod.data)) {
- mResult.append("ADR;TYPE=POSTAL:").append(
- foldingString(contactMethod.data, version)).append(
- mNewline);
- }
- break;
- default:
- break;
- }
- }
- for (Map.Entry<String, String> email : emailMap.entrySet()) {
- if (version == VERSION_VCARD21_INT) {
- mResult.append("EMAIL;");
- } else {
- mResult.append("EMAIL;TYPE=");
- }
- mResult.append(email.getValue()).append(":").append(email.getKey())
- .append(mNewline);
- }
- }
-}
diff --git a/core/java/android/syncml/pim/vcard/VCardException.java b/core/java/android/syncml/pim/vcard/VCardException.java
deleted file mode 100644
index 35b31ec..0000000
--- a/core/java/android/syncml/pim/vcard/VCardException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim.vcard;
-
-public class VCardException extends java.lang.Exception{
- // constructors
-
- /**
- * Constructs a VCardException object
- */
-
- public VCardException()
- {
- }
-
- /**
- * Constructs a VCardException object
- *
- * @param message the error message
- */
-
- public VCardException( String message )
- {
- super( message );
- }
-
-}
diff --git a/core/java/android/syncml/pim/vcard/VCardParser.java b/core/java/android/syncml/pim/vcard/VCardParser.java
deleted file mode 100644
index 3926243..0000000
--- a/core/java/android/syncml/pim/vcard/VCardParser.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim.vcard;
-
-import android.syncml.pim.VDataBuilder;
-import android.syncml.pim.VParser;
-import android.util.Config;
-import android.util.Log;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-
-public class VCardParser {
-
- VParser mParser = null;
-
- public final static String VERSION_VCARD21 = "vcard2.1";
-
- public final static String VERSION_VCARD30 = "vcard3.0";
-
- final public static int VERSION_VCARD21_INT = 1;
-
- final public static int VERSION_VCARD30_INT = 2;
-
- String mVersion = null;
-
- static final private String TAG = "VCardParser";
-
- public VCardParser() {
- }
-
- /**
- * If version not given. Search from vcard string of the VERSION property.
- * Then instance mParser to appropriate parser.
- *
- * @param vcardStr
- * the content of vcard data
- */
- private void judgeVersion(String vcardStr) {
- if (mVersion == null) {// auto judge
- int verIdx = vcardStr.indexOf("\nVERSION:");
- if (verIdx == -1) // if not have VERSION, v2.1 default
- mVersion = VERSION_VCARD21;
- else {
- String verStr = vcardStr.substring(verIdx, vcardStr.indexOf(
- "\n", verIdx + 1));
- if (verStr.indexOf("2.1") > 0)
- mVersion = VERSION_VCARD21;
- else if (verStr.indexOf("3.0") > 0)
- mVersion = VERSION_VCARD30;
- else
- mVersion = VERSION_VCARD21;
- }
- }
- if (mVersion.equals(VERSION_VCARD21))
- mParser = new VCardParser_V21();
- if (mVersion.equals(VERSION_VCARD30))
- mParser = new VCardParser_V30();
- }
-
- /**
- * To make sure the vcard string has proper wrap character
- *
- * @param vcardStr
- * the string to be checked
- * @return string after verified
- */
- private String verifyVCard(String vcardStr) {
- this.judgeVersion(vcardStr);
- // -- indent line:
- vcardStr = vcardStr.replaceAll("\r\n", "\n");
- String[] strlist = vcardStr.split("\n");
- StringBuilder v21str = new StringBuilder("");
- for (int i = 0; i < strlist.length; i++) {
- if (strlist[i].indexOf(":") < 0) {
- if (strlist[i].length() == 0 && strlist[i + 1].indexOf(":") > 0)
- v21str.append(strlist[i]).append("\r\n");
- else
- v21str.append(" ").append(strlist[i]).append("\r\n");
- } else
- v21str.append(strlist[i]).append("\r\n");
- }
- return v21str.toString();
- }
-
- /**
- * Set current version
- *
- * @param version
- * the new version
- */
- private void setVersion(String version) {
- this.mVersion = version;
- }
-
- /**
- * Parse the given vcard string
- *
- * @param vcardStr
- * to content to be parsed
- * @param builder
- * the data builder to hold data
- * @return true if the string is successfully parsed, else return false
- * @throws VCardException
- * @throws IOException
- */
- public boolean parse(String vcardStr, VDataBuilder builder)
- throws VCardException, IOException {
-
- vcardStr = this.verifyVCard(vcardStr);
-
- boolean isSuccess = mParser.parse(new ByteArrayInputStream(vcardStr
- .getBytes()), "US-ASCII", builder);
- if (!isSuccess) {
- if (mVersion.equals(VERSION_VCARD21)) {
- if (Config.LOGD)
- Log.d(TAG, "Parse failed for vCard 2.1 parser."
- + " Try to use 3.0 parser.");
-
- this.setVersion(VERSION_VCARD30);
-
- return this.parse(vcardStr, builder);
- }
- throw new VCardException("parse failed.(even use 3.0 parser)");
- }
- return true;
- }
-}
diff --git a/core/java/android/syncml/pim/vcard/VCardParser_V21.java b/core/java/android/syncml/pim/vcard/VCardParser_V21.java
deleted file mode 100644
index b6fa032..0000000
--- a/core/java/android/syncml/pim/vcard/VCardParser_V21.java
+++ /dev/null
@@ -1,970 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim.vcard;
-
-import android.syncml.pim.VParser;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * This class is used to parse vcard. Please refer to vCard Specification 2.1
- */
-public class VCardParser_V21 extends VParser {
-
- /** Store the known-type */
- private static final HashSet<String> mKnownTypeSet = new HashSet<String>(
- Arrays.asList("DOM", "INTL", "POSTAL", "PARCEL", "HOME", "WORK",
- "PREF", "VOICE", "FAX", "MSG", "CELL", "PAGER", "BBS",
- "MODEM", "CAR", "ISDN", "VIDEO", "AOL", "APPLELINK",
- "ATTMAIL", "CIS", "EWORLD", "INTERNET", "IBMMAIL",
- "MCIMAIL", "POWERSHARE", "PRODIGY", "TLX", "X400", "GIF",
- "CGM", "WMF", "BMP", "MET", "PMB", "DIB", "PICT", "TIFF",
- "PDF", "PS", "JPEG", "QTIME", "MPEG", "MPEG2", "AVI",
- "WAVE", "AIFF", "PCM", "X509", "PGP"));
-
- /** Store the name */
- private static final HashSet<String> mName = new HashSet<String>(Arrays
- .asList("LOGO", "PHOTO", "LABEL", "FN", "TITLE", "SOUND",
- "VERSION", "TEL", "EMAIL", "TZ", "GEO", "NOTE", "URL",
- "BDAY", "ROLE", "REV", "UID", "KEY", "MAILER"));
-
- /**
- * Create a new VCard parser.
- */
- public VCardParser_V21() {
- super();
- }
-
- /**
- * Parse the file at the given position
- *
- * @param offset
- * the given position to parse
- * @return vcard length
- */
- protected int parseVFile(int offset) {
- return parseVCardFile(offset);
- }
-
- /**
- * [wsls] vcard [wsls]
- */
- int parseVCardFile(int offset) {
- int ret = 0, sum = 0;
-
- /* remove \t \r\n */
- while ((ret = parseWsls(offset)) != PARSE_ERROR) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseVCard(offset); // BEGIN:VCARD ... END:VCARD
- if (ret != PARSE_ERROR) {
- offset += ret;
- sum += ret;
- } else {
- return PARSE_ERROR;
- }
-
- /* remove \t \r\n */
- while ((ret = parseWsls(offset)) != PARSE_ERROR) {
- offset += ret;
- sum += ret;
- }
- return sum;
- }
-
- /**
- * "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF items *CRLF "END" [ws] ":"
- * "VCARD"
- */
- private int parseVCard(int offset) {
- int ret = 0, sum = 0;
-
- /* BEGIN */
- ret = parseString(offset, "BEGIN", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- /* [ws] */
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- /* colon */
- ret = parseString(offset, ":", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- /* [ws] */
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- /* VCARD */
- ret = parseString(offset, "VCARD", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.startRecord("VCARD");
- }
-
- /* [ws] */
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- /* 1*CRLF */
- ret = parseCrlf(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- while ((ret = parseCrlf(offset)) != PARSE_ERROR) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseItems(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- /* *CRLF */
- while ((ret = parseCrlf(offset)) != PARSE_ERROR) {
- offset += ret;
- sum += ret;
- }
-
- /* END */
- ret = parseString(offset, "END", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- /* [ws] */
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- /* colon */
- ret = parseString(offset, ":", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- /* [ws] */
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- /* VCARD */
- ret = parseString(offset, "VCARD", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- // offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.endRecord();
- }
-
- return sum;
- }
-
- /**
- * items *CRLF item / item
- */
- private int parseItems(int offset) {
- /* items *CRLF item / item */
- int ret = 0, sum = 0;
-
- if (mBuilder != null) {
- mBuilder.startProperty();
- }
- ret = parseItem(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.endProperty();
- }
-
- for (;;) {
- while ((ret = parseCrlf(offset)) != PARSE_ERROR) {
- offset += ret;
- sum += ret;
- }
- // follow VCARD ,it wont reach endProperty
- if (mBuilder != null) {
- mBuilder.startProperty();
- }
-
- ret = parseItem(offset);
- if (ret == PARSE_ERROR) {
- break;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.endProperty();
- }
- }
-
- return sum;
- }
-
- /**
- * item0 / item1 / item2
- */
- private int parseItem(int offset) {
- int ret = 0, sum = 0;
- mEncoding = mDefaultEncoding;
-
- ret = parseItem0(offset);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseItem1(offset);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseItem2(offset);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- return PARSE_ERROR;
- }
-
- /** [groups "."] name [params] ":" value CRLF */
- private int parseItem0(int offset) {
- int ret = 0, sum = 0, start = offset;
- String proName = "", proValue = "";
-
- ret = parseGroupsWithDot(offset);
- if (ret != PARSE_ERROR) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseName(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- proName = mBuffer.substring(start, offset).trim();
- mBuilder.propertyName(proName);
- }
-
- ret = parseParams(offset);
- if (ret != PARSE_ERROR) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseString(offset, ":", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parseValue(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- proValue = mBuffer.substring(start, offset);
- if (proName.equals("VERSION") && !proValue.equals("2.1")) {
- return PARSE_ERROR;
- }
- if (mBuilder != null) {
- ArrayList<String> v = new ArrayList<String>();
- v.add(proValue);
- mBuilder.propertyValues(v);
- }
-
- ret = parseCrlf(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- sum += ret;
-
- return sum;
- }
-
- /** "ADR" "ORG" "N" with semi-colon separated content */
- private int parseItem1(int offset) {
- int ret = 0, sum = 0, start = offset;
-
- ret = parseGroupsWithDot(offset);
- if (ret != PARSE_ERROR) {
- offset += ret;
- sum += ret;
- }
-
- if ((ret = parseString(offset, "ADR", true)) == PARSE_ERROR
- && (ret = parseString(offset, "ORG", true)) == PARSE_ERROR
- && (ret = parseString(offset, "N", true)) == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyName(mBuffer.substring(start, offset).trim());
- }
-
- ret = parseParams(offset);
- if (ret != PARSE_ERROR) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseString(offset, ":", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parseValue(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- int end = 0;
- ArrayList<String> v = new ArrayList<String>();
- Pattern p = Pattern
- .compile("([^;\\\\]*(\\\\[\\\\;:,])*[^;\\\\]*)(;?)");
- Matcher m = p.matcher(mBuffer.substring(start, offset));
- while (m.find()) {
- String s = escapeTranslator(m.group(1));
- v.add(s);
- end = m.end();
- if (offset == start + end) {
- String endValue = m.group(3);
- if (";".equals(endValue)) {
- v.add("");
- }
- break;
- }
- }
- mBuilder.propertyValues(v);
- }
-
- ret = parseCrlf(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- sum += ret;
-
- return sum;
- }
-
- /** [groups] "." "AGENT" [params] ":" vcard CRLF */
- private int parseItem2(int offset) {
- int ret = 0, sum = 0, start = offset;
-
- ret = parseGroupsWithDot(offset);
- if (ret != PARSE_ERROR) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseString(offset, "AGENT", true);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyName(mBuffer.substring(start, offset));
- }
-
- ret = parseParams(offset);
- if (ret != PARSE_ERROR) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseString(offset, ":", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = parseCrlf(offset);
- if (ret != PARSE_ERROR) {
- offset += ret;
- sum += ret;
- }
-
- ret = parseVCard(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyValues(new ArrayList<String>());
- }
-
- ret = parseCrlf(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- sum += ret;
-
- return sum;
- }
-
- private int parseGroupsWithDot(int offset) {
- int ret = 0, sum = 0;
- /* [groups "."] */
- ret = parseGroups(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, ".", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- sum += ret;
-
- return sum;
- }
-
- /** ";" [ws] paramlist */
- private int parseParams(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseString(offset, ";", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseParamList(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- sum += ret;
-
- return sum;
- }
-
- /**
- * paramlist [ws] ";" [ws] param / param
- */
- private int parseParamList(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseParam(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- int offsetTemp = offset;
- int sumTemp = sum;
- for (;;) {
- ret = removeWs(offsetTemp);
- offsetTemp += ret;
- sumTemp += ret;
-
- ret = parseString(offsetTemp, ";", false);
- if (ret == PARSE_ERROR) {
- return sum;
- }
- offsetTemp += ret;
- sumTemp += ret;
-
- ret = removeWs(offsetTemp);
- offsetTemp += ret;
- sumTemp += ret;
-
- ret = parseParam(offsetTemp);
- if (ret == PARSE_ERROR) {
- break;
- }
- offsetTemp += ret;
- sumTemp += ret;
-
- // offset = offsetTemp;
- sum = sumTemp;
- }
- return sum;
- }
-
- /**
- * param0 / param1 / param2 / param3 / param4 / param5 / knowntype<BR>
- * TYPE / VALUE / ENDCODING / CHARSET / LANGUAGE ...
- */
- private int parseParam(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseParam0(offset);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseParam1(offset);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseParam2(offset);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseParam3(offset);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseParam4(offset);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseParam5(offset);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- int start = offset;
- ret = parseKnownType(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamType(null);
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
-
- return sum;
- }
-
- /** "TYPE" [ws] "=" [ws] ptypeval */
- private int parseParam0(int offset) {
- int ret = 0, sum = 0, start = offset;
-
- ret = parseString(offset, "TYPE", true);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamType(mBuffer.substring(start, offset));
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, "=", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parsePTypeVal(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
-
- return sum;
-
- }
-
- /** "VALUE" [ws] "=" [ws] pvalueval */
- private int parseParam1(int offset) {
- int ret = 0, sum = 0, start = offset;
-
- ret = parseString(offset, "VALUE", true);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamType(mBuffer.substring(start, offset));
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, "=", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parsePValueVal(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
-
- return sum;
- }
-
- /** "ENCODING" [ws] "=" [ws] pencodingval */
- private int parseParam2(int offset) {
- int ret = 0, sum = 0, start = offset;
-
- ret = parseString(offset, "ENCODING", true);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamType(mBuffer.substring(start, offset));
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, "=", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parsePEncodingVal(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
-
- return sum;
-
- }
-
- /** "CHARSET" [ws] "=" [ws] charsetval */
- private int parseParam3(int offset) {
- int ret = 0, sum = 0, start = offset;
-
- ret = parseString(offset, "CHARSET", true);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamType(mBuffer.substring(start, offset));
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, "=", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parseCharsetVal(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
-
- return sum;
- }
-
- /** "LANGUAGE" [ws] "=" [ws] langval */
- private int parseParam4(int offset) {
- int ret = 0, sum = 0, start = offset;
-
- ret = parseString(offset, "LANGUAGE", true);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamType(mBuffer.substring(start, offset));
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, "=", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parseLangVal(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
-
- return sum;
-
- }
-
- /** "X-" word [ws] "=" [ws] word */
- private int parseParam5(int offset) {
- int ret = 0, sum = 0, start = offset;
-
- ret = parseXWord(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamType(mBuffer.substring(start, offset));
- }
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- ret = parseString(offset, "=", false);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- ret = removeWs(offset);
- offset += ret;
- sum += ret;
-
- start = offset;
- ret = parseWord(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
- if (mBuilder != null) {
- mBuilder.propertyParamValue(mBuffer.substring(start, offset));
- }
-
- return sum;
- }
-
- /**
- * knowntype: "DOM" / "INTL" / ...
- */
- private int parseKnownType(int offset) {
- String word = getWord(offset);
-
- if (mKnownTypeSet.contains(word.toUpperCase())) {
- return word.length();
- }
- return PARSE_ERROR;
- }
-
- /** knowntype / "X-" word */
- private int parsePTypeVal(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseKnownType(offset);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
-
- ret = parseXWord(offset);
- if (ret != PARSE_ERROR) {
- sum += ret;
- return sum;
- }
- sum += ret;
-
- return sum;
- }
-
- /** "LOGO" /.../ XWord, case insensitive */
- private int parseName(int offset) {
- int ret = 0;
- ret = parseXWord(offset);
- if (ret != PARSE_ERROR) {
- return ret;
- }
- String word = getWord(offset).toUpperCase();
- if (mName.contains(word)) {
- return word.length();
- }
- return PARSE_ERROR;
- }
-
- /** groups "." word / word */
- private int parseGroups(int offset) {
- int ret = 0, sum = 0;
-
- ret = parseWord(offset);
- if (ret == PARSE_ERROR) {
- return PARSE_ERROR;
- }
- offset += ret;
- sum += ret;
-
- for (;;) {
- ret = parseString(offset, ".", false);
- if (ret == PARSE_ERROR) {
- break;
- }
-
- int ret1 = parseWord(offset);
- if (ret1 == PARSE_ERROR) {
- break;
- }
- offset += ret + ret1;
- sum += ret + ret1;
- }
- return sum;
- }
-
- /**
- * Translate escape characters("\\", "\;") which define in vcard2.1 spec.
- * But for fault tolerance, we will translate "\:" and "\,", which isn't
- * define in vcard2.1 explicitly, as the same behavior as other client.
- *
- * @param str:
- * the string will be translated.
- * @return the string which do not contain any escape character in vcard2.1
- */
- private String escapeTranslator(String str) {
- if (null == str)
- return null;
-
- String tmp = str.replace("\\\\", "\n\r\n");
- tmp = tmp.replace("\\;", ";");
- tmp = tmp.replace("\\:", ":");
- tmp = tmp.replace("\\,", ",");
- tmp = tmp.replace("\n\r\n", "\\");
- return tmp;
- }
-}
diff --git a/core/java/android/syncml/pim/vcard/VCardParser_V30.java b/core/java/android/syncml/pim/vcard/VCardParser_V30.java
deleted file mode 100644
index c56cfed..0000000
--- a/core/java/android/syncml/pim/vcard/VCardParser_V30.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.syncml.pim.vcard;
-
-import android.syncml.pim.VBuilder;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-
-/**
- * This class is used to parse vcard3.0. <br>
- * It get useful data refer from android contact, and alter to vCard 2.1 format.
- * Then reuse vcard 2.1 parser to analyze the result.<br>
- * Please refer to vCard Specification 3.0
- */
-public class VCardParser_V30 extends VCardParser_V21 {
- private static final String V21LINEBREAKER = "\r\n";
-
- private static final HashSet<String> acceptablePropsWithParam = new HashSet<String>(
- Arrays.asList("PHOTO", "LOGO", "TEL", "EMAIL", "ADR"));
-
- private static final HashSet<String> acceptablePropsWithoutParam = new HashSet<String>(
- Arrays.asList("ORG", "NOTE", "TITLE", "FN", "N"));
-
- private static final HashMap<String, String> propV30ToV21Map = new HashMap<String, String>();
-
- static {
- propV30ToV21Map.put("PHOTO", "PHOTO");
- propV30ToV21Map.put("LOGO", "PHOTO");
- }
-
- @Override
- public boolean parse(InputStream is, String encoding, VBuilder builder)
- throws IOException {
- // get useful info for android contact, and alter to vCard 2.1
- byte[] bytes = new byte[is.available()];
- is.read(bytes);
- String scStr = new String(bytes);
- StringBuilder v21str = new StringBuilder("");
-
- String[] strlist = splitProperty(scStr);
-
- if ("BEGIN:vCard".equals(strlist[0])
- || "BEGIN:VCARD".equals(strlist[0])) {
- v21str.append("BEGIN:VCARD" + V21LINEBREAKER);
- } else {
- return false;
- }
-
- for (int i = 1; i < strlist.length - 1; i++) {// for ever property
- // line
- String propName;
- String params;
- String value;
-
- String line = strlist[i];
- if ("".equals(line)) { // line breaker is useful in encoding string
- v21str.append(V21LINEBREAKER);
- continue;
- }
-
- String[] contentline = line.split(":", 2);
- String propNameAndParam = contentline[0];
- value = (contentline.length > 1) ? contentline[1] : "";
- if (propNameAndParam.length() > 0) {
- String[] nameAndParams = propNameAndParam.split(";", 2);
- propName = nameAndParams[0];
- params = (nameAndParams.length > 1) ? nameAndParams[1] : "";
-
- if (acceptablePropsWithParam.contains(propName)
- || acceptablePropsWithoutParam.contains(propName)) {
- v21str.append(mapContentlineV30ToV21(propName, params,
- value));
- }
- }
- }// end for
-
- if ("END:vCard".equals(strlist[strlist.length - 1])
- || "END:VCARD".equals(strlist[strlist.length - 1])) {
- v21str.append("END:VCARD" + V21LINEBREAKER);
- } else {
- return false;
- }
-
- return super.parse(
- // use vCard 2.1 parser
- new ByteArrayInputStream(v21str.toString().getBytes()),
- encoding, builder);
- }
-
- /**
- * Convert V30 string to V21 string
- *
- * @param propName
- * The name of property
- * @param params
- * parameter of property
- * @param value
- * value of property
- * @return the converted string
- */
- private String mapContentlineV30ToV21(String propName, String params,
- String value) {
- String result;
-
- if (propV30ToV21Map.containsKey(propName)) {
- result = propV30ToV21Map.get(propName);
- } else {
- result = propName;
- }
- // Alter parameter part of property to vCard 2.1 format
- if (acceptablePropsWithParam.contains(propName) && params.length() > 0)
- result = result
- + ";"
- + params.replaceAll(",", ";").replaceAll("ENCODING=B",
- "ENCODING=BASE64").replaceAll("ENCODING=b",
- "ENCODING=BASE64");
-
- return result + ":" + value + V21LINEBREAKER;
- }
-
- /**
- * Split ever property line to Stringp[], not split folding line.
- *
- * @param scStr
- * the string to be splitted
- * @return a list of splitted string
- */
- private String[] splitProperty(String scStr) {
- /*
- * Property splitted by \n, and unfold folding lines by removing
- * CRLF+LWSP-char
- */
- scStr = scStr.replaceAll("\r\n", "\n").replaceAll("\n ", "")
- .replaceAll("\n\t", "");
- String[] strs = scStr.split("\n");
- return strs;
- }
-}
diff --git a/core/java/android/syncml/pim/vcard/package.html b/core/java/android/syncml/pim/vcard/package.html
deleted file mode 100644
index cb4ca46..0000000
--- a/core/java/android/syncml/pim/vcard/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<HTML>
-<BODY>
-Support classes for SyncML.
-{@hide}
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/core/java/android/test/AndroidTestCase.java b/core/java/android/test/AndroidTestCase.java
deleted file mode 100644
index 9bafa32..0000000
--- a/core/java/android/test/AndroidTestCase.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.test;
-
-import android.content.Context;
-
-import java.lang.reflect.Field;
-
-import junit.framework.TestCase;
-
-/**
- * Extend this if you need to access Resources or other things that depend on Activity Context.
- */
-public class AndroidTestCase extends TestCase {
-
- protected Context mContext;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
- public void testAndroidTestCaseSetupProperly() {
- assertNotNull("Context is null. setContext should be called before tests are run",
- mContext);
- }
-
- public void setContext(Context context) {
- mContext = context;
- }
-
- public Context getContext() {
- return mContext;
- }
-
- /**
- * This function is called by various TestCase implementations, at tearDown() time, in order
- * to scrub out any class variables. This protects against memory leaks in the case where a
- * test case creates a non-static inner class (thus referencing the test case) and gives it to
- * someone else to hold onto.
- *
- * @param testCaseClass The class of the derived TestCase implementation.
- *
- * @throws IllegalAccessException
- */
- protected void scrubClass(final Class<?> testCaseClass)
- throws IllegalAccessException {
- final Field[] fields = getClass().getDeclaredFields();
- for (Field field : fields) {
- final Class<?> fieldClass = field.getDeclaringClass();
- if (testCaseClass.isAssignableFrom(fieldClass) && !field.getType().isPrimitive()) {
- try {
- field.setAccessible(true);
- field.set(this, null);
- } catch (Exception e) {
- android.util.Log.d("TestCase", "Error: Could not nullify field!");
- }
-
- if (field.get(this) != null) {
- android.util.Log.d("TestCase", "Error: Could not nullify field!");
- }
- }
- }
- }
-
-
-}
diff --git a/core/java/android/test/FlakyTest.java b/core/java/android/test/FlakyTest.java
deleted file mode 100644
index 919767f..0000000
--- a/core/java/android/test/FlakyTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.test;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.annotation.ElementType;
-
-/**
- * This annotation can be used on an {@link android.test.InstrumentationTestCase}'s
- * test methods. When the annotation is present, the test method is re-executed if
- * the test fails. The total number of executions is specified by the tolerance and
- * defaults to 1.
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface FlakyTest {
- /**
- * Indicates how many times a test can run and fail before being reported
- * as a failed test. If the tolerance factor is less than 1, the test runs
- * only once.
- *
- * @return The total number of allowed run, the default is 1.
- */
- int tolerance() default 1;
-}
diff --git a/core/java/android/test/InstrumentationTestCase.java b/core/java/android/test/InstrumentationTestCase.java
deleted file mode 100644
index 82f2ef9..0000000
--- a/core/java/android/test/InstrumentationTestCase.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.test;
-
-import junit.framework.TestCase;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.KeyEvent;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.InvocationTargetException;
-
-/**
- * A test case that has access to {@link Instrumentation}.
- */
-public class InstrumentationTestCase extends TestCase {
-
- private Instrumentation mInstrumentation;
-
- /**
- * Injects instrumentation into this test case. This method is
- * called by the test runner during test setup.
- *
- * @param instrumentation the instrumentation to use with this instance
- */
- public void injectInsrumentation(Instrumentation instrumentation) {
- mInstrumentation = instrumentation;
- }
-
- /**
- * Inheritors can access the instrumentation using this.
- * @return instrumentation
- */
- public Instrumentation getInstrumentation() {
- return mInstrumentation;
- }
-
- /**
- * Utility method for launching an activity.
- *
- * <p>The {@link Intent} used to launch the Activity is:
- * action = {@link Intent#ACTION_MAIN}
- * extras = null, unless a custom bundle is provided here
- * All other fields are null or empty.
- *
- * @param pkg The package hosting the activity to be launched.
- * @param activityCls The activity class to launch.
- * @param extras Optional extra stuff to pass to the activity.
- * @return The activity, or null if non launched.
- */
- @SuppressWarnings("unchecked")
- public final <T extends Activity> T launchActivity(
- String pkg,
- Class<T> activityCls,
- Bundle extras) {
- Intent intent = new Intent(Intent.ACTION_MAIN);
- if (extras != null) {
- intent.putExtras(extras);
- }
- return launchActivityWithIntent(pkg, activityCls, intent);
- }
-
- /**
- * Utility method for launching an activity with a specific Intent.
- * @param pkg The package hosting the activity to be launched.
- * @param activityCls The activity class to launch.
- * @param intent The intent to launch with
- * @return The activity, or null if non launched.
- */
- @SuppressWarnings("unchecked")
- public final <T extends Activity> T launchActivityWithIntent(
- String pkg,
- Class<T> activityCls,
- Intent intent) {
- intent.setClassName(pkg, activityCls.getName());
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- T activity = (T) getInstrumentation().startActivitySync(intent);
- getInstrumentation().waitForIdleSync();
- return activity;
- }
-
- /**
- * Helper for running portions of a test on the UI thread.
- *
- * Note, in most cases it is simpler to annotate the test method with
- * {@link android.test.UiThreadTest}, which will run the entire test method on the UI thread.
- * Use this method if you need to switch in and out of the UI thread to perform your test.
- *
- * @param r runnable containing test code in the {@link Runnable#run()} method
- */
- public void runTestOnUiThread(final Runnable r) throws Throwable {
- final Throwable[] exceptions = new Throwable[1];
- getInstrumentation().runOnMainSync(new Runnable() {
- public void run() {
- try {
- r.run();
- } catch (Throwable throwable) {
- exceptions[0] = throwable;
- }
- }
- });
- if (exceptions[0] != null) {
- throw exceptions[0];
- }
- }
-
- /**
- * Runs the current unit test. If the unit test is annotated with
- * {@link android.test.UiThreadTest}, the test is run on the UI thread.
- */
- @Override
- protected void runTest() throws Throwable {
- String fName = getName();
- assertNotNull(fName);
- Method method = null;
- try {
- // use getMethod to get all public inherited
- // methods. getDeclaredMethods returns all
- // methods of this class but excludes the
- // inherited ones.
- method = getClass().getMethod(fName, (Class[]) null);
- } catch (NoSuchMethodException e) {
- fail("Method \""+fName+"\" not found");
- }
-
- if (!Modifier.isPublic(method.getModifiers())) {
- fail("Method \""+fName+"\" should be public");
- }
-
- int runCount = 1;
- if (method.isAnnotationPresent(FlakyTest.class)) {
- runCount = method.getAnnotation(FlakyTest.class).tolerance();
- }
-
- if (method.isAnnotationPresent(UiThreadTest.class)) {
- final int tolerance = runCount;
- final Method testMethod = method;
- final Throwable[] exceptions = new Throwable[1];
- getInstrumentation().runOnMainSync(new Runnable() {
- public void run() {
- try {
- runMethod(testMethod, tolerance);
- } catch (Throwable throwable) {
- exceptions[0] = throwable;
- }
- }
- });
- if (exceptions[0] != null) {
- throw exceptions[0];
- }
- } else {
- runMethod(method, runCount);
- }
- }
-
- private void runMethod(Method runMethod, int tolerance) throws Throwable {
- Throwable exception = null;
-
- int runCount = 0;
- do {
- try {
- runMethod.invoke(this, (Object[]) null);
- exception = null;
- } catch (InvocationTargetException e) {
- e.fillInStackTrace();
- exception = e.getTargetException();
- } catch (IllegalAccessException e) {
- e.fillInStackTrace();
- exception = e;
- } finally {
- runCount++;
- }
- } while ((runCount < tolerance) && (exception != null));
-
- if (exception != null) {
- throw exception;
- }
- }
-
- /**
- * Sends a series of key events through instrumentation and waits for idle. The sequence
- * of keys is a string containing the key names as specified in KeyEvent, without the
- * KEYCODE_ prefix. For instance: sendKeys("DPAD_LEFT A B C DPAD_CENTER"). Each key can
- * be repeated by using the N* prefix. For instance, to send two KEYCODE_DPAD_LEFT, use
- * the following: sendKeys("2*DPAD_LEFT").
- *
- * @param keysSequence The sequence of keys.
- */
- public void sendKeys(String keysSequence) {
- final String[] keys = keysSequence.split(" ");
- final int count = keys.length;
-
- final Instrumentation instrumentation = getInstrumentation();
-
- for (int i = 0; i < count; i++) {
- String key = keys[i];
- int repeater = key.indexOf('*');
-
- int keyCount;
- try {
- keyCount = repeater == -1 ? 1 : Integer.parseInt(key.substring(0, repeater));
- } catch (NumberFormatException e) {
- Log.w("ActivityTestCase", "Invalid repeat count: " + key);
- continue;
- }
-
- if (repeater != -1) {
- key = key.substring(repeater + 1);
- }
-
- for (int j = 0; j < keyCount; j++) {
- try {
- final Field keyCodeField = KeyEvent.class.getField("KEYCODE_" + key);
- final int keyCode = keyCodeField.getInt(null);
- instrumentation.sendKeyDownUpSync(keyCode);
- } catch (NoSuchFieldException e) {
- Log.w("ActivityTestCase", "Unknown keycode: KEYCODE_" + key);
- break;
- } catch (IllegalAccessException e) {
- Log.w("ActivityTestCase", "Unknown keycode: KEYCODE_" + key);
- break;
- }
- }
- }
-
- instrumentation.waitForIdleSync();
- }
-
- /**
- * Sends a series of key events through instrumentation and waits for idle. For instance:
- * sendKeys(KEYCODE_DPAD_LEFT, KEYCODE_DPAD_CENTER).
- *
- * @param keys The series of key codes to send through instrumentation.
- */
- public void sendKeys(int... keys) {
- final int count = keys.length;
- final Instrumentation instrumentation = getInstrumentation();
-
- for (int i = 0; i < count; i++) {
- instrumentation.sendKeyDownUpSync(keys[i]);
- }
-
- instrumentation.waitForIdleSync();
- }
-
- /**
- * Sends a series of key events through instrumentation and waits for idle. Each key code
- * must be preceded by the number of times the key code must be sent. For instance:
- * sendRepeatedKeys(1, KEYCODE_DPAD_CENTER, 2, KEYCODE_DPAD_LEFT).
- *
- * @param keys The series of key repeats and codes to send through instrumentation.
- */
- public void sendRepeatedKeys(int... keys) {
- final int count = keys.length;
- if ((count & 0x1) == 0x1) {
- throw new IllegalArgumentException("The size of the keys array must "
- + "be a multiple of 2");
- }
-
- final Instrumentation instrumentation = getInstrumentation();
-
- for (int i = 0; i < count; i += 2) {
- final int keyCount = keys[i];
- final int keyCode = keys[i + 1];
- for (int j = 0; j < keyCount; j++) {
- instrumentation.sendKeyDownUpSync(keyCode);
- }
- }
-
- instrumentation.waitForIdleSync();
- }
-
- /**
- * Make sure all resources are cleaned up and garbage collected before moving on to the next
- * test. Subclasses that override this method should make sure they call super.tearDown()
- * at the end of the overriding method.
- *
- * @throws Exception
- */
- protected void tearDown() throws Exception {
- Runtime.getRuntime().gc();
- Runtime.getRuntime().runFinalization();
- Runtime.getRuntime().gc();
- super.tearDown();
- }
-}
diff --git a/core/java/android/test/InstrumentationTestSuite.java b/core/java/android/test/InstrumentationTestSuite.java
deleted file mode 100644
index 2ab949e..0000000
--- a/core/java/android/test/InstrumentationTestSuite.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.test;
-
-import android.app.Instrumentation;
-
-import junit.framework.TestSuite;
-import junit.framework.Test;
-import junit.framework.TestResult;
-
-/**
- * A {@link junit.framework.TestSuite} that injects {@link android.app.Instrumentation} into
- * {@link InstrumentationTestCase} before running them.
- */
-public class InstrumentationTestSuite extends TestSuite {
-
- private final Instrumentation mInstrumentation;
-
- /**
- * @param instr The instrumentation that will be injected into each
- * test before running it.
- */
- public InstrumentationTestSuite(Instrumentation instr) {
- mInstrumentation = instr;
- }
-
-
- public InstrumentationTestSuite(String name, Instrumentation instr) {
- super(name);
- mInstrumentation = instr;
- }
-
- /**
- * @param theClass Inspected for methods starting with 'test'
- * @param instr The instrumentation to inject into each test before
- * running.
- */
- public InstrumentationTestSuite(final Class theClass, Instrumentation instr) {
- super(theClass);
- mInstrumentation = instr;
- }
-
-
- @Override
- public void addTestSuite(Class testClass) {
- addTest(new InstrumentationTestSuite(testClass, mInstrumentation));
- }
-
-
- @Override
- public void runTest(Test test, TestResult result) {
-
- if (test instanceof InstrumentationTestCase) {
- ((InstrumentationTestCase) test).injectInsrumentation(mInstrumentation);
- }
-
- // run the test as usual
- super.runTest(test, result);
- }
-}
diff --git a/core/java/android/test/PerformanceTestCase.java b/core/java/android/test/PerformanceTestCase.java
deleted file mode 100644
index 679ad40..0000000
--- a/core/java/android/test/PerformanceTestCase.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.test;
-
-/**
- * More complex interface performance for test cases.
- *
- * If you want your test to be used as a performance test, you must
- * implement this interface.
- */
-public interface PerformanceTestCase
-{
- /**
- * Callbacks for {@link PerformanceTestCase}.
- */
- public interface Intermediates
- {
- void setInternalIterations(int count);
- void startTiming(boolean realTime);
- void addIntermediate(String name);
- void addIntermediate(String name, long timeInNS);
- void finishTiming(boolean realTime);
- }
-
- /**
- * Set up to begin performance tests. The 'intermediates' is a
- * communication channel to send back intermediate performance numbers --
- * if you use it, you will probably want to ensure your test is only
- * executed once by returning 1. Otherwise, return 0 to allow the test
- * harness to decide the number of iterations.
- *
- * <p>If you return a non-zero iteration count, you should call
- * {@link Intermediates#startTiming intermediates.startTiming} and
- * {@link Intermediates#finishTiming intermediates.endTiming} to report the
- * duration of the test whose performance should actually be measured.
- *
- * @param intermediates Callback for sending intermediate results.
- *
- * @return int Maximum number of iterations to run, or 0 to let the caller
- * decide.
- */
- int startPerformance(Intermediates intermediates);
-
- /**
- * This method is used to determine what modes this test case can run in.
- *
- * @return true if this test case can only be run in performance mode.
- */
- boolean isPerformanceOnly();
-}
-
diff --git a/core/java/android/test/UiThreadTest.java b/core/java/android/test/UiThreadTest.java
deleted file mode 100644
index cd92231..0000000
--- a/core/java/android/test/UiThreadTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.test;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.annotation.ElementType;
-
-/**
- * This annotation can be used on an {@link InstrumentationTestCase}'s test methods.
- * When the annotation is present, the test method is executed on the application's
- * main thread (or UI thread.) Note that instrumentation methods may not be used
- * when this annotation is present.
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface UiThreadTest {
-}
diff --git a/core/java/android/test/package.html b/core/java/android/test/package.html
deleted file mode 100644
index 1972bed..0000000
--- a/core/java/android/test/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<HTML>
-<BODY>
-A framework for writing Android test cases and suites.
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/core/java/android/test/suitebuilder/annotation/LargeTest.java b/core/java/android/test/suitebuilder/annotation/LargeTest.java
deleted file mode 100644
index a6269e7..0000000
--- a/core/java/android/test/suitebuilder/annotation/LargeTest.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.test.suitebuilder.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marks a test that should run as part of the large tests.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD, ElementType.TYPE})
-public @interface LargeTest {
-}
diff --git a/core/java/android/test/suitebuilder/annotation/MediumTest.java b/core/java/android/test/suitebuilder/annotation/MediumTest.java
deleted file mode 100644
index 8afeb91..0000000
--- a/core/java/android/test/suitebuilder/annotation/MediumTest.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.test.suitebuilder.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marks a test that should run as part of the medium tests.
- *
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD, ElementType.TYPE})
-public @interface MediumTest {
-}
diff --git a/core/java/android/test/suitebuilder/annotation/SmallTest.java b/core/java/android/test/suitebuilder/annotation/SmallTest.java
deleted file mode 100644
index ad530e2..0000000
--- a/core/java/android/test/suitebuilder/annotation/SmallTest.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.test.suitebuilder.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marks a test that should run as part of the small tests.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD, ElementType.TYPE})
-public @interface SmallTest {
-}
diff --git a/core/java/android/test/suitebuilder/annotation/Smoke.java b/core/java/android/test/suitebuilder/annotation/Smoke.java
deleted file mode 100644
index 237e033..0000000
--- a/core/java/android/test/suitebuilder/annotation/Smoke.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.test.suitebuilder.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marks a test that should run as part of the smoke tests.
- * The <code>android.test.suitebuilder.SmokeTestSuiteBuilder</code>
- * will run all tests with this annotation.
- *
- * @see android.test.suitebuilder.SmokeTestSuiteBuilder
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD, ElementType.TYPE})
-public @interface Smoke {
-}
diff --git a/core/java/android/test/suitebuilder/annotation/Suppress.java b/core/java/android/test/suitebuilder/annotation/Suppress.java
deleted file mode 100644
index f16c8fa..0000000
--- a/core/java/android/test/suitebuilder/annotation/Suppress.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.test.suitebuilder.annotation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.annotation.ElementType;
-
-/**
- * Use this annotation on test classes or test methods that should not be included in a test
- * suite. If the annotation appears on the class then no tests in that class will be included. If
- * the annotation appears only on a test method then only that method will be excluded.
- *
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD, ElementType.TYPE})
-public @interface Suppress {
-}
diff --git a/core/java/android/text/AlteredCharSequence.java b/core/java/android/text/AlteredCharSequence.java
deleted file mode 100644
index 4cc71fd..0000000
--- a/core/java/android/text/AlteredCharSequence.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-// XXX should this really be in the public API at all?
-/**
- * An AlteredCharSequence is a CharSequence that is largely mirrored from
- * another CharSequence, except that a specified range of characters are
- * mirrored from a different char array instead.
- */
-public class AlteredCharSequence
-implements CharSequence, GetChars
-{
- /**
- * Create an AlteredCharSequence whose text (and possibly spans)
- * are mirrored from <code>source</code>, except that the range of
- * offsets <code>substart</code> inclusive to <code>subend</code> exclusive
- * are mirrored instead from <code>sub</code>, beginning at offset 0.
- */
- public static AlteredCharSequence make(CharSequence source, char[] sub,
- int substart, int subend) {
- if (source instanceof Spanned)
- return new AlteredSpanned(source, sub, substart, subend);
- else
- return new AlteredCharSequence(source, sub, substart, subend);
- }
-
- private AlteredCharSequence(CharSequence source, char[] sub,
- int substart, int subend) {
- mSource = source;
- mChars = sub;
- mStart = substart;
- mEnd = subend;
- }
-
- /* package */ void update(char[] sub, int substart, int subend) {
- mChars = sub;
- mStart = substart;
- mEnd = subend;
- }
-
- private static class AlteredSpanned
- extends AlteredCharSequence
- implements Spanned
- {
- private AlteredSpanned(CharSequence source, char[] sub,
- int substart, int subend) {
- super(source, sub, substart, subend);
- mSpanned = (Spanned) source;
- }
-
- public <T> T[] getSpans(int start, int end, Class<T> kind) {
- return mSpanned.getSpans(start, end, kind);
- }
-
- public int getSpanStart(Object span) {
- return mSpanned.getSpanStart(span);
- }
-
- public int getSpanEnd(Object span) {
- return mSpanned.getSpanEnd(span);
- }
-
- public int getSpanFlags(Object span) {
- return mSpanned.getSpanFlags(span);
- }
-
- public int nextSpanTransition(int start, int end, Class kind) {
- return mSpanned.nextSpanTransition(start, end, kind);
- }
-
- private Spanned mSpanned;
- }
-
- public char charAt(int off) {
- if (off >= mStart && off < mEnd)
- return mChars[off - mStart];
- else
- return mSource.charAt(off);
- }
-
- public int length() {
- return mSource.length();
- }
-
- public CharSequence subSequence(int start, int end) {
- return AlteredCharSequence.make(mSource.subSequence(start, end),
- mChars, mStart - start, mEnd - start);
- }
-
- public void getChars(int start, int end, char[] dest, int off) {
- TextUtils.getChars(mSource, start, end, dest, off);
-
- start = Math.max(mStart, start);
- end = Math.min(mEnd, end);
-
- if (start > end)
- System.arraycopy(mChars, start - mStart, dest, off, end - start);
- }
-
- public String toString() {
- int len = length();
-
- char[] ret = new char[len];
- getChars(0, len, ret, 0);
- return String.valueOf(ret);
- }
-
- private int mStart;
- private int mEnd;
- private char[] mChars;
- private CharSequence mSource;
-}
diff --git a/core/java/android/text/AndroidCharacter.java b/core/java/android/text/AndroidCharacter.java
deleted file mode 100644
index 6dfd64d..0000000
--- a/core/java/android/text/AndroidCharacter.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-/**
- * AndroidCharacter exposes some character properties that are not
- * easily accessed from java.lang.Character.
- */
-public class AndroidCharacter
-{
- /**
- * Fill in the first <code>count</code> bytes of <code>dest</code> with the
- * directionalities from the first <code>count</code> chars of <code>src</code>.
- * This is just like Character.getDirectionality() except it is a
- * batch operation.
- */
- public native static void getDirectionalities(char[] src, byte[] dest,
- int count);
- /**
- * Replace the specified slice of <code>text</code> with the chars'
- * right-to-left mirrors (if any), returning true if any
- * replacements were made.
- */
- public native static boolean mirror(char[] text, int start, int count);
-
- /**
- * Return the right-to-left mirror (or the original char if none)
- * of the specified char.
- */
- public native static char getMirror(char ch);
-}
diff --git a/core/java/android/text/Annotation.java b/core/java/android/text/Annotation.java
deleted file mode 100644
index dbc290b..0000000
--- a/core/java/android/text/Annotation.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import android.os.Parcel;
-
-/**
- * Annotations are simple key-value pairs that are preserved across
- * TextView save/restore cycles and can be used to keep application-specific
- * data that needs to be maintained for regions of text.
- */
-public class Annotation implements ParcelableSpan {
- private final String mKey;
- private final String mValue;
-
- public Annotation(String key, String value) {
- mKey = key;
- mValue = value;
- }
-
- public Annotation(Parcel src) {
- mKey = src.readString();
- mValue = src.readString();
- }
-
- public int getSpanTypeId() {
- return TextUtils.ANNOTATION;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mKey);
- dest.writeString(mValue);
- }
-
- public String getKey() {
- return mKey;
- }
-
- public String getValue() {
- return mValue;
- }
-}
diff --git a/core/java/android/text/AutoText.java b/core/java/android/text/AutoText.java
deleted file mode 100644
index 508d740..0000000
--- a/core/java/android/text/AutoText.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
-import com.android.internal.util.XmlUtils;
-import android.view.View;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.util.Locale;
-
-/**
- * This class accesses a dictionary of corrections to frequent misspellings.
- */
-public class AutoText {
- // struct trie {
- // char c;
- // int off;
- // struct trie *child;
- // struct trie *next;
- // };
-
- private static final int TRIE_C = 0;
- private static final int TRIE_OFF = 1;
- private static final int TRIE_CHILD = 2;
- private static final int TRIE_NEXT = 3;
-
- private static final int TRIE_SIZEOF = 4;
- private static final char TRIE_NULL = (char) -1;
- private static final int TRIE_ROOT = 0;
-
- private static final int INCREMENT = 1024;
-
- private static final int DEFAULT = 14337; // Size of the Trie 13 Aug 2007
-
- private static final int RIGHT = 9300; // Size of 'right' 13 Aug 2007
-
- private static AutoText sInstance = new AutoText(Resources.getSystem());
- private static Object sLock = new Object();
-
- // TODO:
- //
- // Note the assumption that the destination strings total less than
- // 64K characters and that the trie for the source side totals less
- // than 64K chars/offsets/child pointers/next pointers.
- //
- // This seems very safe for English (currently 7K of destination,
- // 14K of trie) but may need to be revisited.
-
- private char[] mTrie;
- private char mTrieUsed;
- private String mText;
- private Locale mLocale;
-
- private AutoText(Resources resources) {
- mLocale = resources.getConfiguration().locale;
- init(resources);
- }
-
- /**
- * Retrieves a possible spelling correction for the specified range
- * of text. Returns null if no correction can be found.
- * The View is used to get the current Locale and Resources.
- */
- public static String get(CharSequence src, final int start, final int end,
- View view) {
- Resources res = view.getContext().getResources();
- Locale locale = res.getConfiguration().locale;
- AutoText instance;
-
- synchronized (sLock) {
- instance = sInstance;
-
- if (!locale.equals(instance.mLocale)) {
- instance = new AutoText(res);
- sInstance = instance;
- }
- }
-
- return instance.lookup(src, start, end);
- }
-
- private String lookup(CharSequence src, final int start, final int end) {
- int here = mTrie[TRIE_ROOT];
-
- for (int i = start; i < end; i++) {
- char c = src.charAt(i);
-
- for (; here != TRIE_NULL; here = mTrie[here + TRIE_NEXT]) {
- if (c == mTrie[here + TRIE_C]) {
- if ((i == end - 1)
- && (mTrie[here + TRIE_OFF] != TRIE_NULL)) {
- int off = mTrie[here + TRIE_OFF];
- int len = mText.charAt(off);
-
- return mText.substring(off + 1, off + 1 + len);
- }
-
- here = mTrie[here + TRIE_CHILD];
- break;
- }
- }
-
- if (here == TRIE_NULL) {
- return null;
- }
- }
-
- return null;
- }
-
- private void init(Resources r) {
- XmlResourceParser parser = r.getXml(com.android.internal.R.xml.autotext);
-
- StringBuilder right = new StringBuilder(RIGHT);
- mTrie = new char[DEFAULT];
- mTrie[TRIE_ROOT] = TRIE_NULL;
- mTrieUsed = TRIE_ROOT + 1;
-
- try {
- XmlUtils.beginDocument(parser, "words");
- String odest = "";
- char ooff = 0;
-
- while (true) {
- XmlUtils.nextElement(parser);
-
- String element = parser.getName();
- if (element == null || !(element.equals("word"))) {
- break;
- }
-
- String src = parser.getAttributeValue(null, "src");
- if (parser.next() == XmlPullParser.TEXT) {
- String dest = parser.getText();
- char off;
-
- if (dest.equals(odest)) {
- off = ooff;
- } else {
- off = (char) right.length();
- right.append((char) dest.length());
- right.append(dest);
- }
-
- add(src, off);
- }
- }
-
- // Don't let Resources cache a copy of all these strings.
- r.flushLayoutCache();
- } catch (XmlPullParserException e) {
- throw new RuntimeException(e);
- } catch (IOException e) {
- throw new RuntimeException(e);
- } finally {
- parser.close();
- }
-
- mText = right.toString();
- }
-
- private void add(String src, char off) {
- int slen = src.length();
- int herep = TRIE_ROOT;
-
- for (int i = 0; i < slen; i++) {
- char c = src.charAt(i);
- boolean found = false;
-
- for (; mTrie[herep] != TRIE_NULL;
- herep = mTrie[herep] + TRIE_NEXT) {
- if (c == mTrie[mTrie[herep] + TRIE_C]) {
- // There is a node for this letter, and this is the
- // end, so fill in the right hand side fields.
-
- if (i == slen - 1) {
- mTrie[mTrie[herep] + TRIE_OFF] = off;
- return;
- }
-
- // There is a node for this letter, and we need
- // to go deeper into it to fill in the rest.
-
- herep = mTrie[herep] + TRIE_CHILD;
- found = true;
- break;
- }
- }
-
- if (!found) {
- // No node for this letter yet. Make one.
-
- char node = newTrieNode();
- mTrie[herep] = node;
-
- mTrie[mTrie[herep] + TRIE_C] = c;
- mTrie[mTrie[herep] + TRIE_OFF] = TRIE_NULL;
- mTrie[mTrie[herep] + TRIE_NEXT] = TRIE_NULL;
- mTrie[mTrie[herep] + TRIE_CHILD] = TRIE_NULL;
-
- // If this is the end of the word, fill in the offset.
-
- if (i == slen - 1) {
- mTrie[mTrie[herep] + TRIE_OFF] = off;
- return;
- }
-
- // Otherwise, step in deeper and go to the next letter.
-
- herep = mTrie[herep] + TRIE_CHILD;
- }
- }
- }
-
- private char newTrieNode() {
- if (mTrieUsed + TRIE_SIZEOF > mTrie.length) {
- char[] copy = new char[mTrie.length + INCREMENT];
- System.arraycopy(mTrie, 0, copy, 0, mTrie.length);
- mTrie = copy;
- }
-
- char ret = mTrieUsed;
- mTrieUsed += TRIE_SIZEOF;
-
- return ret;
- }
-}
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
deleted file mode 100644
index 843754b..0000000
--- a/core/java/android/text/BoringLayout.java
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.util.FloatMath;
-
-/**
- * A BoringLayout is a very simple Layout implementation for text that
- * fits on a single line and is all left-to-right characters.
- * You will probably never want to make one of these yourself;
- * if you do, be sure to call {@link #isBoring} first to make sure
- * the text meets the criteria.
- * <p>This class is used by widgets to control text layout. You should not need
- * to use this class directly unless you are implementing your own widget
- * or custom display object, in which case
- * you are encouraged to use a Layout instead of calling
- * {@link android.graphics.Canvas#drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint)
- * Canvas.drawText()} directly.</p>
- */
-public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback {
- public static BoringLayout make(CharSequence source,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- BoringLayout.Metrics metrics, boolean includepad) {
- return new BoringLayout(source, paint, outerwidth, align,
- spacingmult, spacingadd, metrics,
- includepad);
- }
-
- public static BoringLayout make(CharSequence source,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- BoringLayout.Metrics metrics, boolean includepad,
- TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
- return new BoringLayout(source, paint, outerwidth, align,
- spacingmult, spacingadd, metrics,
- includepad, ellipsize, ellipsizedWidth);
- }
-
- /**
- * Returns a BoringLayout for the specified text, potentially reusing
- * this one if it is already suitable. The caller must make sure that
- * no one is still using this Layout.
- */
- public BoringLayout replaceOrMake(CharSequence source, TextPaint paint,
- int outerwidth, Alignment align,
- float spacingmult, float spacingadd,
- BoringLayout.Metrics metrics,
- boolean includepad) {
- replaceWith(source, paint, outerwidth, align, spacingmult,
- spacingadd);
-
- mEllipsizedWidth = outerwidth;
- mEllipsizedStart = 0;
- mEllipsizedCount = 0;
-
- init(source, paint, outerwidth, align, spacingmult, spacingadd,
- metrics, includepad, true);
- return this;
- }
-
- /**
- * Returns a BoringLayout for the specified text, potentially reusing
- * this one if it is already suitable. The caller must make sure that
- * no one is still using this Layout.
- */
- public BoringLayout replaceOrMake(CharSequence source, TextPaint paint,
- int outerwidth, Alignment align,
- float spacingmult, float spacingadd,
- BoringLayout.Metrics metrics,
- boolean includepad,
- TextUtils.TruncateAt ellipsize,
- int ellipsizedWidth) {
- boolean trust;
-
- if (ellipsize == null || ellipsize == TextUtils.TruncateAt.MARQUEE) {
- replaceWith(source, paint, outerwidth, align, spacingmult,
- spacingadd);
-
- mEllipsizedWidth = outerwidth;
- mEllipsizedStart = 0;
- mEllipsizedCount = 0;
- trust = true;
- } else {
- replaceWith(TextUtils.ellipsize(source, paint, ellipsizedWidth,
- ellipsize, true, this),
- paint, outerwidth, align, spacingmult,
- spacingadd);
-
- mEllipsizedWidth = ellipsizedWidth;
- trust = false;
- }
-
- init(getText(), paint, outerwidth, align, spacingmult, spacingadd,
- metrics, includepad, trust);
- return this;
- }
-
- public BoringLayout(CharSequence source,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- BoringLayout.Metrics metrics, boolean includepad) {
- super(source, paint, outerwidth, align, spacingmult, spacingadd);
-
- mEllipsizedWidth = outerwidth;
- mEllipsizedStart = 0;
- mEllipsizedCount = 0;
-
- init(source, paint, outerwidth, align, spacingmult, spacingadd,
- metrics, includepad, true);
- }
-
- public BoringLayout(CharSequence source,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- BoringLayout.Metrics metrics, boolean includepad,
- TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
- /*
- * It is silly to have to call super() and then replaceWith(),
- * but we can't use "this" for the callback until the call to
- * super() finishes.
- */
- super(source, paint, outerwidth, align, spacingmult, spacingadd);
-
- boolean trust;
-
- if (ellipsize == null || ellipsize == TextUtils.TruncateAt.MARQUEE) {
- mEllipsizedWidth = outerwidth;
- mEllipsizedStart = 0;
- mEllipsizedCount = 0;
- trust = true;
- } else {
- replaceWith(TextUtils.ellipsize(source, paint, ellipsizedWidth,
- ellipsize, true, this),
- paint, outerwidth, align, spacingmult,
- spacingadd);
-
-
- mEllipsizedWidth = ellipsizedWidth;
- trust = false;
- }
-
- init(getText(), paint, outerwidth, align, spacingmult, spacingadd,
- metrics, includepad, trust);
- }
-
- /* package */ void init(CharSequence source,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- BoringLayout.Metrics metrics, boolean includepad,
- boolean trustWidth) {
- int spacing;
-
- if (source instanceof String && align == Layout.Alignment.ALIGN_NORMAL) {
- mDirect = source.toString();
- } else {
- mDirect = null;
- }
-
- mPaint = paint;
-
- if (includepad) {
- spacing = metrics.bottom - metrics.top;
- } else {
- spacing = metrics.descent - metrics.ascent;
- }
-
- if (spacingmult != 1 || spacingadd != 0) {
- spacing = (int)(spacing * spacingmult + spacingadd + 0.5f);
- }
-
- mBottom = spacing;
-
- if (includepad) {
- mDesc = spacing + metrics.top;
- } else {
- mDesc = spacing + metrics.ascent;
- }
-
- if (trustWidth) {
- mMax = metrics.width;
- } else {
- /*
- * If we have ellipsized, we have to actually calculate the
- * width because the width that was passed in was for the
- * full text, not the ellipsized form.
- */
- synchronized (sTemp) {
- mMax = (int) (FloatMath.ceil(Styled.measureText(paint, sTemp,
- source, 0, source.length(),
- null)));
- }
- }
-
- if (includepad) {
- mTopPadding = metrics.top - metrics.ascent;
- mBottomPadding = metrics.bottom - metrics.descent;
- }
- }
-
- /**
- * Returns null if not boring; the width, ascent, and descent if boring.
- */
- public static Metrics isBoring(CharSequence text,
- TextPaint paint) {
- return isBoring(text, paint, null);
- }
-
- /**
- * Returns null if not boring; the width, ascent, and descent in the
- * provided Metrics object (or a new one if the provided one was null)
- * if boring.
- */
- public static Metrics isBoring(CharSequence text, TextPaint paint,
- Metrics metrics) {
- char[] temp = TextUtils.obtain(500);
- int len = text.length();
- boolean boring = true;
-
- outer:
- for (int i = 0; i < len; i += 500) {
- int j = i + 500;
-
- if (j > len)
- j = len;
-
- TextUtils.getChars(text, i, j, temp, 0);
-
- int n = j - i;
-
- for (int a = 0; a < n; a++) {
- char c = temp[a];
-
- if (c == '\n' || c == '\t' || c >= FIRST_RIGHT_TO_LEFT) {
- boring = false;
- break outer;
- }
- }
- }
-
- TextUtils.recycle(temp);
-
- if (boring) {
- Metrics fm = metrics;
- if (fm == null) {
- fm = new Metrics();
- }
-
- int wid;
-
- synchronized (sTemp) {
- wid = (int) (FloatMath.ceil(Styled.measureText(paint, sTemp,
- text, 0, text.length(), fm)));
- }
- fm.width = wid;
- return fm;
- } else {
- return null;
- }
- }
-
- @Override public int getHeight() {
- return mBottom;
- }
-
- @Override public int getLineCount() {
- return 1;
- }
-
- @Override public int getLineTop(int line) {
- if (line == 0)
- return 0;
- else
- return mBottom;
- }
-
- @Override public int getLineDescent(int line) {
- return mDesc;
- }
-
- @Override public int getLineStart(int line) {
- if (line == 0)
- return 0;
- else
- return getText().length();
- }
-
- @Override public int getParagraphDirection(int line) {
- return DIR_LEFT_TO_RIGHT;
- }
-
- @Override public boolean getLineContainsTab(int line) {
- return false;
- }
-
- @Override public float getLineMax(int line) {
- return mMax;
- }
-
- @Override public final Directions getLineDirections(int line) {
- return Layout.DIRS_ALL_LEFT_TO_RIGHT;
- }
-
- public int getTopPadding() {
- return mTopPadding;
- }
-
- public int getBottomPadding() {
- return mBottomPadding;
- }
-
- @Override
- public int getEllipsisCount(int line) {
- return mEllipsizedCount;
- }
-
- @Override
- public int getEllipsisStart(int line) {
- return mEllipsizedStart;
- }
-
- @Override
- public int getEllipsizedWidth() {
- return mEllipsizedWidth;
- }
-
- // Override draw so it will be faster.
- @Override
- public void draw(Canvas c, Path highlight, Paint highlightpaint,
- int cursorOffset) {
- if (mDirect != null && highlight == null) {
- c.drawText(mDirect, 0, mBottom - mDesc, mPaint);
- } else {
- super.draw(c, highlight, highlightpaint, cursorOffset);
- }
- }
-
- /**
- * Callback for the ellipsizer to report what region it ellipsized.
- */
- public void ellipsized(int start, int end) {
- mEllipsizedStart = start;
- mEllipsizedCount = end - start;
- }
-
- private static final char FIRST_RIGHT_TO_LEFT = '\u0590';
-
- private String mDirect;
- private Paint mPaint;
-
- /* package */ int mBottom, mDesc; // for Direct
- private int mTopPadding, mBottomPadding;
- private float mMax;
- private int mEllipsizedWidth, mEllipsizedStart, mEllipsizedCount;
-
- private static final TextPaint sTemp =
- new TextPaint();
-
- public static class Metrics extends Paint.FontMetricsInt {
- public int width;
-
- @Override public String toString() {
- return super.toString() + " width=" + width;
- }
- }
-}
diff --git a/core/java/android/text/ClipboardManager.java b/core/java/android/text/ClipboardManager.java
deleted file mode 100644
index 52039af..0000000
--- a/core/java/android/text/ClipboardManager.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import android.content.Context;
-import android.os.RemoteException;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.ServiceManager;
-import android.util.Log;
-
-/**
- * Interface to the clipboard service, for placing and retrieving text in
- * the global clipboard.
- *
- * <p>
- * You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService}.
- *
- * @see android.content.Context#getSystemService
- */
-public class ClipboardManager {
- private static IClipboard sService;
-
- private Context mContext;
-
- static private IClipboard getService() {
- if (sService != null) {
- return sService;
- }
- IBinder b = ServiceManager.getService("clipboard");
- sService = IClipboard.Stub.asInterface(b);
- return sService;
- }
-
- /** {@hide} */
- public ClipboardManager(Context context, Handler handler) {
- mContext = context;
- }
-
- /**
- * Returns the text on the clipboard. It will eventually be possible
- * to store types other than text too, in which case this will return
- * null if the type cannot be coerced to text.
- */
- public CharSequence getText() {
- try {
- return getService().getClipboardText();
- } catch (RemoteException e) {
- return null;
- }
- }
-
- /**
- * Sets the contents of the clipboard to the specified text.
- */
- public void setText(CharSequence text) {
- try {
- getService().setClipboardText(text);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Returns true if the clipboard contains text; false otherwise.
- */
- public boolean hasText() {
- try {
- return getService().hasClipboardText();
- } catch (RemoteException e) {
- return false;
- }
- }
-}
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
deleted file mode 100644
index 14e5655..0000000
--- a/core/java/android/text/DynamicLayout.java
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import android.graphics.Paint;
-import android.text.style.UpdateLayout;
-import android.text.style.WrapTogetherSpan;
-
-import java.lang.ref.WeakReference;
-
-/**
- * DynamicLayout is a text layout that updates itself as the text is edited.
- * <p>This is used by widgets to control text layout. You should not need
- * to use this class directly unless you are implementing your own widget
- * or custom display object, or need to call
- * {@link android.graphics.Canvas#drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint)
- * Canvas.drawText()} directly.</p>
- */
-public class DynamicLayout
-extends Layout
-{
- private static final int PRIORITY = 128;
-
- /**
- * Make a layout for the specified text that will be updated as
- * the text is changed.
- */
- public DynamicLayout(CharSequence base,
- TextPaint paint,
- int width, Alignment align,
- float spacingmult, float spacingadd,
- boolean includepad) {
- this(base, base, paint, width, align, spacingmult, spacingadd,
- includepad);
- }
-
- /**
- * Make a layout for the transformed text (password transformation
- * being the primary example of a transformation)
- * that will be updated as the base text is changed.
- */
- public DynamicLayout(CharSequence base, CharSequence display,
- TextPaint paint,
- int width, Alignment align,
- float spacingmult, float spacingadd,
- boolean includepad) {
- this(base, display, paint, width, align, spacingmult, spacingadd,
- includepad, null, 0);
- }
-
- /**
- * Make a layout for the transformed text (password transformation
- * being the primary example of a transformation)
- * that will be updated as the base text is changed.
- * If ellipsize is non-null, the Layout will ellipsize the text
- * down to ellipsizedWidth.
- */
- public DynamicLayout(CharSequence base, CharSequence display,
- TextPaint paint,
- int width, Alignment align,
- float spacingmult, float spacingadd,
- boolean includepad,
- TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
- super((ellipsize == null)
- ? display
- : (display instanceof Spanned)
- ? new SpannedEllipsizer(display)
- : new Ellipsizer(display),
- paint, width, align, spacingmult, spacingadd);
-
- mBase = base;
- mDisplay = display;
-
- if (ellipsize != null) {
- mInts = new PackedIntVector(COLUMNS_ELLIPSIZE);
- mEllipsizedWidth = ellipsizedWidth;
- mEllipsizeAt = ellipsize;
- } else {
- mInts = new PackedIntVector(COLUMNS_NORMAL);
- mEllipsizedWidth = width;
- mEllipsizeAt = ellipsize;
- }
-
- mObjects = new PackedObjectVector<Directions>(1);
-
- mIncludePad = includepad;
-
- /*
- * This is annoying, but we can't refer to the layout until
- * superclass construction is finished, and the superclass
- * constructor wants the reference to the display text.
- *
- * This will break if the superclass constructor ever actually
- * cares about the content instead of just holding the reference.
- */
- if (ellipsize != null) {
- Ellipsizer e = (Ellipsizer) getText();
-
- e.mLayout = this;
- e.mWidth = ellipsizedWidth;
- e.mMethod = ellipsize;
- mEllipsize = true;
- }
-
- // Initial state is a single line with 0 characters (0 to 0),
- // with top at 0 and bottom at whatever is natural, and
- // undefined ellipsis.
-
- int[] start;
-
- if (ellipsize != null) {
- start = new int[COLUMNS_ELLIPSIZE];
- start[ELLIPSIS_START] = ELLIPSIS_UNDEFINED;
- } else {
- start = new int[COLUMNS_NORMAL];
- }
-
- Directions[] dirs = new Directions[] { DIRS_ALL_LEFT_TO_RIGHT };
-
- Paint.FontMetricsInt fm = paint.getFontMetricsInt();
- int asc = fm.ascent;
- int desc = fm.descent;
-
- start[DIR] = DIR_LEFT_TO_RIGHT << DIR_SHIFT;
- start[TOP] = 0;
- start[DESCENT] = desc;
- mInts.insertAt(0, start);
-
- start[TOP] = desc - asc;
- mInts.insertAt(1, start);
-
- mObjects.insertAt(0, dirs);
-
- // Update from 0 characters to whatever the real text is
-
- reflow(base, 0, 0, base.length());
-
- if (base instanceof Spannable) {
- if (mWatcher == null)
- mWatcher = new ChangeWatcher(this);
-
- // Strip out any watchers for other DynamicLayouts.
- Spannable sp = (Spannable) base;
- ChangeWatcher[] spans = sp.getSpans(0, sp.length(), ChangeWatcher.class);
- for (int i = 0; i < spans.length; i++)
- sp.removeSpan(spans[i]);
-
- sp.setSpan(mWatcher, 0, base.length(),
- Spannable.SPAN_INCLUSIVE_INCLUSIVE |
- (PRIORITY << Spannable.SPAN_PRIORITY_SHIFT));
- }
- }
-
- private void reflow(CharSequence s, int where, int before, int after) {
- if (s != mBase)
- return;
-
- CharSequence text = mDisplay;
- int len = text.length();
-
- // seek back to the start of the paragraph
-
- int find = TextUtils.lastIndexOf(text, '\n', where - 1);
- if (find < 0)
- find = 0;
- else
- find = find + 1;
-
- {
- int diff = where - find;
- before += diff;
- after += diff;
- where -= diff;
- }
-
- // seek forward to the end of the paragraph
-
- int look = TextUtils.indexOf(text, '\n', where + after);
- if (look < 0)
- look = len;
- else
- look++; // we want the index after the \n
-
- int change = look - (where + after);
- before += change;
- after += change;
-
- // seek further out to cover anything that is forced to wrap together
-
- if (text instanceof Spanned) {
- Spanned sp = (Spanned) text;
- boolean again;
-
- do {
- again = false;
-
- Object[] force = sp.getSpans(where, where + after,
- WrapTogetherSpan.class);
-
- for (int i = 0; i < force.length; i++) {
- int st = sp.getSpanStart(force[i]);
- int en = sp.getSpanEnd(force[i]);
-
- if (st < where) {
- again = true;
-
- int diff = where - st;
- before += diff;
- after += diff;
- where -= diff;
- }
-
- if (en > where + after) {
- again = true;
-
- int diff = en - (where + after);
- before += diff;
- after += diff;
- }
- }
- } while (again);
- }
-
- // find affected region of old layout
-
- int startline = getLineForOffset(where);
- int startv = getLineTop(startline);
-
- int endline = getLineForOffset(where + before);
- if (where + after == len)
- endline = getLineCount();
- int endv = getLineTop(endline);
- boolean islast = (endline == getLineCount());
-
- // generate new layout for affected text
-
- StaticLayout reflowed;
-
- synchronized (sLock) {
- reflowed = sStaticLayout;
- sStaticLayout = null;
- }
-
- if (reflowed == null)
- reflowed = new StaticLayout(true);
-
- reflowed.generate(text, where, where + after,
- getPaint(), getWidth(), getAlignment(),
- getSpacingMultiplier(), getSpacingAdd(),
- false, true, mEllipsize,
- mEllipsizedWidth, mEllipsizeAt);
- int n = reflowed.getLineCount();
-
- // If the new layout has a blank line at the end, but it is not
- // the very end of the buffer, then we already have a line that
- // starts there, so disregard the blank line.
-
- if (where + after != len &&
- reflowed.getLineStart(n - 1) == where + after)
- n--;
-
- // remove affected lines from old layout
-
- mInts.deleteAt(startline, endline - startline);
- mObjects.deleteAt(startline, endline - startline);
-
- // adjust offsets in layout for new height and offsets
-
- int ht = reflowed.getLineTop(n);
- int toppad = 0, botpad = 0;
-
- if (mIncludePad && startline == 0) {
- toppad = reflowed.getTopPadding();
- mTopPadding = toppad;
- ht -= toppad;
- }
- if (mIncludePad && islast) {
- botpad = reflowed.getBottomPadding();
- mBottomPadding = botpad;
- ht += botpad;
- }
-
- mInts.adjustValuesBelow(startline, START, after - before);
- mInts.adjustValuesBelow(startline, TOP, startv - endv + ht);
-
- // insert new layout
-
- int[] ints;
-
- if (mEllipsize) {
- ints = new int[COLUMNS_ELLIPSIZE];
- ints[ELLIPSIS_START] = ELLIPSIS_UNDEFINED;
- } else {
- ints = new int[COLUMNS_NORMAL];
- }
-
- Directions[] objects = new Directions[1];
-
-
- for (int i = 0; i < n; i++) {
- ints[START] = reflowed.getLineStart(i) |
- (reflowed.getParagraphDirection(i) << DIR_SHIFT) |
- (reflowed.getLineContainsTab(i) ? TAB_MASK : 0);
-
- int top = reflowed.getLineTop(i) + startv;
- if (i > 0)
- top -= toppad;
- ints[TOP] = top;
-
- int desc = reflowed.getLineDescent(i);
- if (i == n - 1)
- desc += botpad;
-
- ints[DESCENT] = desc;
- objects[0] = reflowed.getLineDirections(i);
-
- if (mEllipsize) {
- ints[ELLIPSIS_START] = reflowed.getEllipsisStart(i);
- ints[ELLIPSIS_COUNT] = reflowed.getEllipsisCount(i);
- }
-
- mInts.insertAt(startline + i, ints);
- mObjects.insertAt(startline + i, objects);
- }
-
- synchronized (sLock) {
- sStaticLayout = reflowed;
- }
- }
-
- private void dump(boolean show) {
- int n = getLineCount();
-
- for (int i = 0; i < n; i++) {
- System.out.print("line " + i + ": " + getLineStart(i) + " to " + getLineEnd(i) + " ");
-
- if (show) {
- System.out.print(getText().subSequence(getLineStart(i),
- getLineEnd(i)));
- }
-
- System.out.println("");
- }
-
- System.out.println("");
- }
-
- public int getLineCount() {
- return mInts.size() - 1;
- }
-
- public int getLineTop(int line) {
- return mInts.getValue(line, TOP);
- }
-
- public int getLineDescent(int line) {
- return mInts.getValue(line, DESCENT);
- }
-
- public int getLineStart(int line) {
- return mInts.getValue(line, START) & START_MASK;
- }
-
- public boolean getLineContainsTab(int line) {
- return (mInts.getValue(line, TAB) & TAB_MASK) != 0;
- }
-
- public int getParagraphDirection(int line) {
- return mInts.getValue(line, DIR) >> DIR_SHIFT;
- }
-
- public final Directions getLineDirections(int line) {
- return mObjects.getValue(line, 0);
- }
-
- public int getTopPadding() {
- return mTopPadding;
- }
-
- public int getBottomPadding() {
- return mBottomPadding;
- }
-
- @Override
- public int getEllipsizedWidth() {
- return mEllipsizedWidth;
- }
-
- private static class ChangeWatcher
- implements TextWatcher, SpanWatcher
- {
- public ChangeWatcher(DynamicLayout layout) {
- mLayout = new WeakReference(layout);
- }
-
- private void reflow(CharSequence s, int where, int before, int after) {
- DynamicLayout ml = (DynamicLayout) mLayout.get();
-
- if (ml != null)
- ml.reflow(s, where, before, after);
- else if (s instanceof Spannable)
- ((Spannable) s).removeSpan(this);
- }
-
- public void beforeTextChanged(CharSequence s,
- int where, int before, int after) {
- ;
- }
-
- public void onTextChanged(CharSequence s,
- int where, int before, int after) {
- reflow(s, where, before, after);
- }
-
- public void afterTextChanged(Editable s) {
- ;
- }
-
- public void onSpanAdded(Spannable s, Object o, int start, int end) {
- if (o instanceof UpdateLayout)
- reflow(s, start, end - start, end - start);
- }
-
- public void onSpanRemoved(Spannable s, Object o, int start, int end) {
- if (o instanceof UpdateLayout)
- reflow(s, start, end - start, end - start);
- }
-
- public void onSpanChanged(Spannable s, Object o, int start, int end,
- int nstart, int nend) {
- if (o instanceof UpdateLayout) {
- reflow(s, start, end - start, end - start);
- reflow(s, nstart, nend - nstart, nend - nstart);
- }
- }
-
- private WeakReference mLayout;
- }
-
- public int getEllipsisStart(int line) {
- if (mEllipsizeAt == null) {
- return 0;
- }
-
- return mInts.getValue(line, ELLIPSIS_START);
- }
-
- public int getEllipsisCount(int line) {
- if (mEllipsizeAt == null) {
- return 0;
- }
-
- return mInts.getValue(line, ELLIPSIS_COUNT);
- }
-
- private CharSequence mBase;
- private CharSequence mDisplay;
- private ChangeWatcher mWatcher;
- private boolean mIncludePad;
- private boolean mEllipsize;
- private int mEllipsizedWidth;
- private TextUtils.TruncateAt mEllipsizeAt;
-
- private PackedIntVector mInts;
- private PackedObjectVector<Directions> mObjects;
-
- private int mTopPadding, mBottomPadding;
-
- private static StaticLayout sStaticLayout = new StaticLayout(true);
- private static Object sLock = new Object();
-
- private static final int START = 0;
- private static final int DIR = START;
- private static final int TAB = START;
- private static final int TOP = 1;
- private static final int DESCENT = 2;
- private static final int COLUMNS_NORMAL = 3;
-
- private static final int ELLIPSIS_START = 3;
- private static final int ELLIPSIS_COUNT = 4;
- private static final int COLUMNS_ELLIPSIZE = 5;
-
- private static final int START_MASK = 0x1FFFFFFF;
- private static final int DIR_MASK = 0xC0000000;
- private static final int DIR_SHIFT = 30;
- private static final int TAB_MASK = 0x20000000;
-
- private static final int ELLIPSIS_UNDEFINED = 0x80000000;
-}
diff --git a/core/java/android/text/Editable.java b/core/java/android/text/Editable.java
deleted file mode 100644
index a284a00..0000000
--- a/core/java/android/text/Editable.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-/**
- * This is the interface for text whose content and markup
- * can be changed (as opposed
- * to immutable text like Strings). If you make a {@link DynamicLayout}
- * of an Editable, the layout will be reflowed as the text is changed.
- */
-public interface Editable
-extends CharSequence, GetChars, Spannable, Appendable
-{
- /**
- * Replaces the specified range (<code>st&hellip;en</code>) of text in this
- * Editable with a copy of the slice <code>start&hellip;end</code> from
- * <code>source</code>. The destination slice may be empty, in which case
- * the operation is an insertion, or the source slice may be empty,
- * in which case the operation is a deletion.
- * <p>
- * Before the change is committed, each filter that was set with
- * {@link #setFilters} is given the opportunity to modify the
- * <code>source</code> text.
- * <p>
- * If <code>source</code>
- * is Spanned, the spans from it are preserved into the Editable.
- * Existing spans within the Editable that entirely cover the replaced
- * range are retained, but any that were strictly within the range
- * that was replaced are removed. As a special case, the cursor
- * position is preserved even when the entire range where it is
- * located is replaced.
- * @return a reference to this object.
- */
- public Editable replace(int st, int en, CharSequence source, int start, int end);
-
- /**
- * Convenience for replace(st, en, text, 0, text.length())
- * @see #replace(int, int, CharSequence, int, int)
- */
- public Editable replace(int st, int en, CharSequence text);
-
- /**
- * Convenience for replace(where, where, text, start, end)
- * @see #replace(int, int, CharSequence, int, int)
- */
- public Editable insert(int where, CharSequence text, int start, int end);
-
- /**
- * Convenience for replace(where, where, text, 0, text.length());
- * @see #replace(int, int, CharSequence, int, int)
- */
- public Editable insert(int where, CharSequence text);
-
- /**
- * Convenience for replace(st, en, "", 0, 0)
- * @see #replace(int, int, CharSequence, int, int)
- */
- public Editable delete(int st, int en);
-
- /**
- * Convenience for replace(length(), length(), text, 0, text.length())
- * @see #replace(int, int, CharSequence, int, int)
- */
- public Editable append(CharSequence text);
-
- /**
- * Convenience for replace(length(), length(), text, start, end)
- * @see #replace(int, int, CharSequence, int, int)
- */
- public Editable append(CharSequence text, int start, int end);
-
- /**
- * Convenience for append(String.valueOf(text)).
- * @see #replace(int, int, CharSequence, int, int)
- */
- public Editable append(char text);
-
- /**
- * Convenience for replace(0, length(), "", 0, 0)
- * @see #replace(int, int, CharSequence, int, int)
- * Note that this clears the text, not the spans;
- * use {@link #clearSpans} if you need that.
- */
- public void clear();
-
- /**
- * Removes all spans from the Editable, as if by calling
- * {@link #removeSpan} on each of them.
- */
- public void clearSpans();
-
- /**
- * Sets the series of filters that will be called in succession
- * whenever the text of this Editable is changed, each of which has
- * the opportunity to limit or transform the text that is being inserted.
- */
- public void setFilters(InputFilter[] filters);
-
- /**
- * Returns the array of input filters that are currently applied
- * to changes to this Editable.
- */
- public InputFilter[] getFilters();
-
- /**
- * Factory used by TextView to create new Editables. You can subclass
- * it to provide something other than SpannableStringBuilder.
- */
- public static class Factory {
- private static Editable.Factory sInstance = new Editable.Factory();
-
- /**
- * Returns the standard Editable Factory.
- */
- public static Editable.Factory getInstance() {
- return sInstance;
- }
-
- /**
- * Returns a new SpannedStringBuilder from the specified
- * CharSequence. You can override this to provide
- * a different kind of Spanned.
- */
- public Editable newEditable(CharSequence source) {
- return new SpannableStringBuilder(source);
- }
- }
-}
diff --git a/core/java/android/text/GetChars.java b/core/java/android/text/GetChars.java
deleted file mode 100644
index 348a911..0000000
--- a/core/java/android/text/GetChars.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-/**
- * Please implement this interface if your CharSequence has a
- * getChars() method like the one in String that is faster than
- * calling charAt() multiple times.
- */
-public interface GetChars
-extends CharSequence
-{
- /**
- * Exactly like String.getChars(): copy chars <code>start</code>
- * through <code>end - 1</code> from this CharSequence into <code>dest</code>
- * beginning at offset <code>destoff</code>.
- */
- public void getChars(int start, int end, char[] dest, int destoff);
-}
diff --git a/core/java/android/text/GraphicsOperations.java b/core/java/android/text/GraphicsOperations.java
deleted file mode 100644
index c3bd0ae..0000000
--- a/core/java/android/text/GraphicsOperations.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-
-/**
- * Please implement this interface if your CharSequence can do quick
- * draw/measure/widths calculations from an internal array.
- * {@hide}
- */
-public interface GraphicsOperations
-extends CharSequence
-{
- /**
- * Just like {@link Canvas#drawText}.
- */
- void drawText(Canvas c, int start, int end,
- float x, float y, Paint p);
-
- /**
- * Just like {@link Paint#measureText}.
- */
- float measureText(int start, int end, Paint p);
-
-
- /**
- * Just like {@link Paint#getTextWidths}.
- */
- public int getTextWidths(int start, int end, float[] widths, Paint p);
-}
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
deleted file mode 100644
index 8495714..0000000
--- a/core/java/android/text/Html.java
+++ /dev/null
@@ -1,784 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import org.ccil.cowan.tagsoup.HTMLSchema;
-import org.ccil.cowan.tagsoup.Parser;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-
-import android.content.res.Resources;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
-import android.text.style.CharacterStyle;
-import android.text.style.ForegroundColorSpan;
-import android.text.style.ImageSpan;
-import android.text.style.ParagraphStyle;
-import android.text.style.QuoteSpan;
-import android.text.style.RelativeSizeSpan;
-import android.text.style.StrikethroughSpan;
-import android.text.style.StyleSpan;
-import android.text.style.SubscriptSpan;
-import android.text.style.SuperscriptSpan;
-import android.text.style.TypefaceSpan;
-import android.text.style.URLSpan;
-import android.text.style.UnderlineSpan;
-import com.android.internal.util.XmlUtils;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.nio.CharBuffer;
-
-/**
- * This class processes HTML strings into displayable styled text.
- * Not all HTML tags are supported.
- */
-public class Html {
- /**
- * Retrieves images for HTML &lt;img&gt; tags.
- */
- public static interface ImageGetter {
- /**
- * This methos is called when the HTML parser encounters an
- * &lt;img&gt; tag. The <code>source</code> argument is the
- * string from the "src" attribute; the return value should be
- * a Drawable representation of the image or <code>null</code>
- * for a generic replacement image. Make sure you call
- * setBounds() on your Drawable if it doesn't already have
- * its bounds set.
- */
- public Drawable getDrawable(String source);
- }
-
- /**
- * Is notified when HTML tags are encountered that the parser does
- * not know how to interpret.
- */
- public static interface TagHandler {
- /**
- * This method will be called whenn the HTML parser encounters
- * a tag that it does not know how to interpret.
- */
- public void handleTag(boolean opening, String tag,
- Editable output, XMLReader xmlReader);
- }
-
- private Html() { }
-
- /**
- * Returns displayable styled text from the provided HTML string.
- * Any &lt;img&gt; tags in the HTML will display as a generic
- * replacement image which your program can then go through and
- * replace with real images.
- *
- * <p>This uses TagSoup to handle real HTML, including all of the brokenness found in the wild.
- */
- public static Spanned fromHtml(String source) {
- return fromHtml(source, null, null);
- }
-
- /**
- * Lazy initialization holder for HTML parser. This class will
- * a) be preloaded by the zygote, or b) not loaded until absolutely
- * necessary.
- */
- private static class HtmlParser {
- private static final HTMLSchema schema = new HTMLSchema();
- }
-
- /**
- * Returns displayable styled text from the provided HTML string.
- * Any &lt;img&gt; tags in the HTML will use the specified ImageGetter
- * to request a representation of the image (use null if you don't
- * want this) and the specified TagHandler to handle unknown tags
- * (specify null if you don't want this).
- *
- * <p>This uses TagSoup to handle real HTML, including all of the brokenness found in the wild.
- */
- public static Spanned fromHtml(String source, ImageGetter imageGetter,
- TagHandler tagHandler) {
- Parser parser = new Parser();
- try {
- parser.setProperty(Parser.schemaProperty, HtmlParser.schema);
- } catch (org.xml.sax.SAXNotRecognizedException e) {
- // Should not happen.
- throw new RuntimeException(e);
- } catch (org.xml.sax.SAXNotSupportedException e) {
- // Should not happen.
- throw new RuntimeException(e);
- }
-
- HtmlToSpannedConverter converter =
- new HtmlToSpannedConverter(source, imageGetter, tagHandler,
- parser);
- return converter.convert();
- }
-
- /**
- * Returns an HTML representation of the provided Spanned text.
- */
- public static String toHtml(Spanned text) {
- StringBuilder out = new StringBuilder();
- int len = text.length();
-
- int next;
- for (int i = 0; i < text.length(); i = next) {
- next = text.nextSpanTransition(i, len, QuoteSpan.class);
- QuoteSpan[] quotes = text.getSpans(i, next, QuoteSpan.class);
-
- for (QuoteSpan quote: quotes) {
- out.append("<blockquote>");
- }
-
- withinBlockquote(out, text, i, next);
-
- for (QuoteSpan quote: quotes) {
- out.append("</blockquote>\n");
- }
- }
-
- return out.toString();
- }
-
- private static void withinBlockquote(StringBuilder out, Spanned text,
- int start, int end) {
- out.append("<p>");
-
- int next;
- for (int i = start; i < end; i = next) {
- next = TextUtils.indexOf(text, '\n', i, end);
- if (next < 0) {
- next = end;
- }
-
- int nl = 0;
-
- while (next < end && text.charAt(next) == '\n') {
- nl++;
- next++;
- }
-
- withinParagraph(out, text, i, next - nl, nl, next == end);
- }
-
- out.append("</p>\n");
- }
-
- private static void withinParagraph(StringBuilder out, Spanned text,
- int start, int end, int nl,
- boolean last) {
- int next;
- for (int i = start; i < end; i = next) {
- next = text.nextSpanTransition(i, end, CharacterStyle.class);
- CharacterStyle[] style = text.getSpans(i, next,
- CharacterStyle.class);
-
- for (int j = 0; j < style.length; j++) {
- if (style[j] instanceof StyleSpan) {
- int s = ((StyleSpan) style[j]).getStyle();
-
- if ((s & Typeface.BOLD) != 0) {
- out.append("<b>");
- }
- if ((s & Typeface.ITALIC) != 0) {
- out.append("<i>");
- }
- }
- if (style[j] instanceof TypefaceSpan) {
- String s = ((TypefaceSpan) style[j]).getFamily();
-
- if (s.equals("monospace")) {
- out.append("<tt>");
- }
- }
- if (style[j] instanceof SuperscriptSpan) {
- out.append("<sup>");
- }
- if (style[j] instanceof SubscriptSpan) {
- out.append("<sub>");
- }
- if (style[j] instanceof UnderlineSpan) {
- out.append("<u>");
- }
- if (style[j] instanceof StrikethroughSpan) {
- out.append("<strike>");
- }
- if (style[j] instanceof URLSpan) {
- out.append("<a href=\"");
- out.append(((URLSpan) style[j]).getURL());
- out.append("\">");
- }
- if (style[j] instanceof ImageSpan) {
- out.append("<img src=\"");
- out.append(((ImageSpan) style[j]).getSource());
- out.append("\">");
-
- // Don't output the dummy character underlying the image.
- i = next;
- }
- }
-
- withinStyle(out, text, i, next);
-
- for (int j = style.length - 1; j >= 0; j--) {
- if (style[j] instanceof URLSpan) {
- out.append("</a>");
- }
- if (style[j] instanceof StrikethroughSpan) {
- out.append("</strike>");
- }
- if (style[j] instanceof UnderlineSpan) {
- out.append("</u>");
- }
- if (style[j] instanceof SubscriptSpan) {
- out.append("</sub>");
- }
- if (style[j] instanceof SuperscriptSpan) {
- out.append("</sup>");
- }
- if (style[j] instanceof TypefaceSpan) {
- String s = ((TypefaceSpan) style[j]).getFamily();
-
- if (s.equals("monospace")) {
- out.append("</tt>");
- }
- }
- if (style[j] instanceof StyleSpan) {
- int s = ((StyleSpan) style[j]).getStyle();
-
- if ((s & Typeface.BOLD) != 0) {
- out.append("</b>");
- }
- if ((s & Typeface.ITALIC) != 0) {
- out.append("</i>");
- }
- }
- }
- }
-
- String p = last ? "" : "</p>\n<p>";
-
- if (nl == 1) {
- out.append("<br>\n");
- } else if (nl == 2) {
- out.append(p);
- } else {
- for (int i = 2; i < nl; i++) {
- out.append("<br>");
- }
-
- out.append(p);
- }
- }
-
- private static void withinStyle(StringBuilder out, Spanned text,
- int start, int end) {
- for (int i = start; i < end; i++) {
- char c = text.charAt(i);
-
- if (c == '<') {
- out.append("&lt;");
- } else if (c == '>') {
- out.append("&gt;");
- } else if (c == '&') {
- out.append("&amp;");
- } else if (c > 0x7E || c < ' ') {
- out.append("&#" + ((int) c) + ";");
- } else if (c == ' ') {
- while (i + 1 < end && text.charAt(i + 1) == ' ') {
- out.append("&nbsp;");
- i++;
- }
-
- out.append(' ');
- } else {
- out.append(c);
- }
- }
- }
-}
-
-class HtmlToSpannedConverter implements ContentHandler {
-
- private static final float[] HEADER_SIZES = {
- 1.5f, 1.4f, 1.3f, 1.2f, 1.1f, 1f,
- };
-
- private String mSource;
- private XMLReader mReader;
- private SpannableStringBuilder mSpannableStringBuilder;
- private Html.ImageGetter mImageGetter;
- private Html.TagHandler mTagHandler;
-
- public HtmlToSpannedConverter(
- String source, Html.ImageGetter imageGetter, Html.TagHandler tagHandler,
- Parser parser) {
- mSource = source;
- mSpannableStringBuilder = new SpannableStringBuilder();
- mImageGetter = imageGetter;
- mTagHandler = tagHandler;
- mReader = parser;
- }
-
- public Spanned convert() {
-
- mReader.setContentHandler(this);
- try {
- mReader.parse(new InputSource(new StringReader(mSource)));
- } catch (IOException e) {
- // We are reading from a string. There should not be IO problems.
- throw new RuntimeException(e);
- } catch (SAXException e) {
- // TagSoup doesn't throw parse exceptions.
- throw new RuntimeException(e);
- }
-
- // Fix flags and range for paragraph-type markup.
- Object[] obj = mSpannableStringBuilder.getSpans(0, mSpannableStringBuilder.length(), ParagraphStyle.class);
- for (int i = 0; i < obj.length; i++) {
- int start = mSpannableStringBuilder.getSpanStart(obj[i]);
- int end = mSpannableStringBuilder.getSpanEnd(obj[i]);
-
- // If the last line of the range is blank, back off by one.
- if (end - 2 >= 0) {
- if (mSpannableStringBuilder.charAt(end - 1) == '\n' &&
- mSpannableStringBuilder.charAt(end - 2) == '\n') {
- end--;
- }
- }
-
- if (end == start) {
- mSpannableStringBuilder.removeSpan(obj[i]);
- } else {
- mSpannableStringBuilder.setSpan(obj[i], start, end, Spannable.SPAN_PARAGRAPH);
- }
- }
-
- return mSpannableStringBuilder;
- }
-
- private void handleStartTag(String tag, Attributes attributes) {
- if (tag.equalsIgnoreCase("br")) {
- // We don't need to handle this. TagSoup will ensure that there's a </br> for each <br>
- // so we can safely emite the linebreaks when we handle the close tag.
- } else if (tag.equalsIgnoreCase("p")) {
- handleP(mSpannableStringBuilder);
- } else if (tag.equalsIgnoreCase("div")) {
- handleP(mSpannableStringBuilder);
- } else if (tag.equalsIgnoreCase("em")) {
- start(mSpannableStringBuilder, new Bold());
- } else if (tag.equalsIgnoreCase("b")) {
- start(mSpannableStringBuilder, new Bold());
- } else if (tag.equalsIgnoreCase("strong")) {
- start(mSpannableStringBuilder, new Italic());
- } else if (tag.equalsIgnoreCase("cite")) {
- start(mSpannableStringBuilder, new Italic());
- } else if (tag.equalsIgnoreCase("dfn")) {
- start(mSpannableStringBuilder, new Italic());
- } else if (tag.equalsIgnoreCase("i")) {
- start(mSpannableStringBuilder, new Italic());
- } else if (tag.equalsIgnoreCase("big")) {
- start(mSpannableStringBuilder, new Big());
- } else if (tag.equalsIgnoreCase("small")) {
- start(mSpannableStringBuilder, new Small());
- } else if (tag.equalsIgnoreCase("font")) {
- startFont(mSpannableStringBuilder, attributes);
- } else if (tag.equalsIgnoreCase("blockquote")) {
- handleP(mSpannableStringBuilder);
- start(mSpannableStringBuilder, new Blockquote());
- } else if (tag.equalsIgnoreCase("tt")) {
- start(mSpannableStringBuilder, new Monospace());
- } else if (tag.equalsIgnoreCase("a")) {
- startA(mSpannableStringBuilder, attributes);
- } else if (tag.equalsIgnoreCase("u")) {
- start(mSpannableStringBuilder, new Underline());
- } else if (tag.equalsIgnoreCase("sup")) {
- start(mSpannableStringBuilder, new Super());
- } else if (tag.equalsIgnoreCase("sub")) {
- start(mSpannableStringBuilder, new Sub());
- } else if (tag.length() == 2 &&
- Character.toLowerCase(tag.charAt(0)) == 'h' &&
- tag.charAt(1) >= '1' && tag.charAt(1) <= '6') {
- handleP(mSpannableStringBuilder);
- start(mSpannableStringBuilder, new Header(tag.charAt(1) - '1'));
- } else if (tag.equalsIgnoreCase("img")) {
- startImg(mSpannableStringBuilder, attributes, mImageGetter);
- } else if (mTagHandler != null) {
- mTagHandler.handleTag(true, tag, mSpannableStringBuilder, mReader);
- }
- }
-
- private void handleEndTag(String tag) {
- if (tag.equalsIgnoreCase("br")) {
- handleBr(mSpannableStringBuilder);
- } else if (tag.equalsIgnoreCase("p")) {
- handleP(mSpannableStringBuilder);
- } else if (tag.equalsIgnoreCase("div")) {
- handleP(mSpannableStringBuilder);
- } else if (tag.equalsIgnoreCase("em")) {
- end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD));
- } else if (tag.equalsIgnoreCase("b")) {
- end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD));
- } else if (tag.equalsIgnoreCase("strong")) {
- end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC));
- } else if (tag.equalsIgnoreCase("cite")) {
- end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC));
- } else if (tag.equalsIgnoreCase("dfn")) {
- end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC));
- } else if (tag.equalsIgnoreCase("i")) {
- end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC));
- } else if (tag.equalsIgnoreCase("big")) {
- end(mSpannableStringBuilder, Big.class, new RelativeSizeSpan(1.25f));
- } else if (tag.equalsIgnoreCase("small")) {
- end(mSpannableStringBuilder, Small.class, new RelativeSizeSpan(0.8f));
- } else if (tag.equalsIgnoreCase("font")) {
- endFont(mSpannableStringBuilder);
- } else if (tag.equalsIgnoreCase("blockquote")) {
- handleP(mSpannableStringBuilder);
- end(mSpannableStringBuilder, Blockquote.class, new QuoteSpan());
- } else if (tag.equalsIgnoreCase("tt")) {
- end(mSpannableStringBuilder, Monospace.class,
- new TypefaceSpan("monospace"));
- } else if (tag.equalsIgnoreCase("a")) {
- endA(mSpannableStringBuilder);
- } else if (tag.equalsIgnoreCase("u")) {
- end(mSpannableStringBuilder, Underline.class, new UnderlineSpan());
- } else if (tag.equalsIgnoreCase("sup")) {
- end(mSpannableStringBuilder, Super.class, new SuperscriptSpan());
- } else if (tag.equalsIgnoreCase("sub")) {
- end(mSpannableStringBuilder, Sub.class, new SubscriptSpan());
- } else if (tag.length() == 2 &&
- Character.toLowerCase(tag.charAt(0)) == 'h' &&
- tag.charAt(1) >= '1' && tag.charAt(1) <= '6') {
- handleP(mSpannableStringBuilder);
- endHeader(mSpannableStringBuilder);
- } else if (mTagHandler != null) {
- mTagHandler.handleTag(false, tag, mSpannableStringBuilder, mReader);
- }
- }
-
- private static void handleP(SpannableStringBuilder text) {
- int len = text.length();
-
- if (len >= 1 && text.charAt(len - 1) == '\n') {
- if (len >= 2 && text.charAt(len - 2) == '\n') {
- return;
- }
-
- text.append("\n");
- return;
- }
-
- if (len != 0) {
- text.append("\n\n");
- }
- }
-
- private static void handleBr(SpannableStringBuilder text) {
- text.append("\n");
- }
-
- private static Object getLast(Spanned text, Class kind) {
- /*
- * This knows that the last returned object from getSpans()
- * will be the most recently added.
- */
- Object[] objs = text.getSpans(0, text.length(), kind);
-
- if (objs.length == 0) {
- return null;
- } else {
- return objs[objs.length - 1];
- }
- }
-
- private static void start(SpannableStringBuilder text, Object mark) {
- int len = text.length();
- text.setSpan(mark, len, len, Spannable.SPAN_MARK_MARK);
- }
-
- private static void end(SpannableStringBuilder text, Class kind,
- Object repl) {
- int len = text.length();
- Object obj = getLast(text, kind);
- int where = text.getSpanStart(obj);
-
- text.removeSpan(obj);
-
- if (where != len) {
- text.setSpan(repl, where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
- return;
- }
-
- private static void startImg(SpannableStringBuilder text,
- Attributes attributes, Html.ImageGetter img) {
- String src = attributes.getValue("", "src");
- Drawable d = null;
-
- if (img != null) {
- d = img.getDrawable(src);
- }
-
- if (d == null) {
- d = Resources.getSystem().
- getDrawable(com.android.internal.R.drawable.unknown_image);
- d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
- }
-
- int len = text.length();
- text.append("\uFFFC");
-
- text.setSpan(new ImageSpan(d, src), len, text.length(),
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
- private static void startFont(SpannableStringBuilder text,
- Attributes attributes) {
- String color = attributes.getValue("", "color");
- String face = attributes.getValue("", "face");
-
- int len = text.length();
- text.setSpan(new Font(color, face), len, len, Spannable.SPAN_MARK_MARK);
- }
-
- private static void endFont(SpannableStringBuilder text) {
- int len = text.length();
- Object obj = getLast(text, Font.class);
- int where = text.getSpanStart(obj);
-
- text.removeSpan(obj);
-
- if (where != len) {
- Font f = (Font) obj;
-
- if (f.mColor != null) {
- int c = -1;
-
- if (f.mColor.equalsIgnoreCase("aqua")) {
- c = 0x00FFFF;
- } else if (f.mColor.equalsIgnoreCase("black")) {
- c = 0x000000;
- } else if (f.mColor.equalsIgnoreCase("blue")) {
- c = 0x0000FF;
- } else if (f.mColor.equalsIgnoreCase("fuchsia")) {
- c = 0xFF00FF;
- } else if (f.mColor.equalsIgnoreCase("green")) {
- c = 0x008000;
- } else if (f.mColor.equalsIgnoreCase("grey")) {
- c = 0x808080;
- } else if (f.mColor.equalsIgnoreCase("lime")) {
- c = 0x00FF00;
- } else if (f.mColor.equalsIgnoreCase("maroon")) {
- c = 0x800000;
- } else if (f.mColor.equalsIgnoreCase("navy")) {
- c = 0x000080;
- } else if (f.mColor.equalsIgnoreCase("olive")) {
- c = 0x808000;
- } else if (f.mColor.equalsIgnoreCase("purple")) {
- c = 0x800080;
- } else if (f.mColor.equalsIgnoreCase("red")) {
- c = 0xFF0000;
- } else if (f.mColor.equalsIgnoreCase("silver")) {
- c = 0xC0C0C0;
- } else if (f.mColor.equalsIgnoreCase("teal")) {
- c = 0x008080;
- } else if (f.mColor.equalsIgnoreCase("white")) {
- c = 0xFFFFFF;
- } else if (f.mColor.equalsIgnoreCase("yellow")) {
- c = 0xFFFF00;
- } else {
- try {
- c = XmlUtils.convertValueToInt(f.mColor, -1);
- } catch (NumberFormatException nfe) {
- // Can't understand the color, so just drop it.
- }
- }
-
- if (c != -1) {
- text.setSpan(new ForegroundColorSpan(c | 0xFF000000),
- where, len,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
-
- if (f.mFace != null) {
- text.setSpan(new TypefaceSpan(f.mFace), where, len,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- }
-
- private static void startA(SpannableStringBuilder text, Attributes attributes) {
- String href = attributes.getValue("", "href");
-
- int len = text.length();
- text.setSpan(new Href(href), len, len, Spannable.SPAN_MARK_MARK);
- }
-
- private static void endA(SpannableStringBuilder text) {
- int len = text.length();
- Object obj = getLast(text, Href.class);
- int where = text.getSpanStart(obj);
-
- text.removeSpan(obj);
-
- if (where != len) {
- Href h = (Href) obj;
-
- if (h.mHref != null) {
- text.setSpan(new URLSpan(h.mHref), where, len,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- }
-
- private static void endHeader(SpannableStringBuilder text) {
- int len = text.length();
- Object obj = getLast(text, Header.class);
-
- int where = text.getSpanStart(obj);
-
- text.removeSpan(obj);
-
- // Back off not to change only the text, not the blank line.
- while (len > where && text.charAt(len - 1) == '\n') {
- len--;
- }
-
- if (where != len) {
- Header h = (Header) obj;
-
- text.setSpan(new RelativeSizeSpan(HEADER_SIZES[h.mLevel]),
- where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- text.setSpan(new StyleSpan(Typeface.BOLD),
- where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
-
- public void setDocumentLocator(Locator locator) {
- }
-
- public void startDocument() throws SAXException {
- }
-
- public void endDocument() throws SAXException {
- }
-
- public void startPrefixMapping(String prefix, String uri) throws SAXException {
- }
-
- public void endPrefixMapping(String prefix) throws SAXException {
- }
-
- public void startElement(String uri, String localName, String qName, Attributes attributes)
- throws SAXException {
- handleStartTag(localName, attributes);
- }
-
- public void endElement(String uri, String localName, String qName) throws SAXException {
- handleEndTag(localName);
- }
-
- public void characters(char ch[], int start, int length) throws SAXException {
- StringBuilder sb = new StringBuilder();
-
- /*
- * Ignore whitespace that immediately follows other whitespace;
- * newlines count as spaces.
- */
-
- for (int i = 0; i < length; i++) {
- char c = ch[i + start];
-
- if (c == ' ' || c == '\n') {
- char pred;
- int len = sb.length();
-
- if (len == 0) {
- len = mSpannableStringBuilder.length();
-
- if (len == 0) {
- pred = '\n';
- } else {
- pred = mSpannableStringBuilder.charAt(len - 1);
- }
- } else {
- pred = sb.charAt(len - 1);
- }
-
- if (pred != ' ' && pred != '\n') {
- sb.append(' ');
- }
- } else {
- sb.append(c);
- }
- }
-
- mSpannableStringBuilder.append(sb);
- }
-
- public void ignorableWhitespace(char ch[], int start, int length) throws SAXException {
- }
-
- public void processingInstruction(String target, String data) throws SAXException {
- }
-
- public void skippedEntity(String name) throws SAXException {
- }
-
- private static class Bold { }
- private static class Italic { }
- private static class Underline { }
- private static class Big { }
- private static class Small { }
- private static class Monospace { }
- private static class Blockquote { }
- private static class Super { }
- private static class Sub { }
-
- private static class Font {
- public String mColor;
- public String mFace;
-
- public Font(String color, String face) {
- mColor = color;
- mFace = face;
- }
- }
-
- private static class Href {
- public String mHref;
-
- public Href(String href) {
- mHref = href;
- }
- }
-
- private static class Header {
- private int mLevel;
-
- public Header(int level) {
- mLevel = level;
- }
- }
-}
diff --git a/core/java/android/text/IClipboard.aidl b/core/java/android/text/IClipboard.aidl
deleted file mode 100644
index 4deb5c8..0000000
--- a/core/java/android/text/IClipboard.aidl
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Copyright (c) 2008, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-/**
- * Programming interface to the clipboard, which allows copying and pasting
- * between applications.
- * {@hide}
- */
-interface IClipboard {
- /**
- * Returns the text on the clipboard. It will eventually be possible
- * to store types other than text too, in which case this will return
- * null if the type cannot be coerced to text.
- */
- CharSequence getClipboardText();
-
- /**
- * Sets the contents of the clipboard to the specified text.
- */
- void setClipboardText(CharSequence text);
-
- /**
- * Returns true if the clipboard contains text; false otherwise.
- */
- boolean hasClipboardText();
-}
-
diff --git a/core/java/android/text/InputFilter.java b/core/java/android/text/InputFilter.java
deleted file mode 100644
index 2f55677..0000000
--- a/core/java/android/text/InputFilter.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-/**
- * InputFilters can be attached to {@link Editable}s to constrain the
- * changes that can be made to them.
- */
-public interface InputFilter
-{
- /**
- * This method is called when the buffer is going to replace the
- * range <code>dstart &hellip; dend</code> of <code>dest</code>
- * with the new text from the range <code>start &hellip; end</code>
- * of <code>source</code>. Return the CharSequence that you would
- * like to have placed there instead, including an empty string
- * if appropriate, or <code>null</code> to accept the original
- * replacement. Be careful to not to reject 0-length replacements,
- * as this is what happens when you delete text. Also beware that
- * you should not attempt to make any changes to <code>dest</code>
- * from this method; you may only examine it for context.
- *
- * Note: If <var>source</var> is an instance of {@link Spanned} or
- * {@link Spannable}, the span objects in the <var>source</var> should be
- * copied into the filtered result (i.e. the non-null return value).
- * {@link TextUtils#copySpansFrom} can be used for convenience.
- */
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend);
-
- /**
- * This filter will capitalize all the lower case letters that are added
- * through edits.
- */
- public static class AllCaps implements InputFilter {
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend) {
- for (int i = start; i < end; i++) {
- if (Character.isLowerCase(source.charAt(i))) {
- char[] v = new char[end - start];
- TextUtils.getChars(source, start, end, v, 0);
- String s = new String(v).toUpperCase();
-
- if (source instanceof Spanned) {
- SpannableString sp = new SpannableString(s);
- TextUtils.copySpansFrom((Spanned) source,
- start, end, null, sp, 0);
- return sp;
- } else {
- return s;
- }
- }
- }
-
- return null; // keep original
- }
- }
-
- /**
- * This filter will constrain edits not to make the length of the text
- * greater than the specified length.
- */
- public static class LengthFilter implements InputFilter {
- public LengthFilter(int max) {
- mMax = max;
- }
-
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend) {
- int keep = mMax - (dest.length() - (dend - dstart));
-
- if (keep <= 0) {
- return "";
- } else if (keep >= end - start) {
- return null; // keep original
- } else {
- return source.subSequence(start, start + keep);
- }
- }
-
- private int mMax;
- }
-}
diff --git a/core/java/android/text/InputType.java b/core/java/android/text/InputType.java
deleted file mode 100644
index a073cf4..0000000
--- a/core/java/android/text/InputType.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import android.text.TextUtils;
-
-/**
- * Bit definitions for an integer defining the basic content type of text
- * held in an {@link Editable} object.
- */
-public interface InputType {
- /**
- * Mask of bits that determine the overall class
- * of text being given. Currently supported classes are:
- * {@link #TYPE_CLASS_TEXT}, {@link #TYPE_CLASS_NUMBER},
- * {@link #TYPE_CLASS_PHONE}, {@link #TYPE_CLASS_DATETIME}.
- * If the class is not one you
- * understand, assume {@link #TYPE_CLASS_TEXT} with NO variation
- * or flags.
- */
- public static final int TYPE_MASK_CLASS = 0x0000000f;
-
- /**
- * Mask of bits that determine the variation of
- * the base content class.
- */
- public static final int TYPE_MASK_VARIATION = 0x00000ff0;
-
- /**
- * Mask of bits that provide addition bit flags
- * of options.
- */
- public static final int TYPE_MASK_FLAGS = 0x00fff000;
-
- /**
- * Special content type for when no explicit type has been specified.
- * This should be interpreted to mean that the target input connection
- * is not rich, it can not process and show things like candidate text nor
- * retrieve the current text, so the input method will need to run in a
- * limited "generate key events" mode.
- */
- public static final int TYPE_NULL = 0x00000000;
-
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
-
- /**
- * Class for normal text. This class supports the following flags (only
- * one of which should be set):
- * {@link #TYPE_TEXT_FLAG_CAP_CHARACTERS},
- * {@link #TYPE_TEXT_FLAG_CAP_WORDS}, and.
- * {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}. It also supports the
- * following variations:
- * {@link #TYPE_TEXT_VARIATION_NORMAL}, and
- * {@link #TYPE_TEXT_VARIATION_URI}. If you do not recognize the
- * variation, normal should be assumed.
- */
- public static final int TYPE_CLASS_TEXT = 0x00000001;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: capitalize all characters. Overrides
- * {@link #TYPE_TEXT_FLAG_CAP_WORDS} and
- * {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}. This value is explicitly defined
- * to be the same as {@link TextUtils#CAP_MODE_CHARACTERS}.
- */
- public static final int TYPE_TEXT_FLAG_CAP_CHARACTERS = 0x00001000;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: capitalize first character of
- * all words. Overrides {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}. This
- * value is explicitly defined
- * to be the same as {@link TextUtils#CAP_MODE_WORDS}.
- */
- public static final int TYPE_TEXT_FLAG_CAP_WORDS = 0x00002000;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: capitalize first character of
- * each sentence. This value is explicitly defined
- * to be the same as {@link TextUtils#CAP_MODE_SENTENCES}.
- */
- public static final int TYPE_TEXT_FLAG_CAP_SENTENCES = 0x00004000;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: the user is entering free-form
- * text that should have auto-correction applied to it.
- */
- public static final int TYPE_TEXT_FLAG_AUTO_CORRECT = 0x00008000;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: the text editor is performing
- * auto-completion of the text being entered based on its own semantics,
- * which it will present to the user as they type. This generally means
- * that the input method should not be showing candidates itself, but can
- * expect for the editor to supply its own completions/candidates from
- * {@link android.view.inputmethod.InputMethodSession#displayCompletions
- * InputMethodSession.displayCompletions()} as a result of the editor calling
- * {@link android.view.inputmethod.InputMethodManager#displayCompletions
- * InputMethodManager.displayCompletions()}.
- */
- public static final int TYPE_TEXT_FLAG_AUTO_COMPLETE = 0x00010000;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: multiple lines of text can be
- * entered into the field. If this flag is not set, the text field
- * will be constrained to a single line.
- */
- public static final int TYPE_TEXT_FLAG_MULTI_LINE = 0x00020000;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: the regular text view associated
- * with this should not be multi-line, but when a fullscreen input method
- * is providing text it should use multiple lines if it can.
- */
- public static final int TYPE_TEXT_FLAG_IME_MULTI_LINE = 0x00040000;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: flags any text being used as a search string
- */
- public static final int TYPE_TEXT_FLAG_SEARCH = 0x00080000;
-
- // ----------------------------------------------------------------------
-
- /**
- * Default variation of {@link #TYPE_CLASS_TEXT}: plain old normal text.
- */
- public static final int TYPE_TEXT_VARIATION_NORMAL = 0x00000000;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering a URI.
- */
- public static final int TYPE_TEXT_VARIATION_URI = 0x00000010;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering an e-mail address.
- */
- public static final int TYPE_TEXT_VARIATION_EMAIL_ADDRESS = 0x00000020;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering the subject line of
- * an e-mail.
- */
- public static final int TYPE_TEXT_VARIATION_EMAIL_SUBJECT = 0x00000030;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering a short, possibly informal
- * message such as an instant message or a text message.
- */
- public static final int TYPE_TEXT_VARIATION_SHORT_MESSAGE = 0x00000040;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering the content of a long, possibly
- * formal message such as the body of an e-mail.
- */
- public static final int TYPE_TEXT_VARIATION_LONG_MESSAGE = 0x00000050;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering the name of a person.
- */
- public static final int TYPE_TEXT_VARIATION_PERSON_NAME = 0x00000060;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering a postal mailing address.
- */
- public static final int TYPE_TEXT_VARIATION_POSTAL_ADDRESS = 0x00000070;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering a password.
- */
- public static final int TYPE_TEXT_VARIATION_PASSWORD = 0x00000080;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering text inside of a web form.
- */
- public static final int TYPE_TEXT_VARIATION_WEB_EDIT_TEXT = 0x00000090;
-
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
-
- /**
- * Class for numeric text. This class supports the following flag:
- * {@link #TYPE_NUMBER_FLAG_SIGNED} and
- * {@link #TYPE_NUMBER_FLAG_DECIMAL}.
- */
- public static final int TYPE_CLASS_NUMBER = 0x00000002;
-
- /**
- * Flag of {@link #TYPE_CLASS_NUMBER}: the number is signed, allowing
- * a positive or negative sign at the start.
- */
- public static final int TYPE_NUMBER_FLAG_SIGNED = 0x00001000;
-
- /**
- * Flag of {@link #TYPE_CLASS_NUMBER}: the number is decimal, allowing
- * a decimal point to provide fractional values.
- */
- public static final int TYPE_NUMBER_FLAG_DECIMAL = 0x00002000;
-
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
-
- /**
- * Class for a phone number. This class currently supports no variations
- * or flags.
- */
- public static final int TYPE_CLASS_PHONE = 0x00000003;
-
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
-
- /**
- * Class for dates and times. It supports the
- * following variations:
- * {@link #TYPE_DATETIME_VARIATION_NORMAL}
- * {@link #TYPE_DATETIME_VARIATION_DATE}, and
- * {@link #TYPE_DATETIME_VARIATION_TIME},.
- */
- public static final int TYPE_CLASS_DATETIME = 0x00000004;
-
- /**
- * Default variation of {@link #TYPE_CLASS_DATETIME}: allows entering
- * both a date and time.
- */
- public static final int TYPE_DATETIME_VARIATION_NORMAL = 0x00000000;
-
- /**
- * Default variation of {@link #TYPE_CLASS_DATETIME}: allows entering
- * only a date.
- */
- public static final int TYPE_DATETIME_VARIATION_DATE = 0x00000010;
-
- /**
- * Default variation of {@link #TYPE_CLASS_DATETIME}: allows entering
- * only a time.
- */
- public static final int TYPE_DATETIME_VARIATION_TIME = 0x00000020;
-}
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
deleted file mode 100644
index 95acf9d..0000000
--- a/core/java/android/text/Layout.java
+++ /dev/null
@@ -1,1747 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Path;
-import com.android.internal.util.ArrayUtils;
-import android.util.Config;
-
-import junit.framework.Assert;
-import android.text.style.*;
-import android.text.method.TextKeyListener;
-import android.view.KeyEvent;
-
-/**
- * A base class that manages text layout in visual elements on
- * the screen.
- * <p>For text that will be edited, use a {@link DynamicLayout},
- * which will be updated as the text changes.
- * For text that will not change, use a {@link StaticLayout}.
- */
-public abstract class Layout {
- /**
- * Return how wide a layout would be necessary to display the
- * specified text with one line per paragraph.
- */
- public static float getDesiredWidth(CharSequence source,
- TextPaint paint) {
- return getDesiredWidth(source, 0, source.length(), paint);
- }
-
- /**
- * Return how wide a layout would be necessary to display the
- * specified text slice with one line per paragraph.
- */
- public static float getDesiredWidth(CharSequence source,
- int start, int end,
- TextPaint paint) {
- float need = 0;
- TextPaint workPaint = new TextPaint();
-
- int next;
- for (int i = start; i <= end; i = next) {
- next = TextUtils.indexOf(source, '\n', i, end);
-
- if (next < 0)
- next = end;
-
- float w = measureText(paint, workPaint,
- source, i, next, null, true, null);
-
- if (w > need)
- need = w;
-
- next++;
- }
-
- return need;
- }
-
- /**
- * Subclasses of Layout use this constructor to set the display text,
- * width, and other standard properties.
- */
- protected Layout(CharSequence text, TextPaint paint,
- int width, Alignment align,
- float spacingmult, float spacingadd) {
- if (width < 0)
- throw new IllegalArgumentException("Layout: " + width + " < 0");
-
- mText = text;
- mPaint = paint;
- mWorkPaint = new TextPaint();
- mWidth = width;
- mAlignment = align;
- mSpacingMult = spacingmult;
- mSpacingAdd = spacingadd;
- mSpannedText = text instanceof Spanned;
- }
-
- /**
- * Replace constructor properties of this Layout with new ones. Be careful.
- */
- /* package */ void replaceWith(CharSequence text, TextPaint paint,
- int width, Alignment align,
- float spacingmult, float spacingadd) {
- if (width < 0) {
- throw new IllegalArgumentException("Layout: " + width + " < 0");
- }
-
- mText = text;
- mPaint = paint;
- mWidth = width;
- mAlignment = align;
- mSpacingMult = spacingmult;
- mSpacingAdd = spacingadd;
- mSpannedText = text instanceof Spanned;
- }
-
- /**
- * Draw this Layout on the specified Canvas.
- */
- public void draw(Canvas c) {
- draw(c, null, null, 0);
- }
-
- /**
- * Draw the specified rectangle from this Layout on the specified Canvas,
- * with the specified path drawn between the background and the text.
- */
- public void draw(Canvas c, Path highlight, Paint highlightpaint,
- int cursorOffsetVertical) {
- int dtop, dbottom;
-
- synchronized (sTempRect) {
- if (!c.getClipBounds(sTempRect)) {
- return;
- }
-
- dtop = sTempRect.top;
- dbottom = sTempRect.bottom;
- }
-
- TextPaint paint = mPaint;
-
- int top = 0;
- // getLineBottom(getLineCount() -1) just calls getLineTop(getLineCount)
- int bottom = getLineTop(getLineCount());
-
-
- if (dtop > top) {
- top = dtop;
- }
- if (dbottom < bottom) {
- bottom = dbottom;
- }
-
- int first = getLineForVertical(top);
- int last = getLineForVertical(bottom);
-
- int previousLineBottom = getLineTop(first);
- int previousLineEnd = getLineStart(first);
-
- CharSequence buf = mText;
-
- ParagraphStyle[] nospans = ArrayUtils.emptyArray(ParagraphStyle.class);
- ParagraphStyle[] spans = nospans;
- int spanend = 0;
- int textLength = 0;
- boolean spannedText = mSpannedText;
-
- if (spannedText) {
- spanend = 0;
- textLength = buf.length();
- for (int i = first; i <= last; i++) {
- int start = previousLineEnd;
- int end = getLineStart(i+1);
- previousLineEnd = end;
-
- int ltop = previousLineBottom;
- int lbottom = getLineTop(i+1);
- previousLineBottom = lbottom;
- int lbaseline = lbottom - getLineDescent(i);
-
- if (start >= spanend) {
- Spanned sp = (Spanned) buf;
- spanend = sp.nextSpanTransition(start, textLength,
- LineBackgroundSpan.class);
- spans = sp.getSpans(start, spanend,
- LineBackgroundSpan.class);
- }
-
- for (int n = 0; n < spans.length; n++) {
- LineBackgroundSpan back = (LineBackgroundSpan) spans[n];
-
- back.drawBackground(c, paint, 0, mWidth,
- ltop, lbaseline, lbottom,
- buf, start, end,
- i);
- }
- }
- // reset to their original values
- spanend = 0;
- previousLineBottom = getLineTop(first);
- previousLineEnd = getLineStart(first);
- spans = nospans;
- }
-
- // There can be a highlight even without spans if we are drawing
- // a non-spanned transformation of a spanned editing buffer.
- if (highlight != null) {
- if (cursorOffsetVertical != 0) {
- c.translate(0, cursorOffsetVertical);
- }
-
- c.drawPath(highlight, highlightpaint);
-
- if (cursorOffsetVertical != 0) {
- c.translate(0, -cursorOffsetVertical);
- }
- }
-
- Alignment align = mAlignment;
-
- for (int i = first; i <= last; i++) {
- int start = previousLineEnd;
-
- previousLineEnd = getLineStart(i+1);
- int end = getLineVisibleEnd(i, start, previousLineEnd);
-
- int ltop = previousLineBottom;
- int lbottom = getLineTop(i+1);
- previousLineBottom = lbottom;
- int lbaseline = lbottom - getLineDescent(i);
-
- boolean par = false;
- if (spannedText) {
- if (start == 0 || buf.charAt(start - 1) == '\n') {
- par = true;
- }
- if (start >= spanend) {
-
- Spanned sp = (Spanned) buf;
-
- spanend = sp.nextSpanTransition(start, textLength,
- ParagraphStyle.class);
- spans = sp.getSpans(start, spanend, ParagraphStyle.class);
-
- align = mAlignment;
-
- for (int n = spans.length-1; n >= 0; n--) {
- if (spans[n] instanceof AlignmentSpan) {
- align = ((AlignmentSpan) spans[n]).getAlignment();
- break;
- }
- }
- }
- }
-
- int dir = getParagraphDirection(i);
- int left = 0;
- int right = mWidth;
-
- if (spannedText) {
- final int length = spans.length;
- for (int n = 0; n < length; n++) {
- if (spans[n] instanceof LeadingMarginSpan) {
- LeadingMarginSpan margin = (LeadingMarginSpan) spans[n];
-
- if (dir == DIR_RIGHT_TO_LEFT) {
- margin.drawLeadingMargin(c, paint, right, dir, ltop,
- lbaseline, lbottom, buf,
- start, end, par, this);
-
- right -= margin.getLeadingMargin(par);
- } else {
- margin.drawLeadingMargin(c, paint, left, dir, ltop,
- lbaseline, lbottom, buf,
- start, end, par, this);
-
- left += margin.getLeadingMargin(par);
- }
- }
- }
- }
-
- int x;
- if (align == Alignment.ALIGN_NORMAL) {
- if (dir == DIR_LEFT_TO_RIGHT) {
- x = left;
- } else {
- x = right;
- }
- } else {
- int max = (int)getLineMax(i, spans, false);
- if (align == Alignment.ALIGN_OPPOSITE) {
- if (dir == DIR_RIGHT_TO_LEFT) {
- x = left + max;
- } else {
- x = right - max;
- }
- } else {
- // Alignment.ALIGN_CENTER
- max = max & ~1;
- int half = (right - left - max) >> 1;
- if (dir == DIR_RIGHT_TO_LEFT) {
- x = right - half;
- } else {
- x = left + half;
- }
- }
- }
-
- Directions directions = getLineDirections(i);
- boolean hasTab = getLineContainsTab(i);
- if (directions == DIRS_ALL_LEFT_TO_RIGHT &&
- !spannedText && !hasTab) {
- if (Config.DEBUG) {
- Assert.assertTrue(dir == DIR_LEFT_TO_RIGHT);
- Assert.assertNotNull(c);
- }
- c.drawText(buf, start, end, x, lbaseline, paint);
- } else {
- drawText(c, buf, start, end, dir, directions,
- x, ltop, lbaseline, lbottom, paint, mWorkPaint,
- hasTab, spans);
- }
- }
- }
-
- /**
- * Return the text that is displayed by this Layout.
- */
- public final CharSequence getText() {
- return mText;
- }
-
- /**
- * Return the base Paint properties for this layout.
- * Do NOT change the paint, which may result in funny
- * drawing for this layout.
- */
- public final TextPaint getPaint() {
- return mPaint;
- }
-
- /**
- * Return the width of this layout.
- */
- public final int getWidth() {
- return mWidth;
- }
-
- /**
- * Return the width to which this Layout is ellipsizing, or
- * {@link #getWidth} if it is not doing anything special.
- */
- public int getEllipsizedWidth() {
- return mWidth;
- }
-
- /**
- * Increase the width of this layout to the specified width.
- * Be careful to use this only when you know it is appropriate --
- * it does not cause the text to reflow to use the full new width.
- */
- public final void increaseWidthTo(int wid) {
- if (wid < mWidth) {
- throw new RuntimeException("attempted to reduce Layout width");
- }
-
- mWidth = wid;
- }
-
- /**
- * Return the total height of this layout.
- */
- public int getHeight() {
- return getLineTop(getLineCount()); // same as getLineBottom(getLineCount() - 1);
- }
-
- /**
- * Return the base alignment of this layout.
- */
- public final Alignment getAlignment() {
- return mAlignment;
- }
-
- /**
- * Return what the text height is multiplied by to get the line height.
- */
- public final float getSpacingMultiplier() {
- return mSpacingMult;
- }
-
- /**
- * Return the number of units of leading that are added to each line.
- */
- public final float getSpacingAdd() {
- return mSpacingAdd;
- }
-
- /**
- * Return the number of lines of text in this layout.
- */
- public abstract int getLineCount();
-
- /**
- * Return the baseline for the specified line (0&hellip;getLineCount() - 1)
- * If bounds is not null, return the top, left, right, bottom extents
- * of the specified line in it.
- * @param line which line to examine (0..getLineCount() - 1)
- * @param bounds Optional. If not null, it returns the extent of the line
- * @return the Y-coordinate of the baseline
- */
- public int getLineBounds(int line, Rect bounds) {
- if (bounds != null) {
- bounds.left = 0; // ???
- bounds.top = getLineTop(line);
- bounds.right = mWidth; // ???
- bounds.bottom = getLineBottom(line);
- }
- return getLineBaseline(line);
- }
-
- /**
- * Return the vertical position of the top of the specified line.
- * If the specified line is one beyond the last line, returns the
- * bottom of the last line.
- */
- public abstract int getLineTop(int line);
-
- /**
- * Return the descent of the specified line.
- */
- public abstract int getLineDescent(int line);
-
- /**
- * Return the text offset of the beginning of the specified line.
- * If the specified line is one beyond the last line, returns the
- * end of the last line.
- */
- public abstract int getLineStart(int line);
-
- /**
- * Returns the primary directionality of the paragraph containing
- * the specified line.
- */
- public abstract int getParagraphDirection(int line);
-
- /**
- * Returns whether the specified line contains one or more tabs.
- */
- public abstract boolean getLineContainsTab(int line);
-
- /**
- * Returns an array of directionalities for the specified line.
- * The array alternates counts of characters in left-to-right
- * and right-to-left segments of the line.
- */
- public abstract Directions getLineDirections(int line);
-
- /**
- * Returns the (negative) number of extra pixels of ascent padding in the
- * top line of the Layout.
- */
- public abstract int getTopPadding();
-
- /**
- * Returns the number of extra pixels of descent padding in the
- * bottom line of the Layout.
- */
- public abstract int getBottomPadding();
-
- /**
- * Get the primary horizontal position for the specified text offset.
- * This is the location where a new character would be inserted in
- * the paragraph's primary direction.
- */
- public float getPrimaryHorizontal(int offset) {
- return getHorizontal(offset, false, true);
- }
-
- /**
- * Get the secondary horizontal position for the specified text offset.
- * This is the location where a new character would be inserted in
- * the direction other than the paragraph's primary direction.
- */
- public float getSecondaryHorizontal(int offset) {
- return getHorizontal(offset, true, true);
- }
-
- private float getHorizontal(int offset, boolean trailing, boolean alt) {
- int line = getLineForOffset(offset);
-
- return getHorizontal(offset, trailing, alt, line);
- }
-
- private float getHorizontal(int offset, boolean trailing, boolean alt,
- int line) {
- int start = getLineStart(line);
- int end = getLineVisibleEnd(line);
- int dir = getParagraphDirection(line);
- boolean tab = getLineContainsTab(line);
- Directions directions = getLineDirections(line);
-
- TabStopSpan[] tabs = null;
- if (tab && mText instanceof Spanned) {
- tabs = ((Spanned) mText).getSpans(start, end, TabStopSpan.class);
- }
-
- float wid = measureText(mPaint, mWorkPaint, mText, start, offset, end,
- dir, directions, trailing, alt, tab, tabs);
-
- if (offset > end) {
- if (dir == DIR_RIGHT_TO_LEFT)
- wid -= measureText(mPaint, mWorkPaint,
- mText, end, offset, null, tab, tabs);
- else
- wid += measureText(mPaint, mWorkPaint,
- mText, end, offset, null, tab, tabs);
- }
-
- Alignment align = getParagraphAlignment(line);
- int left = getParagraphLeft(line);
- int right = getParagraphRight(line);
-
- if (align == Alignment.ALIGN_NORMAL) {
- if (dir == DIR_RIGHT_TO_LEFT)
- return right + wid;
- else
- return left + wid;
- }
-
- float max = getLineMax(line);
-
- if (align == Alignment.ALIGN_OPPOSITE) {
- if (dir == DIR_RIGHT_TO_LEFT)
- return left + max + wid;
- else
- return right - max + wid;
- } else { /* align == Alignment.ALIGN_CENTER */
- int imax = ((int) max) & ~1;
-
- if (dir == DIR_RIGHT_TO_LEFT)
- return right - (((right - left) - imax) / 2) + wid;
- else
- return left + ((right - left) - imax) / 2 + wid;
- }
- }
-
- /**
- * Get the leftmost position that should be exposed for horizontal
- * scrolling on the specified line.
- */
- public float getLineLeft(int line) {
- int dir = getParagraphDirection(line);
- Alignment align = getParagraphAlignment(line);
-
- if (align == Alignment.ALIGN_NORMAL) {
- if (dir == DIR_RIGHT_TO_LEFT)
- return getParagraphRight(line) - getLineMax(line);
- else
- return 0;
- } else if (align == Alignment.ALIGN_OPPOSITE) {
- if (dir == DIR_RIGHT_TO_LEFT)
- return 0;
- else
- return mWidth - getLineMax(line);
- } else { /* align == Alignment.ALIGN_CENTER */
- int left = getParagraphLeft(line);
- int right = getParagraphRight(line);
- int max = ((int) getLineMax(line)) & ~1;
-
- return left + ((right - left) - max) / 2;
- }
- }
-
- /**
- * Get the rightmost position that should be exposed for horizontal
- * scrolling on the specified line.
- */
- public float getLineRight(int line) {
- int dir = getParagraphDirection(line);
- Alignment align = getParagraphAlignment(line);
-
- if (align == Alignment.ALIGN_NORMAL) {
- if (dir == DIR_RIGHT_TO_LEFT)
- return mWidth;
- else
- return getParagraphLeft(line) + getLineMax(line);
- } else if (align == Alignment.ALIGN_OPPOSITE) {
- if (dir == DIR_RIGHT_TO_LEFT)
- return getLineMax(line);
- else
- return mWidth;
- } else { /* align == Alignment.ALIGN_CENTER */
- int left = getParagraphLeft(line);
- int right = getParagraphRight(line);
- int max = ((int) getLineMax(line)) & ~1;
-
- return right - ((right - left) - max) / 2;
- }
- }
-
- /**
- * Gets the horizontal extent of the specified line, excluding
- * trailing whitespace.
- */
- public float getLineMax(int line) {
- return getLineMax(line, null, false);
- }
-
- /**
- * Gets the horizontal extent of the specified line, including
- * trailing whitespace.
- */
- public float getLineWidth(int line) {
- return getLineMax(line, null, true);
- }
-
- private float getLineMax(int line, Object[] tabs, boolean full) {
- int start = getLineStart(line);
- int end;
-
- if (full) {
- end = getLineEnd(line);
- } else {
- end = getLineVisibleEnd(line);
- }
- boolean tab = getLineContainsTab(line);
-
- if (tabs == null && tab && mText instanceof Spanned) {
- tabs = ((Spanned) mText).getSpans(start, end, TabStopSpan.class);
- }
-
- return measureText(mPaint, mWorkPaint,
- mText, start, end, null, tab, tabs);
- }
-
- /**
- * Get the line number corresponding to the specified vertical position.
- * If you ask for a position above 0, you get 0; if you ask for a position
- * below the bottom of the text, you get the last line.
- */
- // FIXME: It may be faster to do a linear search for layouts without many lines.
- public int getLineForVertical(int vertical) {
- int high = getLineCount(), low = -1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
-
- if (getLineTop(guess) > vertical)
- high = guess;
- else
- low = guess;
- }
-
- if (low < 0)
- return 0;
- else
- return low;
- }
-
- /**
- * Get the line number on which the specified text offset appears.
- * If you ask for a position before 0, you get 0; if you ask for a position
- * beyond the end of the text, you get the last line.
- */
- public int getLineForOffset(int offset) {
- int high = getLineCount(), low = -1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
-
- if (getLineStart(guess) > offset)
- high = guess;
- else
- low = guess;
- }
-
- if (low < 0)
- return 0;
- else
- return low;
- }
-
- /**
- * Get the character offset on the specfied line whose position is
- * closest to the specified horizontal position.
- */
- public int getOffsetForHorizontal(int line, float horiz) {
- int max = getLineEnd(line) - 1;
- int min = getLineStart(line);
- Directions dirs = getLineDirections(line);
-
- if (line == getLineCount() - 1)
- max++;
-
- int best = min;
- float bestdist = Math.abs(getPrimaryHorizontal(best) - horiz);
-
- int here = min;
- for (int i = 0; i < dirs.mDirections.length; i++) {
- int there = here + dirs.mDirections[i];
- int swap = ((i & 1) == 0) ? 1 : -1;
-
- if (there > max)
- there = max;
-
- int high = there - 1 + 1, low = here + 1 - 1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
- int adguess = getOffsetAtStartOf(guess);
-
- if (getPrimaryHorizontal(adguess) * swap >= horiz * swap)
- high = guess;
- else
- low = guess;
- }
-
- if (low < here + 1)
- low = here + 1;
-
- if (low < there) {
- low = getOffsetAtStartOf(low);
-
- float dist = Math.abs(getPrimaryHorizontal(low) - horiz);
-
- int aft = TextUtils.getOffsetAfter(mText, low);
- if (aft < there) {
- float other = Math.abs(getPrimaryHorizontal(aft) - horiz);
-
- if (other < dist) {
- dist = other;
- low = aft;
- }
- }
-
- if (dist < bestdist) {
- bestdist = dist;
- best = low;
- }
- }
-
- float dist = Math.abs(getPrimaryHorizontal(here) - horiz);
-
- if (dist < bestdist) {
- bestdist = dist;
- best = here;
- }
-
- here = there;
- }
-
- float dist = Math.abs(getPrimaryHorizontal(max) - horiz);
-
- if (dist < bestdist) {
- bestdist = dist;
- best = max;
- }
-
- return best;
- }
-
- /**
- * Return the text offset after the last character on the specified line.
- */
- public final int getLineEnd(int line) {
- return getLineStart(line + 1);
- }
-
- /**
- * Return the text offset after the last visible character (so whitespace
- * is not counted) on the specified line.
- */
- public int getLineVisibleEnd(int line) {
- return getLineVisibleEnd(line, getLineStart(line), getLineStart(line+1));
- }
-
- private int getLineVisibleEnd(int line, int start, int end) {
- if (Config.DEBUG) {
- Assert.assertTrue(getLineStart(line) == start && getLineStart(line+1) == end);
- }
-
- CharSequence text = mText;
- char ch;
- if (line == getLineCount() - 1) {
- return end;
- }
-
- for (; end > start; end--) {
- ch = text.charAt(end - 1);
-
- if (ch == '\n') {
- return end - 1;
- }
-
- if (ch != ' ' && ch != '\t') {
- break;
- }
-
- }
-
- return end;
- }
-
- /**
- * Return the vertical position of the bottom of the specified line.
- */
- public final int getLineBottom(int line) {
- return getLineTop(line + 1);
- }
-
- /**
- * Return the vertical position of the baseline of the specified line.
- */
- public final int getLineBaseline(int line) {
- // getLineTop(line+1) == getLineTop(line)
- return getLineTop(line+1) - getLineDescent(line);
- }
-
- /**
- * Get the ascent of the text on the specified line.
- * The return value is negative to match the Paint.ascent() convention.
- */
- public final int getLineAscent(int line) {
- // getLineTop(line+1) - getLineDescent(line) == getLineBaseLine(line)
- return getLineTop(line) - (getLineTop(line+1) - getLineDescent(line));
- }
-
- /**
- * Return the text offset that would be reached by moving left
- * (possibly onto another line) from the specified offset.
- */
- public int getOffsetToLeftOf(int offset) {
- int line = getLineForOffset(offset);
- int start = getLineStart(line);
- int end = getLineEnd(line);
- Directions dirs = getLineDirections(line);
-
- if (line != getLineCount() - 1)
- end--;
-
- float horiz = getPrimaryHorizontal(offset);
-
- int best = offset;
- float besth = Integer.MIN_VALUE;
- int candidate;
-
- candidate = TextUtils.getOffsetBefore(mText, offset);
- if (candidate >= start && candidate <= end) {
- float h = getPrimaryHorizontal(candidate);
-
- if (h < horiz && h > besth) {
- best = candidate;
- besth = h;
- }
- }
-
- candidate = TextUtils.getOffsetAfter(mText, offset);
- if (candidate >= start && candidate <= end) {
- float h = getPrimaryHorizontal(candidate);
-
- if (h < horiz && h > besth) {
- best = candidate;
- besth = h;
- }
- }
-
- int here = start;
- for (int i = 0; i < dirs.mDirections.length; i++) {
- int there = here + dirs.mDirections[i];
- if (there > end)
- there = end;
-
- float h = getPrimaryHorizontal(here);
-
- if (h < horiz && h > besth) {
- best = here;
- besth = h;
- }
-
- candidate = TextUtils.getOffsetAfter(mText, here);
- if (candidate >= start && candidate <= end) {
- h = getPrimaryHorizontal(candidate);
-
- if (h < horiz && h > besth) {
- best = candidate;
- besth = h;
- }
- }
-
- candidate = TextUtils.getOffsetBefore(mText, there);
- if (candidate >= start && candidate <= end) {
- h = getPrimaryHorizontal(candidate);
-
- if (h < horiz && h > besth) {
- best = candidate;
- besth = h;
- }
- }
-
- here = there;
- }
-
- float h = getPrimaryHorizontal(end);
-
- if (h < horiz && h > besth) {
- best = end;
- besth = h;
- }
-
- if (best != offset)
- return best;
-
- int dir = getParagraphDirection(line);
-
- if (dir > 0) {
- if (line == 0)
- return best;
- else
- return getOffsetForHorizontal(line - 1, 10000);
- } else {
- if (line == getLineCount() - 1)
- return best;
- else
- return getOffsetForHorizontal(line + 1, 10000);
- }
- }
-
- /**
- * Return the text offset that would be reached by moving right
- * (possibly onto another line) from the specified offset.
- */
- public int getOffsetToRightOf(int offset) {
- int line = getLineForOffset(offset);
- int start = getLineStart(line);
- int end = getLineEnd(line);
- Directions dirs = getLineDirections(line);
-
- if (line != getLineCount() - 1)
- end--;
-
- float horiz = getPrimaryHorizontal(offset);
-
- int best = offset;
- float besth = Integer.MAX_VALUE;
- int candidate;
-
- candidate = TextUtils.getOffsetBefore(mText, offset);
- if (candidate >= start && candidate <= end) {
- float h = getPrimaryHorizontal(candidate);
-
- if (h > horiz && h < besth) {
- best = candidate;
- besth = h;
- }
- }
-
- candidate = TextUtils.getOffsetAfter(mText, offset);
- if (candidate >= start && candidate <= end) {
- float h = getPrimaryHorizontal(candidate);
-
- if (h > horiz && h < besth) {
- best = candidate;
- besth = h;
- }
- }
-
- int here = start;
- for (int i = 0; i < dirs.mDirections.length; i++) {
- int there = here + dirs.mDirections[i];
- if (there > end)
- there = end;
-
- float h = getPrimaryHorizontal(here);
-
- if (h > horiz && h < besth) {
- best = here;
- besth = h;
- }
-
- candidate = TextUtils.getOffsetAfter(mText, here);
- if (candidate >= start && candidate <= end) {
- h = getPrimaryHorizontal(candidate);
-
- if (h > horiz && h < besth) {
- best = candidate;
- besth = h;
- }
- }
-
- candidate = TextUtils.getOffsetBefore(mText, there);
- if (candidate >= start && candidate <= end) {
- h = getPrimaryHorizontal(candidate);
-
- if (h > horiz && h < besth) {
- best = candidate;
- besth = h;
- }
- }
-
- here = there;
- }
-
- float h = getPrimaryHorizontal(end);
-
- if (h > horiz && h < besth) {
- best = end;
- besth = h;
- }
-
- if (best != offset)
- return best;
-
- int dir = getParagraphDirection(line);
-
- if (dir > 0) {
- if (line == getLineCount() - 1)
- return best;
- else
- return getOffsetForHorizontal(line + 1, -10000);
- } else {
- if (line == 0)
- return best;
- else
- return getOffsetForHorizontal(line - 1, -10000);
- }
- }
-
- private int getOffsetAtStartOf(int offset) {
- if (offset == 0)
- return 0;
-
- CharSequence text = mText;
- char c = text.charAt(offset);
-
- if (c >= '\uDC00' && c <= '\uDFFF') {
- char c1 = text.charAt(offset - 1);
-
- if (c1 >= '\uD800' && c1 <= '\uDBFF')
- offset -= 1;
- }
-
- if (mSpannedText) {
- ReplacementSpan[] spans = ((Spanned) text).getSpans(offset, offset,
- ReplacementSpan.class);
-
- for (int i = 0; i < spans.length; i++) {
- int start = ((Spanned) text).getSpanStart(spans[i]);
- int end = ((Spanned) text).getSpanEnd(spans[i]);
-
- if (start < offset && end > offset)
- offset = start;
- }
- }
-
- return offset;
- }
-
- /**
- * Fills in the specified Path with a representation of a cursor
- * at the specified offset. This will often be a vertical line
- * but can be multiple discontinous lines in text with multiple
- * directionalities.
- */
- public void getCursorPath(int point, Path dest,
- CharSequence editingBuffer) {
- dest.reset();
-
- int line = getLineForOffset(point);
- int top = getLineTop(line);
- int bottom = getLineTop(line+1);
-
- float h1 = getPrimaryHorizontal(point) - 0.5f;
- float h2 = getSecondaryHorizontal(point) - 0.5f;
-
- int caps = TextKeyListener.getMetaState(editingBuffer,
- KeyEvent.META_SHIFT_ON) |
- TextKeyListener.getMetaState(editingBuffer,
- TextKeyListener.META_SELECTING);
- int fn = TextKeyListener.getMetaState(editingBuffer,
- KeyEvent.META_ALT_ON);
- int dist = 0;
-
- if (caps != 0 || fn != 0) {
- dist = (bottom - top) >> 2;
-
- if (fn != 0)
- top += dist;
- if (caps != 0)
- bottom -= dist;
- }
-
- if (h1 < 0.5f)
- h1 = 0.5f;
- if (h2 < 0.5f)
- h2 = 0.5f;
-
- if (h1 == h2) {
- dest.moveTo(h1, top);
- dest.lineTo(h1, bottom);
- } else {
- dest.moveTo(h1, top);
- dest.lineTo(h1, (top + bottom) >> 1);
-
- dest.moveTo(h2, (top + bottom) >> 1);
- dest.lineTo(h2, bottom);
- }
-
- if (caps == 2) {
- dest.moveTo(h2, bottom);
- dest.lineTo(h2 - dist, bottom + dist);
- dest.lineTo(h2, bottom);
- dest.lineTo(h2 + dist, bottom + dist);
- } else if (caps == 1) {
- dest.moveTo(h2, bottom);
- dest.lineTo(h2 - dist, bottom + dist);
-
- dest.moveTo(h2 - dist, bottom + dist - 0.5f);
- dest.lineTo(h2 + dist, bottom + dist - 0.5f);
-
- dest.moveTo(h2 + dist, bottom + dist);
- dest.lineTo(h2, bottom);
- }
-
- if (fn == 2) {
- dest.moveTo(h1, top);
- dest.lineTo(h1 - dist, top - dist);
- dest.lineTo(h1, top);
- dest.lineTo(h1 + dist, top - dist);
- } else if (fn == 1) {
- dest.moveTo(h1, top);
- dest.lineTo(h1 - dist, top - dist);
-
- dest.moveTo(h1 - dist, top - dist + 0.5f);
- dest.lineTo(h1 + dist, top - dist + 0.5f);
-
- dest.moveTo(h1 + dist, top - dist);
- dest.lineTo(h1, top);
- }
- }
-
- private void addSelection(int line, int start, int end,
- int top, int bottom, Path dest) {
- int linestart = getLineStart(line);
- int lineend = getLineEnd(line);
- Directions dirs = getLineDirections(line);
-
- if (lineend > linestart && mText.charAt(lineend - 1) == '\n')
- lineend--;
-
- int here = linestart;
- for (int i = 0; i < dirs.mDirections.length; i++) {
- int there = here + dirs.mDirections[i];
- if (there > lineend)
- there = lineend;
-
- if (start <= there && end >= here) {
- int st = Math.max(start, here);
- int en = Math.min(end, there);
-
- if (st != en) {
- float h1 = getHorizontal(st, false, false, line);
- float h2 = getHorizontal(en, true, false, line);
-
- dest.addRect(h1, top, h2, bottom, Path.Direction.CW);
- }
- }
-
- here = there;
- }
- }
-
- /**
- * Fills in the specified Path with a representation of a highlight
- * between the specified offsets. This will often be a rectangle
- * or a potentially discontinuous set of rectangles. If the start
- * and end are the same, the returned path is empty.
- */
- public void getSelectionPath(int start, int end, Path dest) {
- dest.reset();
-
- if (start == end)
- return;
-
- if (end < start) {
- int temp = end;
- end = start;
- start = temp;
- }
-
- int startline = getLineForOffset(start);
- int endline = getLineForOffset(end);
-
- int top = getLineTop(startline);
- int bottom = getLineBottom(endline);
-
- if (startline == endline) {
- addSelection(startline, start, end, top, bottom, dest);
- } else {
- final float width = mWidth;
-
- addSelection(startline, start, getLineEnd(startline),
- top, getLineBottom(startline), dest);
-
- if (getParagraphDirection(startline) == DIR_RIGHT_TO_LEFT)
- dest.addRect(getLineLeft(startline), top,
- 0, getLineBottom(startline), Path.Direction.CW);
- else
- dest.addRect(getLineRight(startline), top,
- width, getLineBottom(startline), Path.Direction.CW);
-
- for (int i = startline + 1; i < endline; i++) {
- top = getLineTop(i);
- bottom = getLineBottom(i);
- dest.addRect(0, top, width, bottom, Path.Direction.CW);
- }
-
- top = getLineTop(endline);
- bottom = getLineBottom(endline);
-
- addSelection(endline, getLineStart(endline), end,
- top, bottom, dest);
-
- if (getParagraphDirection(endline) == DIR_RIGHT_TO_LEFT)
- dest.addRect(width, top, getLineRight(endline), bottom, Path.Direction.CW);
- else
- dest.addRect(0, top, getLineLeft(endline), bottom, Path.Direction.CW);
- }
- }
-
- /**
- * Get the alignment of the specified paragraph, taking into account
- * markup attached to it.
- */
- public final Alignment getParagraphAlignment(int line) {
- Alignment align = mAlignment;
-
- if (mSpannedText) {
- Spanned sp = (Spanned) mText;
- AlignmentSpan[] spans = sp.getSpans(getLineStart(line),
- getLineEnd(line),
- AlignmentSpan.class);
-
- int spanLength = spans.length;
- if (spanLength > 0) {
- align = spans[spanLength-1].getAlignment();
- }
- }
-
- return align;
- }
-
- /**
- * Get the left edge of the specified paragraph, inset by left margins.
- */
- public final int getParagraphLeft(int line) {
- int dir = getParagraphDirection(line);
-
- int left = 0;
-
- boolean par = false;
- int off = getLineStart(line);
- if (off == 0 || mText.charAt(off - 1) == '\n')
- par = true;
-
- if (dir == DIR_LEFT_TO_RIGHT) {
- if (mSpannedText) {
- Spanned sp = (Spanned) mText;
- LeadingMarginSpan[] spans = sp.getSpans(getLineStart(line),
- getLineEnd(line),
- LeadingMarginSpan.class);
-
- for (int i = 0; i < spans.length; i++) {
- left += spans[i].getLeadingMargin(par);
- }
- }
- }
-
- return left;
- }
-
- /**
- * Get the right edge of the specified paragraph, inset by right margins.
- */
- public final int getParagraphRight(int line) {
- int dir = getParagraphDirection(line);
-
- int right = mWidth;
-
- boolean par = false;
- int off = getLineStart(line);
- if (off == 0 || mText.charAt(off - 1) == '\n')
- par = true;
-
-
- if (dir == DIR_RIGHT_TO_LEFT) {
- if (mSpannedText) {
- Spanned sp = (Spanned) mText;
- LeadingMarginSpan[] spans = sp.getSpans(getLineStart(line),
- getLineEnd(line),
- LeadingMarginSpan.class);
-
- for (int i = 0; i < spans.length; i++) {
- right -= spans[i].getLeadingMargin(par);
- }
- }
- }
-
- return right;
- }
-
- private static void drawText(Canvas canvas,
- CharSequence text, int start, int end,
- int dir, Directions directions,
- float x, int top, int y, int bottom,
- TextPaint paint,
- TextPaint workPaint,
- boolean hasTabs, Object[] parspans) {
- char[] buf;
- if (!hasTabs) {
- if (directions == DIRS_ALL_LEFT_TO_RIGHT) {
- if (Config.DEBUG) {
- Assert.assertTrue(DIR_LEFT_TO_RIGHT == dir);
- }
- Styled.drawText(canvas, text, start, end, dir, false, x, top, y, bottom, paint, workPaint, false);
- return;
- }
- buf = null;
- } else {
- buf = TextUtils.obtain(end - start);
- TextUtils.getChars(text, start, end, buf, 0);
- }
-
- float h = 0;
-
- int here = 0;
- for (int i = 0; i < directions.mDirections.length; i++) {
- int there = here + directions.mDirections[i];
- if (there > end - start)
- there = end - start;
-
- int segstart = here;
- for (int j = hasTabs ? here : there; j <= there; j++) {
- if (j == there || buf[j] == '\t') {
- h += Styled.drawText(canvas, text,
- start + segstart, start + j,
- dir, (i & 1) != 0, x + h,
- top, y, bottom, paint, workPaint,
- start + j != end);
-
- if (j != there && buf[j] == '\t')
- h = dir * nextTab(text, start, end, h * dir, parspans);
-
- segstart = j + 1;
- }
- }
-
- here = there;
- }
-
- if (hasTabs)
- TextUtils.recycle(buf);
- }
-
- private static float measureText(TextPaint paint,
- TextPaint workPaint,
- CharSequence text,
- int start, int offset, int end,
- int dir, Directions directions,
- boolean trailing, boolean alt,
- boolean hasTabs, Object[] tabs) {
- char[] buf = null;
-
- if (hasTabs) {
- buf = TextUtils.obtain(end - start);
- TextUtils.getChars(text, start, end, buf, 0);
- }
-
- float h = 0;
-
- if (alt) {
- if (dir == DIR_RIGHT_TO_LEFT)
- trailing = !trailing;
- }
-
- int here = 0;
- for (int i = 0; i < directions.mDirections.length; i++) {
- if (alt)
- trailing = !trailing;
-
- int there = here + directions.mDirections[i];
- if (there > end - start)
- there = end - start;
-
- int segstart = here;
- for (int j = hasTabs ? here : there; j <= there; j++) {
- if (j == there || buf[j] == '\t') {
- float segw;
-
- if (offset < start + j ||
- (trailing && offset <= start + j)) {
- if (dir == DIR_LEFT_TO_RIGHT && (i & 1) == 0) {
- h += Styled.measureText(paint, workPaint, text,
- start + segstart, offset,
- null);
- return h;
- }
-
- if (dir == DIR_RIGHT_TO_LEFT && (i & 1) != 0) {
- h -= Styled.measureText(paint, workPaint, text,
- start + segstart, offset,
- null);
- return h;
- }
- }
-
- segw = Styled.measureText(paint, workPaint, text,
- start + segstart, start + j,
- null);
-
- if (offset < start + j ||
- (trailing && offset <= start + j)) {
- if (dir == DIR_LEFT_TO_RIGHT) {
- h += segw - Styled.measureText(paint, workPaint,
- text,
- start + segstart,
- offset, null);
- return h;
- }
-
- if (dir == DIR_RIGHT_TO_LEFT) {
- h -= segw - Styled.measureText(paint, workPaint,
- text,
- start + segstart,
- offset, null);
- return h;
- }
- }
-
- if (dir == DIR_RIGHT_TO_LEFT)
- h -= segw;
- else
- h += segw;
-
- if (j != there && buf[j] == '\t') {
- if (offset == start + j)
- return h;
-
- h = dir * nextTab(text, start, end, h * dir, tabs);
- }
-
- segstart = j + 1;
- }
- }
-
- here = there;
- }
-
- if (hasTabs)
- TextUtils.recycle(buf);
-
- return h;
- }
-
- /* package */ static float measureText(TextPaint paint,
- TextPaint workPaint,
- CharSequence text,
- int start, int end,
- Paint.FontMetricsInt fm,
- boolean hasTabs, Object[] tabs) {
- char[] buf = null;
-
- if (hasTabs) {
- buf = TextUtils.obtain(end - start);
- TextUtils.getChars(text, start, end, buf, 0);
- }
-
- int len = end - start;
-
- int here = 0;
- float h = 0;
- int ab = 0, be = 0;
- int top = 0, bot = 0;
-
- if (fm != null) {
- fm.ascent = 0;
- fm.descent = 0;
- }
-
- for (int i = hasTabs ? 0 : len; i <= len; i++) {
- if (i == len || buf[i] == '\t') {
- workPaint.baselineShift = 0;
-
- h += Styled.measureText(paint, workPaint, text,
- start + here, start + i,
- fm);
-
- if (fm != null) {
- if (workPaint.baselineShift < 0) {
- fm.ascent += workPaint.baselineShift;
- fm.top += workPaint.baselineShift;
- } else {
- fm.descent += workPaint.baselineShift;
- fm.bottom += workPaint.baselineShift;
- }
- }
-
- if (i != len)
- h = nextTab(text, start, end, h, tabs);
-
- if (fm != null) {
- if (fm.ascent < ab) {
- ab = fm.ascent;
- }
- if (fm.descent > be) {
- be = fm.descent;
- }
-
- if (fm.top < top) {
- top = fm.top;
- }
- if (fm.bottom > bot) {
- bot = fm.bottom;
- }
- }
-
- here = i + 1;
- }
- }
-
- if (fm != null) {
- fm.ascent = ab;
- fm.descent = be;
- fm.top = top;
- fm.bottom = bot;
- }
-
- if (hasTabs)
- TextUtils.recycle(buf);
-
- return h;
- }
-
- /* package */ static float nextTab(CharSequence text, int start, int end,
- float h, Object[] tabs) {
- float nh = Float.MAX_VALUE;
- boolean alltabs = false;
-
- if (text instanceof Spanned) {
- if (tabs == null) {
- tabs = ((Spanned) text).getSpans(start, end, TabStopSpan.class);
- alltabs = true;
- }
-
- for (int i = 0; i < tabs.length; i++) {
- if (!alltabs) {
- if (!(tabs[i] instanceof TabStopSpan))
- continue;
- }
-
- int where = ((TabStopSpan) tabs[i]).getTabStop();
-
- if (where < nh && where > h)
- nh = where;
- }
-
- if (nh != Float.MAX_VALUE)
- return nh;
- }
-
- return ((int) ((h + TAB_INCREMENT) / TAB_INCREMENT)) * TAB_INCREMENT;
- }
-
- protected final boolean isSpanned() {
- return mSpannedText;
- }
-
- private void ellipsize(int start, int end, int line,
- char[] dest, int destoff) {
- int ellipsisCount = getEllipsisCount(line);
-
- if (ellipsisCount == 0) {
- return;
- }
-
- int ellipsisStart = getEllipsisStart(line);
- int linestart = getLineStart(line);
-
- for (int i = ellipsisStart; i < ellipsisStart + ellipsisCount; i++) {
- char c;
-
- if (i == ellipsisStart) {
- c = '\u2026'; // ellipsis
- } else {
- c = '\uFEFF'; // 0-width space
- }
-
- int a = i + linestart;
-
- if (a >= start && a < end) {
- dest[destoff + a - start] = c;
- }
- }
- }
-
- /**
- * Stores information about bidirectional (left-to-right or right-to-left)
- * text within the layout of a line. TODO: This work is not complete
- * or correct and will be fleshed out in a later revision.
- */
- public static class Directions {
- private short[] mDirections;
-
- /* package */ Directions(short[] dirs) {
- mDirections = dirs;
- }
- }
-
- /**
- * Return the offset of the first character to be ellipsized away,
- * relative to the start of the line. (So 0 if the beginning of the
- * line is ellipsized, not getLineStart().)
- */
- public abstract int getEllipsisStart(int line);
- /**
- * Returns the number of characters to be ellipsized away, or 0 if
- * no ellipsis is to take place.
- */
- public abstract int getEllipsisCount(int line);
-
- /* package */ static class Ellipsizer implements CharSequence, GetChars {
- /* package */ CharSequence mText;
- /* package */ Layout mLayout;
- /* package */ int mWidth;
- /* package */ TextUtils.TruncateAt mMethod;
-
- public Ellipsizer(CharSequence s) {
- mText = s;
- }
-
- public char charAt(int off) {
- char[] buf = TextUtils.obtain(1);
- getChars(off, off + 1, buf, 0);
- char ret = buf[0];
-
- TextUtils.recycle(buf);
- return ret;
- }
-
- public void getChars(int start, int end, char[] dest, int destoff) {
- int line1 = mLayout.getLineForOffset(start);
- int line2 = mLayout.getLineForOffset(end);
-
- TextUtils.getChars(mText, start, end, dest, destoff);
-
- for (int i = line1; i <= line2; i++) {
- mLayout.ellipsize(start, end, i, dest, destoff);
- }
- }
-
- public int length() {
- return mText.length();
- }
-
- public CharSequence subSequence(int start, int end) {
- char[] s = new char[end - start];
- getChars(start, end, s, 0);
- return new String(s);
- }
-
- public String toString() {
- char[] s = new char[length()];
- getChars(0, length(), s, 0);
- return new String(s);
- }
-
- }
-
- /* package */ static class SpannedEllipsizer
- extends Ellipsizer implements Spanned {
- private Spanned mSpanned;
-
- public SpannedEllipsizer(CharSequence display) {
- super(display);
- mSpanned = (Spanned) display;
- }
-
- public <T> T[] getSpans(int start, int end, Class<T> type) {
- return mSpanned.getSpans(start, end, type);
- }
-
- public int getSpanStart(Object tag) {
- return mSpanned.getSpanStart(tag);
- }
-
- public int getSpanEnd(Object tag) {
- return mSpanned.getSpanEnd(tag);
- }
-
- public int getSpanFlags(Object tag) {
- return mSpanned.getSpanFlags(tag);
- }
-
- public int nextSpanTransition(int start, int limit, Class type) {
- return mSpanned.nextSpanTransition(start, limit, type);
- }
-
- public CharSequence subSequence(int start, int end) {
- char[] s = new char[end - start];
- getChars(start, end, s, 0);
-
- SpannableString ss = new SpannableString(new String(s));
- TextUtils.copySpansFrom(mSpanned, start, end, Object.class, ss, 0);
- return ss;
- }
- }
-
- private CharSequence mText;
- private TextPaint mPaint;
- /* package */ TextPaint mWorkPaint;
- private int mWidth;
- private Alignment mAlignment = Alignment.ALIGN_NORMAL;
- private float mSpacingMult;
- private float mSpacingAdd;
- private static Rect sTempRect = new Rect();
- private boolean mSpannedText;
-
- public static final int DIR_LEFT_TO_RIGHT = 1;
- public static final int DIR_RIGHT_TO_LEFT = -1;
-
- public enum Alignment {
- ALIGN_NORMAL,
- ALIGN_OPPOSITE,
- ALIGN_CENTER,
- // XXX ALIGN_LEFT,
- // XXX ALIGN_RIGHT,
- }
-
- private static final int TAB_INCREMENT = 20;
-
- /* package */ static final Directions DIRS_ALL_LEFT_TO_RIGHT =
- new Directions(new short[] { 32767 });
- /* package */ static final Directions DIRS_ALL_RIGHT_TO_LEFT =
- new Directions(new short[] { 0, 32767 });
-
-}
-
diff --git a/core/java/android/text/LoginFilter.java b/core/java/android/text/LoginFilter.java
deleted file mode 100644
index 27c703f..0000000
--- a/core/java/android/text/LoginFilter.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-/**
- * Abstract class for filtering login-related text (user names and passwords)
- *
- */
-public abstract class LoginFilter implements InputFilter {
- private boolean mAppendInvalid; // whether to append or ignore invalid characters
- /**
- * Base constructor for LoginFilter
- * @param appendInvalid whether or not to append invalid characters.
- */
- LoginFilter(boolean appendInvalid) {
- mAppendInvalid = appendInvalid;
- }
-
- /**
- * Default constructor for LoginFilter doesn't append invalid characters.
- */
- LoginFilter() {
- mAppendInvalid = false;
- }
-
- /**
- * This method is called when the buffer is going to replace the
- * range <code>dstart &hellip; dend</code> of <code>dest</code>
- * with the new text from the range <code>start &hellip; end</code>
- * of <code>source</code>. Returns the CharSequence that we want
- * placed there instead, including an empty string
- * if appropriate, or <code>null</code> to accept the original
- * replacement. Be careful to not to reject 0-length replacements,
- * as this is what happens when you delete text.
- */
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend) {
- char[] out = new char[end - start]; // reserve enough space for whole string
- int outidx = 0;
- boolean changed = false;
-
- onStart();
-
- // Scan through beginning characters in dest, calling onInvalidCharacter()
- // for each invalid character.
- for (int i = 0; i < dstart; i++) {
- char c = dest.charAt(i);
- if (!isAllowed(c)) onInvalidCharacter(c);
- }
-
- // Scan through changed characters rejecting disallowed chars
- for (int i = start; i < end; i++) {
- char c = source.charAt(i);
- if (isAllowed(c)) {
- // Character allowed. Add it to the sequence.
- out[outidx++] = c;
- } else {
- if (mAppendInvalid) out[outidx++] = c;
- else changed = true; // we changed the original string
- onInvalidCharacter(c);
- }
- }
-
- // Scan through remaining characters in dest, calling onInvalidCharacter()
- // for each invalid character.
- for (int i = dend; i < dest.length(); i++) {
- char c = dest.charAt(i);
- if (!isAllowed(c)) onInvalidCharacter(c);
- }
-
- onStop();
-
- if (!changed) {
- return null;
- }
-
- String s = new String(out, 0, outidx);
-
- if (source instanceof Spanned) {
- SpannableString sp = new SpannableString(s);
- TextUtils.copySpansFrom((Spanned) source,
- start, end, null, sp, 0);
- return sp;
- } else {
- return s;
- }
- }
-
- /**
- * Called when we start processing filter.
- */
- public void onStart() {
-
- }
-
- /**
- * Called whenever we encounter an invalid character.
- * @param c the invalid character
- */
- public void onInvalidCharacter(char c) {
-
- }
-
- /**
- * Called when we're done processing filter
- */
- public void onStop() {
-
- }
-
- /**
- * Returns whether or not we allow character c.
- * Subclasses must override this method.
- */
- public abstract boolean isAllowed(char c);
-
- /**
- * This filter rejects characters in the user name that are not compatible with GMail
- * account creation. It prevents the user from entering user names with characters other than
- * [a-zA-Z0-9.].
- *
- */
- public static class UsernameFilterGMail extends LoginFilter {
-
- public UsernameFilterGMail() {
- super(false);
- }
-
- public UsernameFilterGMail(boolean appendInvalid) {
- super(appendInvalid);
- }
-
- @Override
- public boolean isAllowed(char c) {
- // Allow [a-zA-Z0-9@.]
- if ('0' <= c && c <= '9')
- return true;
- if ('a' <= c && c <= 'z')
- return true;
- if ('A' <= c && c <= 'Z')
- return true;
- if ('.' == c)
- return true;
- return false;
- }
- }
-
- /**
- * This filter rejects characters in the user name that are not compatible with Google login.
- * It is slightly less restrictive than the above filter in that it allows [a-zA-Z0-9._-].
- *
- */
- public static class UsernameFilterGeneric extends LoginFilter {
- private static final String mAllowed = "@_-."; // Additional characters
-
- public UsernameFilterGeneric() {
- super(false);
- }
-
- public UsernameFilterGeneric(boolean appendInvalid) {
- super(appendInvalid);
- }
-
- @Override
- public boolean isAllowed(char c) {
- // Allow [a-zA-Z0-9@.]
- if ('0' <= c && c <= '9')
- return true;
- if ('a' <= c && c <= 'z')
- return true;
- if ('A' <= c && c <= 'Z')
- return true;
- if (mAllowed.indexOf(c) != -1)
- return true;
- return false;
- }
- }
-
- /**
- * This filter is compatible with GMail passwords which restricts characters to
- * the Latin-1 (ISO8859-1) char set.
- *
- */
- public static class PasswordFilterGMail extends LoginFilter {
-
- public PasswordFilterGMail() {
- super(false);
- }
-
- public PasswordFilterGMail(boolean appendInvalid) {
- super(appendInvalid);
- }
-
- // We should reject anything not in the Latin-1 (ISO8859-1) charset
- @Override
- public boolean isAllowed(char c) {
- if (32 <= c && c <= 127)
- return true; // standard charset
- // if (128 <= c && c <= 159) return true; // nonstandard (Windows(TM)(R)) charset
- if (160 <= c && c <= 255)
- return true; // extended charset
- return false;
- }
- }
-}
diff --git a/core/java/android/text/NoCopySpan.java b/core/java/android/text/NoCopySpan.java
deleted file mode 100644
index 0855c0b..0000000
--- a/core/java/android/text/NoCopySpan.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-/**
- * This interface should be added to a span object that should not be copied
- * into a new Spenned when performing a slice or copy operation on the original
- * Spanned it was placed in.
- */
-public interface NoCopySpan {
- /**
- * Convenience equivalent for when you would just want a new Object() for
- * a span but want it to be no-copy. Use this instead.
- */
- public class Concrete implements NoCopySpan {
- }
-}
diff --git a/core/java/android/text/PackedIntVector.java b/core/java/android/text/PackedIntVector.java
deleted file mode 100644
index d87f600..0000000
--- a/core/java/android/text/PackedIntVector.java
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import com.android.internal.util.ArrayUtils;
-
-
-/**
- * PackedIntVector stores a two-dimensional array of integers,
- * optimized for inserting and deleting rows and for
- * offsetting the values in segments of a given column.
- */
-class PackedIntVector {
- private final int mColumns;
- private int mRows;
-
- private int mRowGapStart;
- private int mRowGapLength;
-
- private int[] mValues;
- private int[] mValueGap; // starts, followed by lengths
-
- /**
- * Creates a new PackedIntVector with the specified width and
- * a height of 0.
- *
- * @param columns the width of the PackedIntVector.
- */
- public PackedIntVector(int columns) {
- mColumns = columns;
- mRows = 0;
-
- mRowGapStart = 0;
- mRowGapLength = mRows;
-
- mValues = null;
- mValueGap = new int[2 * columns];
- }
-
- /**
- * Returns the value at the specified row and column.
- *
- * @param row the index of the row to return.
- * @param column the index of the column to return.
- *
- * @return the value stored at the specified position.
- *
- * @throws IndexOutOfBoundsException if the row is out of range
- * (row &lt; 0 || row >= size()) or the column is out of range
- * (column &lt; 0 || column >= width()).
- */
- public int getValue(int row, int column) {
- final int columns = mColumns;
-
- if (((row | column) < 0) || (row >= size()) || (column >= columns)) {
- throw new IndexOutOfBoundsException(row + ", " + column);
- }
-
- if (row >= mRowGapStart) {
- row += mRowGapLength;
- }
-
- int value = mValues[row * columns + column];
-
- int[] valuegap = mValueGap;
- if (row >= valuegap[column]) {
- value += valuegap[column + columns];
- }
-
- return value;
- }
-
- /**
- * Sets the value at the specified row and column.
- *
- * @param row the index of the row to set.
- * @param column the index of the column to set.
- *
- * @throws IndexOutOfBoundsException if the row is out of range
- * (row &lt; 0 || row >= size()) or the column is out of range
- * (column &lt; 0 || column >= width()).
- */
- public void setValue(int row, int column, int value) {
- if (((row | column) < 0) || (row >= size()) || (column >= mColumns)) {
- throw new IndexOutOfBoundsException(row + ", " + column);
- }
-
- if (row >= mRowGapStart) {
- row += mRowGapLength;
- }
-
- int[] valuegap = mValueGap;
- if (row >= valuegap[column]) {
- value -= valuegap[column + mColumns];
- }
-
- mValues[row * mColumns + column] = value;
- }
-
- /**
- * Sets the value at the specified row and column.
- * Private internal version: does not check args.
- *
- * @param row the index of the row to set.
- * @param column the index of the column to set.
- *
- */
- private void setValueInternal(int row, int column, int value) {
- if (row >= mRowGapStart) {
- row += mRowGapLength;
- }
-
- int[] valuegap = mValueGap;
- if (row >= valuegap[column]) {
- value -= valuegap[column + mColumns];
- }
-
- mValues[row * mColumns + column] = value;
- }
-
-
- /**
- * Increments all values in the specified column whose row >= the
- * specified row by the specified delta.
- *
- * @param startRow the row at which to begin incrementing.
- * This may be == size(), which case there is no effect.
- * @param column the index of the column to set.
- *
- * @throws IndexOutOfBoundsException if the row is out of range
- * (startRow &lt; 0 || startRow > size()) or the column
- * is out of range (column &lt; 0 || column >= width()).
- */
- public void adjustValuesBelow(int startRow, int column, int delta) {
- if (((startRow | column) < 0) || (startRow > size()) ||
- (column >= width())) {
- throw new IndexOutOfBoundsException(startRow + ", " + column);
- }
-
- if (startRow >= mRowGapStart) {
- startRow += mRowGapLength;
- }
-
- moveValueGapTo(column, startRow);
- mValueGap[column + mColumns] += delta;
- }
-
- /**
- * Inserts a new row of values at the specified row offset.
- *
- * @param row the row above which to insert the new row.
- * This may be == size(), which case the new row is added
- * at the end.
- * @param values the new values to be added. If this is null,
- * a row of zeroes is added.
- *
- * @throws IndexOutOfBoundsException if the row is out of range
- * (row &lt; 0 || row > size()) or if the length of the
- * values array is too small (values.length < width()).
- */
- public void insertAt(int row, int[] values) {
- if ((row < 0) || (row > size())) {
- throw new IndexOutOfBoundsException("row " + row);
- }
-
- if ((values != null) && (values.length < width())) {
- throw new IndexOutOfBoundsException("value count " + values.length);
- }
-
- moveRowGapTo(row);
-
- if (mRowGapLength == 0) {
- growBuffer();
- }
-
- mRowGapStart++;
- mRowGapLength--;
-
- if (values == null) {
- for (int i = mColumns - 1; i >= 0; i--) {
- setValueInternal(row, i, 0);
- }
- } else {
- for (int i = mColumns - 1; i >= 0; i--) {
- setValueInternal(row, i, values[i]);
- }
- }
- }
-
- /**
- * Deletes the specified number of rows starting with the specified
- * row.
- *
- * @param row the index of the first row to be deleted.
- * @param count the number of rows to delete.
- *
- * @throws IndexOutOfBoundsException if any of the rows to be deleted
- * are out of range (row &lt; 0 || count &lt; 0 ||
- * row + count > size()).
- */
- public void deleteAt(int row, int count) {
- if (((row | count) < 0) || (row + count > size())) {
- throw new IndexOutOfBoundsException(row + ", " + count);
- }
-
- moveRowGapTo(row + count);
-
- mRowGapStart -= count;
- mRowGapLength += count;
-
- // TODO: Reclaim memory when the new height is much smaller
- // than the allocated size.
- }
-
- /**
- * Returns the number of rows in the PackedIntVector. This number
- * will change as rows are inserted and deleted.
- *
- * @return the number of rows.
- */
- public int size() {
- return mRows - mRowGapLength;
- }
-
- /**
- * Returns the width of the PackedIntVector. This number is set
- * at construction and will not change.
- *
- * @return the number of columns.
- */
- public int width() {
- return mColumns;
- }
-
- /**
- * Grows the value and gap arrays to be large enough to store at least
- * one more than the current number of rows.
- */
- private final void growBuffer() {
- final int columns = mColumns;
- int newsize = size() + 1;
- newsize = ArrayUtils.idealIntArraySize(newsize * columns) / columns;
- int[] newvalues = new int[newsize * columns];
-
- final int[] valuegap = mValueGap;
- final int rowgapstart = mRowGapStart;
-
- int after = mRows - (rowgapstart + mRowGapLength);
-
- if (mValues != null) {
- System.arraycopy(mValues, 0, newvalues, 0, columns * rowgapstart);
- System.arraycopy(mValues, (mRows - after) * columns,
- newvalues, (newsize - after) * columns,
- after * columns);
- }
-
- for (int i = 0; i < columns; i++) {
- if (valuegap[i] >= rowgapstart) {
- valuegap[i] += newsize - mRows;
-
- if (valuegap[i] < rowgapstart) {
- valuegap[i] = rowgapstart;
- }
- }
- }
-
- mRowGapLength += newsize - mRows;
- mRows = newsize;
- mValues = newvalues;
- }
-
- /**
- * Moves the gap in the values of the specified column to begin at
- * the specified row.
- */
- private final void moveValueGapTo(int column, int where) {
- final int[] valuegap = mValueGap;
- final int[] values = mValues;
- final int columns = mColumns;
-
- if (where == valuegap[column]) {
- return;
- } else if (where > valuegap[column]) {
- for (int i = valuegap[column]; i < where; i++) {
- values[i * columns + column] += valuegap[column + columns];
- }
- } else /* where < valuegap[column] */ {
- for (int i = where; i < valuegap[column]; i++) {
- values[i * columns + column] -= valuegap[column + columns];
- }
- }
-
- valuegap[column] = where;
- }
-
- /**
- * Moves the gap in the row indices to begin at the specified row.
- */
- private final void moveRowGapTo(int where) {
- if (where == mRowGapStart) {
- return;
- } else if (where > mRowGapStart) {
- int moving = where + mRowGapLength - (mRowGapStart + mRowGapLength);
- final int columns = mColumns;
- final int[] valuegap = mValueGap;
- final int[] values = mValues;
- final int gapend = mRowGapStart + mRowGapLength;
-
- for (int i = gapend; i < gapend + moving; i++) {
- int destrow = i - gapend + mRowGapStart;
-
- for (int j = 0; j < columns; j++) {
- int val = values[i * columns+ j];
-
- if (i >= valuegap[j]) {
- val += valuegap[j + columns];
- }
-
- if (destrow >= valuegap[j]) {
- val -= valuegap[j + columns];
- }
-
- values[destrow * columns + j] = val;
- }
- }
- } else /* where < mRowGapStart */ {
- int moving = mRowGapStart - where;
- final int columns = mColumns;
- final int[] valuegap = mValueGap;
- final int[] values = mValues;
- final int gapend = mRowGapStart + mRowGapLength;
-
- for (int i = where + moving - 1; i >= where; i--) {
- int destrow = i - where + gapend - moving;
-
- for (int j = 0; j < columns; j++) {
- int val = values[i * columns+ j];
-
- if (i >= valuegap[j]) {
- val += valuegap[j + columns];
- }
-
- if (destrow >= valuegap[j]) {
- val -= valuegap[j + columns];
- }
-
- values[destrow * columns + j] = val;
- }
- }
- }
-
- mRowGapStart = where;
- }
-}
diff --git a/core/java/android/text/PackedObjectVector.java b/core/java/android/text/PackedObjectVector.java
deleted file mode 100644
index a29df09..0000000
--- a/core/java/android/text/PackedObjectVector.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import com.android.internal.util.ArrayUtils;
-
-class PackedObjectVector<E>
-{
- private int mColumns;
- private int mRows;
-
- private int mRowGapStart;
- private int mRowGapLength;
-
- private Object[] mValues;
-
- public
- PackedObjectVector(int columns)
- {
- mColumns = columns;
- mRows = ArrayUtils.idealIntArraySize(0) / mColumns;
-
- mRowGapStart = 0;
- mRowGapLength = mRows;
-
- mValues = new Object[mRows * mColumns];
- }
-
- public E
- getValue(int row, int column)
- {
- if (row >= mRowGapStart)
- row += mRowGapLength;
-
- Object value = mValues[row * mColumns + column];
-
- return (E) value;
- }
-
- public void
- setValue(int row, int column, E value)
- {
- if (row >= mRowGapStart)
- row += mRowGapLength;
-
- mValues[row * mColumns + column] = value;
- }
-
- public void
- insertAt(int row, E[] values)
- {
- moveRowGapTo(row);
-
- if (mRowGapLength == 0)
- growBuffer();
-
- mRowGapStart++;
- mRowGapLength--;
-
- if (values == null)
- for (int i = 0; i < mColumns; i++)
- setValue(row, i, null);
- else
- for (int i = 0; i < mColumns; i++)
- setValue(row, i, values[i]);
- }
-
- public void
- deleteAt(int row, int count)
- {
- moveRowGapTo(row + count);
-
- mRowGapStart -= count;
- mRowGapLength += count;
-
- if (mRowGapLength > size() * 2)
- {
- // dump();
- // growBuffer();
- }
- }
-
- public int
- size()
- {
- return mRows - mRowGapLength;
- }
-
- public int
- width()
- {
- return mColumns;
- }
-
- private void
- growBuffer()
- {
- int newsize = size() + 1;
- newsize = ArrayUtils.idealIntArraySize(newsize * mColumns) / mColumns;
- Object[] newvalues = new Object[newsize * mColumns];
-
- int after = mRows - (mRowGapStart + mRowGapLength);
-
- System.arraycopy(mValues, 0, newvalues, 0, mColumns * mRowGapStart);
- System.arraycopy(mValues, (mRows - after) * mColumns, newvalues, (newsize - after) * mColumns, after * mColumns);
-
- mRowGapLength += newsize - mRows;
- mRows = newsize;
- mValues = newvalues;
- }
-
- private void
- moveRowGapTo(int where)
- {
- if (where == mRowGapStart)
- return;
-
- if (where > mRowGapStart)
- {
- int moving = where + mRowGapLength - (mRowGapStart + mRowGapLength);
-
- for (int i = mRowGapStart + mRowGapLength; i < mRowGapStart + mRowGapLength + moving; i++)
- {
- int destrow = i - (mRowGapStart + mRowGapLength) + mRowGapStart;
-
- for (int j = 0; j < mColumns; j++)
- {
- Object val = mValues[i * mColumns + j];
-
- mValues[destrow * mColumns + j] = val;
- }
- }
- }
- else /* where < mRowGapStart */
- {
- int moving = mRowGapStart - where;
-
- for (int i = where + moving - 1; i >= where; i--)
- {
- int destrow = i - where + mRowGapStart + mRowGapLength - moving;
-
- for (int j = 0; j < mColumns; j++)
- {
- Object val = mValues[i * mColumns + j];
-
- mValues[destrow * mColumns + j] = val;
- }
- }
- }
-
- mRowGapStart = where;
- }
-
- public void // XXX
- dump()
- {
- for (int i = 0; i < mRows; i++)
- {
- for (int j = 0; j < mColumns; j++)
- {
- Object val = mValues[i * mColumns + j];
-
- if (i < mRowGapStart || i >= mRowGapStart + mRowGapLength)
- System.out.print(val + " ");
- else
- System.out.print("(" + val + ") ");
- }
-
- System.out.print(" << \n");
- }
-
- System.out.print("-----\n\n");
- }
-}
diff --git a/core/java/android/text/ParcelableSpan.java b/core/java/android/text/ParcelableSpan.java
deleted file mode 100644
index 224511a..0000000
--- a/core/java/android/text/ParcelableSpan.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import android.os.Parcelable;
-
-/**
- * A special kind of Parcelable for objects that will serve as text spans.
- * This can only be used by code in the framework; it is not intended for
- * applications to implement their own Parcelable spans.
- */
-public interface ParcelableSpan extends Parcelable {
- /**
- * Return a special type identifier for this span class.
- */
- public abstract int getSpanTypeId();
-}
diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java
deleted file mode 100644
index bb98bce..0000000
--- a/core/java/android/text/Selection.java
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-
-/**
- * Utility class for manipulating cursors and selections in CharSequences.
- * A cursor is a selection where the start and end are at the same offset.
- */
-public class Selection {
- private Selection() { /* cannot be instantiated */ }
-
- /*
- * Retrieving the selection
- */
-
- /**
- * Return the offset of the selection anchor or cursor, or -1 if
- * there is no selection or cursor.
- */
- public static final int getSelectionStart(CharSequence text) {
- if (text instanceof Spanned)
- return ((Spanned) text).getSpanStart(SELECTION_START);
- else
- return -1;
- }
-
- /**
- * Return the offset of the selection edge or cursor, or -1 if
- * there is no selection or cursor.
- */
- public static final int getSelectionEnd(CharSequence text) {
- if (text instanceof Spanned)
- return ((Spanned) text).getSpanStart(SELECTION_END);
- else
- return -1;
- }
-
- /*
- * Setting the selection
- */
-
- // private static int pin(int value, int min, int max) {
- // return value < min ? 0 : (value > max ? max : value);
- // }
-
- /**
- * Set the selection anchor to <code>start</code> and the selection edge
- * to <code>stop</code>.
- */
- public static void setSelection(Spannable text, int start, int stop) {
- // int len = text.length();
- // start = pin(start, 0, len); XXX remove unless we really need it
- // stop = pin(stop, 0, len);
-
- int ostart = getSelectionStart(text);
- int oend = getSelectionEnd(text);
-
- if (ostart != start || oend != stop) {
- text.setSpan(SELECTION_START, start, start,
- Spanned.SPAN_POINT_POINT|Spanned.SPAN_INTERMEDIATE);
- text.setSpan(SELECTION_END, stop, stop,
- Spanned.SPAN_POINT_POINT);
- }
- }
-
- /**
- * Move the cursor to offset <code>index</code>.
- */
- public static final void setSelection(Spannable text, int index) {
- setSelection(text, index, index);
- }
-
- /**
- * Select the entire text.
- */
- public static final void selectAll(Spannable text) {
- setSelection(text, 0, text.length());
- }
-
- /**
- * Move the selection edge to offset <code>index</code>.
- */
- public static final void extendSelection(Spannable text, int index) {
- if (text.getSpanStart(SELECTION_END) != index)
- text.setSpan(SELECTION_END, index, index, Spanned.SPAN_POINT_POINT);
- }
-
- /**
- * Remove the selection or cursor, if any, from the text.
- */
- public static final void removeSelection(Spannable text) {
- text.removeSpan(SELECTION_START);
- text.removeSpan(SELECTION_END);
- }
-
- /*
- * Moving the selection within the layout
- */
-
- /**
- * Move the cursor to the buffer offset physically above the current
- * offset, or return false if the cursor is already on the top line.
- */
- public static boolean moveUp(Spannable text, Layout layout) {
- int start = getSelectionStart(text);
- int end = getSelectionEnd(text);
-
- if (start != end) {
- int min = Math.min(start, end);
- int max = Math.max(start, end);
-
- setSelection(text, min);
-
- if (min == 0 && max == text.length()) {
- return false;
- }
-
- return true;
- } else {
- int line = layout.getLineForOffset(end);
-
- if (line > 0) {
- int move;
-
- if (layout.getParagraphDirection(line) ==
- layout.getParagraphDirection(line - 1)) {
- float h = layout.getPrimaryHorizontal(end);
- move = layout.getOffsetForHorizontal(line - 1, h);
- } else {
- move = layout.getLineStart(line - 1);
- }
-
- setSelection(text, move);
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Move the cursor to the buffer offset physically below the current
- * offset, or return false if the cursor is already on the bottom line.
- */
- public static boolean moveDown(Spannable text, Layout layout) {
- int start = getSelectionStart(text);
- int end = getSelectionEnd(text);
-
- if (start != end) {
- int min = Math.min(start, end);
- int max = Math.max(start, end);
-
- setSelection(text, max);
-
- if (min == 0 && max == text.length()) {
- return false;
- }
-
- return true;
- } else {
- int line = layout.getLineForOffset(end);
-
- if (line < layout.getLineCount() - 1) {
- int move;
-
- if (layout.getParagraphDirection(line) ==
- layout.getParagraphDirection(line + 1)) {
- float h = layout.getPrimaryHorizontal(end);
- move = layout.getOffsetForHorizontal(line + 1, h);
- } else {
- move = layout.getLineStart(line + 1);
- }
-
- setSelection(text, move);
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Move the cursor to the buffer offset physically to the left of
- * the current offset, or return false if the cursor is already
- * at the left edge of the line and there is not another line to move it to.
- */
- public static boolean moveLeft(Spannable text, Layout layout) {
- int start = getSelectionStart(text);
- int end = getSelectionEnd(text);
-
- if (start != end) {
- setSelection(text, chooseHorizontal(layout, -1, start, end));
- return true;
- } else {
- int to = layout.getOffsetToLeftOf(end);
-
- if (to != end) {
- setSelection(text, to);
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Move the cursor to the buffer offset physically to the right of
- * the current offset, or return false if the cursor is already at
- * at the right edge of the line and there is not another line
- * to move it to.
- */
- public static boolean moveRight(Spannable text, Layout layout) {
- int start = getSelectionStart(text);
- int end = getSelectionEnd(text);
-
- if (start != end) {
- setSelection(text, chooseHorizontal(layout, 1, start, end));
- return true;
- } else {
- int to = layout.getOffsetToRightOf(end);
-
- if (to != end) {
- setSelection(text, to);
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Move the selection end to the buffer offset physically above
- * the current selection end.
- */
- public static boolean extendUp(Spannable text, Layout layout) {
- int end = getSelectionEnd(text);
- int line = layout.getLineForOffset(end);
-
- if (line > 0) {
- int move;
-
- if (layout.getParagraphDirection(line) ==
- layout.getParagraphDirection(line - 1)) {
- float h = layout.getPrimaryHorizontal(end);
- move = layout.getOffsetForHorizontal(line - 1, h);
- } else {
- move = layout.getLineStart(line - 1);
- }
-
- extendSelection(text, move);
- return true;
- } else if (end != 0) {
- extendSelection(text, 0);
- return true;
- }
-
- return true;
- }
-
- /**
- * Move the selection end to the buffer offset physically below
- * the current selection end.
- */
- public static boolean extendDown(Spannable text, Layout layout) {
- int end = getSelectionEnd(text);
- int line = layout.getLineForOffset(end);
-
- if (line < layout.getLineCount() - 1) {
- int move;
-
- if (layout.getParagraphDirection(line) ==
- layout.getParagraphDirection(line + 1)) {
- float h = layout.getPrimaryHorizontal(end);
- move = layout.getOffsetForHorizontal(line + 1, h);
- } else {
- move = layout.getLineStart(line + 1);
- }
-
- extendSelection(text, move);
- return true;
- } else if (end != text.length()) {
- extendSelection(text, text.length());
- return true;
- }
-
- return true;
- }
-
- /**
- * Move the selection end to the buffer offset physically to the left of
- * the current selection end.
- */
- public static boolean extendLeft(Spannable text, Layout layout) {
- int end = getSelectionEnd(text);
- int to = layout.getOffsetToLeftOf(end);
-
- if (to != end) {
- extendSelection(text, to);
- return true;
- }
-
- return true;
- }
-
- /**
- * Move the selection end to the buffer offset physically to the right of
- * the current selection end.
- */
- public static boolean extendRight(Spannable text, Layout layout) {
- int end = getSelectionEnd(text);
- int to = layout.getOffsetToRightOf(end);
-
- if (to != end) {
- extendSelection(text, to);
- return true;
- }
-
- return true;
- }
-
- public static boolean extendToLeftEdge(Spannable text, Layout layout) {
- int where = findEdge(text, layout, -1);
- extendSelection(text, where);
- return true;
- }
-
- public static boolean extendToRightEdge(Spannable text, Layout layout) {
- int where = findEdge(text, layout, 1);
- extendSelection(text, where);
- return true;
- }
-
- public static boolean moveToLeftEdge(Spannable text, Layout layout) {
- int where = findEdge(text, layout, -1);
- setSelection(text, where);
- return true;
- }
-
- public static boolean moveToRightEdge(Spannable text, Layout layout) {
- int where = findEdge(text, layout, 1);
- setSelection(text, where);
- return true;
- }
-
- private static int findEdge(Spannable text, Layout layout, int dir) {
- int pt = getSelectionEnd(text);
- int line = layout.getLineForOffset(pt);
- int pdir = layout.getParagraphDirection(line);
-
- if (dir * pdir < 0) {
- return layout.getLineStart(line);
- } else {
- int end = layout.getLineEnd(line);
-
- if (line == layout.getLineCount() - 1)
- return end;
- else
- return end - 1;
- }
- }
-
- private static int chooseHorizontal(Layout layout, int direction,
- int off1, int off2) {
- int line1 = layout.getLineForOffset(off1);
- int line2 = layout.getLineForOffset(off2);
-
- if (line1 == line2) {
- // same line, so it goes by pure physical direction
-
- float h1 = layout.getPrimaryHorizontal(off1);
- float h2 = layout.getPrimaryHorizontal(off2);
-
- if (direction < 0) {
- // to left
-
- if (h1 < h2)
- return off1;
- else
- return off2;
- } else {
- // to right
-
- if (h1 > h2)
- return off1;
- else
- return off2;
- }
- } else {
- // different line, so which line is "left" and which is "right"
- // depends upon the directionality of the text
-
- // This only checks at one end, but it's not clear what the
- // right thing to do is if the ends don't agree. Even if it
- // is wrong it should still not be too bad.
- int line = layout.getLineForOffset(off1);
- int textdir = layout.getParagraphDirection(line);
-
- if (textdir == direction)
- return Math.max(off1, off2);
- else
- return Math.min(off1, off2);
- }
- }
-
- private static final class START implements NoCopySpan { };
- private static final class END implements NoCopySpan { };
-
- /*
- * Public constants
- */
-
- public static final Object SELECTION_START = new START();
- public static final Object SELECTION_END = new END();
-}
diff --git a/core/java/android/text/SpanWatcher.java b/core/java/android/text/SpanWatcher.java
deleted file mode 100644
index 01e82c8..0000000
--- a/core/java/android/text/SpanWatcher.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-/**
- * When an object of this type is attached to a Spannable, its methods
- * will be called to notify it that other markup objects have been
- * added, changed, or removed.
- */
-public interface SpanWatcher extends NoCopySpan {
- /**
- * This method is called to notify you that the specified object
- * has been attached to the specified range of the text.
- */
- public void onSpanAdded(Spannable text, Object what, int start, int end);
- /**
- * This method is called to notify you that the specified object
- * has been detached from the specified range of the text.
- */
- public void onSpanRemoved(Spannable text, Object what, int start, int end);
- /**
- * This method is called to notify you that the specified object
- * has been relocated from the range <code>ostart&hellip;oend</code>
- * to the new range <code>nstart&hellip;nend</code> of the text.
- */
- public void onSpanChanged(Spannable text, Object what, int ostart, int oend,
- int nstart, int nend);
-}
diff --git a/core/java/android/text/Spannable.java b/core/java/android/text/Spannable.java
deleted file mode 100644
index ae5d356..0000000
--- a/core/java/android/text/Spannable.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-/**
- * This is the interface for text to which markup objects can be
- * attached and detached. Not all Spannable classes have mutable text;
- * see {@link Editable} for that.
- */
-public interface Spannable
-extends Spanned
-{
- /**
- * Attach the specified markup object to the range <code>start&hellip;end</code>
- * of the text, or move the object to that range if it was already
- * attached elsewhere. See {@link Spanned} for an explanation of
- * what the flags mean. The object can be one that has meaning only
- * within your application, or it can be one that the text system will
- * use to affect text display or behavior. Some noteworthy ones are
- * the subclasses of {@link android.text.style.CharacterStyle} and
- * {@link android.text.style.ParagraphStyle}, and
- * {@link android.text.TextWatcher} and
- * {@link android.text.SpanWatcher}.
- */
- public void setSpan(Object what, int start, int end, int flags);
-
- /**
- * Remove the specified object from the range of text to which it
- * was attached, if any. It is OK to remove an object that was never
- * attached in the first place.
- */
- public void removeSpan(Object what);
-
- /**
- * Factory used by TextView to create new Spannables. You can subclass
- * it to provide something other than SpannableString.
- */
- public static class Factory {
- private static Spannable.Factory sInstance = new Spannable.Factory();
-
- /**
- * Returns the standard Spannable Factory.
- */
- public static Spannable.Factory getInstance() {
- return sInstance;
- }
-
- /**
- * Returns a new SpannableString from the specified CharSequence.
- * You can override this to provide a different kind of Spannable.
- */
- public Spannable newSpannable(CharSequence source) {
- return new SpannableString(source);
- }
- }
-}
diff --git a/core/java/android/text/SpannableString.java b/core/java/android/text/SpannableString.java
deleted file mode 100644
index 56d0946..0000000
--- a/core/java/android/text/SpannableString.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-
-/**
- * This is the class for text whose content is immutable but to which
- * markup objects can be attached and detached.
- * For mutable text, see {@link SpannableStringBuilder}.
- */
-public class SpannableString
-extends SpannableStringInternal
-implements CharSequence, GetChars, Spannable
-{
- public SpannableString(CharSequence source) {
- super(source, 0, source.length());
- }
-
- private SpannableString(CharSequence source, int start, int end) {
- super(source, start, end);
- }
-
- public static SpannableString valueOf(CharSequence source) {
- if (source instanceof SpannableString) {
- return (SpannableString) source;
- } else {
- return new SpannableString(source);
- }
- }
-
- public void setSpan(Object what, int start, int end, int flags) {
- super.setSpan(what, start, end, flags);
- }
-
- public void removeSpan(Object what) {
- super.removeSpan(what);
- }
-
- public final CharSequence subSequence(int start, int end) {
- return new SpannableString(this, start, end);
- }
-}
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
deleted file mode 100644
index caaafa1..0000000
--- a/core/java/android/text/SpannableStringBuilder.java
+++ /dev/null
@@ -1,1140 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import com.android.internal.util.ArrayUtils;
-import android.graphics.Paint;
-import android.graphics.Canvas;
-
-import java.lang.reflect.Array;
-
-/**
- * This is the class for text whose content and markup can both be changed.
- */
-public class SpannableStringBuilder
-implements CharSequence, GetChars, Spannable, Editable, Appendable,
- GraphicsOperations
-{
- /**
- * Create a new SpannableStringBuilder with empty contents
- */
- public SpannableStringBuilder() {
- this("");
- }
-
- /**
- * Create a new SpannableStringBuilder containing a copy of the
- * specified text, including its spans if any.
- */
- public SpannableStringBuilder(CharSequence text) {
- this(text, 0, text.length());
- }
-
- /**
- * Create a new SpannableStringBuilder containing a copy of the
- * specified slice of the specified text, including its spans if any.
- */
- public SpannableStringBuilder(CharSequence text, int start, int end) {
- int srclen = end - start;
-
- int len = ArrayUtils.idealCharArraySize(srclen + 1);
- mText = new char[len];
- mGapStart = srclen;
- mGapLength = len - srclen;
-
- TextUtils.getChars(text, start, end, mText, 0);
-
- mSpanCount = 0;
- int alloc = ArrayUtils.idealIntArraySize(0);
- mSpans = new Object[alloc];
- mSpanStarts = new int[alloc];
- mSpanEnds = new int[alloc];
- mSpanFlags = new int[alloc];
-
- if (text instanceof Spanned) {
- Spanned sp = (Spanned) text;
- Object[] spans = sp.getSpans(start, end, Object.class);
-
- for (int i = 0; i < spans.length; i++) {
- if (spans[i] instanceof NoCopySpan) {
- continue;
- }
-
- int st = sp.getSpanStart(spans[i]) - start;
- int en = sp.getSpanEnd(spans[i]) - start;
- int fl = sp.getSpanFlags(spans[i]);
-
- if (st < 0)
- st = 0;
- if (st > end - start)
- st = end - start;
-
- if (en < 0)
- en = 0;
- if (en > end - start)
- en = end - start;
-
- setSpan(spans[i], st, en, fl);
- }
- }
- }
-
- public static SpannableStringBuilder valueOf(CharSequence source) {
- if (source instanceof SpannableStringBuilder) {
- return (SpannableStringBuilder) source;
- } else {
- return new SpannableStringBuilder(source);
- }
- }
-
- /**
- * Return the char at the specified offset within the buffer.
- */
- public char charAt(int where) {
- int len = length();
- if (where < 0) {
- throw new IndexOutOfBoundsException("charAt: " + where + " < 0");
- } else if (where >= len) {
- throw new IndexOutOfBoundsException("charAt: " + where +
- " >= length " + len);
- }
-
- if (where >= mGapStart)
- return mText[where + mGapLength];
- else
- return mText[where];
- }
-
- /**
- * Return the number of chars in the buffer.
- */
- public int length() {
- return mText.length - mGapLength;
- }
-
- private void resizeFor(int size) {
- int newlen = ArrayUtils.idealCharArraySize(size + 1);
- char[] newtext = new char[newlen];
-
- int after = mText.length - (mGapStart + mGapLength);
-
- System.arraycopy(mText, 0, newtext, 0, mGapStart);
- System.arraycopy(mText, mText.length - after,
- newtext, newlen - after, after);
-
- for (int i = 0; i < mSpanCount; i++) {
- if (mSpanStarts[i] > mGapStart)
- mSpanStarts[i] += newlen - mText.length;
- if (mSpanEnds[i] > mGapStart)
- mSpanEnds[i] += newlen - mText.length;
- }
-
- int oldlen = mText.length;
- mText = newtext;
- mGapLength += mText.length - oldlen;
-
- if (mGapLength < 1)
- new Exception("mGapLength < 1").printStackTrace();
- }
-
- private void moveGapTo(int where) {
- if (where == mGapStart)
- return;
-
- boolean atend = (where == length());
-
- if (where < mGapStart) {
- int overlap = mGapStart - where;
-
- System.arraycopy(mText, where,
- mText, mGapStart + mGapLength - overlap, overlap);
- } else /* where > mGapStart */ {
- int overlap = where - mGapStart;
-
- System.arraycopy(mText, where + mGapLength - overlap,
- mText, mGapStart, overlap);
- }
-
- // XXX be more clever
- for (int i = 0; i < mSpanCount; i++) {
- int start = mSpanStarts[i];
- int end = mSpanEnds[i];
-
- if (start > mGapStart)
- start -= mGapLength;
- if (start > where)
- start += mGapLength;
- else if (start == where) {
- int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT;
-
- if (flag == POINT || (atend && flag == PARAGRAPH))
- start += mGapLength;
- }
-
- if (end > mGapStart)
- end -= mGapLength;
- if (end > where)
- end += mGapLength;
- else if (end == where) {
- int flag = (mSpanFlags[i] & END_MASK);
-
- if (flag == POINT || (atend && flag == PARAGRAPH))
- end += mGapLength;
- }
-
- mSpanStarts[i] = start;
- mSpanEnds[i] = end;
- }
-
- mGapStart = where;
- }
-
- // Documentation from interface
- public SpannableStringBuilder insert(int where, CharSequence tb, int start, int end) {
- return replace(where, where, tb, start, end);
- }
-
- // Documentation from interface
- public SpannableStringBuilder insert(int where, CharSequence tb) {
- return replace(where, where, tb, 0, tb.length());
- }
-
- // Documentation from interface
- public SpannableStringBuilder delete(int start, int end) {
- SpannableStringBuilder ret = replace(start, end, "", 0, 0);
-
- if (mGapLength > 2 * length())
- resizeFor(length());
-
- return ret; // == this
- }
-
- // Documentation from interface
- public void clear() {
- replace(0, length(), "", 0, 0);
- }
-
- // Documentation from interface
- public void clearSpans() {
- for (int i = mSpanCount - 1; i >= 0; i--) {
- Object what = mSpans[i];
- int ostart = mSpanStarts[i];
- int oend = mSpanEnds[i];
-
- if (ostart > mGapStart)
- ostart -= mGapLength;
- if (oend > mGapStart)
- oend -= mGapLength;
-
- mSpanCount = i;
- mSpans[i] = null;
-
- sendSpanRemoved(what, ostart, oend);
- }
- }
-
- // Documentation from interface
- public SpannableStringBuilder append(CharSequence text) {
- int length = length();
- return replace(length, length, text, 0, text.length());
- }
-
- // Documentation from interface
- public SpannableStringBuilder append(CharSequence text, int start, int end) {
- int length = length();
- return replace(length, length, text, start, end);
- }
-
- // Documentation from interface
- public SpannableStringBuilder append(char text) {
- return append(String.valueOf(text));
- }
-
- private int change(int start, int end,
- CharSequence tb, int tbstart, int tbend) {
- return change(true, start, end, tb, tbstart, tbend);
- }
-
- private int change(boolean notify, int start, int end,
- CharSequence tb, int tbstart, int tbend) {
- checkRange("replace", start, end);
- int ret = tbend - tbstart;
- TextWatcher[] recipients = null;
-
- if (notify)
- recipients = sendTextWillChange(start, end - start,
- tbend - tbstart);
-
- for (int i = mSpanCount - 1; i >= 0; i--) {
- if ((mSpanFlags[i] & SPAN_PARAGRAPH) == SPAN_PARAGRAPH) {
- int st = mSpanStarts[i];
- if (st > mGapStart)
- st -= mGapLength;
-
- int en = mSpanEnds[i];
- if (en > mGapStart)
- en -= mGapLength;
-
- int ost = st;
- int oen = en;
- int clen = length();
-
- if (st > start && st <= end) {
- for (st = end; st < clen; st++)
- if (st > end && charAt(st - 1) == '\n')
- break;
- }
-
- if (en > start && en <= end) {
- for (en = end; en < clen; en++)
- if (en > end && charAt(en - 1) == '\n')
- break;
- }
-
- if (st != ost || en != oen)
- setSpan(mSpans[i], st, en, mSpanFlags[i]);
- }
- }
-
- moveGapTo(end);
-
- if (tbend - tbstart >= mGapLength + (end - start))
- resizeFor(mText.length - mGapLength +
- tbend - tbstart - (end - start));
-
- mGapStart += tbend - tbstart - (end - start);
- mGapLength -= tbend - tbstart - (end - start);
-
- if (mGapLength < 1)
- new Exception("mGapLength < 1").printStackTrace();
-
- TextUtils.getChars(tb, tbstart, tbend, mText, start);
-
- if (tb instanceof Spanned) {
- Spanned sp = (Spanned) tb;
- Object[] spans = sp.getSpans(tbstart, tbend, Object.class);
-
- for (int i = 0; i < spans.length; i++) {
- int st = sp.getSpanStart(spans[i]);
- int en = sp.getSpanEnd(spans[i]);
-
- if (st < tbstart)
- st = tbstart;
- if (en > tbend)
- en = tbend;
-
- if (getSpanStart(spans[i]) < 0) {
- setSpan(false, spans[i],
- st - tbstart + start,
- en - tbstart + start,
- sp.getSpanFlags(spans[i]));
- }
- }
- }
-
- // no need for span fixup on pure insertion
- if (tbend > tbstart && end - start == 0) {
- if (notify) {
- sendTextChange(recipients, start, end - start, tbend - tbstart);
- sendTextHasChanged(recipients);
- }
-
- return ret;
- }
-
- boolean atend = (mGapStart + mGapLength == mText.length);
-
- for (int i = mSpanCount - 1; i >= 0; i--) {
- if (mSpanStarts[i] >= start &&
- mSpanStarts[i] < mGapStart + mGapLength) {
- int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT;
-
- if (flag == POINT || (flag == PARAGRAPH && atend))
- mSpanStarts[i] = mGapStart + mGapLength;
- else
- mSpanStarts[i] = start;
- }
-
- if (mSpanEnds[i] >= start &&
- mSpanEnds[i] < mGapStart + mGapLength) {
- int flag = (mSpanFlags[i] & END_MASK);
-
- if (flag == POINT || (flag == PARAGRAPH && atend))
- mSpanEnds[i] = mGapStart + mGapLength;
- else
- mSpanEnds[i] = start;
- }
-
- // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE
- // XXX send notification on removal
-
- if (mSpanEnds[i] < mSpanStarts[i]) {
- System.arraycopy(mSpans, i + 1,
- mSpans, i, mSpanCount - (i + 1));
- System.arraycopy(mSpanStarts, i + 1,
- mSpanStarts, i, mSpanCount - (i + 1));
- System.arraycopy(mSpanEnds, i + 1,
- mSpanEnds, i, mSpanCount - (i + 1));
- System.arraycopy(mSpanFlags, i + 1,
- mSpanFlags, i, mSpanCount - (i + 1));
-
- mSpanCount--;
- }
- }
-
- if (notify) {
- sendTextChange(recipients, start, end - start, tbend - tbstart);
- sendTextHasChanged(recipients);
- }
-
- return ret;
- }
-
- // Documentation from interface
- public SpannableStringBuilder replace(int start, int end, CharSequence tb) {
- return replace(start, end, tb, 0, tb.length());
- }
-
- // Documentation from interface
- public SpannableStringBuilder replace(final int start, final int end,
- CharSequence tb, int tbstart, int tbend) {
- int filtercount = mFilters.length;
- for (int i = 0; i < filtercount; i++) {
- CharSequence repl = mFilters[i].filter(tb, tbstart, tbend,
- this, start, end);
-
- if (repl != null) {
- tb = repl;
- tbstart = 0;
- tbend = repl.length();
- }
- }
-
- if (end == start && tbstart == tbend) {
- return this;
- }
-
- if (end == start || tbstart == tbend) {
- change(start, end, tb, tbstart, tbend);
- } else {
- int selstart = Selection.getSelectionStart(this);
- int selend = Selection.getSelectionEnd(this);
-
- // XXX just make the span fixups in change() do the right thing
- // instead of this madness!
-
- checkRange("replace", start, end);
- moveGapTo(end);
- TextWatcher[] recipients;
-
- recipients = sendTextWillChange(start, end - start,
- tbend - tbstart);
-
- int origlen = end - start;
-
- if (mGapLength < 2)
- resizeFor(length() + 1);
-
- for (int i = mSpanCount - 1; i >= 0; i--) {
- if (mSpanStarts[i] == mGapStart)
- mSpanStarts[i]++;
-
- if (mSpanEnds[i] == mGapStart)
- mSpanEnds[i]++;
- }
-
- mText[mGapStart] = ' ';
- mGapStart++;
- mGapLength--;
-
- if (mGapLength < 1)
- new Exception("mGapLength < 1").printStackTrace();
-
- int oldlen = (end + 1) - start;
-
- int inserted = change(false, start + 1, start + 1,
- tb, tbstart, tbend);
- change(false, start, start + 1, "", 0, 0);
- change(false, start + inserted, start + inserted + oldlen - 1,
- "", 0, 0);
-
- /*
- * Special case to keep the cursor in the same position
- * if it was somewhere in the middle of the replaced region.
- * If it was at the start or the end or crossing the whole
- * replacement, it should already be where it belongs.
- * TODO: Is there some more general mechanism that could
- * accomplish this?
- */
- if (selstart > start && selstart < end) {
- long off = selstart - start;
-
- off = off * inserted / (end - start);
- selstart = (int) off + start;
-
- setSpan(false, Selection.SELECTION_START, selstart, selstart,
- Spanned.SPAN_POINT_POINT);
- }
- if (selend > start && selend < end) {
- long off = selend - start;
-
- off = off * inserted / (end - start);
- selend = (int) off + start;
-
- setSpan(false, Selection.SELECTION_END, selend, selend,
- Spanned.SPAN_POINT_POINT);
- }
-
- sendTextChange(recipients, start, origlen, inserted);
- sendTextHasChanged(recipients);
- }
- return this;
- }
-
- /**
- * Mark the specified range of text with the specified object.
- * The flags determine how the span will behave when text is
- * inserted at the start or end of the span's range.
- */
- public void setSpan(Object what, int start, int end, int flags) {
- setSpan(true, what, start, end, flags);
- }
-
- private void setSpan(boolean send,
- Object what, int start, int end, int flags) {
- int nstart = start;
- int nend = end;
-
- checkRange("setSpan", start, end);
-
- if ((flags & START_MASK) == (PARAGRAPH << START_SHIFT)) {
- if (start != 0 && start != length()) {
- char c = charAt(start - 1);
-
- if (c != '\n')
- throw new RuntimeException(
- "PARAGRAPH span must start at paragraph boundary");
- }
- }
-
- if ((flags & END_MASK) == PARAGRAPH) {
- if (end != 0 && end != length()) {
- char c = charAt(end - 1);
-
- if (c != '\n')
- throw new RuntimeException(
- "PARAGRAPH span must end at paragraph boundary");
- }
- }
-
- if (start > mGapStart)
- start += mGapLength;
- else if (start == mGapStart) {
- int flag = (flags & START_MASK) >> START_SHIFT;
-
- if (flag == POINT || (flag == PARAGRAPH && start == length()))
- start += mGapLength;
- }
-
- if (end > mGapStart)
- end += mGapLength;
- else if (end == mGapStart) {
- int flag = (flags & END_MASK);
-
- if (flag == POINT || (flag == PARAGRAPH && end == length()))
- end += mGapLength;
- }
-
- int count = mSpanCount;
- Object[] spans = mSpans;
-
- for (int i = 0; i < count; i++) {
- if (spans[i] == what) {
- int ostart = mSpanStarts[i];
- int oend = mSpanEnds[i];
-
- if (ostart > mGapStart)
- ostart -= mGapLength;
- if (oend > mGapStart)
- oend -= mGapLength;
-
- mSpanStarts[i] = start;
- mSpanEnds[i] = end;
- mSpanFlags[i] = flags;
-
- if (send)
- sendSpanChanged(what, ostart, oend, nstart, nend);
-
- return;
- }
- }
-
- if (mSpanCount + 1 >= mSpans.length) {
- int newsize = ArrayUtils.idealIntArraySize(mSpanCount + 1);
- Object[] newspans = new Object[newsize];
- int[] newspanstarts = new int[newsize];
- int[] newspanends = new int[newsize];
- int[] newspanflags = new int[newsize];
-
- System.arraycopy(mSpans, 0, newspans, 0, mSpanCount);
- System.arraycopy(mSpanStarts, 0, newspanstarts, 0, mSpanCount);
- System.arraycopy(mSpanEnds, 0, newspanends, 0, mSpanCount);
- System.arraycopy(mSpanFlags, 0, newspanflags, 0, mSpanCount);
-
- mSpans = newspans;
- mSpanStarts = newspanstarts;
- mSpanEnds = newspanends;
- mSpanFlags = newspanflags;
- }
-
- mSpans[mSpanCount] = what;
- mSpanStarts[mSpanCount] = start;
- mSpanEnds[mSpanCount] = end;
- mSpanFlags[mSpanCount] = flags;
- mSpanCount++;
-
- if (send)
- sendSpanAdded(what, nstart, nend);
- }
-
- /**
- * Remove the specified markup object from the buffer.
- */
- public void removeSpan(Object what) {
- for (int i = mSpanCount - 1; i >= 0; i--) {
- if (mSpans[i] == what) {
- int ostart = mSpanStarts[i];
- int oend = mSpanEnds[i];
-
- if (ostart > mGapStart)
- ostart -= mGapLength;
- if (oend > mGapStart)
- oend -= mGapLength;
-
- int count = mSpanCount - (i + 1);
-
- System.arraycopy(mSpans, i + 1, mSpans, i, count);
- System.arraycopy(mSpanStarts, i + 1, mSpanStarts, i, count);
- System.arraycopy(mSpanEnds, i + 1, mSpanEnds, i, count);
- System.arraycopy(mSpanFlags, i + 1, mSpanFlags, i, count);
-
- mSpanCount--;
- mSpans[mSpanCount] = null;
-
- sendSpanRemoved(what, ostart, oend);
- return;
- }
- }
- }
-
- /**
- * Return the buffer offset of the beginning of the specified
- * markup object, or -1 if it is not attached to this buffer.
- */
- public int getSpanStart(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- int where = mSpanStarts[i];
-
- if (where > mGapStart)
- where -= mGapLength;
-
- return where;
- }
- }
-
- return -1;
- }
-
- /**
- * Return the buffer offset of the end of the specified
- * markup object, or -1 if it is not attached to this buffer.
- */
- public int getSpanEnd(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- int where = mSpanEnds[i];
-
- if (where > mGapStart)
- where -= mGapLength;
-
- return where;
- }
- }
-
- return -1;
- }
-
- /**
- * Return the flags of the end of the specified
- * markup object, or 0 if it is not attached to this buffer.
- */
- public int getSpanFlags(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- return mSpanFlags[i];
- }
- }
-
- return 0;
- }
-
- /**
- * Return an array of the spans of the specified type that overlap
- * the specified range of the buffer. The kind may be Object.class to get
- * a list of all the spans regardless of type.
- */
- public <T> T[] getSpans(int queryStart, int queryEnd, Class<T> kind) {
- int spanCount = mSpanCount;
- Object[] spans = mSpans;
- int[] starts = mSpanStarts;
- int[] ends = mSpanEnds;
- int[] flags = mSpanFlags;
- int gapstart = mGapStart;
- int gaplen = mGapLength;
-
- int count = 0;
- Object[] ret = null;
- Object ret1 = null;
-
- for (int i = 0; i < spanCount; i++) {
- int spanStart = starts[i];
- int spanEnd = ends[i];
-
- if (spanStart > gapstart) {
- spanStart -= gaplen;
- }
- if (spanEnd > gapstart) {
- spanEnd -= gaplen;
- }
-
- if (spanStart > queryEnd) {
- continue;
- }
- if (spanEnd < queryStart) {
- continue;
- }
-
- if (spanStart != spanEnd && queryStart != queryEnd) {
- if (spanStart == queryEnd)
- continue;
- if (spanEnd == queryStart)
- continue;
- }
-
- if (kind != null && !kind.isInstance(spans[i])) {
- continue;
- }
-
- if (count == 0) {
- ret1 = spans[i];
- count++;
- } else {
- if (count == 1) {
- ret = (Object[]) Array.newInstance(kind, spanCount - i + 1);
- ret[0] = ret1;
- }
-
- int prio = flags[i] & SPAN_PRIORITY;
- if (prio != 0) {
- int j;
-
- for (j = 0; j < count; j++) {
- int p = getSpanFlags(ret[j]) & SPAN_PRIORITY;
-
- if (prio > p) {
- break;
- }
- }
-
- System.arraycopy(ret, j, ret, j + 1, count - j);
- ret[j] = spans[i];
- count++;
- } else {
- ret[count++] = spans[i];
- }
- }
- }
-
- if (count == 0) {
- return (T[]) ArrayUtils.emptyArray(kind);
- }
- if (count == 1) {
- ret = (Object[]) Array.newInstance(kind, 1);
- ret[0] = ret1;
- return (T[]) ret;
- }
- if (count == ret.length) {
- return (T[]) ret;
- }
-
- Object[] nret = (Object[]) Array.newInstance(kind, count);
- System.arraycopy(ret, 0, nret, 0, count);
- return (T[]) nret;
- }
-
- /**
- * Return the next offset after <code>start</code> but less than or
- * equal to <code>limit</code> where a span of the specified type
- * begins or ends.
- */
- public int nextSpanTransition(int start, int limit, Class kind) {
- int count = mSpanCount;
- Object[] spans = mSpans;
- int[] starts = mSpanStarts;
- int[] ends = mSpanEnds;
- int gapstart = mGapStart;
- int gaplen = mGapLength;
-
- if (kind == null) {
- kind = Object.class;
- }
-
- for (int i = 0; i < count; i++) {
- int st = starts[i];
- int en = ends[i];
-
- if (st > gapstart)
- st -= gaplen;
- if (en > gapstart)
- en -= gaplen;
-
- if (st > start && st < limit && kind.isInstance(spans[i]))
- limit = st;
- if (en > start && en < limit && kind.isInstance(spans[i]))
- limit = en;
- }
-
- return limit;
- }
-
- /**
- * Return a new CharSequence containing a copy of the specified
- * range of this buffer, including the overlapping spans.
- */
- public CharSequence subSequence(int start, int end) {
- return new SpannableStringBuilder(this, start, end);
- }
-
- /**
- * Copy the specified range of chars from this buffer into the
- * specified array, beginning at the specified offset.
- */
- public void getChars(int start, int end, char[] dest, int destoff) {
- checkRange("getChars", start, end);
-
- if (end <= mGapStart) {
- System.arraycopy(mText, start, dest, destoff, end - start);
- } else if (start >= mGapStart) {
- System.arraycopy(mText, start + mGapLength,
- dest, destoff, end - start);
- } else {
- System.arraycopy(mText, start, dest, destoff, mGapStart - start);
- System.arraycopy(mText, mGapStart + mGapLength,
- dest, destoff + (mGapStart - start),
- end - mGapStart);
- }
- }
-
- /**
- * Return a String containing a copy of the chars in this buffer.
- */
- public String toString() {
- int len = length();
- char[] buf = new char[len];
-
- getChars(0, len, buf, 0);
- return new String(buf);
- }
-
- private TextWatcher[] sendTextWillChange(int start, int before, int after) {
- TextWatcher[] recip = getSpans(start, start + before, TextWatcher.class);
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].beforeTextChanged(this, start, before, after);
- }
-
- return recip;
- }
-
- private void sendTextChange(TextWatcher[] recip, int start, int before,
- int after) {
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].onTextChanged(this, start, before, after);
- }
- }
-
- private void sendTextHasChanged(TextWatcher[] recip) {
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].afterTextChanged(this);
- }
- }
-
- private void sendSpanAdded(Object what, int start, int end) {
- SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class);
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].onSpanAdded(this, what, start, end);
- }
- }
-
- private void sendSpanRemoved(Object what, int start, int end) {
- SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class);
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].onSpanRemoved(this, what, start, end);
- }
- }
-
- private void sendSpanChanged(Object what, int s, int e, int st, int en) {
- SpanWatcher[] recip = getSpans(Math.min(s, st), Math.max(e, en),
- SpanWatcher.class);
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].onSpanChanged(this, what, s, e, st, en);
- }
- }
-
- private static String region(int start, int end) {
- return "(" + start + " ... " + end + ")";
- }
-
- private void checkRange(final String operation, int start, int end) {
- if (end < start) {
- throw new IndexOutOfBoundsException(operation + " " +
- region(start, end) +
- " has end before start");
- }
-
- int len = length();
-
- if (start > len || end > len) {
- throw new IndexOutOfBoundsException(operation + " " +
- region(start, end) +
- " ends beyond length " + len);
- }
-
- if (start < 0 || end < 0) {
- throw new IndexOutOfBoundsException(operation + " " +
- region(start, end) +
- " starts before 0");
- }
- }
-
- private boolean isprint(char c) { // XXX
- if (c >= ' ' && c <= '~')
- return true;
- else
- return false;
- }
-
-/*
- private static final int startFlag(int flag) {
- return (flag >> 4) & 0x0F;
- }
-
- private static final int endFlag(int flag) {
- return flag & 0x0F;
- }
-
- public void dump() { // XXX
- for (int i = 0; i < mGapStart; i++) {
- System.out.print('|');
- System.out.print(' ');
- System.out.print(isprint(mText[i]) ? mText[i] : '.');
- System.out.print(' ');
- }
-
- for (int i = mGapStart; i < mGapStart + mGapLength; i++) {
- System.out.print('|');
- System.out.print('(');
- System.out.print(isprint(mText[i]) ? mText[i] : '.');
- System.out.print(')');
- }
-
- for (int i = mGapStart + mGapLength; i < mText.length; i++) {
- System.out.print('|');
- System.out.print(' ');
- System.out.print(isprint(mText[i]) ? mText[i] : '.');
- System.out.print(' ');
- }
-
- System.out.print('\n');
-
- for (int i = 0; i < mText.length + 1; i++) {
- int found = 0;
- int wfound = 0;
-
- for (int j = 0; j < mSpanCount; j++) {
- if (mSpanStarts[j] == i) {
- found = 1;
- wfound = j;
- break;
- }
-
- if (mSpanEnds[j] == i) {
- found = 2;
- wfound = j;
- break;
- }
- }
-
- if (found == 1) {
- if (startFlag(mSpanFlags[wfound]) == MARK)
- System.out.print("( ");
- if (startFlag(mSpanFlags[wfound]) == PARAGRAPH)
- System.out.print("< ");
- else
- System.out.print("[ ");
- } else if (found == 2) {
- if (endFlag(mSpanFlags[wfound]) == POINT)
- System.out.print(") ");
- if (endFlag(mSpanFlags[wfound]) == PARAGRAPH)
- System.out.print("> ");
- else
- System.out.print("] ");
- } else {
- System.out.print(" ");
- }
- }
-
- System.out.print("\n");
- }
-*/
-
- /**
- * Don't call this yourself -- exists for Canvas to use internally.
- * {@hide}
- */
- public void drawText(Canvas c, int start, int end,
- float x, float y, Paint p) {
- checkRange("drawText", start, end);
-
- if (end <= mGapStart) {
- c.drawText(mText, start, end - start, x, y, p);
- } else if (start >= mGapStart) {
- c.drawText(mText, start + mGapLength, end - start, x, y, p);
- } else {
- char[] buf = TextUtils.obtain(end - start);
-
- getChars(start, end, buf, 0);
- c.drawText(buf, 0, end - start, x, y, p);
- TextUtils.recycle(buf);
- }
- }
-
- /**
- * Don't call this yourself -- exists for Paint to use internally.
- * {@hide}
- */
- public float measureText(int start, int end, Paint p) {
- checkRange("measureText", start, end);
-
- float ret;
-
- if (end <= mGapStart) {
- ret = p.measureText(mText, start, end - start);
- } else if (start >= mGapStart) {
- ret = p.measureText(mText, start + mGapLength, end - start);
- } else {
- char[] buf = TextUtils.obtain(end - start);
-
- getChars(start, end, buf, 0);
- ret = p.measureText(buf, 0, end - start);
- TextUtils.recycle(buf);
- }
-
- return ret;
- }
-
- /**
- * Don't call this yourself -- exists for Paint to use internally.
- * {@hide}
- */
- public int getTextWidths(int start, int end, float[] widths, Paint p) {
- checkRange("getTextWidths", start, end);
-
- int ret;
-
- if (end <= mGapStart) {
- ret = p.getTextWidths(mText, start, end - start, widths);
- } else if (start >= mGapStart) {
- ret = p.getTextWidths(mText, start + mGapLength, end - start,
- widths);
- } else {
- char[] buf = TextUtils.obtain(end - start);
-
- getChars(start, end, buf, 0);
- ret = p.getTextWidths(buf, 0, end - start, widths);
- TextUtils.recycle(buf);
- }
-
- return ret;
- }
-
- // Documentation from interface
- public void setFilters(InputFilter[] filters) {
- if (filters == null) {
- throw new IllegalArgumentException();
- }
-
- mFilters = filters;
- }
-
- // Documentation from interface
- public InputFilter[] getFilters() {
- return mFilters;
- }
-
- private static final InputFilter[] NO_FILTERS = new InputFilter[0];
- private InputFilter[] mFilters = NO_FILTERS;
-
- private char[] mText;
- private int mGapStart;
- private int mGapLength;
-
- private Object[] mSpans;
- private int[] mSpanStarts;
- private int[] mSpanEnds;
- private int[] mSpanFlags;
- private int mSpanCount;
-
- private static final int MARK = 1;
- private static final int POINT = 2;
- private static final int PARAGRAPH = 3;
-
- private static final int START_MASK = 0xF0;
- private static final int END_MASK = 0x0F;
- private static final int START_SHIFT = 4;
-}
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
deleted file mode 100644
index 0412285..0000000
--- a/core/java/android/text/SpannableStringInternal.java
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import com.android.internal.util.ArrayUtils;
-
-import java.lang.reflect.Array;
-
-/* package */ abstract class SpannableStringInternal
-{
- /* package */ SpannableStringInternal(CharSequence source,
- int start, int end) {
- if (start == 0 && end == source.length())
- mText = source.toString();
- else
- mText = source.toString().substring(start, end);
-
- int initial = ArrayUtils.idealIntArraySize(0);
- mSpans = new Object[initial];
- mSpanData = new int[initial * 3];
-
- if (source instanceof Spanned) {
- Spanned sp = (Spanned) source;
- Object[] spans = sp.getSpans(start, end, Object.class);
-
- for (int i = 0; i < spans.length; i++) {
- int st = sp.getSpanStart(spans[i]);
- int en = sp.getSpanEnd(spans[i]);
- int fl = sp.getSpanFlags(spans[i]);
-
- if (st < start)
- st = start;
- if (en > end)
- en = end;
-
- setSpan(spans[i], st - start, en - start, fl);
- }
- }
- }
-
- public final int length() {
- return mText.length();
- }
-
- public final char charAt(int i) {
- return mText.charAt(i);
- }
-
- public final String toString() {
- return mText;
- }
-
- /* subclasses must do subSequence() to preserve type */
-
- public final void getChars(int start, int end, char[] dest, int off) {
- mText.getChars(start, end, dest, off);
- }
-
- /* package */ void setSpan(Object what, int start, int end, int flags) {
- int nstart = start;
- int nend = end;
-
- checkRange("setSpan", start, end);
-
- if ((flags & Spannable.SPAN_PARAGRAPH) == Spannable.SPAN_PARAGRAPH) {
- if (start != 0 && start != length()) {
- char c = charAt(start - 1);
-
- if (c != '\n')
- throw new RuntimeException(
- "PARAGRAPH span must start at paragraph boundary" +
- " (" + start + " follows " + c + ")");
- }
-
- if (end != 0 && end != length()) {
- char c = charAt(end - 1);
-
- if (c != '\n')
- throw new RuntimeException(
- "PARAGRAPH span must end at paragraph boundary" +
- " (" + end + " follows " + c + ")");
- }
- }
-
- int count = mSpanCount;
- Object[] spans = mSpans;
- int[] data = mSpanData;
-
- for (int i = 0; i < count; i++) {
- if (spans[i] == what) {
- int ostart = data[i * COLUMNS + START];
- int oend = data[i * COLUMNS + END];
-
- data[i * COLUMNS + START] = start;
- data[i * COLUMNS + END] = end;
- data[i * COLUMNS + FLAGS] = flags;
-
- sendSpanChanged(what, ostart, oend, nstart, nend);
- return;
- }
- }
-
- if (mSpanCount + 1 >= mSpans.length) {
- int newsize = ArrayUtils.idealIntArraySize(mSpanCount + 1);
- Object[] newtags = new Object[newsize];
- int[] newdata = new int[newsize * 3];
-
- System.arraycopy(mSpans, 0, newtags, 0, mSpanCount);
- System.arraycopy(mSpanData, 0, newdata, 0, mSpanCount * 3);
-
- mSpans = newtags;
- mSpanData = newdata;
- }
-
- mSpans[mSpanCount] = what;
- mSpanData[mSpanCount * COLUMNS + START] = start;
- mSpanData[mSpanCount * COLUMNS + END] = end;
- mSpanData[mSpanCount * COLUMNS + FLAGS] = flags;
- mSpanCount++;
-
- if (this instanceof Spannable)
- sendSpanAdded(what, nstart, nend);
- }
-
- /* package */ void removeSpan(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
- int[] data = mSpanData;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- int ostart = data[i * COLUMNS + START];
- int oend = data[i * COLUMNS + END];
-
- int c = count - (i + 1);
-
- System.arraycopy(spans, i + 1, spans, i, c);
- System.arraycopy(data, (i + 1) * COLUMNS,
- data, i * COLUMNS, c * COLUMNS);
-
- mSpanCount--;
-
- sendSpanRemoved(what, ostart, oend);
- return;
- }
- }
- }
-
- public int getSpanStart(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
- int[] data = mSpanData;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- return data[i * COLUMNS + START];
- }
- }
-
- return -1;
- }
-
- public int getSpanEnd(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
- int[] data = mSpanData;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- return data[i * COLUMNS + END];
- }
- }
-
- return -1;
- }
-
- public int getSpanFlags(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
- int[] data = mSpanData;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- return data[i * COLUMNS + FLAGS];
- }
- }
-
- return 0;
- }
-
- public <T> T[] getSpans(int queryStart, int queryEnd, Class<T> kind) {
- int count = 0;
-
- int spanCount = mSpanCount;
- Object[] spans = mSpans;
- int[] data = mSpanData;
- Object[] ret = null;
- Object ret1 = null;
-
- for (int i = 0; i < spanCount; i++) {
- int spanStart = data[i * COLUMNS + START];
- int spanEnd = data[i * COLUMNS + END];
-
- if (spanStart > queryEnd) {
- continue;
- }
- if (spanEnd < queryStart) {
- continue;
- }
-
- if (spanStart != spanEnd && queryStart != queryEnd) {
- if (spanStart == queryEnd) {
- continue;
- }
- if (spanEnd == queryStart) {
- continue;
- }
- }
-
- if (kind != null && !kind.isInstance(spans[i])) {
- continue;
- }
-
- if (count == 0) {
- ret1 = spans[i];
- count++;
- } else {
- if (count == 1) {
- ret = (Object[]) Array.newInstance(kind, spanCount - i + 1);
- ret[0] = ret1;
- }
-
- int prio = data[i * COLUMNS + FLAGS] & Spanned.SPAN_PRIORITY;
- if (prio != 0) {
- int j;
-
- for (j = 0; j < count; j++) {
- int p = getSpanFlags(ret[j]) & Spanned.SPAN_PRIORITY;
-
- if (prio > p) {
- break;
- }
- }
-
- System.arraycopy(ret, j, ret, j + 1, count - j);
- ret[j] = spans[i];
- count++;
- } else {
- ret[count++] = spans[i];
- }
- }
- }
-
- if (count == 0) {
- return (T[]) ArrayUtils.emptyArray(kind);
- }
- if (count == 1) {
- ret = (Object[]) Array.newInstance(kind, 1);
- ret[0] = ret1;
- return (T[]) ret;
- }
- if (count == ret.length) {
- return (T[]) ret;
- }
-
- Object[] nret = (Object[]) Array.newInstance(kind, count);
- System.arraycopy(ret, 0, nret, 0, count);
- return (T[]) nret;
- }
-
- public int nextSpanTransition(int start, int limit, Class kind) {
- int count = mSpanCount;
- Object[] spans = mSpans;
- int[] data = mSpanData;
-
- if (kind == null) {
- kind = Object.class;
- }
-
- for (int i = 0; i < count; i++) {
- int st = data[i * COLUMNS + START];
- int en = data[i * COLUMNS + END];
-
- if (st > start && st < limit && kind.isInstance(spans[i]))
- limit = st;
- if (en > start && en < limit && kind.isInstance(spans[i]))
- limit = en;
- }
-
- return limit;
- }
-
- private void sendSpanAdded(Object what, int start, int end) {
- SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class);
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].onSpanAdded((Spannable) this, what, start, end);
- }
- }
-
- private void sendSpanRemoved(Object what, int start, int end) {
- SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class);
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].onSpanRemoved((Spannable) this, what, start, end);
- }
- }
-
- private void sendSpanChanged(Object what, int s, int e, int st, int en) {
- SpanWatcher[] recip = getSpans(Math.min(s, st), Math.max(e, en),
- SpanWatcher.class);
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].onSpanChanged((Spannable) this, what, s, e, st, en);
- }
- }
-
- private static String region(int start, int end) {
- return "(" + start + " ... " + end + ")";
- }
-
- private void checkRange(final String operation, int start, int end) {
- if (end < start) {
- throw new IndexOutOfBoundsException(operation + " " +
- region(start, end) +
- " has end before start");
- }
-
- int len = length();
-
- if (start > len || end > len) {
- throw new IndexOutOfBoundsException(operation + " " +
- region(start, end) +
- " ends beyond length " + len);
- }
-
- if (start < 0 || end < 0) {
- throw new IndexOutOfBoundsException(operation + " " +
- region(start, end) +
- " starts before 0");
- }
- }
-
- private String mText;
- private Object[] mSpans;
- private int[] mSpanData;
- private int mSpanCount;
-
- /* package */ static final Object[] EMPTY = new Object[0];
-
- private static final int START = 0;
- private static final int END = 1;
- private static final int FLAGS = 2;
- private static final int COLUMNS = 3;
-}
diff --git a/core/java/android/text/Spanned.java b/core/java/android/text/Spanned.java
deleted file mode 100644
index 154497d..0000000
--- a/core/java/android/text/Spanned.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-/**
- * This is the interface for text that has markup objects attached to
- * ranges of it. Not all text classes have mutable markup or text;
- * see {@link Spannable} for mutable markup and {@link Editable} for
- * mutable text.
- */
-public interface Spanned
-extends CharSequence
-{
- /**
- * Bitmask of bits that are relevent for controlling point/mark behavior
- * of spans.
- */
- public static final int SPAN_POINT_MARK_MASK = 0x33;
-
- /**
- * 0-length spans with type SPAN_MARK_MARK behave like text marks:
- * they remain at their original offset when text is inserted
- * at that offset.
- */
- public static final int SPAN_MARK_MARK = 0x11;
- /**
- * SPAN_MARK_POINT is a synonym for {@link #SPAN_INCLUSIVE_INCLUSIVE}.
- */
- public static final int SPAN_MARK_POINT = 0x12;
- /**
- * SPAN_POINT_MARK is a synonym for {@link #SPAN_EXCLUSIVE_EXCLUSIVE}.
- */
- public static final int SPAN_POINT_MARK = 0x21;
-
- /**
- * 0-length spans with type SPAN_POINT_POINT behave like cursors:
- * they are pushed forward by the length of the insertion when text
- * is inserted at their offset.
- */
- public static final int SPAN_POINT_POINT = 0x22;
-
- /**
- * SPAN_PARAGRAPH behaves like SPAN_INCLUSIVE_EXCLUSIVE
- * (SPAN_MARK_MARK), except that if either end of the span is
- * at the end of the buffer, that end behaves like _POINT
- * instead (so SPAN_INCLUSIVE_INCLUSIVE if it starts in the
- * middle and ends at the end, or SPAN_EXCLUSIVE_INCLUSIVE
- * if it both starts and ends at the end).
- * <p>
- * Its endpoints must be the start or end of the buffer or
- * immediately after a \n character, and if the \n
- * that anchors it is deleted, the endpoint is pulled to the
- * next \n that follows in the buffer (or to the end of
- * the buffer).
- */
- public static final int SPAN_PARAGRAPH = 0x33;
-
- /**
- * Non-0-length spans of type SPAN_INCLUSIVE_EXCLUSIVE expand
- * to include text inserted at their starting point but not at their
- * ending point. When 0-length, they behave like marks.
- */
- public static final int SPAN_INCLUSIVE_EXCLUSIVE = SPAN_MARK_MARK;
-
- /**
- * Spans of type SPAN_INCLUSIVE_INCLUSIVE expand
- * to include text inserted at either their starting or ending point.
- */
- public static final int SPAN_INCLUSIVE_INCLUSIVE = SPAN_MARK_POINT;
-
- /**
- * Spans of type SPAN_EXCLUSIVE_EXCLUSIVE do not expand
- * to include text inserted at either their starting or ending point.
- * They can never have a length of 0 and are automatically removed
- * from the buffer if all the text they cover is removed.
- */
- public static final int SPAN_EXCLUSIVE_EXCLUSIVE = SPAN_POINT_MARK;
-
- /**
- * Non-0-length spans of type SPAN_INCLUSIVE_EXCLUSIVE expand
- * to include text inserted at their ending point but not at their
- * starting point. When 0-length, they behave like points.
- */
- public static final int SPAN_EXCLUSIVE_INCLUSIVE = SPAN_POINT_POINT;
-
- /**
- * This flag is set on spans that are being used to apply temporary
- * styling information on the composing text of an input method, so that
- * they can be found and removed when the composing text is being
- * replaced.
- */
- public static final int SPAN_COMPOSING = 0x100;
-
- /**
- * This flag will be set for intermediate span changes, meaning there
- * is guaranteed to be another change following it. Typically it is
- * used for {@link Selection} which automatically uses this with the first
- * offset it sets when updating the selection.
- */
- public static final int SPAN_INTERMEDIATE = 0x200;
-
- /**
- * The bits numbered SPAN_USER_SHIFT and above are available
- * for callers to use to store scalar data associated with their
- * span object.
- */
- public static final int SPAN_USER_SHIFT = 24;
- /**
- * The bits specified by the SPAN_USER bitfield are available
- * for callers to use to store scalar data associated with their
- * span object.
- */
- public static final int SPAN_USER = 0xFFFFFFFF << SPAN_USER_SHIFT;
-
- /**
- * The bits numbered just above SPAN_PRIORITY_SHIFT determine the order
- * of change notifications -- higher numbers go first. You probably
- * don't need to set this; it is used so that when text changes, the
- * text layout gets the chance to update itself before any other
- * callbacks can inquire about the layout of the text.
- */
- public static final int SPAN_PRIORITY_SHIFT = 16;
- /**
- * The bits specified by the SPAN_PRIORITY bitmap determine the order
- * of change notifications -- higher numbers go first. You probably
- * don't need to set this; it is used so that when text changes, the
- * text layout gets the chance to update itself before any other
- * callbacks can inquire about the layout of the text.
- */
- public static final int SPAN_PRIORITY = 0xFF << SPAN_PRIORITY_SHIFT;
-
- /**
- * Return an array of the markup objects attached to the specified
- * slice of this CharSequence and whose type is the specified type
- * or a subclass of it. Specify Object.class for the type if you
- * want all the objects regardless of type.
- */
- public <T> T[] getSpans(int start, int end, Class<T> type);
-
- /**
- * Return the beginning of the range of text to which the specified
- * markup object is attached, or -1 if the object is not attached.
- */
- public int getSpanStart(Object tag);
-
- /**
- * Return the end of the range of text to which the specified
- * markup object is attached, or -1 if the object is not attached.
- */
- public int getSpanEnd(Object tag);
-
- /**
- * Return the flags that were specified when {@link Spannable#setSpan} was
- * used to attach the specified markup object, or 0 if the specified
- * object has not been attached.
- */
- public int getSpanFlags(Object tag);
-
- /**
- * Return the first offset greater than or equal to <code>start</code>
- * where a markup object of class <code>type</code> begins or ends,
- * or <code>limit</code> if there are no starts or ends greater than or
- * equal to <code>start</code> but less than <code>limit</code>. Specify
- * <code>null</code> or Object.class for the type if you want every
- * transition regardless of type.
- */
- public int nextSpanTransition(int start, int limit, Class type);
-}
diff --git a/core/java/android/text/SpannedString.java b/core/java/android/text/SpannedString.java
deleted file mode 100644
index afed221..0000000
--- a/core/java/android/text/SpannedString.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-
-/**
- * This is the class for text whose content and markup are immutable.
- * For mutable markup, see {@link SpannableString}; for mutable text,
- * see {@link SpannableStringBuilder}.
- */
-public final class SpannedString
-extends SpannableStringInternal
-implements CharSequence, GetChars, Spanned
-{
- public SpannedString(CharSequence source) {
- super(source, 0, source.length());
- }
-
- private SpannedString(CharSequence source, int start, int end) {
- super(source, start, end);
- }
-
- public CharSequence subSequence(int start, int end) {
- return new SpannedString(this, start, end);
- }
-
- public static SpannedString valueOf(CharSequence source) {
- if (source instanceof SpannedString) {
- return (SpannedString) source;
- } else {
- return new SpannedString(source);
- }
- }
-}
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
deleted file mode 100644
index 0fef40b..0000000
--- a/core/java/android/text/StaticLayout.java
+++ /dev/null
@@ -1,1195 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import android.graphics.Paint;
-import com.android.internal.util.ArrayUtils;
-import android.util.Log;
-import android.text.style.LeadingMarginSpan;
-import android.text.style.LineHeightSpan;
-import android.text.style.MetricAffectingSpan;
-import android.text.style.ReplacementSpan;
-
-/**
- * StaticLayout is a Layout for text that will not be edited after it
- * is laid out. Use {@link DynamicLayout} for text that may change.
- * <p>This is used by widgets to control text layout. You should not need
- * to use this class directly unless you are implementing your own widget
- * or custom display object, or would be tempted to call
- * {@link android.graphics.Canvas#drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint)
- * Canvas.drawText()} directly.</p>
- */
-public class
-StaticLayout
-extends Layout
-{
- public StaticLayout(CharSequence source, TextPaint paint,
- int width,
- Alignment align, float spacingmult, float spacingadd,
- boolean includepad) {
- this(source, 0, source.length(), paint, width, align,
- spacingmult, spacingadd, includepad);
- }
-
- public StaticLayout(CharSequence source, int bufstart, int bufend,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- boolean includepad) {
- this(source, bufstart, bufend, paint, outerwidth, align,
- spacingmult, spacingadd, includepad, null, 0);
- }
-
- public StaticLayout(CharSequence source, int bufstart, int bufend,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- boolean includepad,
- TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
- super((ellipsize == null)
- ? source
- : (source instanceof Spanned)
- ? new SpannedEllipsizer(source)
- : new Ellipsizer(source),
- paint, outerwidth, align, spacingmult, spacingadd);
-
- /*
- * This is annoying, but we can't refer to the layout until
- * superclass construction is finished, and the superclass
- * constructor wants the reference to the display text.
- *
- * This will break if the superclass constructor ever actually
- * cares about the content instead of just holding the reference.
- */
- if (ellipsize != null) {
- Ellipsizer e = (Ellipsizer) getText();
-
- e.mLayout = this;
- e.mWidth = ellipsizedWidth;
- e.mMethod = ellipsize;
- mEllipsizedWidth = ellipsizedWidth;
-
- mColumns = COLUMNS_ELLIPSIZE;
- } else {
- mColumns = COLUMNS_NORMAL;
- mEllipsizedWidth = outerwidth;
- }
-
- mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)];
- mLineDirections = new Directions[
- ArrayUtils.idealIntArraySize(2 * mColumns)];
-
- generate(source, bufstart, bufend, paint, outerwidth, align,
- spacingmult, spacingadd, includepad, includepad,
- ellipsize != null, ellipsizedWidth, ellipsize);
-
- mChdirs = null;
- mChs = null;
- mWidths = null;
- mFontMetricsInt = null;
- }
-
- /* package */ StaticLayout(boolean ellipsize) {
- super(null, null, 0, null, 0, 0);
-
- mColumns = COLUMNS_ELLIPSIZE;
- mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)];
- mLineDirections = new Directions[
- ArrayUtils.idealIntArraySize(2 * mColumns)];
- }
-
- /* package */ void generate(CharSequence source, int bufstart, int bufend,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- boolean includepad, boolean trackpad,
- boolean breakOnlyAtSpaces,
- float ellipsizedWidth, TextUtils.TruncateAt where) {
- mLineCount = 0;
-
- int v = 0;
- boolean needMultiply = (spacingmult != 1 || spacingadd != 0);
-
- Paint.FontMetricsInt fm = mFontMetricsInt;
- int[] choosehtv = null;
-
- int end = TextUtils.indexOf(source, '\n', bufstart, bufend);
- int bufsiz = end >= 0 ? end - bufstart : bufend - bufstart;
- boolean first = true;
-
- if (mChdirs == null) {
- mChdirs = new byte[ArrayUtils.idealByteArraySize(bufsiz + 1)];
- mChs = new char[ArrayUtils.idealCharArraySize(bufsiz + 1)];
- mWidths = new float[ArrayUtils.idealIntArraySize((bufsiz + 1) * 2)];
- }
-
- byte[] chdirs = mChdirs;
- char[] chs = mChs;
- float[] widths = mWidths;
-
- AlteredCharSequence alter = null;
- Spanned spanned = null;
-
- if (source instanceof Spanned)
- spanned = (Spanned) source;
-
- int DEFAULT_DIR = DIR_LEFT_TO_RIGHT; // XXX
-
- for (int start = bufstart; start <= bufend; start = end) {
- if (first)
- first = false;
- else
- end = TextUtils.indexOf(source, '\n', start, bufend);
-
- if (end < 0)
- end = bufend;
- else
- end++;
-
- int firstwidth = outerwidth;
- int restwidth = outerwidth;
-
- LineHeightSpan[] chooseht = null;
-
- if (spanned != null) {
- LeadingMarginSpan[] sp;
-
- sp = spanned.getSpans(start, end, LeadingMarginSpan.class);
- for (int i = 0; i < sp.length; i++) {
- firstwidth -= sp[i].getLeadingMargin(true);
- restwidth -= sp[i].getLeadingMargin(false);
- }
-
- chooseht = spanned.getSpans(start, end, LineHeightSpan.class);
-
- if (chooseht.length != 0) {
- if (choosehtv == null ||
- choosehtv.length < chooseht.length) {
- choosehtv = new int[ArrayUtils.idealIntArraySize(
- chooseht.length)];
- }
-
- for (int i = 0; i < chooseht.length; i++) {
- int o = spanned.getSpanStart(chooseht[i]);
-
- if (o < start) {
- // starts in this layout, before the
- // current paragraph
-
- choosehtv[i] = getLineTop(getLineForOffset(o));
- } else {
- // starts in this paragraph
-
- choosehtv[i] = v;
- }
- }
- }
- }
-
- if (end - start > chdirs.length) {
- chdirs = new byte[ArrayUtils.idealByteArraySize(end - start)];
- mChdirs = chdirs;
- }
- if (end - start > chs.length) {
- chs = new char[ArrayUtils.idealCharArraySize(end - start)];
- mChs = chs;
- }
- if ((end - start) * 2 > widths.length) {
- widths = new float[ArrayUtils.idealIntArraySize((end - start) * 2)];
- mWidths = widths;
- }
-
- TextUtils.getChars(source, start, end, chs, 0);
- final int n = end - start;
-
- boolean easy = true;
- boolean altered = false;
- int dir = DEFAULT_DIR; // XXX
-
- for (int i = 0; i < n; i++) {
- if (chs[i] >= FIRST_RIGHT_TO_LEFT) {
- easy = false;
- break;
- }
- }
-
- if (!easy) {
- AndroidCharacter.getDirectionalities(chs, chdirs, end - start);
-
- /*
- * Determine primary paragraph direction
- */
-
- for (int j = start; j < end; j++) {
- int d = chdirs[j - start];
-
- if (d == Character.DIRECTIONALITY_LEFT_TO_RIGHT) {
- dir = DIR_LEFT_TO_RIGHT;
- break;
- }
- if (d == Character.DIRECTIONALITY_RIGHT_TO_LEFT) {
- dir = DIR_RIGHT_TO_LEFT;
- break;
- }
- }
-
- /*
- * XXX Explicit overrides should go here
- */
-
- /*
- * Weak type resolution
- */
-
- final byte SOR = dir == DIR_LEFT_TO_RIGHT ?
- Character.DIRECTIONALITY_LEFT_TO_RIGHT :
- Character.DIRECTIONALITY_RIGHT_TO_LEFT;
-
- // dump(chdirs, n, "initial");
-
- // W1 non spacing marks
- for (int j = 0; j < n; j++) {
- if (chdirs[j] == Character.NON_SPACING_MARK) {
- if (j == 0)
- chdirs[j] = SOR;
- else
- chdirs[j] = chdirs[j - 1];
- }
- }
-
- // dump(chdirs, n, "W1");
-
- // W2 european numbers
- byte cur = SOR;
- for (int j = 0; j < n; j++) {
- byte d = chdirs[j];
-
- if (d == Character.DIRECTIONALITY_LEFT_TO_RIGHT ||
- d == Character.DIRECTIONALITY_RIGHT_TO_LEFT ||
- d == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC)
- cur = d;
- else if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER) {
- if (cur ==
- Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC)
- chdirs[j] = Character.DIRECTIONALITY_ARABIC_NUMBER;
- }
- }
-
- // dump(chdirs, n, "W2");
-
- // W3 arabic letters
- for (int j = 0; j < n; j++) {
- if (chdirs[j] == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC)
- chdirs[j] = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
- }
-
- // dump(chdirs, n, "W3");
-
- // W4 single separator between numbers
- for (int j = 1; j < n - 1; j++) {
- byte d = chdirs[j];
- byte prev = chdirs[j - 1];
- byte next = chdirs[j + 1];
-
- if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR) {
- if (prev == Character.DIRECTIONALITY_EUROPEAN_NUMBER &&
- next == Character.DIRECTIONALITY_EUROPEAN_NUMBER)
- chdirs[j] = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
- } else if (d == Character.DIRECTIONALITY_COMMON_NUMBER_SEPARATOR) {
- if (prev == Character.DIRECTIONALITY_EUROPEAN_NUMBER &&
- next == Character.DIRECTIONALITY_EUROPEAN_NUMBER)
- chdirs[j] = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
- if (prev == Character.DIRECTIONALITY_ARABIC_NUMBER &&
- next == Character.DIRECTIONALITY_ARABIC_NUMBER)
- chdirs[j] = Character.DIRECTIONALITY_ARABIC_NUMBER;
- }
- }
-
- // dump(chdirs, n, "W4");
-
- // W5 european number terminators
- boolean adjacent = false;
- for (int j = 0; j < n; j++) {
- byte d = chdirs[j];
-
- if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER)
- adjacent = true;
- else if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR && adjacent)
- chdirs[j] = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
- else
- adjacent = false;
- }
-
- //dump(chdirs, n, "W5");
-
- // W5 european number terminators part 2,
- // W6 separators and terminators
- adjacent = false;
- for (int j = n - 1; j >= 0; j--) {
- byte d = chdirs[j];
-
- if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER)
- adjacent = true;
- else if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR) {
- if (adjacent)
- chdirs[j] = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
- else
- chdirs[j] = Character.DIRECTIONALITY_OTHER_NEUTRALS;
- }
- else {
- adjacent = false;
-
- if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR ||
- d == Character.DIRECTIONALITY_COMMON_NUMBER_SEPARATOR ||
- d == Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR ||
- d == Character.DIRECTIONALITY_SEGMENT_SEPARATOR)
- chdirs[j] = Character.DIRECTIONALITY_OTHER_NEUTRALS;
- }
- }
-
- // dump(chdirs, n, "W6");
-
- // W7 strong direction of european numbers
- cur = SOR;
- for (int j = 0; j < n; j++) {
- byte d = chdirs[j];
-
- if (d == SOR ||
- d == Character.DIRECTIONALITY_LEFT_TO_RIGHT ||
- d == Character.DIRECTIONALITY_RIGHT_TO_LEFT)
- cur = d;
-
- if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER)
- chdirs[j] = cur;
- }
-
- // dump(chdirs, n, "W7");
-
- // N1, N2 neutrals
- cur = SOR;
- for (int j = 0; j < n; j++) {
- byte d = chdirs[j];
-
- if (d == Character.DIRECTIONALITY_LEFT_TO_RIGHT ||
- d == Character.DIRECTIONALITY_RIGHT_TO_LEFT) {
- cur = d;
- } else if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER ||
- d == Character.DIRECTIONALITY_ARABIC_NUMBER) {
- cur = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
- } else {
- byte dd = SOR;
- int k;
-
- for (k = j + 1; k < n; k++) {
- dd = chdirs[k];
-
- if (dd == Character.DIRECTIONALITY_LEFT_TO_RIGHT ||
- dd == Character.DIRECTIONALITY_RIGHT_TO_LEFT) {
- break;
- }
- if (dd == Character.DIRECTIONALITY_EUROPEAN_NUMBER ||
- dd == Character.DIRECTIONALITY_ARABIC_NUMBER) {
- dd = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
- break;
- }
- }
-
- for (int y = j; y < k; y++) {
- if (dd == cur)
- chdirs[y] = cur;
- else
- chdirs[y] = SOR;
- }
-
- j = k - 1;
- }
- }
-
- // dump(chdirs, n, "final");
-
- // extra: enforce that all tabs go the primary direction
-
- for (int j = 0; j < n; j++) {
- if (chs[j] == '\t')
- chdirs[j] = SOR;
- }
-
- // extra: enforce that object replacements go to the
- // primary direction
- // and that none of the underlying characters are treated
- // as viable breakpoints
-
- if (source instanceof Spanned) {
- Spanned sp = (Spanned) source;
- ReplacementSpan[] spans = sp.getSpans(start, end, ReplacementSpan.class);
-
- for (int y = 0; y < spans.length; y++) {
- int a = sp.getSpanStart(spans[y]);
- int b = sp.getSpanEnd(spans[y]);
-
- for (int x = a; x < b; x++) {
- chdirs[x - start] = SOR;
- chs[x - start] = '\uFFFC';
- }
- }
- }
-
- // Do mirroring for right-to-left segments
-
- for (int i = 0; i < n; i++) {
- if (chdirs[i] == Character.DIRECTIONALITY_RIGHT_TO_LEFT) {
- int j;
-
- for (j = i; j < n; j++) {
- if (chdirs[j] !=
- Character.DIRECTIONALITY_RIGHT_TO_LEFT)
- break;
- }
-
- if (AndroidCharacter.mirror(chs, i, j - i))
- altered = true;
-
- i = j - 1;
- }
- }
- }
-
- CharSequence sub;
-
- if (altered) {
- if (alter == null)
- alter = AlteredCharSequence.make(source, chs, start, end);
- else
- alter.update(chs, start, end);
-
- sub = alter;
- } else {
- sub = source;
- }
-
- int width = firstwidth;
-
- float w = 0;
- int here = start;
-
- int ok = start;
- float okwidth = w;
- int okascent = 0, okdescent = 0, oktop = 0, okbottom = 0;
-
- int fit = start;
- float fitwidth = w;
- int fitascent = 0, fitdescent = 0, fittop = 0, fitbottom = 0;
-
- boolean tab = false;
-
- int next;
- for (int i = start; i < end; i = next) {
- if (spanned == null)
- next = end;
- else
- next = spanned.nextSpanTransition(i, end,
- MetricAffectingSpan.
- class);
-
- if (spanned == null) {
- paint.getTextWidths(sub, i, next, widths);
- System.arraycopy(widths, 0, widths,
- end - start + (i - start), next - i);
-
- paint.getFontMetricsInt(fm);
- } else {
- mWorkPaint.baselineShift = 0;
-
- Styled.getTextWidths(paint, mWorkPaint,
- spanned, i, next,
- widths, fm);
- System.arraycopy(widths, 0, widths,
- end - start + (i - start), next - i);
-
- if (mWorkPaint.baselineShift < 0) {
- fm.ascent += mWorkPaint.baselineShift;
- fm.top += mWorkPaint.baselineShift;
- } else {
- fm.descent += mWorkPaint.baselineShift;
- fm.bottom += mWorkPaint.baselineShift;
- }
- }
-
- int fmtop = fm.top;
- int fmbottom = fm.bottom;
- int fmascent = fm.ascent;
- int fmdescent = fm.descent;
-
- if (false) {
- StringBuilder sb = new StringBuilder();
- for (int j = i; j < next; j++) {
- sb.append(widths[j - start + (end - start)]);
- sb.append(' ');
- }
-
- Log.e("text", sb.toString());
- }
-
- for (int j = i; j < next; j++) {
- char c = chs[j - start];
- float before = w;
-
- switch (c) {
- case '\n':
- break;
-
- case '\t':
- w = Layout.nextTab(sub, start, end, w, null);
- tab = true;
- break;
-
- default:
- w += widths[j - start + (end - start)];
- }
-
- // Log.e("text", "was " + before + " now " + w + " after " + c + " within " + width);
-
- if (w <= width) {
- fitwidth = w;
- fit = j + 1;
-
- if (fmtop < fittop)
- fittop = fmtop;
- if (fmascent < fitascent)
- fitascent = fmascent;
- if (fmdescent > fitdescent)
- fitdescent = fmdescent;
- if (fmbottom > fitbottom)
- fitbottom = fmbottom;
-
- /*
- * From the Unicode Line Breaking Algorithm:
- * (at least approximately)
- *
- * .,:; are class IS: breakpoints
- * except when adjacent to digits
- * / is class SY: a breakpoint
- * except when followed by a digit.
- * - is class HY: a breakpoint
- * except when followed by a digit.
- *
- * Ideographs are class ID: breakpoints when adjacent.
- */
-
- if (c == ' ' || c == '\t' ||
- ((c == '.' || c == ',' || c == ':' || c == ';') &&
- (j - 1 < here || !Character.isDigit(chs[j - 1 - start])) &&
- (j + 1 >= next || !Character.isDigit(chs[j + 1 - start]))) ||
- ((c == '/' || c == '-') &&
- (j + 1 >= next || !Character.isDigit(chs[j + 1 - start]))) ||
- (c >= FIRST_CJK && isIdeographic(c) &&
- j + 1 < next && isIdeographic(chs[j + 1 - start]))) {
- okwidth = w;
- ok = j + 1;
-
- if (fittop < oktop)
- oktop = fittop;
- if (fitascent < okascent)
- okascent = fitascent;
- if (fitdescent > okdescent)
- okdescent = fitdescent;
- if (fitbottom > okbottom)
- okbottom = fitbottom;
- }
- } else if (breakOnlyAtSpaces) {
- if (ok != here) {
- // Log.e("text", "output ok " + here + " to " +ok);
-
- while (ok < next && chs[ok - start] == ' ') {
- ok++;
- }
-
- v = out(source,
- here, ok,
- okascent, okdescent, oktop, okbottom,
- v,
- spacingmult, spacingadd, chooseht,
- choosehtv, fm, tab,
- needMultiply, start, chdirs, dir, easy,
- ok == bufend, includepad, trackpad,
- widths, start, end - start,
- where, ellipsizedWidth, okwidth,
- paint);
-
- here = ok;
- } else {
- // Act like it fit even though it didn't.
-
- fitwidth = w;
- fit = j + 1;
-
- if (fmtop < fittop)
- fittop = fmtop;
- if (fmascent < fitascent)
- fitascent = fmascent;
- if (fmdescent > fitdescent)
- fitdescent = fmdescent;
- if (fmbottom > fitbottom)
- fitbottom = fmbottom;
- }
- } else {
- if (ok != here) {
- // Log.e("text", "output ok " + here + " to " +ok);
-
- while (ok < next && chs[ok - start] == ' ') {
- ok++;
- }
-
- v = out(source,
- here, ok,
- okascent, okdescent, oktop, okbottom,
- v,
- spacingmult, spacingadd, chooseht,
- choosehtv, fm, tab,
- needMultiply, start, chdirs, dir, easy,
- ok == bufend, includepad, trackpad,
- widths, start, end - start,
- where, ellipsizedWidth, okwidth,
- paint);
-
- here = ok;
- } else if (fit != here) {
- // Log.e("text", "output fit " + here + " to " +fit);
- v = out(source,
- here, fit,
- fitascent, fitdescent,
- fittop, fitbottom,
- v,
- spacingmult, spacingadd, chooseht,
- choosehtv, fm, tab,
- needMultiply, start, chdirs, dir, easy,
- fit == bufend, includepad, trackpad,
- widths, start, end - start,
- where, ellipsizedWidth, fitwidth,
- paint);
-
- here = fit;
- } else {
- // Log.e("text", "output one " + here + " to " +(here + 1));
- measureText(paint, mWorkPaint,
- source, here, here + 1, fm, tab,
- null);
-
- v = out(source,
- here, here+1,
- fm.ascent, fm.descent,
- fm.top, fm.bottom,
- v,
- spacingmult, spacingadd, chooseht,
- choosehtv, fm, tab,
- needMultiply, start, chdirs, dir, easy,
- here + 1 == bufend, includepad,
- trackpad,
- widths, start, end - start,
- where, ellipsizedWidth,
- widths[here - start], paint);
-
- here = here + 1;
- }
-
- if (here < i) {
- j = next = here; // must remeasure
- } else {
- j = here - 1; // continue looping
- }
-
- ok = fit = here;
- w = 0;
- fitascent = fitdescent = fittop = fitbottom = 0;
- okascent = okdescent = oktop = okbottom = 0;
-
- width = restwidth;
- }
- }
- }
-
- if (end != here) {
- if ((fittop | fitbottom | fitdescent | fitascent) == 0) {
- paint.getFontMetricsInt(fm);
-
- fittop = fm.top;
- fitbottom = fm.bottom;
- fitascent = fm.ascent;
- fitdescent = fm.descent;
- }
-
- // Log.e("text", "output rest " + here + " to " + end);
-
- v = out(source,
- here, end, fitascent, fitdescent,
- fittop, fitbottom,
- v,
- spacingmult, spacingadd, chooseht,
- choosehtv, fm, tab,
- needMultiply, start, chdirs, dir, easy,
- end == bufend, includepad, trackpad,
- widths, start, end - start,
- where, ellipsizedWidth, w, paint);
- }
-
- start = end;
-
- if (end == bufend)
- break;
- }
-
- if (bufend == bufstart || source.charAt(bufend - 1) == '\n') {
- // Log.e("text", "output last " + bufend);
-
- paint.getFontMetricsInt(fm);
-
- v = out(source,
- bufend, bufend, fm.ascent, fm.descent,
- fm.top, fm.bottom,
- v,
- spacingmult, spacingadd, null,
- null, fm, false,
- needMultiply, bufend, chdirs, DEFAULT_DIR, true,
- true, includepad, trackpad,
- widths, bufstart, 0,
- where, ellipsizedWidth, 0, paint);
- }
- }
-
- private static final char FIRST_CJK = '\u2E80';
- /**
- * Returns true if the specified character is one of those specified
- * as being Ideographic (class ID) by the Unicode Line Breaking Algorithm
- * (http://www.unicode.org/unicode/reports/tr14/), and is therefore OK
- * to break between a pair of.
- */
- private static final boolean isIdeographic(char c) {
- if (c >= '\u2E80' && c <= '\u2FFF') {
- return true; // CJK, KANGXI RADICALS, DESCRIPTION SYMBOLS
- }
- if (c == '\u3000') {
- return true; // IDEOGRAPHIC SPACE
- }
- if (c >= '\u3040' && c <= '\u309F') {
- return true; // Hiragana (except small characters)
- }
- if (c >= '\u30A0' && c <= '\u30FF') {
- return true; // Katakana (except small characters)
- }
- if (c >= '\u3400' && c <= '\u4DB5') {
- return true; // CJK UNIFIED IDEOGRAPHS EXTENSION A
- }
- if (c >= '\u4E00' && c <= '\u9FBB') {
- return true; // CJK UNIFIED IDEOGRAPHS
- }
- if (c >= '\uF900' && c <= '\uFAD9') {
- return true; // CJK COMPATIBILITY IDEOGRAPHS
- }
- if (c >= '\uA000' && c <= '\uA48F') {
- return true; // YI SYLLABLES
- }
- if (c >= '\uA490' && c <= '\uA4CF') {
- return true; // YI RADICALS
- }
- if (c >= '\uFE62' && c <= '\uFE66') {
- return true; // SMALL PLUS SIGN to SMALL EQUALS SIGN
- }
- if (c >= '\uFF10' && c <= '\uFF19') {
- return true; // WIDE DIGITS
- }
-
- return false;
- }
-
-/*
- private static void dump(byte[] data, int count, String label) {
- if (false) {
- System.out.print(label);
-
- for (int i = 0; i < count; i++)
- System.out.print(" " + data[i]);
-
- System.out.println();
- }
- }
-*/
-
- private static int getFit(TextPaint paint,
- TextPaint workPaint,
- CharSequence text, int start, int end,
- float wid) {
- int high = end + 1, low = start - 1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
-
- if (measureText(paint, workPaint,
- text, start, guess, null, true, null) > wid)
- high = guess;
- else
- low = guess;
- }
-
- if (low < start)
- return start;
- else
- return low;
- }
-
- private int out(CharSequence text, int start, int end,
- int above, int below, int top, int bottom, int v,
- float spacingmult, float spacingadd,
- LineHeightSpan[] chooseht, int[] choosehtv,
- Paint.FontMetricsInt fm, boolean tab,
- boolean needMultiply, int pstart, byte[] chdirs,
- int dir, boolean easy, boolean last,
- boolean includepad, boolean trackpad,
- float[] widths, int widstart, int widoff,
- TextUtils.TruncateAt ellipsize, float ellipsiswidth,
- float textwidth, TextPaint paint) {
- int j = mLineCount;
- int off = j * mColumns;
- int want = off + mColumns + TOP;
- int[] lines = mLines;
-
- // Log.e("text", "line " + start + " to " + end + (last ? "===" : ""));
-
- if (want >= lines.length) {
- int nlen = ArrayUtils.idealIntArraySize(want + 1);
- int[] grow = new int[nlen];
- System.arraycopy(lines, 0, grow, 0, lines.length);
- mLines = grow;
- lines = grow;
-
- Directions[] grow2 = new Directions[nlen];
- System.arraycopy(mLineDirections, 0, grow2, 0,
- mLineDirections.length);
- mLineDirections = grow2;
- }
-
- if (chooseht != null) {
- fm.ascent = above;
- fm.descent = below;
- fm.top = top;
- fm.bottom = bottom;
-
- for (int i = 0; i < chooseht.length; i++) {
- chooseht[i].chooseHeight(text, start, end, choosehtv[i], v, fm);
- }
-
- above = fm.ascent;
- below = fm.descent;
- top = fm.top;
- bottom = fm.bottom;
- }
-
- if (j == 0) {
- if (trackpad) {
- mTopPadding = top - above;
- }
-
- if (includepad) {
- above = top;
- }
- }
- if (last) {
- if (trackpad) {
- mBottomPadding = bottom - below;
- }
-
- if (includepad) {
- below = bottom;
- }
- }
-
- int extra;
-
- if (needMultiply) {
- extra = (int) ((below - above) * (spacingmult - 1)
- + spacingadd + 0.5);
- } else {
- extra = 0;
- }
-
- lines[off + START] = start;
- lines[off + TOP] = v;
- lines[off + DESCENT] = below + extra;
-
- v += (below - above) + extra;
- lines[off + mColumns + START] = end;
- lines[off + mColumns + TOP] = v;
-
- if (tab)
- lines[off + TAB] |= TAB_MASK;
-
- {
- lines[off + DIR] |= dir << DIR_SHIFT;
-
- int cur = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
- int count = 0;
-
- if (!easy) {
- for (int k = start; k < end; k++) {
- if (chdirs[k - pstart] != cur) {
- count++;
- cur = chdirs[k - pstart];
- }
- }
- }
-
- Directions linedirs;
-
- if (count == 0) {
- linedirs = DIRS_ALL_LEFT_TO_RIGHT;
- } else {
- short[] ld = new short[count + 1];
-
- cur = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
- count = 0;
- int here = start;
-
- for (int k = start; k < end; k++) {
- if (chdirs[k - pstart] != cur) {
- // XXX check to make sure we don't
- // overflow short
- ld[count++] = (short) (k - here);
- cur = chdirs[k - pstart];
- here = k;
- }
- }
-
- ld[count] = (short) (end - here);
-
- if (count == 1 && ld[0] == 0) {
- linedirs = DIRS_ALL_RIGHT_TO_LEFT;
- } else {
- linedirs = new Directions(ld);
- }
- }
-
- mLineDirections[j] = linedirs;
-
- // If ellipsize is in marquee mode, do not apply ellipsis on the first line
- if (ellipsize != null && (ellipsize != TextUtils.TruncateAt.MARQUEE || j != 0)) {
- calculateEllipsis(start, end, widths, widstart, widoff,
- ellipsiswidth, ellipsize, j,
- textwidth, paint);
- }
- }
-
- mLineCount++;
- return v;
- }
-
- private void calculateEllipsis(int linestart, int lineend,
- float[] widths, int widstart, int widoff,
- float avail, TextUtils.TruncateAt where,
- int line, float textwidth, TextPaint paint) {
- int len = lineend - linestart;
-
- if (textwidth <= avail) {
- // Everything fits!
- mLines[mColumns * line + ELLIPSIS_START] = 0;
- mLines[mColumns * line + ELLIPSIS_COUNT] = 0;
- return;
- }
-
- float ellipsiswid = paint.measureText("\u2026");
- int ellipsisStart, ellipsisCount;
-
- if (where == TextUtils.TruncateAt.START) {
- float sum = 0;
- int i;
-
- for (i = len; i >= 0; i--) {
- float w = widths[i - 1 + linestart - widstart + widoff];
-
- if (w + sum + ellipsiswid > avail) {
- break;
- }
-
- sum += w;
- }
-
- ellipsisStart = 0;
- ellipsisCount = i;
- } else if (where == TextUtils.TruncateAt.END || where == TextUtils.TruncateAt.MARQUEE) {
- float sum = 0;
- int i;
-
- for (i = 0; i < len; i++) {
- float w = widths[i + linestart - widstart + widoff];
-
- if (w + sum + ellipsiswid > avail) {
- break;
- }
-
- sum += w;
- }
-
- ellipsisStart = i;
- ellipsisCount = len - i;
- } else /* where = TextUtils.TruncateAt.MIDDLE */ {
- float lsum = 0, rsum = 0;
- int left = 0, right = len;
-
- float ravail = (avail - ellipsiswid) / 2;
- for (right = len; right >= 0; right--) {
- float w = widths[right - 1 + linestart - widstart + widoff];
-
- if (w + rsum > ravail) {
- break;
- }
-
- rsum += w;
- }
-
- float lavail = avail - ellipsiswid - rsum;
- for (left = 0; left < right; left++) {
- float w = widths[left + linestart - widstart + widoff];
-
- if (w + lsum > lavail) {
- break;
- }
-
- lsum += w;
- }
-
- ellipsisStart = left;
- ellipsisCount = right - left;
- }
-
- mLines[mColumns * line + ELLIPSIS_START] = ellipsisStart;
- mLines[mColumns * line + ELLIPSIS_COUNT] = ellipsisCount;
- }
-
- // Override the baseclass so we can directly access our members,
- // rather than relying on member functions.
- // The logic mirrors that of Layout.getLineForVertical
- // FIXME: It may be faster to do a linear search for layouts without many lines.
- public int getLineForVertical(int vertical) {
- int high = mLineCount;
- int low = -1;
- int guess;
- int[] lines = mLines;
- while (high - low > 1) {
- guess = (high + low) >> 1;
- if (lines[mColumns * guess + TOP] > vertical){
- high = guess;
- } else {
- low = guess;
- }
- }
- if (low < 0) {
- return 0;
- } else {
- return low;
- }
- }
-
- public int getLineCount() {
- return mLineCount;
- }
-
- public int getLineTop(int line) {
- return mLines[mColumns * line + TOP];
- }
-
- public int getLineDescent(int line) {
- return mLines[mColumns * line + DESCENT];
- }
-
- public int getLineStart(int line) {
- return mLines[mColumns * line + START] & START_MASK;
- }
-
- public int getParagraphDirection(int line) {
- return mLines[mColumns * line + DIR] >> DIR_SHIFT;
- }
-
- public boolean getLineContainsTab(int line) {
- return (mLines[mColumns * line + TAB] & TAB_MASK) != 0;
- }
-
- public final Directions getLineDirections(int line) {
- return mLineDirections[line];
- }
-
- public int getTopPadding() {
- return mTopPadding;
- }
-
- public int getBottomPadding() {
- return mBottomPadding;
- }
-
- @Override
- public int getEllipsisCount(int line) {
- if (mColumns < COLUMNS_ELLIPSIZE) {
- return 0;
- }
-
- return mLines[mColumns * line + ELLIPSIS_COUNT];
- }
-
- @Override
- public int getEllipsisStart(int line) {
- if (mColumns < COLUMNS_ELLIPSIZE) {
- return 0;
- }
-
- return mLines[mColumns * line + ELLIPSIS_START];
- }
-
- @Override
- public int getEllipsizedWidth() {
- return mEllipsizedWidth;
- }
-
- private int mLineCount;
- private int mTopPadding, mBottomPadding;
- private int mColumns;
- private int mEllipsizedWidth;
-
- private static final int COLUMNS_NORMAL = 3;
- private static final int COLUMNS_ELLIPSIZE = 5;
- private static final int START = 0;
- private static final int DIR = START;
- private static final int TAB = START;
- private static final int TOP = 1;
- private static final int DESCENT = 2;
- private static final int ELLIPSIS_START = 3;
- private static final int ELLIPSIS_COUNT = 4;
-
- private int[] mLines;
- private Directions[] mLineDirections;
-
- private static final int START_MASK = 0x1FFFFFFF;
- private static final int DIR_MASK = 0xC0000000;
- private static final int DIR_SHIFT = 30;
- private static final int TAB_MASK = 0x20000000;
-
- private static final char FIRST_RIGHT_TO_LEFT = '\u0590';
-
- /*
- * These are reused across calls to generate()
- */
- private byte[] mChdirs;
- private char[] mChs;
- private float[] mWidths;
- private Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
-}
diff --git a/core/java/android/text/Styled.java b/core/java/android/text/Styled.java
deleted file mode 100644
index 05c27ea..0000000
--- a/core/java/android/text/Styled.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.graphics.Path;
-import android.graphics.RectF;
-import android.graphics.Typeface;
-import android.graphics.MaskFilter;
-import android.graphics.Rasterizer;
-import android.graphics.LayerRasterizer;
-import android.text.style.*;
-
-/* package */ class Styled
-{
- private static float each(Canvas canvas,
- Spanned text, int start, int end,
- int dir, boolean reverse,
- float x, int top, int y, int bottom,
- Paint.FontMetricsInt fm,
- TextPaint realPaint,
- TextPaint paint,
- boolean needwid) {
-
- boolean havewid = false;
- float ret = 0;
- CharacterStyle[] spans = text.getSpans(start, end, CharacterStyle.class);
-
- ReplacementSpan replacement = null;
-
- realPaint.bgColor = 0;
- realPaint.baselineShift = 0;
- paint.set(realPaint);
-
- if (spans.length > 0) {
- for (int i = 0; i < spans.length; i++) {
- CharacterStyle span = spans[i];
-
- if (span instanceof ReplacementSpan) {
- replacement = (ReplacementSpan)span;
- }
- else {
- span.updateDrawState(paint);
- }
- }
- }
-
- if (replacement == null) {
- CharSequence tmp;
- int tmpstart, tmpend;
-
- if (reverse) {
- tmp = TextUtils.getReverse(text, start, end);
- tmpstart = 0;
- tmpend = end - start;
- } else {
- tmp = text;
- tmpstart = start;
- tmpend = end;
- }
-
- if (fm != null) {
- paint.getFontMetricsInt(fm);
- }
-
- if (canvas != null) {
- if (paint.bgColor != 0) {
- int c = paint.getColor();
- Paint.Style s = paint.getStyle();
- paint.setColor(paint.bgColor);
- paint.setStyle(Paint.Style.FILL);
-
- if (!havewid) {
- ret = paint.measureText(tmp, tmpstart, tmpend);
- havewid = true;
- }
-
- if (dir == Layout.DIR_RIGHT_TO_LEFT)
- canvas.drawRect(x - ret, top, x, bottom, paint);
- else
- canvas.drawRect(x, top, x + ret, bottom, paint);
-
- paint.setStyle(s);
- paint.setColor(c);
- }
-
- if (dir == Layout.DIR_RIGHT_TO_LEFT) {
- if (!havewid) {
- ret = paint.measureText(tmp, tmpstart, tmpend);
- havewid = true;
- }
-
- canvas.drawText(tmp, tmpstart, tmpend,
- x - ret, y + paint.baselineShift, paint);
- } else {
- if (needwid) {
- if (!havewid) {
- ret = paint.measureText(tmp, tmpstart, tmpend);
- havewid = true;
- }
- }
-
- canvas.drawText(tmp, tmpstart, tmpend,
- x, y + paint.baselineShift, paint);
- }
- } else {
- if (needwid && !havewid) {
- ret = paint.measureText(tmp, tmpstart, tmpend);
- havewid = true;
- }
- }
- } else {
- ret = replacement.getSize(paint, text, start, end, fm);
-
- if (canvas != null) {
- if (dir == Layout.DIR_RIGHT_TO_LEFT)
- replacement.draw(canvas, text, start, end,
- x - ret, top, y, bottom, paint);
- else
- replacement.draw(canvas, text, start, end,
- x, top, y, bottom, paint);
- }
- }
-
- if (dir == Layout.DIR_RIGHT_TO_LEFT)
- return -ret;
- else
- return ret;
- }
-
- public static int getTextWidths(TextPaint realPaint,
- TextPaint paint,
- Spanned text, int start, int end,
- float[] widths, Paint.FontMetricsInt fm) {
-
- MetricAffectingSpan[] spans = text.getSpans(start, end, MetricAffectingSpan.class);
-
- ReplacementSpan replacement = null;
- paint.set(realPaint);
-
- for (int i = 0; i < spans.length; i++) {
- MetricAffectingSpan span = spans[i];
- if (span instanceof ReplacementSpan) {
- replacement = (ReplacementSpan)span;
- }
- else {
- span.updateMeasureState(paint);
- }
- }
-
- if (replacement == null) {
- paint.getFontMetricsInt(fm);
- paint.getTextWidths(text, start, end, widths);
- } else {
- int wid = replacement.getSize(paint, text, start, end, fm);
-
- if (end > start) {
- widths[0] = wid;
-
- for (int i = start + 1; i < end; i++)
- widths[i - start] = 0;
- }
- }
- return end - start;
- }
-
- private static float foreach(Canvas canvas,
- CharSequence text, int start, int end,
- int dir, boolean reverse,
- float x, int top, int y, int bottom,
- Paint.FontMetricsInt fm,
- TextPaint paint,
- TextPaint workPaint,
- boolean needwid) {
- if (! (text instanceof Spanned)) {
- float ret = 0;
-
- if (reverse) {
- CharSequence tmp = TextUtils.getReverse(text, start, end);
- int tmpend = end - start;
-
- if (canvas != null || needwid)
- ret = paint.measureText(tmp, 0, tmpend);
-
- if (canvas != null)
- canvas.drawText(tmp, 0, tmpend,
- x - ret, y, paint);
- } else {
- if (needwid)
- ret = paint.measureText(text, start, end);
-
- if (canvas != null)
- canvas.drawText(text, start, end, x, y, paint);
- }
-
- if (fm != null) {
- paint.getFontMetricsInt(fm);
- }
-
- return ret * dir; //Layout.DIR_RIGHT_TO_LEFT == -1
- }
-
- float ox = x;
- int asc = 0, desc = 0;
- int ftop = 0, fbot = 0;
-
- Spanned sp = (Spanned) text;
- Class division;
-
- if (canvas == null)
- division = MetricAffectingSpan.class;
- else
- division = CharacterStyle.class;
-
- int next;
- for (int i = start; i < end; i = next) {
- next = sp.nextSpanTransition(i, end, division);
-
- x += each(canvas, sp, i, next, dir, reverse,
- x, top, y, bottom, fm, paint, workPaint,
- needwid || next != end);
-
- if (fm != null) {
- if (fm.ascent < asc)
- asc = fm.ascent;
- if (fm.descent > desc)
- desc = fm.descent;
-
- if (fm.top < ftop)
- ftop = fm.top;
- if (fm.bottom > fbot)
- fbot = fm.bottom;
- }
- }
-
- if (fm != null) {
- if (start == end) {
- paint.getFontMetricsInt(fm);
- } else {
- fm.ascent = asc;
- fm.descent = desc;
- fm.top = ftop;
- fm.bottom = fbot;
- }
- }
-
- return x - ox;
- }
-
- public static float drawText(Canvas canvas,
- CharSequence text, int start, int end,
- int dir, boolean reverse,
- float x, int top, int y, int bottom,
- TextPaint paint,
- TextPaint workPaint,
- boolean needwid) {
- if ((dir == Layout.DIR_RIGHT_TO_LEFT && !reverse)||(reverse && dir == Layout.DIR_LEFT_TO_RIGHT)) {
- float ch = foreach(null, text, start, end, Layout.DIR_LEFT_TO_RIGHT,
- false, 0, 0, 0, 0, null, paint, workPaint,
- true);
-
- ch *= dir; // DIR_RIGHT_TO_LEFT == -1
- foreach(canvas, text, start, end, -dir,
- reverse, x + ch, top, y, bottom, null, paint,
- workPaint, true);
-
- return ch;
- }
-
- return foreach(canvas, text, start, end, dir, reverse,
- x, top, y, bottom, null, paint, workPaint,
- needwid);
- }
-
- public static float measureText(TextPaint paint,
- TextPaint workPaint,
- CharSequence text, int start, int end,
- Paint.FontMetricsInt fm) {
- return foreach(null, text, start, end,
- Layout.DIR_LEFT_TO_RIGHT, false,
- 0, 0, 0, 0, fm, paint, workPaint, true);
- }
-}
diff --git a/core/java/android/text/TextPaint.java b/core/java/android/text/TextPaint.java
deleted file mode 100644
index f13820d..0000000
--- a/core/java/android/text/TextPaint.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import android.graphics.Paint;
-
-/**
- * TextPaint is an extension of Paint that leaves room for some extra
- * data used during text measuring and drawing.
- */
-public class TextPaint extends Paint {
- public int bgColor;
- public int baselineShift;
- public int linkColor;
- public int[] drawableState;
-
- public TextPaint() {
- super();
- }
-
- public TextPaint(int flags) {
- super(flags);
- }
-
- public TextPaint(Paint p) {
- super(p);
- }
-
- /**
- * Copy the fields from tp into this TextPaint, including the
- * fields inherited from Paint.
- */
- public void set(TextPaint tp) {
- super.set(tp);
-
- bgColor = tp.bgColor;
- baselineShift = tp.baselineShift;
- linkColor = tp.linkColor;
- drawableState = tp.drawableState;
- }
-}
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
deleted file mode 100644
index 5b4c380..0000000
--- a/core/java/android/text/TextUtils.java
+++ /dev/null
@@ -1,1620 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import com.android.internal.R;
-
-import android.content.res.ColorStateList;
-import android.content.res.Resources;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.method.TextKeyListener.Capitalize;
-import android.text.style.AbsoluteSizeSpan;
-import android.text.style.AlignmentSpan;
-import android.text.style.BackgroundColorSpan;
-import android.text.style.BulletSpan;
-import android.text.style.CharacterStyle;
-import android.text.style.ForegroundColorSpan;
-import android.text.style.LeadingMarginSpan;
-import android.text.style.MetricAffectingSpan;
-import android.text.style.QuoteSpan;
-import android.text.style.RelativeSizeSpan;
-import android.text.style.ReplacementSpan;
-import android.text.style.ScaleXSpan;
-import android.text.style.StrikethroughSpan;
-import android.text.style.StyleSpan;
-import android.text.style.SubscriptSpan;
-import android.text.style.SuperscriptSpan;
-import android.text.style.TextAppearanceSpan;
-import android.text.style.TypefaceSpan;
-import android.text.style.URLSpan;
-import android.text.style.UnderlineSpan;
-import android.util.Printer;
-
-import com.android.internal.util.ArrayUtils;
-
-import java.util.regex.Pattern;
-import java.util.Iterator;
-
-public class TextUtils {
- private TextUtils() { /* cannot be instantiated */ }
-
- private static String[] EMPTY_STRING_ARRAY = new String[]{};
-
- public static void getChars(CharSequence s, int start, int end,
- char[] dest, int destoff) {
- Class c = s.getClass();
-
- if (c == String.class)
- ((String) s).getChars(start, end, dest, destoff);
- else if (c == StringBuffer.class)
- ((StringBuffer) s).getChars(start, end, dest, destoff);
- else if (c == StringBuilder.class)
- ((StringBuilder) s).getChars(start, end, dest, destoff);
- else if (s instanceof GetChars)
- ((GetChars) s).getChars(start, end, dest, destoff);
- else {
- for (int i = start; i < end; i++)
- dest[destoff++] = s.charAt(i);
- }
- }
-
- public static int indexOf(CharSequence s, char ch) {
- return indexOf(s, ch, 0);
- }
-
- public static int indexOf(CharSequence s, char ch, int start) {
- Class c = s.getClass();
-
- if (c == String.class)
- return ((String) s).indexOf(ch, start);
-
- return indexOf(s, ch, start, s.length());
- }
-
- public static int indexOf(CharSequence s, char ch, int start, int end) {
- Class c = s.getClass();
-
- if (s instanceof GetChars || c == StringBuffer.class ||
- c == StringBuilder.class || c == String.class) {
- final int INDEX_INCREMENT = 500;
- char[] temp = obtain(INDEX_INCREMENT);
-
- while (start < end) {
- int segend = start + INDEX_INCREMENT;
- if (segend > end)
- segend = end;
-
- getChars(s, start, segend, temp, 0);
-
- int count = segend - start;
- for (int i = 0; i < count; i++) {
- if (temp[i] == ch) {
- recycle(temp);
- return i + start;
- }
- }
-
- start = segend;
- }
-
- recycle(temp);
- return -1;
- }
-
- for (int i = start; i < end; i++)
- if (s.charAt(i) == ch)
- return i;
-
- return -1;
- }
-
- public static int lastIndexOf(CharSequence s, char ch) {
- return lastIndexOf(s, ch, s.length() - 1);
- }
-
- public static int lastIndexOf(CharSequence s, char ch, int last) {
- Class c = s.getClass();
-
- if (c == String.class)
- return ((String) s).lastIndexOf(ch, last);
-
- return lastIndexOf(s, ch, 0, last);
- }
-
- public static int lastIndexOf(CharSequence s, char ch,
- int start, int last) {
- if (last < 0)
- return -1;
- if (last >= s.length())
- last = s.length() - 1;
-
- int end = last + 1;
-
- Class c = s.getClass();
-
- if (s instanceof GetChars || c == StringBuffer.class ||
- c == StringBuilder.class || c == String.class) {
- final int INDEX_INCREMENT = 500;
- char[] temp = obtain(INDEX_INCREMENT);
-
- while (start < end) {
- int segstart = end - INDEX_INCREMENT;
- if (segstart < start)
- segstart = start;
-
- getChars(s, segstart, end, temp, 0);
-
- int count = end - segstart;
- for (int i = count - 1; i >= 0; i--) {
- if (temp[i] == ch) {
- recycle(temp);
- return i + segstart;
- }
- }
-
- end = segstart;
- }
-
- recycle(temp);
- return -1;
- }
-
- for (int i = end - 1; i >= start; i--)
- if (s.charAt(i) == ch)
- return i;
-
- return -1;
- }
-
- public static int indexOf(CharSequence s, CharSequence needle) {
- return indexOf(s, needle, 0, s.length());
- }
-
- public static int indexOf(CharSequence s, CharSequence needle, int start) {
- return indexOf(s, needle, start, s.length());
- }
-
- public static int indexOf(CharSequence s, CharSequence needle,
- int start, int end) {
- int nlen = needle.length();
- if (nlen == 0)
- return start;
-
- char c = needle.charAt(0);
-
- for (;;) {
- start = indexOf(s, c, start);
- if (start > end - nlen) {
- break;
- }
-
- if (start < 0) {
- return -1;
- }
-
- if (regionMatches(s, start, needle, 0, nlen)) {
- return start;
- }
-
- start++;
- }
- return -1;
- }
-
- public static boolean regionMatches(CharSequence one, int toffset,
- CharSequence two, int ooffset,
- int len) {
- char[] temp = obtain(2 * len);
-
- getChars(one, toffset, toffset + len, temp, 0);
- getChars(two, ooffset, ooffset + len, temp, len);
-
- boolean match = true;
- for (int i = 0; i < len; i++) {
- if (temp[i] != temp[i + len]) {
- match = false;
- break;
- }
- }
-
- recycle(temp);
- return match;
- }
-
- /**
- * Create a new String object containing the given range of characters
- * from the source string. This is different than simply calling
- * {@link CharSequence#subSequence(int, int) CharSequence.subSequence}
- * in that it does not preserve any style runs in the source sequence,
- * allowing a more efficient implementation.
- */
- public static String substring(CharSequence source, int start, int end) {
- if (source instanceof String)
- return ((String) source).substring(start, end);
- if (source instanceof StringBuilder)
- return ((StringBuilder) source).substring(start, end);
- if (source instanceof StringBuffer)
- return ((StringBuffer) source).substring(start, end);
-
- char[] temp = obtain(end - start);
- getChars(source, start, end, temp, 0);
- String ret = new String(temp, 0, end - start);
- recycle(temp);
-
- return ret;
- }
-
- /**
- * Returns a string containing the tokens joined by delimiters.
- * @param tokens an array objects to be joined. Strings will be formed from
- * the objects by calling object.toString().
- */
- public static String join(CharSequence delimiter, Object[] tokens) {
- StringBuilder sb = new StringBuilder();
- boolean firstTime = true;
- for (Object token: tokens) {
- if (firstTime) {
- firstTime = false;
- } else {
- sb.append(delimiter);
- }
- sb.append(token);
- }
- return sb.toString();
- }
-
- /**
- * Returns a string containing the tokens joined by delimiters.
- * @param tokens an array objects to be joined. Strings will be formed from
- * the objects by calling object.toString().
- */
- public static String join(CharSequence delimiter, Iterable tokens) {
- StringBuilder sb = new StringBuilder();
- boolean firstTime = true;
- for (Object token: tokens) {
- if (firstTime) {
- firstTime = false;
- } else {
- sb.append(delimiter);
- }
- sb.append(token);
- }
- return sb.toString();
- }
-
- /**
- * String.split() returns [''] when the string to be split is empty. This returns []. This does
- * not remove any empty strings from the result. For example split("a,", "," ) returns {"a", ""}.
- *
- * @param text the string to split
- * @param expression the regular expression to match
- * @return an array of strings. The array will be empty if text is empty
- *
- * @throws NullPointerException if expression or text is null
- */
- public static String[] split(String text, String expression) {
- if (text.length() == 0) {
- return EMPTY_STRING_ARRAY;
- } else {
- return text.split(expression, -1);
- }
- }
-
- /**
- * Splits a string on a pattern. String.split() returns [''] when the string to be
- * split is empty. This returns []. This does not remove any empty strings from the result.
- * @param text the string to split
- * @param pattern the regular expression to match
- * @return an array of strings. The array will be empty if text is empty
- *
- * @throws NullPointerException if expression or text is null
- */
- public static String[] split(String text, Pattern pattern) {
- if (text.length() == 0) {
- return EMPTY_STRING_ARRAY;
- } else {
- return pattern.split(text, -1);
- }
- }
-
- /**
- * An interface for splitting strings according to rules that are opaque to the user of this
- * interface. This also has less overhead than split, which uses regular expressions and
- * allocates an array to hold the results.
- *
- * <p>The most efficient way to use this class is:
- *
- * <pre>
- * // Once
- * TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(delimiter);
- *
- * // Once per string to split
- * splitter.setString(string);
- * for (String s : splitter) {
- * ...
- * }
- * </pre>
- */
- public interface StringSplitter extends Iterable<String> {
- public void setString(String string);
- }
-
- /**
- * A simple string splitter.
- *
- * <p>If the final character in the string to split is the delimiter then no empty string will
- * be returned for the empty string after that delimeter. That is, splitting <tt>"a,b,"</tt> on
- * comma will return <tt>"a", "b"</tt>, not <tt>"a", "b", ""</tt>.
- */
- public static class SimpleStringSplitter implements StringSplitter, Iterator<String> {
- private String mString;
- private char mDelimiter;
- private int mPosition;
- private int mLength;
-
- /**
- * Initializes the splitter. setString may be called later.
- * @param delimiter the delimeter on which to split
- */
- public SimpleStringSplitter(char delimiter) {
- mDelimiter = delimiter;
- }
-
- /**
- * Sets the string to split
- * @param string the string to split
- */
- public void setString(String string) {
- mString = string;
- mPosition = 0;
- mLength = mString.length();
- }
-
- public Iterator<String> iterator() {
- return this;
- }
-
- public boolean hasNext() {
- return mPosition < mLength;
- }
-
- public String next() {
- int end = mString.indexOf(mDelimiter, mPosition);
- if (end == -1) {
- end = mLength;
- }
- String nextString = mString.substring(mPosition, end);
- mPosition = end + 1; // Skip the delimiter.
- return nextString;
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-
- public static CharSequence stringOrSpannedString(CharSequence source) {
- if (source == null)
- return null;
- if (source instanceof SpannedString)
- return source;
- if (source instanceof Spanned)
- return new SpannedString(source);
-
- return source.toString();
- }
-
- /**
- * Returns true if the string is null or 0-length.
- * @param str the string to be examined
- * @return true if str is null or zero length
- */
- public static boolean isEmpty(CharSequence str) {
- if (str == null || str.length() == 0)
- return true;
- else
- return false;
- }
-
- /**
- * Returns the length that the specified CharSequence would have if
- * spaces and control characters were trimmed from the start and end,
- * as by {@link String#trim}.
- */
- public static int getTrimmedLength(CharSequence s) {
- int len = s.length();
-
- int start = 0;
- while (start < len && s.charAt(start) <= ' ') {
- start++;
- }
-
- int end = len;
- while (end > start && s.charAt(end - 1) <= ' ') {
- end--;
- }
-
- return end - start;
- }
-
- /**
- * Returns true if a and b are equal, including if they are both null.
- * <p><i>Note: In platform versions 1.1 and earlier, this method only worked well if
- * both the arguments were instances of String.</i></p>
- * @param a first CharSequence to check
- * @param b second CharSequence to check
- * @return true if a and b are equal
- */
- public static boolean equals(CharSequence a, CharSequence b) {
- if (a == b) return true;
- int length;
- if (a != null && b != null && (length = a.length()) == b.length()) {
- if (a instanceof String && b instanceof String) {
- return a.equals(b);
- } else {
- for (int i = 0; i < length; i++) {
- if (a.charAt(i) != b.charAt(i)) return false;
- }
- return true;
- }
- }
- return false;
- }
-
- // XXX currently this only reverses chars, not spans
- public static CharSequence getReverse(CharSequence source,
- int start, int end) {
- return new Reverser(source, start, end);
- }
-
- private static class Reverser
- implements CharSequence, GetChars
- {
- public Reverser(CharSequence source, int start, int end) {
- mSource = source;
- mStart = start;
- mEnd = end;
- }
-
- public int length() {
- return mEnd - mStart;
- }
-
- public CharSequence subSequence(int start, int end) {
- char[] buf = new char[end - start];
-
- getChars(start, end, buf, 0);
- return new String(buf);
- }
-
- public String toString() {
- return subSequence(0, length()).toString();
- }
-
- public char charAt(int off) {
- return AndroidCharacter.getMirror(mSource.charAt(mEnd - 1 - off));
- }
-
- public void getChars(int start, int end, char[] dest, int destoff) {
- TextUtils.getChars(mSource, start + mStart, end + mStart,
- dest, destoff);
- AndroidCharacter.mirror(dest, 0, end - start);
-
- int len = end - start;
- int n = (end - start) / 2;
- for (int i = 0; i < n; i++) {
- char tmp = dest[destoff + i];
-
- dest[destoff + i] = dest[destoff + len - i - 1];
- dest[destoff + len - i - 1] = tmp;
- }
- }
-
- private CharSequence mSource;
- private int mStart;
- private int mEnd;
- }
-
- /** @hide */
- public static final int ALIGNMENT_SPAN = 1;
- /** @hide */
- public static final int FOREGROUND_COLOR_SPAN = 2;
- /** @hide */
- public static final int RELATIVE_SIZE_SPAN = 3;
- /** @hide */
- public static final int SCALE_X_SPAN = 4;
- /** @hide */
- public static final int STRIKETHROUGH_SPAN = 5;
- /** @hide */
- public static final int UNDERLINE_SPAN = 6;
- /** @hide */
- public static final int STYLE_SPAN = 7;
- /** @hide */
- public static final int BULLET_SPAN = 8;
- /** @hide */
- public static final int QUOTE_SPAN = 9;
- /** @hide */
- public static final int LEADING_MARGIN_SPAN = 10;
- /** @hide */
- public static final int URL_SPAN = 11;
- /** @hide */
- public static final int BACKGROUND_COLOR_SPAN = 12;
- /** @hide */
- public static final int TYPEFACE_SPAN = 13;
- /** @hide */
- public static final int SUPERSCRIPT_SPAN = 14;
- /** @hide */
- public static final int SUBSCRIPT_SPAN = 15;
- /** @hide */
- public static final int ABSOLUTE_SIZE_SPAN = 16;
- /** @hide */
- public static final int TEXT_APPEARANCE_SPAN = 17;
- /** @hide */
- public static final int ANNOTATION = 18;
-
- /**
- * Flatten a CharSequence and whatever styles can be copied across processes
- * into the parcel.
- */
- public static void writeToParcel(CharSequence cs, Parcel p,
- int parcelableFlags) {
- if (cs instanceof Spanned) {
- p.writeInt(0);
- p.writeString(cs.toString());
-
- Spanned sp = (Spanned) cs;
- Object[] os = sp.getSpans(0, cs.length(), Object.class);
-
- // note to people adding to this: check more specific types
- // before more generic types. also notice that it uses
- // "if" instead of "else if" where there are interfaces
- // so one object can be several.
-
- for (int i = 0; i < os.length; i++) {
- Object o = os[i];
- Object prop = os[i];
-
- if (prop instanceof CharacterStyle) {
- prop = ((CharacterStyle) prop).getUnderlying();
- }
-
- if (prop instanceof ParcelableSpan) {
- ParcelableSpan ps = (ParcelableSpan)prop;
- p.writeInt(ps.getSpanTypeId());
- ps.writeToParcel(p, parcelableFlags);
- writeWhere(p, sp, o);
- }
- }
-
- p.writeInt(0);
- } else {
- p.writeInt(1);
- if (cs != null) {
- p.writeString(cs.toString());
- } else {
- p.writeString(null);
- }
- }
- }
-
- private static void writeWhere(Parcel p, Spanned sp, Object o) {
- p.writeInt(sp.getSpanStart(o));
- p.writeInt(sp.getSpanEnd(o));
- p.writeInt(sp.getSpanFlags(o));
- }
-
- public static final Parcelable.Creator<CharSequence> CHAR_SEQUENCE_CREATOR
- = new Parcelable.Creator<CharSequence>() {
- /**
- * Read and return a new CharSequence, possibly with styles,
- * from the parcel.
- */
- public CharSequence createFromParcel(Parcel p) {
- int kind = p.readInt();
-
- if (kind == 1)
- return p.readString();
-
- SpannableString sp = new SpannableString(p.readString());
-
- while (true) {
- kind = p.readInt();
-
- if (kind == 0)
- break;
-
- switch (kind) {
- case ALIGNMENT_SPAN:
- readSpan(p, sp, new AlignmentSpan.Standard(p));
- break;
-
- case FOREGROUND_COLOR_SPAN:
- readSpan(p, sp, new ForegroundColorSpan(p));
- break;
-
- case RELATIVE_SIZE_SPAN:
- readSpan(p, sp, new RelativeSizeSpan(p));
- break;
-
- case SCALE_X_SPAN:
- readSpan(p, sp, new ScaleXSpan(p));
- break;
-
- case STRIKETHROUGH_SPAN:
- readSpan(p, sp, new StrikethroughSpan(p));
- break;
-
- case UNDERLINE_SPAN:
- readSpan(p, sp, new UnderlineSpan(p));
- break;
-
- case STYLE_SPAN:
- readSpan(p, sp, new StyleSpan(p));
- break;
-
- case BULLET_SPAN:
- readSpan(p, sp, new BulletSpan(p));
- break;
-
- case QUOTE_SPAN:
- readSpan(p, sp, new QuoteSpan(p));
- break;
-
- case LEADING_MARGIN_SPAN:
- readSpan(p, sp, new LeadingMarginSpan.Standard(p));
- break;
-
- case URL_SPAN:
- readSpan(p, sp, new URLSpan(p));
- break;
-
- case BACKGROUND_COLOR_SPAN:
- readSpan(p, sp, new BackgroundColorSpan(p));
- break;
-
- case TYPEFACE_SPAN:
- readSpan(p, sp, new TypefaceSpan(p));
- break;
-
- case SUPERSCRIPT_SPAN:
- readSpan(p, sp, new SuperscriptSpan(p));
- break;
-
- case SUBSCRIPT_SPAN:
- readSpan(p, sp, new SubscriptSpan(p));
- break;
-
- case ABSOLUTE_SIZE_SPAN:
- readSpan(p, sp, new AbsoluteSizeSpan(p));
- break;
-
- case TEXT_APPEARANCE_SPAN:
- readSpan(p, sp, new TextAppearanceSpan(p));
- break;
-
- case ANNOTATION:
- readSpan(p, sp, new Annotation(p));
- break;
-
- default:
- throw new RuntimeException("bogus span encoding " + kind);
- }
- }
-
- return sp;
- }
-
- public CharSequence[] newArray(int size)
- {
- return new CharSequence[size];
- }
- };
-
- /**
- * Debugging tool to print the spans in a CharSequence. The output will
- * be printed one span per line. If the CharSequence is not a Spanned,
- * then the entire string will be printed on a single line.
- */
- public static void dumpSpans(CharSequence cs, Printer printer, String prefix) {
- if (cs instanceof Spanned) {
- Spanned sp = (Spanned) cs;
- Object[] os = sp.getSpans(0, cs.length(), Object.class);
-
- for (int i = 0; i < os.length; i++) {
- Object o = os[i];
- printer.println(prefix + cs.subSequence(sp.getSpanStart(o),
- sp.getSpanEnd(o)) + ": "
- + Integer.toHexString(System.identityHashCode(o))
- + " " + o.getClass().getCanonicalName()
- + " (" + sp.getSpanStart(o) + "-" + sp.getSpanEnd(o)
- + ") fl=#" + sp.getSpanFlags(o));
- }
- } else {
- printer.println(prefix + cs + ": (no spans)");
- }
- }
-
- /**
- * Return a new CharSequence in which each of the source strings is
- * replaced by the corresponding element of the destinations.
- */
- public static CharSequence replace(CharSequence template,
- String[] sources,
- CharSequence[] destinations) {
- SpannableStringBuilder tb = new SpannableStringBuilder(template);
-
- for (int i = 0; i < sources.length; i++) {
- int where = indexOf(tb, sources[i]);
-
- if (where >= 0)
- tb.setSpan(sources[i], where, where + sources[i].length(),
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
- for (int i = 0; i < sources.length; i++) {
- int start = tb.getSpanStart(sources[i]);
- int end = tb.getSpanEnd(sources[i]);
-
- if (start >= 0) {
- tb.replace(start, end, destinations[i]);
- }
- }
-
- return tb;
- }
-
- /**
- * Replace instances of "^1", "^2", etc. in the
- * <code>template</code> CharSequence with the corresponding
- * <code>values</code>. "^^" is used to produce a single caret in
- * the output. Only up to 9 replacement values are supported,
- * "^10" will be produce the first replacement value followed by a
- * '0'.
- *
- * @param template the input text containing "^1"-style
- * placeholder values. This object is not modified; a copy is
- * returned.
- *
- * @param values CharSequences substituted into the template. The
- * first is substituted for "^1", the second for "^2", and so on.
- *
- * @return the new CharSequence produced by doing the replacement
- *
- * @throws IllegalArgumentException if the template requests a
- * value that was not provided, or if more than 9 values are
- * provided.
- */
- public static CharSequence expandTemplate(CharSequence template,
- CharSequence... values) {
- if (values.length > 9) {
- throw new IllegalArgumentException("max of 9 values are supported");
- }
-
- SpannableStringBuilder ssb = new SpannableStringBuilder(template);
-
- try {
- int i = 0;
- while (i < ssb.length()) {
- if (ssb.charAt(i) == '^') {
- char next = ssb.charAt(i+1);
- if (next == '^') {
- ssb.delete(i+1, i+2);
- ++i;
- continue;
- } else if (Character.isDigit(next)) {
- int which = Character.getNumericValue(next) - 1;
- if (which < 0) {
- throw new IllegalArgumentException(
- "template requests value ^" + (which+1));
- }
- if (which >= values.length) {
- throw new IllegalArgumentException(
- "template requests value ^" + (which+1) +
- "; only " + values.length + " provided");
- }
- ssb.replace(i, i+2, values[which]);
- i += values[which].length();
- continue;
- }
- }
- ++i;
- }
- } catch (IndexOutOfBoundsException ignore) {
- // happens when ^ is the last character in the string.
- }
- return ssb;
- }
-
- public static int getOffsetBefore(CharSequence text, int offset) {
- if (offset == 0)
- return 0;
- if (offset == 1)
- return 0;
-
- char c = text.charAt(offset - 1);
-
- if (c >= '\uDC00' && c <= '\uDFFF') {
- char c1 = text.charAt(offset - 2);
-
- if (c1 >= '\uD800' && c1 <= '\uDBFF')
- offset -= 2;
- else
- offset -= 1;
- } else {
- offset -= 1;
- }
-
- if (text instanceof Spanned) {
- ReplacementSpan[] spans = ((Spanned) text).getSpans(offset, offset,
- ReplacementSpan.class);
-
- for (int i = 0; i < spans.length; i++) {
- int start = ((Spanned) text).getSpanStart(spans[i]);
- int end = ((Spanned) text).getSpanEnd(spans[i]);
-
- if (start < offset && end > offset)
- offset = start;
- }
- }
-
- return offset;
- }
-
- public static int getOffsetAfter(CharSequence text, int offset) {
- int len = text.length();
-
- if (offset == len)
- return len;
- if (offset == len - 1)
- return len;
-
- char c = text.charAt(offset);
-
- if (c >= '\uD800' && c <= '\uDBFF') {
- char c1 = text.charAt(offset + 1);
-
- if (c1 >= '\uDC00' && c1 <= '\uDFFF')
- offset += 2;
- else
- offset += 1;
- } else {
- offset += 1;
- }
-
- if (text instanceof Spanned) {
- ReplacementSpan[] spans = ((Spanned) text).getSpans(offset, offset,
- ReplacementSpan.class);
-
- for (int i = 0; i < spans.length; i++) {
- int start = ((Spanned) text).getSpanStart(spans[i]);
- int end = ((Spanned) text).getSpanEnd(spans[i]);
-
- if (start < offset && end > offset)
- offset = end;
- }
- }
-
- return offset;
- }
-
- private static void readSpan(Parcel p, Spannable sp, Object o) {
- sp.setSpan(o, p.readInt(), p.readInt(), p.readInt());
- }
-
- public static void copySpansFrom(Spanned source, int start, int end,
- Class kind,
- Spannable dest, int destoff) {
- if (kind == null) {
- kind = Object.class;
- }
-
- Object[] spans = source.getSpans(start, end, kind);
-
- for (int i = 0; i < spans.length; i++) {
- int st = source.getSpanStart(spans[i]);
- int en = source.getSpanEnd(spans[i]);
- int fl = source.getSpanFlags(spans[i]);
-
- if (st < start)
- st = start;
- if (en > end)
- en = end;
-
- dest.setSpan(spans[i], st - start + destoff, en - start + destoff,
- fl);
- }
- }
-
- public enum TruncateAt {
- START,
- MIDDLE,
- END,
- MARQUEE,
- }
-
- public interface EllipsizeCallback {
- /**
- * This method is called to report that the specified region of
- * text was ellipsized away by a call to {@link #ellipsize}.
- */
- public void ellipsized(int start, int end);
- }
-
- private static String sEllipsis = null;
-
- /**
- * Returns the original text if it fits in the specified width
- * given the properties of the specified Paint,
- * or, if it does not fit, a truncated
- * copy with ellipsis character added at the specified edge or center.
- */
- public static CharSequence ellipsize(CharSequence text,
- TextPaint p,
- float avail, TruncateAt where) {
- return ellipsize(text, p, avail, where, false, null);
- }
-
- /**
- * Returns the original text if it fits in the specified width
- * given the properties of the specified Paint,
- * or, if it does not fit, a copy with ellipsis character added
- * at the specified edge or center.
- * If <code>preserveLength</code> is specified, the returned copy
- * will be padded with zero-width spaces to preserve the original
- * length and offsets instead of truncating.
- * If <code>callback</code> is non-null, it will be called to
- * report the start and end of the ellipsized range.
- */
- public static CharSequence ellipsize(CharSequence text,
- TextPaint p,
- float avail, TruncateAt where,
- boolean preserveLength,
- EllipsizeCallback callback) {
- if (sEllipsis == null) {
- Resources r = Resources.getSystem();
- sEllipsis = r.getString(R.string.ellipsis);
- }
-
- int len = text.length();
-
- // Use Paint.breakText() for the non-Spanned case to avoid having
- // to allocate memory and accumulate the character widths ourselves.
-
- if (!(text instanceof Spanned)) {
- float wid = p.measureText(text, 0, len);
-
- if (wid <= avail) {
- if (callback != null) {
- callback.ellipsized(0, 0);
- }
-
- return text;
- }
-
- float ellipsiswid = p.measureText(sEllipsis);
-
- if (ellipsiswid > avail) {
- if (callback != null) {
- callback.ellipsized(0, len);
- }
-
- if (preserveLength) {
- char[] buf = obtain(len);
- for (int i = 0; i < len; i++) {
- buf[i] = '\uFEFF';
- }
- String ret = new String(buf, 0, len);
- recycle(buf);
- return ret;
- } else {
- return "";
- }
- }
-
- if (where == TruncateAt.START) {
- int fit = p.breakText(text, 0, len, false,
- avail - ellipsiswid, null);
-
- if (callback != null) {
- callback.ellipsized(0, len - fit);
- }
-
- if (preserveLength) {
- return blank(text, 0, len - fit);
- } else {
- return sEllipsis + text.toString().substring(len - fit, len);
- }
- } else if (where == TruncateAt.END) {
- int fit = p.breakText(text, 0, len, true,
- avail - ellipsiswid, null);
-
- if (callback != null) {
- callback.ellipsized(fit, len);
- }
-
- if (preserveLength) {
- return blank(text, fit, len);
- } else {
- return text.toString().substring(0, fit) + sEllipsis;
- }
- } else /* where == TruncateAt.MIDDLE */ {
- int right = p.breakText(text, 0, len, false,
- (avail - ellipsiswid) / 2, null);
- float used = p.measureText(text, len - right, len);
- int left = p.breakText(text, 0, len - right, true,
- avail - ellipsiswid - used, null);
-
- if (callback != null) {
- callback.ellipsized(left, len - right);
- }
-
- if (preserveLength) {
- return blank(text, left, len - right);
- } else {
- String s = text.toString();
- return s.substring(0, left) + sEllipsis +
- s.substring(len - right, len);
- }
- }
- }
-
- // But do the Spanned cases by hand, because it's such a pain
- // to iterate the span transitions backwards and getTextWidths()
- // will give us the information we need.
-
- // getTextWidths() always writes into the start of the array,
- // so measure each span into the first half and then copy the
- // results into the second half to use later.
-
- float[] wid = new float[len * 2];
- TextPaint temppaint = new TextPaint();
- Spanned sp = (Spanned) text;
-
- int next;
- for (int i = 0; i < len; i = next) {
- next = sp.nextSpanTransition(i, len, MetricAffectingSpan.class);
-
- Styled.getTextWidths(p, temppaint, sp, i, next, wid, null);
- System.arraycopy(wid, 0, wid, len + i, next - i);
- }
-
- float sum = 0;
- for (int i = 0; i < len; i++) {
- sum += wid[len + i];
- }
-
- if (sum <= avail) {
- if (callback != null) {
- callback.ellipsized(0, 0);
- }
-
- return text;
- }
-
- float ellipsiswid = p.measureText(sEllipsis);
-
- if (ellipsiswid > avail) {
- if (callback != null) {
- callback.ellipsized(0, len);
- }
-
- if (preserveLength) {
- char[] buf = obtain(len);
- for (int i = 0; i < len; i++) {
- buf[i] = '\uFEFF';
- }
- SpannableString ss = new SpannableString(new String(buf, 0, len));
- recycle(buf);
- copySpansFrom(sp, 0, len, Object.class, ss, 0);
- return ss;
- } else {
- return "";
- }
- }
-
- if (where == TruncateAt.START) {
- sum = 0;
- int i;
-
- for (i = len; i >= 0; i--) {
- float w = wid[len + i - 1];
-
- if (w + sum + ellipsiswid > avail) {
- break;
- }
-
- sum += w;
- }
-
- if (callback != null) {
- callback.ellipsized(0, i);
- }
-
- if (preserveLength) {
- SpannableString ss = new SpannableString(blank(text, 0, i));
- copySpansFrom(sp, 0, len, Object.class, ss, 0);
- return ss;
- } else {
- SpannableStringBuilder out = new SpannableStringBuilder(sEllipsis);
- out.insert(1, text, i, len);
-
- return out;
- }
- } else if (where == TruncateAt.END) {
- sum = 0;
- int i;
-
- for (i = 0; i < len; i++) {
- float w = wid[len + i];
-
- if (w + sum + ellipsiswid > avail) {
- break;
- }
-
- sum += w;
- }
-
- if (callback != null) {
- callback.ellipsized(i, len);
- }
-
- if (preserveLength) {
- SpannableString ss = new SpannableString(blank(text, i, len));
- copySpansFrom(sp, 0, len, Object.class, ss, 0);
- return ss;
- } else {
- SpannableStringBuilder out = new SpannableStringBuilder(sEllipsis);
- out.insert(0, text, 0, i);
-
- return out;
- }
- } else /* where = TruncateAt.MIDDLE */ {
- float lsum = 0, rsum = 0;
- int left = 0, right = len;
-
- float ravail = (avail - ellipsiswid) / 2;
- for (right = len; right >= 0; right--) {
- float w = wid[len + right - 1];
-
- if (w + rsum > ravail) {
- break;
- }
-
- rsum += w;
- }
-
- float lavail = avail - ellipsiswid - rsum;
- for (left = 0; left < right; left++) {
- float w = wid[len + left];
-
- if (w + lsum > lavail) {
- break;
- }
-
- lsum += w;
- }
-
- if (callback != null) {
- callback.ellipsized(left, right);
- }
-
- if (preserveLength) {
- SpannableString ss = new SpannableString(blank(text, left, right));
- copySpansFrom(sp, 0, len, Object.class, ss, 0);
- return ss;
- } else {
- SpannableStringBuilder out = new SpannableStringBuilder(sEllipsis);
- out.insert(0, text, 0, left);
- out.insert(out.length(), text, right, len);
-
- return out;
- }
- }
- }
-
- private static String blank(CharSequence source, int start, int end) {
- int len = source.length();
- char[] buf = obtain(len);
-
- if (start != 0) {
- getChars(source, 0, start, buf, 0);
- }
- if (end != len) {
- getChars(source, end, len, buf, end);
- }
-
- if (start != end) {
- buf[start] = '\u2026';
-
- for (int i = start + 1; i < end; i++) {
- buf[i] = '\uFEFF';
- }
- }
-
- String ret = new String(buf, 0, len);
- recycle(buf);
-
- return ret;
- }
-
- /**
- * Converts a CharSequence of the comma-separated form "Andy, Bob,
- * Charles, David" that is too wide to fit into the specified width
- * into one like "Andy, Bob, 2 more".
- *
- * @param text the text to truncate
- * @param p the Paint with which to measure the text
- * @param avail the horizontal width available for the text
- * @param oneMore the string for "1 more" in the current locale
- * @param more the string for "%d more" in the current locale
- */
- public static CharSequence commaEllipsize(CharSequence text,
- TextPaint p, float avail,
- String oneMore,
- String more) {
- int len = text.length();
- char[] buf = new char[len];
- TextUtils.getChars(text, 0, len, buf, 0);
-
- int commaCount = 0;
- for (int i = 0; i < len; i++) {
- if (buf[i] == ',') {
- commaCount++;
- }
- }
-
- float[] wid;
-
- if (text instanceof Spanned) {
- Spanned sp = (Spanned) text;
- TextPaint temppaint = new TextPaint();
- wid = new float[len * 2];
-
- int next;
- for (int i = 0; i < len; i = next) {
- next = sp.nextSpanTransition(i, len, MetricAffectingSpan.class);
-
- Styled.getTextWidths(p, temppaint, sp, i, next, wid, null);
- System.arraycopy(wid, 0, wid, len + i, next - i);
- }
-
- System.arraycopy(wid, len, wid, 0, len);
- } else {
- wid = new float[len];
- p.getTextWidths(text, 0, len, wid);
- }
-
- int ok = 0;
- int okRemaining = commaCount + 1;
- String okFormat = "";
-
- int w = 0;
- int count = 0;
-
- for (int i = 0; i < len; i++) {
- w += wid[i];
-
- if (buf[i] == ',') {
- count++;
-
- int remaining = commaCount - count + 1;
- float moreWid;
- String format;
-
- if (remaining == 1) {
- format = " " + oneMore;
- } else {
- format = " " + String.format(more, remaining);
- }
-
- moreWid = p.measureText(format);
-
- if (w + moreWid <= avail) {
- ok = i + 1;
- okRemaining = remaining;
- okFormat = format;
- }
- }
- }
-
- if (w <= avail) {
- return text;
- } else {
- SpannableStringBuilder out = new SpannableStringBuilder(okFormat);
- out.insert(0, text, 0, ok);
- return out;
- }
- }
-
- /* package */ static char[] obtain(int len) {
- char[] buf;
-
- synchronized (sLock) {
- buf = sTemp;
- sTemp = null;
- }
-
- if (buf == null || buf.length < len)
- buf = new char[ArrayUtils.idealCharArraySize(len)];
-
- return buf;
- }
-
- /* package */ static void recycle(char[] temp) {
- if (temp.length > 1000)
- return;
-
- synchronized (sLock) {
- sTemp = temp;
- }
- }
-
- /**
- * Html-encode the string.
- * @param s the string to be encoded
- * @return the encoded string
- */
- public static String htmlEncode(String s) {
- StringBuilder sb = new StringBuilder();
- char c;
- for (int i = 0; i < s.length(); i++) {
- c = s.charAt(i);
- switch (c) {
- case '<':
- sb.append("&lt;"); //$NON-NLS-1$
- break;
- case '>':
- sb.append("&gt;"); //$NON-NLS-1$
- break;
- case '&':
- sb.append("&amp;"); //$NON-NLS-1$
- break;
- case '\'':
- sb.append("&apos;"); //$NON-NLS-1$
- break;
- case '"':
- sb.append("&quot;"); //$NON-NLS-1$
- break;
- default:
- sb.append(c);
- }
- }
- return sb.toString();
- }
-
- /**
- * Returns a CharSequence concatenating the specified CharSequences,
- * retaining their spans if any.
- */
- public static CharSequence concat(CharSequence... text) {
- if (text.length == 0) {
- return "";
- }
-
- if (text.length == 1) {
- return text[0];
- }
-
- boolean spanned = false;
- for (int i = 0; i < text.length; i++) {
- if (text[i] instanceof Spanned) {
- spanned = true;
- break;
- }
- }
-
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < text.length; i++) {
- sb.append(text[i]);
- }
-
- if (!spanned) {
- return sb.toString();
- }
-
- SpannableString ss = new SpannableString(sb);
- int off = 0;
- for (int i = 0; i < text.length; i++) {
- int len = text[i].length();
-
- if (text[i] instanceof Spanned) {
- copySpansFrom((Spanned) text[i], 0, len, Object.class, ss, off);
- }
-
- off += len;
- }
-
- return new SpannedString(ss);
- }
-
- /**
- * Returns whether the given CharSequence contains any printable characters.
- */
- public static boolean isGraphic(CharSequence str) {
- final int len = str.length();
- for (int i=0; i<len; i++) {
- int gc = Character.getType(str.charAt(i));
- if (gc != Character.CONTROL
- && gc != Character.FORMAT
- && gc != Character.SURROGATE
- && gc != Character.UNASSIGNED
- && gc != Character.LINE_SEPARATOR
- && gc != Character.PARAGRAPH_SEPARATOR
- && gc != Character.SPACE_SEPARATOR) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns whether this character is a printable character.
- */
- public static boolean isGraphic(char c) {
- int gc = Character.getType(c);
- return gc != Character.CONTROL
- && gc != Character.FORMAT
- && gc != Character.SURROGATE
- && gc != Character.UNASSIGNED
- && gc != Character.LINE_SEPARATOR
- && gc != Character.PARAGRAPH_SEPARATOR
- && gc != Character.SPACE_SEPARATOR;
- }
-
- /**
- * Returns whether the given CharSequence contains only digits.
- */
- public static boolean isDigitsOnly(CharSequence str) {
- final int len = str.length();
- for (int i = 0; i < len; i++) {
- if (!Character.isDigit(str.charAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Capitalization mode for {@link #getCapsMode}: capitalize all
- * characters. This value is explicitly defined to be the same as
- * {@link InputType#TYPE_TEXT_FLAG_CAP_CHARACTERS}.
- */
- public static final int CAP_MODE_CHARACTERS
- = InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
-
- /**
- * Capitalization mode for {@link #getCapsMode}: capitalize the first
- * character of all words. This value is explicitly defined to be the same as
- * {@link InputType#TYPE_TEXT_FLAG_CAP_WORDS}.
- */
- public static final int CAP_MODE_WORDS
- = InputType.TYPE_TEXT_FLAG_CAP_WORDS;
-
- /**
- * Capitalization mode for {@link #getCapsMode}: capitalize the first
- * character of each sentence. This value is explicitly defined to be the same as
- * {@link InputType#TYPE_TEXT_FLAG_CAP_SENTENCES}.
- */
- public static final int CAP_MODE_SENTENCES
- = InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
-
- /**
- * Determine what caps mode should be in effect at the current offset in
- * the text. Only the mode bits set in <var>reqModes</var> will be
- * checked. Note that the caps mode flags here are explicitly defined
- * to match those in {@link InputType}.
- *
- * @param cs The text that should be checked for caps modes.
- * @param off Location in the text at which to check.
- * @param reqModes The modes to be checked: may be any combination of
- * {@link #CAP_MODE_CHARACTERS}, {@link #CAP_MODE_WORDS}, and
- * {@link #CAP_MODE_SENTENCES}.
- *
- * @return Returns the actual capitalization modes that can be in effect
- * at the current position, which is any combination of
- * {@link #CAP_MODE_CHARACTERS}, {@link #CAP_MODE_WORDS}, and
- * {@link #CAP_MODE_SENTENCES}.
- */
- public static int getCapsMode(CharSequence cs, int off, int reqModes) {
- int i;
- char c;
- int mode = 0;
-
- if ((reqModes&CAP_MODE_CHARACTERS) != 0) {
- mode |= CAP_MODE_CHARACTERS;
- }
- if ((reqModes&(CAP_MODE_WORDS|CAP_MODE_SENTENCES)) == 0) {
- return mode;
- }
-
- // Back over allowed opening punctuation.
-
- for (i = off; i > 0; i--) {
- c = cs.charAt(i - 1);
-
- if (c != '"' && c != '\'' &&
- Character.getType(c) != Character.START_PUNCTUATION) {
- break;
- }
- }
-
- // Start of paragraph, with optional whitespace.
-
- int j = i;
- while (j > 0 && ((c = cs.charAt(j - 1)) == ' ' || c == '\t')) {
- j--;
- }
- if (j == 0 || cs.charAt(j - 1) == '\n') {
- return mode | CAP_MODE_WORDS;
- }
-
- // Or start of word if we are that style.
-
- if ((reqModes&CAP_MODE_SENTENCES) == 0) {
- if (i != j) mode |= CAP_MODE_WORDS;
- return mode;
- }
-
- // There must be a space if not the start of paragraph.
-
- if (i == j) {
- return mode;
- }
-
- // Back over allowed closing punctuation.
-
- for (; j > 0; j--) {
- c = cs.charAt(j - 1);
-
- if (c != '"' && c != '\'' &&
- Character.getType(c) != Character.END_PUNCTUATION) {
- break;
- }
- }
-
- if (j > 0) {
- c = cs.charAt(j - 1);
-
- if (c == '.' || c == '?' || c == '!') {
- // Do not capitalize if the word ends with a period but
- // also contains a period, in which case it is an abbreviation.
-
- if (c == '.') {
- for (int k = j - 2; k >= 0; k--) {
- c = cs.charAt(k);
-
- if (c == '.') {
- return mode;
- }
-
- if (!Character.isLetter(c)) {
- break;
- }
- }
- }
-
- return mode | CAP_MODE_SENTENCES;
- }
- }
-
- return mode;
- }
-
- private static Object sLock = new Object();
- private static char[] sTemp = null;
-}
diff --git a/core/java/android/text/TextWatcher.java b/core/java/android/text/TextWatcher.java
deleted file mode 100644
index bad09f2..0000000
--- a/core/java/android/text/TextWatcher.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-/**
- * When an object of a type is attached to an Editable, its methods will
- * be called when the text is changed.
- */
-public interface TextWatcher extends NoCopySpan {
- /**
- * This method is called to notify you that, within <code>s</code>,
- * the <code>count</code> characters beginning at <code>start</code>
- * are about to be replaced by new text with length <code>after</code>.
- * It is an error to attempt to make changes to <code>s</code> from
- * this callback.
- */
- public void beforeTextChanged(CharSequence s, int start,
- int count, int after);
- /**
- * This method is called to notify you that, within <code>s</code>,
- * the <code>count</code> characters beginning at <code>start</code>
- * have just replaced old text that had length <code>before</code>.
- * It is an error to attempt to make changes to <code>s</code> from
- * this callback.
- */
- public void onTextChanged(CharSequence s, int start, int before, int count);
-
- /**
- * This method is called to notify you that, somewhere within
- * <code>s</code>, the text has been changed.
- * It is legitimate to make further changes to <code>s</code> from
- * this callback, but be careful not to get yourself into an infinite
- * loop, because any changes you make will cause this method to be
- * called again recursively.
- * (You are not told where the change took place because other
- * afterTextChanged() methods may already have made other changes
- * and invalidated the offsets. But if you need to know here,
- * you can use {@link Spannable#setSpan} in {@link #onTextChanged}
- * to mark your place and then look up from here where the span
- * ended up.
- */
- public void afterTextChanged(Editable s);
-}
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
deleted file mode 100644
index 0dc96c3..0000000
--- a/core/java/android/text/format/DateFormat.java
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.format;
-
-import android.content.Context;
-import android.provider.Settings;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-import android.text.SpannedString;
-
-import com.android.internal.R;
-
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.TimeZone;
-import java.text.SimpleDateFormat;
-
-/**
- Utility class for producing strings with formatted date/time.
-
- <p>
- This class takes as inputs a format string and a representation of a date/time.
- The format string controls how the output is generated.
- </p>
- <p>
- Formatting characters may be repeated in order to get more detailed representations
- of that field. For instance, the format character &apos;M&apos; is used to
- represent the month. Depending on how many times that character is repeated
- you get a different representation.
- </p>
- <p>
- For the month of September:<br/>
- M -&gt; 9<br/>
- MM -&gt; 09<br/>
- MMM -&gt; Sep<br/>
- MMMM -&gt; September
- </p>
- <p>
- The effects of the duplication vary depending on the nature of the field.
- See the notes on the individual field formatters for details. For purely numeric
- fields such as <code>HOUR</code> adding more copies of the designator will
- zero-pad the value to that number of characters.
- </p>
- <p>
- For 7 minutes past the hour:<br/>
- m -&gt; 7<br/>
- mm -&gt; 07<br/>
- mmm -&gt; 007<br/>
- mmmm -&gt; 0007
- </p>
- <p>
- Examples for April 6, 1970 at 3:23am:<br/>
- &quot;MM/dd/yy h:mmaa&quot; -&gt; &quot;04/06/70 3:23am&quot<br/>
- &quot;MMM dd, yyyy h:mmaa&quot; -&gt; &quot;Apr 6, 1970 3:23am&quot<br/>
- &quot;MMMM dd, yyyy h:mmaa&quot; -&gt; &quot;April 6, 1970 3:23am&quot<br/>
- &quot;E, MMMM dd, yyyy h:mmaa&quot; -&gt; &quot;Mon, April 6, 1970 3:23am&<br/>
- &quot;EEEE, MMMM dd, yyyy h:mmaa&quot; -&gt; &quot;Monday, April 6, 1970 3:23am&quot;<br/>
- &quot;&apos;Noteworthy day: &apos;M/d/yy&quot; -&gt; &quot;Noteworthy day: 4/6/70&quot;
- */
-
-public class DateFormat {
- /**
- Text in the format string that should be copied verbatim rather that
- interpreted as formatting codes must be surrounded by the <code>QUOTE</code>
- character. If you need to embed a literal <code>QUOTE</code> character in
- the output text then use two in a row.
- */
- public static final char QUOTE = '\'';
-
- /**
- This designator indicates whether the <code>HOUR</code> field is before
- or after noon. The output is lower-case.
-
- Examples:
- a -> a or p
- aa -> am or pm
- */
- public static final char AM_PM = 'a';
-
- /**
- This designator indicates whether the <code>HOUR</code> field is before
- or after noon. The output is capitalized.
-
- Examples:
- A -> A or P
- AA -> AM or PM
- */
- public static final char CAPITAL_AM_PM = 'A';
-
- /**
- This designator indicates the day of the month.
-
- Examples for the 9th of the month:
- d -> 9
- dd -> 09
- */
- public static final char DATE = 'd';
-
- /**
- This designator indicates the name of the day of the week.
-
- Examples for Sunday:
- E -> Sun
- EEEE -> Sunday
- */
- public static final char DAY = 'E';
-
- /**
- This designator indicates the hour of the day in 12 hour format.
-
- Examples for 3pm:
- h -> 3
- hh -> 03
- */
- public static final char HOUR = 'h';
-
- /**
- This designator indicates the hour of the day in 24 hour format.
-
- Example for 3pm:
- k -> 15
-
- Examples for midnight:
- k -> 0
- kk -> 00
- */
- public static final char HOUR_OF_DAY = 'k';
-
- /**
- This designator indicates the minute of the hour.
-
- Examples for 7 minutes past the hour:
- m -> 7
- mm -> 07
- */
- public static final char MINUTE = 'm';
-
- /**
- This designator indicates the month of the year
-
- Examples for September:
- M -> 9
- MM -> 09
- MMM -> Sep
- MMMM -> September
- */
- public static final char MONTH = 'M';
-
- /**
- This designator indicates the seconds of the minute.
-
- Examples for 7 seconds past the minute:
- s -> 7
- ss -> 07
- */
- public static final char SECONDS = 's';
-
- /**
- This designator indicates the offset of the timezone from GMT.
-
- Example for US/Pacific timezone:
- z -> -0800
- zz -> PST
- */
- public static final char TIME_ZONE = 'z';
-
- /**
- This designator indicates the year.
-
- Examples for 2006
- y -> 06
- yyyy -> 2006
- */
- public static final char YEAR = 'y';
-
-
- private static final Object sLocaleLock = new Object();
- private static Locale sIs24HourLocale;
- private static boolean sIs24Hour;
-
-
- /**
- * Returns true if user preference is set to 24-hour format.
- * @param context the context to use for the content resolver
- * @return true if 24 hour time format is selected, false otherwise.
- */
- public static boolean is24HourFormat(Context context) {
- String value = Settings.System.getString(context.getContentResolver(),
- Settings.System.TIME_12_24);
-
- if (value == null) {
- Locale locale = context.getResources().getConfiguration().locale;
-
- synchronized (sLocaleLock) {
- if (sIs24HourLocale != null && sIs24HourLocale.equals(locale)) {
- return sIs24Hour;
- }
- }
-
- java.text.DateFormat natural =
- java.text.DateFormat.getTimeInstance(
- java.text.DateFormat.LONG, locale);
-
- if (natural instanceof SimpleDateFormat) {
- SimpleDateFormat sdf = (SimpleDateFormat) natural;
- String pattern = sdf.toPattern();
-
- if (pattern.indexOf('H') >= 0) {
- value = "24";
- } else {
- value = "12";
- }
- } else {
- value = "12";
- }
-
- synchronized (sLocaleLock) {
- sIs24HourLocale = locale;
- sIs24Hour = !value.equals("12");
- }
- }
-
- boolean b24 = !(value == null || value.equals("12"));
- return b24;
- }
-
- /**
- * Returns a {@link java.text.DateFormat} object that can format the time according
- * to the current user preference.
- * @param context the application context
- * @return the {@link java.text.DateFormat} object that properly formats the time.
- */
- public static final java.text.DateFormat getTimeFormat(Context context) {
- boolean b24 = is24HourFormat(context);
- int res;
-
- if (b24) {
- res = R.string.twenty_four_hour_time_format;
- } else {
- res = R.string.twelve_hour_time_format;
- }
-
- return new java.text.SimpleDateFormat(context.getString(res));
- }
-
- /**
- * Returns a {@link java.text.DateFormat} object that can format the date according
- * to the current user preference.
- * @param context the application context
- * @return the {@link java.text.DateFormat} object that properly formats the date.
- */
- public static final java.text.DateFormat getDateFormat(Context context) {
- String value = getDateFormatString(context);
- return new java.text.SimpleDateFormat(value);
- }
-
- /**
- * Returns a {@link java.text.DateFormat} object that can format the date
- * in long form (such as December 31, 1999) based on user preference.
- * @param context the application context
- * @return the {@link java.text.DateFormat} object that formats the date in long form.
- */
- public static final java.text.DateFormat getLongDateFormat(Context context) {
- String value = getDateFormatString(context);
- if (value.indexOf('M') < value.indexOf('d')) {
- value = context.getString(R.string.full_date_month_first);
- } else {
- value = context.getString(R.string.full_date_day_first);
- }
- return new java.text.SimpleDateFormat(value);
- }
-
- /**
- * Returns a {@link java.text.DateFormat} object that can format the date
- * in medium form (such as Dec. 31, 1999) based on user preference.
- * @param context the application context
- * @return the {@link java.text.DateFormat} object that formats the date in long form.
- */
- public static final java.text.DateFormat getMediumDateFormat(Context context) {
- String value = getDateFormatString(context);
- if (value.indexOf('M') < value.indexOf('d')) {
- value = context.getString(R.string.medium_date_month_first);
- } else {
- value = context.getString(R.string.medium_date_day_first);
- }
- return new java.text.SimpleDateFormat(value);
- }
-
- /**
- * Gets the current date format stored as a char array. The array will contain
- * 3 elements ({@link #DATE}, {@link #MONTH}, and {@link #YEAR}) in the order
- * preferred by the user.
- */
- public static final char[] getDateFormatOrder(Context context) {
- char[] order = new char[] {DATE, MONTH, YEAR};
- String value = getDateFormatString(context);
- int index = 0;
- boolean foundDate = false;
- boolean foundMonth = false;
- boolean foundYear = false;
-
- for (char c : value.toCharArray()) {
- if (!foundDate && (c == DATE)) {
- foundDate = true;
- order[index] = DATE;
- index++;
- }
-
- if (!foundMonth && (c == MONTH)) {
- foundMonth = true;
- order[index] = MONTH;
- index++;
- }
-
- if (!foundYear && (c == YEAR)) {
- foundYear = true;
- order[index] = YEAR;
- index++;
- }
- }
- return order;
- }
-
- private static String getDateFormatString(Context context) {
- String value = Settings.System.getString(context.getContentResolver(),
- Settings.System.DATE_FORMAT);
- if (value == null || value.length() < 6) {
- /*
- * No need to localize -- this is an emergency fallback in case
- * the setting is missing, but it should always be set.
- */
- value = "MM-dd-yyyy";
- }
- return value;
- }
-
- /**
- * Given a format string and a time in milliseconds since Jan 1, 1970 GMT, returns a
- * CharSequence containing the requested date.
- * @param inFormat the format string, as described in {@link android.text.format.DateFormat}
- * @param inTimeInMillis in milliseconds since Jan 1, 1970 GMT
- * @return a {@link CharSequence} containing the requested text
- */
- public static final CharSequence format(CharSequence inFormat, long inTimeInMillis) {
- return format(inFormat, new Date(inTimeInMillis));
- }
-
- /**
- * Given a format string and a {@link java.util.Date} object, returns a CharSequence containing
- * the requested date.
- * @param inFormat the format string, as described in {@link android.text.format.DateFormat}
- * @param inDate the date to format
- * @return a {@link CharSequence} containing the requested text
- */
- public static final CharSequence format(CharSequence inFormat, Date inDate) {
- Calendar c = new GregorianCalendar();
-
- c.setTime(inDate);
-
- return format(inFormat, c);
- }
-
- /**
- * Given a format string and a {@link java.util.Calendar} object, returns a CharSequence
- * containing the requested date.
- * @param inFormat the format string, as described in {@link android.text.format.DateFormat}
- * @param inDate the date to format
- * @return a {@link CharSequence} containing the requested text
- */
- public static final CharSequence format(CharSequence inFormat, Calendar inDate) {
- SpannableStringBuilder s = new SpannableStringBuilder(inFormat);
- int c;
- int count;
-
- int len = inFormat.length();
-
- for (int i = 0; i < len; i += count) {
- int temp;
-
- count = 1;
- c = s.charAt(i);
-
- if (c == QUOTE) {
- count = appendQuotedText(s, i, len);
- len = s.length();
- continue;
- }
-
- while ((i + count < len) && (s.charAt(i + count) == c)) {
- count++;
- }
-
- String replacement;
-
- switch (c) {
- case AM_PM:
- replacement = DateUtils.getAMPMString(inDate.get(Calendar.AM_PM));
- break;
-
- case CAPITAL_AM_PM:
- //FIXME: this is the same as AM_PM? no capital?
- replacement = DateUtils.getAMPMString(inDate.get(Calendar.AM_PM));
- break;
-
- case DATE:
- replacement = zeroPad(inDate.get(Calendar.DATE), count);
- break;
-
- case DAY:
- temp = inDate.get(Calendar.DAY_OF_WEEK);
- replacement = DateUtils.getDayOfWeekString(temp,
- count < 4 ?
- DateUtils.LENGTH_MEDIUM :
- DateUtils.LENGTH_LONG);
- break;
-
- case HOUR:
- temp = inDate.get(Calendar.HOUR);
-
- if (0 == temp)
- temp = 12;
-
- replacement = zeroPad(temp, count);
- break;
-
- case HOUR_OF_DAY:
- replacement = zeroPad(inDate.get(Calendar.HOUR_OF_DAY), count);
- break;
-
- case MINUTE:
- replacement = zeroPad(inDate.get(Calendar.MINUTE), count);
- break;
-
- case MONTH:
- replacement = getMonthString(inDate, count);
- break;
-
- case SECONDS:
- replacement = zeroPad(inDate.get(Calendar.SECOND), count);
- break;
-
- case TIME_ZONE:
- replacement = getTimeZoneString(inDate, count);
- break;
-
- case YEAR:
- replacement = getYearString(inDate, count);
- break;
-
- default:
- replacement = null;
- break;
- }
-
- if (replacement != null) {
- s.replace(i, i + count, replacement);
- count = replacement.length(); // CARE: count is used in the for loop above
- len = s.length();
- }
- }
-
- if (inFormat instanceof Spanned)
- return new SpannedString(s);
- else
- return s.toString();
- }
-
- private static final String getMonthString(Calendar inDate, int count) {
- int month = inDate.get(Calendar.MONTH);
-
- if (count >= 4)
- return DateUtils.getMonthString(month, DateUtils.LENGTH_LONG);
- else if (count == 3)
- return DateUtils.getMonthString(month, DateUtils.LENGTH_MEDIUM);
- else {
- // Calendar.JANUARY == 0, so add 1 to month.
- return zeroPad(month+1, count);
- }
- }
-
- private static final String getTimeZoneString(Calendar inDate, int count) {
- TimeZone tz = inDate.getTimeZone();
-
- if (count < 2) { // FIXME: shouldn't this be <= 2 ?
- return formatZoneOffset(inDate.get(Calendar.DST_OFFSET) +
- inDate.get(Calendar.ZONE_OFFSET),
- count);
- } else {
- boolean dst = inDate.get(Calendar.DST_OFFSET) != 0;
- return tz.getDisplayName(dst, TimeZone.SHORT);
- }
- }
-
- private static final String formatZoneOffset(int offset, int count) {
- offset /= 1000; // milliseconds to seconds
- StringBuilder tb = new StringBuilder();
-
- if (offset < 0) {
- tb.insert(0, "-");
- offset = -offset;
- } else {
- tb.insert(0, "+");
- }
-
- int hours = offset / 3600;
- int minutes = (offset % 3600) / 60;
-
- tb.append(zeroPad(hours, 2));
- tb.append(zeroPad(minutes, 2));
- return tb.toString();
- }
-
- private static final String getYearString(Calendar inDate, int count) {
- int year = inDate.get(Calendar.YEAR);
- return (count <= 2) ? zeroPad(year % 100, 2) : String.valueOf(year);
- }
-
- private static final int appendQuotedText(SpannableStringBuilder s, int i, int len) {
- if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
- s.delete(i, i + 1);
- return 1;
- }
-
- int count = 0;
-
- // delete leading quote
- s.delete(i, i + 1);
- len--;
-
- while (i < len) {
- char c = s.charAt(i);
-
- if (c == QUOTE) {
- // QUOTEQUOTE -> QUOTE
- if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
-
- s.delete(i, i + 1);
- len--;
- count++;
- i++;
- } else {
- // Closing QUOTE ends quoted text copying
- s.delete(i, i + 1);
- break;
- }
- } else {
- i++;
- count++;
- }
- }
-
- return count;
- }
-
- private static final String zeroPad(int inValue, int inMinDigits) {
- String val = String.valueOf(inValue);
-
- if (val.length() < inMinDigits) {
- char[] buf = new char[inMinDigits];
-
- for (int i = 0; i < inMinDigits; i++)
- buf[i] = '0';
-
- val.getChars(0, val.length(), buf, inMinDigits - val.length());
- val = new String(buf);
- }
- return val;
- }
-}
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
deleted file mode 100644
index feae6cf..0000000
--- a/core/java/android/text/format/DateUtils.java
+++ /dev/null
@@ -1,1581 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.format;
-
-import com.android.internal.R;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.pim.DateException;
-
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.TimeZone;
-
-/**
- * This class contains various date-related utilities for creating text for things like
- * elapsed time and date ranges, strings for days of the week and months, and AM/PM text etc.
- */
-public class DateUtils
-{
- private static final Object sLock = new Object();
- private static final int[] sDaysLong = new int[] {
- com.android.internal.R.string.day_of_week_long_sunday,
- com.android.internal.R.string.day_of_week_long_monday,
- com.android.internal.R.string.day_of_week_long_tuesday,
- com.android.internal.R.string.day_of_week_long_wednesday,
- com.android.internal.R.string.day_of_week_long_thursday,
- com.android.internal.R.string.day_of_week_long_friday,
- com.android.internal.R.string.day_of_week_long_saturday,
- };
- private static final int[] sDaysMedium = new int[] {
- com.android.internal.R.string.day_of_week_medium_sunday,
- com.android.internal.R.string.day_of_week_medium_monday,
- com.android.internal.R.string.day_of_week_medium_tuesday,
- com.android.internal.R.string.day_of_week_medium_wednesday,
- com.android.internal.R.string.day_of_week_medium_thursday,
- com.android.internal.R.string.day_of_week_medium_friday,
- com.android.internal.R.string.day_of_week_medium_saturday,
- };
- private static final int[] sDaysShort = new int[] {
- com.android.internal.R.string.day_of_week_short_sunday,
- com.android.internal.R.string.day_of_week_short_monday,
- com.android.internal.R.string.day_of_week_short_tuesday,
- com.android.internal.R.string.day_of_week_short_wednesday,
- com.android.internal.R.string.day_of_week_short_thursday,
- com.android.internal.R.string.day_of_week_short_friday,
- com.android.internal.R.string.day_of_week_short_saturday,
- };
- private static final int[] sDaysShorter = new int[] {
- com.android.internal.R.string.day_of_week_shorter_sunday,
- com.android.internal.R.string.day_of_week_shorter_monday,
- com.android.internal.R.string.day_of_week_shorter_tuesday,
- com.android.internal.R.string.day_of_week_shorter_wednesday,
- com.android.internal.R.string.day_of_week_shorter_thursday,
- com.android.internal.R.string.day_of_week_shorter_friday,
- com.android.internal.R.string.day_of_week_shorter_saturday,
- };
- private static final int[] sDaysShortest = new int[] {
- com.android.internal.R.string.day_of_week_shortest_sunday,
- com.android.internal.R.string.day_of_week_shortest_monday,
- com.android.internal.R.string.day_of_week_shortest_tuesday,
- com.android.internal.R.string.day_of_week_shortest_wednesday,
- com.android.internal.R.string.day_of_week_shortest_thursday,
- com.android.internal.R.string.day_of_week_shortest_friday,
- com.android.internal.R.string.day_of_week_shortest_saturday,
- };
- private static final int[] sMonthsLong = new int [] {
- com.android.internal.R.string.month_long_january,
- com.android.internal.R.string.month_long_february,
- com.android.internal.R.string.month_long_march,
- com.android.internal.R.string.month_long_april,
- com.android.internal.R.string.month_long_may,
- com.android.internal.R.string.month_long_june,
- com.android.internal.R.string.month_long_july,
- com.android.internal.R.string.month_long_august,
- com.android.internal.R.string.month_long_september,
- com.android.internal.R.string.month_long_october,
- com.android.internal.R.string.month_long_november,
- com.android.internal.R.string.month_long_december,
- };
- private static final int[] sMonthsMedium = new int [] {
- com.android.internal.R.string.month_medium_january,
- com.android.internal.R.string.month_medium_february,
- com.android.internal.R.string.month_medium_march,
- com.android.internal.R.string.month_medium_april,
- com.android.internal.R.string.month_medium_may,
- com.android.internal.R.string.month_medium_june,
- com.android.internal.R.string.month_medium_july,
- com.android.internal.R.string.month_medium_august,
- com.android.internal.R.string.month_medium_september,
- com.android.internal.R.string.month_medium_october,
- com.android.internal.R.string.month_medium_november,
- com.android.internal.R.string.month_medium_december,
- };
- private static final int[] sMonthsShortest = new int [] {
- com.android.internal.R.string.month_shortest_january,
- com.android.internal.R.string.month_shortest_february,
- com.android.internal.R.string.month_shortest_march,
- com.android.internal.R.string.month_shortest_april,
- com.android.internal.R.string.month_shortest_may,
- com.android.internal.R.string.month_shortest_june,
- com.android.internal.R.string.month_shortest_july,
- com.android.internal.R.string.month_shortest_august,
- com.android.internal.R.string.month_shortest_september,
- com.android.internal.R.string.month_shortest_october,
- com.android.internal.R.string.month_shortest_november,
- com.android.internal.R.string.month_shortest_december,
- };
- private static final int[] sAmPm = new int[] {
- com.android.internal.R.string.am,
- com.android.internal.R.string.pm,
- };
- private static Configuration sLastConfig;
- private static String sStatusTimeFormat;
- private static String sElapsedFormatMMSS;
- private static String sElapsedFormatHMMSS;
-
- private static final String FAST_FORMAT_HMMSS = "%1$d:%2$02d:%3$02d";
- private static final String FAST_FORMAT_MMSS = "%1$02d:%2$02d";
- private static final char TIME_PADDING = '0';
- private static final char TIME_SEPARATOR = ':';
-
-
- public static final long SECOND_IN_MILLIS = 1000;
- public static final long MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60;
- public static final long HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60;
- public static final long DAY_IN_MILLIS = HOUR_IN_MILLIS * 24;
- public static final long WEEK_IN_MILLIS = DAY_IN_MILLIS * 7;
- public static final long YEAR_IN_MILLIS = WEEK_IN_MILLIS * 52;
-
- // The following FORMAT_* symbols are used for specifying the format of
- // dates and times in the formatDateRange method.
- public static final int FORMAT_SHOW_TIME = 0x00001;
- public static final int FORMAT_SHOW_WEEKDAY = 0x00002;
- public static final int FORMAT_SHOW_YEAR = 0x00004;
- public static final int FORMAT_NO_YEAR = 0x00008;
- public static final int FORMAT_SHOW_DATE = 0x00010;
- public static final int FORMAT_NO_MONTH_DAY = 0x00020;
- public static final int FORMAT_12HOUR = 0x00040;
- public static final int FORMAT_24HOUR = 0x00080;
- public static final int FORMAT_CAP_AMPM = 0x00100;
- public static final int FORMAT_NO_NOON = 0x00200;
- public static final int FORMAT_CAP_NOON = 0x00400;
- public static final int FORMAT_NO_MIDNIGHT = 0x00800;
- public static final int FORMAT_CAP_MIDNIGHT = 0x01000;
- public static final int FORMAT_UTC = 0x02000;
- public static final int FORMAT_ABBREV_TIME = 0x04000;
- public static final int FORMAT_ABBREV_WEEKDAY = 0x08000;
- public static final int FORMAT_ABBREV_MONTH = 0x10000;
- public static final int FORMAT_NUMERIC_DATE = 0x20000;
- public static final int FORMAT_ABBREV_RELATIVE = 0x40000;
- public static final int FORMAT_ABBREV_ALL = 0x80000;
- public static final int FORMAT_CAP_NOON_MIDNIGHT = (FORMAT_CAP_NOON | FORMAT_CAP_MIDNIGHT);
- public static final int FORMAT_NO_NOON_MIDNIGHT = (FORMAT_NO_NOON | FORMAT_NO_MIDNIGHT);
-
- // Date and time format strings that are constant and don't need to be
- // translated.
- public static final String HOUR_MINUTE_24 = "%H:%M";
- public static final String MONTH_FORMAT = "%B";
- public static final String ABBREV_MONTH_FORMAT = "%b";
- public static final String NUMERIC_MONTH_FORMAT = "%m";
- public static final String MONTH_DAY_FORMAT = "%-d";
- public static final String YEAR_FORMAT = "%Y";
- public static final String YEAR_FORMAT_TWO_DIGITS = "%g";
- public static final String WEEKDAY_FORMAT = "%A";
- public static final String ABBREV_WEEKDAY_FORMAT = "%a";
-
- // This table is used to lookup the resource string id of a format string
- // used for formatting a start and end date that fall in the same year.
- // The index is constructed from a bit-wise OR of the boolean values:
- // {showTime, showYear, showWeekDay}. For example, if showYear and
- // showWeekDay are both true, then the index would be 3.
- public static final int sameYearTable[] = {
- com.android.internal.R.string.same_year_md1_md2,
- com.android.internal.R.string.same_year_wday1_md1_wday2_md2,
- com.android.internal.R.string.same_year_mdy1_mdy2,
- com.android.internal.R.string.same_year_wday1_mdy1_wday2_mdy2,
- com.android.internal.R.string.same_year_md1_time1_md2_time2,
- com.android.internal.R.string.same_year_wday1_md1_time1_wday2_md2_time2,
- com.android.internal.R.string.same_year_mdy1_time1_mdy2_time2,
- com.android.internal.R.string.same_year_wday1_mdy1_time1_wday2_mdy2_time2,
-
- // Numeric date strings
- com.android.internal.R.string.numeric_md1_md2,
- com.android.internal.R.string.numeric_wday1_md1_wday2_md2,
- com.android.internal.R.string.numeric_mdy1_mdy2,
- com.android.internal.R.string.numeric_wday1_mdy1_wday2_mdy2,
- com.android.internal.R.string.numeric_md1_time1_md2_time2,
- com.android.internal.R.string.numeric_wday1_md1_time1_wday2_md2_time2,
- com.android.internal.R.string.numeric_mdy1_time1_mdy2_time2,
- com.android.internal.R.string.numeric_wday1_mdy1_time1_wday2_mdy2_time2,
- };
-
- // This table is used to lookup the resource string id of a format string
- // used for formatting a start and end date that fall in the same month.
- // The index is constructed from a bit-wise OR of the boolean values:
- // {showTime, showYear, showWeekDay}. For example, if showYear and
- // showWeekDay are both true, then the index would be 3.
- public static final int sameMonthTable[] = {
- com.android.internal.R.string.same_month_md1_md2,
- com.android.internal.R.string.same_month_wday1_md1_wday2_md2,
- com.android.internal.R.string.same_month_mdy1_mdy2,
- com.android.internal.R.string.same_month_wday1_mdy1_wday2_mdy2,
- com.android.internal.R.string.same_month_md1_time1_md2_time2,
- com.android.internal.R.string.same_month_wday1_md1_time1_wday2_md2_time2,
- com.android.internal.R.string.same_month_mdy1_time1_mdy2_time2,
- com.android.internal.R.string.same_month_wday1_mdy1_time1_wday2_mdy2_time2,
-
- com.android.internal.R.string.numeric_md1_md2,
- com.android.internal.R.string.numeric_wday1_md1_wday2_md2,
- com.android.internal.R.string.numeric_mdy1_mdy2,
- com.android.internal.R.string.numeric_wday1_mdy1_wday2_mdy2,
- com.android.internal.R.string.numeric_md1_time1_md2_time2,
- com.android.internal.R.string.numeric_wday1_md1_time1_wday2_md2_time2,
- com.android.internal.R.string.numeric_mdy1_time1_mdy2_time2,
- com.android.internal.R.string.numeric_wday1_mdy1_time1_wday2_mdy2_time2,
- };
-
- /**
- * Request the full spelled-out name. For use with the 'abbrev' parameter of
- * {@link #getDayOfWeekString} and {@link #getMonthString}.
- *
- * @more <p>
- * e.g. "Sunday" or "January"
- */
- public static final int LENGTH_LONG = 10;
-
- /**
- * Request an abbreviated version of the name. For use with the 'abbrev'
- * parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
- *
- * @more <p>
- * e.g. "Sun" or "Jan"
- */
- public static final int LENGTH_MEDIUM = 20;
-
- /**
- * Request a shorter abbreviated version of the name.
- * For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
- * @more
- * <p>e.g. "Su" or "Jan"
- * <p>In some languages, the results returned for LENGTH_SHORT may be the same as
- * return for {@link #LENGTH_MEDIUM}.
- */
- public static final int LENGTH_SHORT = 30;
-
- /**
- * Request an even shorter abbreviated version of the name.
- * For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
- * @more
- * <p>e.g. "M", "Tu", "Th" or "J"
- * <p>In some languages, the results returned for LENGTH_SHORTEST may be the same as
- * return for {@link #LENGTH_SHORTER}.
- */
- public static final int LENGTH_SHORTER = 40;
-
- /**
- * Request an even shorter abbreviated version of the name.
- * For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
- * @more
- * <p>e.g. "S", "T", "T" or "J"
- * <p>In some languages, the results returned for LENGTH_SHORTEST may be the same as
- * return for {@link #LENGTH_SHORTER}.
- */
- public static final int LENGTH_SHORTEST = 50;
-
- /**
- * Return a string for the day of the week.
- * @param dayOfWeek One of {@link Calendar#SUNDAY Calendar.SUNDAY},
- * {@link Calendar#MONDAY Calendar.MONDAY}, etc.
- * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_SHORT}, {@link #LENGTH_SHORTER}
- * or {@link #LENGTH_SHORTEST}. For forward compatibility, anything else
- * will return the same as {#LENGTH_MEDIUM}.
- * @throws IndexOutOfBoundsException if the dayOfWeek is out of bounds.
- */
- public static String getDayOfWeekString(int dayOfWeek, int abbrev) {
- int[] list;
- switch (abbrev) {
- case LENGTH_LONG: list = sDaysLong; break;
- case LENGTH_MEDIUM: list = sDaysMedium; break;
- case LENGTH_SHORT: list = sDaysShort; break;
- case LENGTH_SHORTER: list = sDaysShorter; break;
- case LENGTH_SHORTEST: list = sDaysShortest; break;
- default: list = sDaysMedium; break;
- }
-
- Resources r = Resources.getSystem();
- return r.getString(list[dayOfWeek - Calendar.SUNDAY]);
- }
-
- /**
- * Return a localized string for AM or PM.
- * @param ampm Either {@link Calendar#AM Calendar.AM} or {@link Calendar#PM Calendar.PM}.
- * @throws IndexOutOfBoundsException if the ampm is out of bounds.
- * @return Localized version of "AM" or "PM".
- */
- public static String getAMPMString(int ampm) {
- Resources r = Resources.getSystem();
- return r.getString(sAmPm[ampm - Calendar.AM]);
- }
-
- /**
- * Return a localized string for the day of the week.
- * @param month One of {@link Calendar#JANUARY Calendar.JANUARY},
- * {@link Calendar#FEBRUARY Calendar.FEBRUARY}, etc.
- * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_SHORT}, {@link #LENGTH_SHORTER}
- * or {@link #LENGTH_SHORTEST}. For forward compatibility, anything else
- * will return the same as {#LENGTH_MEDIUM}.
- * @return Localized day of the week.
- */
- public static String getMonthString(int month, int abbrev) {
- // Note that here we use sMonthsMedium for MEDIUM, SHORT and SHORTER.
- // This is a shortcut to not spam the translators with too many variations
- // of the same string. If we find that in a language the distinction
- // is necessary, we can can add more without changing this API.
- int[] list;
- switch (abbrev) {
- case LENGTH_LONG: list = sMonthsLong; break;
- case LENGTH_MEDIUM: list = sMonthsMedium; break;
- case LENGTH_SHORT: list = sMonthsMedium; break;
- case LENGTH_SHORTER: list = sMonthsMedium; break;
- case LENGTH_SHORTEST: list = sMonthsShortest; break;
- default: list = sMonthsMedium; break;
- }
-
- Resources r = Resources.getSystem();
- return r.getString(list[month - Calendar.JANUARY]);
- }
-
- /**
- * Returns a string describing the elapsed time since startTime.
- * @param startTime some time in the past.
- * @return a String object containing the elapsed time.
- * @see #getRelativeTimeSpanString(long, long, long)
- */
- public static CharSequence getRelativeTimeSpanString(long startTime) {
- return getRelativeTimeSpanString(startTime, System.currentTimeMillis(), MINUTE_IN_MILLIS);
- }
-
- /**
- * Returns a string describing 'time' as a time relative to 'now'.
- * <p>
- * Time spans in the past are formatted like "42 minutes ago".
- * Time spans in the future are formatted like "in 42 minutes".
- *
- * @param time the time to describe, in milliseconds
- * @param now the current time in milliseconds
- * @param minResolution the minimum timespan to report. For example, a time 3 seconds in the
- * past will be reported as "0 minutes ago" if this is set to MINUTE_IN_MILLIS. Pass one of
- * 0, MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS, WEEK_IN_MILLIS
- */
- public static CharSequence getRelativeTimeSpanString(long time, long now, long minResolution) {
- int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR | FORMAT_ABBREV_MONTH;
- return getRelativeTimeSpanString(time, now, minResolution, flags);
- }
-
- /**
- * Returns a string describing 'time' as a time relative to 'now'.
- * <p>
- * Time spans in the past are formatted like "42 minutes ago". Time spans in
- * the future are formatted like "in 42 minutes".
- * <p>
- * Can use {@link #FORMAT_ABBREV_RELATIVE} flag to use abbreviated relative
- * times, like "42 mins ago".
- *
- * @param time the time to describe, in milliseconds
- * @param now the current time in milliseconds
- * @param minResolution the minimum timespan to report. For example, a time
- * 3 seconds in the past will be reported as "0 minutes ago" if
- * this is set to MINUTE_IN_MILLIS. Pass one of 0,
- * MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS,
- * WEEK_IN_MILLIS
- * @param flags a bit mask of formatting options, such as
- * {@link #FORMAT_NUMERIC_DATE} or
- * {@link #FORMAT_ABBREV_RELATIVE}
- */
- public static CharSequence getRelativeTimeSpanString(long time, long now, long minResolution,
- int flags) {
- Resources r = Resources.getSystem();
- boolean abbrevRelative = (flags & (FORMAT_ABBREV_RELATIVE | FORMAT_ABBREV_ALL)) != 0;
-
- boolean past = (now >= time);
- long duration = Math.abs(now - time);
-
- int resId;
- long count;
- if (duration < MINUTE_IN_MILLIS && minResolution < MINUTE_IN_MILLIS) {
- count = duration / SECOND_IN_MILLIS;
- if (past) {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_num_seconds_ago;
- } else {
- resId = com.android.internal.R.plurals.num_seconds_ago;
- }
- } else {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_in_num_seconds;
- } else {
- resId = com.android.internal.R.plurals.in_num_seconds;
- }
- }
- } else if (duration < HOUR_IN_MILLIS && minResolution < HOUR_IN_MILLIS) {
- count = duration / MINUTE_IN_MILLIS;
- if (past) {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_num_minutes_ago;
- } else {
- resId = com.android.internal.R.plurals.num_minutes_ago;
- }
- } else {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_in_num_minutes;
- } else {
- resId = com.android.internal.R.plurals.in_num_minutes;
- }
- }
- } else if (duration < DAY_IN_MILLIS && minResolution < DAY_IN_MILLIS) {
- count = duration / HOUR_IN_MILLIS;
- if (past) {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_num_hours_ago;
- } else {
- resId = com.android.internal.R.plurals.num_hours_ago;
- }
- } else {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_in_num_hours;
- } else {
- resId = com.android.internal.R.plurals.in_num_hours;
- }
- }
- } else if (duration < WEEK_IN_MILLIS && minResolution < WEEK_IN_MILLIS) {
- count = duration / DAY_IN_MILLIS;
- if (past) {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_num_days_ago;
- } else {
- resId = com.android.internal.R.plurals.num_days_ago;
- }
- } else {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_in_num_days;
- } else {
- resId = com.android.internal.R.plurals.in_num_days;
- }
- }
- } else {
- // We know that we won't be showing the time, so it is safe to pass
- // in a null context.
- return formatDateRange(null, time, time, flags);
- }
-
- String format = r.getQuantityString(resId, (int) count);
- return String.format(format, count);
- }
-
- /**
- * Return string describing the elapsed time since startTime formatted like
- * "[relative time/date], [time]".
- * <p>
- * Example output strings for the US date format.
- * <ul>
- * <li>3 mins ago, 10:15 AM</li>
- * <li>yesterday, 12:20 PM</li>
- * <li>Dec 12, 4:12 AM</li>
- * <li>11/14/2007, 8:20 AM</li>
- * </ul>
- *
- * @param time some time in the past.
- * @param minResolution the minimum elapsed time (in milliseconds) to report
- * when showing relative times. For example, a time 3 seconds in
- * the past will be reported as "0 minutes ago" if this is set to
- * {@link #MINUTE_IN_MILLIS}.
- * @param transitionResolution the elapsed time (in milliseconds) at which
- * to stop reporting relative measurements. Elapsed times greater
- * than this resolution will default to normal date formatting.
- * For example, will transition from "6 days ago" to "Dec 12"
- * when using {@link #WEEK_IN_MILLIS}.
- */
- public static CharSequence getRelativeDateTimeString(Context c, long time, long minResolution,
- long transitionResolution, int flags) {
- Resources r = Resources.getSystem();
-
- long now = System.currentTimeMillis();
- long duration = Math.abs(now - time);
-
- // getRelativeTimeSpanString() doesn't correctly format relative dates
- // above a week or exact dates below a day, so clamp
- // transitionResolution as needed.
- if (transitionResolution > WEEK_IN_MILLIS) {
- transitionResolution = WEEK_IN_MILLIS;
- } else if (transitionResolution < DAY_IN_MILLIS) {
- transitionResolution = DAY_IN_MILLIS;
- }
-
- CharSequence timeClause = formatDateRange(c, time, time, FORMAT_SHOW_TIME);
-
- String result;
- if (duration < transitionResolution) {
- CharSequence relativeClause = getRelativeTimeSpanString(time, now, minResolution, flags);
- result = r.getString(com.android.internal.R.string.relative_time, relativeClause, timeClause);
- } else {
- CharSequence dateClause = getRelativeTimeSpanString(c, time, false);
- result = r.getString(com.android.internal.R.string.date_time, dateClause, timeClause);
- }
-
- return result;
- }
-
- /**
- * Returns a string describing a day relative to the current day. For example if the day is
- * today this function returns "Today", if the day was a week ago it returns "7 days ago", and
- * if the day is in 2 weeks it returns "in 14 days".
- *
- * @param r the resources to get the strings from
- * @param day the relative day to describe in UTC milliseconds
- * @param today the current time in UTC milliseconds
- * @return a formatting string
- */
- private static final String getRelativeDayString(Resources r, long day, long today) {
- Time startTime = new Time();
- startTime.set(day);
- Time currentTime = new Time();
- currentTime.set(today);
-
- int startDay = Time.getJulianDay(day, startTime.gmtoff);
- int currentDay = Time.getJulianDay(today, currentTime.gmtoff);
-
- int days = Math.abs(currentDay - startDay);
- boolean past = (today > day);
-
- if (days == 1) {
- if (past) {
- return r.getString(com.android.internal.R.string.yesterday);
- } else {
- return r.getString(com.android.internal.R.string.tomorrow);
- }
- } else if (days == 0) {
- return r.getString(com.android.internal.R.string.today);
- }
-
- int resId;
- if (past) {
- resId = com.android.internal.R.plurals.num_days_ago;
- } else {
- resId = com.android.internal.R.plurals.in_num_days;
- }
-
- String format = r.getQuantityString(resId, days);
- return String.format(format, days);
- }
-
- private static void initFormatStrings() {
- synchronized (sLock) {
- Resources r = Resources.getSystem();
- Configuration cfg = r.getConfiguration();
- if (sLastConfig == null || !sLastConfig.equals(cfg)) {
- sLastConfig = cfg;
- sStatusTimeFormat = r.getString(com.android.internal.R.string.status_bar_time_format);
- sElapsedFormatMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_mm_ss);
- sElapsedFormatHMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_h_mm_ss);
- }
- }
- }
-
- /**
- * Format a time so it appears like it would in the status bar clock.
- * @deprecated use {@link #DateFormat.getTimeFormat(Context)} instead.
- * @hide
- */
- public static final CharSequence timeString(long millis) {
- initFormatStrings();
- return DateFormat.format(sStatusTimeFormat, millis);
- }
-
- /**
- * Formats an elapsed time in the form "MM:SS" or "H:MM:SS"
- * for display on the call-in-progress screen.
- * @param elapsedSeconds the elapsed time in seconds.
- */
- public static String formatElapsedTime(long elapsedSeconds) {
- initFormatStrings();
-
- long hours = 0;
- long minutes = 0;
- long seconds = 0;
-
- if (elapsedSeconds >= 3600) {
- hours = elapsedSeconds / 3600;
- elapsedSeconds -= hours * 3600;
- }
- if (elapsedSeconds >= 60) {
- minutes = elapsedSeconds / 60;
- elapsedSeconds -= minutes * 60;
- }
- seconds = elapsedSeconds;
-
- String result;
- if (hours > 0) {
- return formatElapsedTime(sElapsedFormatHMMSS, hours, minutes, seconds);
- } else {
- return formatElapsedTime(sElapsedFormatMMSS, minutes, seconds);
- }
- }
-
- /**
- * Fast formatting of h:mm:ss
- */
- private static String formatElapsedTime(String format, long hours, long minutes, long seconds) {
- if (FAST_FORMAT_HMMSS.equals(format)) {
- StringBuffer sb = new StringBuffer(16);
- sb.append(hours);
- sb.append(TIME_SEPARATOR);
- if (minutes < 10) {
- sb.append(TIME_PADDING);
- } else {
- sb.append(toDigitChar(minutes / 10));
- }
- sb.append(toDigitChar(minutes % 10));
- sb.append(TIME_SEPARATOR);
- if (seconds < 10) {
- sb.append(TIME_PADDING);
- } else {
- sb.append(toDigitChar(seconds / 10));
- }
- sb.append(toDigitChar(seconds % 10));
- return sb.toString();
- } else {
- return String.format(format, hours, minutes, seconds);
- }
- }
-
- /**
- * Fast formatting of m:ss
- */
- private static String formatElapsedTime(String format, long minutes, long seconds) {
- if (FAST_FORMAT_MMSS.equals(format)) {
- StringBuffer sb = new StringBuffer(16);
- if (minutes < 10) {
- sb.append(TIME_PADDING);
- } else {
- sb.append(toDigitChar(minutes / 10));
- }
- sb.append(toDigitChar(minutes % 10));
- sb.append(TIME_SEPARATOR);
- if (seconds < 10) {
- sb.append(TIME_PADDING);
- } else {
- sb.append(toDigitChar(seconds / 10));
- }
- sb.append(toDigitChar(seconds % 10));
- return sb.toString();
- } else {
- return String.format(format, minutes, seconds);
- }
- }
-
- private static char toDigitChar(long digit) {
- return (char) (digit + '0');
- }
-
- /**
- * Format a date / time such that if the then is on the same day as now, it shows
- * just the time and if it's a different day, it shows just the date.
- *
- * <p>The parameters dateFormat and timeFormat should each be one of
- * {@link java.text.DateFormat#DEFAULT},
- * {@link java.text.DateFormat#FULL},
- * {@link java.text.DateFormat#LONG},
- * {@link java.text.DateFormat#MEDIUM}
- * or
- * {@link java.text.DateFormat#SHORT}
- *
- * @param then the date to format
- * @param now the base time
- * @param dateStyle how to format the date portion.
- * @param timeStyle how to format the time portion.
- */
- public static final CharSequence formatSameDayTime(long then, long now,
- int dateStyle, int timeStyle) {
- Calendar thenCal = new GregorianCalendar();
- thenCal.setTimeInMillis(then);
- Date thenDate = thenCal.getTime();
- Calendar nowCal = new GregorianCalendar();
- nowCal.setTimeInMillis(now);
-
- java.text.DateFormat f;
-
- if (thenCal.get(Calendar.YEAR) == nowCal.get(Calendar.YEAR)
- && thenCal.get(Calendar.MONTH) == nowCal.get(Calendar.MONTH)
- && thenCal.get(Calendar.DAY_OF_MONTH) == nowCal.get(Calendar.DAY_OF_MONTH)) {
- f = java.text.DateFormat.getTimeInstance(timeStyle);
- } else {
- f = java.text.DateFormat.getDateInstance(dateStyle);
- }
- return f.format(thenDate);
- }
-
- /**
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static Calendar newCalendar(boolean zulu)
- {
- if (zulu)
- return Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-
- return Calendar.getInstance();
- }
-
- /**
- * @return true if the supplied when is today else false
- */
- public static boolean isToday(long when) {
- Time time = new Time();
- time.set(when);
-
- int thenYear = time.year;
- int thenMonth = time.month;
- int thenMonthDay = time.monthDay;
-
- time.set(System.currentTimeMillis());
- return (thenYear == time.year)
- && (thenMonth == time.month)
- && (thenMonthDay == time.monthDay);
- }
-
- /**
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- private static final int ctoi(String str, int index)
- throws DateException
- {
- char c = str.charAt(index);
- if (c >= '0' && c <= '9') {
- return (int)(c - '0');
- }
- throw new DateException("Expected numeric character. Got '" +
- c + "'");
- }
-
- /**
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- private static final int check(int lowerBound, int upperBound, int value)
- throws DateException
- {
- if (value >= lowerBound && value <= upperBound) {
- return value;
- }
- throw new DateException("field out of bounds. max=" + upperBound
- + " value=" + value);
- }
-
- /**
- * @hide
- * @deprecated use {@link android.text.format.Time}
- * Return true if this date string is local time
- */
- public static boolean isUTC(String s)
- {
- if (s.length() == 16 && s.charAt(15) == 'Z') {
- return true;
- }
- if (s.length() == 9 && s.charAt(8) == 'Z') {
- // XXX not sure if this case possible/valid
- return true;
- }
- return false;
- }
-
-
- // note that month in Calendar is 0 based and in all other human
- // representations, it's 1 based.
- // Returns if the Z was present, meaning that the time is in UTC
- /**
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static boolean parseDateTime(String str, Calendar cal)
- throws DateException
- {
- int len = str.length();
- boolean dateTime = (len == 15 || len == 16) && str.charAt(8) == 'T';
- boolean justDate = len == 8;
- if (dateTime || justDate) {
- cal.clear();
- cal.set(Calendar.YEAR,
- ctoi(str, 0)*1000 + ctoi(str, 1)*100
- + ctoi(str, 2)*10 + ctoi(str, 3));
- cal.set(Calendar.MONTH,
- check(0, 11, ctoi(str, 4)*10 + ctoi(str, 5) - 1));
- cal.set(Calendar.DAY_OF_MONTH,
- check(1, 31, ctoi(str, 6)*10 + ctoi(str, 7)));
- if (dateTime) {
- cal.set(Calendar.HOUR_OF_DAY,
- check(0, 23, ctoi(str, 9)*10 + ctoi(str, 10)));
- cal.set(Calendar.MINUTE,
- check(0, 59, ctoi(str, 11)*10 + ctoi(str, 12)));
- cal.set(Calendar.SECOND,
- check(0, 59, ctoi(str, 13)*10 + ctoi(str, 14)));
- }
- if (justDate) {
- cal.set(Calendar.HOUR_OF_DAY, 0);
- cal.set(Calendar.MINUTE, 0);
- cal.set(Calendar.SECOND, 0);
- return true;
- }
- if (len == 15) {
- return false;
- }
- if (str.charAt(15) == 'Z') {
- return true;
- }
- }
- throw new DateException("Invalid time (expected "
- + "YYYYMMDDThhmmssZ? got '" + str + "').");
- }
-
- /**
- * Given a timezone string which can be null, and a dateTime string,
- * set that time into a calendar.
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static void parseDateTime(String tz, String dateTime, Calendar out)
- throws DateException
- {
- TimeZone timezone;
- if (DateUtils.isUTC(dateTime)) {
- timezone = TimeZone.getTimeZone("UTC");
- }
- else if (tz == null) {
- timezone = TimeZone.getDefault();
- }
- else {
- timezone = TimeZone.getTimeZone(tz);
- }
-
- Calendar local = new GregorianCalendar(timezone);
- DateUtils.parseDateTime(dateTime, local);
-
- out.setTimeInMillis(local.getTimeInMillis());
- }
-
-
- /**
- * Return a string containing the date and time in RFC2445 format.
- * Ensures that the time is written in UTC. The Calendar class doesn't
- * really help out with this, so this is slower than it ought to be.
- *
- * @param cal the date and time to write
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static String writeDateTime(Calendar cal)
- {
- TimeZone tz = TimeZone.getTimeZone("GMT");
- GregorianCalendar c = new GregorianCalendar(tz);
- c.setTimeInMillis(cal.getTimeInMillis());
- return writeDateTime(c, true);
- }
-
- /**
- * Return a string containing the date and time in RFC2445 format.
- *
- * @param cal the date and time to write
- * @param zulu If the calendar is in UTC, pass true, and a Z will
- * be written at the end as per RFC2445. Otherwise, the time is
- * considered in localtime.
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static String writeDateTime(Calendar cal, boolean zulu)
- {
- StringBuilder sb = new StringBuilder();
- sb.ensureCapacity(16);
- if (zulu) {
- sb.setLength(16);
- sb.setCharAt(15, 'Z');
- } else {
- sb.setLength(15);
- }
- return writeDateTime(cal, sb);
- }
-
- /**
- * Return a string containing the date and time in RFC2445 format.
- *
- * @param cal the date and time to write
- * @param sb a StringBuilder to use. It is assumed that setLength
- * has already been called on sb to the appropriate length
- * which is sb.setLength(zulu ? 16 : 15)
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static String writeDateTime(Calendar cal, StringBuilder sb)
- {
- int n;
-
- n = cal.get(Calendar.YEAR);
- sb.setCharAt(3, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(2, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(1, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(0, (char)('0'+n%10));
-
- n = cal.get(Calendar.MONTH) + 1;
- sb.setCharAt(5, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(4, (char)('0'+n%10));
-
- n = cal.get(Calendar.DAY_OF_MONTH);
- sb.setCharAt(7, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(6, (char)('0'+n%10));
-
- sb.setCharAt(8, 'T');
-
- n = cal.get(Calendar.HOUR_OF_DAY);
- sb.setCharAt(10, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(9, (char)('0'+n%10));
-
- n = cal.get(Calendar.MINUTE);
- sb.setCharAt(12, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(11, (char)('0'+n%10));
-
- n = cal.get(Calendar.SECOND);
- sb.setCharAt(14, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(13, (char)('0'+n%10));
-
- return sb.toString();
- }
-
- /**
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static void assign(Calendar lval, Calendar rval)
- {
- // there should be a faster way.
- lval.clear();
- lval.setTimeInMillis(rval.getTimeInMillis());
- }
-
- /**
- * Formats a date or a time range according to the local conventions.
- *
- * <p>
- * Example output strings (date formats in these examples are shown using
- * the US date format convention but that may change depending on the
- * local settings):
- * <ul>
- * <li>10:15am</li>
- * <li>3:00pm - 4:00pm</li>
- * <li>3pm - 4pm</li>
- * <li>3PM - 4PM</li>
- * <li>08:00 - 17:00</li>
- * <li>Oct 9</li>
- * <li>Tue, Oct 9</li>
- * <li>October 9, 2007</li>
- * <li>Oct 9 - 10</li>
- * <li>Oct 9 - 10, 2007</li>
- * <li>Oct 28 - Nov 3, 2007</li>
- * <li>Dec 31, 2007 - Jan 1, 2008</li>
- * <li>Oct 9, 8:00am - Oct 10, 5:00pm</li>
- * <li>12/31/2007 - 01/01/2008</li>
- * </ul>
- *
- * <p>
- * The flags argument is a bitmask of options from the following list:
- *
- * <ul>
- * <li>FORMAT_SHOW_TIME</li>
- * <li>FORMAT_SHOW_WEEKDAY</li>
- * <li>FORMAT_SHOW_YEAR</li>
- * <li>FORMAT_NO_YEAR</li>
- * <li>FORMAT_SHOW_DATE</li>
- * <li>FORMAT_NO_MONTH_DAY</li>
- * <li>FORMAT_12HOUR</li>
- * <li>FORMAT_24HOUR</li>
- * <li>FORMAT_CAP_AMPM</li>
- * <li>FORMAT_NO_NOON</li>
- * <li>FORMAT_CAP_NOON</li>
- * <li>FORMAT_NO_MIDNIGHT</li>
- * <li>FORMAT_CAP_MIDNIGHT</li>
- * <li>FORMAT_UTC</li>
- * <li>FORMAT_ABBREV_TIME</li>
- * <li>FORMAT_ABBREV_WEEKDAY</li>
- * <li>FORMAT_ABBREV_MONTH</li>
- * <li>FORMAT_ABBREV_ALL</li>
- * <li>FORMAT_NUMERIC_DATE</li>
- * </ul>
- *
- * <p>
- * If FORMAT_SHOW_TIME is set, the time is shown as part of the date range.
- * If the start and end time are the same, then just the start time is
- * shown.
- *
- * <p>
- * If FORMAT_SHOW_WEEKDAY is set, then the weekday is shown.
- *
- * <p>
- * If FORMAT_SHOW_YEAR is set, then the year is always shown.
- * If FORMAT_NO_YEAR is set, then the year is not shown.
- * If neither FORMAT_SHOW_YEAR nor FORMAT_NO_YEAR are set, then the year
- * is shown only if it is different from the current year, or if the start
- * and end dates fall on different years.
- *
- * <p>
- * Normally the date is shown unless the start and end day are the same.
- * If FORMAT_SHOW_DATE is set, then the date is always shown, even for
- * same day ranges.
- *
- * <p>
- * If FORMAT_NO_MONTH_DAY is set, then if the date is shown, just the
- * month name will be shown, not the day of the month. For example,
- * "January, 2008" instead of "January 6 - 12, 2008".
- *
- * <p>
- * If FORMAT_CAP_AMPM is set and 12-hour time is used, then the "AM"
- * and "PM" are capitalized.
- *
- * <p>
- * If FORMAT_NO_NOON is set and 12-hour time is used, then "12pm" is
- * shown instead of "noon".
- *
- * <p>
- * If FORMAT_CAP_NOON is set and 12-hour time is used, then "Noon" is
- * shown instead of "noon".
- *
- * <p>
- * If FORMAT_NO_MIDNIGHT is set and 12-hour time is used, then "12am" is
- * shown instead of "midnight".
- *
- * <p>
- * If FORMAT_CAP_NOON is set and 12-hour time is used, then "Midnight" is
- * shown instead of "midnight".
- *
- * <p>
- * If FORMAT_12HOUR is set and the time is shown, then the time is
- * shown in the 12-hour time format. You should not normally set this.
- * Instead, let the time format be chosen automatically according to the
- * system settings. If both FORMAT_12HOUR and FORMAT_24HOUR are set, then
- * FORMAT_24HOUR takes precedence.
- *
- * <p>
- * If FORMAT_24HOUR is set and the time is shown, then the time is
- * shown in the 24-hour time format. You should not normally set this.
- * Instead, let the time format be chosen automatically according to the
- * system settings. If both FORMAT_12HOUR and FORMAT_24HOUR are set, then
- * FORMAT_24HOUR takes precedence.
- *
- * <p>
- * If FORMAT_UTC is set, then the UTC timezone is used for the start
- * and end milliseconds.
- *
- * <p>
- * If FORMAT_ABBREV_TIME is set and 12-hour time format is used, then the
- * start and end times (if shown) are abbreviated by not showing the minutes
- * if they are zero. For example, instead of "3:00pm" the time would be
- * abbreviated to "3pm".
- *
- * <p>
- * If FORMAT_ABBREV_WEEKDAY is set, then the weekday (if shown) is
- * abbreviated to a 3-letter string.
- *
- * <p>
- * If FORMAT_ABBREV_MONTH is set, then the month (if shown) is abbreviated
- * to a 3-letter string.
- *
- * <p>
- * If FORMAT_ABBREV_ALL is set, then the weekday and the month (if shown)
- * are abbreviated to 3-letter strings.
- *
- * <p>
- * If FORMAT_NUMERIC_DATE is set, then the date is shown in numeric format
- * instead of using the name of the month. For example, "12/31/2008"
- * instead of "December 31, 2008".
- *
- * @param context the context is required only if the time is shown
- * @param startMillis the start time in UTC milliseconds
- * @param endMillis the end time in UTC milliseconds
- * @param flags a bit mask of options
- *
- * @return a string containing the formatted date/time range.
- */
- public static String formatDateRange(Context context, long startMillis,
- long endMillis, int flags) {
- Resources res = Resources.getSystem();
- boolean showTime = (flags & FORMAT_SHOW_TIME) != 0;
- boolean showWeekDay = (flags & FORMAT_SHOW_WEEKDAY) != 0;
- boolean showYear = (flags & FORMAT_SHOW_YEAR) != 0;
- boolean noYear = (flags & FORMAT_NO_YEAR) != 0;
- boolean useUTC = (flags & FORMAT_UTC) != 0;
- boolean abbrevWeekDay = (flags & (FORMAT_ABBREV_WEEKDAY | FORMAT_ABBREV_ALL)) != 0;
- boolean abbrevMonth = (flags & (FORMAT_ABBREV_MONTH | FORMAT_ABBREV_ALL)) != 0;
- boolean noMonthDay = (flags & FORMAT_NO_MONTH_DAY) != 0;
- boolean numericDate = (flags & FORMAT_NUMERIC_DATE) != 0;
-
- Time startDate;
- Time endDate;
-
- if (useUTC) {
- startDate = new Time(Time.TIMEZONE_UTC);
- endDate = new Time(Time.TIMEZONE_UTC);
- } else {
- startDate = new Time();
- endDate = new Time();
- }
-
- startDate.set(startMillis);
- endDate.set(endMillis);
- int startJulianDay = Time.getJulianDay(startMillis, startDate.gmtoff);
- int endJulianDay = Time.getJulianDay(endMillis, endDate.gmtoff);
- int dayDistance = endJulianDay - startJulianDay;
-
- // If the end date ends at 12am at the beginning of a day,
- // then modify it to make it look like it ends at midnight on
- // the previous day. This will allow us to display "8pm - midnight",
- // for example, instead of "Nov 10, 8pm - Nov 11, 12am". But we only do
- // this if it is midnight of the same day as the start date because
- // for multiple-day events, an end time of "midnight on Nov 11" is
- // ambiguous and confusing (is that midnight the start of Nov 11, or
- // the end of Nov 11?).
- // If we are not showing the time then also adjust the end date
- // for multiple-day events. This is to allow us to display, for
- // example, "Nov 10 -11" for an event with a start date of Nov 10
- // and an end date of Nov 12 at 00:00.
- // If the start and end time are the same, then skip this and don't
- // adjust the date.
- if ((endDate.hour | endDate.minute | endDate.second) == 0
- && (!showTime || dayDistance <= 1) && (startMillis != endMillis)) {
- endDate.monthDay -= 1;
- endDate.normalize(true /* ignore isDst */);
- }
-
- int startDay = startDate.monthDay;
- int startMonthNum = startDate.month;
- int startYear = startDate.year;
-
- int endDay = endDate.monthDay;
- int endMonthNum = endDate.month;
- int endYear = endDate.year;
-
- String startWeekDayString = "";
- String endWeekDayString = "";
- if (showWeekDay) {
- String weekDayFormat = "";
- if (abbrevWeekDay) {
- weekDayFormat = ABBREV_WEEKDAY_FORMAT;
- } else {
- weekDayFormat = WEEKDAY_FORMAT;
- }
- startWeekDayString = startDate.format(weekDayFormat);
- endWeekDayString = endDate.format(weekDayFormat);
- }
-
- String startTimeString = "";
- String endTimeString = "";
- if (showTime) {
- String startTimeFormat = "";
- String endTimeFormat = "";
- boolean force24Hour = (flags & FORMAT_24HOUR) != 0;
- boolean force12Hour = (flags & FORMAT_12HOUR) != 0;
- boolean use24Hour;
- if (force24Hour) {
- use24Hour = true;
- } else if (force12Hour) {
- use24Hour = false;
- } else {
- use24Hour = DateFormat.is24HourFormat(context);
- }
- if (use24Hour) {
- startTimeFormat = HOUR_MINUTE_24;
- endTimeFormat = HOUR_MINUTE_24;
- } else {
- boolean abbrevTime = (flags & (FORMAT_ABBREV_TIME | FORMAT_ABBREV_ALL)) != 0;
- boolean capAMPM = (flags & FORMAT_CAP_AMPM) != 0;
- boolean noNoon = (flags & FORMAT_NO_NOON) != 0;
- boolean capNoon = (flags & FORMAT_CAP_NOON) != 0;
- boolean noMidnight = (flags & FORMAT_NO_MIDNIGHT) != 0;
- boolean capMidnight = (flags & FORMAT_CAP_MIDNIGHT) != 0;
-
- boolean startOnTheHour = startDate.minute == 0 && startDate.second == 0;
- boolean endOnTheHour = endDate.minute == 0 && endDate.second == 0;
- if (abbrevTime && startOnTheHour) {
- if (capAMPM) {
- startTimeFormat = res.getString(com.android.internal.R.string.hour_cap_ampm);
- } else {
- startTimeFormat = res.getString(com.android.internal.R.string.hour_ampm);
- }
- } else {
- if (capAMPM) {
- startTimeFormat = res.getString(com.android.internal.R.string.hour_minute_cap_ampm);
- } else {
- startTimeFormat = res.getString(com.android.internal.R.string.hour_minute_ampm);
- }
- }
- if (abbrevTime && endOnTheHour) {
- if (capAMPM) {
- endTimeFormat = res.getString(com.android.internal.R.string.hour_cap_ampm);
- } else {
- endTimeFormat = res.getString(com.android.internal.R.string.hour_ampm);
- }
- } else {
- if (capAMPM) {
- endTimeFormat = res.getString(com.android.internal.R.string.hour_minute_cap_ampm);
- } else {
- endTimeFormat = res.getString(com.android.internal.R.string.hour_minute_ampm);
- }
- }
-
- if (startDate.hour == 12 && startOnTheHour && !noNoon) {
- if (capNoon) {
- startTimeFormat = res.getString(com.android.internal.R.string.Noon);
- } else {
- startTimeFormat = res.getString(com.android.internal.R.string.noon);
- }
- // Don't show the start time starting at midnight. Show
- // 12am instead.
- }
-
- if (endDate.hour == 12 && endOnTheHour && !noNoon) {
- if (capNoon) {
- endTimeFormat = res.getString(com.android.internal.R.string.Noon);
- } else {
- endTimeFormat = res.getString(com.android.internal.R.string.noon);
- }
- } else if (endDate.hour == 0 && endOnTheHour && !noMidnight) {
- if (capMidnight) {
- endTimeFormat = res.getString(com.android.internal.R.string.Midnight);
- } else {
- endTimeFormat = res.getString(com.android.internal.R.string.midnight);
- }
- }
- }
- startTimeString = startDate.format(startTimeFormat);
- endTimeString = endDate.format(endTimeFormat);
- }
-
- // Get the current year
- long millis = System.currentTimeMillis();
- Time time = new Time();
- time.set(millis);
- int currentYear = time.year;
-
- // Show the year if the user specified FORMAT_SHOW_YEAR or if
- // the starting and end years are different from each other
- // or from the current year. But don't show the year if the
- // user specified FORMAT_NO_YEAR;
- showYear = showYear || (!noYear && (startYear != endYear || startYear != currentYear));
-
- String defaultDateFormat, fullFormat, dateRange;
- if (numericDate) {
- defaultDateFormat = res.getString(com.android.internal.R.string.numeric_date);
- } else if (showYear) {
- if (abbrevMonth) {
- if (noMonthDay) {
- defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month_year);
- } else {
- defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month_day_year);
- }
- } else {
- if (noMonthDay) {
- defaultDateFormat = res.getString(com.android.internal.R.string.month_year);
- } else {
- defaultDateFormat = res.getString(com.android.internal.R.string.month_day_year);
- }
- }
- } else {
- if (abbrevMonth) {
- if (noMonthDay) {
- defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month);
- } else {
- defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month_day);
- }
- } else {
- if (noMonthDay) {
- defaultDateFormat = res.getString(com.android.internal.R.string.month);
- } else {
- defaultDateFormat = res.getString(com.android.internal.R.string.month_day);
- }
- }
- }
-
- if (showWeekDay) {
- if (showTime) {
- fullFormat = res.getString(com.android.internal.R.string.wday1_date1_time1_wday2_date2_time2);
- } else {
- fullFormat = res.getString(com.android.internal.R.string.wday1_date1_wday2_date2);
- }
- } else {
- if (showTime) {
- fullFormat = res.getString(com.android.internal.R.string.date1_time1_date2_time2);
- } else {
- fullFormat = res.getString(com.android.internal.R.string.date1_date2);
- }
- }
-
- if (noMonthDay && startMonthNum == endMonthNum) {
- // Example: "January, 2008"
- String startDateString = startDate.format(defaultDateFormat);
- return startDateString;
- }
-
- if (startYear != endYear || noMonthDay) {
- // Different year or we are not showing the month day number.
- // Example: "December 31, 2007 - January 1, 2008"
- // Or: "January - February, 2008"
- String startDateString = startDate.format(defaultDateFormat);
- String endDateString = endDate.format(defaultDateFormat);
-
- // The values that are used in a fullFormat string are specified
- // by position.
- dateRange = String.format(fullFormat,
- startWeekDayString, startDateString, startTimeString,
- endWeekDayString, endDateString, endTimeString);
- return dateRange;
- }
-
- // Get the month, day, and year strings for the start and end dates
- String monthFormat;
- if (numericDate) {
- monthFormat = NUMERIC_MONTH_FORMAT;
- } else if (abbrevMonth) {
- monthFormat = ABBREV_MONTH_FORMAT;
- } else {
- monthFormat = MONTH_FORMAT;
- }
- String startMonthString = startDate.format(monthFormat);
- String startMonthDayString = startDate.format(MONTH_DAY_FORMAT);
- String startYearString = startDate.format(YEAR_FORMAT);
- String endMonthString = endDate.format(monthFormat);
- String endMonthDayString = endDate.format(MONTH_DAY_FORMAT);
- String endYearString = endDate.format(YEAR_FORMAT);
-
- if (startMonthNum != endMonthNum) {
- // Same year, different month.
- // Example: "October 28 - November 3"
- // or: "Wed, Oct 31 - Sat, Nov 3, 2007"
- // or: "Oct 31, 8am - Sat, Nov 3, 2007, 5pm"
-
- int index = 0;
- if (showWeekDay) index = 1;
- if (showYear) index += 2;
- if (showTime) index += 4;
- if (numericDate) index += 8;
- int resId = sameYearTable[index];
- fullFormat = res.getString(resId);
-
- // The values that are used in a fullFormat string are specified
- // by position.
- dateRange = String.format(fullFormat,
- startWeekDayString, startMonthString, startMonthDayString,
- startYearString, startTimeString,
- endWeekDayString, endMonthString, endMonthDayString,
- endYearString, endTimeString);
- return dateRange;
- }
-
- if (startDay != endDay) {
- // Same month, different day.
- int index = 0;
- if (showWeekDay) index = 1;
- if (showYear) index += 2;
- if (showTime) index += 4;
- if (numericDate) index += 8;
- int resId = sameMonthTable[index];
- fullFormat = res.getString(resId);
-
- // The values that are used in a fullFormat string are specified
- // by position.
- dateRange = String.format(fullFormat,
- startWeekDayString, startMonthString, startMonthDayString,
- startYearString, startTimeString,
- endWeekDayString, endMonthString, endMonthDayString,
- endYearString, endTimeString);
- return dateRange;
- }
-
- // Same start and end day
- boolean showDate = (flags & FORMAT_SHOW_DATE) != 0;
-
- // If nothing was specified, then show the date.
- if (!showTime && !showDate && !showWeekDay) showDate = true;
-
- // Compute the time string (example: "10:00 - 11:00 am")
- String timeString = "";
- if (showTime) {
- // If the start and end time are the same, then just show the
- // start time.
- if (startMillis == endMillis) {
- // Same start and end time.
- // Example: "10:15 AM"
- timeString = startTimeString;
- } else {
- // Example: "10:00 - 11:00 am"
- String timeFormat = res.getString(com.android.internal.R.string.time1_time2);
- timeString = String.format(timeFormat, startTimeString, endTimeString);
- }
- }
-
- // Figure out which full format to use.
- fullFormat = "";
- String dateString = "";
- if (showDate) {
- dateString = startDate.format(defaultDateFormat);
- if (showWeekDay) {
- if (showTime) {
- // Example: "10:00 - 11:00 am, Tue, Oct 9"
- fullFormat = res.getString(com.android.internal.R.string.time_wday_date);
- } else {
- // Example: "Tue, Oct 9"
- fullFormat = res.getString(com.android.internal.R.string.wday_date);
- }
- } else {
- if (showTime) {
- // Example: "10:00 - 11:00 am, Oct 9"
- fullFormat = res.getString(com.android.internal.R.string.time_date);
- } else {
- // Example: "Oct 9"
- return dateString;
- }
- }
- } else if (showWeekDay) {
- if (showTime) {
- // Example: "10:00 - 11:00 am, Tue"
- fullFormat = res.getString(com.android.internal.R.string.time_wday);
- } else {
- // Example: "Tue"
- return startWeekDayString;
- }
- } else if (showTime) {
- return timeString;
- }
-
- // The values that are used in a fullFormat string are specified
- // by position.
- dateRange = String.format(fullFormat, timeString, startWeekDayString, dateString);
- return dateRange;
- }
-
- /**
- * Formats a date or a time according to the local conventions. There are
- * lots of options that allow the caller to control, for example, if the
- * time is shown, if the day of the week is shown, if the month name is
- * abbreviated, if noon is shown instead of 12pm, and so on. For the
- * complete list of options, see the documentation for
- * {@link #formatDateRange}.
- * <p>
- * Example output strings (date formats in these examples are shown using
- * the US date format convention but that may change depending on the
- * local settings):
- * <ul>
- * <li>10:15am</li>
- * <li>3:00pm</li>
- * <li>3pm</li>
- * <li>3PM</li>
- * <li>08:00</li>
- * <li>17:00</li>
- * <li>noon</li>
- * <li>Noon</li>
- * <li>midnight</li>
- * <li>Midnight</li>
- * <li>Oct 31</li>
- * <li>Oct 31, 2007</li>
- * <li>October 31, 2007</li>
- * <li>10am, Oct 31</li>
- * <li>17:00, Oct 31</li>
- * <li>Wed</li>
- * <li>Wednesday</li>
- * <li>10am, Wed, Oct 31</li>
- * <li>Wed, Oct 31</li>
- * <li>Wednesday, Oct 31</li>
- * <li>Wed, Oct 31, 2007</li>
- * <li>Wed, October 31</li>
- * <li>10/31/2007</li>
- * </ul>
- *
- * @param context the context is required only if the time is shown
- * @param millis a point in time in UTC milliseconds
- * @param flags a bit mask of formatting options
- * @return a string containing the formatted date/time.
- */
- public static String formatDateTime(Context context, long millis, int flags) {
- return formatDateRange(context, millis, millis, flags);
- }
-
- /**
- * @return a relative time string to display the time expressed by millis. Times
- * are counted starting at midnight, which means that assuming that the current
- * time is March 31st, 0:30:
- * <ul>
- * <li>"millis=0:10 today" will be displayed as "0:10"</li>
- * <li>"millis=11:30pm the day before" will be displayed as "Mar 30"</li>
- * </ul>
- * If the given millis is in a different year, then the full date is
- * returned in numeric format (e.g., "10/12/2008").
- *
- * @param withPreposition If true, the string returned will include the correct
- * preposition ("at 9:20am", "on 10/12/2008" or "on May 29").
- */
- public static CharSequence getRelativeTimeSpanString(Context c, long millis,
- boolean withPreposition) {
-
- long now = System.currentTimeMillis();
- long span = now - millis;
-
- if (sNowTime == null) {
- sNowTime = new Time();
- sThenTime = new Time();
- }
-
- sNowTime.set(now);
- sThenTime.set(millis);
-
- String result;
- int prepositionId;
- if (span < DAY_IN_MILLIS && sNowTime.weekDay == sThenTime.weekDay) {
- // Same day
- int flags = FORMAT_SHOW_TIME;
- result = formatDateRange(c, millis, millis, flags);
- prepositionId = R.string.preposition_for_time;
- } else if (sNowTime.year != sThenTime.year) {
- // Different years
- int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE;
- result = formatDateRange(c, millis, millis, flags);
-
- // This is a date (like "10/31/2008" so use the date preposition)
- prepositionId = R.string.preposition_for_date;
- } else {
- // Default
- int flags = FORMAT_SHOW_DATE | FORMAT_ABBREV_MONTH;
- result = formatDateRange(c, millis, millis, flags);
- prepositionId = R.string.preposition_for_date;
- }
- if (withPreposition) {
- Resources res = c.getResources();
- result = res.getString(prepositionId, result);
- }
- return result;
- }
-
- /**
- * Convenience function to return relative time string without preposition.
- * @param c context for resources
- * @param millis time in milliseconds
- * @return {@link CharSequence} containing relative time.
- * @see #getRelativeTimeSpanString(Context, long, boolean)
- */
- public static CharSequence getRelativeTimeSpanString(Context c, long millis) {
- return getRelativeTimeSpanString(c, millis, false /* no preposition */);
- }
-
- private static Time sNowTime;
- private static Time sThenTime;
-}
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
deleted file mode 100644
index 1b30aa0..0000000
--- a/core/java/android/text/format/Formatter.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.format;
-
-import android.content.Context;
-
-/**
- * Utility class to aid in formatting common values that are not covered
- * by the standard java.util.Formatter.
- */
-public final class Formatter {
-
- /**
- * Formats a content size to be in the form of bytes, kilobytes, megabytes, etc
- *
- * @param context Context to use to load the localized units
- * @param number size value to be formated
- * @return formated string with the number
- */
- public static String formatFileSize(Context context, long number) {
- if (context == null) {
- return "";
- }
-
- float result = number;
- int suffix = com.android.internal.R.string.byteShort;
- if (result > 900) {
- suffix = com.android.internal.R.string.kilobyteShort;
- result = result / 1024;
- }
- if (result > 900) {
- suffix = com.android.internal.R.string.megabyteShort;
- result = result / 1024;
- }
- if (result > 900) {
- suffix = com.android.internal.R.string.gigabyteShort;
- result = result / 1024;
- }
- if (result > 900) {
- suffix = com.android.internal.R.string.terabyteShort;
- result = result / 1024;
- }
- if (result > 900) {
- suffix = com.android.internal.R.string.petabyteShort;
- result = result / 1024;
- }
- if (result < 100) {
- return String.format("%.2f%s", result, context.getText(suffix).toString());
- }
- return String.format("%.0f%s", result, context.getText(suffix).toString());
- }
-
- /**
- * Returns a string in the canonical IP format ###.###.###.### from a packed integer containing
- * the IP address. The IP address is expected to be in little-endian format (LSB first). That
- * is, 0x01020304 will return "4.3.2.1".
- *
- * @param addr the IP address as a packed integer with LSB first.
- * @return string with canonical IP address format.
- */
- public static String formatIpAddress(int addr) {
- StringBuffer buf = new StringBuffer();
- buf.append(addr & 0xff).append('.').
- append((addr >>>= 8) & 0xff).append('.').
- append((addr >>>= 8) & 0xff).append('.').
- append((addr >>>= 8) & 0xff);
- return buf.toString();
- }
-}
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
deleted file mode 100644
index daa99c2..0000000
--- a/core/java/android/text/format/Time.java
+++ /dev/null
@@ -1,757 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.format;
-
-import android.content.res.Resources;
-
-import java.util.Locale;
-import java.util.TimeZone;
-
-/**
- * The Time class is a faster replacement for the java.util.Calendar and
- * java.util.GregorianCalendar classes. An instance of the Time class represents
- * a moment in time, specified with second precision. It is modelled after
- * struct tm, and in fact, uses struct tm to implement most of the
- * functionality.
- */
-public class Time {
- private static final String Y_M_D_T_H_M_S_000 = "%Y-%m-%dT%H:%M:%S.000";
- private static final String Y_M_D_T_H_M_S_000_Z = "%Y-%m-%dT%H:%M:%S.000Z";
- private static final String Y_M_D = "%Y-%m-%d";
-
- public static final String TIMEZONE_UTC = "UTC";
-
- /**
- * The Julian day of the epoch, that is, January 1, 1970 on the Gregorian
- * calendar.
- */
- public static final int EPOCH_JULIAN_DAY = 2440588;
-
- /**
- * True if this is an allDay event. The hour, minute, second fields are
- * all zero, and the date is displayed the same in all time zones.
- */
- public boolean allDay;
-
- /**
- * Seconds [0-61] (2 leap seconds allowed)
- */
- public int second;
-
- /**
- * Minute [0-59]
- */
- public int minute;
-
- /**
- * Hour of day [0-23]
- */
- public int hour;
-
- /**
- * Day of month [1-31]
- */
- public int monthDay;
-
- /**
- * Month [0-11]
- */
- public int month;
-
- /**
- * Year. TBD. Is this years since 1900 like in struct tm?
- */
- public int year;
-
- /**
- * Day of week [0-6]
- */
- public int weekDay;
-
- /**
- * Day of year [0-365]
- */
- public int yearDay;
-
- /**
- * This time is in daylight savings time. One of:
- * <ul>
- * <li><b>positive</b> - in dst</li>
- * <li><b>0</b> - not in dst</li>
- * <li><b>negative</b> - unknown</li>
- * </ul>
- */
- public int isDst;
-
- /**
- * Offset from UTC (in seconds).
- */
- public long gmtoff;
-
- /**
- * The timezone for this Time. Should not be null.
- */
- public String timezone;
-
- /*
- * Define symbolic constants for accessing the fields in this class. Used in
- * getActualMaximum().
- */
- public static final int SECOND = 1;
- public static final int MINUTE = 2;
- public static final int HOUR = 3;
- public static final int MONTH_DAY = 4;
- public static final int MONTH = 5;
- public static final int YEAR = 6;
- public static final int WEEK_DAY = 7;
- public static final int YEAR_DAY = 8;
- public static final int WEEK_NUM = 9;
-
- public static final int SUNDAY = 0;
- public static final int MONDAY = 1;
- public static final int TUESDAY = 2;
- public static final int WEDNESDAY = 3;
- public static final int THURSDAY = 4;
- public static final int FRIDAY = 5;
- public static final int SATURDAY = 6;
-
- /*
- * The Locale for which date formatting strings have been loaded.
- */
- private static Locale sLocale;
- private static String[] sShortMonths;
- private static String[] sLongMonths;
- private static String[] sShortWeekdays;
- private static String[] sLongWeekdays;
- private static String sTimeOnlyFormat;
- private static String sDateOnlyFormat;
- private static String sDateTimeFormat;
- private static String sAm;
- private static String sPm;
- private static String sDateCommand = "%a %b %e %H:%M:%S %Z %Y";
-
- /**
- * Construct a Time object in the timezone named by the string
- * argument "timezone". The time is initialized to Jan 1, 1970.
- * @param timezone string containing the timezone to use.
- * @see TimeZone
- */
- public Time(String timezone) {
- if (timezone == null) {
- throw new NullPointerException("timezone is null!");
- }
- this.timezone = timezone;
- this.year = 1970;
- this.monthDay = 1;
- // Set the daylight-saving indicator to the unknown value -1 so that
- // it will be recomputed.
- this.isDst = -1;
- }
-
- /**
- * Construct a Time object in the default timezone. The time is initialized to
- * Jan 1, 1970.
- */
- public Time() {
- this(TimeZone.getDefault().getID());
- }
-
- /**
- * A copy constructor. Construct a Time object by copying the given
- * Time object. No normalization occurs.
- *
- * @param other
- */
- public Time(Time other) {
- set(other);
- }
-
- /**
- * Ensures the values in each field are in range. For example if the
- * current value of this calendar is March 32, normalize() will convert it
- * to April 1. It also fills in weekDay, yearDay, isDst and gmtoff.
- *
- * <p>
- * If "ignoreDst" is true, then this method sets the "isDst" field to -1
- * (the "unknown" value) before normalizing. It then computes the
- * correct value for "isDst".
- *
- * <p>
- * See {@link #toMillis(boolean)} for more information about when to
- * use <tt>true</tt> or <tt>false</tt> for "ignoreDst".
- *
- * @return the UTC milliseconds since the epoch
- */
- native public long normalize(boolean ignoreDst);
-
- /**
- * Convert this time object so the time represented remains the same, but is
- * instead located in a different timezone. This method automatically calls
- * normalize() in some cases
- */
- native public void switchTimezone(String timezone);
-
- private static final int[] DAYS_PER_MONTH = { 31, 28, 31, 30, 31, 30, 31,
- 31, 30, 31, 30, 31 };
-
- /**
- * Return the maximum possible value for the given field given the value of
- * the other fields. Requires that it be normalized for MONTH_DAY and
- * YEAR_DAY.
- * @param field one of the constants for HOUR, MINUTE, SECOND, etc.
- * @return the maximum value for the field.
- */
- public int getActualMaximum(int field) {
- switch (field) {
- case SECOND:
- return 59; // leap seconds, bah humbug
- case MINUTE:
- return 59;
- case HOUR:
- return 23;
- case MONTH_DAY: {
- int n = DAYS_PER_MONTH[this.month];
- if (n != 28) {
- return n;
- } else {
- int y = this.year;
- return ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0)) ? 29 : 28;
- }
- }
- case MONTH:
- return 11;
- case YEAR:
- return 2037;
- case WEEK_DAY:
- return 6;
- case YEAR_DAY: {
- int y = this.year;
- // Year days are numbered from 0, so the last one is usually 364.
- return ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0)) ? 365 : 364;
- }
- case WEEK_NUM:
- throw new RuntimeException("WEEK_NUM not implemented");
- default:
- throw new RuntimeException("bad field=" + field);
- }
- }
-
- /**
- * Clears all values, setting the timezone to the given timezone. Sets isDst
- * to a negative value to mean "unknown".
- * @param timezone the timezone to use.
- */
- public void clear(String timezone) {
- if (timezone == null) {
- throw new NullPointerException("timezone is null!");
- }
- this.timezone = timezone;
- this.allDay = false;
- this.second = 0;
- this.minute = 0;
- this.hour = 0;
- this.monthDay = 0;
- this.month = 0;
- this.year = 0;
- this.weekDay = 0;
- this.yearDay = 0;
- this.gmtoff = 0;
- this.isDst = -1;
- }
-
- /**
- * return a negative number if a is less than b, a positive number if a is
- * greater than b, and 0 if they are equal.
- */
- native public static int compare(Time a, Time b);
-
- /**
- * Print the current value given the format string provided. See man
- * strftime for what means what. The final string must be less than 256
- * characters.
- * @param format a string containing the desired format.
- * @return a String containing the current time expressed in the current locale.
- */
- public String format(String format) {
- synchronized (Time.class) {
- Locale locale = Locale.getDefault();
-
- if (sLocale == null || locale == null || !(locale.equals(sLocale))) {
- Resources r = Resources.getSystem();
-
- sShortMonths = new String[] {
- r.getString(com.android.internal.R.string.month_medium_january),
- r.getString(com.android.internal.R.string.month_medium_february),
- r.getString(com.android.internal.R.string.month_medium_march),
- r.getString(com.android.internal.R.string.month_medium_april),
- r.getString(com.android.internal.R.string.month_medium_may),
- r.getString(com.android.internal.R.string.month_medium_june),
- r.getString(com.android.internal.R.string.month_medium_july),
- r.getString(com.android.internal.R.string.month_medium_august),
- r.getString(com.android.internal.R.string.month_medium_september),
- r.getString(com.android.internal.R.string.month_medium_october),
- r.getString(com.android.internal.R.string.month_medium_november),
- r.getString(com.android.internal.R.string.month_medium_december),
- };
- sLongMonths = new String[] {
- r.getString(com.android.internal.R.string.month_long_january),
- r.getString(com.android.internal.R.string.month_long_february),
- r.getString(com.android.internal.R.string.month_long_march),
- r.getString(com.android.internal.R.string.month_long_april),
- r.getString(com.android.internal.R.string.month_long_may),
- r.getString(com.android.internal.R.string.month_long_june),
- r.getString(com.android.internal.R.string.month_long_july),
- r.getString(com.android.internal.R.string.month_long_august),
- r.getString(com.android.internal.R.string.month_long_september),
- r.getString(com.android.internal.R.string.month_long_october),
- r.getString(com.android.internal.R.string.month_long_november),
- r.getString(com.android.internal.R.string.month_long_december),
- };
- sShortWeekdays = new String[] {
- r.getString(com.android.internal.R.string.day_of_week_medium_sunday),
- r.getString(com.android.internal.R.string.day_of_week_medium_monday),
- r.getString(com.android.internal.R.string.day_of_week_medium_tuesday),
- r.getString(com.android.internal.R.string.day_of_week_medium_wednesday),
- r.getString(com.android.internal.R.string.day_of_week_medium_thursday),
- r.getString(com.android.internal.R.string.day_of_week_medium_friday),
- r.getString(com.android.internal.R.string.day_of_week_medium_saturday),
- };
- sLongWeekdays = new String[] {
- r.getString(com.android.internal.R.string.day_of_week_long_sunday),
- r.getString(com.android.internal.R.string.day_of_week_long_monday),
- r.getString(com.android.internal.R.string.day_of_week_long_tuesday),
- r.getString(com.android.internal.R.string.day_of_week_long_wednesday),
- r.getString(com.android.internal.R.string.day_of_week_long_thursday),
- r.getString(com.android.internal.R.string.day_of_week_long_friday),
- r.getString(com.android.internal.R.string.day_of_week_long_saturday),
- };
- sTimeOnlyFormat = r.getString(com.android.internal.R.string.time_of_day);
- sDateOnlyFormat = r.getString(com.android.internal.R.string.month_day_year);
- sDateTimeFormat = r.getString(com.android.internal.R.string.date_and_time);
- sAm = r.getString(com.android.internal.R.string.am);
- sPm = r.getString(com.android.internal.R.string.pm);
-
- sLocale = locale;
- }
-
- return format1(format);
- }
- }
-
- native private String format1(String format);
-
- /**
- * Return the current time in YYYYMMDDTHHMMSS<tz> format
- */
- @Override
- native public String toString();
-
- /**
- * Parses a date-time string in either the RFC 2445 format or an abbreviated
- * format that does not include the "time" field. For example, all of the
- * following strings are valid:
- *
- * <ul>
- * <li>"20081013T160000Z"</li>
- * <li>"20081013T160000"</li>
- * <li>"20081013"</li>
- * </ul>
- *
- * Returns whether or not the time is in UTC (ends with Z). If the string
- * ends with "Z" then the timezone is set to UTC. If the date-time string
- * included only a date and no time field, then the <code>allDay</code>
- * field of this Time class is set to true and the <code>hour</code>,
- * <code>minute</code>, and <code>second</code> fields are set to zero;
- * otherwise (a time field was included in the date-time string)
- * <code>allDay</code> is set to false. The fields <code>weekDay</code>,
- * <code>yearDay</code>, and <code>gmtoff</code> are always set to zero,
- * and the field <code>isDst</code> is set to -1 (unknown). To set those
- * fields, call {@link #normalize(boolean)} after parsing.
- *
- * To parse a date-time string and convert it to UTC milliseconds, do
- * something like this:
- *
- * <pre>
- * Time time = new Time();
- * String date = "20081013T160000Z";
- * time.parse(date);
- * long millis = time.normalize(false);
- * </pre>
- *
- * @param s the string to parse
- * @return true if the resulting time value is in UTC time
- * @throws android.util.TimeFormatException if s cannot be parsed.
- */
- public boolean parse(String s) {
- if (nativeParse(s)) {
- timezone = TIMEZONE_UTC;
- return true;
- }
- return false;
- }
-
- /**
- * Parse a time in the current zone in YYYYMMDDTHHMMSS format.
- */
- native private boolean nativeParse(String s);
-
- /**
- * Parse a time in RFC 3339 format. This method also parses simple dates
- * (that is, strings that contain no time or time offset). For example,
- * all of the following strings are valid:
- *
- * <ul>
- * <li>"2008-10-13T16:00:00.000Z"</li>
- * <li>"2008-10-13T16:00:00.000+07:00"</li>
- * <li>"2008-10-13T16:00:00.000-07:00"</li>
- * <li>"2008-10-13"</li>
- * </ul>
- *
- * <p>
- * If the string contains a time and time offset, then the time offset will
- * be used to convert the time value to UTC.
- * </p>
- *
- * <p>
- * If the given string contains just a date (with no time field), then
- * the {@link #allDay} field is set to true and the {@link #hour},
- * {@link #minute}, and {@link #second} fields are set to zero.
- * </p>
- *
- * <p>
- * Returns true if the resulting time value is in UTC time.
- * </p>
- *
- * @param s the string to parse
- * @return true if the resulting time value is in UTC time
- */
- public boolean parse3339(String s) {
- if (nativeParse3339(s)) {
- timezone = TIMEZONE_UTC;
- return true;
- }
- return false;
- }
-
- native private boolean nativeParse3339(String s);
-
- /**
- * Returns the timezone string that is currently set for the device.
- */
- public static String getCurrentTimezone() {
- return TimeZone.getDefault().getID();
- }
-
- /**
- * Sets the time of the given Time object to the current time.
- */
- native public void setToNow();
-
- /**
- * Converts this time to milliseconds. Suitable for interacting with the
- * standard java libraries. The time is in UTC milliseconds since the epoch.
- * This does an implicit normalization to compute the milliseconds but does
- * <em>not</em> change any of the fields in this Time object. If you want
- * to normalize the fields in this Time object and also get the milliseconds
- * then use {@link #normalize(boolean)}.
- *
- * <p>
- * If "ignoreDst" is false, then this method uses the current setting of the
- * "isDst" field and will adjust the returned time if the "isDst" field is
- * wrong for the given time. See the sample code below for an example of
- * this.
- *
- * <p>
- * If "ignoreDst" is true, then this method ignores the current setting of
- * the "isDst" field in this Time object and will instead figure out the
- * correct value of "isDst" (as best it can) from the fields in this
- * Time object. The only case where this method cannot figure out the
- * correct value of the "isDst" field is when the time is inherently
- * ambiguous because it falls in the hour that is repeated when switching
- * from Daylight-Saving Time to Standard Time.
- *
- * <p>
- * Here is an example where <tt>toMillis(true)</tt> adjusts the time,
- * assuming that DST changes at 2am on Sunday, Nov 4, 2007.
- *
- * <pre>
- * Time time = new Time();
- * time.set(2007, 10, 4); // set the date to Nov 4, 2007, 12am
- * time.normalize(); // this sets isDst = 1
- * time.monthDay += 1; // changes the date to Nov 5, 2007, 12am
- * millis = time.toMillis(false); // millis is Nov 4, 2007, 11pm
- * millis = time.toMillis(true); // millis is Nov 5, 2007, 12am
- * </pre>
- *
- * <p>
- * To avoid this problem, use <tt>toMillis(true)</tt>
- * after adding or subtracting days or explicitly setting the "monthDay"
- * field. On the other hand, if you are adding
- * or subtracting hours or minutes, then you should use
- * <tt>toMillis(false)</tt>.
- *
- * <p>
- * You should also use <tt>toMillis(false)</tt> if you want
- * to read back the same milliseconds that you set with {@link #set(long)}
- * or {@link #set(Time)} or after parsing a date string.
- */
- native public long toMillis(boolean ignoreDst);
-
- /**
- * Sets the fields in this Time object given the UTC milliseconds. After
- * this method returns, all the fields are normalized.
- * This also sets the "isDst" field to the correct value.
- *
- * @param millis the time in UTC milliseconds since the epoch.
- */
- native public void set(long millis);
-
- /**
- * Format according to RFC 2445 DATETIME type.
- *
- * <p>
- * The same as format("%Y%m%dT%H%M%S").
- */
- native public String format2445();
-
- /**
- * Copy the value of that to this Time object. No normalization happens.
- */
- public void set(Time that) {
- this.timezone = that.timezone;
- this.allDay = that.allDay;
- this.second = that.second;
- this.minute = that.minute;
- this.hour = that.hour;
- this.monthDay = that.monthDay;
- this.month = that.month;
- this.year = that.year;
- this.weekDay = that.weekDay;
- this.yearDay = that.yearDay;
- this.isDst = that.isDst;
- this.gmtoff = that.gmtoff;
- }
-
- /**
- * Sets the fields. Sets weekDay, yearDay and gmtoff to 0, and isDst to -1.
- * Call {@link #normalize(boolean)} if you need those.
- */
- public void set(int second, int minute, int hour, int monthDay, int month, int year) {
- this.allDay = false;
- this.second = second;
- this.minute = minute;
- this.hour = hour;
- this.monthDay = monthDay;
- this.month = month;
- this.year = year;
- this.weekDay = 0;
- this.yearDay = 0;
- this.isDst = -1;
- this.gmtoff = 0;
- }
-
- /**
- * Sets the date from the given fields. Also sets allDay to true.
- * Sets weekDay, yearDay and gmtoff to 0, and isDst to -1.
- * Call {@link #normalize(boolean)} if you need those.
- *
- * @param monthDay the day of the month (in the range [1,31])
- * @param month the zero-based month number (in the range [0,11])
- * @param year the year
- */
- public void set(int monthDay, int month, int year) {
- this.allDay = true;
- this.second = 0;
- this.minute = 0;
- this.hour = 0;
- this.monthDay = monthDay;
- this.month = month;
- this.year = year;
- this.weekDay = 0;
- this.yearDay = 0;
- this.isDst = -1;
- this.gmtoff = 0;
- }
-
- /**
- * Returns true if the time represented by this Time object occurs before
- * the given time.
- *
- * @param that a given Time object to compare against
- * @return true if this time is less than the given time
- */
- public boolean before(Time that) {
- return Time.compare(this, that) < 0;
- }
-
-
- /**
- * Returns true if the time represented by this Time object occurs after
- * the given time.
- *
- * @param that a given Time object to compare against
- * @return true if this time is greater than the given time
- */
- public boolean after(Time that) {
- return Time.compare(this, that) > 0;
- }
-
- /**
- * This array is indexed by the weekDay field (SUNDAY=0, MONDAY=1, etc.)
- * and gives a number that can be added to the yearDay to give the
- * closest Thursday yearDay.
- */
- private static final int[] sThursdayOffset = { -3, 3, 2, 1, 0, -1, -2 };
-
- /**
- * Computes the week number according to ISO 8601. The current Time
- * object must already be normalized because this method uses the
- * yearDay and weekDay fields.
- *
- * <p>
- * In IS0 8601, weeks start on Monday.
- * The first week of the year (week 1) is defined by ISO 8601 as the
- * first week with four or more of its days in the starting year.
- * Or equivalently, the week containing January 4. Or equivalently,
- * the week with the year's first Thursday in it.
- * </p>
- *
- * <p>
- * The week number can be calculated by counting Thursdays. Week N
- * contains the Nth Thursday of the year.
- * </p>
- *
- * @return the ISO week number.
- */
- public int getWeekNumber() {
- // Get the year day for the closest Thursday
- int closestThursday = yearDay + sThursdayOffset[weekDay];
-
- // Year days start at 0
- if (closestThursday >= 0 && closestThursday <= 364) {
- return closestThursday / 7 + 1;
- }
-
- // The week crosses a year boundary.
- Time temp = new Time(this);
- temp.monthDay += sThursdayOffset[weekDay];
- temp.normalize(true /* ignore isDst */);
- return temp.yearDay / 7 + 1;
- }
-
- /**
- * Return a string in the RFC 3339 format.
- * <p>
- * If allDay is true, expresses the time as Y-M-D</p>
- * <p>
- * Otherwise, if the timezone is UTC, expresses the time as Y-M-D-T-H-M-S UTC</p>
- * <p>
- * Otherwise the time is expressed the time as Y-M-D-T-H-M-S +- GMT</p>
- * @param allDay
- * @return string in the RFC 3339 format.
- */
- public String format3339(boolean allDay) {
- if (allDay) {
- return format(Y_M_D);
- } else if (TIMEZONE_UTC.equals(timezone)) {
- return format(Y_M_D_T_H_M_S_000_Z);
- } else {
- String base = format(Y_M_D_T_H_M_S_000);
- String sign = (gmtoff < 0) ? "-" : "+";
- int offset = (int)Math.abs(gmtoff);
- int minutes = (offset % 3600) / 60;
- int hours = offset / 3600;
-
- return String.format("%s%s%02d:%02d", base, sign, hours, minutes);
- }
- }
-
- /**
- * Returns true if the day of the given time is the epoch on the Julian Calendar
- * (January 1, 1970 on the Gregorian calendar).
- *
- * @param time the time to test
- * @return true if epoch.
- */
- public static boolean isEpoch(Time time) {
- long millis = time.toMillis(true);
- return getJulianDay(millis, 0) == EPOCH_JULIAN_DAY;
- }
-
- /**
- * Computes the Julian day number, given the UTC milliseconds
- * and the offset (in seconds) from UTC. The Julian day for a given
- * date will be the same for every timezone. For example, the Julian
- * day for July 1, 2008 is 2454649. This is the same value no matter
- * what timezone is being used. The Julian day is useful for testing
- * if two events occur on the same day and for determining the relative
- * time of an event from the present ("yesterday", "3 days ago", etc.).
- *
- * <p>
- * Use {@link #toMillis(boolean)} to get the milliseconds.
- *
- * @param millis the time in UTC milliseconds
- * @param gmtoff the offset from UTC in seconds
- * @return the Julian day
- */
- public static int getJulianDay(long millis, long gmtoff) {
- long offsetMillis = gmtoff * 1000;
- long julianDay = (millis + offsetMillis) / DateUtils.DAY_IN_MILLIS;
- return (int) julianDay + EPOCH_JULIAN_DAY;
- }
-
- /**
- * <p>Sets the time from the given Julian day number, which must be based on
- * the same timezone that is set in this Time object. The "gmtoff" field
- * need not be initialized because the given Julian day may have a different
- * GMT offset than whatever is currently stored in this Time object anyway.
- * After this method returns all the fields will be normalized and the time
- * will be set to 12am at the beginning of the given Julian day.
- * </p>
- *
- * <p>
- * The only exception to this is if 12am does not exist for that day because
- * of daylight saving time. For example, Cairo, Eqypt moves time ahead one
- * hour at 12am on April 25, 2008 and there are a few other places that
- * also change daylight saving time at 12am. In those cases, the time
- * will be set to 1am.
- * </p>
- *
- * @param julianDay the Julian day in the timezone for this Time object
- * @return the UTC milliseconds for the beginning of the Julian day
- */
- public long setJulianDay(int julianDay) {
- // Don't bother with the GMT offset since we don't know the correct
- // value for the given Julian day. Just get close and then adjust
- // the day.
- long millis = (julianDay - EPOCH_JULIAN_DAY) * DateUtils.DAY_IN_MILLIS;
- set(millis);
-
- // Figure out how close we are to the requested Julian day.
- // We can't be off by more than a day.
- int approximateDay = getJulianDay(millis, gmtoff);
- int diff = julianDay - approximateDay;
- monthDay += diff;
-
- // Set the time to 12am and re-normalize.
- hour = 0;
- minute = 0;
- second = 0;
- millis = normalize(true);
- return millis;
- }
-}
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
deleted file mode 100644
index 6df0b35..0000000
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.util.Log;
-import android.view.KeyEvent;
-import android.text.*;
-import android.widget.TextView;
-import android.view.View;
-import android.view.MotionEvent;
-
-// XXX this doesn't extend MetaKeyKeyListener because the signatures
-// don't match. Need to figure that out. Meanwhile the meta keys
-// won't work in fields that don't take input.
-
-public class
-ArrowKeyMovementMethod
-implements MovementMethod
-{
- private boolean up(TextView widget, Spannable buffer) {
- boolean cap = (MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_SHIFT_ON) == 1) ||
- (MetaKeyKeyListener.getMetaState(buffer,
- MetaKeyKeyListener.META_SELECTING) != 0);
- boolean alt = MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_ALT_ON) == 1;
- Layout layout = widget.getLayout();
-
- if (cap) {
- if (alt) {
- Selection.extendSelection(buffer, 0);
- return true;
- } else {
- return Selection.extendUp(buffer, layout);
- }
- } else {
- if (alt) {
- Selection.setSelection(buffer, 0);
- return true;
- } else {
- return Selection.moveUp(buffer, layout);
- }
- }
- }
-
- private boolean down(TextView widget, Spannable buffer) {
- boolean cap = (MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_SHIFT_ON) == 1) ||
- (MetaKeyKeyListener.getMetaState(buffer,
- MetaKeyKeyListener.META_SELECTING) != 0);
- boolean alt = MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_ALT_ON) == 1;
- Layout layout = widget.getLayout();
-
- if (cap) {
- if (alt) {
- Selection.extendSelection(buffer, buffer.length());
- return true;
- } else {
- return Selection.extendDown(buffer, layout);
- }
- } else {
- if (alt) {
- Selection.setSelection(buffer, buffer.length());
- return true;
- } else {
- return Selection.moveDown(buffer, layout);
- }
- }
- }
-
- private boolean left(TextView widget, Spannable buffer) {
- boolean cap = (MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_SHIFT_ON) == 1) ||
- (MetaKeyKeyListener.getMetaState(buffer,
- MetaKeyKeyListener.META_SELECTING) != 0);
- boolean alt = MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_ALT_ON) == 1;
- Layout layout = widget.getLayout();
-
- if (cap) {
- if (alt) {
- return Selection.extendToLeftEdge(buffer, layout);
- } else {
- return Selection.extendLeft(buffer, layout);
- }
- } else {
- if (alt) {
- return Selection.moveToLeftEdge(buffer, layout);
- } else {
- return Selection.moveLeft(buffer, layout);
- }
- }
- }
-
- private boolean right(TextView widget, Spannable buffer) {
- boolean cap = (MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_SHIFT_ON) == 1) ||
- (MetaKeyKeyListener.getMetaState(buffer,
- MetaKeyKeyListener.META_SELECTING) != 0);
- boolean alt = MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_ALT_ON) == 1;
- Layout layout = widget.getLayout();
-
- if (cap) {
- if (alt) {
- return Selection.extendToRightEdge(buffer, layout);
- } else {
- return Selection.extendRight(buffer, layout);
- }
- } else {
- if (alt) {
- return Selection.moveToRightEdge(buffer, layout);
- } else {
- return Selection.moveRight(buffer, layout);
- }
- }
- }
-
- public boolean onKeyDown(TextView widget, Spannable buffer, int keyCode, KeyEvent event) {
- if (executeDown(widget, buffer, keyCode)) {
- MetaKeyKeyListener.adjustMetaAfterKeypress(buffer);
- MetaKeyKeyListener.resetLockedMeta(buffer);
- return true;
- }
-
- return false;
- }
-
- private boolean executeDown(TextView widget, Spannable buffer, int keyCode) {
- boolean handled = false;
-
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_UP:
- handled |= up(widget, buffer);
- break;
-
- case KeyEvent.KEYCODE_DPAD_DOWN:
- handled |= down(widget, buffer);
- break;
-
- case KeyEvent.KEYCODE_DPAD_LEFT:
- handled |= left(widget, buffer);
- break;
-
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- handled |= right(widget, buffer);
- break;
-
- case KeyEvent.KEYCODE_DPAD_CENTER:
- if (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0) {
- if (widget.showContextMenu()) {
- handled = true;
- }
- }
- }
-
- if (handled) {
- MetaKeyKeyListener.adjustMetaAfterKeypress(buffer);
- MetaKeyKeyListener.resetLockedMeta(buffer);
- }
-
- return handled;
- }
-
- public boolean onKeyUp(TextView widget, Spannable buffer, int keyCode, KeyEvent event) {
- return false;
- }
-
- public boolean onKeyOther(TextView view, Spannable text, KeyEvent event) {
- int code = event.getKeyCode();
- if (code != KeyEvent.KEYCODE_UNKNOWN
- && event.getAction() == KeyEvent.ACTION_MULTIPLE) {
- int repeat = event.getRepeatCount();
- boolean handled = false;
- while ((--repeat) > 0) {
- handled |= executeDown(view, text, code);
- }
- return handled;
- }
- return false;
- }
-
- public boolean onTrackballEvent(TextView widget, Spannable text,
- MotionEvent event) {
- return false;
- }
-
- public boolean onTouchEvent(TextView widget, Spannable buffer,
- MotionEvent event) {
- boolean handled = Touch.onTouchEvent(widget, buffer, event);
-
- if (widget.isFocused()) {
- if (event.getAction() == MotionEvent.ACTION_UP) {
- int x = (int) event.getX();
- int y = (int) event.getY();
-
- x -= widget.getTotalPaddingLeft();
- y -= widget.getTotalPaddingTop();
-
- x += widget.getScrollX();
- y += widget.getScrollY();
-
- Layout layout = widget.getLayout();
- int line = layout.getLineForVertical(y);
- int off = layout.getOffsetForHorizontal(line, x);
-
- boolean cap = (MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_SHIFT_ON) == 1) ||
- (MetaKeyKeyListener.getMetaState(buffer,
- MetaKeyKeyListener.META_SELECTING) != 0);
-
- if (cap) {
- Selection.extendSelection(buffer, off);
- } else {
- Selection.setSelection(buffer, off);
- }
-
- MetaKeyKeyListener.adjustMetaAfterKeypress(buffer);
- MetaKeyKeyListener.resetLockedMeta(buffer);
-
- return true;
- }
- }
-
- return handled;
- }
-
- public boolean canSelectArbitrarily() {
- return true;
- }
-
- public void initialize(TextView widget, Spannable text) {
- Selection.setSelection(text, 0);
- }
-
- public void onTakeFocus(TextView view, Spannable text, int dir) {
- if ((dir & (View.FOCUS_FORWARD | View.FOCUS_DOWN)) != 0) {
- Layout layout = view.getLayout();
-
- if (layout == null) {
- /*
- * This shouldn't be null, but do something sensible if it is.
- */
- Selection.setSelection(text, text.length());
- } else {
- /*
- * Put the cursor at the end of the first line, which is
- * either the last offset if there is only one line, or the
- * offset before the first character of the second line
- * if there is more than one line.
- */
- if (layout.getLineCount() == 1) {
- Selection.setSelection(text, text.length());
- } else {
- Selection.setSelection(text, layout.getLineStart(1) - 1);
- }
- }
- } else {
- Selection.setSelection(text, text.length());
- }
- }
-
- public static MovementMethod getInstance() {
- if (sInstance == null)
- sInstance = new ArrowKeyMovementMethod();
-
- return sInstance;
- }
-
- private static ArrowKeyMovementMethod sInstance;
-}
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
deleted file mode 100644
index 6df6a3a..0000000
--- a/core/java/android/text/method/BaseKeyListener.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.view.KeyEvent;
-import android.view.View;
-import android.text.*;
-import android.text.method.TextKeyListener.Capitalize;
-import android.widget.TextView;
-
-public abstract class BaseKeyListener
-extends MetaKeyKeyListener
-implements KeyListener {
- /* package */ static final Object OLD_SEL_START = new NoCopySpan.Concrete();
-
- /**
- * Performs the action that happens when you press the DEL key in
- * a TextView. If there is a selection, deletes the selection;
- * otherwise, DEL alone deletes the character before the cursor,
- * if any;
- * ALT+DEL deletes everything on the line the cursor is on.
- *
- * @return true if anything was deleted; false otherwise.
- */
- public boolean backspace(View view, Editable content, int keyCode,
- KeyEvent event) {
- int selStart, selEnd;
- boolean result = true;
-
- {
- int a = Selection.getSelectionStart(content);
- int b = Selection.getSelectionEnd(content);
-
- selStart = Math.min(a, b);
- selEnd = Math.max(a, b);
- }
-
- if (selStart != selEnd) {
- content.delete(selStart, selEnd);
- } else if (altBackspace(view, content, keyCode, event)) {
- result = true;
- } else {
- int to = TextUtils.getOffsetBefore(content, selEnd);
-
- if (to != selEnd) {
- content.delete(Math.min(to, selEnd), Math.max(to, selEnd));
- }
- else {
- result = false;
- }
- }
-
- if (result)
- adjustMetaAfterKeypress(content);
-
- return result;
- }
-
- private boolean altBackspace(View view, Editable content, int keyCode,
- KeyEvent event) {
- if (getMetaState(content, META_ALT_ON) != 1) {
- return false;
- }
-
- if (!(view instanceof TextView)) {
- return false;
- }
-
- Layout layout = ((TextView) view).getLayout();
-
- if (layout == null) {
- return false;
- }
-
- int l = layout.getLineForOffset(Selection.getSelectionStart(content));
- int start = layout.getLineStart(l);
- int end = layout.getLineEnd(l);
-
- if (end == start) {
- return false;
- }
-
- content.delete(start, end);
- return true;
- }
-
- static int makeTextContentType(Capitalize caps, boolean autoText) {
- int contentType = InputType.TYPE_CLASS_TEXT;
- switch (caps) {
- case CHARACTERS:
- contentType |= InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
- break;
- case WORDS:
- contentType |= InputType.TYPE_TEXT_FLAG_CAP_WORDS;
- break;
- case SENTENCES:
- contentType |= InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
- break;
- }
- if (autoText) {
- contentType |= InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
- }
- return contentType;
- }
-
- public boolean onKeyDown(View view, Editable content,
- int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_DEL) {
- backspace(view, content, keyCode, event);
- return true;
- }
-
- return super.onKeyDown(view, content, keyCode, event);
- }
-
- /**
- * Base implementation handles ACTION_MULTIPLE KEYCODE_UNKNOWN by inserting
- * the event's text into the content.
- */
- public boolean onKeyOther(View view, Editable content, KeyEvent event) {
- if (event.getAction() != KeyEvent.ACTION_MULTIPLE
- || event.getKeyCode() != KeyEvent.KEYCODE_UNKNOWN) {
- // Not something we are interested in.
- return false;
- }
-
- int selStart, selEnd;
-
- {
- int a = Selection.getSelectionStart(content);
- int b = Selection.getSelectionEnd(content);
-
- selStart = Math.min(a, b);
- selEnd = Math.max(a, b);
- }
-
- CharSequence text = event.getCharacters();
- if (text == null) {
- return false;
- }
-
- content.replace(selStart, selEnd, text);
- return true;
- }
-}
-
diff --git a/core/java/android/text/method/CharacterPickerDialog.java b/core/java/android/text/method/CharacterPickerDialog.java
deleted file mode 100644
index 3c406751..0000000
--- a/core/java/android/text/method/CharacterPickerDialog.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import com.android.internal.R;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.os.Bundle;
-import android.text.*;
-import android.view.LayoutInflater;
-import android.view.View.OnClickListener;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.Button;
-import android.widget.GridView;
-import android.widget.TextView;
-
-/**
- * Dialog for choosing accented characters related to a base character.
- */
-public class CharacterPickerDialog extends Dialog
- implements OnItemClickListener, OnClickListener {
- private View mView;
- private Editable mText;
- private String mOptions;
- private boolean mInsert;
- private LayoutInflater mInflater;
-
- /**
- * Creates a new CharacterPickerDialog that presents the specified
- * <code>options</code> for insertion or replacement (depending on
- * the sense of <code>insert</code>) into <code>text</code>.
- */
- public CharacterPickerDialog(Context context, View view,
- Editable text, String options,
- boolean insert) {
- super(context);
-
- mView = view;
- mText = text;
- mOptions = options;
- mInsert = insert;
- mInflater = LayoutInflater.from(context);
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- WindowManager.LayoutParams params = getWindow().getAttributes();
- params.token = mView.getApplicationWindowToken();
- params.type = params.TYPE_APPLICATION_ATTACHED_DIALOG;
-
- setTitle(R.string.select_character);
- setContentView(R.layout.character_picker);
-
- GridView grid = (GridView) findViewById(R.id.characterPicker);
- grid.setAdapter(new OptionsAdapter(getContext()));
- grid.setOnItemClickListener(this);
-
- findViewById(R.id.cancel).setOnClickListener(this);
- }
-
- /**
- * Handles clicks on the character buttons.
- */
- public void onItemClick(AdapterView parent, View view, int position, long id) {
- int selEnd = Selection.getSelectionEnd(mText);
- String result = String.valueOf(mOptions.charAt(position));
-
- if (mInsert || selEnd == 0) {
- mText.insert(selEnd, result);
- } else {
- mText.replace(selEnd - 1, selEnd, result);
- }
-
- dismiss();
- }
-
- /**
- * Handles clicks on the Cancel button.
- */
- public void onClick(View v) {
- dismiss();
- }
-
- private class OptionsAdapter extends BaseAdapter {
- private Context mContext;
-
- public OptionsAdapter(Context context) {
- super();
- mContext = context;
- }
-
- public View getView(int position, View convertView, ViewGroup parent) {
- Button b = (Button)
- mInflater.inflate(R.layout.character_picker_button, null);
- b.setText(String.valueOf(mOptions.charAt(position)));
- return b;
- }
-
- public final int getCount() {
- return mOptions.length();
- }
-
- public final Object getItem(int position) {
- return String.valueOf(mOptions.charAt(position));
- }
-
- public final long getItemId(int position) {
- return position;
- }
- }
-}
diff --git a/core/java/android/text/method/DateKeyListener.java b/core/java/android/text/method/DateKeyListener.java
deleted file mode 100644
index 7c11434..0000000
--- a/core/java/android/text/method/DateKeyListener.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.view.KeyEvent;
-import android.text.InputType;
-
-/**
- * For entering dates in a text field.
- */
-public class DateKeyListener extends NumberKeyListener
-{
- public int getInputType() {
- return InputType.TYPE_CLASS_DATETIME
- | InputType.TYPE_DATETIME_VARIATION_DATE;
- }
-
- @Override
- protected char[] getAcceptedChars()
- {
- return CHARACTERS;
- }
-
- public static DateKeyListener getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new DateKeyListener();
- return sInstance;
- }
-
- /**
- * The characters that are used.
- *
- * @see KeyEvent#getMatch
- * @see #getAcceptedChars
- */
- public static final char[] CHARACTERS = new char[] {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- '/', '-', '.'
- };
-
- private static DateKeyListener sInstance;
-}
diff --git a/core/java/android/text/method/DateTimeKeyListener.java b/core/java/android/text/method/DateTimeKeyListener.java
deleted file mode 100644
index f8ebc40..0000000
--- a/core/java/android/text/method/DateTimeKeyListener.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.text.InputType;
-import android.view.KeyEvent;
-
-/**
- * For entering dates and times in the same text field.
- */
-public class DateTimeKeyListener extends NumberKeyListener
-{
- public int getInputType() {
- return InputType.TYPE_CLASS_DATETIME
- | InputType.TYPE_DATETIME_VARIATION_NORMAL;
- }
-
- @Override
- protected char[] getAcceptedChars()
- {
- return CHARACTERS;
- }
-
- public static DateTimeKeyListener getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new DateTimeKeyListener();
- return sInstance;
- }
-
- /**
- * The characters that are used.
- *
- * @see KeyEvent#getMatch
- * @see #getAcceptedChars
- */
- public static final char[] CHARACTERS = new char[] {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'm',
- 'p', ':', '/', '-', ' '
- };
-
- private static DateTimeKeyListener sInstance;
-}
diff --git a/core/java/android/text/method/DialerKeyListener.java b/core/java/android/text/method/DialerKeyListener.java
deleted file mode 100644
index b121e60..0000000
--- a/core/java/android/text/method/DialerKeyListener.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.view.KeyEvent;
-import android.view.KeyCharacterMap.KeyData;
-import android.text.InputType;
-import android.text.Spannable;
-
-/**
- * For dialing-only text entry
- */
-public class DialerKeyListener extends NumberKeyListener
-{
- @Override
- protected char[] getAcceptedChars()
- {
- return CHARACTERS;
- }
-
- public static DialerKeyListener getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new DialerKeyListener();
- return sInstance;
- }
-
- public int getInputType() {
- return InputType.TYPE_CLASS_PHONE;
- }
-
- /**
- * Overrides the superclass's lookup method to prefer the number field
- * from the KeyEvent.
- */
- protected int lookup(KeyEvent event, Spannable content) {
- int meta = getMetaState(content);
- int number = event.getNumber();
-
- /*
- * Prefer number if no meta key is active, or if it produces something
- * valid and the meta lookup does not.
- */
- if ((meta & (KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON)) == 0) {
- if (number != 0) {
- return number;
- }
- }
-
- int match = super.lookup(event, content);
-
- if (match != 0) {
- return match;
- } else {
- /*
- * If a meta key is active but the lookup with the meta key
- * did not produce anything, try some other meta keys, because
- * the user might have pressed SHIFT when they meant ALT,
- * or vice versa.
- */
-
- if (meta != 0) {
- KeyData kd = new KeyData();
- char[] accepted = getAcceptedChars();
-
- if (event.getKeyData(kd)) {
- for (int i = 1; i < kd.meta.length; i++) {
- if (ok(accepted, kd.meta[i])) {
- return kd.meta[i];
- }
- }
- }
- }
-
- /*
- * Otherwise, use the number associated with the key, since
- * whatever they wanted to do with the meta key does not
- * seem to be valid here.
- */
-
- return number;
- }
- }
-
-
- /**
- * The characters that are used.
- *
- * @see KeyEvent#getMatch
- * @see #getAcceptedChars
- */
- public static final char[] CHARACTERS = new char[] {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '*',
- '+', '-', '(', ')', ',', '/', 'N', '.', ' '
- };
-
- private static DialerKeyListener sInstance;
-}
diff --git a/core/java/android/text/method/DigitsKeyListener.java b/core/java/android/text/method/DigitsKeyListener.java
deleted file mode 100644
index f0f072c..0000000
--- a/core/java/android/text/method/DigitsKeyListener.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.text.InputType;
-import android.text.Spanned;
-import android.text.SpannableStringBuilder;
-import android.view.KeyEvent;
-
-
-/**
- * For digits-only text entry
- */
-public class DigitsKeyListener extends NumberKeyListener
-{
- private char[] mAccepted;
- private boolean mSign;
- private boolean mDecimal;
-
- private static final int SIGN = 1;
- private static final int DECIMAL = 2;
-
- @Override
- protected char[] getAcceptedChars() {
- return mAccepted;
- }
-
- /**
- * The characters that are used.
- *
- * @see KeyEvent#getMatch
- * @see #getAcceptedChars
- */
- private static final char[][] CHARACTERS = new char[][] {
- new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' },
- new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-' },
- new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.' },
- new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '.' },
- };
-
- /**
- * Allocates a DigitsKeyListener that accepts the digits 0 through 9.
- */
- public DigitsKeyListener() {
- this(false, false);
- }
-
- /**
- * Allocates a DigitsKeyListener that accepts the digits 0 through 9,
- * plus the minus sign (only at the beginning) and/or decimal point
- * (only one per field) if specified.
- */
- public DigitsKeyListener(boolean sign, boolean decimal) {
- mSign = sign;
- mDecimal = decimal;
-
- int kind = (sign ? SIGN : 0) | (decimal ? DECIMAL : 0);
- mAccepted = CHARACTERS[kind];
- }
-
- /**
- * Returns a DigitsKeyListener that accepts the digits 0 through 9.
- */
- public static DigitsKeyListener getInstance() {
- return getInstance(false, false);
- }
-
- /**
- * Returns a DigitsKeyListener that accepts the digits 0 through 9,
- * plus the minus sign (only at the beginning) and/or decimal point
- * (only one per field) if specified.
- */
- public static DigitsKeyListener getInstance(boolean sign, boolean decimal) {
- int kind = (sign ? SIGN : 0) | (decimal ? DECIMAL : 0);
-
- if (sInstance[kind] != null)
- return sInstance[kind];
-
- sInstance[kind] = new DigitsKeyListener(sign, decimal);
- return sInstance[kind];
- }
-
- /**
- * Returns a DigitsKeyListener that accepts only the characters
- * that appear in the specified String. Note that not all characters
- * may be available on every keyboard.
- */
- public static DigitsKeyListener getInstance(String accepted) {
- // TODO: do we need a cache of these to avoid allocating?
-
- DigitsKeyListener dim = new DigitsKeyListener();
-
- dim.mAccepted = new char[accepted.length()];
- accepted.getChars(0, accepted.length(), dim.mAccepted, 0);
-
- return dim;
- }
-
- public int getInputType() {
- int contentType = InputType.TYPE_CLASS_NUMBER;
- if (mSign) {
- contentType |= InputType.TYPE_NUMBER_FLAG_SIGNED;
- }
- if (mDecimal) {
- contentType |= InputType.TYPE_NUMBER_FLAG_DECIMAL;
- }
- return contentType;
- }
-
- @Override
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend) {
- CharSequence out = super.filter(source, start, end, dest, dstart, dend);
-
- if (mSign == false && mDecimal == false) {
- return out;
- }
-
- if (out != null) {
- source = out;
- start = 0;
- end = out.length();
- }
-
- int sign = -1;
- int decimal = -1;
- int dlen = dest.length();
-
- /*
- * Find out if the existing text has '-' or '.' characters.
- */
-
- for (int i = 0; i < dstart; i++) {
- char c = dest.charAt(i);
-
- if (c == '-') {
- sign = i;
- } else if (c == '.') {
- decimal = i;
- }
- }
- for (int i = dend; i < dlen; i++) {
- char c = dest.charAt(i);
-
- if (c == '-') {
- return ""; // Nothing can be inserted in front of a '-'.
- } else if (c == '.') {
- decimal = i;
- }
- }
-
- /*
- * If it does, we must strip them out from the source.
- * In addition, '-' must be the very first character,
- * and nothing can be inserted before an existing '-'.
- * Go in reverse order so the offsets are stable.
- */
-
- SpannableStringBuilder stripped = null;
-
- for (int i = end - 1; i >= start; i--) {
- char c = source.charAt(i);
- boolean strip = false;
-
- if (c == '-') {
- if (i != start || dstart != 0) {
- strip = true;
- } else if (sign >= 0) {
- strip = true;
- } else {
- sign = i;
- }
- } else if (c == '.') {
- if (decimal >= 0) {
- strip = true;
- } else {
- decimal = i;
- }
- }
-
- if (strip) {
- if (end == start + 1) {
- return ""; // Only one character, and it was stripped.
- }
-
- if (stripped == null) {
- stripped = new SpannableStringBuilder(source, start, end);
- }
-
- stripped.delete(i - start, i + 1 - start);
- }
- }
-
- if (stripped != null) {
- return stripped;
- } else if (out != null) {
- return out;
- } else {
- return null;
- }
- }
-
- private static DigitsKeyListener[] sInstance = new DigitsKeyListener[4];
-}
diff --git a/core/java/android/text/method/HideReturnsTransformationMethod.java b/core/java/android/text/method/HideReturnsTransformationMethod.java
deleted file mode 100644
index ce18692..0000000
--- a/core/java/android/text/method/HideReturnsTransformationMethod.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.graphics.Rect;
-import android.text.GetChars;
-import android.text.Spanned;
-import android.text.SpannedString;
-import android.text.TextUtils;
-import android.view.View;
-
-/**
- * This transformation method causes any carriage return characters (\r)
- * to be hidden by displaying them as zero-width non-breaking space
- * characters (\uFEFF).
- */
-public class HideReturnsTransformationMethod
-extends ReplacementTransformationMethod {
- private static char[] ORIGINAL = new char[] { '\r' };
- private static char[] REPLACEMENT = new char[] { '\uFEFF' };
-
- /**
- * The character to be replaced is \r.
- */
- protected char[] getOriginal() {
- return ORIGINAL;
- }
-
- /**
- * The character that \r is replaced with is \uFEFF.
- */
- protected char[] getReplacement() {
- return REPLACEMENT;
- }
-
- public static HideReturnsTransformationMethod getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new HideReturnsTransformationMethod();
- return sInstance;
- }
-
- private static HideReturnsTransformationMethod sInstance;
-}
diff --git a/core/java/android/text/method/KeyListener.java b/core/java/android/text/method/KeyListener.java
deleted file mode 100644
index 8594852..0000000
--- a/core/java/android/text/method/KeyListener.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.text.Editable;
-import android.view.KeyEvent;
-import android.view.View;
-
-/**
- * Interface for converting text key events into edit operations on an
- * Editable class. Note that for must cases this interface has been
- * superceded by general soft input methods as defined by
- * {@link android.view.inputmethod.InputMethod}; it should only be used
- * for cases where an application has its own on-screen keypad and also wants
- * to process hard keyboard events to match it.
- */
-public interface KeyListener {
- /**
- * Return the type of text that this key listener is manipulating,
- * as per {@link android.text.InputType}. This is used to
- * determine the mode of the soft keyboard that is shown for the editor.
- *
- * <p>If you return
- * {@link android.text.InputType#TYPE_NULL}
- * then <em>no</em> soft keyboard will provided. In other words, you
- * must be providing your own key pad for on-screen input and the key
- * listener will be used to handle input from a hard keyboard.
- *
- * <p>If you
- * return any other value, a soft input method will be created when the
- * user puts focus in the editor, which will provide a keypad and also
- * consume hard key events. This means that the key listener will generally
- * not be used, instead the soft input method will take care of managing
- * key input as per the content type returned here.
- */
- public int getInputType();
-
- /**
- * If the key listener wants to handle this key, return true,
- * otherwise return false and the caller (i.e. the widget host)
- * will handle the key.
- */
- public boolean onKeyDown(View view, Editable text,
- int keyCode, KeyEvent event);
-
- /**
- * If the key listener wants to handle this key release, return true,
- * otherwise return false and the caller (i.e. the widget host)
- * will handle the key.
- */
- public boolean onKeyUp(View view, Editable text,
- int keyCode, KeyEvent event);
-
- /**
- * If the key listener wants to other kinds of key events, return true,
- * otherwise return false and the caller (i.e. the widget host)
- * will handle the key.
- */
- public boolean onKeyOther(View view, Editable text, KeyEvent event);
-
- /**
- * Remove the given shift states from the edited text.
- */
- public void clearMetaKeyState(View view, Editable content, int states);
-}
diff --git a/core/java/android/text/method/LinkMovementMethod.java b/core/java/android/text/method/LinkMovementMethod.java
deleted file mode 100644
index 22e9cc6..0000000
--- a/core/java/android/text/method/LinkMovementMethod.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.text.*;
-import android.text.style.*;
-import android.view.View;
-import android.widget.TextView;
-
-public class
-LinkMovementMethod
-extends ScrollingMovementMethod
-{
- private static final int CLICK = 1;
- private static final int UP = 2;
- private static final int DOWN = 3;
-
- @Override
- public boolean onKeyDown(TextView widget, Spannable buffer,
- int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_ENTER:
- if (event.getRepeatCount() == 0) {
- if (action(CLICK, widget, buffer)) {
- return true;
- }
- }
- }
-
- return super.onKeyDown(widget, buffer, keyCode, event);
- }
-
- @Override
- protected boolean up(TextView widget, Spannable buffer) {
- if (action(UP, widget, buffer)) {
- return true;
- }
-
- return super.up(widget, buffer);
- }
-
- @Override
- protected boolean down(TextView widget, Spannable buffer) {
- if (action(DOWN, widget, buffer)) {
- return true;
- }
-
- return super.down(widget, buffer);
- }
-
- @Override
- protected boolean left(TextView widget, Spannable buffer) {
- if (action(UP, widget, buffer)) {
- return true;
- }
-
- return super.left(widget, buffer);
- }
-
- @Override
- protected boolean right(TextView widget, Spannable buffer) {
- if (action(DOWN, widget, buffer)) {
- return true;
- }
-
- return super.right(widget, buffer);
- }
-
- private boolean action(int what, TextView widget, Spannable buffer) {
- boolean handled = false;
-
- Layout layout = widget.getLayout();
-
- int padding = widget.getTotalPaddingTop() +
- widget.getTotalPaddingBottom();
- int areatop = widget.getScrollY();
- int areabot = areatop + widget.getHeight() - padding;
-
- int linetop = layout.getLineForVertical(areatop);
- int linebot = layout.getLineForVertical(areabot);
-
- int first = layout.getLineStart(linetop);
- int last = layout.getLineEnd(linebot);
-
- ClickableSpan[] candidates = buffer.getSpans(first, last, ClickableSpan.class);
-
- int a = Selection.getSelectionStart(buffer);
- int b = Selection.getSelectionEnd(buffer);
-
- int selStart = Math.min(a, b);
- int selEnd = Math.max(a, b);
-
- if (selStart < 0) {
- if (buffer.getSpanStart(FROM_BELOW) >= 0) {
- selStart = selEnd = buffer.length();
- }
- }
-
- if (selStart > last)
- selStart = selEnd = Integer.MAX_VALUE;
- if (selEnd < first)
- selStart = selEnd = -1;
-
- switch (what) {
- case CLICK:
- if (selStart == selEnd) {
- return false;
- }
-
- ClickableSpan[] link = buffer.getSpans(selStart, selEnd, ClickableSpan.class);
-
- if (link.length != 1)
- return false;
-
- link[0].onClick(widget);
- break;
-
- case UP:
- int beststart, bestend;
-
- beststart = -1;
- bestend = -1;
-
- for (int i = 0; i < candidates.length; i++) {
- int end = buffer.getSpanEnd(candidates[i]);
-
- if (end < selEnd || selStart == selEnd) {
- if (end > bestend) {
- beststart = buffer.getSpanStart(candidates[i]);
- bestend = end;
- }
- }
- }
-
- if (beststart >= 0) {
- Selection.setSelection(buffer, bestend, beststart);
- return true;
- }
-
- break;
-
- case DOWN:
- beststart = Integer.MAX_VALUE;
- bestend = Integer.MAX_VALUE;
-
- for (int i = 0; i < candidates.length; i++) {
- int start = buffer.getSpanStart(candidates[i]);
-
- if (start > selStart || selStart == selEnd) {
- if (start < beststart) {
- beststart = start;
- bestend = buffer.getSpanEnd(candidates[i]);
- }
- }
- }
-
- if (bestend < Integer.MAX_VALUE) {
- Selection.setSelection(buffer, beststart, bestend);
- return true;
- }
-
- break;
- }
-
- return false;
- }
-
- public boolean onKeyUp(TextView widget, Spannable buffer,
- int keyCode, KeyEvent event) {
- return false;
- }
-
- @Override
- public boolean onTouchEvent(TextView widget, Spannable buffer,
- MotionEvent event) {
- int action = event.getAction();
-
- if (action == MotionEvent.ACTION_UP ||
- action == MotionEvent.ACTION_DOWN) {
- int x = (int) event.getX();
- int y = (int) event.getY();
-
- x -= widget.getTotalPaddingLeft();
- y -= widget.getTotalPaddingTop();
-
- x += widget.getScrollX();
- y += widget.getScrollY();
-
- Layout layout = widget.getLayout();
- int line = layout.getLineForVertical(y);
- int off = layout.getOffsetForHorizontal(line, x);
-
- ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
-
- if (link.length != 0) {
- if (action == MotionEvent.ACTION_UP) {
- link[0].onClick(widget);
- } else if (action == MotionEvent.ACTION_DOWN) {
- Selection.setSelection(buffer,
- buffer.getSpanStart(link[0]),
- buffer.getSpanEnd(link[0]));
- }
-
- return true;
- } else {
- Selection.removeSelection(buffer);
- }
- }
-
- return super.onTouchEvent(widget, buffer, event);
- }
-
- public void initialize(TextView widget, Spannable text) {
- Selection.removeSelection(text);
- text.removeSpan(FROM_BELOW);
- }
-
- public void onTakeFocus(TextView view, Spannable text, int dir) {
- Selection.removeSelection(text);
-
- if ((dir & View.FOCUS_BACKWARD) != 0) {
- text.setSpan(FROM_BELOW, 0, 0, Spannable.SPAN_POINT_POINT);
- } else {
- text.removeSpan(FROM_BELOW);
- }
- }
-
- public static MovementMethod getInstance() {
- if (sInstance == null)
- sInstance = new LinkMovementMethod();
-
- return sInstance;
- }
-
- private static LinkMovementMethod sInstance;
- private static Object FROM_BELOW = new NoCopySpan.Concrete();
-}
diff --git a/core/java/android/text/method/MetaKeyKeyListener.java b/core/java/android/text/method/MetaKeyKeyListener.java
deleted file mode 100644
index 39ad976..0000000
--- a/core/java/android/text/method/MetaKeyKeyListener.java
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.view.KeyEvent;
-import android.view.View;
-import android.text.*;
-
-/**
- * This base class encapsulates the behavior for handling the meta keys
- * (shift and alt) and the pseudo-meta state of selecting text.
- * Key listeners that care about meta state should
- * inherit from it; you should not instantiate this class directly in a client.
- */
-
-public abstract class MetaKeyKeyListener {
- public static final int META_SHIFT_ON = KeyEvent.META_SHIFT_ON;
- public static final int META_ALT_ON = KeyEvent.META_ALT_ON;
- public static final int META_SYM_ON = KeyEvent.META_SYM_ON;
-
- private static final int LOCKED_SHIFT = 8;
-
- public static final int META_CAP_LOCKED = KeyEvent.META_SHIFT_ON << LOCKED_SHIFT;
- public static final int META_ALT_LOCKED = KeyEvent.META_ALT_ON << LOCKED_SHIFT;
- public static final int META_SYM_LOCKED = KeyEvent.META_SYM_ON << LOCKED_SHIFT;
-
- /**
- * @hide pending API review
- */
- public static final int META_SELECTING = 1 << 16;
-
- private static final int USED_SHIFT = 24;
-
- private static final long META_CAP_USED = ((long)KeyEvent.META_SHIFT_ON) << USED_SHIFT;
- private static final long META_ALT_USED = ((long)KeyEvent.META_ALT_ON) << USED_SHIFT;
- private static final long META_SYM_USED = ((long)KeyEvent.META_SYM_ON) << USED_SHIFT;
-
- private static final int PRESSED_SHIFT = 32;
-
- private static final long META_CAP_PRESSED = ((long)KeyEvent.META_SHIFT_ON) << PRESSED_SHIFT;
- private static final long META_ALT_PRESSED = ((long)KeyEvent.META_ALT_ON) << PRESSED_SHIFT;
- private static final long META_SYM_PRESSED = ((long)KeyEvent.META_SYM_ON) << PRESSED_SHIFT;
-
- private static final int RELEASED_SHIFT = 40;
-
- private static final long META_CAP_RELEASED = ((long)KeyEvent.META_SHIFT_ON) << RELEASED_SHIFT;
- private static final long META_ALT_RELEASED = ((long)KeyEvent.META_ALT_ON) << RELEASED_SHIFT;
- private static final long META_SYM_RELEASED = ((long)KeyEvent.META_SYM_ON) << RELEASED_SHIFT;
-
- private static final long META_SHIFT_MASK = META_SHIFT_ON
- | META_CAP_LOCKED | META_CAP_USED
- | META_CAP_PRESSED | META_CAP_RELEASED;
- private static final long META_ALT_MASK = META_ALT_ON
- | META_ALT_LOCKED | META_ALT_USED
- | META_ALT_PRESSED | META_ALT_RELEASED;
- private static final long META_SYM_MASK = META_SYM_ON
- | META_SYM_LOCKED | META_SYM_USED
- | META_SYM_PRESSED | META_SYM_RELEASED;
-
- private static final Object CAP = new NoCopySpan.Concrete();
- private static final Object ALT = new NoCopySpan.Concrete();
- private static final Object SYM = new NoCopySpan.Concrete();
- private static final Object SELECTING = new NoCopySpan.Concrete();
-
- /**
- * Resets all meta state to inactive.
- */
- public static void resetMetaState(Spannable text) {
- text.removeSpan(CAP);
- text.removeSpan(ALT);
- text.removeSpan(SYM);
- text.removeSpan(SELECTING);
- }
-
- /**
- * Gets the state of the meta keys.
- *
- * @param text the buffer in which the meta key would have been pressed.
- *
- * @return an integer in which each bit set to one represents a pressed
- * or locked meta key.
- */
- public static final int getMetaState(CharSequence text) {
- return getActive(text, CAP, META_SHIFT_ON, META_CAP_LOCKED) |
- getActive(text, ALT, META_ALT_ON, META_ALT_LOCKED) |
- getActive(text, SYM, META_SYM_ON, META_SYM_LOCKED) |
- getActive(text, SELECTING, META_SELECTING, META_SELECTING);
- }
-
- /**
- * Gets the state of a particular meta key.
- *
- * @param meta META_SHIFT_ON, META_ALT_ON, META_SYM_ON, or META_SELECTING
- * @param text the buffer in which the meta key would have been pressed.
- *
- * @return 0 if inactive, 1 if active, 2 if locked.
- */
- public static final int getMetaState(CharSequence text, int meta) {
- switch (meta) {
- case META_SHIFT_ON:
- return getActive(text, CAP, 1, 2);
-
- case META_ALT_ON:
- return getActive(text, ALT, 1, 2);
-
- case META_SYM_ON:
- return getActive(text, SYM, 1, 2);
-
- case META_SELECTING:
- return getActive(text, SELECTING, 1, 2);
-
- default:
- return 0;
- }
- }
-
- private static int getActive(CharSequence text, Object meta,
- int on, int lock) {
- if (!(text instanceof Spanned)) {
- return 0;
- }
-
- Spanned sp = (Spanned) text;
- int flag = sp.getSpanFlags(meta);
-
- if (flag == LOCKED) {
- return lock;
- } else if (flag != 0) {
- return on;
- } else {
- return 0;
- }
- }
-
- /**
- * Call this method after you handle a keypress so that the meta
- * state will be reset to unshifted (if it is not still down)
- * or primed to be reset to unshifted (once it is released).
- */
- public static void adjustMetaAfterKeypress(Spannable content) {
- adjust(content, CAP);
- adjust(content, ALT);
- adjust(content, SYM);
- }
-
- /**
- * Returns true if this object is one that this class would use to
- * keep track of meta state in the specified text.
- */
- public static boolean isMetaTracker(CharSequence text, Object what) {
- return what == CAP || what == ALT || what == SYM ||
- what == SELECTING;
- }
-
- private static void adjust(Spannable content, Object what) {
- int current = content.getSpanFlags(what);
-
- if (current == PRESSED)
- content.setSpan(what, 0, 0, USED);
- else if (current == RELEASED)
- content.removeSpan(what);
- }
-
- /**
- * Call this if you are a method that ignores the locked meta state
- * (arrow keys, for example) and you handle a key.
- */
- protected static void resetLockedMeta(Spannable content) {
- resetLock(content, CAP);
- resetLock(content, ALT);
- resetLock(content, SYM);
- resetLock(content, SELECTING);
- }
-
- private static void resetLock(Spannable content, Object what) {
- int current = content.getSpanFlags(what);
-
- if (current == LOCKED)
- content.removeSpan(what);
- }
-
- /**
- * Handles presses of the meta keys.
- */
- public boolean onKeyDown(View view, Editable content,
- int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
- press(content, CAP);
- return true;
- }
-
- if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT
- || keyCode == KeyEvent.KEYCODE_NUM) {
- press(content, ALT);
- return true;
- }
-
- if (keyCode == KeyEvent.KEYCODE_SYM) {
- press(content, SYM);
- return true;
- }
-
- return false; // no super to call through to
- }
-
- private void press(Editable content, Object what) {
- int state = content.getSpanFlags(what);
-
- if (state == PRESSED)
- ; // repeat before use
- else if (state == RELEASED)
- content.setSpan(what, 0, 0, LOCKED);
- else if (state == USED)
- ; // repeat after use
- else if (state == LOCKED)
- content.removeSpan(what);
- else
- content.setSpan(what, 0, 0, PRESSED);
- }
-
- /**
- * Start selecting text.
- * @hide pending API review
- */
- public static void startSelecting(View view, Spannable content) {
- content.setSpan(SELECTING, 0, 0, PRESSED);
- }
-
- /**
- * Stop selecting text. This does not actually collapse the selection;
- * call {@link android.text.Selection#setSelection} too.
- * @hide pending API review
- */
- public static void stopSelecting(View view, Spannable content) {
- content.removeSpan(SELECTING);
- }
-
- /**
- * Handles release of the meta keys.
- */
- public boolean onKeyUp(View view, Editable content, int keyCode,
- KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
- release(content, CAP);
- return true;
- }
-
- if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT
- || keyCode == KeyEvent.KEYCODE_NUM) {
- release(content, ALT);
- return true;
- }
-
- if (keyCode == KeyEvent.KEYCODE_SYM) {
- release(content, SYM);
- return true;
- }
-
- return false; // no super to call through to
- }
-
- private void release(Editable content, Object what) {
- int current = content.getSpanFlags(what);
-
- if (current == USED)
- content.removeSpan(what);
- else if (current == PRESSED)
- content.setSpan(what, 0, 0, RELEASED);
- }
-
- public void clearMetaKeyState(View view, Editable content, int states) {
- clearMetaKeyState(content, states);
- }
-
- public static void clearMetaKeyState(Editable content, int states) {
- if ((states&META_SHIFT_ON) != 0) content.removeSpan(CAP);
- if ((states&META_ALT_ON) != 0) content.removeSpan(ALT);
- if ((states&META_SYM_ON) != 0) content.removeSpan(SYM);
- if ((states&META_SELECTING) != 0) content.removeSpan(SELECTING);
- }
-
- /**
- * Call this if you are a method that ignores the locked meta state
- * (arrow keys, for example) and you handle a key.
- */
- public static long resetLockedMeta(long state) {
- state = resetLock(state, META_SHIFT_ON, META_SHIFT_MASK);
- state = resetLock(state, META_ALT_ON, META_ALT_MASK);
- state = resetLock(state, META_SYM_ON, META_SYM_MASK);
- return state;
- }
-
- private static long resetLock(long state, int what, long mask) {
- if ((state&(((long)what)<<LOCKED_SHIFT)) != 0) {
- state &= ~mask;
- }
- return state;
- }
-
- // ---------------------------------------------------------------------
- // Version of API that operates on a state bit mask
- // ---------------------------------------------------------------------
-
- /**
- * Gets the state of the meta keys.
- *
- * @param state the current meta state bits.
- *
- * @return an integer in which each bit set to one represents a pressed
- * or locked meta key.
- */
- public static final int getMetaState(long state) {
- return getActive(state, META_SHIFT_ON, META_SHIFT_ON, META_CAP_LOCKED) |
- getActive(state, META_ALT_ON, META_ALT_ON, META_ALT_LOCKED) |
- getActive(state, META_SYM_ON, META_SYM_ON, META_SYM_LOCKED);
- }
-
- /**
- * Gets the state of a particular meta key.
- *
- * @param state the current state bits.
- * @param meta META_SHIFT_ON, META_ALT_ON, or META_SYM_ON
- *
- * @return 0 if inactive, 1 if active, 2 if locked.
- */
- public static final int getMetaState(long state, int meta) {
- switch (meta) {
- case META_SHIFT_ON:
- return getActive(state, meta, 1, 2);
-
- case META_ALT_ON:
- return getActive(state, meta, 1, 2);
-
- case META_SYM_ON:
- return getActive(state, meta, 1, 2);
-
- default:
- return 0;
- }
- }
-
- private static int getActive(long state, int meta, int on, int lock) {
- if ((state&(meta<<LOCKED_SHIFT)) != 0) {
- return lock;
- } else if ((state&meta) != 0) {
- return on;
- } else {
- return 0;
- }
- }
-
- /**
- * Call this method after you handle a keypress so that the meta
- * state will be reset to unshifted (if it is not still down)
- * or primed to be reset to unshifted (once it is released). Takes
- * the current state, returns the new state.
- */
- public static long adjustMetaAfterKeypress(long state) {
- state = adjust(state, META_SHIFT_ON, META_SHIFT_MASK);
- state = adjust(state, META_ALT_ON, META_ALT_MASK);
- state = adjust(state, META_SYM_ON, META_SYM_MASK);
- return state;
- }
-
- private static long adjust(long state, int what, long mask) {
- if ((state&(((long)what)<<PRESSED_SHIFT)) != 0)
- return (state&~mask) | what | ((long)what)<<USED_SHIFT;
- else if ((state&(((long)what)<<RELEASED_SHIFT)) != 0)
- return state & ~mask;
- return state;
- }
-
- /**
- * Handles presses of the meta keys.
- */
- public static long handleKeyDown(long state, int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
- return press(state, META_SHIFT_ON, META_SHIFT_MASK);
- }
-
- if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT
- || keyCode == KeyEvent.KEYCODE_NUM) {
- return press(state, META_ALT_ON, META_ALT_MASK);
- }
-
- if (keyCode == KeyEvent.KEYCODE_SYM) {
- return press(state, META_SYM_ON, META_SYM_MASK);
- }
-
- return state;
- }
-
- private static long press(long state, int what, long mask) {
- if ((state&(((long)what)<<PRESSED_SHIFT)) != 0)
- ; // repeat before use
- else if ((state&(((long)what)<<RELEASED_SHIFT)) != 0)
- state = (state&~mask) | what | (((long)what) << LOCKED_SHIFT);
- else if ((state&(((long)what)<<USED_SHIFT)) != 0)
- ; // repeat after use
- else if ((state&(((long)what)<<LOCKED_SHIFT)) != 0)
- state = state&~mask;
- else
- state = state | what | (((long)what)<<PRESSED_SHIFT);
- return state;
- }
-
- /**
- * Handles release of the meta keys.
- */
- public static long handleKeyUp(long state, int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
- return release(state, META_SHIFT_ON, META_SHIFT_MASK);
- }
-
- if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT
- || keyCode == KeyEvent.KEYCODE_NUM) {
- return release(state, META_ALT_ON, META_ALT_MASK);
- }
-
- if (keyCode == KeyEvent.KEYCODE_SYM) {
- return release(state, META_SYM_ON, META_SYM_MASK);
- }
-
- return state;
- }
-
- private static long release(long state, int what, long mask) {
- if ((state&(((long)what)<<USED_SHIFT)) != 0)
- state = state&~mask;
- else if ((state&(((long)what)<<PRESSED_SHIFT)) != 0)
- state = state | what | (((long)what)<<RELEASED_SHIFT);
- return state;
- }
-
- public long clearMetaKeyState(long state, int which) {
- if ((which&META_SHIFT_ON) != 0)
- state = resetLock(state, META_SHIFT_ON, META_SHIFT_MASK);
- if ((which&META_ALT_ON) != 0)
- state = resetLock(state, META_ALT_ON, META_ALT_MASK);
- if ((which&META_SYM_ON) != 0)
- state = resetLock(state, META_SYM_ON, META_SYM_MASK);
- return state;
- }
-
- /**
- * The meta key has been pressed but has not yet been used.
- */
- private static final int PRESSED =
- Spannable.SPAN_MARK_MARK | (1 << Spannable.SPAN_USER_SHIFT);
-
- /**
- * The meta key has been pressed and released but has still
- * not yet been used.
- */
- private static final int RELEASED =
- Spannable.SPAN_MARK_MARK | (2 << Spannable.SPAN_USER_SHIFT);
-
- /**
- * The meta key has been pressed and used but has not yet been released.
- */
- private static final int USED =
- Spannable.SPAN_MARK_MARK | (3 << Spannable.SPAN_USER_SHIFT);
-
- /**
- * The meta key has been pressed and released without use, and then
- * pressed again; it may also have been released again.
- */
- private static final int LOCKED =
- Spannable.SPAN_MARK_MARK | (4 << Spannable.SPAN_USER_SHIFT);
-}
-
diff --git a/core/java/android/text/method/MovementMethod.java b/core/java/android/text/method/MovementMethod.java
deleted file mode 100644
index 29f67a1..0000000
--- a/core/java/android/text/method/MovementMethod.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.widget.TextView;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.text.*;
-
-public interface MovementMethod
-{
- public void initialize(TextView widget, Spannable text);
- public boolean onKeyDown(TextView widget, Spannable text, int keyCode, KeyEvent event);
- public boolean onKeyUp(TextView widget, Spannable text, int keyCode, KeyEvent event);
-
- /**
- * If the key listener wants to other kinds of key events, return true,
- * otherwise return false and the caller (i.e. the widget host)
- * will handle the key.
- */
- public boolean onKeyOther(TextView view, Spannable text, KeyEvent event);
-
- public void onTakeFocus(TextView widget, Spannable text, int direction);
- public boolean onTrackballEvent(TextView widget, Spannable text,
- MotionEvent event);
- public boolean onTouchEvent(TextView widget, Spannable text,
- MotionEvent event);
-
- /**
- * Returns true if this movement method allows arbitrary selection
- * of any text; false if it has no selection (like a movement method
- * that only scrolls) or a constrained selection (for example
- * limited to links. The "Select All" menu item is disabled
- * if arbitrary selection is not allowed.
- */
- public boolean canSelectArbitrarily();
-}
diff --git a/core/java/android/text/method/MultiTapKeyListener.java b/core/java/android/text/method/MultiTapKeyListener.java
deleted file mode 100644
index 6d94788..0000000
--- a/core/java/android/text/method/MultiTapKeyListener.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.view.KeyEvent;
-import android.view.View;
-import android.os.Handler;
-import android.os.SystemClock;
-import android.text.*;
-import android.text.method.TextKeyListener.Capitalize;
-import android.util.SparseArray;
-
-/**
- * This is the standard key listener for alphabetic input on 12-key
- * keyboards. You should generally not need to instantiate this yourself;
- * TextKeyListener will do it for you.
- */
-public class MultiTapKeyListener extends BaseKeyListener
- implements SpanWatcher {
- private static MultiTapKeyListener[] sInstance =
- new MultiTapKeyListener[Capitalize.values().length * 2];
-
- private static final SparseArray<String> sRecs = new SparseArray<String>();
-
- private Capitalize mCapitalize;
- private boolean mAutoText;
-
- static {
- sRecs.put(KeyEvent.KEYCODE_1, ".,1!@#$%^&*:/?'=()");
- sRecs.put(KeyEvent.KEYCODE_2, "abc2ABC");
- sRecs.put(KeyEvent.KEYCODE_3, "def3DEF");
- sRecs.put(KeyEvent.KEYCODE_4, "ghi4GHI");
- sRecs.put(KeyEvent.KEYCODE_5, "jkl5JKL");
- sRecs.put(KeyEvent.KEYCODE_6, "mno6MNO");
- sRecs.put(KeyEvent.KEYCODE_7, "pqrs7PQRS");
- sRecs.put(KeyEvent.KEYCODE_8, "tuv8TUV");
- sRecs.put(KeyEvent.KEYCODE_9, "wxyz9WXYZ");
- sRecs.put(KeyEvent.KEYCODE_0, "0+");
- sRecs.put(KeyEvent.KEYCODE_POUND, " ");
- };
-
- public MultiTapKeyListener(Capitalize cap,
- boolean autotext) {
- mCapitalize = cap;
- mAutoText = autotext;
- }
-
- /**
- * Returns a new or existing instance with the specified capitalization
- * and correction properties.
- */
- public static MultiTapKeyListener getInstance(boolean autotext,
- Capitalize cap) {
- int off = cap.ordinal() * 2 + (autotext ? 1 : 0);
-
- if (sInstance[off] == null) {
- sInstance[off] = new MultiTapKeyListener(cap, autotext);
- }
-
- return sInstance[off];
- }
-
- public int getInputType() {
- return makeTextContentType(mCapitalize, mAutoText);
- }
-
- public boolean onKeyDown(View view, Editable content,
- int keyCode, KeyEvent event) {
- int selStart, selEnd;
- int pref = 0;
-
- if (view != null) {
- pref = TextKeyListener.getInstance().getPrefs(view.getContext());
- }
-
- {
- int a = Selection.getSelectionStart(content);
- int b = Selection.getSelectionEnd(content);
-
- selStart = Math.min(a, b);
- selEnd = Math.max(a, b);
- }
-
- int activeStart = content.getSpanStart(TextKeyListener.ACTIVE);
- int activeEnd = content.getSpanEnd(TextKeyListener.ACTIVE);
-
- // now for the multitap cases...
-
- // Try to increment the character we were working on before
- // if we have one and it's still the same key.
-
- int rec = (content.getSpanFlags(TextKeyListener.ACTIVE)
- & Spannable.SPAN_USER) >>> Spannable.SPAN_USER_SHIFT;
-
- if (activeStart == selStart && activeEnd == selEnd &&
- selEnd - selStart == 1 &&
- rec >= 0 && rec < sRecs.size()) {
- if (keyCode == KeyEvent.KEYCODE_STAR) {
- char current = content.charAt(selStart);
-
- if (Character.isLowerCase(current)) {
- content.replace(selStart, selEnd,
- String.valueOf(current).toUpperCase());
- removeTimeouts(content);
- Timeout t = new Timeout(content);
-
- return true;
- }
- if (Character.isUpperCase(current)) {
- content.replace(selStart, selEnd,
- String.valueOf(current).toLowerCase());
- removeTimeouts(content);
- Timeout t = new Timeout(content);
-
- return true;
- }
- }
-
- if (sRecs.indexOfKey(keyCode) == rec) {
- String val = sRecs.valueAt(rec);
- char ch = content.charAt(selStart);
- int ix = val.indexOf(ch);
-
- if (ix >= 0) {
- ix = (ix + 1) % (val.length());
-
- content.replace(selStart, selEnd, val, ix, ix + 1);
- removeTimeouts(content);
- Timeout t = new Timeout(content);
-
- return true;
- }
- }
-
- // Is this key one we know about at all? If so, acknowledge
- // that the selection is our fault but the key has changed
- // or the text no longer matches, so move the selection over
- // so that it inserts instead of replaces.
-
- rec = sRecs.indexOfKey(keyCode);
-
- if (rec >= 0) {
- Selection.setSelection(content, selEnd, selEnd);
- selStart = selEnd;
- }
- } else {
- rec = sRecs.indexOfKey(keyCode);
- }
-
- if (rec >= 0) {
- // We have a valid key. Replace the selection or insertion point
- // with the first character for that key, and remember what
- // record it came from for next time.
-
- String val = sRecs.valueAt(rec);
-
- int off = 0;
- if ((pref & TextKeyListener.AUTO_CAP) != 0 &&
- TextKeyListener.shouldCap(mCapitalize, content, selStart)) {
- for (int i = 0; i < val.length(); i++) {
- if (Character.isUpperCase(val.charAt(i))) {
- off = i;
- break;
- }
- }
- }
-
- if (selStart != selEnd) {
- Selection.setSelection(content, selEnd);
- }
-
- content.setSpan(OLD_SEL_START, selStart, selStart,
- Spannable.SPAN_MARK_MARK);
-
- content.replace(selStart, selEnd, val, off, off + 1);
-
- int oldStart = content.getSpanStart(OLD_SEL_START);
- selEnd = Selection.getSelectionEnd(content);
-
- if (selEnd != oldStart) {
- Selection.setSelection(content, oldStart, selEnd);
-
- content.setSpan(TextKeyListener.LAST_TYPED,
- oldStart, selEnd,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-
- content.setSpan(TextKeyListener.ACTIVE,
- oldStart, selEnd,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE |
- (rec << Spannable.SPAN_USER_SHIFT));
-
- }
-
- removeTimeouts(content);
- Timeout t = new Timeout(content);
-
- // Set up the callback so we can remove the timeout if the
- // cursor moves.
-
- if (content.getSpanStart(this) < 0) {
- KeyListener[] methods = content.getSpans(0, content.length(),
- KeyListener.class);
- for (Object method : methods) {
- content.removeSpan(method);
- }
- content.setSpan(this, 0, content.length(),
- Spannable.SPAN_INCLUSIVE_INCLUSIVE);
- }
-
- return true;
- }
-
- return super.onKeyDown(view, content, keyCode, event);
- }
-
- public void onSpanChanged(Spannable buf,
- Object what, int s, int e, int start, int stop) {
- if (what == Selection.SELECTION_END) {
- buf.removeSpan(TextKeyListener.ACTIVE);
- removeTimeouts(buf);
- }
- }
-
- private static void removeTimeouts(Spannable buf) {
- Timeout[] timeout = buf.getSpans(0, buf.length(), Timeout.class);
-
- for (int i = 0; i < timeout.length; i++) {
- Timeout t = timeout[i];
-
- t.removeCallbacks(t);
- t.mBuffer = null;
- buf.removeSpan(t);
- }
- }
-
- private class Timeout
- extends Handler
- implements Runnable
- {
- public Timeout(Editable buffer) {
- mBuffer = buffer;
- mBuffer.setSpan(Timeout.this, 0, mBuffer.length(),
- Spannable.SPAN_INCLUSIVE_INCLUSIVE);
-
- postAtTime(this, SystemClock.uptimeMillis() + 2000);
- }
-
- public void run() {
- Spannable buf = mBuffer;
-
- if (buf != null) {
- int st = Selection.getSelectionStart(buf);
- int en = Selection.getSelectionEnd(buf);
-
- int start = buf.getSpanStart(TextKeyListener.ACTIVE);
- int end = buf.getSpanEnd(TextKeyListener.ACTIVE);
-
- if (st == start && en == end) {
- Selection.setSelection(buf, Selection.getSelectionEnd(buf));
- }
-
- buf.removeSpan(Timeout.this);
- }
- }
-
- private Editable mBuffer;
- }
-
- public void onSpanAdded(Spannable s, Object what, int start, int end) { }
- public void onSpanRemoved(Spannable s, Object what, int start, int end) { }
-}
-
diff --git a/core/java/android/text/method/NumberKeyListener.java b/core/java/android/text/method/NumberKeyListener.java
deleted file mode 100644
index e500fae..0000000
--- a/core/java/android/text/method/NumberKeyListener.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.view.KeyEvent;
-import android.view.View;
-import android.text.Editable;
-import android.text.InputFilter;
-import android.text.Selection;
-import android.text.Spannable;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-
-/**
- * For numeric text entry
- */
-public abstract class NumberKeyListener extends BaseKeyListener
- implements InputFilter
-{
- /**
- * You can say which characters you can accept.
- */
- protected abstract char[] getAcceptedChars();
-
- protected int lookup(KeyEvent event, Spannable content) {
- return event.getMatch(getAcceptedChars(), getMetaState(content));
- }
-
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend) {
- char[] accept = getAcceptedChars();
- boolean filter = false;
-
- int i;
- for (i = start; i < end; i++) {
- if (!ok(accept, source.charAt(i))) {
- break;
- }
- }
-
- if (i == end) {
- // It was all OK.
- return null;
- }
-
- if (end - start == 1) {
- // It was not OK, and there is only one char, so nothing remains.
- return "";
- }
-
- SpannableStringBuilder filtered =
- new SpannableStringBuilder(source, start, end);
- i -= start;
- end -= start;
-
- int len = end - start;
- // Only count down to i because the chars before that were all OK.
- for (int j = end - 1; j >= i; j--) {
- if (!ok(accept, source.charAt(j))) {
- filtered.delete(j, j + 1);
- }
- }
-
- return filtered;
- }
-
- protected static boolean ok(char[] accept, char c) {
- for (int i = accept.length - 1; i >= 0; i--) {
- if (accept[i] == c) {
- return true;
- }
- }
-
- return false;
- }
-
- @Override
- public boolean onKeyDown(View view, Editable content,
- int keyCode, KeyEvent event) {
- int selStart, selEnd;
-
- {
- int a = Selection.getSelectionStart(content);
- int b = Selection.getSelectionEnd(content);
-
- selStart = Math.min(a, b);
- selEnd = Math.max(a, b);
- }
-
- int i = event != null ? lookup(event, content) : 0;
- int repeatCount = event != null ? event.getRepeatCount() : 0;
- if (repeatCount == 0) {
- if (i != 0) {
- if (selStart != selEnd) {
- Selection.setSelection(content, selEnd);
- }
-
- content.replace(selStart, selEnd, String.valueOf((char) i));
-
- adjustMetaAfterKeypress(content);
- return true;
- }
- } else if (i == '0' && repeatCount == 1) {
- // Pretty hackish, it replaces the 0 with the +
-
- if (selStart == selEnd && selEnd > 0 &&
- content.charAt(selStart - 1) == '0') {
- content.replace(selStart - 1, selEnd, String.valueOf('+'));
- adjustMetaAfterKeypress(content);
- return true;
- }
- }
-
- adjustMetaAfterKeypress(content);
- return super.onKeyDown(view, content, keyCode, event);
- }
-}
diff --git a/core/java/android/text/method/PasswordTransformationMethod.java b/core/java/android/text/method/PasswordTransformationMethod.java
deleted file mode 100644
index fad4f64..0000000
--- a/core/java/android/text/method/PasswordTransformationMethod.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.os.Handler;
-import android.os.SystemClock;
-import android.graphics.Rect;
-import android.view.View;
-import android.text.Editable;
-import android.text.GetChars;
-import android.text.NoCopySpan;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.text.Selection;
-import android.text.Spanned;
-import android.text.Spannable;
-import android.text.style.UpdateLayout;
-
-import java.lang.ref.WeakReference;
-
-public class PasswordTransformationMethod
-implements TransformationMethod, TextWatcher
-{
- public CharSequence getTransformation(CharSequence source, View view) {
- if (source instanceof Spannable) {
- Spannable sp = (Spannable) source;
-
- /*
- * Remove any references to other views that may still be
- * attached. This will happen when you flip the screen
- * while a password field is showing; there will still
- * be references to the old EditText in the text.
- */
- ViewReference[] vr = sp.getSpans(0, sp.length(),
- ViewReference.class);
- for (int i = 0; i < vr.length; i++) {
- sp.removeSpan(vr[i]);
- }
-
- sp.setSpan(new ViewReference(view), 0, 0,
- Spannable.SPAN_POINT_POINT);
- }
-
- return new PasswordCharSequence(source);
- }
-
- public static PasswordTransformationMethod getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new PasswordTransformationMethod();
- return sInstance;
- }
-
- public void beforeTextChanged(CharSequence s, int start,
- int count, int after) {
- // This callback isn't used.
- }
-
- public void onTextChanged(CharSequence s, int start,
- int before, int count) {
- if (s instanceof Spannable) {
- Spannable sp = (Spannable) s;
- ViewReference[] vr = sp.getSpans(0, s.length(),
- ViewReference.class);
- if (vr.length == 0) {
- return;
- }
-
- /*
- * There should generally only be one ViewReference in the text,
- * but make sure to look through all of them if necessary in case
- * something strange is going on. (We might still end up with
- * multiple ViewReferences if someone moves text from one password
- * field to another.)
- */
- View v = null;
- for (int i = 0; v == null && i < vr.length; i++) {
- v = vr[i].get();
- }
-
- if (v == null) {
- return;
- }
-
- int pref = TextKeyListener.getInstance().getPrefs(v.getContext());
- if ((pref & TextKeyListener.SHOW_PASSWORD) != 0) {
- if (count > 0) {
- Visible[] old = sp.getSpans(0, sp.length(), Visible.class);
- for (int i = 0; i < old.length; i++) {
- sp.removeSpan(old[i]);
- }
-
- if (count == 1) {
- sp.setSpan(new Visible(sp, this), start, start + count,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- }
- }
- }
-
- public void afterTextChanged(Editable s) {
- // This callback isn't used.
- }
-
- public void onFocusChanged(View view, CharSequence sourceText,
- boolean focused, int direction,
- Rect previouslyFocusedRect) {
- if (!focused) {
- if (sourceText instanceof Spannable) {
- Spannable sp = (Spannable) sourceText;
-
- Visible[] old = sp.getSpans(0, sp.length(), Visible.class);
- for (int i = 0; i < old.length; i++) {
- sp.removeSpan(old[i]);
- }
- }
- }
- }
-
- private static class PasswordCharSequence
- implements CharSequence, GetChars
- {
- public PasswordCharSequence(CharSequence source) {
- mSource = source;
- }
-
- public int length() {
- return mSource.length();
- }
-
- public char charAt(int i) {
- if (mSource instanceof Spanned) {
- Spanned sp = (Spanned) mSource;
-
- int st = sp.getSpanStart(TextKeyListener.ACTIVE);
- int en = sp.getSpanEnd(TextKeyListener.ACTIVE);
-
- if (i >= st && i < en) {
- return mSource.charAt(i);
- }
-
- Visible[] visible = sp.getSpans(0, sp.length(), Visible.class);
-
- for (int a = 0; a < visible.length; a++) {
- if (sp.getSpanStart(visible[a].mTransformer) >= 0) {
- st = sp.getSpanStart(visible[a]);
- en = sp.getSpanEnd(visible[a]);
-
- if (i >= st && i < en) {
- return mSource.charAt(i);
- }
- }
- }
- }
-
- return DOT;
- }
-
- public CharSequence subSequence(int start, int end) {
- char[] buf = new char[end - start];
-
- getChars(start, end, buf, 0);
- return new String(buf);
- }
-
- public String toString() {
- return subSequence(0, length()).toString();
- }
-
- public void getChars(int start, int end, char[] dest, int off) {
- TextUtils.getChars(mSource, start, end, dest, off);
-
- int st = -1, en = -1;
- int nvisible = 0;
- int[] starts = null, ends = null;
-
- if (mSource instanceof Spanned) {
- Spanned sp = (Spanned) mSource;
-
- st = sp.getSpanStart(TextKeyListener.ACTIVE);
- en = sp.getSpanEnd(TextKeyListener.ACTIVE);
-
- Visible[] visible = sp.getSpans(0, sp.length(), Visible.class);
- nvisible = visible.length;
- starts = new int[nvisible];
- ends = new int[nvisible];
-
- for (int i = 0; i < nvisible; i++) {
- if (sp.getSpanStart(visible[i].mTransformer) >= 0) {
- starts[i] = sp.getSpanStart(visible[i]);
- ends[i] = sp.getSpanEnd(visible[i]);
- }
- }
- }
-
- for (int i = start; i < end; i++) {
- if (! (i >= st && i < en)) {
- boolean visible = false;
-
- for (int a = 0; a < nvisible; a++) {
- if (i >= starts[a] && i < ends[a]) {
- visible = true;
- break;
- }
- }
-
- if (!visible) {
- dest[i - start + off] = DOT;
- }
- }
- }
- }
-
- private CharSequence mSource;
- }
-
- private static class Visible
- extends Handler
- implements UpdateLayout, Runnable
- {
- public Visible(Spannable sp, PasswordTransformationMethod ptm) {
- mText = sp;
- mTransformer = ptm;
- postAtTime(this, SystemClock.uptimeMillis() + 1500);
- }
-
- public void run() {
- mText.removeSpan(this);
- }
-
- private Spannable mText;
- private PasswordTransformationMethod mTransformer;
- }
-
- /**
- * Used to stash a reference back to the View in the Editable so we
- * can use it to check the settings.
- */
- private static class ViewReference extends WeakReference<View>
- implements NoCopySpan {
- public ViewReference(View v) {
- super(v);
- }
- }
-
- private static PasswordTransformationMethod sInstance;
- private static char DOT = '\u2022';
-}
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
deleted file mode 100644
index 0b39517..0000000
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.text.*;
-import android.text.method.TextKeyListener.Capitalize;
-import android.util.SparseArray;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.View;
-
-/**
- * This is the standard key listener for alphabetic input on qwerty
- * keyboards. You should generally not need to instantiate this yourself;
- * TextKeyListener will do it for you.
- */
-public class QwertyKeyListener extends BaseKeyListener {
- private static QwertyKeyListener[] sInstance =
- new QwertyKeyListener[Capitalize.values().length * 2];
-
- public QwertyKeyListener(Capitalize cap, boolean autotext) {
- mAutoCap = cap;
- mAutoText = autotext;
- }
-
- /**
- * Returns a new or existing instance with the specified capitalization
- * and correction properties.
- */
- public static QwertyKeyListener getInstance(boolean autotext,
- Capitalize cap) {
- int off = cap.ordinal() * 2 + (autotext ? 1 : 0);
-
- if (sInstance[off] == null) {
- sInstance[off] = new QwertyKeyListener(cap, autotext);
- }
-
- return sInstance[off];
- }
-
- public int getInputType() {
- return makeTextContentType(mAutoCap, mAutoText);
- }
-
- public boolean onKeyDown(View view, Editable content,
- int keyCode, KeyEvent event) {
- int selStart, selEnd;
- int pref = 0;
-
- if (view != null) {
- pref = TextKeyListener.getInstance().getPrefs(view.getContext());
- }
-
- {
- int a = Selection.getSelectionStart(content);
- int b = Selection.getSelectionEnd(content);
-
- selStart = Math.min(a, b);
- selEnd = Math.max(a, b);
-
- if (selStart < 0 || selEnd < 0) {
- selStart = selEnd = 0;
- Selection.setSelection(content, 0, 0);
- }
- }
-
- int activeStart = content.getSpanStart(TextKeyListener.ACTIVE);
- int activeEnd = content.getSpanEnd(TextKeyListener.ACTIVE);
-
- // QWERTY keyboard normal case
-
- int i = event.getUnicodeChar(getMetaState(content));
-
- int count = event.getRepeatCount();
- if (count > 0 && selStart == selEnd && selStart > 0) {
- char c = content.charAt(selStart - 1);
-
- if (c == i || c == Character.toUpperCase(i) && view != null) {
- if (showCharacterPicker(view, content, c, false, count)) {
- resetMetaState(content);
- return true;
- }
- }
- }
-
- if (i == KeyCharacterMap.PICKER_DIALOG_INPUT) {
- if (view != null) {
- showCharacterPicker(view, content,
- KeyCharacterMap.PICKER_DIALOG_INPUT, true, 1);
- }
- resetMetaState(content);
- return true;
- }
-
- if (i == KeyCharacterMap.HEX_INPUT) {
- int start;
-
- if (selStart == selEnd) {
- start = selEnd;
-
- while (start > 0 && selEnd - start < 4 &&
- Character.digit(content.charAt(start - 1), 16) >= 0) {
- start--;
- }
- } else {
- start = selStart;
- }
-
- int ch = -1;
- try {
- String hex = TextUtils.substring(content, start, selEnd);
- ch = Integer.parseInt(hex, 16);
- } catch (NumberFormatException nfe) { }
-
- if (ch >= 0) {
- selStart = start;
- Selection.setSelection(content, selStart, selEnd);
- i = ch;
- } else {
- i = 0;
- }
- }
-
- if (i != 0) {
- boolean dead = false;
-
- if ((i & KeyCharacterMap.COMBINING_ACCENT) != 0) {
- dead = true;
- i = i & KeyCharacterMap.COMBINING_ACCENT_MASK;
- }
-
- if (activeStart == selStart && activeEnd == selEnd) {
- boolean replace = false;
-
- if (selEnd - selStart - 1 == 0) {
- char accent = content.charAt(selStart);
- int composed = event.getDeadChar(accent, i);
-
- if (composed != 0) {
- i = composed;
- replace = true;
- }
- }
-
- if (!replace) {
- Selection.setSelection(content, selEnd);
- content.removeSpan(TextKeyListener.ACTIVE);
- selStart = selEnd;
- }
- }
-
- if ((pref & TextKeyListener.AUTO_CAP) != 0 &&
- Character.isLowerCase(i) &&
- TextKeyListener.shouldCap(mAutoCap, content, selStart)) {
- int where = content.getSpanEnd(TextKeyListener.CAPPED);
- int flags = content.getSpanFlags(TextKeyListener.CAPPED);
-
- if (where == selStart && (((flags >> 16) & 0xFFFF) == i)) {
- content.removeSpan(TextKeyListener.CAPPED);
- } else {
- flags = i << 16;
- i = Character.toUpperCase(i);
-
- if (selStart == 0)
- content.setSpan(TextKeyListener.CAPPED, 0, 0,
- Spannable.SPAN_MARK_MARK | flags);
- else
- content.setSpan(TextKeyListener.CAPPED,
- selStart - 1, selStart,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE |
- flags);
- }
- }
-
- if (selStart != selEnd) {
- Selection.setSelection(content, selEnd);
- }
- content.setSpan(OLD_SEL_START, selStart, selStart,
- Spannable.SPAN_MARK_MARK);
-
- content.replace(selStart, selEnd, String.valueOf((char) i));
-
- int oldStart = content.getSpanStart(OLD_SEL_START);
- selEnd = Selection.getSelectionEnd(content);
-
- if (oldStart < selEnd) {
- content.setSpan(TextKeyListener.LAST_TYPED,
- oldStart, selEnd,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-
- if (dead) {
- Selection.setSelection(content, oldStart, selEnd);
- content.setSpan(TextKeyListener.ACTIVE, oldStart, selEnd,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
-
- adjustMetaAfterKeypress(content);
-
- // potentially do autotext replacement if the character
- // that was typed was an autotext terminator
-
- if ((pref & TextKeyListener.AUTO_TEXT) != 0 && mAutoText &&
- (i == ' ' || i == '\t' || i == '\n' ||
- i == ',' || i == '.' || i == '!' || i == '?' ||
- i == '"' || Character.getType(i) == Character.END_PUNCTUATION) &&
- content.getSpanEnd(TextKeyListener.INHIBIT_REPLACEMENT)
- != oldStart) {
- int x;
-
- for (x = oldStart; x > 0; x--) {
- char c = content.charAt(x - 1);
- if (c != '\'' && !Character.isLetter(c)) {
- break;
- }
- }
-
- String rep = getReplacement(content, x, oldStart, view);
-
- if (rep != null) {
- Replaced[] repl = content.getSpans(0, content.length(),
- Replaced.class);
- for (int a = 0; a < repl.length; a++)
- content.removeSpan(repl[a]);
-
- char[] orig = new char[oldStart - x];
- TextUtils.getChars(content, x, oldStart, orig, 0);
-
- content.setSpan(new Replaced(orig), x, oldStart,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- content.replace(x, oldStart, rep);
- }
- }
-
- // Replace two spaces by a period and a space.
-
- if ((pref & TextKeyListener.AUTO_PERIOD) != 0 && mAutoText) {
- selEnd = Selection.getSelectionEnd(content);
- if (selEnd - 3 >= 0) {
- if (content.charAt(selEnd - 1) == ' ' &&
- content.charAt(selEnd - 2) == ' ') {
- char c = content.charAt(selEnd - 3);
-
- for (int j = selEnd - 3; j > 0; j--) {
- if (c == '"' ||
- Character.getType(c) == Character.END_PUNCTUATION) {
- c = content.charAt(j - 1);
- } else {
- break;
- }
- }
-
- if (Character.isLetter(c) || Character.isDigit(c)) {
- content.replace(selEnd - 2, selEnd - 1, ".");
- }
- }
- }
- }
-
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_DEL && selStart == selEnd) {
- // special backspace case for undoing autotext
-
- int consider = 1;
-
- // if backspacing over the last typed character,
- // it undoes the autotext prior to that character
- // (unless the character typed was newline, in which
- // case this behavior would be confusing)
-
- if (content.getSpanEnd(TextKeyListener.LAST_TYPED) == selStart) {
- if (content.charAt(selStart - 1) != '\n')
- consider = 2;
- }
-
- Replaced[] repl = content.getSpans(selStart - consider, selStart,
- Replaced.class);
-
- if (repl.length > 0) {
- int st = content.getSpanStart(repl[0]);
- int en = content.getSpanEnd(repl[0]);
- String old = new String(repl[0].mText);
-
- content.removeSpan(repl[0]);
- content.setSpan(TextKeyListener.INHIBIT_REPLACEMENT,
- en, en, Spannable.SPAN_POINT_POINT);
- content.replace(st, en, old);
-
- en = content.getSpanStart(TextKeyListener.INHIBIT_REPLACEMENT);
- if (en - 1 >= 0) {
- content.setSpan(TextKeyListener.INHIBIT_REPLACEMENT,
- en - 1, en,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- } else {
- content.removeSpan(TextKeyListener.INHIBIT_REPLACEMENT);
- }
-
- adjustMetaAfterKeypress(content);
-
- return true;
- }
- }
-
- return super.onKeyDown(view, content, keyCode, event);
- }
-
- private String getReplacement(CharSequence src, int start, int end,
- View view) {
- int len = end - start;
- boolean changecase = false;
-
- String replacement = AutoText.get(src, start, end, view);
-
- if (replacement == null) {
- String key = TextUtils.substring(src, start, end).toLowerCase();
- replacement = AutoText.get(key, 0, end - start, view);
- changecase = true;
-
- if (replacement == null)
- return null;
- }
-
- int caps = 0;
-
- if (changecase) {
- for (int j = start; j < end; j++) {
- if (Character.isUpperCase(src.charAt(j)))
- caps++;
- }
- }
-
- String out;
-
- if (caps == 0)
- out = replacement;
- else if (caps == 1)
- out = toTitleCase(replacement);
- else if (caps == len)
- out = replacement.toUpperCase();
- else
- out = toTitleCase(replacement);
-
- if (out.length() == len &&
- TextUtils.regionMatches(src, start, out, 0, len))
- return null;
-
- return out;
- }
-
- /**
- * Marks the specified region of <code>content</code> as having
- * contained <code>original</code> prior to AutoText replacement.
- * Call this method when you have done or are about to do an
- * AutoText-style replacement on a region of text and want to let
- * the same mechanism (the user pressing DEL immediately after the
- * change) undo the replacement.
- *
- * @param content the Editable text where the replacement was made
- * @param start the start of the replaced region
- * @param end the end of the replaced region; the location of the cursor
- * @param original the text to be restored if the user presses DEL
- */
- public static void markAsReplaced(Spannable content, int start, int end,
- String original) {
- Replaced[] repl = content.getSpans(0, content.length(), Replaced.class);
- for (int a = 0; a < repl.length; a++) {
- content.removeSpan(repl[a]);
- }
-
- int len = original.length();
- char[] orig = new char[len];
- original.getChars(0, len, orig, 0);
-
- content.setSpan(new Replaced(orig), start, end,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
- private static SparseArray<String> PICKER_SETS =
- new SparseArray<String>();
- static {
- PICKER_SETS.put('!', "\u00A1");
- PICKER_SETS.put('<', "\u00AB");
- PICKER_SETS.put('>', "\u00BB");
- PICKER_SETS.put('?', "\u00BF");
- PICKER_SETS.put('A', "\u00C0\u00C1\u00C2\u00C4\u00C6\u00C3\u00C5");
- PICKER_SETS.put('C', "\u00C7");
- PICKER_SETS.put('E', "\u00C8\u00C9\u00CA\u00CB");
- PICKER_SETS.put('I', "\u00CC\u00CD\u00CE\u00CF");
- PICKER_SETS.put('N', "\u00D1");
- PICKER_SETS.put('O', "\u00D8\u0152\u00D5\u00D2\u00D3\u00D4\u00D6");
- PICKER_SETS.put('U', "\u00D9\u00DA\u00DB\u00DC");
- PICKER_SETS.put('Y', "\u00DD\u0178");
- PICKER_SETS.put('a', "\u00E0\u00E1\u00E2\u00E4\u00E6\u00E3\u00E5");
- PICKER_SETS.put('c', "\u00E7");
- PICKER_SETS.put('e', "\u00E8\u00E9\u00EA\u00EB");
- PICKER_SETS.put('i', "\u00EC\u00ED\u00EE\u00EF");
- PICKER_SETS.put('n', "\u00F1");
- PICKER_SETS.put('o', "\u00F8\u0153\u00F5\u00F2\u00F3\u00F4\u00F6");
- PICKER_SETS.put('s', "\u00A7\u00DF");
- PICKER_SETS.put('u', "\u00F9\u00FA\u00FB\u00FC");
- PICKER_SETS.put('y', "\u00FD\u00FF");
- PICKER_SETS.put(KeyCharacterMap.PICKER_DIALOG_INPUT,
- "\u2026\u00A5\u2022\u00AE\u00A9\u00B1");
- };
-
- private boolean showCharacterPicker(View view, Editable content, char c,
- boolean insert, int count) {
- String set = PICKER_SETS.get(c);
- if (set == null) {
- return false;
- }
-
- if (count == 1) {
- new CharacterPickerDialog(view.getContext(),
- view, content, set, insert).show();
- }
-
- return true;
- }
-
- private static String toTitleCase(String src) {
- return Character.toUpperCase(src.charAt(0)) + src.substring(1);
- }
-
- /* package */ static class Replaced implements NoCopySpan
- {
- public Replaced(char[] text) {
- mText = text;
- }
-
- private char[] mText;
- }
-
- private Capitalize mAutoCap;
- private boolean mAutoText;
-}
-
diff --git a/core/java/android/text/method/ReplacementTransformationMethod.java b/core/java/android/text/method/ReplacementTransformationMethod.java
deleted file mode 100644
index d6f879a..0000000
--- a/core/java/android/text/method/ReplacementTransformationMethod.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.graphics.Rect;
-import android.text.Editable;
-import android.text.GetChars;
-import android.text.Spannable;
-import android.text.Spanned;
-import android.text.SpannedString;
-import android.text.TextUtils;
-import android.view.View;
-
-/**
- * This transformation method causes the characters in the {@link #getOriginal}
- * array to be replaced by the corresponding characters in the
- * {@link #getReplacement} array.
- */
-public abstract class ReplacementTransformationMethod
-implements TransformationMethod
-{
- /**
- * Returns the list of characters that are to be replaced by other
- * characters when displayed.
- */
- protected abstract char[] getOriginal();
- /**
- * Returns a parallel array of replacement characters for the ones
- * that are to be replaced.
- */
- protected abstract char[] getReplacement();
-
- /**
- * Returns a CharSequence that will mirror the contents of the
- * source CharSequence but with the characters in {@link #getOriginal}
- * replaced by ones from {@link #getReplacement}.
- */
- public CharSequence getTransformation(CharSequence source, View v) {
- char[] original = getOriginal();
- char[] replacement = getReplacement();
-
- /*
- * Short circuit for faster display if the text will never change.
- */
- if (!(source instanceof Editable)) {
- /*
- * Check whether the text does not contain any of the
- * source characters so can be used unchanged.
- */
- boolean doNothing = true;
- int n = original.length;
- for (int i = 0; i < n; i++) {
- if (TextUtils.indexOf(source, original[i]) >= 0) {
- doNothing = false;
- break;
- }
- }
- if (doNothing) {
- return source;
- }
-
- if (!(source instanceof Spannable)) {
- /*
- * The text contains some of the source characters,
- * but they can be flattened out now instead of
- * at display time.
- */
- if (source instanceof Spanned) {
- return new SpannedString(new SpannedReplacementCharSequence(
- (Spanned) source,
- original, replacement));
- } else {
- return new ReplacementCharSequence(source,
- original,
- replacement).toString();
- }
- }
- }
-
- if (source instanceof Spanned) {
- return new SpannedReplacementCharSequence((Spanned) source,
- original, replacement);
- } else {
- return new ReplacementCharSequence(source, original, replacement);
- }
- }
-
- public void onFocusChanged(View view, CharSequence sourceText,
- boolean focused, int direction,
- Rect previouslyFocusedRect) {
- // This callback isn't used.
- }
-
- private static class ReplacementCharSequence
- implements CharSequence, GetChars {
- private char[] mOriginal, mReplacement;
-
- public ReplacementCharSequence(CharSequence source, char[] original,
- char[] replacement) {
- mSource = source;
- mOriginal = original;
- mReplacement = replacement;
- }
-
- public int length() {
- return mSource.length();
- }
-
- public char charAt(int i) {
- char c = mSource.charAt(i);
-
- int n = mOriginal.length;
- for (int j = 0; j < n; j++) {
- if (c == mOriginal[j]) {
- c = mReplacement[j];
- }
- }
-
- return c;
- }
-
- public CharSequence subSequence(int start, int end) {
- char[] c = new char[end - start];
-
- getChars(start, end, c, 0);
- return new String(c);
- }
-
- public String toString() {
- char[] c = new char[length()];
-
- getChars(0, length(), c, 0);
- return new String(c);
- }
-
- public void getChars(int start, int end, char[] dest, int off) {
- TextUtils.getChars(mSource, start, end, dest, off);
- int offend = end - start + off;
- int n = mOriginal.length;
-
- for (int i = off; i < offend; i++) {
- char c = dest[i];
-
- for (int j = 0; j < n; j++) {
- if (c == mOriginal[j]) {
- dest[i] = mReplacement[j];
- }
- }
- }
- }
-
- private CharSequence mSource;
- }
-
- private static class SpannedReplacementCharSequence
- extends ReplacementCharSequence
- implements Spanned
- {
- public SpannedReplacementCharSequence(Spanned source, char[] original,
- char[] replacement) {
- super(source, original, replacement);
- mSpanned = source;
- }
-
- public CharSequence subSequence(int start, int end) {
- return new SpannedString(this).subSequence(start, end);
- }
-
- public <T> T[] getSpans(int start, int end, Class<T> type) {
- return mSpanned.getSpans(start, end, type);
- }
-
- public int getSpanStart(Object tag) {
- return mSpanned.getSpanStart(tag);
- }
-
- public int getSpanEnd(Object tag) {
- return mSpanned.getSpanEnd(tag);
- }
-
- public int getSpanFlags(Object tag) {
- return mSpanned.getSpanFlags(tag);
- }
-
- public int nextSpanTransition(int start, int end, Class type) {
- return mSpanned.nextSpanTransition(start, end, type);
- }
-
- private Spanned mSpanned;
- }
-}
diff --git a/core/java/android/text/method/ScrollingMovementMethod.java b/core/java/android/text/method/ScrollingMovementMethod.java
deleted file mode 100644
index 563ceed..0000000
--- a/core/java/android/text/method/ScrollingMovementMethod.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.text.*;
-import android.widget.TextView;
-import android.view.View;
-
-public class
-ScrollingMovementMethod
-implements MovementMethod
-{
- /**
- * Scrolls the text to the left if possible.
- */
- protected boolean left(TextView widget, Spannable buffer) {
- Layout layout = widget.getLayout();
-
- int scrolly = widget.getScrollY();
- int scr = widget.getScrollX();
- int em = Math.round(layout.getPaint().getFontSpacing());
-
- int padding = widget.getTotalPaddingTop() +
- widget.getTotalPaddingBottom();
- int top = layout.getLineForVertical(scrolly);
- int bottom = layout.getLineForVertical(scrolly + widget.getHeight() -
- padding);
- int left = Integer.MAX_VALUE;
-
- for (int i = top; i <= bottom; i++) {
- left = (int) Math.min(left, layout.getLineLeft(i));
- }
-
- if (scr > left) {
- int s = Math.max(scr - em, left);
- widget.scrollTo(s, widget.getScrollY());
- return true;
- }
-
- return false;
- }
-
- /**
- * Scrolls the text to the right if possible.
- */
- protected boolean right(TextView widget, Spannable buffer) {
- Layout layout = widget.getLayout();
-
- int scrolly = widget.getScrollY();
- int scr = widget.getScrollX();
- int em = Math.round(layout.getPaint().getFontSpacing());
-
- int padding = widget.getTotalPaddingTop() +
- widget.getTotalPaddingBottom();
- int top = layout.getLineForVertical(scrolly);
- int bottom = layout.getLineForVertical(scrolly + widget.getHeight() -
- padding);
- int right = 0;
-
- for (int i = top; i <= bottom; i++) {
- right = (int) Math.max(right, layout.getLineRight(i));
- }
-
- padding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight();
- if (scr < right - (widget.getWidth() - padding)) {
- int s = Math.min(scr + em, right - (widget.getWidth() - padding));
- widget.scrollTo(s, widget.getScrollY());
- return true;
- }
-
- return false;
- }
-
- /**
- * Scrolls the text up if possible.
- */
- protected boolean up(TextView widget, Spannable buffer) {
- Layout layout = widget.getLayout();
-
- int areatop = widget.getScrollY();
- int line = layout.getLineForVertical(areatop);
- int linetop = layout.getLineTop(line);
-
- // If the top line is partially visible, bring it all the way
- // into view; otherwise, bring the previous line into view.
- if (areatop == linetop)
- line--;
-
- if (line >= 0) {
- Touch.scrollTo(widget, layout,
- widget.getScrollX(), layout.getLineTop(line));
- return true;
- }
-
- return false;
- }
-
- /**
- * Scrolls the text down if possible.
- */
- protected boolean down(TextView widget, Spannable buffer) {
- Layout layout = widget.getLayout();
-
- int padding = widget.getTotalPaddingTop() +
- widget.getTotalPaddingBottom();
-
- int areabot = widget.getScrollY() + widget.getHeight() - padding;
- int line = layout.getLineForVertical(areabot);
-
- if (layout.getLineTop(line+1) < areabot + 1) {
- // Less than a pixel of this line is out of view,
- // so we must have tried to make it entirely in view
- // and now want the next line to be in view instead.
-
- line++;
- }
-
- if (line <= layout.getLineCount() - 1) {
- widget.scrollTo(widget.getScrollX(), layout.getLineTop(line+1) -
- (widget.getHeight() - padding));
- Touch.scrollTo(widget, layout,
- widget.getScrollX(), widget.getScrollY());
- return true;
- }
-
- return false;
- }
-
- public boolean onKeyDown(TextView widget, Spannable buffer, int keyCode, KeyEvent event) {
- return executeDown(widget, buffer, keyCode);
- }
-
- private boolean executeDown(TextView widget, Spannable buffer, int keyCode) {
- boolean handled = false;
-
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- handled |= left(widget, buffer);
- break;
-
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- handled |= right(widget, buffer);
- break;
-
- case KeyEvent.KEYCODE_DPAD_UP:
- handled |= up(widget, buffer);
- break;
-
- case KeyEvent.KEYCODE_DPAD_DOWN:
- handled |= down(widget, buffer);
- break;
- }
-
- return handled;
- }
-
- public boolean onKeyUp(TextView widget, Spannable buffer, int keyCode, KeyEvent event) {
- return false;
- }
-
- public boolean onKeyOther(TextView view, Spannable text, KeyEvent event) {
- int code = event.getKeyCode();
- if (code != KeyEvent.KEYCODE_UNKNOWN
- && event.getAction() == KeyEvent.ACTION_MULTIPLE) {
- int repeat = event.getRepeatCount();
- boolean first = true;
- boolean handled = false;
- while ((--repeat) > 0) {
- if (first && executeDown(view, text, code)) {
- handled = true;
- MetaKeyKeyListener.adjustMetaAfterKeypress(text);
- MetaKeyKeyListener.resetLockedMeta(text);
- }
- first = false;
- }
- return handled;
- }
- return false;
- }
-
- public boolean onTrackballEvent(TextView widget, Spannable text,
- MotionEvent event) {
- return false;
- }
-
- public boolean onTouchEvent(TextView widget, Spannable buffer,
- MotionEvent event) {
- return Touch.onTouchEvent(widget, buffer, event);
- }
-
- public void initialize(TextView widget, Spannable text) { }
-
- public boolean canSelectArbitrarily() {
- return false;
- }
-
- public void onTakeFocus(TextView widget, Spannable text, int dir) {
- Layout layout = widget.getLayout();
-
- if (layout != null && (dir & View.FOCUS_FORWARD) != 0) {
- widget.scrollTo(widget.getScrollX(),
- layout.getLineTop(0));
- }
- if (layout != null && (dir & View.FOCUS_BACKWARD) != 0) {
- int padding = widget.getTotalPaddingTop() +
- widget.getTotalPaddingBottom();
- int line = layout.getLineCount() - 1;
-
- widget.scrollTo(widget.getScrollX(),
- layout.getLineTop(line+1) -
- (widget.getHeight() - padding));
- }
- }
-
- public static MovementMethod getInstance() {
- if (sInstance == null)
- sInstance = new ScrollingMovementMethod();
-
- return sInstance;
- }
-
- private static ScrollingMovementMethod sInstance;
-}
diff --git a/core/java/android/text/method/SingleLineTransformationMethod.java b/core/java/android/text/method/SingleLineTransformationMethod.java
deleted file mode 100644
index 6a05fe4..0000000
--- a/core/java/android/text/method/SingleLineTransformationMethod.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.graphics.Rect;
-import android.text.Editable;
-import android.text.GetChars;
-import android.text.Spannable;
-import android.text.Spanned;
-import android.text.SpannedString;
-import android.text.TextUtils;
-import android.view.View;
-
-/**
- * This transformation method causes any newline characters (\n) to be
- * displayed as spaces instead of causing line breaks, and causes
- * carriage return characters (\r) to have no appearance.
- */
-public class SingleLineTransformationMethod
-extends ReplacementTransformationMethod {
- private static char[] ORIGINAL = new char[] { '\n', '\r' };
- private static char[] REPLACEMENT = new char[] { ' ', '\uFEFF' };
-
- /**
- * The characters to be replaced are \n and \r.
- */
- protected char[] getOriginal() {
- return ORIGINAL;
- }
-
- /**
- * The character \n is replaced with is space;
- * the character \r is replaced with is FEFF (zero width space).
- */
- protected char[] getReplacement() {
- return REPLACEMENT;
- }
-
- public static SingleLineTransformationMethod getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new SingleLineTransformationMethod();
- return sInstance;
- }
-
- private static SingleLineTransformationMethod sInstance;
-}
diff --git a/core/java/android/text/method/TextKeyListener.java b/core/java/android/text/method/TextKeyListener.java
deleted file mode 100644
index 5be2a48..0000000
--- a/core/java/android/text/method/TextKeyListener.java
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.provider.Settings;
-import android.provider.Settings.System;
-import android.text.*;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.View;
-import android.text.InputType;
-
-import java.lang.ref.WeakReference;
-
-/**
- * This is the key listener for typing normal text. It delegates to
- * other key listeners appropriate to the current keyboard and language.
- */
-public class TextKeyListener extends BaseKeyListener implements SpanWatcher {
- private static TextKeyListener[] sInstance =
- new TextKeyListener[Capitalize.values().length * 2];
-
- /* package */ static final Object ACTIVE = new NoCopySpan.Concrete();
- /* package */ static final Object CAPPED = new NoCopySpan.Concrete();
- /* package */ static final Object INHIBIT_REPLACEMENT = new NoCopySpan.Concrete();
- /* package */ static final Object LAST_TYPED = new NoCopySpan.Concrete();
-
- private Capitalize mAutoCap;
- private boolean mAutoText;
-
- private int mPrefs;
- private boolean mPrefsInited;
-
- /* package */ static final int AUTO_CAP = 1;
- /* package */ static final int AUTO_TEXT = 2;
- /* package */ static final int AUTO_PERIOD = 4;
- /* package */ static final int SHOW_PASSWORD = 8;
- private WeakReference<ContentResolver> mResolver;
- private TextKeyListener.SettingsObserver mObserver;
-
- /**
- * Creates a new TextKeyListener with the specified capitalization
- * and correction properties.
- *
- * @param cap when, if ever, to automatically capitalize.
- * @param autotext whether to automatically do spelling corrections.
- */
- public TextKeyListener(Capitalize cap, boolean autotext) {
- mAutoCap = cap;
- mAutoText = autotext;
- }
-
- /**
- * Returns a new or existing instance with the specified capitalization
- * and correction properties.
- *
- * @param cap when, if ever, to automatically capitalize.
- * @param autotext whether to automatically do spelling corrections.
- */
- public static TextKeyListener getInstance(boolean autotext,
- Capitalize cap) {
- int off = cap.ordinal() * 2 + (autotext ? 1 : 0);
-
- if (sInstance[off] == null) {
- sInstance[off] = new TextKeyListener(cap, autotext);
- }
-
- return sInstance[off];
- }
-
- /**
- * Returns a new or existing instance with no automatic capitalization
- * or correction.
- */
- public static TextKeyListener getInstance() {
- return getInstance(false, Capitalize.NONE);
- }
-
- /**
- * Returns whether it makes sense to automatically capitalize at the
- * specified position in the specified text, with the specified rules.
- *
- * @param cap the capitalization rules to consider.
- * @param cs the text in which an insertion is being made.
- * @param off the offset into that text where the insertion is being made.
- *
- * @return whether the character being inserted should be capitalized.
- */
- public static boolean shouldCap(Capitalize cap, CharSequence cs, int off) {
- int i;
- char c;
-
- if (cap == Capitalize.NONE) {
- return false;
- }
- if (cap == Capitalize.CHARACTERS) {
- return true;
- }
-
- return TextUtils.getCapsMode(cs, off, cap == Capitalize.WORDS
- ? TextUtils.CAP_MODE_WORDS : TextUtils.CAP_MODE_SENTENCES)
- != 0;
- }
-
- public int getInputType() {
- return makeTextContentType(mAutoCap, mAutoText);
- }
-
- @Override
- public boolean onKeyDown(View view, Editable content,
- int keyCode, KeyEvent event) {
- KeyListener im = getKeyListener(event);
-
- return im.onKeyDown(view, content, keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(View view, Editable content,
- int keyCode, KeyEvent event) {
- KeyListener im = getKeyListener(event);
-
- return im.onKeyUp(view, content, keyCode, event);
- }
-
- @Override
- public boolean onKeyOther(View view, Editable content, KeyEvent event) {
- KeyListener im = getKeyListener(event);
-
- return im.onKeyOther(view, content, event);
- }
-
- /**
- * Clear all the input state (autotext, autocap, multitap, undo)
- * from the specified Editable, going beyond Editable.clear(), which
- * just clears the text but not the input state.
- *
- * @param e the buffer whose text and state are to be cleared.
- */
- public static void clear(Editable e) {
- e.clear();
- e.removeSpan(ACTIVE);
- e.removeSpan(CAPPED);
- e.removeSpan(INHIBIT_REPLACEMENT);
- e.removeSpan(LAST_TYPED);
-
- QwertyKeyListener.Replaced[] repl = e.getSpans(0, e.length(),
- QwertyKeyListener.Replaced.class);
- final int count = repl.length;
- for (int i = 0; i < count; i++) {
- e.removeSpan(repl[i]);
- }
- }
-
- public void onSpanAdded(Spannable s, Object what, int start, int end) { }
- public void onSpanRemoved(Spannable s, Object what, int start, int end) { }
-
- public void onSpanChanged(Spannable s, Object what, int start, int end,
- int st, int en) {
- if (what == Selection.SELECTION_END) {
- s.removeSpan(ACTIVE);
- }
- }
-
- private KeyListener getKeyListener(KeyEvent event) {
- KeyCharacterMap kmap = KeyCharacterMap.load(event.getKeyboardDevice());
- int kind = kmap.getKeyboardType();
-
- if (kind == KeyCharacterMap.ALPHA) {
- return QwertyKeyListener.getInstance(mAutoText, mAutoCap);
- } else if (kind == KeyCharacterMap.NUMERIC) {
- return MultiTapKeyListener.getInstance(mAutoText, mAutoCap);
- }
-
- return NullKeyListener.getInstance();
- }
-
- public enum Capitalize {
- NONE, SENTENCES, WORDS, CHARACTERS,
- }
-
- private static class NullKeyListener implements KeyListener
- {
- public int getInputType() {
- return InputType.TYPE_NULL;
- }
-
- public boolean onKeyDown(View view, Editable content,
- int keyCode, KeyEvent event) {
- return false;
- }
-
- public boolean onKeyUp(View view, Editable content, int keyCode,
- KeyEvent event) {
- return false;
- }
-
- public boolean onKeyOther(View view, Editable content, KeyEvent event) {
- return false;
- }
-
- public void clearMetaKeyState(View view, Editable content, int states) {
- }
-
- public static NullKeyListener getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new NullKeyListener();
- return sInstance;
- }
-
- private static NullKeyListener sInstance;
- }
-
- public void release() {
- if (mResolver != null) {
- final ContentResolver contentResolver = mResolver.get();
- if (contentResolver != null) {
- contentResolver.unregisterContentObserver(mObserver);
- mResolver.clear();
- }
- mObserver = null;
- mResolver = null;
- mPrefsInited = false;
- }
- }
-
- private void initPrefs(Context context) {
- final ContentResolver contentResolver = context.getContentResolver();
- mResolver = new WeakReference<ContentResolver>(contentResolver);
- mObserver = new SettingsObserver();
- contentResolver.registerContentObserver(Settings.System.CONTENT_URI, true, mObserver);
-
- updatePrefs(contentResolver);
- mPrefsInited = true;
- }
-
- private class SettingsObserver extends ContentObserver {
- public SettingsObserver() {
- super(new Handler());
- }
-
- @Override
- public void onChange(boolean selfChange) {
- if (mResolver != null) {
- final ContentResolver contentResolver = mResolver.get();
- if (contentResolver == null) {
- mPrefsInited = false;
- } else {
- updatePrefs(contentResolver);
- }
- } else {
- mPrefsInited = false;
- }
- }
- }
-
- private void updatePrefs(ContentResolver resolver) {
- boolean cap = System.getInt(resolver, System.TEXT_AUTO_CAPS, 1) > 0;
- boolean text = System.getInt(resolver, System.TEXT_AUTO_REPLACE, 1) > 0;
- boolean period = System.getInt(resolver, System.TEXT_AUTO_PUNCTUATE, 1) > 0;
- boolean pw = System.getInt(resolver, System.TEXT_SHOW_PASSWORD, 1) > 0;
-
- mPrefs = (cap ? AUTO_CAP : 0) |
- (text ? AUTO_TEXT : 0) |
- (period ? AUTO_PERIOD : 0) |
- (pw ? SHOW_PASSWORD : 0);
- }
-
- /* package */ int getPrefs(Context context) {
- synchronized (this) {
- if (!mPrefsInited || mResolver.get() == null) {
- initPrefs(context);
- }
- }
-
- return mPrefs;
- }
-}
diff --git a/core/java/android/text/method/TimeKeyListener.java b/core/java/android/text/method/TimeKeyListener.java
deleted file mode 100644
index 3fbfd8c..0000000
--- a/core/java/android/text/method/TimeKeyListener.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.view.KeyEvent;
-import android.text.InputType;
-
-/**
- * For entering times in a text field.
- */
-public class TimeKeyListener extends NumberKeyListener
-{
- public int getInputType() {
- return InputType.TYPE_CLASS_DATETIME
- | InputType.TYPE_DATETIME_VARIATION_TIME;
- }
-
- @Override
- protected char[] getAcceptedChars()
- {
- return CHARACTERS;
- }
-
- public static TimeKeyListener getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new TimeKeyListener();
- return sInstance;
- }
-
- /**
- * The characters that are used.
- *
- * @see KeyEvent#getMatch
- * @see #getAcceptedChars
- */
- public static final char[] CHARACTERS = new char[] {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'm',
- 'p', ':'
- };
-
- private static TimeKeyListener sInstance;
-}
diff --git a/core/java/android/text/method/Touch.java b/core/java/android/text/method/Touch.java
deleted file mode 100644
index 65036ad..0000000
--- a/core/java/android/text/method/Touch.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.text.Layout;
-import android.text.NoCopySpan;
-import android.text.Layout.Alignment;
-import android.text.Spannable;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.widget.TextView;
-
-public class Touch {
- private Touch() { }
-
- /**
- * Scrolls the specified widget to the specified coordinates, except
- * constrains the X scrolling position to the horizontal regions of
- * the text that will be visible after scrolling to the specified
- * Y position.
- */
- public static void scrollTo(TextView widget, Layout layout, int x, int y) {
- int padding = widget.getTotalPaddingTop() +
- widget.getTotalPaddingBottom();
- int top = layout.getLineForVertical(y);
- int bottom = layout.getLineForVertical(y + widget.getHeight() -
- padding);
-
- int left = Integer.MAX_VALUE;
- int right = 0;
- Alignment a = null;
-
- for (int i = top; i <= bottom; i++) {
- left = (int) Math.min(left, layout.getLineLeft(i));
- right = (int) Math.max(right, layout.getLineRight(i));
-
- if (a == null) {
- a = layout.getParagraphAlignment(i);
- }
- }
-
- padding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight();
- int width = widget.getWidth();
- int diff = 0;
-
- if (right - left < width - padding) {
- if (a == Alignment.ALIGN_CENTER) {
- diff = (width - padding - (right - left)) / 2;
- } else if (a == Alignment.ALIGN_OPPOSITE) {
- diff = width - padding - (right - left);
- }
- }
-
- x = Math.min(x, right - (width - padding) - diff);
- x = Math.max(x, left - diff);
-
- widget.scrollTo(x, y);
- }
-
- /**
- * Handles touch events for dragging. You may want to do other actions
- * like moving the cursor on touch as well.
- */
- public static boolean onTouchEvent(TextView widget, Spannable buffer,
- MotionEvent event) {
- DragState[] ds;
-
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- buffer.setSpan(new DragState(event.getX(), event.getY()),
- 0, 0, Spannable.SPAN_MARK_MARK);
- return true;
-
- case MotionEvent.ACTION_UP:
- ds = buffer.getSpans(0, buffer.length(), DragState.class);
-
- for (int i = 0; i < ds.length; i++) {
- buffer.removeSpan(ds[i]);
- }
-
- if (ds.length > 0 && ds[0].mUsed) {
- return true;
- } else {
- return false;
- }
-
- case MotionEvent.ACTION_MOVE:
- ds = buffer.getSpans(0, buffer.length(), DragState.class);
-
- if (ds.length > 0) {
- if (ds[0].mFarEnough == false) {
- int slop = ViewConfiguration.get(widget.getContext()).getScaledTouchSlop();
-
- if (Math.abs(event.getX() - ds[0].mX) >= slop ||
- Math.abs(event.getY() - ds[0].mY) >= slop) {
- ds[0].mFarEnough = true;
- }
- }
-
- if (ds[0].mFarEnough) {
- ds[0].mUsed = true;
-
- float dx = ds[0].mX - event.getX();
- float dy = ds[0].mY - event.getY();
-
- ds[0].mX = event.getX();
- ds[0].mY = event.getY();
-
- int nx = widget.getScrollX() + (int) dx;
- int ny = widget.getScrollY() + (int) dy;
-
- int padding = widget.getTotalPaddingTop() +
- widget.getTotalPaddingBottom();
- Layout layout = widget.getLayout();
-
- ny = Math.min(ny, layout.getHeight() - (widget.getHeight() -
- padding));
- ny = Math.max(ny, 0);
-
- scrollTo(widget, layout, nx, ny);
- widget.cancelLongPress();
- return true;
- }
- }
- }
-
- return false;
- }
-
- private static class DragState implements NoCopySpan {
- public float mX;
- public float mY;
- public boolean mFarEnough;
- public boolean mUsed;
-
- public DragState(float x, float y) {
- mX = x;
- mY = y;
- }
- }
-}
diff --git a/core/java/android/text/method/TransformationMethod.java b/core/java/android/text/method/TransformationMethod.java
deleted file mode 100644
index 9f51c2a..0000000
--- a/core/java/android/text/method/TransformationMethod.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.method;
-
-import android.graphics.Rect;
-import android.view.View;
-import android.widget.TextView;
-
-/**
- * TextView uses TransformationMethods to do things like replacing the
- * characters of passwords with dots, or keeping the newline characters
- * from causing line breaks in single-line text fields.
- */
-public interface TransformationMethod
-{
- /**
- * Returns a CharSequence that is a transformation of the source text --
- * for example, replacing each character with a dot in a password field.
- * Beware that the returned text must be exactly the same length as
- * the source text, and that if the source text is Editable, the returned
- * text must mirror it dynamically instead of doing a one-time copy.
- */
- public CharSequence getTransformation(CharSequence source, View view);
-
- /**
- * This method is called when the TextView that uses this
- * TransformationMethod gains or loses focus.
- */
- public void onFocusChanged(View view, CharSequence sourceText,
- boolean focused, int direction,
- Rect previouslyFocusedRect);
-}
diff --git a/core/java/android/text/method/package.html b/core/java/android/text/method/package.html
deleted file mode 100644
index 93698b8..0000000
--- a/core/java/android/text/method/package.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<html>
-<body>
-
-<p>Provides classes that monitor or modify keypad input.</p>
-<p>You can use these classes to modify the type of keypad entry
-for your application, or decipher the keypresses entered for your specific
-entry method. For example:</p>
-<pre>
-// Set the text to password display style:
-EditText txtView = (EditText)findViewById(R.id.text);
-txtView.setTransformationMethod(PasswordTransformationMethod.getInstance());
-
-//Set the input style to numbers, rather than qwerty keyboard style.
-txtView.setInputMethod(DigitsInputMethod.getInstance());
-
-// Find out whether the caps lock is on.
-// 0 is no, 1 is yes, 2 is caps lock on.
-int active = MultiTapInputMethod.getCapsActive(txtView.getText());
-</pre>
-</body>
-</html>
diff --git a/core/java/android/text/package.html b/core/java/android/text/package.html
deleted file mode 100644
index 162dcd8..0000000
--- a/core/java/android/text/package.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<html>
-<body>
-
-<p>Provides classes used to render or track text and text spans on the screen.</p>
-<p>You can use these classes to design your own widgets that manage text,
-to handle arbitrary text spans for changes, or to handle drawing yourself
-for an existing widget.</p>
-<p>The Span&hellip; interfaces and classes are used to create or manage spans of
-text in a View item. You can use these to style the text or background, or to
-listen for changes. If creating your own widget, extend DynamicLayout, to manages
-the actual wrapping and drawing of your text.
-</body>
-</html>
diff --git a/core/java/android/text/style/AbsoluteSizeSpan.java b/core/java/android/text/style/AbsoluteSizeSpan.java
deleted file mode 100644
index 484f8ce..0000000
--- a/core/java/android/text/style/AbsoluteSizeSpan.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class AbsoluteSizeSpan extends MetricAffectingSpan implements ParcelableSpan {
-
- private final int mSize;
-
- public AbsoluteSizeSpan(int size) {
- mSize = size;
- }
-
- public AbsoluteSizeSpan(Parcel src) {
- mSize = src.readInt();
- }
-
- public int getSpanTypeId() {
- return TextUtils.ABSOLUTE_SIZE_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mSize);
- }
-
- public int getSize() {
- return mSize;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setTextSize(mSize);
- }
-
- @Override
- public void updateMeasureState(TextPaint ds) {
- ds.setTextSize(mSize);
- }
-}
diff --git a/core/java/android/text/style/AlignmentSpan.java b/core/java/android/text/style/AlignmentSpan.java
deleted file mode 100644
index b8a37da..0000000
--- a/core/java/android/text/style/AlignmentSpan.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.os.Parcel;
-import android.text.Layout;
-import android.text.ParcelableSpan;
-import android.text.TextUtils;
-
-public interface AlignmentSpan extends ParagraphStyle {
- public Layout.Alignment getAlignment();
-
- public static class Standard
- implements AlignmentSpan, ParcelableSpan {
- public Standard(Layout.Alignment align) {
- mAlignment = align;
- }
-
- public Standard(Parcel src) {
- mAlignment = Layout.Alignment.valueOf(src.readString());
- }
-
- public int getSpanTypeId() {
- return TextUtils.ALIGNMENT_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mAlignment.name());
- }
-
- public Layout.Alignment getAlignment() {
- return mAlignment;
- }
-
- private final Layout.Alignment mAlignment;
- }
-}
diff --git a/core/java/android/text/style/BackgroundColorSpan.java b/core/java/android/text/style/BackgroundColorSpan.java
deleted file mode 100644
index 580a369..0000000
--- a/core/java/android/text/style/BackgroundColorSpan.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class BackgroundColorSpan extends CharacterStyle
- implements UpdateAppearance, ParcelableSpan {
-
- private final int mColor;
-
- public BackgroundColorSpan(int color) {
- mColor = color;
- }
-
- public BackgroundColorSpan(Parcel src) {
- mColor = src.readInt();
- }
-
- public int getSpanTypeId() {
- return TextUtils.BACKGROUND_COLOR_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mColor);
- }
-
- public int getBackgroundColor() {
- return mColor;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.bgColor = mColor;
- }
-}
diff --git a/core/java/android/text/style/BulletSpan.java b/core/java/android/text/style/BulletSpan.java
deleted file mode 100644
index 655bd81..0000000
--- a/core/java/android/text/style/BulletSpan.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.os.Parcel;
-import android.text.Layout;
-import android.text.ParcelableSpan;
-import android.text.Spanned;
-import android.text.TextUtils;
-
-public class BulletSpan implements LeadingMarginSpan, ParcelableSpan {
- private final int mGapWidth;
- private final boolean mWantColor;
- private final int mColor;
-
- private static final int BULLET_RADIUS = 3;
- public static final int STANDARD_GAP_WIDTH = 2;
-
- public BulletSpan() {
- mGapWidth = STANDARD_GAP_WIDTH;
- mWantColor = false;
- mColor = 0;
- }
-
- public BulletSpan(int gapWidth) {
- mGapWidth = gapWidth;
- mWantColor = false;
- mColor = 0;
- }
-
- public BulletSpan(int gapWidth, int color) {
- mGapWidth = gapWidth;
- mWantColor = true;
- mColor = color;
- }
-
- public BulletSpan(Parcel src) {
- mGapWidth = src.readInt();
- mWantColor = src.readInt() != 0;
- mColor = src.readInt();
- }
-
- public int getSpanTypeId() {
- return TextUtils.BULLET_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mGapWidth);
- dest.writeInt(mWantColor ? 1 : 0);
- dest.writeInt(mColor);
- }
-
- public int getLeadingMargin(boolean first) {
- return 2 * BULLET_RADIUS + mGapWidth;
- }
-
- public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
- int top, int baseline, int bottom,
- CharSequence text, int start, int end,
- boolean first, Layout l) {
- if (((Spanned) text).getSpanStart(this) == start) {
- Paint.Style style = p.getStyle();
- int oldcolor = 0;
-
- if (mWantColor) {
- oldcolor = p.getColor();
- p.setColor(mColor);
- }
-
- p.setStyle(Paint.Style.FILL);
-
- c.drawCircle(x + dir * BULLET_RADIUS, (top + bottom) / 2.0f,
- BULLET_RADIUS, p);
-
- if (mWantColor) {
- p.setColor(oldcolor);
- }
-
- p.setStyle(style);
- }
- }
-}
diff --git a/core/java/android/text/style/CharacterStyle.java b/core/java/android/text/style/CharacterStyle.java
deleted file mode 100644
index 14dfddd..0000000
--- a/core/java/android/text/style/CharacterStyle.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.text.TextPaint;
-
-/**
- * The classes that affect character-level text formatting extend this
- * class. Most extend its subclass {@link MetricAffectingSpan}, but simple
- * ones may just implement {@link UpdateAppearance}.
- */
-public abstract class CharacterStyle {
- public abstract void updateDrawState(TextPaint tp);
-
- /**
- * A given CharacterStyle can only applied to a single region of a given
- * Spanned. If you need to attach the same CharacterStyle to multiple
- * regions, you can use this method to wrap it with a new object that
- * will have the same effect but be a distinct object so that it can
- * also be attached without conflict.
- */
- public static CharacterStyle wrap(CharacterStyle cs) {
- if (cs instanceof MetricAffectingSpan) {
- return new MetricAffectingSpan.Passthrough((MetricAffectingSpan) cs);
- } else {
- return new Passthrough(cs);
- }
- }
-
- /**
- * Returns "this" for most CharacterStyles, but for CharacterStyles
- * that were generated by {@link #wrap}, returns the underlying
- * CharacterStyle.
- */
- public CharacterStyle getUnderlying() {
- return this;
- }
-
- /**
- * A Passthrough CharacterStyle is one that
- * passes {@link #updateDrawState} calls through to the
- * specified CharacterStyle while still being a distinct object,
- * and is therefore able to be attached to the same Spannable
- * to which the specified CharacterStyle is already attached.
- */
- private static class Passthrough extends CharacterStyle {
- private CharacterStyle mStyle;
-
- /**
- * Creates a new Passthrough of the specfied CharacterStyle.
- */
- public Passthrough(CharacterStyle cs) {
- mStyle = cs;
- }
-
- /**
- * Passes updateDrawState through to the underlying CharacterStyle.
- */
- @Override
- public void updateDrawState(TextPaint tp) {
- mStyle.updateDrawState(tp);
- }
-
- /**
- * Returns the CharacterStyle underlying this one, or the one
- * underlying it if it too is a Passthrough.
- */
- @Override
- public CharacterStyle getUnderlying() {
- return mStyle.getUnderlying();
- }
- }
-}
diff --git a/core/java/android/text/style/ClickableSpan.java b/core/java/android/text/style/ClickableSpan.java
deleted file mode 100644
index 989ef54..0000000
--- a/core/java/android/text/style/ClickableSpan.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.text.TextPaint;
-import android.view.View;
-
-/**
- * If an object of this type is attached to the text of a TextView
- * with a movement method of LinkMovementMethod, the affected spans of
- * text can be selected. If clicked, the {@link #onClick} method will
- * be called.
- */
-public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance {
-
- /**
- * Performs the click action associated with this span.
- */
- public abstract void onClick(View widget);
-
- /**
- * Makes the text underlined and in the link color.
- */
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setColor(ds.linkColor);
- ds.setUnderlineText(true);
- }
-}
diff --git a/core/java/android/text/style/DrawableMarginSpan.java b/core/java/android/text/style/DrawableMarginSpan.java
deleted file mode 100644
index 3c471a5..0000000
--- a/core/java/android/text/style/DrawableMarginSpan.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.graphics.drawable.Drawable;
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.graphics.RectF;
-import android.text.Spanned;
-import android.text.Layout;
-
-public class DrawableMarginSpan
-implements LeadingMarginSpan, LineHeightSpan
-{
- public DrawableMarginSpan(Drawable b) {
- mDrawable = b;
- }
-
- public DrawableMarginSpan(Drawable b, int pad) {
- mDrawable = b;
- mPad = pad;
- }
-
- public int getLeadingMargin(boolean first) {
- return mDrawable.getIntrinsicWidth() + mPad;
- }
-
- public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
- int top, int baseline, int bottom,
- CharSequence text, int start, int end,
- boolean first, Layout layout) {
- int st = ((Spanned) text).getSpanStart(this);
- int ix = (int)x;
- int itop = (int)layout.getLineTop(layout.getLineForOffset(st));
-
- int dw = mDrawable.getIntrinsicWidth();
- int dh = mDrawable.getIntrinsicHeight();
-
- if (dir < 0)
- x -= dw;
-
- // XXX What to do about Paint?
- mDrawable.setBounds(ix, itop, ix+dw, itop+dh);
- mDrawable.draw(c);
- }
-
- public void chooseHeight(CharSequence text, int start, int end,
- int istartv, int v,
- Paint.FontMetricsInt fm) {
- if (end == ((Spanned) text).getSpanEnd(this)) {
- int ht = mDrawable.getIntrinsicHeight();
-
- int need = ht - (v + fm.descent - fm.ascent - istartv);
- if (need > 0)
- fm.descent += need;
-
- need = ht - (v + fm.bottom - fm.top - istartv);
- if (need > 0)
- fm.bottom += need;
- }
- }
-
- private Drawable mDrawable;
- private int mPad;
-}
diff --git a/core/java/android/text/style/DynamicDrawableSpan.java b/core/java/android/text/style/DynamicDrawableSpan.java
deleted file mode 100644
index 89dc45b..0000000
--- a/core/java/android/text/style/DynamicDrawableSpan.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Paint.Style;
-import android.graphics.drawable.Drawable;
-import android.util.Log;
-
-import java.lang.ref.WeakReference;
-
-/**
- *
- */
-public abstract class DynamicDrawableSpan extends ReplacementSpan {
- private static final String TAG = "DynamicDrawableSpan";
-
- /**
- * A constant indicating that the bottom of this span should be aligned
- * with the bottom of the surrounding text, i.e., at the same level as the
- * lowest descender in the text.
- */
- public static final int ALIGN_BOTTOM = 0;
-
- /**
- * A constant indicating that the bottom of this span should be aligned
- * with the baseline of the surrounding text.
- */
- public static final int ALIGN_BASELINE = 1;
-
- protected final int mVerticalAlignment;
-
- public DynamicDrawableSpan() {
- mVerticalAlignment = ALIGN_BOTTOM;
- }
-
- /**
- * @param verticalAlignment one of {@link #ALIGN_BOTTOM} or {@link #ALIGN_BASELINE}.
- */
- protected DynamicDrawableSpan(int verticalAlignment) {
- mVerticalAlignment = verticalAlignment;
- }
-
- /**
- * Returns the vertical alignment of this span, one of {@link #ALIGN_BOTTOM} or
- * {@link #ALIGN_BASELINE}.
- */
- public int getVerticalAlignment() {
- return mVerticalAlignment;
- }
-
- /**
- * Your subclass must implement this method to provide the bitmap
- * to be drawn. The dimensions of the bitmap must be the same
- * from each call to the next.
- */
- public abstract Drawable getDrawable();
-
- @Override
- public int getSize(Paint paint, CharSequence text,
- int start, int end,
- Paint.FontMetricsInt fm) {
- Drawable d = getCachedDrawable();
- Rect rect = d.getBounds();
-
- if (fm != null) {
- fm.ascent = -rect.bottom;
- fm.descent = 0;
-
- fm.top = fm.ascent;
- fm.bottom = 0;
- }
-
- return rect.right;
- }
-
- @Override
- public void draw(Canvas canvas, CharSequence text,
- int start, int end, float x,
- int top, int y, int bottom, Paint paint) {
- Drawable b = getCachedDrawable();
- canvas.save();
-
- int transY = bottom - b.getBounds().bottom;
- if (mVerticalAlignment == ALIGN_BASELINE) {
- transY -= paint.getFontMetricsInt().descent;
- }
-
- canvas.translate(x, transY);
- b.draw(canvas);
- canvas.restore();
- }
-
- private Drawable getCachedDrawable() {
- WeakReference<Drawable> wr = mDrawableRef;
- Drawable d = null;
-
- if (wr != null)
- d = wr.get();
-
- if (d == null) {
- d = getDrawable();
- mDrawableRef = new WeakReference<Drawable>(d);
- }
-
- return d;
- }
-
- private WeakReference<Drawable> mDrawableRef;
-}
-
diff --git a/core/java/android/text/style/ForegroundColorSpan.java b/core/java/android/text/style/ForegroundColorSpan.java
deleted file mode 100644
index 476124d..0000000
--- a/core/java/android/text/style/ForegroundColorSpan.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class ForegroundColorSpan extends CharacterStyle
- implements UpdateAppearance, ParcelableSpan {
-
- private final int mColor;
-
- public ForegroundColorSpan(int color) {
- mColor = color;
- }
-
- public ForegroundColorSpan(Parcel src) {
- mColor = src.readInt();
- }
-
- public int getSpanTypeId() {
- return TextUtils.FOREGROUND_COLOR_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mColor);
- }
-
- public int getForegroundColor() {
- return mColor;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setColor(mColor);
- }
-}
diff --git a/core/java/android/text/style/IconMarginSpan.java b/core/java/android/text/style/IconMarginSpan.java
deleted file mode 100644
index c786a17..0000000
--- a/core/java/android/text/style/IconMarginSpan.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.RectF;
-import android.text.Spanned;
-import android.text.Layout;
-
-public class IconMarginSpan
-implements LeadingMarginSpan, LineHeightSpan
-{
- public IconMarginSpan(Bitmap b) {
- mBitmap = b;
- }
-
- public IconMarginSpan(Bitmap b, int pad) {
- mBitmap = b;
- mPad = pad;
- }
-
- public int getLeadingMargin(boolean first) {
- return mBitmap.getWidth() + mPad;
- }
-
- public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
- int top, int baseline, int bottom,
- CharSequence text, int start, int end,
- boolean first, Layout layout) {
- int st = ((Spanned) text).getSpanStart(this);
- int itop = layout.getLineTop(layout.getLineForOffset(st));
-
- if (dir < 0)
- x -= mBitmap.getWidth();
-
- c.drawBitmap(mBitmap, x, itop, p);
- }
-
- public void chooseHeight(CharSequence text, int start, int end,
- int istartv, int v,
- Paint.FontMetricsInt fm) {
- if (end == ((Spanned) text).getSpanEnd(this)) {
- int ht = mBitmap.getHeight();
-
- int need = ht - (v + fm.descent - fm.ascent - istartv);
- if (need > 0)
- fm.descent += need;
-
- need = ht - (v + fm.bottom - fm.top - istartv);
- if (need > 0)
- fm.bottom += need;
- }
- }
-
- private Bitmap mBitmap;
- private int mPad;
-}
diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java
deleted file mode 100644
index efb88a0..0000000
--- a/core/java/android/text/style/ImageSpan.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.util.Log;
-
-import java.io.InputStream;
-
-public class ImageSpan extends DynamicDrawableSpan {
- private Drawable mDrawable;
- private Uri mContentUri;
- private int mResourceId;
- private Context mContext;
- private String mSource;
-
- public ImageSpan(Bitmap b) {
- this(b, ALIGN_BOTTOM);
- }
-
- /**
- * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
- * {@link DynamicDrawableSpan#ALIGN_BASELINE}.
- */
- public ImageSpan(Bitmap b, int verticalAlignment) {
- super(verticalAlignment);
- mDrawable = new BitmapDrawable(b);
- int width = mDrawable.getIntrinsicWidth();
- int height = mDrawable.getIntrinsicHeight();
- mDrawable.setBounds(0, 0, width > 0 ? width : 0, height > 0 ? height : 0);
- }
-
- public ImageSpan(Drawable d) {
- this(d, ALIGN_BOTTOM);
- }
-
- /**
- * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
- * {@link DynamicDrawableSpan#ALIGN_BASELINE}.
- */
- public ImageSpan(Drawable d, int verticalAlignment) {
- super(verticalAlignment);
- mDrawable = d;
- }
-
- public ImageSpan(Drawable d, String source) {
- this(d, source, ALIGN_BOTTOM);
- }
-
- /**
- * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
- * {@link DynamicDrawableSpan#ALIGN_BASELINE}.
- */
- public ImageSpan(Drawable d, String source, int verticalAlignment) {
- super(verticalAlignment);
- mDrawable = d;
- mSource = source;
- }
-
- public ImageSpan(Context context, Uri uri) {
- this(context, uri, ALIGN_BOTTOM);
- }
-
- /**
- * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
- * {@link DynamicDrawableSpan#ALIGN_BASELINE}.
- */
- public ImageSpan(Context context, Uri uri, int verticalAlignment) {
- super(verticalAlignment);
- mContext = context;
- mContentUri = uri;
- }
-
- public ImageSpan(Context context, int resourceId) {
- this(context, resourceId, ALIGN_BOTTOM);
- }
-
- /**
- * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
- * {@link DynamicDrawableSpan#ALIGN_BASELINE}.
- */
- public ImageSpan(Context context, int resourceId, int verticalAlignment) {
- super(verticalAlignment);
- mContext = context;
- mResourceId = resourceId;
- }
-
- @Override
- public Drawable getDrawable() {
- Drawable drawable = null;
-
- if (mDrawable != null) {
- drawable = mDrawable;
- } else if (mContentUri != null) {
- Bitmap bitmap = null;
- try {
- InputStream is = mContext.getContentResolver().openInputStream(
- mContentUri);
- bitmap = BitmapFactory.decodeStream(is);
- drawable = new BitmapDrawable(bitmap);
- is.close();
- } catch (Exception e) {
- Log.e("sms", "Failed to loaded content " + mContentUri, e);
- }
- } else {
- try {
- drawable = mContext.getResources().getDrawable(mResourceId);
- drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
- drawable.getIntrinsicHeight());
- } catch (Exception e) {
- Log.e("sms", "Unable to find resource: " + mResourceId);
- }
- }
-
- return drawable;
- }
-
- /**
- * Returns the source string that was saved during construction.
- */
- public String getSource() {
- return mSource;
- }
-
-}
diff --git a/core/java/android/text/style/LeadingMarginSpan.java b/core/java/android/text/style/LeadingMarginSpan.java
deleted file mode 100644
index 8e212e3..0000000
--- a/core/java/android/text/style/LeadingMarginSpan.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.os.Parcel;
-import android.text.Layout;
-import android.text.ParcelableSpan;
-import android.text.TextUtils;
-
-public interface LeadingMarginSpan
-extends ParagraphStyle
-{
- public int getLeadingMargin(boolean first);
- public void drawLeadingMargin(Canvas c, Paint p,
- int x, int dir,
- int top, int baseline, int bottom,
- CharSequence text, int start, int end,
- boolean first, Layout layout);
-
- public static class Standard implements LeadingMarginSpan, ParcelableSpan {
- private final int mFirst, mRest;
-
- public Standard(int first, int rest) {
- mFirst = first;
- mRest = rest;
- }
-
- public Standard(int every) {
- this(every, every);
- }
-
- public Standard(Parcel src) {
- mFirst = src.readInt();
- mRest = src.readInt();
- }
-
- public int getSpanTypeId() {
- return TextUtils.LEADING_MARGIN_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mFirst);
- dest.writeInt(mRest);
- }
-
- public int getLeadingMargin(boolean first) {
- return first ? mFirst : mRest;
- }
-
- public void drawLeadingMargin(Canvas c, Paint p,
- int x, int dir,
- int top, int baseline, int bottom,
- CharSequence text, int start, int end,
- boolean first, Layout layout) {
- ;
- }
- }
-}
diff --git a/core/java/android/text/style/LineBackgroundSpan.java b/core/java/android/text/style/LineBackgroundSpan.java
deleted file mode 100644
index 854aeaf..0000000
--- a/core/java/android/text/style/LineBackgroundSpan.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Canvas;
-
-public interface LineBackgroundSpan
-extends ParagraphStyle
-{
- public void drawBackground(Canvas c, Paint p,
- int left, int right,
- int top, int baseline, int bottom,
- CharSequence text, int start, int end,
- int lnum);
-}
diff --git a/core/java/android/text/style/LineHeightSpan.java b/core/java/android/text/style/LineHeightSpan.java
deleted file mode 100644
index c0ef97c..0000000
--- a/core/java/android/text/style/LineHeightSpan.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.text.Layout;
-
-public interface LineHeightSpan
-extends ParagraphStyle, WrapTogetherSpan
-{
- public void chooseHeight(CharSequence text, int start, int end,
- int spanstartv, int v,
- Paint.FontMetricsInt fm);
-}
diff --git a/core/java/android/text/style/MaskFilterSpan.java b/core/java/android/text/style/MaskFilterSpan.java
deleted file mode 100644
index 64ab0d8..0000000
--- a/core/java/android/text/style/MaskFilterSpan.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.graphics.MaskFilter;
-import android.text.TextPaint;
-
-public class MaskFilterSpan extends CharacterStyle implements UpdateAppearance {
-
- private MaskFilter mFilter;
-
- public MaskFilterSpan(MaskFilter filter) {
- mFilter = filter;
- }
-
- public MaskFilter getMaskFilter() {
- return mFilter;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setMaskFilter(mFilter);
- }
-}
diff --git a/core/java/android/text/style/MetricAffectingSpan.java b/core/java/android/text/style/MetricAffectingSpan.java
deleted file mode 100644
index 92558eb..0000000
--- a/core/java/android/text/style/MetricAffectingSpan.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.graphics.Paint;
-import android.text.TextPaint;
-
-/**
- * The classes that affect character-level text formatting in a way that
- * changes the width or height of characters extend this class.
- */
-public abstract class MetricAffectingSpan
-extends CharacterStyle
-implements UpdateLayout {
-
- public abstract void updateMeasureState(TextPaint p);
-
- /**
- * Returns "this" for most MetricAffectingSpans, but for
- * MetricAffectingSpans that were generated by {@link #wrap},
- * returns the underlying MetricAffectingSpan.
- */
- @Override
- public MetricAffectingSpan getUnderlying() {
- return this;
- }
-
- /**
- * A Passthrough MetricAffectingSpan is one that
- * passes {@link #updateDrawState} and {@link #updateMeasureState}
- * calls through to the specified MetricAffectingSpan
- * while still being a distinct object,
- * and is therefore able to be attached to the same Spannable
- * to which the specified MetricAffectingSpan is already attached.
- */
- /* package */ static class Passthrough extends MetricAffectingSpan {
- private MetricAffectingSpan mStyle;
-
- /**
- * Creates a new Passthrough of the specfied MetricAffectingSpan.
- */
- public Passthrough(MetricAffectingSpan cs) {
- mStyle = cs;
- }
-
- /**
- * Passes updateDrawState through to the underlying MetricAffectingSpan.
- */
- @Override
- public void updateDrawState(TextPaint tp) {
- mStyle.updateDrawState(tp);
- }
-
- /**
- * Passes updateMeasureState through to the underlying MetricAffectingSpan.
- */
- @Override
- public void updateMeasureState(TextPaint tp) {
- mStyle.updateMeasureState(tp);
- }
-
- /**
- * Returns the MetricAffectingSpan underlying this one, or the one
- * underlying it if it too is a Passthrough.
- */
- @Override
- public MetricAffectingSpan getUnderlying() {
- return mStyle.getUnderlying();
- }
- }
-}
diff --git a/core/java/android/text/style/ParagraphStyle.java b/core/java/android/text/style/ParagraphStyle.java
deleted file mode 100644
index 423156e..0000000
--- a/core/java/android/text/style/ParagraphStyle.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-/**
- * The classes that affect paragraph-level text formatting implement
- * this interface.
- */
-public interface ParagraphStyle
-{
-
-}
diff --git a/core/java/android/text/style/QuoteSpan.java b/core/java/android/text/style/QuoteSpan.java
deleted file mode 100644
index 29dd273..0000000
--- a/core/java/android/text/style/QuoteSpan.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.os.Parcel;
-import android.text.Layout;
-import android.text.ParcelableSpan;
-import android.text.TextUtils;
-
-public class QuoteSpan implements LeadingMarginSpan, ParcelableSpan {
- private static final int STRIPE_WIDTH = 2;
- private static final int GAP_WIDTH = 2;
-
- private final int mColor;
-
- public QuoteSpan() {
- super();
- mColor = 0xff0000ff;
- }
-
- public QuoteSpan(int color) {
- super();
- mColor = color;
- }
-
- public QuoteSpan(Parcel src) {
- mColor = src.readInt();
- }
-
- public int getSpanTypeId() {
- return TextUtils.QUOTE_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mColor);
- }
-
- public int getColor() {
- return mColor;
- }
-
- public int getLeadingMargin(boolean first) {
- return STRIPE_WIDTH + GAP_WIDTH;
- }
-
- public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
- int top, int baseline, int bottom,
- CharSequence text, int start, int end,
- boolean first, Layout layout) {
- Paint.Style style = p.getStyle();
- int color = p.getColor();
-
- p.setStyle(Paint.Style.FILL);
- p.setColor(mColor);
-
- c.drawRect(x, top, x + dir * STRIPE_WIDTH, bottom, p);
-
- p.setStyle(style);
- p.setColor(color);
- }
-}
diff --git a/core/java/android/text/style/RasterizerSpan.java b/core/java/android/text/style/RasterizerSpan.java
deleted file mode 100644
index 75b5bcc..0000000
--- a/core/java/android/text/style/RasterizerSpan.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.graphics.Rasterizer;
-import android.text.TextPaint;
-
-public class RasterizerSpan extends CharacterStyle implements UpdateAppearance {
-
- private Rasterizer mRasterizer;
-
- public RasterizerSpan(Rasterizer r) {
- mRasterizer = r;
- }
-
- public Rasterizer getRasterizer() {
- return mRasterizer;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setRasterizer(mRasterizer);
- }
-}
diff --git a/core/java/android/text/style/RelativeSizeSpan.java b/core/java/android/text/style/RelativeSizeSpan.java
deleted file mode 100644
index 9717362..0000000
--- a/core/java/android/text/style/RelativeSizeSpan.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class RelativeSizeSpan extends MetricAffectingSpan implements ParcelableSpan {
-
- private final float mProportion;
-
- public RelativeSizeSpan(float proportion) {
- mProportion = proportion;
- }
-
- public RelativeSizeSpan(Parcel src) {
- mProportion = src.readFloat();
- }
-
- public int getSpanTypeId() {
- return TextUtils.RELATIVE_SIZE_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeFloat(mProportion);
- }
-
- public float getSizeChange() {
- return mProportion;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setTextSize(ds.getTextSize() * mProportion);
- }
-
- @Override
- public void updateMeasureState(TextPaint ds) {
- ds.setTextSize(ds.getTextSize() * mProportion);
- }
-}
diff --git a/core/java/android/text/style/ReplacementSpan.java b/core/java/android/text/style/ReplacementSpan.java
deleted file mode 100644
index 26c725f..0000000
--- a/core/java/android/text/style/ReplacementSpan.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.text.TextPaint;
-
-public abstract class ReplacementSpan extends MetricAffectingSpan {
-
- public abstract int getSize(Paint paint, CharSequence text,
- int start, int end,
- Paint.FontMetricsInt fm);
- public abstract void draw(Canvas canvas, CharSequence text,
- int start, int end, float x,
- int top, int y, int bottom, Paint paint);
-
- /**
- * This method does nothing, since ReplacementSpans are measured
- * explicitly instead of affecting Paint properties.
- */
- public void updateMeasureState(TextPaint p) { }
-
- /**
- * This method does nothing, since ReplacementSpans are drawn
- * explicitly instead of affecting Paint properties.
- */
- public void updateDrawState(TextPaint ds) { }
-}
diff --git a/core/java/android/text/style/ScaleXSpan.java b/core/java/android/text/style/ScaleXSpan.java
deleted file mode 100644
index 655064b..0000000
--- a/core/java/android/text/style/ScaleXSpan.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class ScaleXSpan extends MetricAffectingSpan implements ParcelableSpan {
-
- private final float mProportion;
-
- public ScaleXSpan(float proportion) {
- mProportion = proportion;
- }
-
- public ScaleXSpan(Parcel src) {
- mProportion = src.readFloat();
- }
-
- public int getSpanTypeId() {
- return TextUtils.SCALE_X_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeFloat(mProportion);
- }
-
- public float getScaleX() {
- return mProportion;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setTextScaleX(ds.getTextScaleX() * mProportion);
- }
-
- @Override
- public void updateMeasureState(TextPaint ds) {
- ds.setTextScaleX(ds.getTextScaleX() * mProportion);
- }
-}
diff --git a/core/java/android/text/style/StrikethroughSpan.java b/core/java/android/text/style/StrikethroughSpan.java
deleted file mode 100644
index b51363a..0000000
--- a/core/java/android/text/style/StrikethroughSpan.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class StrikethroughSpan extends CharacterStyle
- implements UpdateAppearance, ParcelableSpan {
- public StrikethroughSpan() {
- }
-
- public StrikethroughSpan(Parcel src) {
- }
-
- public int getSpanTypeId() {
- return TextUtils.STRIKETHROUGH_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setStrikeThruText(true);
- }
-}
diff --git a/core/java/android/text/style/StyleSpan.java b/core/java/android/text/style/StyleSpan.java
deleted file mode 100644
index 8e6147c..0000000
--- a/core/java/android/text/style/StyleSpan.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Typeface;
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-/**
- *
- * Describes a style in a span.
- * Note that styles are cumulative -- if both bold and italic are set in
- * separate spans, or if the base style is bold and a span calls for italic,
- * you get bold italic. You can't turn off a style from the base style.
- *
- */
-public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan {
-
- private final int mStyle;
-
- /**
- *
- * @param style An integer constant describing the style for this span. Examples
- * include bold, italic, and normal. Values are constants defined
- * in {@link android.graphics.Typeface}.
- */
- public StyleSpan(int style) {
- mStyle = style;
- }
-
- public StyleSpan(Parcel src) {
- mStyle = src.readInt();
- }
-
- public int getSpanTypeId() {
- return TextUtils.STYLE_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mStyle);
- }
-
- /**
- * Returns the style constant defined in {@link android.graphics.Typeface}.
- */
- public int getStyle() {
- return mStyle;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- apply(ds, mStyle);
- }
-
- @Override
- public void updateMeasureState(TextPaint paint) {
- apply(paint, mStyle);
- }
-
- private static void apply(Paint paint, int style) {
- int oldStyle;
-
- Typeface old = paint.getTypeface();
- if (old == null) {
- oldStyle = 0;
- } else {
- oldStyle = old.getStyle();
- }
-
- int want = oldStyle | style;
-
- Typeface tf;
- if (old == null) {
- tf = Typeface.defaultFromStyle(want);
- } else {
- tf = Typeface.create(old, want);
- }
-
- int fake = want & ~tf.getStyle();
-
- if ((fake & Typeface.BOLD) != 0) {
- paint.setFakeBoldText(true);
- }
-
- if ((fake & Typeface.ITALIC) != 0) {
- paint.setTextSkewX(-0.25f);
- }
-
- paint.setTypeface(tf);
- }
-}
diff --git a/core/java/android/text/style/SubscriptSpan.java b/core/java/android/text/style/SubscriptSpan.java
deleted file mode 100644
index de1d8b2..0000000
--- a/core/java/android/text/style/SubscriptSpan.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class SubscriptSpan extends MetricAffectingSpan implements ParcelableSpan {
- public SubscriptSpan() {
- }
-
- public SubscriptSpan(Parcel src) {
- }
-
- public int getSpanTypeId() {
- return TextUtils.SUBSCRIPT_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- }
-
- @Override
- public void updateDrawState(TextPaint tp) {
- tp.baselineShift -= (int) (tp.ascent() / 2);
- }
-
- @Override
- public void updateMeasureState(TextPaint tp) {
- tp.baselineShift -= (int) (tp.ascent() / 2);
- }
-}
diff --git a/core/java/android/text/style/SuperscriptSpan.java b/core/java/android/text/style/SuperscriptSpan.java
deleted file mode 100644
index 285fe84..0000000
--- a/core/java/android/text/style/SuperscriptSpan.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class SuperscriptSpan extends MetricAffectingSpan implements ParcelableSpan {
- public SuperscriptSpan() {
- }
-
- public SuperscriptSpan(Parcel src) {
- }
-
- public int getSpanTypeId() {
- return TextUtils.SUPERSCRIPT_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- }
-
- @Override
- public void updateDrawState(TextPaint tp) {
- tp.baselineShift += (int) (tp.ascent() / 2);
- }
-
- @Override
- public void updateMeasureState(TextPaint tp) {
- tp.baselineShift += (int) (tp.ascent() / 2);
- }
-}
diff --git a/core/java/android/text/style/TabStopSpan.java b/core/java/android/text/style/TabStopSpan.java
deleted file mode 100644
index e5b7644..0000000
--- a/core/java/android/text/style/TabStopSpan.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-public interface TabStopSpan
-extends ParagraphStyle
-{
- public int getTabStop();
-
- public static class Standard
- implements TabStopSpan
- {
- public Standard(int where) {
- mTab = where;
- }
-
- public int getTabStop() {
- return mTab;
- }
-
- private int mTab;
- }
-}
diff --git a/core/java/android/text/style/TextAppearanceSpan.java b/core/java/android/text/style/TextAppearanceSpan.java
deleted file mode 100644
index de929e3..0000000
--- a/core/java/android/text/style/TextAppearanceSpan.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.TypedArray;
-import android.graphics.Typeface;
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-/**
- * Sets the text color, size, style, and typeface to match a TextAppearance
- * resource.
- */
-public class TextAppearanceSpan extends MetricAffectingSpan implements ParcelableSpan {
- private final String mTypeface;
- private final int mStyle;
- private final int mTextSize;
- private final ColorStateList mTextColor;
- private final ColorStateList mTextColorLink;
-
- /**
- * Uses the specified TextAppearance resource to determine the
- * text appearance. The <code>appearance</code> should be, for example,
- * <code>android.R.style.TextAppearance_Small</code>.
- */
- public TextAppearanceSpan(Context context, int appearance) {
- this(context, appearance, -1);
- }
-
- /**
- * Uses the specified TextAppearance resource to determine the
- * text appearance, and the specified text color resource
- * to determine the color. The <code>appearance</code> should be,
- * for example, <code>android.R.style.TextAppearance_Small</code>,
- * and the <code>colorList</code> should be, for example,
- * <code>android.R.styleable.Theme_textColorDim</code>.
- */
- public TextAppearanceSpan(Context context, int appearance,
- int colorList) {
- ColorStateList textColor;
-
- TypedArray a =
- context.obtainStyledAttributes(appearance,
- com.android.internal.R.styleable.TextAppearance);
-
- textColor = a.getColorStateList(com.android.internal.R.styleable.
- TextAppearance_textColor);
- mTextColorLink = a.getColorStateList(com.android.internal.R.styleable.
- TextAppearance_textColorLink);
- mTextSize = a.getDimensionPixelSize(com.android.internal.R.styleable.
- TextAppearance_textSize, -1);
-
- mStyle = a.getInt(com.android.internal.R.styleable.TextAppearance_textStyle, 0);
- int tf = a.getInt(com.android.internal.R.styleable.TextAppearance_typeface, 0);
-
- switch (tf) {
- case 1:
- mTypeface = "sans";
- break;
-
- case 2:
- mTypeface = "serif";
- break;
-
- case 3:
- mTypeface = "monospace";
- break;
-
- default:
- mTypeface = null;
- break;
- }
-
- a.recycle();
-
- if (colorList >= 0) {
- a = context.obtainStyledAttributes(com.android.internal.R.style.Theme,
- com.android.internal.R.styleable.Theme);
-
- textColor = a.getColorStateList(colorList);
- a.recycle();
- }
-
- mTextColor = textColor;
- }
-
- /**
- * Makes text be drawn with the specified typeface, size, style,
- * and colors.
- */
- public TextAppearanceSpan(String family, int style, int size,
- ColorStateList color, ColorStateList linkColor) {
- mTypeface = family;
- mStyle = style;
- mTextSize = size;
- mTextColor = color;
- mTextColorLink = linkColor;
- }
-
- public TextAppearanceSpan(Parcel src) {
- mTypeface = src.readString();
- mStyle = src.readInt();
- mTextSize = src.readInt();
- if (src.readInt() != 0) {
- mTextColor = ColorStateList.CREATOR.createFromParcel(src);
- } else {
- mTextColor = null;
- }
- if (src.readInt() != 0) {
- mTextColorLink = ColorStateList.CREATOR.createFromParcel(src);
- } else {
- mTextColorLink = null;
- }
- }
-
- public int getSpanTypeId() {
- return TextUtils.TEXT_APPEARANCE_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mTypeface);
- dest.writeInt(mStyle);
- dest.writeInt(mTextSize);
- if (mTextColor != null) {
- dest.writeInt(1);
- mTextColor.writeToParcel(dest, flags);
- } else {
- dest.writeInt(0);
- }
- if (mTextColorLink != null) {
- dest.writeInt(1);
- mTextColorLink.writeToParcel(dest, flags);
- } else {
- dest.writeInt(0);
- }
- }
-
- /**
- * Returns the typeface family specified by this span, or <code>null</code>
- * if it does not specify one.
- */
- public String getFamily() {
- return mTypeface;
- }
-
- /**
- * Returns the text color specified by this span, or <code>null</code>
- * if it does not specify one.
- */
- public ColorStateList getTextColor() {
- return mTextColor;
- }
-
- /**
- * Returns the link color specified by this span, or <code>null</code>
- * if it does not specify one.
- */
- public ColorStateList getLinkTextColor() {
- return mTextColorLink;
- }
-
- /**
- * Returns the text size specified by this span, or <code>-1</code>
- * if it does not specify one.
- */
- public int getTextSize() {
- return mTextSize;
- }
-
- /**
- * Returns the text style specified by this span, or <code>0</code>
- * if it does not specify one.
- */
- public int getTextStyle() {
- return mStyle;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- updateMeasureState(ds);
-
- if (mTextColor != null) {
- ds.setColor(mTextColor.getColorForState(ds.drawableState, 0));
- }
-
- if (mTextColorLink != null) {
- ds.linkColor = mTextColor.getColorForState(ds.drawableState, 0);
- }
- }
-
- @Override
- public void updateMeasureState(TextPaint ds) {
- if (mTypeface != null || mStyle != 0) {
- Typeface tf = ds.getTypeface();
- int style = 0;
-
- if (tf != null) {
- style = tf.getStyle();
- }
-
- style |= mStyle;
-
- if (mTypeface != null) {
- tf = Typeface.create(mTypeface, style);
- } else if (tf == null) {
- tf = Typeface.defaultFromStyle(style);
- } else {
- tf = Typeface.create(tf, style);
- }
-
- int fake = style & ~tf.getStyle();
-
- if ((fake & Typeface.BOLD) != 0) {
- ds.setFakeBoldText(true);
- }
-
- if ((fake & Typeface.ITALIC) != 0) {
- ds.setTextSkewX(-0.25f);
- }
-
- ds.setTypeface(tf);
- }
-
- if (mTextSize > 0) {
- ds.setTextSize(mTextSize);
- }
- }
-}
diff --git a/core/java/android/text/style/TypefaceSpan.java b/core/java/android/text/style/TypefaceSpan.java
deleted file mode 100644
index f194060..0000000
--- a/core/java/android/text/style/TypefaceSpan.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Typeface;
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-/**
- * Changes the typeface family of the text to which the span is attached.
- */
-public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan {
- private final String mFamily;
-
- /**
- * @param family The font family for this typeface. Examples include
- * "monospace", "serif", and "sans-serif".
- */
- public TypefaceSpan(String family) {
- mFamily = family;
- }
-
- public TypefaceSpan(Parcel src) {
- mFamily = src.readString();
- }
-
- public int getSpanTypeId() {
- return TextUtils.TYPEFACE_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mFamily);
- }
-
- /**
- * Returns the font family name.
- */
- public String getFamily() {
- return mFamily;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- apply(ds, mFamily);
- }
-
- @Override
- public void updateMeasureState(TextPaint paint) {
- apply(paint, mFamily);
- }
-
- private static void apply(Paint paint, String family) {
- int oldStyle;
-
- Typeface old = paint.getTypeface();
- if (old == null) {
- oldStyle = 0;
- } else {
- oldStyle = old.getStyle();
- }
-
- Typeface tf = Typeface.create(family, oldStyle);
- int fake = oldStyle & ~tf.getStyle();
-
- if ((fake & Typeface.BOLD) != 0) {
- paint.setFakeBoldText(true);
- }
-
- if ((fake & Typeface.ITALIC) != 0) {
- paint.setTextSkewX(-0.25f);
- }
-
- paint.setTypeface(tf);
- }
-}
diff --git a/core/java/android/text/style/URLSpan.java b/core/java/android/text/style/URLSpan.java
deleted file mode 100644
index f458611..0000000
--- a/core/java/android/text/style/URLSpan.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextUtils;
-import android.view.View;
-
-public class URLSpan extends ClickableSpan implements ParcelableSpan {
-
- private final String mURL;
-
- public URLSpan(String url) {
- mURL = url;
- }
-
- public URLSpan(Parcel src) {
- mURL = src.readString();
- }
-
- public int getSpanTypeId() {
- return TextUtils.URL_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mURL);
- }
-
- public String getURL() {
- return mURL;
- }
-
- @Override
- public void onClick(View widget) {
- Uri uri = Uri.parse(getURL());
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- intent.addCategory(Intent.CATEGORY_BROWSABLE);
- widget.getContext().startActivity(intent);
- }
-}
diff --git a/core/java/android/text/style/UnderlineSpan.java b/core/java/android/text/style/UnderlineSpan.java
deleted file mode 100644
index b0cb0e8..0000000
--- a/core/java/android/text/style/UnderlineSpan.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class UnderlineSpan extends CharacterStyle
- implements UpdateAppearance, ParcelableSpan {
- public UnderlineSpan() {
- }
-
- public UnderlineSpan(Parcel src) {
- }
-
- public int getSpanTypeId() {
- return TextUtils.UNDERLINE_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setUnderlineText(true);
- }
-}
diff --git a/core/java/android/text/style/UpdateAppearance.java b/core/java/android/text/style/UpdateAppearance.java
deleted file mode 100644
index 198e4fa..0000000
--- a/core/java/android/text/style/UpdateAppearance.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package android.text.style;
-
-/**
- * The classes that affect character-level text in a way that modifies their
- * appearance when one is added or removed must implement this interface. Note
- * that if the class also impacts size or other metrics, it should instead
- * implement {@link UpdateLayout}.
- */
-public interface UpdateAppearance {
-}
diff --git a/core/java/android/text/style/UpdateLayout.java b/core/java/android/text/style/UpdateLayout.java
deleted file mode 100644
index 591075e..0000000
--- a/core/java/android/text/style/UpdateLayout.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-/**
- * The classes that affect character-level text formatting in a way that
- * triggers a text layout update when one is added or removed must implement
- * this interface. This interface also includes {@link UpdateAppearance}
- * since such a change implicitly also impacts the appearance.
- */
-public interface UpdateLayout extends UpdateAppearance { }
diff --git a/core/java/android/text/style/WrapTogetherSpan.java b/core/java/android/text/style/WrapTogetherSpan.java
deleted file mode 100644
index 11721a8..0000000
--- a/core/java/android/text/style/WrapTogetherSpan.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.style;
-
-public interface WrapTogetherSpan
-extends ParagraphStyle
-{
-
-}
diff --git a/core/java/android/text/style/package.html b/core/java/android/text/style/package.html
deleted file mode 100644
index 0a8520c..0000000
--- a/core/java/android/text/style/package.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<html>
-<body>
-
-<p>Provides classes used to view or change the style of a span of text in a View object.
-The classes with a subclass Standard are passed in to {@link android.text.SpannableString#setSpan(java.lang.Object, int, int, int)
-SpannableString.setSpan()} or {@link android.text.SpannableStringBuilder#setSpan(java.lang.Object, int, int, int)
-SpannableStringBuilder.setSpan()} to add a new styled span to a string in a View object.
-
-</body>
-</html>
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
deleted file mode 100644
index d61e888..0000000
--- a/core/java/android/text/util/Linkify.java
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.util;
-
-import android.text.method.LinkMovementMethod;
-import android.text.method.MovementMethod;
-import android.text.style.URLSpan;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.Spanned;
-import android.webkit.WebView;
-import android.widget.TextView;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Linkify take a piece of text and a regular expression and turns all of the
- * regex matches in the text into clickable links. This is particularly
- * useful for matching things like email addresses, web urls, etc. and making
- * them actionable.
- *
- * Alone with the pattern that is to be matched, a url scheme prefix is also
- * required. Any pattern match that does not begin with the supplied scheme
- * will have the scheme prepended to the matched text when the clickable url
- * is created. For instance, if you are matching web urls you would supply
- * the scheme <code>http://</code>. If the pattern matches example.com, which
- * does not have a url scheme prefix, the supplied scheme will be prepended to
- * create <code>http://example.com</code> when the clickable url link is
- * created.
- */
-
-public class Linkify {
- /**
- * Bit field indicating that web URLs should be matched in methods that
- * take an options mask
- */
- public static final int WEB_URLS = 0x01;
-
- /**
- * Bit field indicating that email addresses should be matched in methods
- * that take an options mask
- */
- public static final int EMAIL_ADDRESSES = 0x02;
-
- /**
- * Bit field indicating that phone numbers should be matched in methods that
- * take an options mask
- */
- public static final int PHONE_NUMBERS = 0x04;
-
- /**
- * Bit field indicating that street addresses should be matched in methods that
- * take an options mask
- */
- public static final int MAP_ADDRESSES = 0x08;
-
- /**
- * Bit mask indicating that all available patterns should be matched in
- * methods that take an options mask
- */
- public static final int ALL = WEB_URLS | EMAIL_ADDRESSES | PHONE_NUMBERS | MAP_ADDRESSES;
-
- /**
- * Don't treat anything with fewer than this many digits as a
- * phone number.
- */
- private static final int PHONE_NUMBER_MINIMUM_DIGITS = 5;
-
- /**
- * Filters out web URL matches that occur after an at-sign (@). This is
- * to prevent turning the domain name in an email address into a web link.
- */
- public static final MatchFilter sUrlMatchFilter = new MatchFilter() {
- public final boolean acceptMatch(CharSequence s, int start, int end) {
- if (start == 0) {
- return true;
- }
-
- if (s.charAt(start - 1) == '@') {
- return false;
- }
-
- return true;
- }
- };
-
- /**
- * Filters out URL matches that don't have enough digits to be a
- * phone number.
- */
- public static final MatchFilter sPhoneNumberMatchFilter = new MatchFilter() {
- public final boolean acceptMatch(CharSequence s, int start, int end) {
- int digitCount = 0;
-
- for (int i = start; i < end; i++) {
- if (Character.isDigit(s.charAt(i))) {
- digitCount++;
- if (digitCount >= PHONE_NUMBER_MINIMUM_DIGITS) {
- return true;
- }
- }
- }
- return false;
- }
- };
-
- /**
- * Transforms matched phone number text into something suitable
- * to be used in a tel: URL. It does this by removing everything
- * but the digits and plus signs. For instance:
- * &apos;+1 (919) 555-1212&apos;
- * becomes &apos;+19195551212&apos;
- */
- public static final TransformFilter sPhoneNumberTransformFilter = new TransformFilter() {
- public final String transformUrl(final Matcher match, String url) {
- return Regex.digitsAndPlusOnly(match);
- }
- };
-
- /**
- * MatchFilter enables client code to have more control over
- * what is allowed to match and become a link, and what is not.
- *
- * For example: when matching web urls you would like things like
- * http://www.example.com to match, as well as just example.com itelf.
- * However, you would not want to match against the domain in
- * support@example.com. So, when matching against a web url pattern you
- * might also include a MatchFilter that disallows the match if it is
- * immediately preceded by an at-sign (@).
- */
- public interface MatchFilter {
- /**
- * Examines the character span matched by the pattern and determines
- * if the match should be turned into an actionable link.
- *
- * @param s The body of text against which the pattern
- * was matched
- * @param start The index of the first character in s that was
- * matched by the pattern - inclusive
- * @param end The index of the last character in s that was
- * matched - exclusive
- *
- * @return Whether this match should be turned into a link
- */
- boolean acceptMatch(CharSequence s, int start, int end);
- }
-
- /**
- * TransformFilter enables client code to have more control over
- * how matched patterns are represented as URLs.
- *
- * For example: when converting a phone number such as (919) 555-1212
- * into a tel: URL the parentheses, white space, and hyphen need to be
- * removed to produce tel:9195551212.
- */
- public interface TransformFilter {
- /**
- * Examines the matched text and either passes it through or uses the
- * data in the Matcher state to produce a replacement.
- *
- * @param match The regex matcher state that found this URL text
- * @param url The text that was matched
- *
- * @return The transformed form of the URL
- */
- String transformUrl(final Matcher match, String url);
- }
-
- /**
- * Scans the text of the provided Spannable and turns all occurrences
- * of the link types indicated in the mask into clickable links.
- * If the mask is nonzero, it also removes any existing URLSpans
- * attached to the Spannable, to avoid problems if you call it
- * repeatedly on the same text.
- */
- public static final boolean addLinks(Spannable text, int mask) {
- if (mask == 0) {
- return false;
- }
-
- URLSpan[] old = text.getSpans(0, text.length(), URLSpan.class);
-
- for (int i = old.length - 1; i >= 0; i--) {
- text.removeSpan(old[i]);
- }
-
- ArrayList<LinkSpec> links = new ArrayList<LinkSpec>();
-
- if ((mask & WEB_URLS) != 0) {
- gatherLinks(links, text, Regex.WEB_URL_PATTERN,
- new String[] { "http://", "https://" },
- sUrlMatchFilter, null);
- }
-
- if ((mask & EMAIL_ADDRESSES) != 0) {
- gatherLinks(links, text, Regex.EMAIL_ADDRESS_PATTERN,
- new String[] { "mailto:" },
- null, null);
- }
-
- if ((mask & PHONE_NUMBERS) != 0) {
- gatherLinks(links, text, Regex.PHONE_PATTERN,
- new String[] { "tel:" },
- sPhoneNumberMatchFilter, sPhoneNumberTransformFilter);
- }
-
- if ((mask & MAP_ADDRESSES) != 0) {
- gatherMapLinks(links, text);
- }
-
- pruneOverlaps(links);
-
- if (links.size() == 0) {
- return false;
- }
-
- for (LinkSpec link: links) {
- applyLink(link.url, link.start, link.end, text);
- }
-
- return true;
- }
-
- /**
- * Scans the text of the provided TextView and turns all occurrences of
- * the link types indicated in the mask into clickable links. If matches
- * are found the movement method for the TextView is set to
- * LinkMovementMethod.
- */
- public static final boolean addLinks(TextView text, int mask) {
- if (mask == 0) {
- return false;
- }
-
- CharSequence t = text.getText();
-
- if (t instanceof Spannable) {
- if (addLinks((Spannable) t, mask)) {
- addLinkMovementMethod(text);
- return true;
- }
-
- return false;
- } else {
- SpannableString s = SpannableString.valueOf(t);
-
- if (addLinks(s, mask)) {
- addLinkMovementMethod(text);
- text.setText(s);
-
- return true;
- }
-
- return false;
- }
- }
-
- private static final void addLinkMovementMethod(TextView t) {
- MovementMethod m = t.getMovementMethod();
-
- if ((m == null) || !(m instanceof LinkMovementMethod)) {
- if (t.getLinksClickable()) {
- t.setMovementMethod(LinkMovementMethod.getInstance());
- }
- }
- }
-
- /**
- * Applies a regex to the text of a TextView turning the matches into
- * links. If links are found then UrlSpans are applied to the link
- * text match areas, and the movement method for the text is changed
- * to LinkMovementMethod.
- *
- * @param text TextView whose text is to be marked-up with links
- * @param pattern Regex pattern to be used for finding links
- * @param scheme Url scheme string (eg <code>http://</code> to be
- * prepended to the url of links that do not have
- * a scheme specified in the link text
- */
- public static final void addLinks(TextView text, Pattern pattern, String scheme) {
- addLinks(text, pattern, scheme, null, null);
- }
-
- /**
- * Applies a regex to the text of a TextView turning the matches into
- * links. If links are found then UrlSpans are applied to the link
- * text match areas, and the movement method for the text is changed
- * to LinkMovementMethod.
- *
- * @param text TextView whose text is to be marked-up with links
- * @param p Regex pattern to be used for finding links
- * @param scheme Url scheme string (eg <code>http://</code> to be
- * prepended to the url of links that do not have
- * a scheme specified in the link text
- * @param matchFilter The filter that is used to allow the client code
- * additional control over which pattern matches are
- * to be converted into links.
- */
- public static final void addLinks(TextView text, Pattern p, String scheme,
- MatchFilter matchFilter, TransformFilter transformFilter) {
- SpannableString s = SpannableString.valueOf(text.getText());
-
- if (addLinks(s, p, scheme, matchFilter, transformFilter)) {
- text.setText(s);
- addLinkMovementMethod(text);
- }
- }
-
- /**
- * Applies a regex to a Spannable turning the matches into
- * links.
- *
- * @param text Spannable whose text is to be marked-up with
- * links
- * @param pattern Regex pattern to be used for finding links
- * @param scheme Url scheme string (eg <code>http://</code> to be
- * prepended to the url of links that do not have
- * a scheme specified in the link text
- */
- public static final boolean addLinks(Spannable text, Pattern pattern, String scheme) {
- return addLinks(text, pattern, scheme, null, null);
- }
-
- /**
- * Applies a regex to a Spannable turning the matches into
- * links.
- *
- * @param s Spannable whose text is to be marked-up with
- * links
- * @param p Regex pattern to be used for finding links
- * @param scheme Url scheme string (eg <code>http://</code> to be
- * prepended to the url of links that do not have
- * a scheme specified in the link text
- * @param matchFilter The filter that is used to allow the client code
- * additional control over which pattern matches are
- * to be converted into links.
- */
- public static final boolean addLinks(Spannable s, Pattern p,
- String scheme, MatchFilter matchFilter,
- TransformFilter transformFilter) {
- boolean hasMatches = false;
- String prefix = (scheme == null) ? "" : scheme.toLowerCase();
- Matcher m = p.matcher(s);
-
- while (m.find()) {
- int start = m.start();
- int end = m.end();
- boolean allowed = true;
-
- if (matchFilter != null) {
- allowed = matchFilter.acceptMatch(s, start, end);
- }
-
- if (allowed) {
- String url = makeUrl(m.group(0), new String[] { prefix },
- m, transformFilter);
-
- applyLink(url, start, end, s);
- hasMatches = true;
- }
- }
-
- return hasMatches;
- }
-
- private static final void applyLink(String url, int start, int end, Spannable text) {
- URLSpan span = new URLSpan(url);
-
- text.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
- private static final String makeUrl(String url, String[] prefixes,
- Matcher m, TransformFilter filter) {
- if (filter != null) {
- url = filter.transformUrl(m, url);
- }
-
- boolean hasPrefix = false;
-
- for (int i = 0; i < prefixes.length; i++) {
- if (url.regionMatches(true, 0, prefixes[i], 0,
- prefixes[i].length())) {
- hasPrefix = true;
-
- // Fix capitalization if necessary
- if (!url.regionMatches(false, 0, prefixes[i], 0,
- prefixes[i].length())) {
- url = prefixes[i] + url.substring(prefixes[i].length());
- }
-
- break;
- }
- }
-
- if (!hasPrefix) {
- url = prefixes[0] + url;
- }
-
- return url;
- }
-
- private static final void gatherLinks(ArrayList<LinkSpec> links,
- Spannable s, Pattern pattern, String[] schemes,
- MatchFilter matchFilter, TransformFilter transformFilter) {
- Matcher m = pattern.matcher(s);
-
- while (m.find()) {
- int start = m.start();
- int end = m.end();
-
- if (matchFilter == null || matchFilter.acceptMatch(s, start, end)) {
- LinkSpec spec = new LinkSpec();
- String url = makeUrl(m.group(0), schemes, m, transformFilter);
-
- spec.url = url;
- spec.start = start;
- spec.end = end;
-
- links.add(spec);
- }
- }
- }
-
- private static final void gatherMapLinks(ArrayList<LinkSpec> links, Spannable s) {
- String string = s.toString();
- String address;
- int base = 0;
-
- while ((address = WebView.findAddress(string)) != null) {
- int start = string.indexOf(address);
-
- if (start < 0) {
- break;
- }
-
- LinkSpec spec = new LinkSpec();
- int length = address.length();
- int end = start + length;
-
- spec.start = base + start;
- spec.end = base + end;
- string = string.substring(end);
- base += end;
-
- String encodedAddress = null;
-
- try {
- encodedAddress = URLEncoder.encode(address,"UTF-8");
- } catch (UnsupportedEncodingException e) {
- continue;
- }
-
- spec.url = "geo:0,0?q=" + encodedAddress;
- links.add(spec);
- }
- }
-
- private static final void pruneOverlaps(ArrayList<LinkSpec> links) {
- Comparator<LinkSpec> c = new Comparator<LinkSpec>() {
- public final int compare(LinkSpec a, LinkSpec b) {
- if (a.start < b.start) {
- return -1;
- }
-
- if (a.start > b.start) {
- return 1;
- }
-
- if (a.end < b.end) {
- return 1;
- }
-
- if (a.end > b.end) {
- return -1;
- }
-
- return 0;
- }
-
- public final boolean equals(Object o) {
- return false;
- }
- };
-
- Collections.sort(links, c);
-
- int len = links.size();
- int i = 0;
-
- while (i < len - 1) {
- LinkSpec a = links.get(i);
- LinkSpec b = links.get(i + 1);
- int remove = -1;
-
- if ((a.start <= b.start) && (a.end > b.start)) {
- if (b.end <= a.end) {
- remove = i + 1;
- } else if ((a.end - a.start) > (b.end - b.start)) {
- remove = i + 1;
- } else if ((a.end - a.start) < (b.end - b.start)) {
- remove = i;
- }
-
- if (remove != -1) {
- links.remove(remove);
- len--;
- continue;
- }
-
- }
-
- i++;
- }
- }
-}
-
-class LinkSpec {
- String url;
- int start;
- int end;
-}
diff --git a/core/java/android/text/util/Regex.java b/core/java/android/text/util/Regex.java
deleted file mode 100644
index 4c128ad..0000000
--- a/core/java/android/text/util/Regex.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.util;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * @hide
- */
-public class Regex {
- /**
- * Regular expression pattern to match all IANA top-level domains.
- * List accurate as of 2007/06/15. List taken from:
- * http://data.iana.org/TLD/tlds-alpha-by-domain.txt
- * This pattern is auto-generated by //device/tools/make-iana-tld-pattern.py
- */
- public static final Pattern TOP_LEVEL_DOMAIN_PATTERN
- = Pattern.compile(
- "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
- + "|(biz|b[abdefghijmnorstvwyz])"
- + "|(cat|com|coop|c[acdfghiklmnoruvxyz])"
- + "|d[ejkmoz]"
- + "|(edu|e[cegrstu])"
- + "|f[ijkmor]"
- + "|(gov|g[abdefghilmnpqrstuwy])"
- + "|h[kmnrtu]"
- + "|(info|int|i[delmnoqrst])"
- + "|(jobs|j[emop])"
- + "|k[eghimnrwyz]"
- + "|l[abcikrstuvy]"
- + "|(mil|mobi|museum|m[acdghklmnopqrstuvwxyz])"
- + "|(name|net|n[acefgilopruz])"
- + "|(org|om)"
- + "|(pro|p[aefghklmnrstwy])"
- + "|qa"
- + "|r[eouw]"
- + "|s[abcdeghijklmnortuvyz]"
- + "|(tel|travel|t[cdfghjklmnoprtvwz])"
- + "|u[agkmsyz]"
- + "|v[aceginu]"
- + "|w[fs]"
- + "|y[etu]"
- + "|z[amw])");
-
- /**
- * Regular expression pattern to match RFC 1738 URLs
- * List accurate as of 2007/06/15. List taken from:
- * http://data.iana.org/TLD/tlds-alpha-by-domain.txt
- * This pattern is auto-generated by //device/tools/make-iana-tld-pattern.py
- */
- public static final Pattern WEB_URL_PATTERN
- = Pattern.compile(
- "((?:(http|https|Http|Https):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
- + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2}))+(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
- + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2}))+)?\\@)?)?"
- + "((?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]*\\.)+" // named host
- + "(?:" // plus top level domain
- + "(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
- + "|(?:biz|b[abdefghijmnorstvwyz])"
- + "|(?:cat|com|coop|c[acdfghiklmnoruvxyz])"
- + "|d[ejkmoz]"
- + "|(?:edu|e[cegrstu])"
- + "|f[ijkmor]"
- + "|(?:gov|g[abdefghilmnpqrstuwy])"
- + "|h[kmnrtu]"
- + "|(?:info|int|i[delmnoqrst])"
- + "|(?:jobs|j[emop])"
- + "|k[eghimnrwyz]"
- + "|l[abcikrstuvy]"
- + "|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])"
- + "|(?:name|net|n[acefgilopruz])"
- + "|(?:org|om)"
- + "|(?:pro|p[aefghklmnrstwy])"
- + "|qa"
- + "|r[eouw]"
- + "|s[abcdeghijklmnortuvyz]"
- + "|(?:tel|travel|t[cdfghjklmnoprtvwz])"
- + "|u[agkmsyz]"
- + "|v[aceginu]"
- + "|w[fs]"
- + "|y[etu]"
- + "|z[amw]))"
- + "|(?:(?:25[0-5]|2[0-4]" // or ip address
- + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(?:25[0-5]|2[0-4][0-9]"
- + "|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1]"
- + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
- + "|[1-9][0-9]|[0-9])))"
- + "(?:\\:\\d{1,5})?)" // plus option port number
- + "(\\/(?:(?:[a-zA-Z0-9\\;\\/\\?\\:\\@\\&\\=\\#\\~" // plus option query params
- + "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
- + "(?:\\b|$)"); // and finally, a word boundary or end of
- // input. This is to stop foo.sure from
- // matching as foo.su
-
- public static final Pattern IP_ADDRESS_PATTERN
- = Pattern.compile(
- "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
- + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
- + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
- + "|[1-9][0-9]|[0-9]))");
-
- public static final Pattern DOMAIN_NAME_PATTERN
- = Pattern.compile(
- "(((([a-zA-Z0-9][a-zA-Z0-9\\-]*)*[a-zA-Z0-9]\\.)+"
- + TOP_LEVEL_DOMAIN_PATTERN + ")|"
- + IP_ADDRESS_PATTERN + ")");
-
- public static final Pattern EMAIL_ADDRESS_PATTERN
- = Pattern.compile(
- "[a-zA-Z0-9\\+\\.\\_\\%\\-]+" +
- "\\@" +
- "[a-zA-Z0-9][a-zA-Z0-9\\-]*" +
- "(" +
- "\\." +
- "[a-zA-Z0-9][a-zA-Z0-9\\-]*" +
- ")+"
- );
-
- /**
- * This pattern is intended for searching for things that look like they
- * might be phone numbers in arbitrary text, not for validating whether
- * something is in fact a phone number. It will miss many things that
- * are legitimate phone numbers.
- *
- * <p> The pattern matches the following:
- * <ul>
- * <li>Optionally, a + sign followed immediately by one or more digits. Spaces, dots, or dashes
- * may follow.
- * <li>Optionally, sets of digits in parentheses, separated by spaces, dots, or dashes.
- * <li>A string starting and ending with a digit, containing digits, spaces, dots, and/or dashes.
- * </ul>
- */
- public static final Pattern PHONE_PATTERN
- = Pattern.compile( // sdd = space, dot, or dash
- "(\\+[0-9]+[\\- \\.]*)?" // +<digits><sdd>*
- + "(\\([0-9]+\\)[\\- \\.]*)?" // (<digits>)<sdd>*
- + "([0-9][0-9\\- \\.][0-9\\- \\.]+[0-9])"); // <digit><digit|sdd>+<digit>
-
- /**
- * Convenience method to take all of the non-null matching groups in a
- * regex Matcher and return them as a concatenated string.
- *
- * @param matcher The Matcher object from which grouped text will
- * be extracted
- *
- * @return A String comprising all of the non-null matched
- * groups concatenated together
- */
- public static final String concatGroups(Matcher matcher) {
- StringBuilder b = new StringBuilder();
- final int numGroups = matcher.groupCount();
-
- for (int i = 1; i <= numGroups; i++) {
- String s = matcher.group(i);
-
- System.err.println("Group(" + i + ") : " + s);
-
- if (s != null) {
- b.append(s);
- }
- }
-
- return b.toString();
- }
-
- /**
- * Convenience method to return only the digits and plus signs
- * in the matching string.
- *
- * @param matcher The Matcher object from which digits and plus will
- * be extracted
- *
- * @return A String comprising all of the digits and plus in
- * the match
- */
- public static final String digitsAndPlusOnly(Matcher matcher) {
- StringBuilder buffer = new StringBuilder();
- String matchingRegion = matcher.group();
-
- for (int i = 0, size = matchingRegion.length(); i < size; i++) {
- char character = matchingRegion.charAt(i);
-
- if (character == '+' || Character.isDigit(character)) {
- buffer.append(character);
- }
- }
- return buffer.toString();
- }
-}
diff --git a/core/java/android/text/util/Rfc822Token.java b/core/java/android/text/util/Rfc822Token.java
deleted file mode 100644
index e6472df..0000000
--- a/core/java/android/text/util/Rfc822Token.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.util;
-
-/**
- * This class stores an RFC 822-like name, address, and comment,
- * and provides methods to convert them to quoted strings.
- */
-public class Rfc822Token {
- private String mName, mAddress, mComment;
-
- /**
- * Creates a new Rfc822Token with the specified name, address,
- * and comment.
- */
- public Rfc822Token(String name, String address, String comment) {
- mName = name;
- mAddress = address;
- mComment = comment;
- }
-
- /**
- * Returns the name part.
- */
- public String getName() {
- return mName;
- }
-
- /**
- * Returns the address part.
- */
- public String getAddress() {
- return mAddress;
- }
-
- /**
- * Returns the comment part.
- */
- public String getComment() {
- return mComment;
- }
-
- /**
- * Changes the name to the specified name.
- */
- public void setName(String name) {
- mName = name;
- }
-
- /**
- * Changes the address to the specified address.
- */
- public void setAddress(String address) {
- mAddress = address;
- }
-
- /**
- * Changes the comment to the specified comment.
- */
- public void setComment(String comment) {
- mComment = comment;
- }
-
- /**
- * Returns the name (with quoting added if necessary),
- * the comment (in parentheses), and the address (in angle brackets).
- * This should be suitable for inclusion in an RFC 822 address list.
- */
- public String toString() {
- StringBuilder sb = new StringBuilder();
-
- if (mName != null && mName.length() != 0) {
- sb.append(quoteNameIfNecessary(mName));
- sb.append(' ');
- }
-
- if (mComment != null && mComment.length() != 0) {
- sb.append('(');
- sb.append(quoteComment(mComment));
- sb.append(") ");
- }
-
- if (mAddress != null && mAddress.length() != 0) {
- sb.append('<');
- sb.append(mAddress);
- sb.append('>');
- }
-
- return sb.toString();
- }
-
- /**
- * Returns the name, conservatively quoting it if there are any
- * characters that are likely to cause trouble outside of a
- * quoted string, or returning it literally if it seems safe.
- */
- public static String quoteNameIfNecessary(String name) {
- int len = name.length();
-
- for (int i = 0; i < len; i++) {
- char c = name.charAt(i);
-
- if (! ((c >= 'A' && i <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- (c == ' ') ||
- (c >= '0' && c <= '9'))) {
- return '"' + quoteName(name) + '"';
- }
- }
-
- return name;
- }
-
- /**
- * Returns the name, with internal backslashes and quotation marks
- * preceded by backslashes. The outer quote marks themselves are not
- * added by this method.
- */
- public static String quoteName(String name) {
- StringBuilder sb = new StringBuilder();
-
- int len = name.length();
- for (int i = 0; i < len; i++) {
- char c = name.charAt(i);
-
- if (c == '\\' || c == '"') {
- sb.append('\\');
- }
-
- sb.append(c);
- }
-
- return sb.toString();
- }
-
- /**
- * Returns the comment, with internal backslashes and parentheses
- * preceded by backslashes. The outer parentheses themselves are
- * not added by this method.
- */
- public static String quoteComment(String comment) {
- int len = comment.length();
- StringBuilder sb = new StringBuilder();
-
- for (int i = 0; i < len; i++) {
- char c = comment.charAt(i);
-
- if (c == '(' || c == ')' || c == '\\') {
- sb.append('\\');
- }
-
- sb.append(c);
- }
-
- return sb.toString();
- }
-}
-
diff --git a/core/java/android/text/util/Rfc822Tokenizer.java b/core/java/android/text/util/Rfc822Tokenizer.java
deleted file mode 100644
index d4e78b0..0000000
--- a/core/java/android/text/util/Rfc822Tokenizer.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.util;
-
-import android.widget.MultiAutoCompleteTextView;
-
-import java.util.ArrayList;
-
-/**
- * This class works as a Tokenizer for MultiAutoCompleteTextView for
- * address list fields, and also provides a method for converting
- * a string of addresses (such as might be typed into such a field)
- * into a series of Rfc822Tokens.
- */
-public class Rfc822Tokenizer implements MultiAutoCompleteTextView.Tokenizer {
- /**
- * This constructor will try to take a string like
- * "Foo Bar (something) &lt;foo\@google.com&gt;,
- * blah\@google.com (something)"
- * and convert it into one or more Rfc822Tokens.
- * It does *not* decode MIME encoded-words; charset conversion
- * must already have taken place if necessary.
- * It will try to be tolerant of broken syntax instead of
- * returning an error.
- */
- public static Rfc822Token[] tokenize(CharSequence text) {
- ArrayList<Rfc822Token> out = new ArrayList<Rfc822Token>();
- StringBuilder name = new StringBuilder();
- StringBuilder address = new StringBuilder();
- StringBuilder comment = new StringBuilder();
-
- int i = 0;
- int cursor = text.length();
-
- while (i < cursor) {
- char c = text.charAt(i);
-
- if (c == ',' || c == ';') {
- i++;
-
- while (i < cursor && text.charAt(i) == ' ') {
- i++;
- }
-
- crunch(name);
-
- if (address.length() > 0) {
- out.add(new Rfc822Token(name.toString(),
- address.toString(),
- comment.toString()));
- } else if (name.length() > 0) {
- out.add(new Rfc822Token(null,
- name.toString(),
- comment.toString()));
- }
-
- name.setLength(0);
- address.setLength(0);
- address.setLength(0);
- } else if (c == '"') {
- i++;
-
- while (i < cursor) {
- c = text.charAt(i);
-
- if (c == '"') {
- i++;
- break;
- } else if (c == '\\') {
- name.append(text.charAt(i + 1));
- i += 2;
- } else {
- name.append(c);
- i++;
- }
- }
- } else if (c == '(') {
- int level = 1;
- i++;
-
- while (i < cursor && level > 0) {
- c = text.charAt(i);
-
- if (c == ')') {
- if (level > 1) {
- comment.append(c);
- }
-
- level--;
- i++;
- } else if (c == '(') {
- comment.append(c);
- level++;
- i++;
- } else if (c == '\\') {
- comment.append(text.charAt(i + 1));
- i += 2;
- } else {
- comment.append(c);
- i++;
- }
- }
- } else if (c == '<') {
- i++;
-
- while (i < cursor) {
- c = text.charAt(i);
-
- if (c == '>') {
- i++;
- break;
- } else {
- address.append(c);
- i++;
- }
- }
- } else if (c == ' ') {
- name.append('\0');
- i++;
- } else {
- name.append(c);
- i++;
- }
- }
-
- crunch(name);
-
- if (address.length() > 0) {
- out.add(new Rfc822Token(name.toString(),
- address.toString(),
- comment.toString()));
- } else if (name.length() > 0) {
- out.add(new Rfc822Token(null,
- name.toString(),
- comment.toString()));
- }
-
- return out.toArray(new Rfc822Token[out.size()]);
- }
-
- private static void crunch(StringBuilder sb) {
- int i = 0;
- int len = sb.length();
-
- while (i < len) {
- char c = sb.charAt(i);
-
- if (c == '\0') {
- if (i == 0 || i == len - 1 ||
- sb.charAt(i - 1) == ' ' ||
- sb.charAt(i - 1) == '\0' ||
- sb.charAt(i + 1) == ' ' ||
- sb.charAt(i + 1) == '\0') {
- sb.deleteCharAt(i);
- len--;
- } else {
- i++;
- }
- } else {
- i++;
- }
- }
-
- for (i = 0; i < len; i++) {
- if (sb.charAt(i) == '\0') {
- sb.setCharAt(i, ' ');
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public int findTokenStart(CharSequence text, int cursor) {
- /*
- * It's hard to search backward, so search forward until
- * we reach the cursor.
- */
-
- int best = 0;
- int i = 0;
-
- while (i < cursor) {
- i = findTokenEnd(text, i);
-
- if (i < cursor) {
- i++; // Skip terminating punctuation
-
- while (i < cursor && text.charAt(i) == ' ') {
- i++;
- }
-
- if (i < cursor) {
- best = i;
- }
- }
- }
-
- return best;
- }
-
- /**
- * {@inheritDoc}
- */
- public int findTokenEnd(CharSequence text, int cursor) {
- int len = text.length();
- int i = cursor;
-
- while (i < len) {
- char c = text.charAt(i);
-
- if (c == ',' || c == ';') {
- return i;
- } else if (c == '"') {
- i++;
-
- while (i < len) {
- c = text.charAt(i);
-
- if (c == '"') {
- i++;
- break;
- } else if (c == '\\') {
- i += 2;
- } else {
- i++;
- }
- }
- } else if (c == '(') {
- int level = 1;
- i++;
-
- while (i < len && level > 0) {
- c = text.charAt(i);
-
- if (c == ')') {
- level--;
- i++;
- } else if (c == '(') {
- level++;
- i++;
- } else if (c == '\\') {
- i += 2;
- } else {
- i++;
- }
- }
- } else if (c == '<') {
- i++;
-
- while (i < len) {
- c = text.charAt(i);
-
- if (c == '>') {
- i++;
- break;
- } else {
- i++;
- }
- }
- } else {
- i++;
- }
- }
-
- return i;
- }
-
- /**
- * Terminates the specified address with a comma and space.
- * This assumes that the specified text already has valid syntax.
- * The Adapter subclass's convertToString() method must make that
- * guarantee.
- */
- public CharSequence terminateToken(CharSequence text) {
- return text + ", ";
- }
-}
diff --git a/core/java/android/text/util/Rfc822Validator.java b/core/java/android/text/util/Rfc822Validator.java
deleted file mode 100644
index 6a6bf69..0000000
--- a/core/java/android/text/util/Rfc822Validator.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.util;
-
-import android.text.TextUtils;
-import android.widget.AutoCompleteTextView;
-
-import java.util.regex.Pattern;
-
-/**
- * This class works as a Validator for AutoCompleteTextView for
- * email addresses. If a token does not appear to be a valid address,
- * it is trimmed of characters that cannot legitimately appear in one
- * and has the specified domain name added. It is meant for use with
- * {@link Rfc822Token} and {@link Rfc822Tokenizer}.
- *
- * @deprecated In the future make sure we don't quietly alter the user's
- * text in ways they did not intend. Meanwhile, hide this
- * class from the public API because it does not even have
- * a full understanding of the syntax it claims to correct.
- * @hide
- */
-public class Rfc822Validator implements AutoCompleteTextView.Validator {
- /*
- * Regex.EMAIL_ADDRESS_PATTERN hardcodes the TLD that we accept, but we
- * want to make sure we will keep accepting email addresses with TLD's
- * that don't exist at the time of this writing, so this regexp relaxes
- * that constraint by accepting any kind of top level domain, not just
- * ".com", ".fr", etc...
- */
- private static final Pattern EMAIL_ADDRESS_PATTERN =
- Pattern.compile("[^\\s@]+@[^\\s@]+\\.[a-zA-z][a-zA-Z][a-zA-Z]*");
-
- private String mDomain;
-
- /**
- * Constructs a new validator that uses the specified domain name as
- * the default when none is specified.
- */
- public Rfc822Validator(String domain) {
- mDomain = domain;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isValid(CharSequence text) {
- Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(text);
-
- return tokens.length == 1 &&
- EMAIL_ADDRESS_PATTERN.
- matcher(tokens[0].getAddress()).matches();
- }
-
- /**
- * @return a string in which all the characters that are illegal for the username
- * or the domain name part of the email address have been removed.
- */
- private String removeIllegalCharacters(String s) {
- StringBuilder result = new StringBuilder();
- int length = s.length();
- for (int i = 0; i < length; i++) {
- char c = s.charAt(i);
-
- /*
- * An RFC822 atom can contain any ASCII printing character
- * except for periods and any of the following punctuation.
- * A local-part can contain multiple atoms, concatenated by
- * periods, so do allow periods here.
- */
-
- if (c <= ' ' || c > '~') {
- continue;
- }
-
- if (c == '(' || c == ')' || c == '<' || c == '>' ||
- c == '@' || c == ',' || c == ';' || c == ':' ||
- c == '\\' || c == '"' || c == '[' || c == ']') {
- continue;
- }
-
- result.append(c);
- }
- return result.toString();
- }
-
- /**
- * {@inheritDoc}
- */
- public CharSequence fixText(CharSequence cs) {
- // Return an empty string if the email address only contains spaces, \n or \t
- if (TextUtils.getTrimmedLength(cs) == 0) return "";
-
- Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(cs);
- StringBuilder sb = new StringBuilder();
-
- for (int i = 0; i < tokens.length; i++) {
- String text = tokens[i].getAddress();
- int index = text.indexOf('@');
- if (index < 0) {
- // If there is no @, just append the domain of the account
- tokens[i].setAddress(removeIllegalCharacters(text) + "@" + mDomain);
- } else {
- // Otherwise, remove the illegal characters on both sides of the '@'
- String fix = removeIllegalCharacters(text.substring(0, index));
- String domain = removeIllegalCharacters(text.substring(index + 1));
- tokens[i].setAddress(fix + "@" + (domain.length() != 0 ? domain : mDomain));
- }
-
- sb.append(tokens[i].toString());
- if (i + 1 < tokens.length) {
- sb.append(", ");
- }
- }
-
- return sb;
- }
-}
diff --git a/core/java/android/text/util/package.html b/core/java/android/text/util/package.html
deleted file mode 100644
index d9312aa2..0000000
--- a/core/java/android/text/util/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<HTML>
-<BODY>
-Utilities for converting identifiable text strings into clickable links
-and creating RFC 822-type message (SMTP) tokens.
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/core/java/android/util/AndroidException.java b/core/java/android/util/AndroidException.java
deleted file mode 100644
index a767ea1..0000000
--- a/core/java/android/util/AndroidException.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-/**
- * Base class for all checked exceptions thrown by the Android frameworks.
- */
-public class AndroidException extends Exception {
- public AndroidException() {
- }
-
- public AndroidException(String name) {
- super(name);
- }
-
- public AndroidException(Exception cause) {
- super(cause);
- }
-};
-
diff --git a/core/java/android/util/AndroidRuntimeException.java b/core/java/android/util/AndroidRuntimeException.java
deleted file mode 100644
index 4ed17bc..0000000
--- a/core/java/android/util/AndroidRuntimeException.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-/**
- * Base class for all unchecked exceptions thrown by the Android frameworks.
- */
-public class AndroidRuntimeException extends RuntimeException {
- public AndroidRuntimeException() {
- }
-
- public AndroidRuntimeException(String name) {
- super(name);
- }
-
- public AndroidRuntimeException(Exception cause) {
- super(cause);
- }
-};
-
diff --git a/core/java/android/util/AttributeSet.java b/core/java/android/util/AttributeSet.java
deleted file mode 100644
index 01a7ad4..0000000
--- a/core/java/android/util/AttributeSet.java
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-
-/**
- * A collection of attributes, as found associated with a tag in an XML
- * document. Often you will not want to use this interface directly, instead
- * passing it to {@link android.content.res.Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)
- * Resources.Theme.obtainStyledAttributes()}
- * which will take care of parsing the attributes for you. In particular,
- * the Resources API will convert resource references (attribute values such as
- * "@string/my_label" in the original XML) to the desired type
- * for you; if you use AttributeSet directly then you will need to manually
- * check for resource references
- * (with {@link #getAttributeResourceValue(int, int)}) and do the resource
- * lookup yourself if needed. Direct use of AttributeSet also prevents the
- * application of themes and styles when retrieving attribute values.
- *
- * <p>This interface provides an efficient mechanism for retrieving
- * data from compiled XML files, which can be retrieved for a particular
- * XmlPullParser through {@link Xml#asAttributeSet
- * Xml.getAttributeSet()}. Normally this will return an implementation
- * of the interface that works on top of a generic XmlPullParser, however it
- * is more useful in conjunction with compiled XML resources:
- *
- * <pre>
- * XmlPullParser parser = resources.getXml(myResouce);
- * AttributeSet attributes = Xml.getAttributeSet(parser);</pre>
- *
- * <p>The implementation returned here, unlike using
- * the implementation on top of a generic XmlPullParser,
- * is highly optimized by retrieving pre-computed information that was
- * generated by aapt when compiling your resources. For example,
- * the {@link #getAttributeFloatValue(int, float)} method returns a floating
- * point number previous stored in the compiled resource instead of parsing
- * at runtime the string originally in the XML file.
- *
- * <p>This interface also provides additional information contained in the
- * compiled XML resource that is not available in a normal XML file, such
- * as {@link #getAttributeNameResource(int)} which returns the resource
- * identifier associated with a particular XML attribute name.
- */
-public interface AttributeSet {
- public int getAttributeCount();
- public String getAttributeName(int index);
- public String getAttributeValue(int index);
- public String getAttributeValue(String namespace, String name);
- public String getPositionDescription();
-
- /**
- * Return the resource ID associated with the given attribute name. This
- * will be the identifier for an attribute resource, which can be used by
- * styles. Returns 0 if there is no resource associated with this
- * attribute.
- *
- * <p>Note that this is different than {@link #getAttributeResourceValue}
- * in that it returns a resource identifier for the attribute name; the
- * other method returns this attribute's value as a resource identifier.
- *
- * @param index Index of the desired attribute, 0...count-1.
- *
- * @return The resource identifier, 0 if none.
- */
- public int getAttributeNameResource(int index);
-
- /**
- * Return the index of the value of 'attribute' in the list 'options'.
- *
- * @param attribute Name of attribute to retrieve.
- * @param options List of strings whose values we are checking against.
- * @param defaultValue Value returned if attribute doesn't exist or no
- * match is found.
- *
- * @return Index in to 'options' or defaultValue.
- */
- public int getAttributeListValue(String namespace, String attribute,
- String[] options, int defaultValue);
-
- /**
- * Return the boolean value of 'attribute'.
- *
- * @param attribute The attribute to retrieve.
- * @param defaultValue What to return if the attribute isn't found.
- *
- * @return Resulting value.
- */
- public boolean getAttributeBooleanValue(String namespace, String attribute,
- boolean defaultValue);
-
- /**
- * Return the value of 'attribute' as a resource identifier.
- *
- * <p>Note that this is different than {@link #getAttributeNameResource}
- * in that it returns a the value contained in this attribute as a
- * resource identifier (i.e., a value originally of the form
- * "@package:type/resource"); the other method returns a resource
- * identifier that identifies the name of the attribute.
- *
- * @param attribute The attribute to retrieve.
- * @param defaultValue What to return if the attribute isn't found.
- *
- * @return Resulting value.
- */
- public int getAttributeResourceValue(String namespace, String attribute,
- int defaultValue);
-
- /**
- * Return the integer value of 'attribute'.
- *
- * @param attribute The attribute to retrieve.
- * @param defaultValue What to return if the attribute isn't found.
- *
- * @return Resulting value.
- */
- public int getAttributeIntValue(String namespace, String attribute,
- int defaultValue);
-
- /**
- * Return the boolean value of 'attribute' that is formatted as an
- * unsigned value. In particular, the formats 0xn...n and #n...n are
- * handled.
- *
- * @param attribute The attribute to retrieve.
- * @param defaultValue What to return if the attribute isn't found.
- *
- * @return Resulting value.
- */
- public int getAttributeUnsignedIntValue(String namespace, String attribute,
- int defaultValue);
-
- /**
- * Return the float value of 'attribute'.
- *
- * @param attribute The attribute to retrieve.
- * @param defaultValue What to return if the attribute isn't found.
- *
- * @return Resulting value.
- */
- public float getAttributeFloatValue(String namespace, String attribute,
- float defaultValue);
-
- /**
- * Return the index of the value of attribute at 'index' in the list
- * 'options'.
- *
- * @param index Index of the desired attribute, 0...count-1.
- * @param options List of strings whose values we are checking against.
- * @param defaultValue Value returned if attribute doesn't exist or no
- * match is found.
- *
- * @return Index in to 'options' or defaultValue.
- */
- public int getAttributeListValue(int index,
- String[] options, int defaultValue);
-
- /**
- * Return the boolean value of attribute at 'index'.
- *
- * @param index Index of the desired attribute, 0...count-1.
- * @param defaultValue What to return if the attribute isn't found.
- *
- * @return Resulting value.
- */
- public boolean getAttributeBooleanValue(int index,
- boolean defaultValue);
-
- /**
- * Return the value of attribute at 'index' as a resource identifier.
- *
- * <p>Note that this is different than {@link #getAttributeNameResource}
- * in that it returns a the value contained in this attribute as a
- * resource identifier (i.e., a value originally of the form
- * "@package:type/resource"); the other method returns a resource
- * identifier that identifies the name of the attribute.
- *
- * @param index Index of the desired attribute, 0...count-1.
- * @param defaultValue What to return if the attribute isn't found.
- *
- * @return Resulting value.
- */
- public int getAttributeResourceValue(int index,
- int defaultValue);
-
- /**
- * Return the integer value of attribute at 'index'.
- *
- * @param index Index of the desired attribute, 0...count-1.
- * @param defaultValue What to return if the attribute isn't found.
- *
- * @return Resulting value.
- */
- public int getAttributeIntValue(int index,
- int defaultValue);
-
- /**
- * Return the integer value of attribute at 'index' that is formatted as an
- * unsigned value. In particular, the formats 0xn...n and #n...n are
- * handled.
- *
- * @param index Index of the desired attribute, 0...count-1.
- * @param defaultValue What to return if the attribute isn't found.
- *
- * @return Resulting value.
- */
- public int getAttributeUnsignedIntValue(int index,
- int defaultValue);
-
- /**
- * Return the float value of attribute at 'index'.
- *
- * @param index Index of the desired attribute, 0...count-1.
- * @param defaultValue What to return if the attribute isn't found.
- *
- * @return Resulting value.
- */
- public float getAttributeFloatValue(int index,
- float defaultValue);
-
- /**
- * Return the value of the "id" attribute or null if there is not one.
- * Equivalent to getAttributeValue(null, "id").
- *
- * @return The id attribute's value or null.
- */
- public String getIdAttribute();
-
- /**
- * Return the value of the "class" attribute or null if there is not one.
- * Equivalent to getAttributeValue(null, "class").
- *
- * @return The class attribute's value or null.
- */
- public String getClassAttribute();
-
- /**
- * Return the integer value of the "id" attribute or defaultValue if there
- * is none.
- * Equivalent to getAttributeResourceValue(null, "id", defaultValue);
- *
- * @param defaultValue What to return if the "id" attribute isn't found.
- * @return int Resulting value.
- */
- public int getIdAttributeResourceValue(int defaultValue);
-
- /**
-
- * Return the value of the "style" attribute or 0 if there is not one.
- * Equivalent to getAttributeResourceValue(null, "style").
- *
- * @return The style attribute's resource identifier or 0.
- */
- public int getStyleAttribute();
-}
-
diff --git a/core/java/android/util/Config.java b/core/java/android/util/Config.java
deleted file mode 100644
index c0b27f8..0000000
--- a/core/java/android/util/Config.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/* device/vmlibs-config/release/android/util/Config.java
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.util;
-
-/**
- * Build configuration. The constants in this class vary depending
- * on release vs. debug build. This is the configuration for release builds.
- * {@more}
- */
-public final class Config
-{
- /**
- * Is this a release build?
- */
- public static final boolean RELEASE = true;
-
- /**
- * Is this a debug build?
- */
- public static final boolean DEBUG = false;
-
- /**
- * Is profiling enabled?
- */
- public static final boolean PROFILE = false;
-
- /**
- * Are VERBOSE log messages enabled?
- */
- public static final boolean LOGV = false;
-
- /**
- * Are DEBUG log messages enabled?
- */
- public static final boolean LOGD = true;
-}
diff --git a/core/java/android/util/DayOfMonthCursor.java b/core/java/android/util/DayOfMonthCursor.java
deleted file mode 100644
index 393b98e..0000000
--- a/core/java/android/util/DayOfMonthCursor.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-/**
- * Helps control and display a month view of a calendar that has a current
- * selected day.
- * <ul>
- * <li>Keeps track of current month, day, year</li>
- * <li>Keeps track of current cursor position (row, column)</li>
- * <li>Provides methods to help display the calendar</li>
- * <li>Provides methods to move the cursor up / down / left / right.</li>
- * </ul>
- *
- * This should be used by anyone who presents a month view to users and wishes
- * to behave consistently with other widgets and apps; if we ever change our
- * mind about when to flip the month, we can change it here only.
- *
- * @hide
- */
-public class DayOfMonthCursor extends MonthDisplayHelper {
-
- private int mRow;
- private int mColumn;
-
- /**
- * @param year The initial year.
- * @param month The initial month.
- * @param dayOfMonth The initial dayOfMonth.
- * @param weekStartDay What dayOfMonth of the week the week should start,
- * in terms of {@link java.util.Calendar} constants such as
- * {@link java.util.Calendar#SUNDAY}.
- */
- public DayOfMonthCursor(int year, int month, int dayOfMonth, int weekStartDay) {
- super(year, month, weekStartDay);
- mRow = getRowOf(dayOfMonth);
- mColumn = getColumnOf(dayOfMonth);
- }
-
-
- public int getSelectedRow() {
- return mRow;
- }
-
- public int getSelectedColumn() {
- return mColumn;
- }
-
- public void setSelectedRowColumn(int row, int col) {
- mRow = row;
- mColumn = col;
- }
-
- public int getSelectedDayOfMonth() {
- return getDayAt(mRow, mColumn);
- }
-
- /**
- * @return 0 if the selection is in the current month, otherwise -1 or +1
- * depending on whether the selection is in the first or last row.
- */
- public int getSelectedMonthOffset() {
- if (isWithinCurrentMonth(mRow, mColumn)) {
- return 0;
- }
- if (mRow == 0) {
- return -1;
- }
- return 1;
- }
-
- public void setSelectedDayOfMonth(int dayOfMonth) {
- mRow = getRowOf(dayOfMonth);
- mColumn = getColumnOf(dayOfMonth);
- }
-
- public boolean isSelected(int row, int column) {
- return (mRow == row) && (mColumn == column);
- }
-
- /**
- * Move up one box, potentially flipping to the previous month.
- * @return Whether the month was flipped to the previous month
- * due to the move.
- */
- public boolean up() {
- if (isWithinCurrentMonth(mRow - 1, mColumn)) {
- // within current month, just move up
- mRow--;
- return false;
- }
- // flip back to previous month, same column, first position within month
- previousMonth();
- mRow = 5;
- while(!isWithinCurrentMonth(mRow, mColumn)) {
- mRow--;
- }
- return true;
- }
-
- /**
- * Move down one box, potentially flipping to the next month.
- * @return Whether the month was flipped to the next month
- * due to the move.
- */
- public boolean down() {
- if (isWithinCurrentMonth(mRow + 1, mColumn)) {
- // within current month, just move down
- mRow++;
- return false;
- }
- // flip to next month, same column, first position within month
- nextMonth();
- mRow = 0;
- while (!isWithinCurrentMonth(mRow, mColumn)) {
- mRow++;
- }
- return true;
- }
-
- /**
- * Move left one box, potentially flipping to the previous month.
- * @return Whether the month was flipped to the previous month
- * due to the move.
- */
- public boolean left() {
- if (mColumn == 0) {
- mRow--;
- mColumn = 6;
- } else {
- mColumn--;
- }
-
- if (isWithinCurrentMonth(mRow, mColumn)) {
- return false;
- }
-
- // need to flip to last day of previous month
- previousMonth();
- int lastDay = getNumberOfDaysInMonth();
- mRow = getRowOf(lastDay);
- mColumn = getColumnOf(lastDay);
- return true;
- }
-
- /**
- * Move right one box, potentially flipping to the next month.
- * @return Whether the month was flipped to the next month
- * due to the move.
- */
- public boolean right() {
- if (mColumn == 6) {
- mRow++;
- mColumn = 0;
- } else {
- mColumn++;
- }
-
- if (isWithinCurrentMonth(mRow, mColumn)) {
- return false;
- }
-
- // need to flip to first day of next month
- nextMonth();
- mRow = 0;
- mColumn = 0;
- while (!isWithinCurrentMonth(mRow, mColumn)) {
- mColumn++;
- }
- return true;
- }
-
-}
diff --git a/core/java/android/util/DebugUtils.java b/core/java/android/util/DebugUtils.java
deleted file mode 100644
index 1c5d669..0000000
--- a/core/java/android/util/DebugUtils.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
-
-/**
- * <p>Various utilities for debugging and logging.</p>
- */
-public class DebugUtils {
- /**
- * <p>Filters objects against the <code>ANDROID_OBJECT_FILTER</code>
- * environment variable. This environment variable can filter objects
- * based on their class name and attribute values.</p>
- *
- * <p>Here is the syntax for <code>ANDROID_OBJECT_FILTER</code>:</p>
- *
- * <p><code>ClassName@attribute1=value1@attribute2=value2...</code></p>
- *
- * <p>Examples:</p>
- * <ul>
- * <li>Select TextView instances: <code>TextView</code></li>
- * <li>Select TextView instances of text "Loading" and bottom offset of 22:
- * <code>TextView@text=Loading.*@bottom=22</code></li>
- * </ul>
- *
- * <p>The class name and the values are regular expressions.</p>
- *
- * <p>This class is useful for debugging and logging purpose:</p>
- * <pre>
- * if (Config.DEBUG) {
- * if (DebugUtils.isObjectSelected(childView) && Config.LOGV) {
- * Log.v(TAG, "Object " + childView + " logged!");
- * }
- * }
- * </pre>
- *
- * <p><strong>NOTE</strong>: This method is very expensive as it relies
- * heavily on regular expressions and reflection. Calls to this method
- * should always be stripped out of the release binaries and avoided
- * as much as possible in debug mode.</p>
- *
- * @param object any object to match against the ANDROID_OBJECT_FILTER
- * environement variable
- * @return true if object is selected by the ANDROID_OBJECT_FILTER
- * environment variable, false otherwise
- */
- public static boolean isObjectSelected(Object object) {
- boolean match = false;
- String s = System.getenv("ANDROID_OBJECT_FILTER");
- if (s != null && s.length() > 0) {
- String[] selectors = s.split("@");
- // first selector == class name
- if (object.getClass().getSimpleName().matches(selectors[0])) {
- // check potential attributes
- for (int i = 1; i < selectors.length; i++) {
- String[] pair = selectors[i].split("=");
- Class<?> klass = object.getClass();
- try {
- Method declaredMethod = null;
- Class<?> parent = klass;
- do {
- declaredMethod = parent.getDeclaredMethod("get" +
- pair[0].substring(0, 1).toUpperCase() +
- pair[0].substring(1),
- (Class[]) null);
- } while ((parent = klass.getSuperclass()) != null &&
- declaredMethod == null);
-
- if (declaredMethod != null) {
- Object value = declaredMethod
- .invoke(object, (Object[])null);
- match |= (value != null ?
- value.toString() : "null").matches(pair[1]);
- }
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- }
- }
- }
- }
- return match;
- }
-
-}
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
deleted file mode 100644
index 9de4cbe..0000000
--- a/core/java/android/util/DisplayMetrics.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import android.os.*;
-
-
-/**
- * A structure describing general information about a display, such as its
- * size, density, and font scaling.
- */
-public class DisplayMetrics {
- /**
- * The reference density used throughout the system.
- *
- * @hide Pending API council approval
- */
- public static final int DEFAULT_DENSITY = 160;
-
- private static final int sLcdDensity = SystemProperties.getInt("ro.sf.lcd_density",
- DEFAULT_DENSITY);
-
- /**
- * The absolute width of the display in pixels.
- */
- public int widthPixels;
- /**
- * The absolute height of the display in pixels.
- */
- public int heightPixels;
- /**
- * The logical density of the display. This is a scaling factor for the
- * Density Independent Pixel unit, where one DIP is one pixel on an
- * approximately 160 dpi screen (for example a 240x320, 1.5"x2" screen),
- * providing the baseline of the system's display. Thus on a 160dpi screen
- * this density value will be 1; on a 106 dpi screen it would be .75; etc.
- *
- * <p>This value does not exactly follow the real screen size (as given by
- * {@link #xdpi} and {@link #ydpi}, but rather is used to scale the size of
- * the overall UI in steps based on gross changes in the display dpi. For
- * example, a 240x320 screen will have a density of 1 even if its width is
- * 1.8", 1.3", etc. However, if the screen resolution is increased to
- * 320x480 but the screen size remained 1.5"x2" then the density would be
- * increased (probably to 1.5).
- *
- * @see #DEFAULT_DENSITY
- */
- public float density;
- /**
- * A scaling factor for fonts displayed on the display. This is the same
- * as {@link #density}, except that it may be adjusted in smaller
- * increments at runtime based on a user preference for the font size.
- */
- public float scaledDensity;
- /**
- * The exact physical pixels per inch of the screen in the X dimension.
- */
- public float xdpi;
- /**
- * The exact physical pixels per inch of the screen in the Y dimension.
- */
- public float ydpi;
-
- public DisplayMetrics() {
- }
-
- public void setTo(DisplayMetrics o) {
- widthPixels = o.widthPixels;
- heightPixels = o.heightPixels;
- density = o.density;
- scaledDensity = o.scaledDensity;
- xdpi = o.xdpi;
- ydpi = o.ydpi;
- }
-
- public void setToDefaults() {
- widthPixels = 0;
- heightPixels = 0;
- density = sLcdDensity / (float) DEFAULT_DENSITY;
- scaledDensity = density;
- xdpi = sLcdDensity;
- ydpi = sLcdDensity;
- }
-}
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java
deleted file mode 100644
index 24b4f73..0000000
--- a/core/java/android/util/EventLog.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import com.google.android.collect.Lists;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * {@hide}
- * Dynamically defined (in terms of event types), space efficient (i.e. "tight") event logging
- * to help instrument code for large scale stability and performance monitoring.
- *
- * Note that this class contains all static methods. This is done for efficiency reasons.
- *
- * Events for the event log are self-describing binary data structures. They start with a 20 byte
- * header (generated automatically) which contains all of the following in order:
- *
- * <ul>
- * <li> Payload length: 2 bytes - length of the non-header portion </li>
- * <li> Padding: 2 bytes - no meaning at this time </li>
- * <li> Timestamp:
- * <ul>
- * <li> Seconds: 4 bytes - seconds since Epoch </li>
- * <li> Nanoseconds: 4 bytes - plus extra nanoseconds </li>
- * </ul></li>
- * <li> Process ID: 4 bytes - matching {@link android.os.Process#myPid} </li>
- * <li> Thread ID: 4 bytes - matching {@link android.os.Process#myTid} </li>
- * </li>
- * </ul>
- *
- * The above is followed by a payload, comprised of the following:
- * <ul>
- * <li> Tag: 4 bytes - unique integer used to identify a particular event. This number is also
- * used as a key to map to a string that can be displayed by log reading tools.
- * </li>
- * <li> Type: 1 byte - can be either {@link #INT}, {@link #LONG}, {@link #STRING},
- * or {@link #LIST}. </li>
- * <li> Event log value: the size and format of which is one of:
- * <ul>
- * <li> INT: 4 bytes </li>
- * <li> LONG: 8 bytes </li>
- * <li> STRING:
- * <ul>
- * <li> Size of STRING: 4 bytes </li>
- * <li> The string: n bytes as specified in the size fields above. </li>
- * </ul></li>
- * <li> {@link List LIST}:
- * <ul>
- * <li> Num items: 1 byte </li>
- * <li> N value payloads, where N is the number of items specified above. </li>
- * </ul></li>
- * </ul>
- * </li>
- * <li> '\n': 1 byte - an automatically generated newline, used to help detect and recover from log
- * corruption and enable stansard unix tools like grep, tail and wc to operate
- * on event logs. </li>
- * </ul>
- *
- * Note that all output is done in the endian-ness of the device (as determined
- * by {@link ByteOrder#nativeOrder()}).
- */
-
-public class EventLog {
-
- // Value types
- public static final byte INT = 0;
- public static final byte LONG = 1;
- public static final byte STRING = 2;
- public static final byte LIST = 3;
-
- /**
- * An immutable tuple used to log a heterogeneous set of loggable items.
- * The items can be Integer, Long, String, or {@link List}.
- * The maximum number of items is 127
- */
- public static final class List {
- private Object[] mItems;
-
- /**
- * Get a particular tuple item
- * @param pos The position of the item in the tuple
- */
- public final Object getItem(int pos) {
- return mItems[pos];
- }
-
- /**
- * Get the number of items in the tuple.
- */
- public final byte getNumItems() {
- return (byte) mItems.length;
- }
-
- /**
- * Create a new tuple.
- * @param items The items to create the tuple with, as varargs.
- * @throws IllegalArgumentException if the arguments are too few (0),
- * too many, or aren't loggable types.
- */
- public List(Object... items) throws IllegalArgumentException {
- if (items.length > Byte.MAX_VALUE) {
- throw new IllegalArgumentException(
- "A List must have fewer than "
- + Byte.MAX_VALUE + " items in it.");
- }
- if (items.length < 1) {
- throw new IllegalArgumentException(
- "A List must have at least one item in it.");
- }
- for (int i = 0; i < items.length; i++) {
- final Object item = items[i];
- if (item == null) {
- // Would be nice to be able to write null strings...
- items[i] = "";
- } else if (!(item instanceof List ||
- item instanceof String ||
- item instanceof Integer ||
- item instanceof Long)) {
- throw new IllegalArgumentException(
- "Attempt to create a List with illegal item type.");
- }
- }
- this.mItems = items;
- }
- }
-
- /**
- * A previously logged event read from the logs.
- */
- public static final class Event {
- private final ByteBuffer mBuffer;
-
- // Layout of event log entry received from kernel.
- private static final int LENGTH_OFFSET = 0;
- private static final int PROCESS_OFFSET = 4;
- private static final int THREAD_OFFSET = 8;
- private static final int SECONDS_OFFSET = 12;
- private static final int NANOSECONDS_OFFSET = 16;
-
- private static final int PAYLOAD_START = 20;
- private static final int TAG_OFFSET = 20;
- private static final int DATA_START = 24;
-
- /** @param data containing event, read from the system */
- public Event(byte[] data) {
- mBuffer = ByteBuffer.wrap(data);
- mBuffer.order(ByteOrder.nativeOrder());
- }
-
- public int getProcessId() {
- return mBuffer.getInt(PROCESS_OFFSET);
- }
-
- public int getThreadId() {
- return mBuffer.getInt(THREAD_OFFSET);
- }
-
- public long getTimeNanos() {
- return mBuffer.getInt(SECONDS_OFFSET) * 1000000000l
- + mBuffer.getInt(NANOSECONDS_OFFSET);
- }
-
- public int getTag() {
- return mBuffer.getInt(TAG_OFFSET);
- }
-
- /** @return one of Integer, Long, String, or List. */
- public synchronized Object getData() {
- mBuffer.limit(PAYLOAD_START + mBuffer.getShort(LENGTH_OFFSET));
- mBuffer.position(DATA_START); // Just after the tag.
- return decodeObject();
- }
-
- /** @return the loggable item at the current position in mBuffer. */
- private Object decodeObject() {
- if (mBuffer.remaining() < 1) return null;
- switch (mBuffer.get()) {
- case INT:
- if (mBuffer.remaining() < 4) return null;
- return mBuffer.getInt();
-
- case LONG:
- if (mBuffer.remaining() < 8) return null;
- return mBuffer.getLong();
-
- case STRING:
- try {
- if (mBuffer.remaining() < 4) return null;
- int length = mBuffer.getInt();
- if (length < 0 || mBuffer.remaining() < length) return null;
- int start = mBuffer.position();
- mBuffer.position(start + length);
- return new String(mBuffer.array(), start, length, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e); // UTF-8 is guaranteed.
- }
-
- case LIST:
- if (mBuffer.remaining() < 1) return null;
- int length = mBuffer.get();
- if (length <= 0) return null;
- Object[] array = new Object[length];
- for (int i = 0; i < length; ++i) {
- array[i] = decodeObject();
- if (array[i] == null) return null;
- }
- return new List(array);
-
- default:
- return null;
- }
- }
- }
-
- // We assume that the native methods deal with any concurrency issues.
-
- /**
- * Send an event log message.
- * @param tag An event identifer
- * @param value A value to log
- * @return The number of bytes written
- */
- public static native int writeEvent(int tag, int value);
-
- /**
- * Send an event log message.
- * @param tag An event identifer
- * @param value A value to log
- * @return The number of bytes written
- */
- public static native int writeEvent(int tag, long value);
-
- /**
- * Send an event log message.
- * @param tag An event identifer
- * @param str A value to log
- * @return The number of bytes written
- */
- public static native int writeEvent(int tag, String str);
-
- /**
- * Send an event log message.
- * @param tag An event identifer
- * @param list A {@link List} to log
- * @return The number of bytes written
- */
- public static native int writeEvent(int tag, List list);
-
- /**
- * Send an event log message.
- * @param tag An event identifer
- * @param list A list of values to log
- * @return The number of bytes written
- */
- public static int writeEvent(int tag, Object... list) {
- return writeEvent(tag, new List(list));
- }
-
- /**
- * Read events from the log, filtered by type.
- * @param tags to search for
- * @param output container to add events into
- * @throws IOException if something goes wrong reading events
- */
- public static native void readEvents(int[] tags, Collection<Event> output)
- throws IOException;
-}
diff --git a/core/java/android/util/EventLogTags.java b/core/java/android/util/EventLogTags.java
deleted file mode 100644
index be905e3..0000000
--- a/core/java/android/util/EventLogTags.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import android.util.Log;
-
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/** Parsed representation of /etc/event-log-tags. */
-public class EventLogTags {
- private final static String TAG = "EventLogTags";
-
- private final static String TAGS_FILE = "/etc/event-log-tags";
-
- public static class Description {
- public final int mTag;
- public final String mName;
- // TODO: Parse parameter descriptions when anyone has a use for them.
-
- Description(int tag, String name) {
- mTag = tag;
- mName = name;
- }
- }
-
- private final static Pattern COMMENT_PATTERN = Pattern.compile(
- "^\\s*(#.*)?$");
-
- private final static Pattern TAG_PATTERN = Pattern.compile(
- "^\\s*(\\d+)\\s+(\\w+)\\s*(\\(.*\\))?\\s*$");
-
- private final HashMap<String, Description> mNameMap =
- new HashMap<String, Description>();
-
- private final HashMap<Integer, Description> mTagMap =
- new HashMap<Integer, Description>();
-
- public EventLogTags() throws IOException {
- this(new BufferedReader(new FileReader(TAGS_FILE), 256));
- }
-
- public EventLogTags(BufferedReader input) throws IOException {
- String line;
- while ((line = input.readLine()) != null) {
- Matcher m = COMMENT_PATTERN.matcher(line);
- if (m.matches()) continue;
-
- m = TAG_PATTERN.matcher(line);
- if (m.matches()) {
- try {
- int tag = Integer.parseInt(m.group(1));
- Description d = new Description(tag, m.group(2));
- mNameMap.put(d.mName, d);
- mTagMap.put(d.mTag, d);
- } catch (NumberFormatException e) {
- Log.e(TAG, "Error in event log tags entry: " + line, e);
- }
- } else {
- Log.e(TAG, "Can't parse event log tags entry: " + line);
- }
- }
- }
-
- public Description get(String name) {
- return mNameMap.get(name);
- }
-
- public Description get(int tag) {
- return mTagMap.get(tag);
- }
-}
diff --git a/core/java/android/util/FloatMath.java b/core/java/android/util/FloatMath.java
deleted file mode 100644
index 6216638..0000000
--- a/core/java/android/util/FloatMath.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-/**
- * Math routines similar to those found in {@link java.lang.Math}. Performs
- * computations on {@code float} values directly without incurring the overhead
- * of conversions to and from {@code double}.
- *
- * <p>On one platform, {@code FloatMath.sqrt(100)} executes in one third of the
- * time required by {@code java.lang.Math.sqrt(100)}.</p>
- */
-public class FloatMath {
-
- /** Prevents instantiation. */
- private FloatMath() {}
-
- /**
- * Returns the float conversion of the most positive (i.e. closest to
- * positive infinity) integer value which is less than the argument.
- *
- * @param value to be converted
- * @return the floor of value
- */
- public static native float floor(float value);
-
- /**
- * Returns the float conversion of the most negative (i.e. closest to
- * negative infinity) integer value which is greater than the argument.
- *
- * @param value to be converted
- * @return the ceiling of value
- */
- public static native float ceil(float value);
-
- /**
- * Returns the closest float approximation of the sine of the argument.
- *
- * @param angle to compute the cosine of, in radians
- * @return the sine of angle
- */
- public static native float sin(float angle);
-
- /**
- * Returns the closest float approximation of the cosine of the argument.
- *
- * @param angle to compute the cosine of, in radians
- * @return the cosine of angle
- */
- public static native float cos(float angle);
-
- /**
- * Returns the closest float approximation of the square root of the
- * argument.
- *
- * @param value to compute sqrt of
- * @return the square root of value
- */
- public static native float sqrt(float value);
-}
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
deleted file mode 100644
index 2572679..0000000
--- a/core/java/android/util/Log.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import com.android.internal.os.RuntimeInit;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-/**
- * API for sending log output.
- *
- * <p>Generally, use the Log.v() Log.d() Log.i() Log.w() and Log.e()
- * methods.
- *
- * <p>The order in terms of verbosity, from least to most is
- * ERROR, WARN, INFO, DEBUG, VERBOSE. Verbose should never be compiled
- * into an application except during development. Debug logs are compiled
- * in but stripped at runtime. Error, warning and info logs are always kept.
- *
- * <p><b>Tip:</b> A good convention is to declare a <code>TAG</code> constant
- * in your class:
- *
- * <pre>private static final String TAG = "MyActivity";</pre>
- *
- * and use that in subsequent calls to the log methods.
- * </p>
- *
- * <p><b>Tip:</b> Don't forget that when you make a call like
- * <pre>Log.v(TAG, "index=" + i);</pre>
- * that when you're building the string to pass into Log.d, the compiler uses a
- * StringBuilder and at least three allocations occur: the StringBuilder
- * itself, the buffer, and the String object. Realistically, there is also
- * another buffer allocation and copy, and even more pressure on the gc.
- * That means that if your log message is filtered out, you might be doing
- * significant work and incurring significant overhead.
- */
-public final class Log {
-
- /**
- * Priority constant for the println method; use Log.v.
- */
- public static final int VERBOSE = 2;
-
- /**
- * Priority constant for the println method; use Log.d.
- */
- public static final int DEBUG = 3;
-
- /**
- * Priority constant for the println method; use Log.i.
- */
- public static final int INFO = 4;
-
- /**
- * Priority constant for the println method; use Log.w.
- */
- public static final int WARN = 5;
-
- /**
- * Priority constant for the println method; use Log.e.
- */
- public static final int ERROR = 6;
-
- /**
- * Priority constant for the println method.
- */
- public static final int ASSERT = 7;
-
- private Log() {
- }
-
- /**
- * Send a {@link #VERBOSE} log message.
- * @param tag Used to identify the source of a log message. It usually identifies
- * the class or activity where the log call occurs.
- * @param msg The message you would like logged.
- */
- public static int v(String tag, String msg) {
- return println(VERBOSE, tag, msg);
- }
-
- /**
- * Send a {@link #VERBOSE} log message and log the exception.
- * @param tag Used to identify the source of a log message. It usually identifies
- * the class or activity where the log call occurs.
- * @param msg The message you would like logged.
- * @param tr An exception to log
- */
- public static int v(String tag, String msg, Throwable tr) {
- return println(VERBOSE, tag, msg + '\n' + getStackTraceString(tr));
- }
-
- /**
- * Send a {@link #DEBUG} log message.
- * @param tag Used to identify the source of a log message. It usually identifies
- * the class or activity where the log call occurs.
- * @param msg The message you would like logged.
- */
- public static int d(String tag, String msg) {
- return println(DEBUG, tag, msg);
- }
-
- /**
- * Send a {@link #DEBUG} log message and log the exception.
- * @param tag Used to identify the source of a log message. It usually identifies
- * the class or activity where the log call occurs.
- * @param msg The message you would like logged.
- * @param tr An exception to log
- */
- public static int d(String tag, String msg, Throwable tr) {
- return println(DEBUG, tag, msg + '\n' + getStackTraceString(tr));
- }
-
- /**
- * Send an {@link #INFO} log message.
- * @param tag Used to identify the source of a log message. It usually identifies
- * the class or activity where the log call occurs.
- * @param msg The message you would like logged.
- */
- public static int i(String tag, String msg) {
- return println(INFO, tag, msg);
- }
-
- /**
- * Send a {@link #INFO} log message and log the exception.
- * @param tag Used to identify the source of a log message. It usually identifies
- * the class or activity where the log call occurs.
- * @param msg The message you would like logged.
- * @param tr An exception to log
- */
- public static int i(String tag, String msg, Throwable tr) {
- return println(INFO, tag, msg + '\n' + getStackTraceString(tr));
- }
-
- /**
- * Send a {@link #WARN} log message.
- * @param tag Used to identify the source of a log message. It usually identifies
- * the class or activity where the log call occurs.
- * @param msg The message you would like logged.
- */
- public static int w(String tag, String msg) {
- return println(WARN, tag, msg);
- }
-
- /**
- * Send a {@link #WARN} log message and log the exception.
- * @param tag Used to identify the source of a log message. It usually identifies
- * the class or activity where the log call occurs.
- * @param msg The message you would like logged.
- * @param tr An exception to log
- */
- public static int w(String tag, String msg, Throwable tr) {
- return println(WARN, tag, msg + '\n' + getStackTraceString(tr));
- }
-
- /**
- * Checks to see whether or not a log for the specified tag is loggable at the specified level.
- *
- * The default level of any tag is set to INFO. This means that any level above and including
- * INFO will be logged. Before you make any calls to a logging method you should check to see
- * if your tag should be logged. You can change the default level by setting a system property:
- * 'setprop log.tag.&lt;YOUR_LOG_TAG> &lt;LEVEL>'
- * Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or SUPPRESS. SUPRESS will
- * turn off all logging for your tag. You can also create a local.prop file that with the
- * following in it:
- * 'log.tag.&lt;YOUR_LOG_TAG>=&lt;LEVEL>'
- * and place that in /data/local.prop.
- *
- * @param tag The tag to check.
- * @param level The level to check.
- * @return Whether or not that this is allowed to be logged.
- * @throws IllegalArgumentException is thrown if the tag.length() > 23.
- */
- public static native boolean isLoggable(String tag, int level);
-
- /*
- * Send a {@link #WARN} log message and log the exception.
- * @param tag Used to identify the source of a log message. It usually identifies
- * the class or activity where the log call occurs.
- * @param tr An exception to log
- */
- public static int w(String tag, Throwable tr) {
- return println(WARN, tag, getStackTraceString(tr));
- }
-
- /**
- * Send an {@link #ERROR} log message.
- * @param tag Used to identify the source of a log message. It usually identifies
- * the class or activity where the log call occurs.
- * @param msg The message you would like logged.
- */
- public static int e(String tag, String msg) {
- return println(ERROR, tag, msg);
- }
-
- /**
- * Send a {@link #ERROR} log message and log the exception.
- * @param tag Used to identify the source of a log message. It usually identifies
- * the class or activity where the log call occurs.
- * @param msg The message you would like logged.
- * @param tr An exception to log
- */
- public static int e(String tag, String msg, Throwable tr) {
- int r = println(ERROR, tag, msg + '\n' + getStackTraceString(tr));
- RuntimeInit.reportException(tag, tr, false); // asynchronous
- return r;
- }
-
- /**
- * Handy function to get a loggable stack trace from a Throwable
- * @param tr An exception to log
- */
- public static String getStackTraceString(Throwable tr) {
- if (tr == null) {
- return "";
- }
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- tr.printStackTrace(pw);
- return sw.toString();
- }
-
- /**
- * Low-level logging call.
- * @param priority The priority/type of this log message
- * @param tag Used to identify the source of a log message. It usually identifies
- * the class or activity where the log call occurs.
- * @param msg The message you would like logged.
- * @return The number of bytes written.
- */
- public static native int println(int priority, String tag, String msg);
-}
diff --git a/core/java/android/util/LogPrinter.java b/core/java/android/util/LogPrinter.java
deleted file mode 100644
index 643b8d3..0000000
--- a/core/java/android/util/LogPrinter.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-/**
- * Implementation of a {@link android.util.Printer} that sends its output
- * to the system log.
- */
-public class LogPrinter implements Printer {
- private final int mPriority;
- private final String mTag;
-
- /**
- * Create a new Printer that sends to the log with the given priority
- * and tag.
- *
- * @param priority The desired log priority:
- * {@link android.util.Log#VERBOSE Log.VERBOSE},
- * {@link android.util.Log#DEBUG Log.DEBUG},
- * {@link android.util.Log#INFO Log.INFO},
- * {@link android.util.Log#WARN Log.WARN}, or
- * {@link android.util.Log#ERROR Log.ERROR}.
- * @param tag A string tag to associate with each printed log statement.
- */
- public LogPrinter(int priority, String tag) {
- mPriority = priority;
- mTag = tag;
- }
-
- public void println(String x) {
- Log.println(mPriority, mTag, x);
- }
-}
diff --git a/core/java/android/util/MonthDisplayHelper.java b/core/java/android/util/MonthDisplayHelper.java
deleted file mode 100644
index c3f13fc..0000000
--- a/core/java/android/util/MonthDisplayHelper.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import java.util.Calendar;
-
-/**
- * Helps answer common questions that come up when displaying a month in a
- * 6 row calendar grid format.
- *
- * Not thread safe.
- */
-public class MonthDisplayHelper {
-
- // display pref
- private final int mWeekStartDay;
-
- // holds current month, year, helps compute display
- private Calendar mCalendar;
-
- // cached computed stuff that helps with display
- private int mNumDaysInMonth;
- private int mNumDaysInPrevMonth;
- private int mOffset;
-
-
- /**
- * @param year The year.
- * @param month The month.
- * @param weekStartDay What day of the week the week should start.
- */
- public MonthDisplayHelper(int year, int month, int weekStartDay) {
-
- if (weekStartDay < Calendar.SUNDAY || weekStartDay > Calendar.SATURDAY) {
- throw new IllegalArgumentException();
- }
- mWeekStartDay = weekStartDay;
-
- mCalendar = Calendar.getInstance();
- mCalendar.set(Calendar.YEAR, year);
- mCalendar.set(Calendar.MONTH, month);
- mCalendar.set(Calendar.DAY_OF_MONTH, 1);
- mCalendar.set(Calendar.HOUR_OF_DAY, 0);
- mCalendar.set(Calendar.MINUTE, 0);
- mCalendar.set(Calendar.SECOND, 0);
- mCalendar.getTimeInMillis();
-
- recalculate();
- }
-
-
- public MonthDisplayHelper(int year, int month) {
- this(year, month, Calendar.SUNDAY);
- }
-
-
- public int getYear() {
- return mCalendar.get(Calendar.YEAR);
- }
-
- public int getMonth() {
- return mCalendar.get(Calendar.MONTH);
- }
-
-
- public int getWeekStartDay() {
- return mWeekStartDay;
- }
-
- /**
- * @return The first day of the month using a constants such as
- * {@link java.util.Calendar#SUNDAY}.
- */
- public int getFirstDayOfMonth() {
- return mCalendar.get(Calendar.DAY_OF_WEEK);
- }
-
- /**
- * @return The number of days in the month.
- */
- public int getNumberOfDaysInMonth() {
- return mNumDaysInMonth;
- }
-
-
- /**
- * @return The offset from displaying everything starting on the very first
- * box. For example, if the calendar is set to display the first day of
- * the week as Sunday, and the month starts on a Wednesday, the offset is 3.
- */
- public int getOffset() {
- return mOffset;
- }
-
-
- /**
- * @param row Which row (0-5).
- * @return the digits of the month to display in one
- * of the 6 rows of a calendar month display.
- */
- public int[] getDigitsForRow(int row) {
- if (row < 0 || row > 5) {
- throw new IllegalArgumentException("row " + row
- + " out of range (0-5)");
- }
-
- int [] result = new int[7];
- for (int column = 0; column < 7; column++) {
- result[column] = getDayAt(row, column);
- }
-
- return result;
- }
-
- /**
- * @param row The row, 0-5, starting from the top.
- * @param column The column, 0-6, starting from the left.
- * @return The day at a particular row, column
- */
- public int getDayAt(int row, int column) {
-
- if (row == 0 && column < mOffset) {
- return mNumDaysInPrevMonth + column - mOffset + 1;
- }
-
- int day = 7 * row + column - mOffset + 1;
-
- return (day > mNumDaysInMonth) ?
- day - mNumDaysInMonth : day;
- }
-
- /**
- * @return Which row day is in.
- */
- public int getRowOf(int day) {
- return (day + mOffset - 1) / 7;
- }
-
- /**
- * @return Which column day is in.
- */
- public int getColumnOf(int day) {
- return (day + mOffset - 1) % 7;
- }
-
- /**
- * Decrement the month.
- */
- public void previousMonth() {
- mCalendar.add(Calendar.MONTH, -1);
- recalculate();
- }
-
- /**
- * Increment the month.
- */
- public void nextMonth() {
- mCalendar.add(Calendar.MONTH, 1);
- recalculate();
- }
-
- /**
- * @return Whether the row and column fall within the month.
- */
- public boolean isWithinCurrentMonth(int row, int column) {
-
- if (row < 0 || column < 0 || row > 5 || column > 6) {
- return false;
- }
-
- if (row == 0 && column < mOffset) {
- return false;
- }
-
- int day = 7 * row + column - mOffset + 1;
- if (day > mNumDaysInMonth) {
- return false;
- }
- return true;
- }
-
-
- // helper method that recalculates cached values based on current month / year
- private void recalculate() {
-
- mNumDaysInMonth = mCalendar.getActualMaximum(Calendar.DAY_OF_MONTH);
-
- mCalendar.add(Calendar.MONTH, -1);
- mNumDaysInPrevMonth = mCalendar.getActualMaximum(Calendar.DAY_OF_MONTH);
- mCalendar.add(Calendar.MONTH, 1);
-
- int firstDayOfMonth = getFirstDayOfMonth();
- int offset = firstDayOfMonth - mWeekStartDay;
- if (offset < 0) {
- offset += 7;
- }
- mOffset = offset;
- }
-}
diff --git a/core/java/android/util/PrintStreamPrinter.java b/core/java/android/util/PrintStreamPrinter.java
deleted file mode 100644
index 1c11f15..0000000
--- a/core/java/android/util/PrintStreamPrinter.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import java.io.PrintStream;
-
-/**
- * Implementation of a {@link android.util.Printer} that sends its output
- * to a {@link java.io.PrintStream}.
- */
-public class PrintStreamPrinter implements Printer {
- private final PrintStream mPS;
-
- /**
- * Create a new Printer that sends to a PrintWriter object.
- *
- * @param pw The PrintWriter where you would like output to go.
- */
- public PrintStreamPrinter(PrintStream pw) {
- mPS = pw;
- }
-
- public void println(String x) {
- mPS.println(x);
- }
-}
diff --git a/core/java/android/util/PrintWriterPrinter.java b/core/java/android/util/PrintWriterPrinter.java
deleted file mode 100644
index 82c4d03..0000000
--- a/core/java/android/util/PrintWriterPrinter.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import java.io.PrintWriter;
-
-/**
- * Implementation of a {@link android.util.Printer} that sends its output
- * to a {@link java.io.PrintWriter}.
- */
-public class PrintWriterPrinter implements Printer {
- private final PrintWriter mPW;
-
- /**
- * Create a new Printer that sends to a PrintWriter object.
- *
- * @param pw The PrintWriter where you would like output to go.
- */
- public PrintWriterPrinter(PrintWriter pw) {
- mPW = pw;
- }
-
- public void println(String x) {
- mPW.println(x);
- }
-}
diff --git a/core/java/android/util/Printer.java b/core/java/android/util/Printer.java
deleted file mode 100644
index 595cf70..0000000
--- a/core/java/android/util/Printer.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-/**
- * Simple interface for printing text, allowing redirection to various
- * targets. Standard implementations are {@link android.util.LogPrinter},
- * {@link android.util.StringBuilderPrinter}, and
- * {@link android.util.PrintWriterPrinter}.
- */
-public interface Printer {
- /**
- * Write a line of text to the output. There is no need to terminate
- * the given string with a newline.
- */
- void println(String x);
-}
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
deleted file mode 100644
index 1c8b330..0000000
--- a/core/java/android/util/SparseArray.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import com.android.internal.util.ArrayUtils;
-
-/**
- * SparseArrays map integers to Objects. Unlike a normal array of Objects,
- * there can be gaps in the indices. It is intended to be more efficient
- * than using a HashMap to map Integers to Objects.
- */
-public class SparseArray<E> {
- private static final Object DELETED = new Object();
- private boolean mGarbage = false;
-
- /**
- * Creates a new SparseArray containing no mappings.
- */
- public SparseArray() {
- this(10);
- }
-
- /**
- * Creates a new SparseArray containing no mappings that will not
- * require any additional memory allocation to store the specified
- * number of mappings.
- */
- public SparseArray(int initialCapacity) {
- initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
-
- mKeys = new int[initialCapacity];
- mValues = new Object[initialCapacity];
- mSize = 0;
- }
-
- /**
- * Gets the Object mapped from the specified key, or <code>null</code>
- * if no such mapping has been made.
- */
- public E get(int key) {
- return get(key, null);
- }
-
- /**
- * Gets the Object mapped from the specified key, or the specified Object
- * if no such mapping has been made.
- */
- public E get(int key, E valueIfKeyNotFound) {
- int i = binarySearch(mKeys, 0, mSize, key);
-
- if (i < 0 || mValues[i] == DELETED) {
- return valueIfKeyNotFound;
- } else {
- return (E) mValues[i];
- }
- }
-
- /**
- * Removes the mapping from the specified key, if there was any.
- */
- public void delete(int key) {
- int i = binarySearch(mKeys, 0, mSize, key);
-
- if (i >= 0) {
- if (mValues[i] != DELETED) {
- mValues[i] = DELETED;
- mGarbage = true;
- }
- }
- }
-
- /**
- * Alias for {@link #delete(int)}.
- */
- public void remove(int key) {
- delete(key);
- }
-
- private void gc() {
- // Log.e("SparseArray", "gc start with " + mSize);
-
- int n = mSize;
- int o = 0;
- int[] keys = mKeys;
- Object[] values = mValues;
-
- for (int i = 0; i < n; i++) {
- Object val = values[i];
-
- if (val != DELETED) {
- if (i != o) {
- keys[o] = keys[i];
- values[o] = val;
- }
-
- o++;
- }
- }
-
- mGarbage = false;
- mSize = o;
-
- // Log.e("SparseArray", "gc end with " + mSize);
- }
-
- /**
- * Adds a mapping from the specified key to the specified value,
- * replacing the previous mapping from the specified key if there
- * was one.
- */
- public void put(int key, E value) {
- int i = binarySearch(mKeys, 0, mSize, key);
-
- if (i >= 0) {
- mValues[i] = value;
- } else {
- i = ~i;
-
- if (i < mSize && mValues[i] == DELETED) {
- mKeys[i] = key;
- mValues[i] = value;
- return;
- }
-
- if (mGarbage && mSize >= mKeys.length) {
- gc();
-
- // Search again because indices may have changed.
- i = ~binarySearch(mKeys, 0, mSize, key);
- }
-
- if (mSize >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(mSize + 1);
-
- int[] nkeys = new int[n];
- Object[] nvalues = new Object[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- if (mSize - i != 0) {
- // Log.e("SparseArray", "move " + (mSize - i));
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
- mSize++;
- }
- }
-
- /**
- * Returns the number of key-value mappings that this SparseArray
- * currently stores.
- */
- public int size() {
- if (mGarbage) {
- gc();
- }
-
- return mSize;
- }
-
- /**
- * Given an index in the range <code>0...size()-1</code>, returns
- * the key from the <code>index</code>th key-value mapping that this
- * SparseArray stores.
- */
- public int keyAt(int index) {
- if (mGarbage) {
- gc();
- }
-
- return mKeys[index];
- }
-
- /**
- * Given an index in the range <code>0...size()-1</code>, returns
- * the value from the <code>index</code>th key-value mapping that this
- * SparseArray stores.
- */
- public E valueAt(int index) {
- if (mGarbage) {
- gc();
- }
-
- return (E) mValues[index];
- }
-
- /**
- * Given an index in the range <code>0...size()-1</code>, sets a new
- * value for the <code>index</code>th key-value mapping that this
- * SparseArray stores.
- */
- public void setValueAt(int index, E value) {
- if (mGarbage) {
- gc();
- }
-
- mValues[index] = value;
- }
-
- /**
- * Returns the index for which {@link #keyAt} would return the
- * specified key, or a negative number if the specified
- * key is not mapped.
- */
- public int indexOfKey(int key) {
- if (mGarbage) {
- gc();
- }
-
- return binarySearch(mKeys, 0, mSize, key);
- }
-
- /**
- * Returns an index for which {@link #valueAt} would return the
- * specified key, or a negative number if no keys map to the
- * specified value.
- * Beware that this is a linear search, unlike lookups by key,
- * and that multiple keys can map to the same value and this will
- * find only one of them.
- */
- public int indexOfValue(E value) {
- if (mGarbage) {
- gc();
- }
-
- for (int i = 0; i < mSize; i++)
- if (mValues[i] == value)
- return i;
-
- return -1;
- }
-
- /**
- * Removes all key-value mappings from this SparseArray.
- */
- public void clear() {
- int n = mSize;
- Object[] values = mValues;
-
- for (int i = 0; i < n; i++) {
- values[i] = null;
- }
-
- mSize = 0;
- mGarbage = false;
- }
-
- /**
- * Puts a key/value pair into the array, optimizing for the case where
- * the key is greater than all existing keys in the array.
- */
- public void append(int key, E value) {
- if (mSize != 0 && key <= mKeys[mSize - 1]) {
- put(key, value);
- return;
- }
-
- if (mGarbage && mSize >= mKeys.length) {
- gc();
- }
-
- int pos = mSize;
- if (pos >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(pos + 1);
-
- int[] nkeys = new int[n];
- Object[] nvalues = new Object[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
- }
-
- private static int binarySearch(int[] a, int start, int len, int key) {
- int high = start + len, low = start - 1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
-
- if (a[guess] < key)
- low = guess;
- else
- high = guess;
- }
-
- if (high == start + len)
- return ~(start + len);
- else if (a[high] == key)
- return high;
- else
- return ~high;
- }
-
- private void checkIntegrity() {
- for (int i = 1; i < mSize; i++) {
- if (mKeys[i] <= mKeys[i - 1]) {
- for (int j = 0; j < mSize; j++) {
- Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]);
- }
-
- throw new RuntimeException();
- }
- }
- }
-
- private int[] mKeys;
- private Object[] mValues;
- private int mSize;
-}
diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java
deleted file mode 100644
index f7799de..0000000
--- a/core/java/android/util/SparseBooleanArray.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import com.android.internal.util.ArrayUtils;
-
-/**
- * SparseBooleanArrays map integers to booleans.
- * Unlike a normal array of booleans
- * there can be gaps in the indices. It is intended to be more efficient
- * than using a HashMap to map Integers to Booleans.
- */
-public class SparseBooleanArray {
- /**
- * Creates a new SparseBooleanArray containing no mappings.
- */
- public SparseBooleanArray() {
- this(10);
- }
-
- /**
- * Creates a new SparseBooleanArray containing no mappings that will not
- * require any additional memory allocation to store the specified
- * number of mappings.
- */
- public SparseBooleanArray(int initialCapacity) {
- initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
-
- mKeys = new int[initialCapacity];
- mValues = new boolean[initialCapacity];
- mSize = 0;
- }
-
- /**
- * Gets the boolean mapped from the specified key, or <code>false</code>
- * if no such mapping has been made.
- */
- public boolean get(int key) {
- return get(key, false);
- }
-
- /**
- * Gets the boolean mapped from the specified key, or the specified value
- * if no such mapping has been made.
- */
- public boolean get(int key, boolean valueIfKeyNotFound) {
- int i = binarySearch(mKeys, 0, mSize, key);
-
- if (i < 0) {
- return valueIfKeyNotFound;
- } else {
- return mValues[i];
- }
- }
-
- /**
- * Removes the mapping from the specified key, if there was any.
- */
- public void delete(int key) {
- int i = binarySearch(mKeys, 0, mSize, key);
-
- if (i >= 0) {
- System.arraycopy(mKeys, i + 1, mKeys, i, mSize - (i + 1));
- System.arraycopy(mValues, i + 1, mValues, i, mSize - (i + 1));
- mSize--;
- }
- }
-
- /**
- * Adds a mapping from the specified key to the specified value,
- * replacing the previous mapping from the specified key if there
- * was one.
- */
- public void put(int key, boolean value) {
- int i = binarySearch(mKeys, 0, mSize, key);
-
- if (i >= 0) {
- mValues[i] = value;
- } else {
- i = ~i;
-
- if (mSize >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(mSize + 1);
-
- int[] nkeys = new int[n];
- boolean[] nvalues = new boolean[n];
-
- // Log.e("SparseBooleanArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- if (mSize - i != 0) {
- // Log.e("SparseBooleanArray", "move " + (mSize - i));
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
- mSize++;
- }
- }
-
- /**
- * Returns the number of key-value mappings that this SparseBooleanArray
- * currently stores.
- */
- public int size() {
- return mSize;
- }
-
- /**
- * Given an index in the range <code>0...size()-1</code>, returns
- * the key from the <code>index</code>th key-value mapping that this
- * SparseBooleanArray stores.
- */
- public int keyAt(int index) {
- return mKeys[index];
- }
-
- /**
- * Given an index in the range <code>0...size()-1</code>, returns
- * the value from the <code>index</code>th key-value mapping that this
- * SparseBooleanArray stores.
- */
- public boolean valueAt(int index) {
- return mValues[index];
- }
-
- /**
- * Returns the index for which {@link #keyAt} would return the
- * specified key, or a negative number if the specified
- * key is not mapped.
- */
- public int indexOfKey(int key) {
- return binarySearch(mKeys, 0, mSize, key);
- }
-
- /**
- * Returns an index for which {@link #valueAt} would return the
- * specified key, or a negative number if no keys map to the
- * specified value.
- * Beware that this is a linear search, unlike lookups by key,
- * and that multiple keys can map to the same value and this will
- * find only one of them.
- */
- public int indexOfValue(boolean value) {
- for (int i = 0; i < mSize; i++)
- if (mValues[i] == value)
- return i;
-
- return -1;
- }
-
- /**
- * Removes all key-value mappings from this SparseBooleanArray.
- */
- public void clear() {
- mSize = 0;
- }
-
- /**
- * Puts a key/value pair into the array, optimizing for the case where
- * the key is greater than all existing keys in the array.
- */
- public void append(int key, boolean value) {
- if (mSize != 0 && key <= mKeys[mSize - 1]) {
- put(key, value);
- return;
- }
-
- int pos = mSize;
- if (pos >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(pos + 1);
-
- int[] nkeys = new int[n];
- boolean[] nvalues = new boolean[n];
-
- // Log.e("SparseBooleanArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
- }
-
- private static int binarySearch(int[] a, int start, int len, int key) {
- int high = start + len, low = start - 1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
-
- if (a[guess] < key)
- low = guess;
- else
- high = guess;
- }
-
- if (high == start + len)
- return ~(start + len);
- else if (a[high] == key)
- return high;
- else
- return ~high;
- }
-
- private void checkIntegrity() {
- for (int i = 1; i < mSize; i++) {
- if (mKeys[i] <= mKeys[i - 1]) {
- for (int j = 0; j < mSize; j++) {
- Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]);
- }
-
- throw new RuntimeException();
- }
- }
- }
-
- private int[] mKeys;
- private boolean[] mValues;
- private int mSize;
-}
diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java
deleted file mode 100644
index 9ab3b53..0000000
--- a/core/java/android/util/SparseIntArray.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import com.android.internal.util.ArrayUtils;
-
-/**
- * SparseIntArrays map integers to integers. Unlike a normal array of integers,
- * there can be gaps in the indices. It is intended to be more efficient
- * than using a HashMap to map Integers to Integers.
- */
-public class SparseIntArray {
- /**
- * Creates a new SparseIntArray containing no mappings.
- */
- public SparseIntArray() {
- this(10);
- }
-
- /**
- * Creates a new SparseIntArray containing no mappings that will not
- * require any additional memory allocation to store the specified
- * number of mappings.
- */
- public SparseIntArray(int initialCapacity) {
- initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
-
- mKeys = new int[initialCapacity];
- mValues = new int[initialCapacity];
- mSize = 0;
- }
-
- /**
- * Gets the int mapped from the specified key, or <code>0</code>
- * if no such mapping has been made.
- */
- public int get(int key) {
- return get(key, 0);
- }
-
- /**
- * Gets the int mapped from the specified key, or the specified value
- * if no such mapping has been made.
- */
- public int get(int key, int valueIfKeyNotFound) {
- int i = binarySearch(mKeys, 0, mSize, key);
-
- if (i < 0) {
- return valueIfKeyNotFound;
- } else {
- return mValues[i];
- }
- }
-
- /**
- * Removes the mapping from the specified key, if there was any.
- */
- public void delete(int key) {
- int i = binarySearch(mKeys, 0, mSize, key);
-
- if (i >= 0) {
- removeAt(i);
- }
- }
-
- /**
- * Removes the mapping at the given index.
- */
- public void removeAt(int index) {
- System.arraycopy(mKeys, index + 1, mKeys, index, mSize - (index + 1));
- System.arraycopy(mValues, index + 1, mValues, index, mSize - (index + 1));
- mSize--;
- }
-
- /**
- * Adds a mapping from the specified key to the specified value,
- * replacing the previous mapping from the specified key if there
- * was one.
- */
- public void put(int key, int value) {
- int i = binarySearch(mKeys, 0, mSize, key);
-
- if (i >= 0) {
- mValues[i] = value;
- } else {
- i = ~i;
-
- if (mSize >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(mSize + 1);
-
- int[] nkeys = new int[n];
- int[] nvalues = new int[n];
-
- // Log.e("SparseIntArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- if (mSize - i != 0) {
- // Log.e("SparseIntArray", "move " + (mSize - i));
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
- mSize++;
- }
- }
-
- /**
- * Returns the number of key-value mappings that this SparseIntArray
- * currently stores.
- */
- public int size() {
- return mSize;
- }
-
- /**
- * Given an index in the range <code>0...size()-1</code>, returns
- * the key from the <code>index</code>th key-value mapping that this
- * SparseIntArray stores.
- */
- public int keyAt(int index) {
- return mKeys[index];
- }
-
- /**
- * Given an index in the range <code>0...size()-1</code>, returns
- * the value from the <code>index</code>th key-value mapping that this
- * SparseIntArray stores.
- */
- public int valueAt(int index) {
- return mValues[index];
- }
-
- /**
- * Returns the index for which {@link #keyAt} would return the
- * specified key, or a negative number if the specified
- * key is not mapped.
- */
- public int indexOfKey(int key) {
- return binarySearch(mKeys, 0, mSize, key);
- }
-
- /**
- * Returns an index for which {@link #valueAt} would return the
- * specified key, or a negative number if no keys map to the
- * specified value.
- * Beware that this is a linear search, unlike lookups by key,
- * and that multiple keys can map to the same value and this will
- * find only one of them.
- */
- public int indexOfValue(int value) {
- for (int i = 0; i < mSize; i++)
- if (mValues[i] == value)
- return i;
-
- return -1;
- }
-
- /**
- * Removes all key-value mappings from this SparseIntArray.
- */
- public void clear() {
- mSize = 0;
- }
-
- /**
- * Puts a key/value pair into the array, optimizing for the case where
- * the key is greater than all existing keys in the array.
- */
- public void append(int key, int value) {
- if (mSize != 0 && key <= mKeys[mSize - 1]) {
- put(key, value);
- return;
- }
-
- int pos = mSize;
- if (pos >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(pos + 1);
-
- int[] nkeys = new int[n];
- int[] nvalues = new int[n];
-
- // Log.e("SparseIntArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
- }
-
- private static int binarySearch(int[] a, int start, int len, int key) {
- int high = start + len, low = start - 1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
-
- if (a[guess] < key)
- low = guess;
- else
- high = guess;
- }
-
- if (high == start + len)
- return ~(start + len);
- else if (a[high] == key)
- return high;
- else
- return ~high;
- }
-
- private void checkIntegrity() {
- for (int i = 1; i < mSize; i++) {
- if (mKeys[i] <= mKeys[i - 1]) {
- for (int j = 0; j < mSize; j++) {
- Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]);
- }
-
- throw new RuntimeException();
- }
- }
- }
-
- private int[] mKeys;
- private int[] mValues;
- private int mSize;
-}
diff --git a/core/java/android/util/StateSet.java b/core/java/android/util/StateSet.java
deleted file mode 100644
index f3d8159..0000000
--- a/core/java/android/util/StateSet.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import com.android.internal.R;
-
-/**
- * State sets are arrays of positive ints where each element
- * represents the state of a {@link android.view.View} (e.g. focused,
- * selected, visible, etc.). A {@link android.view.View} may be in
- * one or more of those states.
- *
- * A state spec is an array of signed ints where each element
- * represents a required (if positive) or an undesired (if negative)
- * {@link android.view.View} state.
- *
- * Utils dealing with state sets.
- *
- * In theory we could encapsulate the state set and state spec arrays
- * and not have static methods here but there is some concern about
- * performance since these methods are called during view drawing.
- */
-
-public class StateSet {
-
- public static final int[] WILD_CARD = new int[0];
-
- /**
- * Return whether the stateSetOrSpec is matched by all StateSets.
- *
- * @param stateSetOrSpec a state set or state spec.
- */
- public static boolean isWildCard(int[] stateSetOrSpec) {
- return stateSetOrSpec.length == 0 || stateSetOrSpec[0] == 0;
- }
-
- /**
- * Return whether the stateSet matches the desired stateSpec.
- *
- * @param stateSpec an array of required (if positive) or
- * prohibited (if negative) {@link android.view.View} states.
- * @param stateSet an array of {@link android.view.View} states
- */
- public static boolean stateSetMatches(int[] stateSpec, int[] stateSet) {
- if (stateSet == null) {
- return (stateSpec == null || isWildCard(stateSpec));
- }
- int stateSpecSize = stateSpec.length;
- int stateSetSize = stateSet.length;
- for (int i = 0; i < stateSpecSize; i++) {
- int stateSpecState = stateSpec[i];
- if (stateSpecState == 0) {
- // We've reached the end of the cases to match against.
- return true;
- }
- final boolean mustMatch;
- if (stateSpecState > 0) {
- mustMatch = true;
- } else {
- // We use negative values to indicate must-NOT-match states.
- mustMatch = false;
- stateSpecState = -stateSpecState;
- }
- boolean found = false;
- for (int j = 0; j < stateSetSize; j++) {
- final int state = stateSet[j];
- if (state == 0) {
- // We've reached the end of states to match.
- if (mustMatch) {
- // We didn't find this must-match state.
- return false;
- } else {
- // Continue checking other must-not-match states.
- break;
- }
- }
- if (state == stateSpecState) {
- if (mustMatch) {
- found = true;
- // Continue checking other other must-match states.
- break;
- } else {
- // Any match of a must-not-match state returns false.
- return false;
- }
- }
- }
- if (mustMatch && !found) {
- // We've reached the end of states to match and we didn't
- // find a must-match state.
- return false;
- }
- }
- return true;
- }
-
- /**
- * Return whether the state matches the desired stateSpec.
- *
- * @param stateSpec an array of required (if positive) or
- * prohibited (if negative) {@link android.view.View} states.
- * @param state a {@link android.view.View} state
- */
- public static boolean stateSetMatches(int[] stateSpec, int state) {
- int stateSpecSize = stateSpec.length;
- for (int i = 0; i < stateSpecSize; i++) {
- int stateSpecState = stateSpec[i];
- if (stateSpecState == 0) {
- // We've reached the end of the cases to match against.
- return true;
- }
- if (stateSpecState > 0) {
- if (state != stateSpecState) {
- return false;
- }
- } else {
- // We use negative values to indicate must-NOT-match states.
- if (state == -stateSpecState) {
- // We matched a must-not-match case.
- return false;
- }
- }
- }
- return true;
- }
-
- public static int[] trimStateSet(int[] states, int newSize) {
- if (states.length == newSize) {
- return states;
- }
-
- int[] trimmedStates = new int[newSize];
- System.arraycopy(states, 0, trimmedStates, 0, newSize);
- return trimmedStates;
- }
-
- public static String dump(int[] states) {
- StringBuilder sb = new StringBuilder();
-
- int count = states.length;
- for (int i = 0; i < count; i++) {
-
- switch (states[i]) {
- case R.attr.state_window_focused:
- sb.append("W ");
- break;
- case R.attr.state_pressed:
- sb.append("P ");
- break;
- case R.attr.state_selected:
- sb.append("S ");
- break;
- case R.attr.state_focused:
- sb.append("F ");
- break;
- case R.attr.state_enabled:
- sb.append("E ");
- break;
- }
- }
-
- return sb.toString();
- }
-}
diff --git a/core/java/android/util/StringBuilderPrinter.java b/core/java/android/util/StringBuilderPrinter.java
deleted file mode 100644
index d0fc1e7..0000000
--- a/core/java/android/util/StringBuilderPrinter.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-/**
- * Implementation of a {@link android.util.Printer} that sends its output
- * to a {@link StringBuilder}.
- */
-public class StringBuilderPrinter implements Printer {
- private final StringBuilder mBuilder;
-
- /**
- * Create a new Printer that sends to a StringBuilder object.
- *
- * @param builder The StringBuilder where you would like output to go.
- */
- public StringBuilderPrinter(StringBuilder builder) {
- mBuilder = builder;
- }
-
- public void println(String x) {
- mBuilder.append(x);
- int len = x.length();
- if (len <= 0 || x.charAt(len-1) != '\n') {
- mBuilder.append('\n');
- }
- }
-}
diff --git a/core/java/android/util/TimeFormatException.java b/core/java/android/util/TimeFormatException.java
deleted file mode 100644
index d7a898b..0000000
--- a/core/java/android/util/TimeFormatException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-public class TimeFormatException extends RuntimeException
-{
- TimeFormatException(String s)
- {
- super(s);
- }
-}
-
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
deleted file mode 100644
index 0fc70d5..0000000
--- a/core/java/android/util/TimeUtils.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
-
-import org.apache.harmony.luni.internal.util.ZoneInfoDB;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.util.TimeZone;
-import java.util.Date;
-
-import com.android.internal.util.XmlUtils;
-
-/**
- * A class containing utility methods related to time zones.
- */
-public class TimeUtils {
- private static final String TAG = "TimeUtils";
-
- /**
- * Tries to return a time zone that would have had the specified offset
- * and DST value at the specified moment in the specified country.
- * Returns null if no suitable zone could be found.
- */
- public static TimeZone getTimeZone(int offset, boolean dst, long when, String country) {
- if (country == null) {
- return null;
- }
-
- TimeZone best = null;
-
- Resources r = Resources.getSystem();
- XmlResourceParser parser = r.getXml(com.android.internal.R.xml.time_zones_by_country);
- Date d = new Date(when);
-
- TimeZone current = TimeZone.getDefault();
- String currentName = current.getID();
- int currentOffset = current.getOffset(when);
- boolean currentDst = current.inDaylightTime(d);
-
- try {
- XmlUtils.beginDocument(parser, "timezones");
-
- while (true) {
- XmlUtils.nextElement(parser);
-
- String element = parser.getName();
- if (element == null || !(element.equals("timezone"))) {
- break;
- }
-
- String code = parser.getAttributeValue(null, "code");
-
- if (country.equals(code)) {
- if (parser.next() == XmlPullParser.TEXT) {
- String maybe = parser.getText();
-
- // If the current time zone is from the right country
- // and meets the other known properties, keep it
- // instead of changing to another one.
-
- if (maybe.equals(currentName)) {
- if (currentOffset == offset && currentDst == dst) {
- return current;
- }
- }
-
- // Otherwise, take the first zone from the right
- // country that has the correct current offset and DST.
- // (Keep iterating instead of returning in case we
- // haven't encountered the current time zone yet.)
-
- if (best == null) {
- TimeZone tz = TimeZone.getTimeZone(maybe);
-
- if (tz.getOffset(when) == offset &&
- tz.inDaylightTime(d) == dst) {
- best = tz;
- }
- }
- }
- }
- }
- } catch (XmlPullParserException e) {
- Log.e(TAG, "Got exception while getting preferred time zone.", e);
- } catch (IOException e) {
- Log.e(TAG, "Got exception while getting preferred time zone.", e);
- } finally {
- parser.close();
- }
-
- return best;
- }
-
- /**
- * Returns a String indicating the version of the time zone database currently
- * in use. The format of the string is dependent on the underlying time zone
- * database implementation, but will typically contain the year in which the database
- * was updated plus a letter from a to z indicating changes made within that year.
- *
- * <p>Time zone database updates should be expected to occur periodically due to
- * political and legal changes that cannot be anticipated in advance. Therefore,
- * when computing the UTC time for a future event, applications should be aware that
- * the results may differ following a time zone database update. This method allows
- * applications to detect that a database change has occurred, and to recalculate any
- * cached times accordingly.
- *
- * <p>The time zone database may be assumed to change only when the device runtime
- * is restarted. Therefore, it is not necessary to re-query the database version
- * during the lifetime of an activity.
- */
- public static String getTimeZoneDatabaseVersion() {
- return ZoneInfoDB.getVersion();
- }
-}
diff --git a/core/java/android/util/TimingLogger.java b/core/java/android/util/TimingLogger.java
deleted file mode 100644
index 0f39c97..0000000
--- a/core/java/android/util/TimingLogger.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import java.util.ArrayList;
-
-import android.os.SystemClock;
-
-/**
- * A utility class to help log timings splits throughout a method call.
- * Typical usage is:
- *
- * TimingLogger timings = new TimingLogger(TAG, "methodA");
- * ... do some work A ...
- * timings.addSplit("work A");
- * ... do some work B ...
- * timings.addSplit("work B");
- * ... do some work C ...
- * timings.addSplit("work C");
- * timings.dumpToLog();
- *
- * The dumpToLog call would add the following to the log:
- *
- * D/TAG ( 3459): methodA: begin
- * D/TAG ( 3459): methodA: 9 ms, work A
- * D/TAG ( 3459): methodA: 1 ms, work B
- * D/TAG ( 3459): methodA: 6 ms, work C
- * D/TAG ( 3459): methodA: end, 16 ms
- */
-public class TimingLogger {
-
- /**
- * The Log tag to use for checking Log.isLoggable and for
- * logging the timings.
- */
- private String mTag;
-
- /** A label to be included in every log. */
- private String mLabel;
-
- /** Used to track whether Log.isLoggable was enabled at reset time. */
- private boolean mDisabled;
-
- /** Stores the time of each split. */
- ArrayList<Long> mSplits;
-
- /** Stores the labels for each split. */
- ArrayList<String> mSplitLabels;
-
- /**
- * Create and initialize a TimingLogger object that will log using
- * the specific tag. If the Log.isLoggable is not enabled to at
- * least the Log.VERBOSE level for that tag at creation time then
- * the addSplit and dumpToLog call will do nothing.
- * @param tag the log tag to use while logging the timings
- * @param label a string to be displayed with each log
- */
- public TimingLogger(String tag, String label) {
- reset(tag, label);
- }
-
- /**
- * Clear and initialize a TimingLogger object that will log using
- * the specific tag. If the Log.isLoggable is not enabled to at
- * least the Log.VERBOSE level for that tag at creation time then
- * the addSplit and dumpToLog call will do nothing.
- * @param tag the log tag to use while logging the timings
- * @param label a string to be displayed with each log
- */
- public void reset(String tag, String label) {
- mTag = tag;
- mLabel = label;
- reset();
- }
-
- /**
- * Clear and initialize a TimingLogger object that will log using
- * the tag and label that was specified previously, either via
- * the constructor or a call to reset(tag, label). If the
- * Log.isLoggable is not enabled to at least the Log.VERBOSE
- * level for that tag at creation time then the addSplit and
- * dumpToLog call will do nothing.
- */
- public void reset() {
- mDisabled = !Log.isLoggable(mTag, Log.VERBOSE);
- if (mDisabled) return;
- if (mSplits == null) {
- mSplits = new ArrayList<Long>();
- mSplitLabels = new ArrayList<String>();
- } else {
- mSplits.clear();
- mSplitLabels.clear();
- }
- addSplit(null);
- }
-
- /**
- * Add a split for the current time, labeled with splitLabel. If
- * Log.isLoggable was not enabled to at least the Log.VERBOSE for
- * the specified tag at construction or reset() time then this
- * call does nothing.
- * @param splitLabel a label to associate with this split.
- */
- public void addSplit(String splitLabel) {
- if (mDisabled) return;
- long now = SystemClock.elapsedRealtime();
- mSplits.add(now);
- mSplitLabels.add(splitLabel);
- }
-
- /**
- * Dumps the timings to the log using Log.d(). If Log.isLoggable was
- * not enabled to at least the Log.VERBOSE for the specified tag at
- * construction or reset() time then this call does nothing.
- */
- public void dumpToLog() {
- if (mDisabled) return;
- Log.d(mTag, mLabel + ": begin");
- final long first = mSplits.get(0);
- long now = first;
- for (int i = 1; i < mSplits.size(); i++) {
- now = mSplits.get(i);
- final String splitLabel = mSplitLabels.get(i);
- final long prev = mSplits.get(i - 1);
-
- Log.d(mTag, mLabel + ": " + (now - prev) + " ms, " + splitLabel);
- }
- Log.d(mTag, mLabel + ": end, " + (now - first) + " ms");
- }
-}
diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java
deleted file mode 100644
index d4ba9e2..0000000
--- a/core/java/android/util/TypedValue.java
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-/**
- * Container for a dynamically typed data value. Primarily used with
- * {@link android.content.res.Resources} for holding resource values.
- */
-public class TypedValue {
- /** The value contains no data. */
- public static final int TYPE_NULL = 0x00;
-
- /** The <var>data</var> field holds a resource identifier. */
- public static final int TYPE_REFERENCE = 0x01;
- /** The <var>data</var> field holds an attribute resource
- * identifier (referencing an attribute in the current theme
- * style, not a resource entry). */
- public static final int TYPE_ATTRIBUTE = 0x02;
- /** The <var>string</var> field holds string data. In addition, if
- * <var>data</var> is non-zero then it is the string block
- * index of the string and <var>assetCookie</var> is the set of
- * assets the string came from. */
- public static final int TYPE_STRING = 0x03;
- /** The <var>data</var> field holds an IEEE 754 floating point number. */
- public static final int TYPE_FLOAT = 0x04;
- /** The <var>data</var> field holds a complex number encoding a
- * dimension value. */
- public static final int TYPE_DIMENSION = 0x05;
- /** The <var>data</var> field holds a complex number encoding a fraction
- * of a container. */
- public static final int TYPE_FRACTION = 0x06;
-
- /** Identifies the start of plain integer values. Any type value
- * from this to {@link #TYPE_LAST_INT} means the
- * <var>data</var> field holds a generic integer value. */
- public static final int TYPE_FIRST_INT = 0x10;
-
- /** The <var>data</var> field holds a number that was
- * originally specified in decimal. */
- public static final int TYPE_INT_DEC = 0x10;
- /** The <var>data</var> field holds a number that was
- * originally specified in hexadecimal (0xn). */
- public static final int TYPE_INT_HEX = 0x11;
- /** The <var>data</var> field holds 0 or 1 that was originally
- * specified as "false" or "true". */
- public static final int TYPE_INT_BOOLEAN = 0x12;
-
- /** Identifies the start of integer values that were specified as
- * color constants (starting with '#'). */
- public static final int TYPE_FIRST_COLOR_INT = 0x1c;
-
- /** The <var>data</var> field holds a color that was originally
- * specified as #aarrggbb. */
- public static final int TYPE_INT_COLOR_ARGB8 = 0x1c;
- /** The <var>data</var> field holds a color that was originally
- * specified as #rrggbb. */
- public static final int TYPE_INT_COLOR_RGB8 = 0x1d;
- /** The <var>data</var> field holds a color that was originally
- * specified as #argb. */
- public static final int TYPE_INT_COLOR_ARGB4 = 0x1e;
- /** The <var>data</var> field holds a color that was originally
- * specified as #rgb. */
- public static final int TYPE_INT_COLOR_RGB4 = 0x1f;
-
- /** Identifies the end of integer values that were specified as color
- * constants. */
- public static final int TYPE_LAST_COLOR_INT = 0x1f;
-
- /** Identifies the end of plain integer values. */
- public static final int TYPE_LAST_INT = 0x1f;
-
- /* ------------------------------------------------------------ */
-
- /** Complex data: bit location of unit information. */
- public static final int COMPLEX_UNIT_SHIFT = 0;
- /** Complex data: mask to extract unit information (after shifting by
- * {@link #COMPLEX_UNIT_SHIFT}). This gives us 16 possible types, as
- * defined below. */
- public static final int COMPLEX_UNIT_MASK = 0xf;
-
- /** {@link #TYPE_DIMENSION} complex unit: Value is raw pixels. */
- public static final int COMPLEX_UNIT_PX = 0;
- /** {@link #TYPE_DIMENSION} complex unit: Value is Device Independent
- * Pixels. */
- public static final int COMPLEX_UNIT_DIP = 1;
- /** {@link #TYPE_DIMENSION} complex unit: Value is a scaled pixel. */
- public static final int COMPLEX_UNIT_SP = 2;
- /** {@link #TYPE_DIMENSION} complex unit: Value is in points. */
- public static final int COMPLEX_UNIT_PT = 3;
- /** {@link #TYPE_DIMENSION} complex unit: Value is in inches. */
- public static final int COMPLEX_UNIT_IN = 4;
- /** {@link #TYPE_DIMENSION} complex unit: Value is in millimeters. */
- public static final int COMPLEX_UNIT_MM = 5;
-
- /** {@link #TYPE_FRACTION} complex unit: A basic fraction of the overall
- * size. */
- public static final int COMPLEX_UNIT_FRACTION = 0;
- /** {@link #TYPE_FRACTION} complex unit: A fraction of the parent size. */
- public static final int COMPLEX_UNIT_FRACTION_PARENT = 1;
-
- /** Complex data: where the radix information is, telling where the decimal
- * place appears in the mantissa. */
- public static final int COMPLEX_RADIX_SHIFT = 4;
- /** Complex data: mask to extract radix information (after shifting by
- * {@link #COMPLEX_RADIX_SHIFT}). This give us 4 possible fixed point
- * representations as defined below. */
- public static final int COMPLEX_RADIX_MASK = 0x3;
-
- /** Complex data: the mantissa is an integral number -- i.e., 0xnnnnnn.0 */
- public static final int COMPLEX_RADIX_23p0 = 0;
- /** Complex data: the mantissa magnitude is 16 bits -- i.e, 0xnnnn.nn */
- public static final int COMPLEX_RADIX_16p7 = 1;
- /** Complex data: the mantissa magnitude is 8 bits -- i.e, 0xnn.nnnn */
- public static final int COMPLEX_RADIX_8p15 = 2;
- /** Complex data: the mantissa magnitude is 0 bits -- i.e, 0x0.nnnnnn */
- public static final int COMPLEX_RADIX_0p23 = 3;
-
- /** Complex data: bit location of mantissa information. */
- public static final int COMPLEX_MANTISSA_SHIFT = 8;
- /** Complex data: mask to extract mantissa information (after shifting by
- * {@link #COMPLEX_MANTISSA_SHIFT}). This gives us 23 bits of precision;
- * the top bit is the sign. */
- public static final int COMPLEX_MANTISSA_MASK = 0xffffff;
-
- /* ------------------------------------------------------------ */
-
- /**
- * If {@link #density} is equal to this value, then the density should be
- * treated as the system's default density value: {@link DisplayMetrics#DEFAULT_DENSITY}.
- *
- * @hide Pending API council approval
- */
- public static final int DENSITY_DEFAULT = 0;
-
- /* ------------------------------------------------------------ */
-
- /** The type held by this value, as defined by the constants here.
- * This tells you how to interpret the other fields in the object. */
- public int type;
-
- /** If the value holds a string, this is it. */
- public CharSequence string;
-
- /** Basic data in the value, interpreted according to {@link #type} */
- public int data;
-
- /** Additional information about where the value came from; only
- * set for strings. */
- public int assetCookie;
-
- /** If Value came from a resource, this holds the corresponding resource id. */
- public int resourceId;
-
- /** If Value came from a resource, these are the configurations for which
- * its contents can change. */
- public int changingConfigurations = -1;
-
- /**
- * If the Value came from a resource, this holds the corresponding pixel density.
- *
- * @hide Pending API council approval
- * */
- public int density;
-
- /* ------------------------------------------------------------ */
-
- /** Return the data for this value as a float. Only use for values
- * whose type is {@link #TYPE_FLOAT}. */
- public final float getFloat() {
- return Float.intBitsToFloat(data);
- }
-
- private static final float MANTISSA_MULT =
- 1.0f / (1<<TypedValue.COMPLEX_MANTISSA_SHIFT);
- private static final float[] RADIX_MULTS = new float[] {
- 1.0f*MANTISSA_MULT, 1.0f/(1<<7)*MANTISSA_MULT,
- 1.0f/(1<<15)*MANTISSA_MULT, 1.0f/(1<<23)*MANTISSA_MULT
- };
-
- /**
- * Retrieve the base value from a complex data integer. This uses the
- * {@link #COMPLEX_MANTISSA_MASK} and {@link #COMPLEX_RADIX_MASK} fields of
- * the data to compute a floating point representation of the number they
- * describe. The units are ignored.
- *
- * @param complex A complex data value.
- *
- * @return A floating point value corresponding to the complex data.
- */
- public static float complexToFloat(int complex)
- {
- return (complex&(TypedValue.COMPLEX_MANTISSA_MASK
- <<TypedValue.COMPLEX_MANTISSA_SHIFT))
- * RADIX_MULTS[(complex>>TypedValue.COMPLEX_RADIX_SHIFT)
- & TypedValue.COMPLEX_RADIX_MASK];
- }
-
- /**
- * Converts a complex data value holding a dimension to its final floating
- * point value. The given <var>data</var> must be structured as a
- * {@link #TYPE_DIMENSION}.
- *
- * @param data A complex data value holding a unit, magnitude, and
- * mantissa.
- * @param metrics Current display metrics to use in the conversion --
- * supplies display density and scaling information.
- *
- * @return The complex floating point value multiplied by the appropriate
- * metrics depending on its unit.
- */
- public static float complexToDimension(int data, DisplayMetrics metrics)
- {
- return applyDimension(
- (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK,
- complexToFloat(data),
- metrics);
- }
-
- /**
- * Converts a complex data value holding a dimension to its final value
- * as an integer pixel offset. This is the same as
- * {@link #complexToDimension}, except the raw floating point value is
- * truncated to an integer (pixel) value.
- * The given <var>data</var> must be structured as a
- * {@link #TYPE_DIMENSION}.
- *
- * @param data A complex data value holding a unit, magnitude, and
- * mantissa.
- * @param metrics Current display metrics to use in the conversion --
- * supplies display density and scaling information.
- *
- * @return The number of pixels specified by the data and its desired
- * multiplier and units.
- */
- public static int complexToDimensionPixelOffset(int data,
- DisplayMetrics metrics)
- {
- return (int)applyDimension(
- (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK,
- complexToFloat(data),
- metrics);
- }
-
- /**
- * Converts a complex data value holding a dimension to its final value
- * as an integer pixel size. This is the same as
- * {@link #complexToDimension}, except the raw floating point value is
- * converted to an integer (pixel) value for use as a size. A size
- * conversion involves rounding the base value, and ensuring that a
- * non-zero base value is at least one pixel in size.
- * The given <var>data</var> must be structured as a
- * {@link #TYPE_DIMENSION}.
- *
- * @param data A complex data value holding a unit, magnitude, and
- * mantissa.
- * @param metrics Current display metrics to use in the conversion --
- * supplies display density and scaling information.
- *
- * @return The number of pixels specified by the data and its desired
- * multiplier and units.
- */
- public static int complexToDimensionPixelSize(int data,
- DisplayMetrics metrics)
- {
- final float value = complexToFloat(data);
- final float f = applyDimension(
- (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK,
- value,
- metrics);
- final int res = (int)(f+0.5f);
- if (res != 0) return res;
- if (value == 0) return 0;
- if (value > 0) return 1;
- return -1;
- }
-
- public static float complexToDimensionNoisy(int data, DisplayMetrics metrics)
- {
- float res = complexToDimension(data, metrics);
- System.out.println(
- "Dimension (0x" + ((data>>TypedValue.COMPLEX_MANTISSA_SHIFT)
- & TypedValue.COMPLEX_MANTISSA_MASK)
- + "*" + (RADIX_MULTS[(data>>TypedValue.COMPLEX_RADIX_SHIFT)
- & TypedValue.COMPLEX_RADIX_MASK] / MANTISSA_MULT)
- + ")" + DIMENSION_UNIT_STRS[(data>>COMPLEX_UNIT_SHIFT)
- & COMPLEX_UNIT_MASK]
- + " = " + res);
- return res;
- }
-
- /**
- * Converts an unpacked complex data value holding a dimension to its final floating
- * point value. The two parameters <var>unit</var> and <var>value</var>
- * are as in {@link #TYPE_DIMENSION}.
- *
- * @param unit The unit to convert from.
- * @param value The value to apply the unit to.
- * @param metrics Current display metrics to use in the conversion --
- * supplies display density and scaling information.
- *
- * @return The complex floating point value multiplied by the appropriate
- * metrics depending on its unit.
- */
- public static float applyDimension(int unit, float value,
- DisplayMetrics metrics)
- {
- switch (unit) {
- case COMPLEX_UNIT_PX:
- return value;
- case COMPLEX_UNIT_DIP:
- return value * metrics.density;
- case COMPLEX_UNIT_SP:
- return value * metrics.scaledDensity;
- case COMPLEX_UNIT_PT:
- return value * metrics.xdpi * (1.0f/72);
- case COMPLEX_UNIT_IN:
- return value * metrics.xdpi;
- case COMPLEX_UNIT_MM:
- return value * metrics.xdpi * (1.0f/25.4f);
- }
- return 0;
- }
-
- /**
- * Return the data for this value as a dimension. Only use for values
- * whose type is {@link #TYPE_DIMENSION}.
- *
- * @param metrics Current display metrics to use in the conversion --
- * supplies display density and scaling information.
- *
- * @return The complex floating point value multiplied by the appropriate
- * metrics depending on its unit.
- */
- public float getDimension(DisplayMetrics metrics)
- {
- return complexToDimension(data, metrics);
- }
-
- /**
- * Converts a complex data value holding a fraction to its final floating
- * point value. The given <var>data</var> must be structured as a
- * {@link #TYPE_FRACTION}.
- *
- * @param data A complex data value holding a unit, magnitude, and
- * mantissa.
- * @param base The base value of this fraction. In other words, a
- * standard fraction is multiplied by this value.
- * @param pbase The parent base value of this fraction. In other
- * words, a parent fraction (nn%p) is multiplied by this
- * value.
- *
- * @return The complex floating point value multiplied by the appropriate
- * base value depending on its unit.
- */
- public static float complexToFraction(int data, float base, float pbase)
- {
- switch ((data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK) {
- case COMPLEX_UNIT_FRACTION:
- return complexToFloat(data) * base;
- case COMPLEX_UNIT_FRACTION_PARENT:
- return complexToFloat(data) * pbase;
- }
- return 0;
- }
-
- /**
- * Return the data for this value as a fraction. Only use for values whose
- * type is {@link #TYPE_FRACTION}.
- *
- * @param base The base value of this fraction. In other words, a
- * standard fraction is multiplied by this value.
- * @param pbase The parent base value of this fraction. In other
- * words, a parent fraction (nn%p) is multiplied by this
- * value.
- *
- * @return The complex floating point value multiplied by the appropriate
- * base value depending on its unit.
- */
- public float getFraction(float base, float pbase)
- {
- return complexToFraction(data, base, pbase);
- }
-
- /**
- * Regardless of the actual type of the value, try to convert it to a
- * string value. For example, a color type will be converted to a
- * string of the form #aarrggbb.
- *
- * @return CharSequence The coerced string value. If the value is
- * null or the type is not known, null is returned.
- */
- public final CharSequence coerceToString()
- {
- int t = type;
- if (t == TYPE_STRING) {
- return string;
- }
- return coerceToString(t, data);
- }
-
- private static final String[] DIMENSION_UNIT_STRS = new String[] {
- "px", "dip", "sp", "pt", "in", "mm"
- };
- private static final String[] FRACTION_UNIT_STRS = new String[] {
- "%", "%p"
- };
-
- /**
- * Perform type conversion as per {@link #coerceToString()} on an
- * explicitly supplied type and data.
- *
- * @param type The data type identifier.
- * @param data The data value.
- *
- * @return String The coerced string value. If the value is
- * null or the type is not known, null is returned.
- */
- public static final String coerceToString(int type, int data)
- {
- switch (type) {
- case TYPE_NULL:
- return null;
- case TYPE_REFERENCE:
- return "@" + data;
- case TYPE_ATTRIBUTE:
- return "?" + data;
- case TYPE_FLOAT:
- return Float.toString(Float.intBitsToFloat(data));
- case TYPE_DIMENSION:
- return Float.toString(complexToFloat(data)) + DIMENSION_UNIT_STRS[
- (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK];
- case TYPE_FRACTION:
- return Float.toString(complexToFloat(data)*100) + FRACTION_UNIT_STRS[
- (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK];
- case TYPE_INT_HEX:
- return "0x" + Integer.toHexString(data);
- case TYPE_INT_BOOLEAN:
- return data != 0 ? "true" : "false";
- }
-
- if (type >= TYPE_FIRST_COLOR_INT && type <= TYPE_LAST_COLOR_INT) {
- return "#" + Integer.toHexString(data);
- } else if (type >= TYPE_FIRST_INT && type <= TYPE_LAST_INT) {
- return Integer.toString(data);
- }
-
- return null;
- }
-
- public void setTo(TypedValue other)
- {
- type = other.type;
- string = other.string;
- data = other.data;
- assetCookie = other.assetCookie;
- resourceId = other.resourceId;
- density = other.density;
- }
-
- public String toString()
- {
- StringBuilder sb = new StringBuilder();
- sb.append("TypedValue{t=0x").append(Integer.toHexString(type));
- sb.append("/d=0x").append(Integer.toHexString(data));
- if (type == TYPE_STRING) {
- sb.append(" \"").append(string != null ? string : "<null>").append("\"");
- }
- if (assetCookie != 0) {
- sb.append(" a=").append(assetCookie);
- }
- if (resourceId != 0) {
- sb.append(" r=0x").append(Integer.toHexString(resourceId));
- }
- sb.append("}");
- return sb.toString();
- }
-};
-
diff --git a/core/java/android/util/Xml.java b/core/java/android/util/Xml.java
deleted file mode 100644
index a2b69a5..0000000
--- a/core/java/android/util/Xml.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlSerializer;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.UnsupportedEncodingException;
-
-import org.apache.harmony.xml.ExpatPullParser;
-import org.apache.harmony.xml.ExpatReader;
-
-/**
- * XML utility methods.
- */
-public class Xml {
-
- /**
- * {@link org.xmlpull.v1.XmlPullParser} "relaxed" feature name.
- *
- * @see <a href="http://xmlpull.org/v1/doc/features.html#relaxed">
- * specification</a>
- */
- public static String FEATURE_RELAXED = ExpatPullParser.FEATURE_RELAXED;
-
- /**
- * Parses the given xml string and fires events on the given SAX handler.
- */
- public static void parse(String xml, ContentHandler contentHandler)
- throws SAXException {
- try {
- XMLReader reader = new ExpatReader();
- reader.setContentHandler(contentHandler);
- reader.parse(new InputSource(new StringReader(xml)));
- }
- catch (IOException e) {
- throw new AssertionError(e);
- }
- }
-
- /**
- * Parses xml from the given reader and fires events on the given SAX
- * handler.
- */
- public static void parse(Reader in, ContentHandler contentHandler)
- throws IOException, SAXException {
- XMLReader reader = new ExpatReader();
- reader.setContentHandler(contentHandler);
- reader.parse(new InputSource(in));
- }
-
- /**
- * Parses xml from the given input stream and fires events on the given SAX
- * handler.
- */
- public static void parse(InputStream in, Encoding encoding,
- ContentHandler contentHandler) throws IOException, SAXException {
- try {
- XMLReader reader = new ExpatReader();
- reader.setContentHandler(contentHandler);
- InputSource source = new InputSource(in);
- source.setEncoding(encoding.expatName);
- reader.parse(source);
- } catch (IOException e) {
- throw new AssertionError(e);
- }
- }
-
- /**
- * Creates a new pull parser with namespace support.
- *
- * <p><b>Note:</b> This is actually slower than the SAX parser, and it's not
- * fully implemented. If you need a fast, mostly implemented pull parser,
- * use this. If you need a complete implementation, use KXML.
- */
- public static XmlPullParser newPullParser() {
- ExpatPullParser parser = new ExpatPullParser();
- parser.setNamespaceProcessingEnabled(true);
- return parser;
- }
-
- /**
- * Creates a new xml serializer.
- */
- public static XmlSerializer newSerializer() {
- try {
- return XmlSerializerFactory.instance.newSerializer();
- } catch (XmlPullParserException e) {
- throw new AssertionError(e);
- }
- }
-
- /** Factory for xml serializers. Initialized on demand. */
- static class XmlSerializerFactory {
- static final String TYPE
- = "org.kxml2.io.KXmlParser,org.kxml2.io.KXmlSerializer";
- static final XmlPullParserFactory instance;
- static {
- try {
- instance = XmlPullParserFactory.newInstance(TYPE, null);
- } catch (XmlPullParserException e) {
- throw new AssertionError(e);
- }
- }
- }
-
- /**
- * Supported character encodings.
- */
- public enum Encoding {
-
- US_ASCII("US-ASCII"),
- UTF_8("UTF-8"),
- UTF_16("UTF-16"),
- ISO_8859_1("ISO-8859-1");
-
- final String expatName;
-
- Encoding(String expatName) {
- this.expatName = expatName;
- }
- }
-
- /**
- * Finds an encoding by name. Returns UTF-8 if you pass {@code null}.
- */
- public static Encoding findEncodingByName(String encodingName)
- throws UnsupportedEncodingException {
- if (encodingName == null) {
- return Encoding.UTF_8;
- }
-
- for (Encoding encoding : Encoding.values()) {
- if (encoding.expatName.equalsIgnoreCase(encodingName))
- return encoding;
- }
- throw new UnsupportedEncodingException(encodingName);
- }
-
- /**
- * Return an AttributeSet interface for use with the given XmlPullParser.
- * If the given parser itself implements AttributeSet, that implementation
- * is simply returned. Otherwise a wrapper class is
- * instantiated on top of the XmlPullParser, as a proxy for retrieving its
- * attributes, and returned to you.
- *
- * @param parser The existing parser for which you would like an
- * AttributeSet.
- *
- * @return An AttributeSet you can use to retrieve the
- * attribute values at each of the tags as the parser moves
- * through its XML document.
- *
- * @see AttributeSet
- */
- public static AttributeSet asAttributeSet(XmlPullParser parser) {
- return (parser instanceof AttributeSet)
- ? (AttributeSet) parser
- : new XmlPullAttributes(parser);
- }
-}
diff --git a/core/java/android/util/XmlPullAttributes.java b/core/java/android/util/XmlPullAttributes.java
deleted file mode 100644
index 12d6dd9..0000000
--- a/core/java/android/util/XmlPullAttributes.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.util.AttributeSet;
-import com.android.internal.util.XmlUtils;
-
-/**
- * Provides an implementation of AttributeSet on top of an XmlPullParser.
- */
-class XmlPullAttributes implements AttributeSet {
- public XmlPullAttributes(XmlPullParser parser) {
- mParser = parser;
- }
-
- public int getAttributeCount() {
- return mParser.getAttributeCount();
- }
-
- public String getAttributeName(int index) {
- return mParser.getAttributeName(index);
- }
-
- public String getAttributeValue(int index) {
- return mParser.getAttributeValue(index);
- }
-
- public String getAttributeValue(String namespace, String name) {
- return mParser.getAttributeValue(namespace, name);
- }
-
- public String getPositionDescription() {
- return mParser.getPositionDescription();
- }
-
- public int getAttributeNameResource(int index) {
- return 0;
- }
-
- public int getAttributeListValue(String namespace, String attribute,
- String[] options, int defaultValue) {
- return XmlUtils.convertValueToList(
- getAttributeValue(namespace, attribute), options, defaultValue);
- }
-
- public boolean getAttributeBooleanValue(String namespace, String attribute,
- boolean defaultValue) {
- return XmlUtils.convertValueToBoolean(
- getAttributeValue(namespace, attribute), defaultValue);
- }
-
- public int getAttributeResourceValue(String namespace, String attribute,
- int defaultValue) {
- return XmlUtils.convertValueToInt(
- getAttributeValue(namespace, attribute), defaultValue);
- }
-
- public int getAttributeIntValue(String namespace, String attribute,
- int defaultValue) {
- return XmlUtils.convertValueToInt(
- getAttributeValue(namespace, attribute), defaultValue);
- }
-
- public int getAttributeUnsignedIntValue(String namespace, String attribute,
- int defaultValue) {
- return XmlUtils.convertValueToUnsignedInt(
- getAttributeValue(namespace, attribute), defaultValue);
- }
-
- public float getAttributeFloatValue(String namespace, String attribute,
- float defaultValue) {
- String s = getAttributeValue(namespace, attribute);
- if (s != null) {
- return Float.parseFloat(s);
- }
- return defaultValue;
- }
-
- public int getAttributeListValue(int index,
- String[] options, int defaultValue) {
- return XmlUtils.convertValueToList(
- getAttributeValue(index), options, defaultValue);
- }
-
- public boolean getAttributeBooleanValue(int index, boolean defaultValue) {
- return XmlUtils.convertValueToBoolean(
- getAttributeValue(index), defaultValue);
- }
-
- public int getAttributeResourceValue(int index, int defaultValue) {
- return XmlUtils.convertValueToInt(
- getAttributeValue(index), defaultValue);
- }
-
- public int getAttributeIntValue(int index, int defaultValue) {
- return XmlUtils.convertValueToInt(
- getAttributeValue(index), defaultValue);
- }
-
- public int getAttributeUnsignedIntValue(int index, int defaultValue) {
- return XmlUtils.convertValueToUnsignedInt(
- getAttributeValue(index), defaultValue);
- }
-
- public float getAttributeFloatValue(int index, float defaultValue) {
- String s = getAttributeValue(index);
- if (s != null) {
- return Float.parseFloat(s);
- }
- return defaultValue;
- }
-
- public String getIdAttribute() {
- return getAttributeValue(null, "id");
- }
-
- public String getClassAttribute() {
- return getAttributeValue(null, "class");
- }
-
- public int getIdAttributeResourceValue(int defaultValue) {
- return getAttributeResourceValue(null, "id", defaultValue);
- }
-
- public int getStyleAttribute() {
- return getAttributeResourceValue(null, "style", 0);
- }
-
- private XmlPullParser mParser;
-}
diff --git a/core/java/android/util/package.html b/core/java/android/util/package.html
deleted file mode 100644
index d918d69..0000000
--- a/core/java/android/util/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<HTML>
-<BODY>
-Provides common utility methods such as date/time manipulation, base64 encoders
-and decoders, string and number conversion methods, and XML utilities.
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/core/java/android/view/AbsSavedState.java b/core/java/android/view/AbsSavedState.java
deleted file mode 100644
index 840d7c1..0000000
--- a/core/java/android/view/AbsSavedState.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * A {@link Parcelable} implementation that should be used by inheritance
- * hierarchies to ensure the state of all classes along the chain is saved.
- */
-public abstract class AbsSavedState implements Parcelable {
- public static final AbsSavedState EMPTY_STATE = new AbsSavedState() {};
-
- private final Parcelable mSuperState;
-
- /**
- * Constructor used to make the EMPTY_STATE singleton
- */
- private AbsSavedState() {
- mSuperState = null;
- }
-
- /**
- * Constructor called by derived classes when creating their SavedState objects
- *
- * @param superState The state of the superclass of this view
- */
- protected AbsSavedState(Parcelable superState) {
- if (superState == null) {
- throw new IllegalArgumentException("superState must not be null");
- }
- mSuperState = superState != EMPTY_STATE ? superState : null;
- }
-
- /**
- * Constructor used when reading from a parcel. Reads the state of the superclass.
- *
- * @param source
- */
- protected AbsSavedState(Parcel source) {
- // FIXME need class loader
- Parcelable superState = (Parcelable) source.readParcelable(null);
-
- mSuperState = superState != null ? superState : EMPTY_STATE;
- }
-
- final public Parcelable getSuperState() {
- return mSuperState;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeParcelable(mSuperState, flags);
- }
-
- public static final Parcelable.Creator<AbsSavedState> CREATOR
- = new Parcelable.Creator<AbsSavedState>() {
-
- public AbsSavedState createFromParcel(Parcel in) {
- Parcelable superState = (Parcelable) in.readParcelable(null);
- if (superState != null) {
- throw new IllegalStateException("superState must be null");
- }
- return EMPTY_STATE;
- }
-
- public AbsSavedState[] newArray(int size) {
- return new AbsSavedState[size];
- }
- };
-}
diff --git a/core/java/android/view/ContextMenu.java b/core/java/android/view/ContextMenu.java
deleted file mode 100644
index dd1d7db..0000000
--- a/core/java/android/view/ContextMenu.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.app.Activity;
-import android.graphics.drawable.Drawable;
-import android.widget.AdapterView;
-
-/**
- * Extension of {@link Menu} for context menus providing functionality to modify
- * the header of the context menu.
- * <p>
- * Context menus do not support item shortcuts and item icons.
- * <p>
- * To show a context menu on long click, most clients will want to call
- * {@link Activity#registerForContextMenu} and override
- * {@link Activity#onCreateContextMenu}.
- */
-public interface ContextMenu extends Menu {
- /**
- * Sets the context menu header's title to the title given in <var>titleRes</var>
- * resource identifier.
- *
- * @param titleRes The string resource identifier used for the title.
- * @return This ContextMenu so additional setters can be called.
- */
- public ContextMenu setHeaderTitle(int titleRes);
-
- /**
- * Sets the context menu header's title to the title given in <var>title</var>.
- *
- * @param title The character sequence used for the title.
- * @return This ContextMenu so additional setters can be called.
- */
- public ContextMenu setHeaderTitle(CharSequence title);
-
- /**
- * Sets the context menu header's icon to the icon given in <var>iconRes</var>
- * resource id.
- *
- * @param iconRes The resource identifier used for the icon.
- * @return This ContextMenu so additional setters can be called.
- */
- public ContextMenu setHeaderIcon(int iconRes);
-
- /**
- * Sets the context menu header's icon to the icon given in <var>icon</var>
- * {@link Drawable}.
- *
- * @param icon The {@link Drawable} used for the icon.
- * @return This ContextMenu so additional setters can be called.
- */
- public ContextMenu setHeaderIcon(Drawable icon);
-
- /**
- * Sets the header of the context menu to the {@link View} given in
- * <var>view</var>. This replaces the header title and icon (and those
- * replace this).
- *
- * @param view The {@link View} used for the header.
- * @return This ContextMenu so additional setters can be called.
- */
- public ContextMenu setHeaderView(View view);
-
- /**
- * Clears the header of the context menu.
- */
- public void clearHeader();
-
- /**
- * Additional information regarding the creation of the context menu. For example,
- * {@link AdapterView}s use this to pass the exact item position within the adapter
- * that initiated the context menu.
- */
- public interface ContextMenuInfo {
- }
-}
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
deleted file mode 100644
index 2045a98..0000000
--- a/core/java/android/view/ContextThemeWrapper.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.res.Resources;
-
-/**
- * A ContextWrapper that allows you to modify the theme from what is in the
- * wrapped context.
- */
-public class ContextThemeWrapper extends ContextWrapper {
- private Context mBase;
- private int mThemeResource;
- private Resources.Theme mTheme;
- private LayoutInflater mInflater;
-
- public ContextThemeWrapper() {
- super(null);
- }
-
- public ContextThemeWrapper(Context base, int themeres) {
- super(base);
- mBase = base;
- mThemeResource = themeres;
- }
-
- @Override protected void attachBaseContext(Context newBase) {
- super.attachBaseContext(newBase);
- mBase = newBase;
- }
-
- @Override public void setTheme(int resid) {
- mThemeResource = resid;
- initializeTheme();
- }
-
- @Override public Resources.Theme getTheme() {
- if (mTheme != null) {
- return mTheme;
- }
-
- if (mThemeResource == 0) {
- mThemeResource = com.android.internal.R.style.Theme;
- }
- initializeTheme();
-
- return mTheme;
- }
-
- @Override public Object getSystemService(String name) {
- if (LAYOUT_INFLATER_SERVICE.equals(name)) {
- if (mInflater == null) {
- mInflater = LayoutInflater.from(mBase).cloneInContext(this);
- }
- return mInflater;
- }
- return mBase.getSystemService(name);
- }
-
- /**
- * Called by {@link #setTheme} and {@link #getTheme} to apply a theme
- * resource to the current Theme object. Can override to change the
- * default (simple) behavior. This method will not be called in multiple
- * threads simultaneously.
- *
- * @param theme The Theme object being modified.
- * @param resid The theme style resource being applied to <var>theme</var>.
- * @param first Set to true if this is the first time a style is being
- * applied to <var>theme</var>.
- */
- protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
- theme.applyStyle(resid, true);
- }
-
- private void initializeTheme() {
- final boolean first = mTheme == null;
- if (first) {
- mTheme = getResources().newTheme();
- Resources.Theme theme = mBase.getTheme();
- if (theme != null) {
- mTheme.setTo(theme);
- }
- }
- onApplyThemeResource(mTheme, mThemeResource, first);
- }
-}
-
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
deleted file mode 100644
index 09ebeed..0000000
--- a/core/java/android/view/Display.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.util.DisplayMetrics;
-
-public class Display
-{
- /**
- * Specify the default Display
- */
- public static final int DEFAULT_DISPLAY = 0;
-
-
- /**
- * Use the WindowManager interface to create a Display object.
- * Display gives you access to some information about a particular display
- * connected to the device.
- */
- Display(int display) {
- // initalize the statics when this class is first instansiated. This is
- // done here instead of in the static block because Zygote
- synchronized (mStaticInit) {
- if (!mInitialized) {
- nativeClassInit();
- mInitialized = true;
- }
- }
- mDisplay = display;
- init(display);
- }
-
- /**
- * @return index of this display.
- */
- public int getDisplayId() {
- return mDisplay;
- }
-
- /**
- * @return the number of displays connected to the device.
- */
- native static int getDisplayCount();
-
- /**
- * @return width of this display in pixels.
- */
- native public int getWidth();
-
- /**
- * @return height of this display in pixels.
- */
- native public int getHeight();
-
- /**
- * @return orientation of this display.
- */
- native public int getOrientation();
-
- /**
- * @return pixel format of this display.
- */
- public int getPixelFormat() {
- return mPixelFormat;
- }
-
- /**
- * @return refresh rate of this display in frames per second.
- */
- public float getRefreshRate() {
- return mRefreshRate;
- }
-
- /**
- * Initialize a DisplayMetrics object from this display's data.
- *
- * @param outMetrics
- */
- public void getMetrics(DisplayMetrics outMetrics) {
- outMetrics.widthPixels = getWidth();
- outMetrics.heightPixels = getHeight();
- outMetrics.density = mDensity;
- outMetrics.scaledDensity= outMetrics.density;
- outMetrics.xdpi = mDpiX;
- outMetrics.ydpi = mDpiY;
- }
-
- /*
- * We use a class initializer to allow the native code to cache some
- * field offsets.
- */
- native private static void nativeClassInit();
-
- private native void init(int display);
-
- private int mDisplay;
- // Following fields are initialized from native code
- private int mPixelFormat;
- private float mRefreshRate;
- private float mDensity;
- private float mDpiX;
- private float mDpiY;
-
- private static final Object mStaticInit = new Object();
- private static boolean mInitialized = false;
-}
-
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
deleted file mode 100644
index 15fb839..0000000
--- a/core/java/android/view/FocusFinder.java
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.graphics.Rect;
-
-import java.util.ArrayList;
-
-/**
- * The algorithm used for finding the next focusable view in a given direction
- * from a view that currently has focus.
- */
-public class FocusFinder {
-
- private static ThreadLocal<FocusFinder> tlFocusFinder =
- new ThreadLocal<FocusFinder>() {
-
- protected FocusFinder initialValue() {
- return new FocusFinder();
- }
- };
-
- /**
- * Get the focus finder for this thread.
- */
- public static FocusFinder getInstance() {
- return tlFocusFinder.get();
- }
-
- Rect mFocusedRect = new Rect();
- Rect mOtherRect = new Rect();
- Rect mBestCandidateRect = new Rect();
-
- // enforce thread local access
- private FocusFinder() {}
-
- /**
- * Find the next view to take focus in root's descendants, starting from the view
- * that currently is focused.
- * @param root Contains focused
- * @param focused Has focus now.
- * @param direction Direction to look.
- * @return The next focusable view, or null if none exists.
- */
- public final View findNextFocus(ViewGroup root, View focused, int direction) {
-
- if (focused != null) {
- // check for user specified next focus
- View userSetNextFocus = focused.findUserSetNextFocus(root, direction);
- if (userSetNextFocus != null &&
- userSetNextFocus.isFocusable() &&
- (!userSetNextFocus.isInTouchMode() ||
- userSetNextFocus.isFocusableInTouchMode())) {
- return userSetNextFocus;
- }
-
- // fill in interesting rect from focused
- focused.getFocusedRect(mFocusedRect);
- root.offsetDescendantRectToMyCoords(focused, mFocusedRect);
- } else {
- // make up a rect at top left or bottom right of root
- switch (direction) {
- case View.FOCUS_RIGHT:
- case View.FOCUS_DOWN:
- final int rootTop = root.getScrollY();
- final int rootLeft = root.getScrollX();
- mFocusedRect.set(rootLeft, rootTop, rootLeft, rootTop);
- break;
-
- case View.FOCUS_LEFT:
- case View.FOCUS_UP:
- final int rootBottom = root.getScrollY() + root.getHeight();
- final int rootRight = root.getScrollX() + root.getWidth();
- mFocusedRect.set(rootRight, rootBottom,
- rootRight, rootBottom);
- break;
- }
- }
- return findNextFocus(root, focused, mFocusedRect, direction);
- }
-
- /**
- * Find the next view to take focus in root's descendants, searching from
- * a particular rectangle in root's coordinates.
- * @param root Contains focusedRect.
- * @param focusedRect The starting point of the search.
- * @param direction Direction to look.
- * @return The next focusable view, or null if none exists.
- */
- public View findNextFocusFromRect(ViewGroup root, Rect focusedRect, int direction) {
- return findNextFocus(root, null, focusedRect, direction);
- }
-
- private View findNextFocus(ViewGroup root, View focused, Rect focusedRect, int direction) {
- ArrayList<View> focusables = root.getFocusables(direction);
-
- // initialize the best candidate to something impossible
- // (so the first plausible view will become the best choice)
- mBestCandidateRect.set(focusedRect);
- switch(direction) {
- case View.FOCUS_LEFT:
- mBestCandidateRect.offset(focusedRect.width() + 1, 0);
- break;
- case View.FOCUS_RIGHT:
- mBestCandidateRect.offset(-(focusedRect.width() + 1), 0);
- break;
- case View.FOCUS_UP:
- mBestCandidateRect.offset(0, focusedRect.height() + 1);
- break;
- case View.FOCUS_DOWN:
- mBestCandidateRect.offset(0, -(focusedRect.height() + 1));
- }
-
- View closest = null;
-
- int numFocusables = focusables.size();
- for (int i = 0; i < numFocusables; i++) {
- View focusable = focusables.get(i);
-
- // only interested in other non-root views
- if (focusable == focused || focusable == root) continue;
-
- // get visible bounds of other view in same coordinate system
- focusable.getDrawingRect(mOtherRect);
- root.offsetDescendantRectToMyCoords(focusable, mOtherRect);
-
- if (isBetterCandidate(direction, focusedRect, mOtherRect, mBestCandidateRect)) {
- mBestCandidateRect.set(mOtherRect);
- closest = focusable;
- }
- }
- return closest;
- }
-
- /**
- * Is rect1 a better candidate than rect2 for a focus search in a particular
- * direction from a source rect? This is the core routine that determines
- * the order of focus searching.
- * @param direction the direction (up, down, left, right)
- * @param source The source we are searching from
- * @param rect1 The candidate rectangle
- * @param rect2 The current best candidate.
- * @return Whether the candidate is the new best.
- */
- boolean isBetterCandidate(int direction, Rect source, Rect rect1, Rect rect2) {
-
- // to be a better candidate, need to at least be a candidate in the first
- // place :)
- if (!isCandidate(source, rect1, direction)) {
- return false;
- }
-
- // we know that rect1 is a candidate.. if rect2 is not a candidate,
- // rect1 is better
- if (!isCandidate(source, rect2, direction)) {
- return true;
- }
-
- // if rect1 is better by beam, it wins
- if (beamBeats(direction, source, rect1, rect2)) {
- return true;
- }
-
- // if rect2 is better, then rect1 cant' be :)
- if (beamBeats(direction, source, rect2, rect1)) {
- return false;
- }
-
- // otherwise, do fudge-tastic comparison of the major and minor axis
- return (getWeightedDistanceFor(
- majorAxisDistance(direction, source, rect1),
- minorAxisDistance(direction, source, rect1))
- < getWeightedDistanceFor(
- majorAxisDistance(direction, source, rect2),
- minorAxisDistance(direction, source, rect2)));
- }
-
- /**
- * One rectangle may be another candidate than another by virtue of being
- * exclusively in the beam of the source rect.
- * @return Whether rect1 is a better candidate than rect2 by virtue of it being in src's
- * beam
- */
- boolean beamBeats(int direction, Rect source, Rect rect1, Rect rect2) {
- final boolean rect1InSrcBeam = beamsOverlap(direction, source, rect1);
- final boolean rect2InSrcBeam = beamsOverlap(direction, source, rect2);
-
- // if rect1 isn't exclusively in the src beam, it doesn't win
- if (rect2InSrcBeam || !rect1InSrcBeam) {
- return false;
- }
-
- // we know rect1 is in the beam, and rect2 is not
-
- // if rect1 is to the direction of, and rect2 is not, rect1 wins.
- // for example, for direction left, if rect1 is to the left of the source
- // and rect2 is below, then we always prefer the in beam rect1, since rect2
- // could be reached by going down.
- if (!isToDirectionOf(direction, source, rect2)) {
- return true;
- }
-
- // for horizontal directions, being exclusively in beam always wins
- if ((direction == View.FOCUS_LEFT || direction == View.FOCUS_RIGHT)) {
- return true;
- }
-
- // for vertical directions, beams only beat up to a point:
- // now, as long as rect2 isn't completely closer, rect1 wins
- // e.g for direction down, completely closer means for rect2's top
- // edge to be closer to the source's top edge than rect1's bottom edge.
- return (majorAxisDistance(direction, source, rect1)
- < majorAxisDistanceToFarEdge(direction, source, rect2));
- }
-
- /**
- * Fudge-factor opportunity: how to calculate distance given major and minor
- * axis distances. Warning: this fudge factor is finely tuned, be sure to
- * run all focus tests if you dare tweak it.
- */
- int getWeightedDistanceFor(int majorAxisDistance, int minorAxisDistance) {
- return 13 * majorAxisDistance * majorAxisDistance
- + minorAxisDistance * minorAxisDistance;
- }
-
- /**
- * Is destRect a candidate for the next focus given the direction? This
- * checks whether the dest is at least partially to the direction of (e.g left of)
- * from source.
- *
- * Includes an edge case for an empty rect (which is used in some cases when
- * searching from a point on the screen).
- */
- boolean isCandidate(Rect srcRect, Rect destRect, int direction) {
- switch (direction) {
- case View.FOCUS_LEFT:
- return (srcRect.right > destRect.right || srcRect.left >= destRect.right)
- && srcRect.left > destRect.left;
- case View.FOCUS_RIGHT:
- return (srcRect.left < destRect.left || srcRect.right <= destRect.left)
- && srcRect.right < destRect.right;
- case View.FOCUS_UP:
- return (srcRect.bottom > destRect.bottom || srcRect.top >= destRect.bottom)
- && srcRect.top > destRect.top;
- case View.FOCUS_DOWN:
- return (srcRect.top < destRect.top || srcRect.bottom <= destRect.top)
- && srcRect.bottom < destRect.bottom;
- }
- throw new IllegalArgumentException("direction must be one of "
- + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
- }
-
-
- /**
- * Do the "beams" w.r.t the given direcition's axos of rect1 and rect2 overlap?
- * @param direction the direction (up, down, left, right)
- * @param rect1 The first rectangle
- * @param rect2 The second rectangle
- * @return whether the beams overlap
- */
- boolean beamsOverlap(int direction, Rect rect1, Rect rect2) {
- switch (direction) {
- case View.FOCUS_LEFT:
- case View.FOCUS_RIGHT:
- return (rect2.bottom >= rect1.top) && (rect2.top <= rect1.bottom);
- case View.FOCUS_UP:
- case View.FOCUS_DOWN:
- return (rect2.right >= rect1.left) && (rect2.left <= rect1.right);
- }
- throw new IllegalArgumentException("direction must be one of "
- + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
- }
-
- /**
- * e.g for left, is 'to left of'
- */
- boolean isToDirectionOf(int direction, Rect src, Rect dest) {
- switch (direction) {
- case View.FOCUS_LEFT:
- return src.left >= dest.right;
- case View.FOCUS_RIGHT:
- return src.right <= dest.left;
- case View.FOCUS_UP:
- return src.top >= dest.bottom;
- case View.FOCUS_DOWN:
- return src.bottom <= dest.top;
- }
- throw new IllegalArgumentException("direction must be one of "
- + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
- }
-
- /**
- * @return The distance from the edge furthest in the given direction
- * of source to the edge nearest in the given direction of dest. If the
- * dest is not in the direction from source, return 0.
- */
- static int majorAxisDistance(int direction, Rect source, Rect dest) {
- return Math.max(0, majorAxisDistanceRaw(direction, source, dest));
- }
-
- static int majorAxisDistanceRaw(int direction, Rect source, Rect dest) {
- switch (direction) {
- case View.FOCUS_LEFT:
- return source.left - dest.right;
- case View.FOCUS_RIGHT:
- return dest.left - source.right;
- case View.FOCUS_UP:
- return source.top - dest.bottom;
- case View.FOCUS_DOWN:
- return dest.top - source.bottom;
- }
- throw new IllegalArgumentException("direction must be one of "
- + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
- }
-
- /**
- * @return The distance along the major axis w.r.t the direction from the
- * edge of source to the far edge of dest. If the
- * dest is not in the direction from source, return 1 (to break ties with
- * {@link #majorAxisDistance}).
- */
- static int majorAxisDistanceToFarEdge(int direction, Rect source, Rect dest) {
- return Math.max(1, majorAxisDistanceToFarEdgeRaw(direction, source, dest));
- }
-
- static int majorAxisDistanceToFarEdgeRaw(int direction, Rect source, Rect dest) {
- switch (direction) {
- case View.FOCUS_LEFT:
- return source.left - dest.left;
- case View.FOCUS_RIGHT:
- return dest.right - source.right;
- case View.FOCUS_UP:
- return source.top - dest.top;
- case View.FOCUS_DOWN:
- return dest.bottom - source.bottom;
- }
- throw new IllegalArgumentException("direction must be one of "
- + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
- }
-
- /**
- * Find the distance on the minor axis w.r.t the direction to the nearest
- * edge of the destination rectange.
- * @param direction the direction (up, down, left, right)
- * @param source The source rect.
- * @param dest The destination rect.
- * @return The distance.
- */
- static int minorAxisDistance(int direction, Rect source, Rect dest) {
- switch (direction) {
- case View.FOCUS_LEFT:
- case View.FOCUS_RIGHT:
- // the distance between the center verticals
- return Math.abs(
- ((source.top + source.height() / 2) -
- ((dest.top + dest.height() / 2))));
- case View.FOCUS_UP:
- case View.FOCUS_DOWN:
- // the distance between the center horizontals
- return Math.abs(
- ((source.left + source.width() / 2) -
- ((dest.left + dest.width() / 2))));
- }
- throw new IllegalArgumentException("direction must be one of "
- + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
- }
-
- /**
- * Find the nearest touchable view to the specified view.
- *
- * @param root The root of the tree in which to search
- * @param x X coordinate from which to start the search
- * @param y Y coordinate from which to start the search
- * @param direction Direction to look
- * @param deltas Offset from the <x, y> to the edge of the nearest view. Note that this array
- * may already be populated with values.
- * @return The nearest touchable view, or null if none exists.
- */
- public View findNearestTouchable(ViewGroup root, int x, int y, int direction, int[] deltas) {
- ArrayList<View> touchables = root.getTouchables();
- int minDistance = Integer.MAX_VALUE;
- View closest = null;
-
- int numTouchables = touchables.size();
-
- int edgeSlop = ViewConfiguration.get(root.mContext).getScaledEdgeSlop();
-
- Rect closestBounds = new Rect();
- Rect touchableBounds = mOtherRect;
-
- for (int i = 0; i < numTouchables; i++) {
- View touchable = touchables.get(i);
-
- // get visible bounds of other view in same coordinate system
- touchable.getDrawingRect(touchableBounds);
-
- root.offsetRectBetweenParentAndChild(touchable, touchableBounds, true, true);
-
- if (!isTouchCandidate(x, y, touchableBounds, direction)) {
- continue;
- }
-
- int distance = Integer.MAX_VALUE;
-
- switch (direction) {
- case View.FOCUS_LEFT:
- distance = x - touchableBounds.right + 1;
- break;
- case View.FOCUS_RIGHT:
- distance = touchableBounds.left;
- break;
- case View.FOCUS_UP:
- distance = y - touchableBounds.bottom + 1;
- break;
- case View.FOCUS_DOWN:
- distance = touchableBounds.top;
- break;
- }
-
- if (distance < edgeSlop) {
- // Give preference to innermost views
- if (closest == null ||
- closestBounds.contains(touchableBounds) ||
- (!touchableBounds.contains(closestBounds) && distance < minDistance)) {
- minDistance = distance;
- closest = touchable;
- closestBounds.set(touchableBounds);
- switch (direction) {
- case View.FOCUS_LEFT:
- deltas[0] = -distance;
- break;
- case View.FOCUS_RIGHT:
- deltas[0] = distance;
- break;
- case View.FOCUS_UP:
- deltas[1] = -distance;
- break;
- case View.FOCUS_DOWN:
- deltas[1] = distance;
- break;
- }
- }
- }
- }
- return closest;
- }
-
-
- /**
- * Is destRect a candidate for the next touch given the direction?
- */
- private boolean isTouchCandidate(int x, int y, Rect destRect, int direction) {
- switch (direction) {
- case View.FOCUS_LEFT:
- return destRect.left <= x && destRect.top <= y && y <= destRect.bottom;
- case View.FOCUS_RIGHT:
- return destRect.left >= x && destRect.top <= y && y <= destRect.bottom;
- case View.FOCUS_UP:
- return destRect.top <= y && destRect.left <= x && x <= destRect.right;
- case View.FOCUS_DOWN:
- return destRect.top >= y && destRect.left <= x && x <= destRect.right;
- }
- throw new IllegalArgumentException("direction must be one of "
- + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
- }
-}
diff --git a/core/java/android/view/FocusFinderHelper.java b/core/java/android/view/FocusFinderHelper.java
deleted file mode 100644
index 69dc056..0000000
--- a/core/java/android/view/FocusFinderHelper.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.graphics.Rect;
-
-/**
- * A helper class that allows unit tests to access FocusFinder methods.
- * @hide
- */
-public class FocusFinderHelper {
-
- private FocusFinder mFocusFinder;
-
- /**
- * Wrap the FocusFinder object
- */
- public FocusFinderHelper(FocusFinder focusFinder) {
- mFocusFinder = focusFinder;
- }
-
- public boolean isBetterCandidate(int direction, Rect source, Rect rect1, Rect rect2) {
- return mFocusFinder.isBetterCandidate(direction, source, rect1, rect2);
- }
-
- public boolean beamBeats(int direction, Rect source, Rect rect1, Rect rect2) {
- return mFocusFinder.beamBeats(direction, source, rect1, rect2);
- }
-
- public boolean isCandidate(Rect srcRect, Rect destRect, int direction) {
- return mFocusFinder.isCandidate(srcRect, destRect, direction);
- }
-
- public boolean beamsOverlap(int direction, Rect rect1, Rect rect2) {
- return mFocusFinder.beamsOverlap(direction, rect1, rect2);
- }
-
- public static int majorAxisDistance(int direction, Rect source, Rect dest) {
- return FocusFinder.majorAxisDistance(direction, source, dest);
- }
-
- public static int majorAxisDistanceToFarEdge(int direction, Rect source, Rect dest) {
- return FocusFinder.majorAxisDistanceToFarEdge(direction, source, dest);
- }
-}
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
deleted file mode 100644
index 679c683..0000000
--- a/core/java/android/view/GestureDetector.java
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.os.Handler;
-import android.os.Message;
-import android.content.Context;
-
-/**
- * Detects various gestures and events using the supplied {@link MotionEvent}s.
- * The {@link OnGestureListener} callback will notify users when a particular
- * motion event has occurred. This class should only be used with {@link MotionEvent}s
- * reported via touch (don't use for trackball events).
- *
- * To use this class:
- * <ul>
- * <li>Create an instance of the {@code GestureDetector} for your {@link View}
- * <li>In the {@link View#onTouchEvent(MotionEvent)} method ensure you call
- * {@link #onTouchEvent(MotionEvent)}. The methods defined in your callback
- * will be executed when the events occur.
- * </ul>
- */
-public class GestureDetector {
- /**
- * The listener that is used to notify when gestures occur.
- * If you want to listen for all the different gestures then implement
- * this interface. If you only want to listen for a subset it might
- * be easier to extend {@link SimpleOnGestureListener}.
- */
- public interface OnGestureListener {
-
- /**
- * Notified when a tap occurs with the down {@link MotionEvent}
- * that triggered it. This will be triggered immediately for
- * every down event. All other events should be preceded by this.
- *
- * @param e The down motion event.
- */
- boolean onDown(MotionEvent e);
-
- /**
- * The user has performed a down {@link MotionEvent} and not performed
- * a move or up yet. This event is commonly used to provide visual
- * feedback to the user to let them know that their action has been
- * recognized i.e. highlight an element.
- *
- * @param e The down motion event
- */
- void onShowPress(MotionEvent e);
-
- /**
- * Notified when a tap occurs with the up {@link MotionEvent}
- * that triggered it.
- *
- * @param e The up motion event that completed the first tap
- * @return true if the event is consumed, else false
- */
- boolean onSingleTapUp(MotionEvent e);
-
- /**
- * Notified when a scroll occurs with the initial on down {@link MotionEvent} and the
- * current move {@link MotionEvent}. The distance in x and y is also supplied for
- * convenience.
- *
- * @param e1 The first down motion event that started the scrolling.
- * @param e2 The move motion event that triggered the current onScroll.
- * @param distanceX The distance along the X axis that has been scrolled since the last
- * call to onScroll. This is NOT the distance between {@code e1}
- * and {@code e2}.
- * @param distanceY The distance along the Y axis that has been scrolled since the last
- * call to onScroll. This is NOT the distance between {@code e1}
- * and {@code e2}.
- * @return true if the event is consumed, else false
- */
- boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
-
- /**
- * Notified when a long press occurs with the initial on down {@link MotionEvent}
- * that trigged it.
- *
- * @param e The initial on down motion event that started the longpress.
- */
- void onLongPress(MotionEvent e);
-
- /**
- * Notified of a fling event when it occurs with the initial on down {@link MotionEvent}
- * and the matching up {@link MotionEvent}. The calculated velocity is supplied along
- * the x and y axis in pixels per second.
- *
- * @param e1 The first down motion event that started the fling.
- * @param e2 The move motion event that triggered the current onFling.
- * @param velocityX The velocity of this fling measured in pixels per second
- * along the x axis.
- * @param velocityY The velocity of this fling measured in pixels per second
- * along the y axis.
- * @return true if the event is consumed, else false
- */
- boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
- }
-
- /**
- * @hide pending API council
- */
- public interface OnDoubleTapListener {
- boolean onSingleTapConfirmed(MotionEvent e);
- boolean onDoubleTapEvent(MotionEvent e);
- }
-
- /**
- * A convenience class to extend when you only want to listen for a
- * subset of all the gestures. This implements all methods in the
- * {@link OnGestureListener} but does nothing and return {@code false}
- * for all applicable methods.
- */
- public static class SimpleOnGestureListener implements OnGestureListener {
- public boolean onSingleTapUp(MotionEvent e) {
- return false;
- }
-
- public void onLongPress(MotionEvent e) {
- }
-
- public boolean onScroll(MotionEvent e1, MotionEvent e2,
- float distanceX, float distanceY) {
- return false;
- }
-
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
- float velocityY) {
- return false;
- }
-
- public void onShowPress(MotionEvent e) {
- }
-
- public boolean onDown(MotionEvent e) {
- return false;
- }
- }
-
- // TODO: ViewConfiguration
- private int mBiggerTouchSlopSquare = 20 * 20;
-
- private int mTouchSlopSquare;
- private int mDoubleTapSlopSquare;
- private int mMinimumFlingVelocity;
-
- private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout();
- private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout();
- // TODO make new double-tap timeout, and define its events (i.e. either time
- // between down-down or time between up-down)
- private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout();
-
- // constants for Message.what used by GestureHandler below
- private static final int SHOW_PRESS = 1;
- private static final int LONG_PRESS = 2;
- private static final int TAP = 3;
-
- private final Handler mHandler;
- private final OnGestureListener mListener;
- private OnDoubleTapListener mDoubleTapListener;
-
- private boolean mStillDown;
- private boolean mInLongPress;
- private boolean mAlwaysInTapRegion;
- private boolean mAlwaysInBiggerTapRegion;
-
- private MotionEvent mCurrentDownEvent;
- private MotionEvent mPreviousUpEvent;
-
- /**
- * True when the user is still touching for the second tap (down, move, and
- * up events). Can only be true if there is a double tap listener attached.
- */
- private boolean mIsDoubleTapping;
-
- private float mLastMotionY;
- private float mLastMotionX;
-
- private boolean mIsLongpressEnabled;
-
- /**
- * Determines speed during touch scrolling
- */
- private VelocityTracker mVelocityTracker;
-
- private class GestureHandler extends Handler {
- GestureHandler() {
- super();
- }
-
- GestureHandler(Handler handler) {
- super(handler.getLooper());
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case SHOW_PRESS:
- mListener.onShowPress(mCurrentDownEvent);
- break;
-
- case LONG_PRESS:
- dispatchLongPress();
- break;
-
- case TAP:
- // If the user's finger is still down, do not count it as a tap
- if (mDoubleTapListener != null && !mStillDown) {
- mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent);
- }
- break;
-
- default:
- throw new RuntimeException("Unknown message " + msg); //never
- }
- }
- }
-
- /**
- * Creates a GestureDetector with the supplied listener.
- * This variant of the constructor should be used from a non-UI thread
- * (as it allows specifying the Handler).
- *
- * @param listener the listener invoked for all the callbacks, this must
- * not be null.
- * @param handler the handler to use
- *
- * @throws NullPointerException if either {@code listener} or
- * {@code handler} is null.
- *
- * @deprecated Use {@link #GestureDetector(android.content.Context,
- * android.view.GestureDetector.OnGestureListener, android.os.Handler)} instead.
- */
- @Deprecated
- public GestureDetector(OnGestureListener listener, Handler handler) {
- this(null, listener, handler);
- }
-
- /**
- * Creates a GestureDetector with the supplied listener.
- * You may only use this constructor from a UI thread (this is the usual situation).
- * @see android.os.Handler#Handler()
- *
- * @param listener the listener invoked for all the callbacks, this must
- * not be null.
- *
- * @throws NullPointerException if {@code listener} is null.
- *
- * @deprecated Use {@link #GestureDetector(android.content.Context,
- * android.view.GestureDetector.OnGestureListener)} instead.
- */
- @Deprecated
- public GestureDetector(OnGestureListener listener) {
- this(null, listener, null);
- }
-
- /**
- * Creates a GestureDetector with the supplied listener.
- * You may only use this constructor from a UI thread (this is the usual situation).
- * @see android.os.Handler#Handler()
- *
- * @param context the application's context
- * @param listener the listener invoked for all the callbacks, this must
- * not be null.
- *
- * @throws NullPointerException if {@code listener} is null.
- */
- public GestureDetector(Context context, OnGestureListener listener) {
- this(context, listener, null);
- }
-
- /**
- * Creates a GestureDetector with the supplied listener.
- * You may only use this constructor from a UI thread (this is the usual situation).
- * @see android.os.Handler#Handler()
- *
- * @param context the application's context
- * @param listener the listener invoked for all the callbacks, this must
- * not be null.
- * @param handler the handler to use
- *
- * @throws NullPointerException if {@code listener} is null.
- */
- public GestureDetector(Context context, OnGestureListener listener, Handler handler) {
- if (handler != null) {
- mHandler = new GestureHandler(handler);
- } else {
- mHandler = new GestureHandler();
- }
- mListener = listener;
- init(context);
- }
-
- private void init(Context context) {
- if (mListener == null) {
- throw new NullPointerException("OnGestureListener must not be null");
- }
- mIsLongpressEnabled = true;
-
- // Fallback to support pre-donuts releases
- int touchSlop, doubleTapSlop;
- if (context == null) {
- //noinspection deprecation
- touchSlop = ViewConfiguration.getTouchSlop();
- doubleTapSlop = ViewConfiguration.getDoubleTapSlop();
- //noinspection deprecation
- mMinimumFlingVelocity = ViewConfiguration.getMinimumFlingVelocity();
- } else {
- final ViewConfiguration configuration = ViewConfiguration.get(context);
- touchSlop = configuration.getScaledTouchSlop();
- doubleTapSlop = configuration.getScaledDoubleTapSlop();
- mMinimumFlingVelocity = configuration.getScaledMinimumFlingVelocity();
- }
- mTouchSlopSquare = touchSlop * touchSlop;
- mDoubleTapSlopSquare = doubleTapSlop * doubleTapSlop;
- }
-
- /**
- * @hide pending API council
- * @param onDoubleTapListener
- */
- public void setOnDoubleTapListener(OnDoubleTapListener onDoubleTapListener) {
- mDoubleTapListener = onDoubleTapListener;
- }
-
- /**
- * Set whether longpress is enabled, if this is enabled when a user
- * presses and holds down you get a longpress event and nothing further.
- * If it's disabled the user can press and hold down and then later
- * moved their finger and you will get scroll events. By default
- * longpress is enabled.
- *
- * @param isLongpressEnabled whether longpress should be enabled.
- */
- public void setIsLongpressEnabled(boolean isLongpressEnabled) {
- mIsLongpressEnabled = isLongpressEnabled;
- }
-
- /**
- * @return true if longpress is enabled, else false.
- */
- public boolean isLongpressEnabled() {
- return mIsLongpressEnabled;
- }
-
- /**
- * Analyzes the given motion event and if applicable triggers the
- * appropriate callbacks on the {@link OnGestureListener} supplied.
- *
- * @param ev The current motion event.
- * @return true if the {@link OnGestureListener} consumed the event,
- * else false.
- */
- public boolean onTouchEvent(MotionEvent ev) {
- final int action = ev.getAction();
- final float y = ev.getY();
- final float x = ev.getX();
-
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(ev);
-
- boolean handled = false;
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- if (mDoubleTapListener != null) {
- boolean hadTapMessage = mHandler.hasMessages(TAP);
- if (hadTapMessage) mHandler.removeMessages(TAP);
- if ((mCurrentDownEvent != null) && (mPreviousUpEvent != null) && hadTapMessage &&
- isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) {
- // This is a second tap
- mIsDoubleTapping = true;
- handled = mDoubleTapListener.onDoubleTapEvent(ev);
- } else {
- // This is a first tap
- mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT);
- }
- }
-
- mLastMotionX = x;
- mLastMotionY = y;
- mCurrentDownEvent = MotionEvent.obtain(ev);
- mAlwaysInTapRegion = true;
- mAlwaysInBiggerTapRegion = true;
- mStillDown = true;
- mInLongPress = false;
-
- if (mIsLongpressEnabled) {
- mHandler.removeMessages(LONG_PRESS);
- mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.getDownTime()
- + TAP_TIMEOUT + LONGPRESS_TIMEOUT);
- }
- mHandler.sendEmptyMessageAtTime(SHOW_PRESS, mCurrentDownEvent.getDownTime() + TAP_TIMEOUT);
- handled |= mListener.onDown(ev);
- break;
-
- case MotionEvent.ACTION_MOVE:
- if (mInLongPress) {
- break;
- }
- final float scrollX = mLastMotionX - x;
- final float scrollY = mLastMotionY - y;
- if (mIsDoubleTapping) {
- handled = mDoubleTapListener.onDoubleTapEvent(ev);
- } else if (mAlwaysInTapRegion) {
- final int deltaX = (int) (x - mCurrentDownEvent.getX());
- final int deltaY = (int) (y - mCurrentDownEvent.getY());
- int distance = (deltaX * deltaX) + (deltaY * deltaY);
- if (distance > mTouchSlopSquare) {
- handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
- mLastMotionX = x;
- mLastMotionY = y;
- mAlwaysInTapRegion = false;
- mHandler.removeMessages(TAP);
- mHandler.removeMessages(SHOW_PRESS);
- mHandler.removeMessages(LONG_PRESS);
- }
- if (distance > mBiggerTouchSlopSquare) {
- mAlwaysInBiggerTapRegion = false;
- }
- } else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1)) {
- handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
- mLastMotionX = x;
- mLastMotionY = y;
- }
- break;
-
- case MotionEvent.ACTION_UP:
- mStillDown = false;
- MotionEvent currentUpEvent = MotionEvent.obtain(ev);
- if (mIsDoubleTapping) {
- handled = mDoubleTapListener.onDoubleTapEvent(ev);
- mIsDoubleTapping = false;
- break;
- } else if (mInLongPress) {
- mHandler.removeMessages(TAP);
- mInLongPress = false;
- break;
- }
- if (mAlwaysInTapRegion) {
- handled = mListener.onSingleTapUp(ev);
- } else {
-
- // A fling must travel the minimum tap distance
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(1000);
- final float velocityY = velocityTracker.getYVelocity();
- final float velocityX = velocityTracker.getXVelocity();
-
- if ((Math.abs(velocityY) > mMinimumFlingVelocity)
- || (Math.abs(velocityX) > mMinimumFlingVelocity)){
- handled = mListener.onFling(mCurrentDownEvent, currentUpEvent, velocityX, velocityY);
- }
- }
- mPreviousUpEvent = MotionEvent.obtain(ev);
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- mHandler.removeMessages(SHOW_PRESS);
- mHandler.removeMessages(LONG_PRESS);
- break;
- case MotionEvent.ACTION_CANCEL:
- mHandler.removeMessages(SHOW_PRESS);
- mHandler.removeMessages(LONG_PRESS);
- mHandler.removeMessages(TAP);
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- mStillDown = false;
- if (mInLongPress) {
- mInLongPress = false;
- break;
- }
- }
- return handled;
- }
-
- private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp,
- MotionEvent secondDown) {
- if (!mAlwaysInBiggerTapRegion) {
- return false;
- }
-
- if (secondDown.getEventTime() - firstUp.getEventTime() > DOUBLE_TAP_TIMEOUT) {
- return false;
- }
-
- int deltaX = (int) firstDown.getX() - (int) secondDown.getX();
- int deltaY = (int) firstDown.getY() - (int) secondDown.getY();
- return (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare);
- }
-
- private void dispatchLongPress() {
- mHandler.removeMessages(TAP);
- mInLongPress = true;
- mListener.onLongPress(mCurrentDownEvent);
- }
-}
diff --git a/core/java/android/view/Gravity.java b/core/java/android/view/Gravity.java
deleted file mode 100644
index 36d8ce6..0000000
--- a/core/java/android/view/Gravity.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-import android.graphics.Rect;
-
-/**
- * Standard constants and tools for placing an object within a potentially
- * larger container.
- */
-public class Gravity
-{
- /** Constant indicating that no gravity has been set **/
- public static final int NO_GRAVITY = 0x0000;
-
- /** Raw bit indicating the gravity for an axis has been specified. */
- public static final int AXIS_SPECIFIED = 0x0001;
-
- /** Raw bit controlling how the left/top edge is placed. */
- public static final int AXIS_PULL_BEFORE = 0x0002;
- /** Raw bit controlling how the right/bottom edge is placed. */
- public static final int AXIS_PULL_AFTER = 0x0004;
- /** Raw bit controlling whether the right/bottom edge is clipped to its
- * container, based on the gravity direction being applied. */
- public static final int AXIS_CLIP = 0x0008;
-
- /** Bits defining the horizontal axis. */
- public static final int AXIS_X_SHIFT = 0;
- /** Bits defining the vertical axis. */
- public static final int AXIS_Y_SHIFT = 4;
-
- /** Push object to the top of its container, not changing its size. */
- public static final int TOP = (AXIS_PULL_BEFORE|AXIS_SPECIFIED)<<AXIS_Y_SHIFT;
- /** Push object to the bottom of its container, not changing its size. */
- public static final int BOTTOM = (AXIS_PULL_AFTER|AXIS_SPECIFIED)<<AXIS_Y_SHIFT;
- /** Push object to the left of its container, not changing its size. */
- public static final int LEFT = (AXIS_PULL_BEFORE|AXIS_SPECIFIED)<<AXIS_X_SHIFT;
- /** Push object to the right of its container, not changing its size. */
- public static final int RIGHT = (AXIS_PULL_AFTER|AXIS_SPECIFIED)<<AXIS_X_SHIFT;
-
- /** Place object in the vertical center of its container, not changing its
- * size. */
- public static final int CENTER_VERTICAL = AXIS_SPECIFIED<<AXIS_Y_SHIFT;
- /** Grow the vertical size of the object if needed so it completely fills
- * its container. */
- public static final int FILL_VERTICAL = TOP|BOTTOM;
-
- /** Place object in the horizontal center of its container, not changing its
- * size. */
- public static final int CENTER_HORIZONTAL = AXIS_SPECIFIED<<AXIS_X_SHIFT;
- /** Grow the horizontal size of the object if needed so it completely fills
- * its container. */
- public static final int FILL_HORIZONTAL = LEFT|RIGHT;
-
- /** Place the object in the center of its container in both the vertical
- * and horizontal axis, not changing its size. */
- public static final int CENTER = CENTER_VERTICAL|CENTER_HORIZONTAL;
-
- /** Grow the horizontal and vertical size of the object if needed so it
- * completely fills its container. */
- public static final int FILL = FILL_VERTICAL|FILL_HORIZONTAL;
-
- /** Flag to clip the edges of the object to its container along the
- * vertical axis. */
- public static final int CLIP_VERTICAL = AXIS_CLIP<<AXIS_Y_SHIFT;
-
- /** Flag to clip the edges of the object to its container along the
- * horizontal axis. */
- public static final int CLIP_HORIZONTAL = AXIS_CLIP<<AXIS_X_SHIFT;
-
- /**
- * Binary mask to get the horizontal gravity of a gravity.
- */
- public static final int HORIZONTAL_GRAVITY_MASK = (AXIS_SPECIFIED |
- AXIS_PULL_BEFORE | AXIS_PULL_AFTER) << AXIS_X_SHIFT;
- /**
- * Binary mask to get the vertical gravity of a gravity.
- */
- public static final int VERTICAL_GRAVITY_MASK = (AXIS_SPECIFIED |
- AXIS_PULL_BEFORE | AXIS_PULL_AFTER) << AXIS_Y_SHIFT;
-
- /** Special constant to enable clipping to an overall display along the
- * vertical dimension. This is not applied by default by
- * {@link #apply(int, int, int, Rect, int, int, Rect)}; you must do so
- * yourself by calling {@link #applyDisplay}.
- */
- public static final int DISPLAY_CLIP_VERTICAL = 0x10000000;
-
- /** Special constant to enable clipping to an overall display along the
- * horizontal dimension. This is not applied by default by
- * {@link #apply(int, int, int, Rect, int, int, Rect)}; you must do so
- * yourself by calling {@link #applyDisplay}.
- */
- public static final int DISPLAY_CLIP_HORIZONTAL = 0x01000000;
-
- /**
- * Apply a gravity constant to an object.
- *
- * @param gravity The desired placement of the object, as defined by the
- * constants in this class.
- * @param w The horizontal size of the object.
- * @param h The vertical size of the object.
- * @param container The frame of the containing space, in which the object
- * will be placed. Should be large enough to contain the
- * width and height of the object.
- * @param outRect Receives the computed frame of the object in its
- * container.
- */
- public static void apply(int gravity, int w, int h, Rect container,
- Rect outRect) {
- apply(gravity, w, h, container, 0, 0, outRect);
- }
-
- /**
- * Apply a gravity constant to an object.
- *
- * @param gravity The desired placement of the object, as defined by the
- * constants in this class.
- * @param w The horizontal size of the object.
- * @param h The vertical size of the object.
- * @param container The frame of the containing space, in which the object
- * will be placed. Should be large enough to contain the
- * width and height of the object.
- * @param xAdj Offset to apply to the X axis. If gravity is LEFT this
- * pushes it to the right; if gravity is RIGHT it pushes it to
- * the left; if gravity is CENTER_HORIZONTAL it pushes it to the
- * right or left; otherwise it is ignored.
- * @param yAdj Offset to apply to the Y axis. If gravity is TOP this pushes
- * it down; if gravity is BOTTOM it pushes it up; if gravity is
- * CENTER_VERTICAL it pushes it down or up; otherwise it is
- * ignored.
- * @param outRect Receives the computed frame of the object in its
- * container.
- */
- public static void apply(int gravity, int w, int h, Rect container,
- int xAdj, int yAdj, Rect outRect) {
- switch (gravity&((AXIS_PULL_BEFORE|AXIS_PULL_AFTER)<<AXIS_X_SHIFT)) {
- case 0:
- outRect.left = container.left
- + ((container.right - container.left - w)/2) + xAdj;
- outRect.right = outRect.left + w;
- if ((gravity&(AXIS_CLIP<<AXIS_X_SHIFT))
- == (AXIS_CLIP<<AXIS_X_SHIFT)) {
- if (outRect.left < container.left) {
- outRect.left = container.left;
- }
- if (outRect.right > container.right) {
- outRect.right = container.right;
- }
- }
- break;
- case AXIS_PULL_BEFORE<<AXIS_X_SHIFT:
- outRect.left = container.left + xAdj;
- outRect.right = outRect.left + w;
- if ((gravity&(AXIS_CLIP<<AXIS_X_SHIFT))
- == (AXIS_CLIP<<AXIS_X_SHIFT)) {
- if (outRect.right > container.right) {
- outRect.right = container.right;
- }
- }
- break;
- case AXIS_PULL_AFTER<<AXIS_X_SHIFT:
- outRect.right = container.right - xAdj;
- outRect.left = outRect.right - w;
- if ((gravity&(AXIS_CLIP<<AXIS_X_SHIFT))
- == (AXIS_CLIP<<AXIS_X_SHIFT)) {
- if (outRect.left < container.left) {
- outRect.left = container.left;
- }
- }
- break;
- default:
- outRect.left = container.left + xAdj;
- outRect.right = container.right + xAdj;
- break;
- }
-
- switch (gravity&((AXIS_PULL_BEFORE|AXIS_PULL_AFTER)<<AXIS_Y_SHIFT)) {
- case 0:
- outRect.top = container.top
- + ((container.bottom - container.top - h)/2) + yAdj;
- outRect.bottom = outRect.top + h;
- if ((gravity&(AXIS_CLIP<<AXIS_Y_SHIFT))
- == (AXIS_CLIP<<AXIS_Y_SHIFT)) {
- if (outRect.top < container.top) {
- outRect.top = container.top;
- }
- if (outRect.bottom > container.bottom) {
- outRect.bottom = container.bottom;
- }
- }
- break;
- case AXIS_PULL_BEFORE<<AXIS_Y_SHIFT:
- outRect.top = container.top + yAdj;
- outRect.bottom = outRect.top + h;
- if ((gravity&(AXIS_CLIP<<AXIS_Y_SHIFT))
- == (AXIS_CLIP<<AXIS_Y_SHIFT)) {
- if (outRect.bottom > container.bottom) {
- outRect.bottom = container.bottom;
- }
- }
- break;
- case AXIS_PULL_AFTER<<AXIS_Y_SHIFT:
- outRect.bottom = container.bottom - yAdj;
- outRect.top = outRect.bottom - h;
- if ((gravity&(AXIS_CLIP<<AXIS_Y_SHIFT))
- == (AXIS_CLIP<<AXIS_Y_SHIFT)) {
- if (outRect.top < container.top) {
- outRect.top = container.top;
- }
- }
- break;
- default:
- outRect.top = container.top + yAdj;
- outRect.bottom = container.bottom + yAdj;
- break;
- }
- }
-
- /**
- * Apply addition gravity behavior based on the overall "display" that an
- * object exists in. This can be used after
- * {@link #apply(int, int, int, Rect, int, int, Rect)} to place the object
- * within a visible display. By default this moves or clips the object
- * to be visible in the display; the gravity flags
- * {@link #DISPLAY_CLIP_HORIZONTAL} and {@link #DISPLAY_CLIP_VERTICAL}
- * can be used to change this behavior.
- *
- * @param gravity Gravity constants to modify the placement within the
- * display.
- * @param display The rectangle of the display in which the object is
- * being placed.
- * @param inoutObj Supplies the current object position; returns with it
- * modified if needed to fit in the display.
- */
- public static void applyDisplay(int gravity, Rect display, Rect inoutObj) {
- if ((gravity&DISPLAY_CLIP_VERTICAL) != 0) {
- if (inoutObj.top < display.top) inoutObj.top = display.top;
- if (inoutObj.bottom > display.bottom) inoutObj.bottom = display.bottom;
- } else {
- int off = 0;
- if (inoutObj.top < display.top) off = display.top-inoutObj.top;
- else if (inoutObj.bottom > display.bottom) off = display.bottom-inoutObj.bottom;
- if (off != 0) {
- if (inoutObj.height() > (display.bottom-display.top)) {
- inoutObj.top = display.top;
- inoutObj.bottom = display.bottom;
- } else {
- inoutObj.top += off;
- inoutObj.bottom += off;
- }
- }
- }
-
- if ((gravity&DISPLAY_CLIP_HORIZONTAL) != 0) {
- if (inoutObj.left < display.left) inoutObj.left = display.left;
- if (inoutObj.right > display.right) inoutObj.right = display.right;
- } else {
- int off = 0;
- if (inoutObj.left < display.left) off = display.left-inoutObj.left;
- else if (inoutObj.right > display.right) off = display.right-inoutObj.right;
- if (off != 0) {
- if (inoutObj.width() > (display.right-display.left)) {
- inoutObj.left = display.left;
- inoutObj.right = display.right;
- } else {
- inoutObj.left += off;
- inoutObj.right += off;
- }
- }
- }
- }
-
- /**
- * <p>Indicate whether the supplied gravity has a vertical pull.</p>
- *
- * @param gravity the gravity to check for vertical pull
- * @return true if the supplied gravity has a vertical pull
- */
- public static boolean isVertical(int gravity) {
- return gravity > 0 && (gravity & VERTICAL_GRAVITY_MASK) != 0;
- }
-
- /**
- * <p>Indicate whether the supplied gravity has an horizontal pull.</p>
- *
- * @param gravity the gravity to check for horizontal pull
- * @return true if the supplied gravity has an horizontal pull
- */
- public static boolean isHorizontal(int gravity) {
- return gravity > 0 && (gravity & HORIZONTAL_GRAVITY_MASK) != 0;
- }
-}
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
deleted file mode 100644
index cc3563c..0000000
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-/**
- * Constants to be used to perform haptic feedback effects via
- * {@link View#performHapticFeedback(int)}
- */
-public class HapticFeedbackConstants {
-
- private HapticFeedbackConstants() {}
-
- public static final int LONG_PRESS = 0;
-
- /** @hide pending API council */
- public static final int ZOOM_RING_TICK = 1;
-
- /**
- * Flag for {@link View#performHapticFeedback(int, int)
- * View.performHapticFeedback(int, int)}: Ignore the setting in the
- * view for whether to perform haptic feedback, do it always.
- */
- public static final int FLAG_IGNORE_VIEW_SETTING = 0x0001;
-
- /**
- * Flag for {@link View#performHapticFeedback(int, int)
- * View.performHapticFeedback(int, int)}: Ignore the global setting
- * for whether to perform haptic feedback, do it always.
- */
- public static final int FLAG_IGNORE_GLOBAL_SETTING = 0x0002;
-}
diff --git a/core/java/android/view/IApplicationToken.aidl b/core/java/android/view/IApplicationToken.aidl
deleted file mode 100644
index 6bff5b3..0000000
--- a/core/java/android/view/IApplicationToken.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/* //device/java/android/android/view/IApplicationToken.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.view;
-
-/** {@hide} */
-interface IApplicationToken
-{
- void windowsVisible();
- void windowsGone();
- boolean keyDispatchingTimedOut();
- long getKeyDispatchingTimeout();
-}
-
diff --git a/core/java/android/view/IOnKeyguardExitResult.aidl b/core/java/android/view/IOnKeyguardExitResult.aidl
deleted file mode 100644
index 47d5220..0000000
--- a/core/java/android/view/IOnKeyguardExitResult.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/* //device/java/android/android/hardware/ISensorListener.aidl
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.view;
-
-/** @hide */
-oneway interface IOnKeyguardExitResult {
-
- void onKeyguardExitResult(boolean success);
-
-}
diff --git a/core/java/android/view/IRotationWatcher.aidl b/core/java/android/view/IRotationWatcher.aidl
deleted file mode 100644
index 2c83642..0000000
--- a/core/java/android/view/IRotationWatcher.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/* //device/java/android/android/hardware/ISensorListener.aidl
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.view;
-
-/**
- * {@hide}
- */
-oneway interface IRotationWatcher {
- void onRotationChanged(int rotation);
-}
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
deleted file mode 100644
index 99d5c0c..0000000
--- a/core/java/android/view/IWindow.aidl
+++ /dev/null
@@ -1,59 +0,0 @@
-/* //device/java/android/android/view/IWindow.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.view;
-
-import android.graphics.Rect;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-
-import android.os.ParcelFileDescriptor;
-
-/**
- * API back to a client window that the Window Manager uses to inform it of
- * interesting things happening.
- *
- * {@hide}
- */
-oneway interface IWindow {
- /**
- * ===== NOTICE =====
- * The first method must remain the first method. Scripts
- * and tools rely on their transaction number to work properly.
- */
-
- /**
- * Invoked by the view server to tell a window to execute the specified
- * command. Any response from the receiver must be sent through the
- * specified file descriptor.
- */
- void executeCommand(String command, String parameters, in ParcelFileDescriptor descriptor);
-
- void resized(int w, int h, in Rect coveredInsets, in Rect visibleInsets,
- boolean reportDraw);
- void dispatchKey(in KeyEvent event);
- void dispatchPointer(in MotionEvent event, long eventTime);
- void dispatchTrackball(in MotionEvent event, long eventTime);
- void dispatchAppVisibility(boolean visible);
- void dispatchGetNewSurface();
-
- /**
- * Tell the window that it is either gaining or losing focus. Keep it up
- * to date on the current state showing navigational focus (touch mode) too.
- */
- void windowFocusChanged(boolean hasFocus, boolean inTouchMode);
-}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
deleted file mode 100644
index a856b24..0000000
--- a/core/java/android/view/IWindowManager.aidl
+++ /dev/null
@@ -1,136 +0,0 @@
-/* //device/java/android/android/view/IWindowManager.aidl
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.view;
-
-import com.android.internal.view.IInputContext;
-import com.android.internal.view.IInputMethodClient;
-
-import android.content.res.Configuration;
-import android.view.IApplicationToken;
-import android.view.IOnKeyguardExitResult;
-import android.view.IRotationWatcher;
-import android.view.IWindowSession;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-
-/**
- * System private interface to the window manager.
- *
- * {@hide}
- */
-interface IWindowManager
-{
- /**
- * ===== NOTICE =====
- * The first three methods must remain the first three methods. Scripts
- * and tools rely on their transaction number to work properly.
- */
- // This is used for debugging
- boolean startViewServer(int port); // Transaction #1
- boolean stopViewServer(); // Transaction #2
- boolean isViewServerRunning(); // Transaction #3
-
- IWindowSession openSession(in IInputMethodClient client,
- in IInputContext inputContext);
- boolean inputMethodClientHasFocus(IInputMethodClient client);
-
- // These can only be called when injecting events to your own window,
- // or by holding the INJECT_EVENTS permission.
- boolean injectKeyEvent(in KeyEvent ev, boolean sync);
- boolean injectPointerEvent(in MotionEvent ev, boolean sync);
- boolean injectTrackballEvent(in MotionEvent ev, boolean sync);
-
- // These can only be called when holding the MANAGE_APP_TOKENS permission.
- void pauseKeyDispatching(IBinder token);
- void resumeKeyDispatching(IBinder token);
- void setEventDispatching(boolean enabled);
- void addAppToken(int addPos, IApplicationToken token,
- int groupId, int requestedOrientation, boolean fullscreen);
- void setAppGroupId(IBinder token, int groupId);
- Configuration updateOrientationFromAppTokens(IBinder freezeThisOneIfNeeded);
- void setAppOrientation(IApplicationToken token, int requestedOrientation);
- int getAppOrientation(IApplicationToken token);
- void setFocusedApp(IBinder token, boolean moveFocusNow);
- void prepareAppTransition(int transit);
- int getPendingAppTransition();
- void executeAppTransition();
- void setAppStartingWindow(IBinder token, String pkg, int theme,
- CharSequence nonLocalizedLabel, int labelRes,
- int icon, IBinder transferFrom, boolean createIfNeeded);
- void setAppWillBeHidden(IBinder token);
- void setAppVisibility(IBinder token, boolean visible);
- void startAppFreezingScreen(IBinder token, int configChanges);
- void stopAppFreezingScreen(IBinder token, boolean force);
- void removeAppToken(IBinder token);
- void moveAppToken(int index, IBinder token);
- void moveAppTokensToTop(in List<IBinder> tokens);
- void moveAppTokensToBottom(in List<IBinder> tokens);
- void addWindowToken(IBinder token, int type);
- void removeWindowToken(IBinder token);
-
- // these require DISABLE_KEYGUARD permission
- void disableKeyguard(IBinder token, String tag);
- void reenableKeyguard(IBinder token);
- void exitKeyguardSecurely(IOnKeyguardExitResult callback);
- boolean inKeyguardRestrictedInputMode();
-
-
- // These can only be called with the SET_ANIMATON_SCALE permission.
- float getAnimationScale(int which);
- float[] getAnimationScales();
- void setAnimationScale(int which, float scale);
- void setAnimationScales(in float[] scales);
-
- // These require the READ_INPUT_STATE permission.
- int getSwitchState(int sw);
- int getSwitchStateForDevice(int devid, int sw);
- int getScancodeState(int sw);
- int getScancodeStateForDevice(int devid, int sw);
- int getKeycodeState(int sw);
- int getKeycodeStateForDevice(int devid, int sw);
-
- // Report whether the hardware supports the given keys; returns true if successful
- boolean hasKeys(in int[] keycodes, inout boolean[] keyExists);
-
- // For testing
- void setInTouchMode(boolean showFocus);
-
- // These can only be called with the SET_ORIENTATION permission.
- /**
- * Change the current screen rotation, constants as per
- * {@link android.view.Surface}.
- * @param rotation the intended rotation.
- * @param alwaysSendConfiguration Flag to force a new configuration to
- * be evaluated. This can be used when there are other parameters in
- * configuration that are changing.
- * {@link android.view.Surface}.
- */
- void setRotation(int rotation, boolean alwaysSendConfiguration);
-
- /**
- * Retrieve the current screen orientation, constants as per
- * {@link android.view.Surface}.
- */
- int getRotation();
-
- /**
- * Watch the rotation of the screen. Returns the current rotation,
- * calls back when it changes.
- */
- int watchRotation(IRotationWatcher watcher);
-}
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
deleted file mode 100644
index 1156856..0000000
--- a/core/java/android/view/IWindowSession.aidl
+++ /dev/null
@@ -1,111 +0,0 @@
-/* //device/java/android/android/view/IWindowSession.aidl
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.view;
-
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.view.IWindow;
-import android.view.MotionEvent;
-import android.view.WindowManager;
-import android.view.Surface;
-
-/**
- * System private per-application interface to the window manager.
- *
- * {@hide}
- */
-interface IWindowSession {
- int add(IWindow window, in WindowManager.LayoutParams attrs,
- in int viewVisibility, out Rect outContentInsets);
- void remove(IWindow window);
-
- /**
- * Change the parameters of a window. You supply the
- * new parameters, it returns the new frame of the window on screen (the
- * position should be ignored) and surface of the window. The surface
- * will be invalid if the window is currently hidden, else you can use it
- * to draw the window's contents.
- *
- * @param window The window being modified.
- * @param attrs If non-null, new attributes to apply to the window.
- * @param requestedWidth The width the window wants to be.
- * @param requestedHeight The height the window wants to be.
- * @param viewVisibility Window root view's visibility.
- * @param insetsPending Set to true if the client will be later giving
- * internal insets; as a result, the window will not impact other window
- * layouts until the insets are given.
- * @param outFrame Rect in which is placed the new position/size on
- * screen.
- * @param outContentInsets Rect in which is placed the offsets from
- * <var>outFrame</var> in which the content of the window should be
- * placed. This can be used to modify the window layout to ensure its
- * contents are visible to the user, taking into account system windows
- * like the status bar or a soft keyboard.
- * @param outVisibleInsets Rect in which is placed the offsets from
- * <var>outFrame</var> in which the window is actually completely visible
- * to the user. This can be used to temporarily scroll the window's
- * contents to make sure the user can see it. This is different than
- * <var>outContentInsets</var> in that these insets change transiently,
- * so complex relayout of the window should not happen based on them.
- * @param outSurface Object in which is placed the new display surface.
- *
- * @return int Result flags: {@link WindowManagerImpl#RELAYOUT_SHOW_FOCUS},
- * {@link WindowManagerImpl#RELAYOUT_FIRST_TIME}.
- */
- int relayout(IWindow window, in WindowManager.LayoutParams attrs,
- int requestedWidth, int requestedHeight, int viewVisibility,
- boolean insetsPending, out Rect outFrame, out Rect outContentInsets,
- out Rect outVisibleInsets, out Surface outSurface);
-
- /**
- * Give the window manager a hint of the part of the window that is
- * completely transparent, allowing it to work with the surface flinger
- * to optimize compositing of this part of the window.
- */
- void setTransparentRegion(IWindow window, in Region region);
-
- /**
- * Tell the window manager about the content and visible insets of the
- * given window, which can be used to adjust the <var>outContentInsets</var>
- * and <var>outVisibleInsets</var> values returned by
- * {@link #relayout relayout()} for windows behind this one.
- *
- * @param touchableInsets Controls which part of the window inside of its
- * frame can receive pointer events, as defined by
- * {@link android.view.ViewTreeObserver.InternalInsetsInfo}.
- */
- void setInsets(IWindow window, int touchableInsets, in Rect contentInsets,
- in Rect visibleInsets);
-
- /**
- * Return the current display size in which the window is being laid out,
- * accounting for screen decorations around it.
- */
- void getDisplayFrame(IWindow window, out Rect outDisplayFrame);
-
- void finishDrawing(IWindow window);
-
- void finishKey(IWindow window);
- MotionEvent getPendingPointerMove(IWindow window);
- MotionEvent getPendingTrackballMove(IWindow window);
-
- void setInTouchMode(boolean showFocus);
- boolean getInTouchMode();
-
- boolean performHapticFeedback(IWindow window, int effectId, boolean always);
-}
diff --git a/core/java/android/view/InflateException.java b/core/java/android/view/InflateException.java
deleted file mode 100644
index 7b39d33..0000000
--- a/core/java/android/view/InflateException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-/**
- * This exception is thrown by an inflater on error conditions.
- */
-public class InflateException extends RuntimeException {
-
- public InflateException() {
- super();
- }
-
- public InflateException(String detailMessage, Throwable throwable) {
- super(detailMessage, throwable);
- }
-
- public InflateException(String detailMessage) {
- super(detailMessage);
- }
-
- public InflateException(Throwable throwable) {
- super(throwable);
- }
-
-}
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
deleted file mode 100644
index 25958aa..0000000
--- a/core/java/android/view/KeyCharacterMap.java
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.text.method.MetaKeyKeyListener;
-import android.util.SparseIntArray;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.util.SparseArray;
-
-import java.lang.Character;
-import java.lang.ref.WeakReference;
-
-public class KeyCharacterMap
-{
- /**
- * The id of the device's primary built in keyboard is always 0.
- */
- public static final int BUILT_IN_KEYBOARD = 0;
-
- /** A numeric (12-key) keyboard. */
- public static final int NUMERIC = 1;
-
- /** A keyboard with all the letters, but with more than one letter
- * per key. */
- public static final int PREDICTIVE = 2;
-
- /** A keyboard with all the letters, and maybe some numbers. */
- public static final int ALPHA = 3;
-
- /**
- * This private-use character is used to trigger Unicode character
- * input by hex digits.
- */
- public static final char HEX_INPUT = '\uEF00';
-
- /**
- * This private-use character is used to bring up a character picker for
- * miscellaneous symbols.
- */
- public static final char PICKER_DIALOG_INPUT = '\uEF01';
-
- private static Object sLock = new Object();
- private static SparseArray<WeakReference<KeyCharacterMap>> sInstances
- = new SparseArray<WeakReference<KeyCharacterMap>>();
-
- public static KeyCharacterMap load(int keyboard)
- {
- synchronized (sLock) {
- KeyCharacterMap result;
- WeakReference<KeyCharacterMap> ref = sInstances.get(keyboard);
- if (ref != null) {
- result = ref.get();
- if (result != null) {
- return result;
- }
- }
- result = new KeyCharacterMap(keyboard);
- sInstances.put(keyboard, new WeakReference<KeyCharacterMap>(result));
- return result;
- }
- }
-
- private KeyCharacterMap(int keyboardDevice)
- {
- mKeyboardDevice = keyboardDevice;
- mPointer = ctor_native(keyboardDevice);
- }
-
- /**
- * <p>
- * Returns the Unicode character that the specified key would produce
- * when the specified meta bits (see {@link MetaKeyKeyListener})
- * were active.
- * </p><p>
- * Returns 0 if the key is not one that is used to type Unicode
- * characters.
- * </p><p>
- * If the return value has bit {@link #COMBINING_ACCENT} set, the
- * key is a "dead key" that should be combined with another to
- * actually produce a character -- see {@link #getDeadChar} --
- * after masking with {@link #COMBINING_ACCENT_MASK}.
- * </p>
- */
- public int get(int keyCode, int meta)
- {
- if ((meta & MetaKeyKeyListener.META_CAP_LOCKED) != 0) {
- meta |= KeyEvent.META_SHIFT_ON;
- }
- if ((meta & MetaKeyKeyListener.META_ALT_LOCKED) != 0) {
- meta |= KeyEvent.META_ALT_ON;
- }
-
- // Ignore caps lock on keys where alt and shift have the same effect.
- if ((meta & MetaKeyKeyListener.META_CAP_LOCKED) != 0) {
- if (get_native(mPointer, keyCode, KeyEvent.META_SHIFT_ON) ==
- get_native(mPointer, keyCode, KeyEvent.META_ALT_ON)) {
- meta &= ~KeyEvent.META_SHIFT_ON;
- }
- }
-
- int ret = get_native(mPointer, keyCode, meta);
- int map = COMBINING.get(ret);
-
- if (map != 0) {
- return map;
- } else {
- return ret;
- }
- }
-
- /**
- * Gets the number or symbol associated with the key. The character value
- * is returned, not the numeric value. If the key is not a number, but is
- * a symbol, the symbol is retuned.
- */
- public char getNumber(int keyCode)
- {
- return getNumber_native(mPointer, keyCode);
- }
-
- /**
- * The same as {@link #getMatch(int,char[],int) getMatch(keyCode, chars, 0)}.
- */
- public char getMatch(int keyCode, char[] chars)
- {
- return getMatch(keyCode, chars, 0);
- }
-
- /**
- * If one of the chars in the array can be generated by keyCode,
- * return the char; otherwise return '\0'.
- * @param keyCode the key code to look at
- * @param chars the characters to try to find
- * @param modifiers the modifier bits to prefer. If any of these bits
- * are set, if there are multiple choices, that could
- * work, the one for this modifier will be set.
- */
- public char getMatch(int keyCode, char[] chars, int modifiers)
- {
- if (chars == null) {
- // catch it here instead of in native
- throw new NullPointerException();
- }
- return getMatch_native(mPointer, keyCode, chars, modifiers);
- }
-
- /**
- * Get the primary character for this key. In other words, the label
- * that is physically printed on it.
- */
- public char getDisplayLabel(int keyCode)
- {
- return getDisplayLabel_native(mPointer, keyCode);
- }
-
- /**
- * Get the character that is produced by putting accent on the character
- * c.
- * For example, getDeadChar('`', 'e') returns &egrave;.
- */
- public static int getDeadChar(int accent, int c)
- {
- return DEAD.get((accent << 16) | c);
- }
-
- public static class KeyData {
- public static final int META_LENGTH = 4;
-
- /**
- * The display label (see {@link #getDisplayLabel}).
- */
- public char displayLabel;
- /**
- * The "number" value (see {@link #getNumber}).
- */
- public char number;
- /**
- * The character that will be generated in various meta states
- * (the same ones used for {@link #get} and defined as
- * {@link KeyEvent#META_SHIFT_ON} and {@link KeyEvent#META_ALT_ON}).
- * <table>
- * <tr><th>Index</th><th align="left">Value</th></tr>
- * <tr><td>0</td><td>no modifiers</td></tr>
- * <tr><td>1</td><td>caps</td></tr>
- * <tr><td>2</td><td>alt</td></tr>
- * <tr><td>3</td><td>caps + alt</td></tr>
- * </table>
- */
- public char[] meta = new char[META_LENGTH];
- }
-
- /**
- * Get the characters conversion data for a given keyCode.
- *
- * @param keyCode the keyCode to look for
- * @param results a {@link KeyData} that will be filled with the results.
- *
- * @return whether the key was mapped or not. If the key was not mapped,
- * results is not modified.
- */
- public boolean getKeyData(int keyCode, KeyData results)
- {
- if (results.meta.length >= KeyData.META_LENGTH) {
- return getKeyData_native(mPointer, keyCode, results);
- } else {
- throw new IndexOutOfBoundsException("results.meta.length must be >= " +
- KeyData.META_LENGTH);
- }
- }
-
- /**
- * Get an array of KeyEvent objects that if put into the input stream
- * could plausibly generate the provided sequence of characters. It is
- * not guaranteed that the sequence is the only way to generate these
- * events or that it is optimal.
- *
- * @return an array of KeyEvent objects, or null if the given char array
- * can not be generated using the current key character map.
- */
- public KeyEvent[] getEvents(char[] chars)
- {
- if (chars == null) {
- throw new NullPointerException();
- }
-
- long[] keys = getEvents_native(mPointer, chars);
- if (keys == null) {
- return null;
- }
-
- // how big should the array be
- int len = keys.length*2;
- int N = keys.length;
- for (int i=0; i<N; i++) {
- int mods = (int)(keys[i] >> 32);
- if ((mods & KeyEvent.META_ALT_ON) != 0) {
- len += 2;
- }
- if ((mods & KeyEvent.META_SHIFT_ON) != 0) {
- len += 2;
- }
- if ((mods & KeyEvent.META_SYM_ON) != 0) {
- len += 2;
- }
- }
-
- // create the events
- KeyEvent[] rv = new KeyEvent[len];
- int index = 0;
- long now = SystemClock.uptimeMillis();
- int device = mKeyboardDevice;
- for (int i=0; i<N; i++) {
- int mods = (int)(keys[i] >> 32);
- int meta = 0;
-
- if ((mods & KeyEvent.META_ALT_ON) != 0) {
- meta |= KeyEvent.META_ALT_ON;
- rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_DOWN,
- KeyEvent.KEYCODE_ALT_LEFT, 0, meta, device, 0);
- index++;
- }
- if ((mods & KeyEvent.META_SHIFT_ON) != 0) {
- meta |= KeyEvent.META_SHIFT_ON;
- rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_DOWN,
- KeyEvent.KEYCODE_SHIFT_LEFT, 0, meta, device, 0);
- index++;
- }
- if ((mods & KeyEvent.META_SYM_ON) != 0) {
- meta |= KeyEvent.META_SYM_ON;
- rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_DOWN,
- KeyEvent.KEYCODE_SYM, 0, meta, device, 0);
- index++;
- }
-
- int key = (int)(keys[i]);
- rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_DOWN,
- key, 0, meta, device, 0);
- index++;
- rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_UP,
- key, 0, meta, device, 0);
- index++;
-
- if ((mods & KeyEvent.META_ALT_ON) != 0) {
- meta &= ~KeyEvent.META_ALT_ON;
- rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_UP,
- KeyEvent.KEYCODE_ALT_LEFT, 0, meta, device, 0);
- index++;
- }
- if ((mods & KeyEvent.META_SHIFT_ON) != 0) {
- meta &= ~KeyEvent.META_SHIFT_ON;
- rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_UP,
- KeyEvent.KEYCODE_SHIFT_LEFT, 0, meta, device, 0);
- index++;
- }
- if ((mods & KeyEvent.META_SYM_ON) != 0) {
- meta &= ~KeyEvent.META_SYM_ON;
- rv[index] = new KeyEvent(now, now, KeyEvent.ACTION_UP,
- KeyEvent.KEYCODE_SYM, 0, meta, device, 0);
- index++;
- }
- }
-
- return rv;
- }
-
- /**
- * Does this character key produce a glyph?
- */
- public boolean isPrintingKey(int keyCode)
- {
- int type = Character.getType(get(keyCode, 0));
-
- switch (type)
- {
- case Character.SPACE_SEPARATOR:
- case Character.LINE_SEPARATOR:
- case Character.PARAGRAPH_SEPARATOR:
- case Character.CONTROL:
- case Character.FORMAT:
- return false;
- default:
- return true;
- }
- }
-
- protected void finalize() throws Throwable
- {
- dtor_native(mPointer);
- }
-
- /**
- * Returns {@link #NUMERIC}, {@link #PREDICTIVE} or {@link #ALPHA}.
- */
- public int getKeyboardType()
- {
- return getKeyboardType_native(mPointer);
- }
-
- /**
- * Queries the framework about whether any physical keys exist on the
- * device that are capable of producing the given key codes.
- */
- public static boolean deviceHasKey(int keyCode) {
- int[] codeArray = new int[1];
- codeArray[0] = keyCode;
- boolean[] ret = deviceHasKeys(codeArray);
- return ret[0];
- }
-
- public static boolean[] deviceHasKeys(int[] keyCodes) {
- boolean[] ret = new boolean[keyCodes.length];
- IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
- try {
- wm.hasKeys(keyCodes, ret);
- } catch (RemoteException e) {
- // no fallback; just return the empty array
- }
- return ret;
- }
-
- private int mPointer;
- private int mKeyboardDevice;
-
- private static native int ctor_native(int id);
- private static native void dtor_native(int ptr);
- private static native char get_native(int ptr, int keycode,
- int meta);
- private static native char getNumber_native(int ptr, int keycode);
- private static native char getMatch_native(int ptr, int keycode,
- char[] chars, int modifiers);
- private static native char getDisplayLabel_native(int ptr, int keycode);
- private static native boolean getKeyData_native(int ptr, int keycode,
- KeyData results);
- private static native int getKeyboardType_native(int ptr);
- private static native long[] getEvents_native(int ptr, char[] str);
-
- /**
- * Maps Unicode combining diacritical to display-form dead key
- * (display character shifted left 16 bits).
- */
- private static SparseIntArray COMBINING = new SparseIntArray();
-
- /**
- * Maps combinations of (display-form) dead key and second character
- * to combined output character.
- */
- private static SparseIntArray DEAD = new SparseIntArray();
-
- /*
- * TODO: Change the table format to support full 21-bit-wide
- * accent characters and combined characters if ever necessary.
- */
- private static final int ACUTE = '\u00B4' << 16;
- private static final int GRAVE = '`' << 16;
- private static final int CIRCUMFLEX = '^' << 16;
- private static final int TILDE = '~' << 16;
- private static final int UMLAUT = '\u00A8' << 16;
-
- /*
- * This bit will be set in the return value of {@link #get(int, int)} if the
- * key is a "dead key."
- */
- public static final int COMBINING_ACCENT = 0x80000000;
- /**
- * Mask the return value from {@link #get(int, int)} with this value to get
- * a printable representation of the accent character of a "dead key."
- */
- public static final int COMBINING_ACCENT_MASK = 0x7FFFFFFF;
-
- static {
- COMBINING.put('\u0300', (GRAVE >> 16) | COMBINING_ACCENT);
- COMBINING.put('\u0301', (ACUTE >> 16) | COMBINING_ACCENT);
- COMBINING.put('\u0302', (CIRCUMFLEX >> 16) | COMBINING_ACCENT);
- COMBINING.put('\u0303', (TILDE >> 16) | COMBINING_ACCENT);
- COMBINING.put('\u0308', (UMLAUT >> 16) | COMBINING_ACCENT);
-
- DEAD.put(ACUTE | 'A', '\u00C1');
- DEAD.put(ACUTE | 'C', '\u0106');
- DEAD.put(ACUTE | 'E', '\u00C9');
- DEAD.put(ACUTE | 'G', '\u01F4');
- DEAD.put(ACUTE | 'I', '\u00CD');
- DEAD.put(ACUTE | 'K', '\u1E30');
- DEAD.put(ACUTE | 'L', '\u0139');
- DEAD.put(ACUTE | 'M', '\u1E3E');
- DEAD.put(ACUTE | 'N', '\u0143');
- DEAD.put(ACUTE | 'O', '\u00D3');
- DEAD.put(ACUTE | 'P', '\u1E54');
- DEAD.put(ACUTE | 'R', '\u0154');
- DEAD.put(ACUTE | 'S', '\u015A');
- DEAD.put(ACUTE | 'U', '\u00DA');
- DEAD.put(ACUTE | 'W', '\u1E82');
- DEAD.put(ACUTE | 'Y', '\u00DD');
- DEAD.put(ACUTE | 'Z', '\u0179');
- DEAD.put(ACUTE | 'a', '\u00E1');
- DEAD.put(ACUTE | 'c', '\u0107');
- DEAD.put(ACUTE | 'e', '\u00E9');
- DEAD.put(ACUTE | 'g', '\u01F5');
- DEAD.put(ACUTE | 'i', '\u00ED');
- DEAD.put(ACUTE | 'k', '\u1E31');
- DEAD.put(ACUTE | 'l', '\u013A');
- DEAD.put(ACUTE | 'm', '\u1E3F');
- DEAD.put(ACUTE | 'n', '\u0144');
- DEAD.put(ACUTE | 'o', '\u00F3');
- DEAD.put(ACUTE | 'p', '\u1E55');
- DEAD.put(ACUTE | 'r', '\u0155');
- DEAD.put(ACUTE | 's', '\u015B');
- DEAD.put(ACUTE | 'u', '\u00FA');
- DEAD.put(ACUTE | 'w', '\u1E83');
- DEAD.put(ACUTE | 'y', '\u00FD');
- DEAD.put(ACUTE | 'z', '\u017A');
- DEAD.put(CIRCUMFLEX | 'A', '\u00C2');
- DEAD.put(CIRCUMFLEX | 'C', '\u0108');
- DEAD.put(CIRCUMFLEX | 'E', '\u00CA');
- DEAD.put(CIRCUMFLEX | 'G', '\u011C');
- DEAD.put(CIRCUMFLEX | 'H', '\u0124');
- DEAD.put(CIRCUMFLEX | 'I', '\u00CE');
- DEAD.put(CIRCUMFLEX | 'J', '\u0134');
- DEAD.put(CIRCUMFLEX | 'O', '\u00D4');
- DEAD.put(CIRCUMFLEX | 'S', '\u015C');
- DEAD.put(CIRCUMFLEX | 'U', '\u00DB');
- DEAD.put(CIRCUMFLEX | 'W', '\u0174');
- DEAD.put(CIRCUMFLEX | 'Y', '\u0176');
- DEAD.put(CIRCUMFLEX | 'Z', '\u1E90');
- DEAD.put(CIRCUMFLEX | 'a', '\u00E2');
- DEAD.put(CIRCUMFLEX | 'c', '\u0109');
- DEAD.put(CIRCUMFLEX | 'e', '\u00EA');
- DEAD.put(CIRCUMFLEX | 'g', '\u011D');
- DEAD.put(CIRCUMFLEX | 'h', '\u0125');
- DEAD.put(CIRCUMFLEX | 'i', '\u00EE');
- DEAD.put(CIRCUMFLEX | 'j', '\u0135');
- DEAD.put(CIRCUMFLEX | 'o', '\u00F4');
- DEAD.put(CIRCUMFLEX | 's', '\u015D');
- DEAD.put(CIRCUMFLEX | 'u', '\u00FB');
- DEAD.put(CIRCUMFLEX | 'w', '\u0175');
- DEAD.put(CIRCUMFLEX | 'y', '\u0177');
- DEAD.put(CIRCUMFLEX | 'z', '\u1E91');
- DEAD.put(GRAVE | 'A', '\u00C0');
- DEAD.put(GRAVE | 'E', '\u00C8');
- DEAD.put(GRAVE | 'I', '\u00CC');
- DEAD.put(GRAVE | 'N', '\u01F8');
- DEAD.put(GRAVE | 'O', '\u00D2');
- DEAD.put(GRAVE | 'U', '\u00D9');
- DEAD.put(GRAVE | 'W', '\u1E80');
- DEAD.put(GRAVE | 'Y', '\u1EF2');
- DEAD.put(GRAVE | 'a', '\u00E0');
- DEAD.put(GRAVE | 'e', '\u00E8');
- DEAD.put(GRAVE | 'i', '\u00EC');
- DEAD.put(GRAVE | 'n', '\u01F9');
- DEAD.put(GRAVE | 'o', '\u00F2');
- DEAD.put(GRAVE | 'u', '\u00F9');
- DEAD.put(GRAVE | 'w', '\u1E81');
- DEAD.put(GRAVE | 'y', '\u1EF3');
- DEAD.put(TILDE | 'A', '\u00C3');
- DEAD.put(TILDE | 'E', '\u1EBC');
- DEAD.put(TILDE | 'I', '\u0128');
- DEAD.put(TILDE | 'N', '\u00D1');
- DEAD.put(TILDE | 'O', '\u00D5');
- DEAD.put(TILDE | 'U', '\u0168');
- DEAD.put(TILDE | 'V', '\u1E7C');
- DEAD.put(TILDE | 'Y', '\u1EF8');
- DEAD.put(TILDE | 'a', '\u00E3');
- DEAD.put(TILDE | 'e', '\u1EBD');
- DEAD.put(TILDE | 'i', '\u0129');
- DEAD.put(TILDE | 'n', '\u00F1');
- DEAD.put(TILDE | 'o', '\u00F5');
- DEAD.put(TILDE | 'u', '\u0169');
- DEAD.put(TILDE | 'v', '\u1E7D');
- DEAD.put(TILDE | 'y', '\u1EF9');
- DEAD.put(UMLAUT | 'A', '\u00C4');
- DEAD.put(UMLAUT | 'E', '\u00CB');
- DEAD.put(UMLAUT | 'H', '\u1E26');
- DEAD.put(UMLAUT | 'I', '\u00CF');
- DEAD.put(UMLAUT | 'O', '\u00D6');
- DEAD.put(UMLAUT | 'U', '\u00DC');
- DEAD.put(UMLAUT | 'W', '\u1E84');
- DEAD.put(UMLAUT | 'X', '\u1E8C');
- DEAD.put(UMLAUT | 'Y', '\u0178');
- DEAD.put(UMLAUT | 'a', '\u00E4');
- DEAD.put(UMLAUT | 'e', '\u00EB');
- DEAD.put(UMLAUT | 'h', '\u1E27');
- DEAD.put(UMLAUT | 'i', '\u00EF');
- DEAD.put(UMLAUT | 'o', '\u00F6');
- DEAD.put(UMLAUT | 't', '\u1E97');
- DEAD.put(UMLAUT | 'u', '\u00FC');
- DEAD.put(UMLAUT | 'w', '\u1E85');
- DEAD.put(UMLAUT | 'x', '\u1E8D');
- DEAD.put(UMLAUT | 'y', '\u00FF');
- }
-}
diff --git a/core/java/android/view/KeyEvent.aidl b/core/java/android/view/KeyEvent.aidl
deleted file mode 100644
index dc15ecf..0000000
--- a/core/java/android/view/KeyEvent.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android.view.KeyEvent.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.view;
-
-parcelable KeyEvent;
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
deleted file mode 100644
index d6ea91c..0000000
--- a/core/java/android/view/KeyEvent.java
+++ /dev/null
@@ -1,880 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.view.KeyCharacterMap;
-import android.view.KeyCharacterMap.KeyData;
-
-/**
- * Contains constants for key events.
- */
-public class KeyEvent implements Parcelable {
- // key codes
- public static final int KEYCODE_UNKNOWN = 0;
- public static final int KEYCODE_SOFT_LEFT = 1;
- public static final int KEYCODE_SOFT_RIGHT = 2;
- public static final int KEYCODE_HOME = 3;
- public static final int KEYCODE_BACK = 4;
- public static final int KEYCODE_CALL = 5;
- public static final int KEYCODE_ENDCALL = 6;
- public static final int KEYCODE_0 = 7;
- public static final int KEYCODE_1 = 8;
- public static final int KEYCODE_2 = 9;
- public static final int KEYCODE_3 = 10;
- public static final int KEYCODE_4 = 11;
- public static final int KEYCODE_5 = 12;
- public static final int KEYCODE_6 = 13;
- public static final int KEYCODE_7 = 14;
- public static final int KEYCODE_8 = 15;
- public static final int KEYCODE_9 = 16;
- public static final int KEYCODE_STAR = 17;
- public static final int KEYCODE_POUND = 18;
- public static final int KEYCODE_DPAD_UP = 19;
- public static final int KEYCODE_DPAD_DOWN = 20;
- public static final int KEYCODE_DPAD_LEFT = 21;
- public static final int KEYCODE_DPAD_RIGHT = 22;
- public static final int KEYCODE_DPAD_CENTER = 23;
- public static final int KEYCODE_VOLUME_UP = 24;
- public static final int KEYCODE_VOLUME_DOWN = 25;
- public static final int KEYCODE_POWER = 26;
- public static final int KEYCODE_CAMERA = 27;
- public static final int KEYCODE_CLEAR = 28;
- public static final int KEYCODE_A = 29;
- public static final int KEYCODE_B = 30;
- public static final int KEYCODE_C = 31;
- public static final int KEYCODE_D = 32;
- public static final int KEYCODE_E = 33;
- public static final int KEYCODE_F = 34;
- public static final int KEYCODE_G = 35;
- public static final int KEYCODE_H = 36;
- public static final int KEYCODE_I = 37;
- public static final int KEYCODE_J = 38;
- public static final int KEYCODE_K = 39;
- public static final int KEYCODE_L = 40;
- public static final int KEYCODE_M = 41;
- public static final int KEYCODE_N = 42;
- public static final int KEYCODE_O = 43;
- public static final int KEYCODE_P = 44;
- public static final int KEYCODE_Q = 45;
- public static final int KEYCODE_R = 46;
- public static final int KEYCODE_S = 47;
- public static final int KEYCODE_T = 48;
- public static final int KEYCODE_U = 49;
- public static final int KEYCODE_V = 50;
- public static final int KEYCODE_W = 51;
- public static final int KEYCODE_X = 52;
- public static final int KEYCODE_Y = 53;
- public static final int KEYCODE_Z = 54;
- public static final int KEYCODE_COMMA = 55;
- public static final int KEYCODE_PERIOD = 56;
- public static final int KEYCODE_ALT_LEFT = 57;
- public static final int KEYCODE_ALT_RIGHT = 58;
- public static final int KEYCODE_SHIFT_LEFT = 59;
- public static final int KEYCODE_SHIFT_RIGHT = 60;
- public static final int KEYCODE_TAB = 61;
- public static final int KEYCODE_SPACE = 62;
- public static final int KEYCODE_SYM = 63;
- public static final int KEYCODE_EXPLORER = 64;
- public static final int KEYCODE_ENVELOPE = 65;
- public static final int KEYCODE_ENTER = 66;
- public static final int KEYCODE_DEL = 67;
- public static final int KEYCODE_GRAVE = 68;
- public static final int KEYCODE_MINUS = 69;
- public static final int KEYCODE_EQUALS = 70;
- public static final int KEYCODE_LEFT_BRACKET = 71;
- public static final int KEYCODE_RIGHT_BRACKET = 72;
- public static final int KEYCODE_BACKSLASH = 73;
- public static final int KEYCODE_SEMICOLON = 74;
- public static final int KEYCODE_APOSTROPHE = 75;
- public static final int KEYCODE_SLASH = 76;
- public static final int KEYCODE_AT = 77;
- public static final int KEYCODE_NUM = 78;
- public static final int KEYCODE_HEADSETHOOK = 79;
- public static final int KEYCODE_FOCUS = 80; // *Camera* focus
- public static final int KEYCODE_PLUS = 81;
- public static final int KEYCODE_MENU = 82;
- public static final int KEYCODE_NOTIFICATION = 83;
- public static final int KEYCODE_SEARCH = 84;
- public static final int KEYCODE_PLAYPAUSE = 85;
- public static final int KEYCODE_STOP = 86;
- public static final int KEYCODE_NEXTSONG = 87;
- public static final int KEYCODE_PREVIOUSSONG = 88;
- public static final int KEYCODE_REWIND = 89;
- public static final int KEYCODE_FORWARD = 90;
- public static final int KEYCODE_MUTE = 91;
- private static final int LAST_KEYCODE = KEYCODE_MUTE;
-
- // NOTE: If you add a new keycode here you must also add it to:
- // isSystem()
- // frameworks/base/include/ui/KeycodeLabels.h
- // tools/puppet_master/PuppetMaster/nav_keys.py
- // frameworks/base/core/res/res/values/attrs.xml
- // commands/monkey/Monkey.java
- // emulator?
-
- /**
- * @deprecated There are now more than MAX_KEYCODE keycodes.
- * Use {@link #getMaxKeyCode()} instead.
- */
- @Deprecated
- public static final int MAX_KEYCODE = 84;
-
- /**
- * {@link #getAction} value: the key has been pressed down.
- */
- public static final int ACTION_DOWN = 0;
- /**
- * {@link #getAction} value: the key has been released.
- */
- public static final int ACTION_UP = 1;
- /**
- * {@link #getAction} value: multiple duplicate key events have
- * occurred in a row, or a complex string is being delivered. If the
- * key code is not {#link {@link #KEYCODE_UNKNOWN} then the
- * {#link {@link #getRepeatCount()} method returns the number of times
- * the given key code should be executed.
- * Otherwise, if the key code {@link #KEYCODE_UNKNOWN}, then
- * this is a sequence of characters as returned by {@link #getCharacters}.
- */
- public static final int ACTION_MULTIPLE = 2;
-
- /**
- * <p>This mask is used to check whether one of the ALT meta keys is pressed.</p>
- *
- * @see #isAltPressed()
- * @see #getMetaState()
- * @see #KEYCODE_ALT_LEFT
- * @see #KEYCODE_ALT_RIGHT
- */
- public static final int META_ALT_ON = 0x02;
-
- /**
- * <p>This mask is used to check whether the left ALT meta key is pressed.</p>
- *
- * @see #isAltPressed()
- * @see #getMetaState()
- * @see #KEYCODE_ALT_LEFT
- */
- public static final int META_ALT_LEFT_ON = 0x10;
-
- /**
- * <p>This mask is used to check whether the right the ALT meta key is pressed.</p>
- *
- * @see #isAltPressed()
- * @see #getMetaState()
- * @see #KEYCODE_ALT_RIGHT
- */
- public static final int META_ALT_RIGHT_ON = 0x20;
-
- /**
- * <p>This mask is used to check whether one of the SHIFT meta keys is pressed.</p>
- *
- * @see #isShiftPressed()
- * @see #getMetaState()
- * @see #KEYCODE_SHIFT_LEFT
- * @see #KEYCODE_SHIFT_RIGHT
- */
- public static final int META_SHIFT_ON = 0x1;
-
- /**
- * <p>This mask is used to check whether the left SHIFT meta key is pressed.</p>
- *
- * @see #isShiftPressed()
- * @see #getMetaState()
- * @see #KEYCODE_SHIFT_LEFT
- */
- public static final int META_SHIFT_LEFT_ON = 0x40;
-
- /**
- * <p>This mask is used to check whether the right SHIFT meta key is pressed.</p>
- *
- * @see #isShiftPressed()
- * @see #getMetaState()
- * @see #KEYCODE_SHIFT_RIGHT
- */
- public static final int META_SHIFT_RIGHT_ON = 0x80;
-
- /**
- * <p>This mask is used to check whether the SYM meta key is pressed.</p>
- *
- * @see #isSymPressed()
- * @see #getMetaState()
- */
- public static final int META_SYM_ON = 0x4;
-
- /**
- * This mask is set if the device woke because of this key event.
- */
- public static final int FLAG_WOKE_HERE = 0x1;
-
- /**
- * This mask is set if the key event was generated by a software keyboard.
- */
- public static final int FLAG_SOFT_KEYBOARD = 0x2;
-
- /**
- * Returns the maximum keycode.
- */
- public static int getMaxKeyCode() {
- return LAST_KEYCODE;
- }
-
- /**
- * Get the character that is produced by putting accent on the character
- * c.
- * For example, getDeadChar('`', 'e') returns &egrave;.
- */
- public static int getDeadChar(int accent, int c) {
- return KeyCharacterMap.getDeadChar(accent, c);
- }
-
- private int mMetaState;
- private int mAction;
- private int mKeyCode;
- private int mScancode;
- private int mRepeatCount;
- private int mDeviceId;
- private int mFlags;
- private long mDownTime;
- private long mEventTime;
- private String mCharacters;
-
- public interface Callback {
- /**
- * Called when a key down event has occurred.
- *
- * @param keyCode The value in event.getKeyCode().
- * @param event Description of the key event.
- *
- * @return If you handled the event, return true. If you want to allow
- * the event to be handled by the next receiver, return false.
- */
- boolean onKeyDown(int keyCode, KeyEvent event);
-
- /**
- * Called when a key up event has occurred.
- *
- * @param keyCode The value in event.getKeyCode().
- * @param event Description of the key event.
- *
- * @return If you handled the event, return true. If you want to allow
- * the event to be handled by the next receiver, return false.
- */
- boolean onKeyUp(int keyCode, KeyEvent event);
-
- /**
- * Called when multiple down/up pairs of the same key have occurred
- * in a row.
- *
- * @param keyCode The value in event.getKeyCode().
- * @param count Number of pairs as returned by event.getRepeatCount().
- * @param event Description of the key event.
- *
- * @return If you handled the event, return true. If you want to allow
- * the event to be handled by the next receiver, return false.
- */
- boolean onKeyMultiple(int keyCode, int count, KeyEvent event);
- }
-
- /**
- * Create a new key event.
- *
- * @param action Action code: either {@link #ACTION_DOWN},
- * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}.
- * @param code The key code.
- */
- public KeyEvent(int action, int code) {
- mAction = action;
- mKeyCode = code;
- mRepeatCount = 0;
- }
-
- /**
- * Create a new key event.
- *
- * @param downTime The time (in {@link android.os.SystemClock#uptimeMillis})
- * at which this key code originally went down.
- * @param eventTime The time (in {@link android.os.SystemClock#uptimeMillis})
- * at which this event happened.
- * @param action Action code: either {@link #ACTION_DOWN},
- * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}.
- * @param code The key code.
- * @param repeat A repeat count for down events (> 0 if this is after the
- * initial down) or event count for multiple events.
- */
- public KeyEvent(long downTime, long eventTime, int action,
- int code, int repeat) {
- mDownTime = downTime;
- mEventTime = eventTime;
- mAction = action;
- mKeyCode = code;
- mRepeatCount = repeat;
- }
-
- /**
- * Create a new key event.
- *
- * @param downTime The time (in {@link android.os.SystemClock#uptimeMillis})
- * at which this key code originally went down.
- * @param eventTime The time (in {@link android.os.SystemClock#uptimeMillis})
- * at which this event happened.
- * @param action Action code: either {@link #ACTION_DOWN},
- * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}.
- * @param code The key code.
- * @param repeat A repeat count for down events (> 0 if this is after the
- * initial down) or event count for multiple events.
- * @param metaState Flags indicating which meta keys are currently pressed.
- */
- public KeyEvent(long downTime, long eventTime, int action,
- int code, int repeat, int metaState) {
- mDownTime = downTime;
- mEventTime = eventTime;
- mAction = action;
- mKeyCode = code;
- mRepeatCount = repeat;
- mMetaState = metaState;
- }
-
- /**
- * Create a new key event.
- *
- * @param downTime The time (in {@link android.os.SystemClock#uptimeMillis})
- * at which this key code originally went down.
- * @param eventTime The time (in {@link android.os.SystemClock#uptimeMillis})
- * at which this event happened.
- * @param action Action code: either {@link #ACTION_DOWN},
- * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}.
- * @param code The key code.
- * @param repeat A repeat count for down events (> 0 if this is after the
- * initial down) or event count for multiple events.
- * @param metaState Flags indicating which meta keys are currently pressed.
- * @param device The device ID that generated the key event.
- * @param scancode Raw device scan code of the event.
- */
- public KeyEvent(long downTime, long eventTime, int action,
- int code, int repeat, int metaState,
- int device, int scancode) {
- mDownTime = downTime;
- mEventTime = eventTime;
- mAction = action;
- mKeyCode = code;
- mRepeatCount = repeat;
- mMetaState = metaState;
- mDeviceId = device;
- mScancode = scancode;
- }
-
- /**
- * Create a new key event.
- *
- * @param downTime The time (in {@link android.os.SystemClock#uptimeMillis})
- * at which this key code originally went down.
- * @param eventTime The time (in {@link android.os.SystemClock#uptimeMillis})
- * at which this event happened.
- * @param action Action code: either {@link #ACTION_DOWN},
- * {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}.
- * @param code The key code.
- * @param repeat A repeat count for down events (> 0 if this is after the
- * initial down) or event count for multiple events.
- * @param metaState Flags indicating which meta keys are currently pressed.
- * @param device The device ID that generated the key event.
- * @param scancode Raw device scan code of the event.
- * @param flags The flags for this key event
- */
- public KeyEvent(long downTime, long eventTime, int action,
- int code, int repeat, int metaState,
- int device, int scancode, int flags) {
- mDownTime = downTime;
- mEventTime = eventTime;
- mAction = action;
- mKeyCode = code;
- mRepeatCount = repeat;
- mMetaState = metaState;
- mDeviceId = device;
- mScancode = scancode;
- mFlags = flags;
- }
-
- /**
- * Create a new key event for a string of characters. The key code,
- * action, and repeat could will automatically be set to
- * {@link #KEYCODE_UNKNOWN}, {@link #ACTION_MULTIPLE}, and 0 for you.
- *
- * @param time The time (in {@link android.os.SystemClock#uptimeMillis})
- * at which this event occured.
- * @param characters The string of characters.
- * @param device The device ID that generated the key event.
- * @param flags The flags for this key event
- */
- public KeyEvent(long time, String characters, int device, int flags) {
- mDownTime = time;
- mEventTime = time;
- mCharacters = characters;
- mAction = ACTION_MULTIPLE;
- mKeyCode = KEYCODE_UNKNOWN;
- mRepeatCount = 0;
- mDeviceId = device;
- mFlags = flags;
- }
-
- /**
- * Copy an existing key event, modifying its time and repeat count.
- *
- * @param origEvent The existing event to be copied.
- * @param eventTime The new event time
- * (in {@link android.os.SystemClock#uptimeMillis}) of the event.
- * @param newRepeat The new repeat count of the event.
- */
- public KeyEvent(KeyEvent origEvent, long eventTime, int newRepeat) {
- mDownTime = origEvent.mDownTime;
- mEventTime = eventTime;
- mAction = origEvent.mAction;
- mKeyCode = origEvent.mKeyCode;
- mRepeatCount = newRepeat;
- mMetaState = origEvent.mMetaState;
- mDeviceId = origEvent.mDeviceId;
- mScancode = origEvent.mScancode;
- mFlags = origEvent.mFlags;
- mCharacters = origEvent.mCharacters;
- }
-
- /**
- * Copy an existing key event, modifying its action.
- *
- * @param origEvent The existing event to be copied.
- * @param action The new action code of the event.
- */
- public KeyEvent(KeyEvent origEvent, int action) {
- mDownTime = origEvent.mDownTime;
- mEventTime = origEvent.mEventTime;
- mAction = action;
- mKeyCode = origEvent.mKeyCode;
- mRepeatCount = origEvent.mRepeatCount;
- mMetaState = origEvent.mMetaState;
- mDeviceId = origEvent.mDeviceId;
- mScancode = origEvent.mScancode;
- mFlags = origEvent.mFlags;
- // Don't copy mCharacters, since one way or the other we'll lose it
- // when changing the action.
- }
-
- /**
- * Don't use in new code, instead explicitly check
- * {@link #getAction()}.
- *
- * @return If the action is ACTION_DOWN, returns true; else false.
- *
- * @deprecated
- * @hide
- */
- @Deprecated public final boolean isDown() {
- return mAction == ACTION_DOWN;
- }
-
- /**
- * Is this a system key? System keys can not be used for menu shortcuts.
- *
- * TODO: this information should come from a table somewhere.
- * TODO: should the dpad keys be here? arguably, because they also shouldn't be menu shortcuts
- */
- public final boolean isSystem() {
- switch (mKeyCode) {
- case KEYCODE_MENU:
- case KEYCODE_SOFT_RIGHT:
- case KEYCODE_HOME:
- case KEYCODE_BACK:
- case KEYCODE_CALL:
- case KEYCODE_ENDCALL:
- case KEYCODE_VOLUME_UP:
- case KEYCODE_VOLUME_DOWN:
- case KEYCODE_MUTE:
- case KEYCODE_POWER:
- case KEYCODE_HEADSETHOOK:
- case KEYCODE_PLAYPAUSE:
- case KEYCODE_STOP:
- case KEYCODE_NEXTSONG:
- case KEYCODE_PREVIOUSSONG:
- case KEYCODE_REWIND:
- case KEYCODE_FORWARD:
- case KEYCODE_CAMERA:
- case KEYCODE_FOCUS:
- case KEYCODE_SEARCH:
- return true;
- default:
- return false;
- }
- }
-
-
- /**
- * <p>Returns the state of the meta keys.</p>
- *
- * @return an integer in which each bit set to 1 represents a pressed
- * meta key
- *
- * @see #isAltPressed()
- * @see #isShiftPressed()
- * @see #isSymPressed()
- * @see #META_ALT_ON
- * @see #META_SHIFT_ON
- * @see #META_SYM_ON
- */
- public final int getMetaState() {
- return mMetaState;
- }
-
- /**
- * Returns the flags for this key event.
- *
- * @see #FLAG_WOKE_HERE
- */
- public final int getFlags() {
- return mFlags;
- }
-
- /**
- * Returns true if this key code is a modifier key.
- *
- * @return whether the provided keyCode is one of
- * {@link #KEYCODE_SHIFT_LEFT} {@link #KEYCODE_SHIFT_RIGHT},
- * {@link #KEYCODE_ALT_LEFT}, {@link #KEYCODE_ALT_RIGHT}
- * or {@link #KEYCODE_SYM}.
- */
- public static boolean isModifierKey(int keyCode) {
- return keyCode == KEYCODE_SHIFT_LEFT || keyCode == KEYCODE_SHIFT_RIGHT
- || keyCode == KEYCODE_ALT_LEFT || keyCode == KEYCODE_ALT_RIGHT
- || keyCode == KEYCODE_SYM;
- }
-
- /**
- * <p>Returns the pressed state of the ALT meta key.</p>
- *
- * @return true if the ALT key is pressed, false otherwise
- *
- * @see #KEYCODE_ALT_LEFT
- * @see #KEYCODE_ALT_RIGHT
- * @see #META_ALT_ON
- */
- public final boolean isAltPressed() {
- return (mMetaState & META_ALT_ON) != 0;
- }
-
- /**
- * <p>Returns the pressed state of the SHIFT meta key.</p>
- *
- * @return true if the SHIFT key is pressed, false otherwise
- *
- * @see #KEYCODE_SHIFT_LEFT
- * @see #KEYCODE_SHIFT_RIGHT
- * @see #META_SHIFT_ON
- */
- public final boolean isShiftPressed() {
- return (mMetaState & META_SHIFT_ON) != 0;
- }
-
- /**
- * <p>Returns the pressed state of the SYM meta key.</p>
- *
- * @return true if the SYM key is pressed, false otherwise
- *
- * @see #KEYCODE_SYM
- * @see #META_SYM_ON
- */
- public final boolean isSymPressed() {
- return (mMetaState & META_SYM_ON) != 0;
- }
-
- /**
- * Retrieve the action of this key event. May be either
- * {@link #ACTION_DOWN}, {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}.
- *
- * @return The event action: ACTION_DOWN, ACTION_UP, or ACTION_MULTIPLE.
- */
- public final int getAction() {
- return mAction;
- }
-
- /**
- * Retrieve the key code of the key event. This is the physical key that
- * was pressed, <em>not</em> the Unicode character.
- *
- * @return The key code of the event.
- */
- public final int getKeyCode() {
- return mKeyCode;
- }
-
- /**
- * For the special case of a {@link #ACTION_MULTIPLE} event with key
- * code of {@link #KEYCODE_UNKNOWN}, this is a raw string of characters
- * associated with the event. In all other cases it is null.
- *
- * @return Returns a String of 1 or more characters associated with
- * the event.
- */
- public final String getCharacters() {
- return mCharacters;
- }
-
- /**
- * Retrieve the hardware key id of this key event. These values are not
- * reliable and vary from device to device.
- *
- * {@more}
- * Mostly this is here for debugging purposes.
- */
- public final int getScanCode() {
- return mScancode;
- }
-
- /**
- * Retrieve the repeat count of the event. For both key up and key down
- * events, this is the number of times the key has repeated with the first
- * down starting at 0 and counting up from there. For multiple key
- * events, this is the number of down/up pairs that have occurred.
- *
- * @return The number of times the key has repeated.
- */
- public final int getRepeatCount() {
- return mRepeatCount;
- }
-
- /**
- * Retrieve the time of the most recent key down event,
- * in the {@link android.os.SystemClock#uptimeMillis} time base. If this
- * is a down event, this will be the same as {@link #getEventTime()}.
- * Note that when chording keys, this value is the down time of the
- * most recently pressed key, which may <em>not</em> be the same physical
- * key of this event.
- *
- * @return Returns the most recent key down time, in the
- * {@link android.os.SystemClock#uptimeMillis} time base
- */
- public final long getDownTime() {
- return mDownTime;
- }
-
- /**
- * Retrieve the time this event occurred,
- * in the {@link android.os.SystemClock#uptimeMillis} time base.
- *
- * @return Returns the time this event occurred,
- * in the {@link android.os.SystemClock#uptimeMillis} time base.
- */
- public final long getEventTime() {
- return mEventTime;
- }
-
- /**
- * Return the id for the keyboard that this event came from. A device
- * id of 0 indicates the event didn't come from a physical device and
- * maps to the default keymap. The other numbers are arbitrary and
- * you shouldn't depend on the values.
- *
- * @see KeyCharacterMap#load
- */
- public final int getDeviceId() {
- return mDeviceId;
- }
-
- /**
- * Renamed to {@link #getDeviceId}.
- *
- * @hide
- * @deprecated
- */
- public final int getKeyboardDevice() {
- return mDeviceId;
- }
-
- /**
- * Get the primary character for this key. In other words, the label
- * that is physically printed on it.
- */
- public char getDisplayLabel() {
- return KeyCharacterMap.load(mDeviceId).getDisplayLabel(mKeyCode);
- }
-
- /**
- * <p>
- * Returns the Unicode character that the key would produce.
- * </p><p>
- * Returns 0 if the key is not one that is used to type Unicode
- * characters.
- * </p><p>
- * If the return value has bit
- * {@link KeyCharacterMap#COMBINING_ACCENT}
- * set, the key is a "dead key" that should be combined with another to
- * actually produce a character -- see {@link #getDeadChar} --
- * after masking with
- * {@link KeyCharacterMap#COMBINING_ACCENT_MASK}.
- * </p>
- */
- public int getUnicodeChar() {
- return getUnicodeChar(mMetaState);
- }
-
- /**
- * <p>
- * Returns the Unicode character that the key would produce.
- * </p><p>
- * Returns 0 if the key is not one that is used to type Unicode
- * characters.
- * </p><p>
- * If the return value has bit
- * {@link KeyCharacterMap#COMBINING_ACCENT}
- * set, the key is a "dead key" that should be combined with another to
- * actually produce a character -- see {@link #getDeadChar} -- after masking
- * with {@link KeyCharacterMap#COMBINING_ACCENT_MASK}.
- * </p>
- */
- public int getUnicodeChar(int meta) {
- return KeyCharacterMap.load(mDeviceId).get(mKeyCode, meta);
- }
-
- /**
- * Get the characters conversion data for the key event..
- *
- * @param results a {@link KeyData} that will be filled with the results.
- *
- * @return whether the key was mapped or not. If the key was not mapped,
- * results is not modified.
- */
- public boolean getKeyData(KeyData results) {
- return KeyCharacterMap.load(mDeviceId).getKeyData(mKeyCode, results);
- }
-
- /**
- * The same as {@link #getMatch(char[],int) getMatch(chars, 0)}.
- */
- public char getMatch(char[] chars) {
- return getMatch(chars, 0);
- }
-
- /**
- * If one of the chars in the array can be generated by the keyCode of this
- * key event, return the char; otherwise return '\0'.
- * @param chars the characters to try to find
- * @param modifiers the modifier bits to prefer. If any of these bits
- * are set, if there are multiple choices, that could
- * work, the one for this modifier will be set.
- */
- public char getMatch(char[] chars, int modifiers) {
- return KeyCharacterMap.load(mDeviceId).getMatch(mKeyCode, chars, modifiers);
- }
-
- /**
- * Gets the number or symbol associated with the key. The character value
- * is returned, not the numeric value. If the key is not a number, but is
- * a symbol, the symbol is retuned.
- */
- public char getNumber() {
- return KeyCharacterMap.load(mDeviceId).getNumber(mKeyCode);
- }
-
- /**
- * Does the key code of this key produce a glyph?
- */
- public boolean isPrintingKey() {
- return KeyCharacterMap.load(mDeviceId).isPrintingKey(mKeyCode);
- }
-
- /**
- * Deliver this key event to a {@link Callback} interface. If this is
- * an ACTION_MULTIPLE event and it is not handled, then an attempt will
- * be made to deliver a single normal event.
- *
- * @param receiver The Callback that will be given the event.
- *
- * @return The return value from the Callback method that was called.
- */
- public final boolean dispatch(Callback receiver) {
- switch (mAction) {
- case ACTION_DOWN:
- return receiver.onKeyDown(mKeyCode, this);
- case ACTION_UP:
- return receiver.onKeyUp(mKeyCode, this);
- case ACTION_MULTIPLE:
- final int count = mRepeatCount;
- final int code = mKeyCode;
- if (receiver.onKeyMultiple(code, count, this)) {
- return true;
- }
- if (code != KeyEvent.KEYCODE_UNKNOWN) {
- mAction = ACTION_DOWN;
- mRepeatCount = 0;
- boolean handled = receiver.onKeyDown(code, this);
- if (handled) {
- mAction = ACTION_UP;
- receiver.onKeyUp(code, this);
- }
- mAction = ACTION_MULTIPLE;
- mRepeatCount = count;
- return handled;
- }
- }
- return false;
- }
-
- public String toString() {
- return "KeyEvent{action=" + mAction + " code=" + mKeyCode
- + " repeat=" + mRepeatCount
- + " meta=" + mMetaState + " scancode=" + mScancode
- + " mFlags=" + mFlags + "}";
- }
-
- public static final Parcelable.Creator<KeyEvent> CREATOR
- = new Parcelable.Creator<KeyEvent>() {
- public KeyEvent createFromParcel(Parcel in) {
- return new KeyEvent(in);
- }
-
- public KeyEvent[] newArray(int size) {
- return new KeyEvent[size];
- }
- };
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mAction);
- out.writeInt(mKeyCode);
- out.writeInt(mRepeatCount);
- out.writeInt(mMetaState);
- out.writeInt(mDeviceId);
- out.writeInt(mScancode);
- out.writeInt(mFlags);
- out.writeLong(mDownTime);
- out.writeLong(mEventTime);
- }
-
- private KeyEvent(Parcel in) {
- mAction = in.readInt();
- mKeyCode = in.readInt();
- mRepeatCount = in.readInt();
- mMetaState = in.readInt();
- mDeviceId = in.readInt();
- mScancode = in.readInt();
- mFlags = in.readInt();
- mDownTime = in.readLong();
- mEventTime = in.readLong();
- }
-}
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
deleted file mode 100644
index 94acd3f..0000000
--- a/core/java/android/view/LayoutInflater.java
+++ /dev/null
@@ -1,744 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.util.AttributeSet;
-import android.util.Xml;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.util.HashMap;
-
-/**
- * This class is used to instantiate layout XML file into its corresponding View
- * objects. It is never be used directly -- use
- * {@link android.app.Activity#getLayoutInflater()} or
- * {@link Context#getSystemService} to retrieve a standard LayoutInflater instance
- * that is already hooked up to the current context and correctly configured
- * for the device you are running on. For example:
- *
- * <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
- * Context.LAYOUT_INFLATER_SERVICE);</pre>
- *
- * <p>
- * To create a new LayoutInflater with an additional {@link Factory} for your
- * own views, you can use {@link #cloneInContext} to clone an existing
- * ViewFactory, and then call {@link #setFactory} on it to include your
- * Factory.
- *
- * <p>
- * For performance reasons, view inflation relies heavily on pre-processing of
- * XML files that is done at build time. Therefore, it is not currently possible
- * to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
- * it only works with an XmlPullParser returned from a compiled resource
- * (R.<em>something</em> file.)
- *
- * @see Context#getSystemService
- */
-public abstract class LayoutInflater {
- private final boolean DEBUG = false;
-
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected final Context mContext;
-
- // these are optional, set by the caller
- private boolean mFactorySet;
- private Factory mFactory;
- private Filter mFilter;
-
- private final Object[] mConstructorArgs = new Object[2];
-
- private static final Class[] mConstructorSignature = new Class[] {
- Context.class, AttributeSet.class};
-
- private static final HashMap<String, Constructor> sConstructorMap =
- new HashMap<String, Constructor>();
-
- private HashMap<String, Boolean> mFilterMap;
-
- private static final String TAG_MERGE = "merge";
- private static final String TAG_INCLUDE = "include";
- private static final String TAG_REQUEST_FOCUS = "requestFocus";
-
- /**
- * Hook to allow clients of the LayoutInflater to restrict the set of Views that are allowed
- * to be inflated.
- *
- */
- public interface Filter {
- /**
- * Hook to allow clients of the LayoutInflater to restrict the set of Views
- * that are allowed to be inflated.
- *
- * @param clazz The class object for the View that is about to be inflated
- *
- * @return True if this class is allowed to be inflated, or false otherwise
- */
- boolean onLoadClass(Class clazz);
- }
-
- public interface Factory {
- /**
- * Hook you can supply that is called when inflating from a LayoutInflater.
- * You can use this to customize the tag names available in your XML
- * layout files.
- *
- * <p>
- * Note that it is good practice to prefix these custom names with your
- * package (i.e., com.coolcompany.apps) to avoid conflicts with system
- * names.
- *
- * @param name Tag name to be inflated.
- * @param context The context the view is being created in.
- * @param attrs Inflation attributes as specified in XML file.
- *
- * @return View Newly created view. Return null for the default
- * behavior.
- */
- public View onCreateView(String name, Context context, AttributeSet attrs);
- }
-
- private static class FactoryMerger implements Factory {
- private final Factory mF1, mF2;
-
- FactoryMerger(Factory f1, Factory f2) {
- mF1 = f1;
- mF2 = f2;
- }
-
- public View onCreateView(String name, Context context, AttributeSet attrs) {
- View v = mF1.onCreateView(name, context, attrs);
- if (v != null) return v;
- return mF2.onCreateView(name, context, attrs);
- }
- }
-
- /**
- * Create a new LayoutInflater instance associated with a particular Context.
- * Applications will almost always want to use
- * {@link Context#getSystemService Context.getSystemService()} to retrieve
- * the standard {@link Context#LAYOUT_INFLATER_SERVICE Context.INFLATER_SERVICE}.
- *
- * @param context The Context in which this LayoutInflater will create its
- * Views; most importantly, this supplies the theme from which the default
- * values for their attributes are retrieved.
- */
- protected LayoutInflater(Context context) {
- mContext = context;
- }
-
- /**
- * Create a new LayoutInflater instance that is a copy of an existing
- * LayoutInflater, optionally with its Context changed. For use in
- * implementing {@link #cloneInContext}.
- *
- * @param original The original LayoutInflater to copy.
- * @param newContext The new Context to use.
- */
- protected LayoutInflater(LayoutInflater original, Context newContext) {
- mContext = newContext;
- mFactory = original.mFactory;
- mFilter = original.mFilter;
- }
-
- /**
- * Obtains the LayoutInflater from the given context.
- */
- public static LayoutInflater from(Context context) {
- LayoutInflater LayoutInflater =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- if (LayoutInflater == null) {
- throw new AssertionError("LayoutInflater not found.");
- }
- return LayoutInflater;
- }
-
- /**
- * Create a copy of the existing LayoutInflater object, with the copy
- * pointing to a different Context than the original. This is used by
- * {@link ContextThemeWrapper} to create a new LayoutInflater to go along
- * with the new Context theme.
- *
- * @param newContext The new Context to associate with the new LayoutInflater.
- * May be the same as the original Context if desired.
- *
- * @return Returns a brand spanking new LayoutInflater object associated with
- * the given Context.
- */
- public abstract LayoutInflater cloneInContext(Context newContext);
-
- /**
- * Return the context we are running in, for access to resources, class
- * loader, etc.
- */
- public Context getContext() {
- return mContext;
- }
-
- /**
- * Return the current factory (or null). This is called on each element
- * name. If the factory returns a View, add that to the hierarchy. If it
- * returns null, proceed to call onCreateView(name).
- */
- public final Factory getFactory() {
- return mFactory;
- }
-
- /**
- * Attach a custom Factory interface for creating views while using
- * this LayoutInflater. This must not be null, and can only be set once;
- * after setting, you can not change the factory. This is
- * called on each element name as the xml is parsed. If the factory returns
- * a View, that is added to the hierarchy. If it returns null, the next
- * factory default {@link #onCreateView} method is called.
- *
- * <p>If you have an existing
- * LayoutInflater and want to add your own factory to it, use
- * {@link #cloneInContext} to clone the existing instance and then you
- * can use this function (once) on the returned new instance. This will
- * merge your own factory with whatever factory the original instance is
- * using.
- */
- public void setFactory(Factory factory) {
- if (mFactorySet) {
- throw new IllegalStateException("A factory has already been set on this LayoutInflater");
- }
- if (factory == null) {
- throw new NullPointerException("Given factory can not be null");
- }
- mFactorySet = true;
- if (mFactory == null) {
- mFactory = factory;
- } else {
- mFactory = new FactoryMerger(factory, mFactory);
- }
- }
-
- /**
- * @return The {@link Filter} currently used by this LayoutInflater to restrict the set of Views
- * that are allowed to be inflated.
- */
- public Filter getFilter() {
- return mFilter;
- }
-
- /**
- * Sets the {@link Filter} to by this LayoutInflater. If a view is attempted to be inflated
- * which is not allowed by the {@link Filter}, the {@link #inflate(int, ViewGroup)} call will
- * throw an {@link InflateException}. This filter will replace any previous filter set on this
- * LayoutInflater.
- *
- * @param filter The Filter which restricts the set of Views that are allowed to be inflated.
- * This filter will replace any previous filter set on this LayoutInflater.
- */
- public void setFilter(Filter filter) {
- mFilter = filter;
- if (filter != null) {
- mFilterMap = new HashMap<String, Boolean>();
- }
- }
-
- /**
- * Inflate a new view hierarchy from the specified xml resource. Throws
- * {@link InflateException} if there is an error.
- *
- * @param resource ID for an XML layout resource to load (e.g.,
- * <code>R.layout.main_page</code>)
- * @param root Optional view to be the parent of the generated hierarchy.
- * @return The root View of the inflated hierarchy. If root was supplied,
- * this is the root View; otherwise it is the root of the inflated
- * XML file.
- */
- public View inflate(int resource, ViewGroup root) {
- return inflate(resource, root, root != null);
- }
-
- /**
- * Inflate a new view hierarchy from the specified xml node. Throws
- * {@link InflateException} if there is an error. *
- * <p>
- * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance
- * reasons, view inflation relies heavily on pre-processing of XML files
- * that is done at build time. Therefore, it is not currently possible to
- * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
- *
- * @param parser XML dom node containing the description of the view
- * hierarchy.
- * @param root Optional view to be the parent of the generated hierarchy.
- * @return The root View of the inflated hierarchy. If root was supplied,
- * this is the root View; otherwise it is the root of the inflated
- * XML file.
- */
- public View inflate(XmlPullParser parser, ViewGroup root) {
- return inflate(parser, root, root != null);
- }
-
- /**
- * Inflate a new view hierarchy from the specified xml resource. Throws
- * {@link InflateException} if there is an error.
- *
- * @param resource ID for an XML layout resource to load (e.g.,
- * <code>R.layout.main_page</code>)
- * @param root Optional view to be the parent of the generated hierarchy (if
- * <em>attachToRoot</em> is true), or else simply an object that
- * provides a set of LayoutParams values for root of the returned
- * hierarchy (if <em>attachToRoot</em> is false.)
- * @param attachToRoot Whether the inflated hierarchy should be attached to
- * the root parameter? If false, root is only used to create the
- * correct subclass of LayoutParams for the root view in the XML.
- * @return The root View of the inflated hierarchy. If root was supplied and
- * attachToRoot is true, this is root; otherwise it is the root of
- * the inflated XML file.
- */
- public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
- if (DEBUG) System.out.println("INFLATING from resource: " + resource);
- XmlResourceParser parser = getContext().getResources().getLayout(resource);
- try {
- return inflate(parser, root, attachToRoot);
- } finally {
- parser.close();
- }
- }
-
- /**
- * Inflate a new view hierarchy from the specified XML node. Throws
- * {@link InflateException} if there is an error.
- * <p>
- * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance
- * reasons, view inflation relies heavily on pre-processing of XML files
- * that is done at build time. Therefore, it is not currently possible to
- * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
- *
- * @param parser XML dom node containing the description of the view
- * hierarchy.
- * @param root Optional view to be the parent of the generated hierarchy (if
- * <em>attachToRoot</em> is true), or else simply an object that
- * provides a set of LayoutParams values for root of the returned
- * hierarchy (if <em>attachToRoot</em> is false.)
- * @param attachToRoot Whether the inflated hierarchy should be attached to
- * the root parameter? If false, root is only used to create the
- * correct subclass of LayoutParams for the root view in the XML.
- * @return The root View of the inflated hierarchy. If root was supplied and
- * attachToRoot is true, this is root; otherwise it is the root of
- * the inflated XML file.
- */
- public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
- synchronized (mConstructorArgs) {
- final AttributeSet attrs = Xml.asAttributeSet(parser);
- mConstructorArgs[0] = mContext;
- View result = root;
-
- try {
- // Look for the root node.
- int type;
- while ((type = parser.next()) != XmlPullParser.START_TAG &&
- type != XmlPullParser.END_DOCUMENT) {
- // Empty
- }
-
- if (type != XmlPullParser.START_TAG) {
- throw new InflateException(parser.getPositionDescription()
- + ": No start tag found!");
- }
-
- final String name = parser.getName();
-
- if (DEBUG) {
- System.out.println("**************************");
- System.out.println("Creating root view: "
- + name);
- System.out.println("**************************");
- }
-
- if (TAG_MERGE.equals(name)) {
- if (root == null || !attachToRoot) {
- throw new InflateException("<merge /> can be used only with a valid "
- + "ViewGroup root and attachToRoot=true");
- }
-
- rInflate(parser, root, attrs);
- } else {
- // Temp is the root view that was found in the xml
- View temp = createViewFromTag(name, attrs);
-
- ViewGroup.LayoutParams params = null;
-
- if (root != null) {
- if (DEBUG) {
- System.out.println("Creating params from root: " +
- root);
- }
- // Create layout params that match root, if supplied
- params = root.generateLayoutParams(attrs);
- if (!attachToRoot) {
- // Set the layout params for temp if we are not
- // attaching. (If we are, we use addView, below)
- temp.setLayoutParams(params);
- }
- }
-
- if (DEBUG) {
- System.out.println("-----> start inflating children");
- }
- // Inflate all children under temp
- rInflate(parser, temp, attrs);
- if (DEBUG) {
- System.out.println("-----> done inflating children");
- }
-
- // We are supposed to attach all the views we found (int temp)
- // to root. Do that now.
- if (root != null && attachToRoot) {
- root.addView(temp, params);
- }
-
- // Decide whether to return the root that was passed in or the
- // top view found in xml.
- if (root == null || !attachToRoot) {
- result = temp;
- }
- }
-
- } catch (XmlPullParserException e) {
- InflateException ex = new InflateException(e.getMessage());
- ex.initCause(e);
- throw ex;
- } catch (IOException e) {
- InflateException ex = new InflateException(
- parser.getPositionDescription()
- + ": " + e.getMessage());
- ex.initCause(e);
- throw ex;
- }
-
- return result;
- }
- }
-
- /**
- * Low-level function for instantiating a view by name. This attempts to
- * instantiate a view class of the given <var>name</var> found in this
- * LayoutInflater's ClassLoader.
- *
- * <p>
- * There are two things that can happen in an error case: either the
- * exception describing the error will be thrown, or a null will be
- * returned. You must deal with both possibilities -- the former will happen
- * the first time createView() is called for a class of a particular name,
- * the latter every time there-after for that class name.
- *
- * @param name The full name of the class to be instantiated.
- * @param attrs The XML attributes supplied for this instance.
- *
- * @return View The newly instantied view, or null.
- */
- public final View createView(String name, String prefix, AttributeSet attrs)
- throws ClassNotFoundException, InflateException {
- Constructor constructor = sConstructorMap.get(name);
-
- try {
- if (constructor == null) {
- // Class not found in the cache, see if it's real, and try to add it
- Class clazz = mContext.getClassLoader().loadClass(
- prefix != null ? (prefix + name) : name);
-
- if (mFilter != null && clazz != null) {
- boolean allowed = mFilter.onLoadClass(clazz);
- if (!allowed) {
- failNotAllowed(name, prefix, attrs);
- }
- }
- constructor = clazz.getConstructor(mConstructorSignature);
- sConstructorMap.put(name, constructor);
- } else {
- // If we have a filter, apply it to cached constructor
- if (mFilter != null) {
- // Have we seen this name before?
- Boolean allowedState = mFilterMap.get(name);
- if (allowedState == null) {
- // New class -- remember whether it is allowed
- Class clazz = mContext.getClassLoader().loadClass(
- prefix != null ? (prefix + name) : name);
-
- boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
- mFilterMap.put(name, allowed);
- if (!allowed) {
- failNotAllowed(name, prefix, attrs);
- }
- } else if (allowedState.equals(Boolean.FALSE)) {
- failNotAllowed(name, prefix, attrs);
- }
- }
- }
-
- Object[] args = mConstructorArgs;
- args[1] = attrs;
- return (View) constructor.newInstance(args);
-
- } catch (NoSuchMethodException e) {
- InflateException ie = new InflateException(attrs.getPositionDescription()
- + ": Error inflating class "
- + (prefix != null ? (prefix + name) : name));
- ie.initCause(e);
- throw ie;
-
- } catch (ClassNotFoundException e) {
- // If loadClass fails, we should propagate the exception.
- throw e;
- } catch (Exception e) {
- InflateException ie = new InflateException(attrs.getPositionDescription()
- + ": Error inflating class "
- + (constructor == null ? "<unknown>" : constructor.getClass().getName()));
- ie.initCause(e);
- throw ie;
- }
- }
-
- /**
- * Throw an excpetion because the specified class is not allowed to be inflated.
- */
- private void failNotAllowed(String name, String prefix, AttributeSet attrs) {
- InflateException ie = new InflateException(attrs.getPositionDescription()
- + ": Class not allowed to be inflated "
- + (prefix != null ? (prefix + name) : name));
- throw ie;
- }
-
- /**
- * This routine is responsible for creating the correct subclass of View
- * given the xml element name. Override it to handle custom view objects. If
- * you override this in your subclass be sure to call through to
- * super.onCreateView(name) for names you do not recognize.
- *
- * @param name The fully qualified class name of the View to be create.
- * @param attrs An AttributeSet of attributes to apply to the View.
- *
- * @return View The View created.
- */
- protected View onCreateView(String name, AttributeSet attrs)
- throws ClassNotFoundException {
- return createView(name, "android.view.", attrs);
- }
-
- /*
- * default visibility so the BridgeInflater can override it.
- */
- View createViewFromTag(String name, AttributeSet attrs) {
- if (name.equals("view")) {
- name = attrs.getAttributeValue(null, "class");
- }
-
- if (DEBUG) System.out.println("******** Creating view: " + name);
-
- try {
- View view = (mFactory == null) ? null : mFactory.onCreateView(name,
- mContext, attrs);
-
- if (view == null) {
- if (-1 == name.indexOf('.')) {
- view = onCreateView(name, attrs);
- } else {
- view = createView(name, null, attrs);
- }
- }
-
- if (DEBUG) System.out.println("Created view is: " + view);
- return view;
-
- } catch (InflateException e) {
- throw e;
-
- } catch (ClassNotFoundException e) {
- InflateException ie = new InflateException(attrs.getPositionDescription()
- + ": Error inflating class " + name);
- ie.initCause(e);
- throw ie;
-
- } catch (Exception e) {
- InflateException ie = new InflateException(attrs.getPositionDescription()
- + ": Error inflating class " + name);
- ie.initCause(e);
- throw ie;
- }
- }
-
- /**
- * Recursive method used to descend down the xml hierarchy and instantiate
- * views, instantiate their children, and then call onFinishInflate().
- */
- private void rInflate(XmlPullParser parser, View parent, final AttributeSet attrs)
- throws XmlPullParserException, IOException {
-
- final int depth = parser.getDepth();
- int type;
-
- while (((type = parser.next()) != XmlPullParser.END_TAG ||
- parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
-
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
-
- final String name = parser.getName();
-
- if (TAG_REQUEST_FOCUS.equals(name)) {
- parseRequestFocus(parser, parent);
- } else if (TAG_INCLUDE.equals(name)) {
- if (parser.getDepth() == 0) {
- throw new InflateException("<include /> cannot be the root element");
- }
- parseInclude(parser, parent, attrs);
- } else if (TAG_MERGE.equals(name)) {
- throw new InflateException("<merge /> must be the root element");
- } else {
- final View view = createViewFromTag(name, attrs);
- final ViewGroup viewGroup = (ViewGroup) parent;
- final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
- rInflate(parser, view, attrs);
- viewGroup.addView(view, params);
- }
- }
-
- parent.onFinishInflate();
- }
-
- private void parseRequestFocus(XmlPullParser parser, View parent)
- throws XmlPullParserException, IOException {
- int type;
- parent.requestFocus();
- final int currentDepth = parser.getDepth();
- while (((type = parser.next()) != XmlPullParser.END_TAG ||
- parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
- // Empty
- }
- }
-
- private void parseInclude(XmlPullParser parser, View parent, AttributeSet attrs)
- throws XmlPullParserException, IOException {
-
- int type;
-
- if (parent instanceof ViewGroup) {
- final int layout = attrs.getAttributeResourceValue(null, "layout", 0);
- if (layout == 0) {
- final String value = attrs.getAttributeValue(null, "layout");
- if (value == null) {
- throw new InflateException("You must specifiy a layout in the"
- + " include tag: <include layout=\"@layout/layoutID\" />");
- } else {
- throw new InflateException("You must specifiy a valid layout "
- + "reference. The layout ID " + value + " is not valid.");
- }
- } else {
- final XmlResourceParser childParser =
- getContext().getResources().getLayout(layout);
-
- try {
- final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
-
- while ((type = childParser.next()) != XmlPullParser.START_TAG &&
- type != XmlPullParser.END_DOCUMENT) {
- // Empty.
- }
-
- if (type != XmlPullParser.START_TAG) {
- throw new InflateException(childParser.getPositionDescription() +
- ": No start tag found!");
- }
-
- final String childName = childParser.getName();
-
- if (TAG_MERGE.equals(childName)) {
- // Inflate all children.
- rInflate(childParser, parent, childAttrs);
- } else {
- final View view = createViewFromTag(childName, childAttrs);
- final ViewGroup group = (ViewGroup) parent;
-
- // We try to load the layout params set in the <include /> tag. If
- // they don't exist, we will rely on the layout params set in the
- // included XML file.
- // During a layoutparams generation, a runtime exception is thrown
- // if either layout_width or layout_height is missing. We catch
- // this exception and set localParams accordingly: true means we
- // successfully loaded layout params from the <include /> tag,
- // false means we need to rely on the included layout params.
- ViewGroup.LayoutParams params = null;
- try {
- params = group.generateLayoutParams(attrs);
- } catch (RuntimeException e) {
- params = group.generateLayoutParams(childAttrs);
- } finally {
- if (params != null) {
- view.setLayoutParams(params);
- }
- }
-
- // Inflate all children.
- rInflate(childParser, view, childAttrs);
-
- // Attempt to override the included layout's android:id with the
- // one set on the <include /> tag itself.
- TypedArray a = mContext.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.View, 0, 0);
- int id = a.getResourceId(com.android.internal.R.styleable.View_id, View.NO_ID);
- // While we're at it, let's try to override android:visibility.
- int visibility = a.getInt(com.android.internal.R.styleable.View_visibility, -1);
- a.recycle();
-
- if (id != View.NO_ID) {
- view.setId(id);
- }
-
- switch (visibility) {
- case 0:
- view.setVisibility(View.VISIBLE);
- break;
- case 1:
- view.setVisibility(View.INVISIBLE);
- break;
- case 2:
- view.setVisibility(View.GONE);
- break;
- }
-
- group.addView(view);
- }
- } finally {
- childParser.close();
- }
- }
- } else {
- throw new InflateException("<include /> can only be used inside of a ViewGroup");
- }
-
- final int currentDepth = parser.getDepth();
- while (((type = parser.next()) != XmlPullParser.END_TAG ||
- parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
- // Empty
- }
- }
-}
diff --git a/core/java/android/view/Menu.java b/core/java/android/view/Menu.java
deleted file mode 100644
index 97825e6..0000000
--- a/core/java/android/view/Menu.java
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.app.Activity;
-import android.content.ComponentName;
-import android.content.Intent;
-
-/**
- * Interface for managing the items in a menu.
- * <p>
- * By default, every Activity supports an options menu of actions or options.
- * You can add items to this menu and handle clicks on your additions. The
- * easiest way of adding menu items is inflating an XML file into the
- * {@link Menu} via {@link MenuInflater}. The easiest way of attaching code to
- * clicks is via {@link Activity#onOptionsItemSelected(MenuItem)} and
- * {@link Activity#onContextItemSelected(MenuItem)}.
- * <p>
- * Different menu types support different features:
- * <ol>
- * <li><b>Context menus</b>: Do not support item shortcuts and item icons.
- * <li><b>Options menus</b>: The <b>icon menus</b> do not support item check
- * marks and only show the item's
- * {@link MenuItem#setTitleCondensed(CharSequence) condensed title}. The
- * <b>expanded menus</b> (only available if six or more menu items are visible,
- * reached via the 'More' item in the icon menu) do not show item icons, and
- * item check marks are discouraged.
- * <li><b>Sub menus</b>: Do not support item icons, or nested sub menus.
- * </ol>
- */
-public interface Menu {
-
- /**
- * This is the part of an order integer that the user can provide.
- * @hide
- */
- static final int USER_MASK = 0x0000ffff;
- /**
- * Bit shift of the user portion of the order integer.
- * @hide
- */
- static final int USER_SHIFT = 0;
-
- /**
- * This is the part of an order integer that supplies the category of the
- * item.
- * @hide
- */
- static final int CATEGORY_MASK = 0xffff0000;
- /**
- * Bit shift of the category portion of the order integer.
- * @hide
- */
- static final int CATEGORY_SHIFT = 16;
-
- /**
- * Value to use for group and item identifier integers when you don't care
- * about them.
- */
- static final int NONE = 0;
-
- /**
- * First value for group and item identifier integers.
- */
- static final int FIRST = 1;
-
- // Implementation note: Keep these CATEGORY_* in sync with the category enum
- // in attrs.xml
-
- /**
- * Category code for the order integer for items/groups that are part of a
- * container -- or/add this with your base value.
- */
- static final int CATEGORY_CONTAINER = 0x00010000;
-
- /**
- * Category code for the order integer for items/groups that are provided by
- * the system -- or/add this with your base value.
- */
- static final int CATEGORY_SYSTEM = 0x00020000;
-
- /**
- * Category code for the order integer for items/groups that are
- * user-supplied secondary (infrequently used) options -- or/add this with
- * your base value.
- */
- static final int CATEGORY_SECONDARY = 0x00030000;
-
- /**
- * Category code for the order integer for items/groups that are
- * alternative actions on the data that is currently displayed -- or/add
- * this with your base value.
- */
- static final int CATEGORY_ALTERNATIVE = 0x00040000;
-
- /**
- * Flag for {@link #addIntentOptions}: if set, do not automatically remove
- * any existing menu items in the same group.
- */
- static final int FLAG_APPEND_TO_GROUP = 0x0001;
-
- /**
- * Flag for {@link #performShortcut}: if set, do not close the menu after
- * executing the shortcut.
- */
- static final int FLAG_PERFORM_NO_CLOSE = 0x0001;
-
- /**
- * Flag for {@link #performShortcut(int, KeyEvent, int)}: if set, always
- * close the menu after executing the shortcut. Closing the menu also resets
- * the prepared state.
- */
- static final int FLAG_ALWAYS_PERFORM_CLOSE = 0x0002;
-
- /**
- * Add a new item to the menu. This item displays the given title for its
- * label.
- *
- * @param title The text to display for the item.
- * @return The newly added menu item.
- */
- public MenuItem add(CharSequence title);
-
- /**
- * Add a new item to the menu. This item displays the given title for its
- * label.
- *
- * @param titleRes Resource identifier of title string.
- * @return The newly added menu item.
- */
- public MenuItem add(int titleRes);
-
- /**
- * Add a new item to the menu. This item displays the given title for its
- * label.
- *
- * @param groupId The group identifier that this item should be part of.
- * This can be used to define groups of items for batch state
- * changes. Normally use {@link #NONE} if an item should not be in a
- * group.
- * @param itemId Unique item ID. Use {@link #NONE} if you do not need a
- * unique ID.
- * @param order The order for the item. Use {@link #NONE} if you do not care
- * about the order. See {@link MenuItem#getOrder()}.
- * @param title The text to display for the item.
- * @return The newly added menu item.
- */
- public MenuItem add(int groupId, int itemId, int order, CharSequence title);
-
- /**
- * Variation on {@link #add(int, int, int, CharSequence)} that takes a
- * string resource identifier instead of the string itself.
- *
- * @param groupId The group identifier that this item should be part of.
- * This can also be used to define groups of items for batch state
- * changes. Normally use {@link #NONE} if an item should not be in a
- * group.
- * @param itemId Unique item ID. Use {@link #NONE} if you do not need a
- * unique ID.
- * @param order The order for the item. Use {@link #NONE} if you do not care
- * about the order. See {@link MenuItem#getOrder()}.
- * @param titleRes Resource identifier of title string.
- * @return The newly added menu item.
- */
- public MenuItem add(int groupId, int itemId, int order, int titleRes);
-
- /**
- * Add a new sub-menu to the menu. This item displays the given title for
- * its label. To modify other attributes on the submenu's menu item, use
- * {@link SubMenu#getItem()}.
- *
- * @param title The text to display for the item.
- * @return The newly added sub-menu
- */
- SubMenu addSubMenu(final CharSequence title);
-
- /**
- * Add a new sub-menu to the menu. This item displays the given title for
- * its label. To modify other attributes on the submenu's menu item, use
- * {@link SubMenu#getItem()}.
- *
- * @param titleRes Resource identifier of title string.
- * @return The newly added sub-menu
- */
- SubMenu addSubMenu(final int titleRes);
-
- /**
- * Add a new sub-menu to the menu. This item displays the given
- * <var>title</var> for its label. To modify other attributes on the
- * submenu's menu item, use {@link SubMenu#getItem()}.
- *<p>
- * Note that you can only have one level of sub-menus, i.e. you cannnot add
- * a subMenu to a subMenu: An {@link UnsupportedOperationException} will be
- * thrown if you try.
- *
- * @param groupId The group identifier that this item should be part of.
- * This can also be used to define groups of items for batch state
- * changes. Normally use {@link #NONE} if an item should not be in a
- * group.
- * @param itemId Unique item ID. Use {@link #NONE} if you do not need a
- * unique ID.
- * @param order The order for the item. Use {@link #NONE} if you do not care
- * about the order. See {@link MenuItem#getOrder()}.
- * @param title The text to display for the item.
- * @return The newly added sub-menu
- */
- SubMenu addSubMenu(final int groupId, final int itemId, int order, final CharSequence title);
-
- /**
- * Variation on {@link #addSubMenu(int, int, int, CharSequence)} that takes
- * a string resource identifier for the title instead of the string itself.
- *
- * @param groupId The group identifier that this item should be part of.
- * This can also be used to define groups of items for batch state
- * changes. Normally use {@link #NONE} if an item should not be in a group.
- * @param itemId Unique item ID. Use {@link #NONE} if you do not need a unique ID.
- * @param order The order for the item. Use {@link #NONE} if you do not care about the
- * order. See {@link MenuItem#getOrder()}.
- * @param titleRes Resource identifier of title string.
- * @return The newly added sub-menu
- */
- SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes);
-
- /**
- * Add a group of menu items corresponding to actions that can be performed
- * for a particular Intent. The Intent is most often configured with a null
- * action, the data that the current activity is working with, and includes
- * either the {@link Intent#CATEGORY_ALTERNATIVE} or
- * {@link Intent#CATEGORY_SELECTED_ALTERNATIVE} to find activities that have
- * said they would like to be included as optional action. You can, however,
- * use any Intent you want.
- *
- * <p>
- * See {@link android.content.pm.PackageManager#queryIntentActivityOptions}
- * for more * details on the <var>caller</var>, <var>specifics</var>, and
- * <var>intent</var> arguments. The list returned by that function is used
- * to populate the resulting menu items.
- *
- * <p>
- * All of the menu items of possible options for the intent will be added
- * with the given group and id. You can use the group to control ordering of
- * the items in relation to other items in the menu. Normally this function
- * will automatically remove any existing items in the menu in the same
- * group and place a divider above and below the added items; this behavior
- * can be modified with the <var>flags</var> parameter. For each of the
- * generated items {@link MenuItem#setIntent} is called to associate the
- * appropriate Intent with the item; this means the activity will
- * automatically be started for you without having to do anything else.
- *
- * @param groupId The group identifier that the items should be part of.
- * This can also be used to define groups of items for batch state
- * changes. Normally use {@link #NONE} if the items should not be in
- * a group.
- * @param itemId Unique item ID. Use {@link #NONE} if you do not need a
- * unique ID.
- * @param order The order for the items. Use {@link #NONE} if you do not
- * care about the order. See {@link MenuItem#getOrder()}.
- * @param caller The current activity component name as defined by
- * queryIntentActivityOptions().
- * @param specifics Specific items to place first as defined by
- * queryIntentActivityOptions().
- * @param intent Intent describing the kinds of items to populate in the
- * list as defined by queryIntentActivityOptions().
- * @param flags Additional options controlling how the items are added.
- * @param outSpecificItems Optional array in which to place the menu items
- * that were generated for each of the <var>specifics</var> that were
- * requested. Entries may be null if no activity was found for that
- * specific action.
- * @return The number of menu items that were added.
- *
- * @see #FLAG_APPEND_TO_GROUP
- * @see MenuItem#setIntent
- * @see android.content.pm.PackageManager#queryIntentActivityOptions
- */
- public int addIntentOptions(int groupId, int itemId, int order,
- ComponentName caller, Intent[] specifics,
- Intent intent, int flags, MenuItem[] outSpecificItems);
-
- /**
- * Remove the item with the given identifier.
- *
- * @param id The item to be removed. If there is no item with this
- * identifier, nothing happens.
- */
- public void removeItem(int id);
-
- /**
- * Remove all items in the given group.
- *
- * @param groupId The group to be removed. If there are no items in this
- * group, nothing happens.
- */
- public void removeGroup(int groupId);
-
- /**
- * Remove all existing items from the menu, leaving it empty as if it had
- * just been created.
- */
- public void clear();
-
- /**
- * Control whether a particular group of items can show a check mark. This
- * is similar to calling {@link MenuItem#setCheckable} on all of the menu items
- * with the given group identifier, but in addition you can control whether
- * this group contains a mutually-exclusive set items. This should be called
- * after the items of the group have been added to the menu.
- *
- * @param group The group of items to operate on.
- * @param checkable Set to true to allow a check mark, false to
- * disallow. The default is false.
- * @param exclusive If set to true, only one item in this group can be
- * checked at a time; checking an item will automatically
- * uncheck all others in the group. If set to false, each
- * item can be checked independently of the others.
- *
- * @see MenuItem#setCheckable
- * @see MenuItem#setChecked
- */
- public void setGroupCheckable(int group, boolean checkable, boolean exclusive);
-
- /**
- * Show or hide all menu items that are in the given group.
- *
- * @param group The group of items to operate on.
- * @param visible If true the items are visible, else they are hidden.
- *
- * @see MenuItem#setVisible
- */
- public void setGroupVisible(int group, boolean visible);
-
- /**
- * Enable or disable all menu items that are in the given group.
- *
- * @param group The group of items to operate on.
- * @param enabled If true the items will be enabled, else they will be disabled.
- *
- * @see MenuItem#setEnabled
- */
- public void setGroupEnabled(int group, boolean enabled);
-
- /**
- * Return whether the menu currently has item items that are visible.
- *
- * @return True if there is one or more item visible,
- * else false.
- */
- public boolean hasVisibleItems();
-
- /**
- * Return the menu item with a particular identifier.
- *
- * @param id The identifier to find.
- *
- * @return The menu item object, or null if there is no item with
- * this identifier.
- */
- public MenuItem findItem(int id);
-
- /**
- * Get the number of items in the menu. Note that this will change any
- * times items are added or removed from the menu.
- *
- * @return The item count.
- */
- public int size();
-
- /**
- * Gets the menu item at the given index.
- *
- * @param index The index of the menu item to return.
- * @return The menu item.
- * @exception IndexOutOfBoundsException
- * when {@code index < 0 || >= size()}
- */
- public MenuItem getItem(int index);
-
- /**
- * Closes the menu, if open.
- */
- public void close();
-
- /**
- * Execute the menu item action associated with the given shortcut
- * character.
- *
- * @param keyCode The keycode of the shortcut key.
- * @param event Key event message.
- * @param flags Additional option flags or 0.
- *
- * @return If the given shortcut exists and is shown, returns
- * true; else returns false.
- *
- * @see #FLAG_PERFORM_NO_CLOSE
- */
- public boolean performShortcut(int keyCode, KeyEvent event, int flags);
-
- /**
- * Is a keypress one of the defined shortcut keys for this window.
- * @param keyCode the key code from {@link KeyEvent} to check.
- * @param event the {@link KeyEvent} to use to help check.
- */
- boolean isShortcutKey(int keyCode, KeyEvent event);
-
- /**
- * Execute the menu item action associated with the given menu identifier.
- *
- * @param id Identifier associated with the menu item.
- * @param flags Additional option flags or 0.
- *
- * @return If the given identifier exists and is shown, returns
- * true; else returns false.
- *
- * @see #FLAG_PERFORM_NO_CLOSE
- */
- public boolean performIdentifierAction(int id, int flags);
-
-
- /**
- * Control whether the menu should be running in qwerty mode (alphabetic
- * shortcuts) or 12-key mode (numeric shortcuts).
- *
- * @param isQwerty If true the menu will use alphabetic shortcuts; else it
- * will use numeric shortcuts.
- */
- public void setQwertyMode(boolean isQwerty);
-}
-
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
deleted file mode 100644
index 46c805c..0000000
--- a/core/java/android/view/MenuInflater.java
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import com.android.internal.view.menu.MenuItemImpl;
-
-import java.io.IOException;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.util.AttributeSet;
-import android.util.Xml;
-
-/**
- * This class is used to instantiate menu XML files into Menu objects.
- * <p>
- * For performance reasons, menu inflation relies heavily on pre-processing of
- * XML files that is done at build time. Therefore, it is not currently possible
- * to use MenuInflater with an XmlPullParser over a plain XML file at runtime;
- * it only works with an XmlPullParser returned from a compiled resource (R.
- * <em>something</em> file.)
- */
-public class MenuInflater {
- /** Menu tag name in XML. */
- private static final String XML_MENU = "menu";
-
- /** Group tag name in XML. */
- private static final String XML_GROUP = "group";
-
- /** Item tag name in XML. */
- private static final String XML_ITEM = "item";
-
- private static final int NO_ID = 0;
-
- private Context mContext;
-
- /**
- * Constructs a menu inflater.
- *
- * @see Activity#getMenuInflater()
- */
- public MenuInflater(Context context) {
- mContext = context;
- }
-
- /**
- * Inflate a menu hierarchy from the specified XML resource. Throws
- * {@link InflateException} if there is an error.
- *
- * @param menuRes Resource ID for an XML layout resource to load (e.g.,
- * <code>R.menu.main_activity</code>)
- * @param menu The Menu to inflate into. The items and submenus will be
- * added to this Menu.
- */
- public void inflate(int menuRes, Menu menu) {
- XmlResourceParser parser = null;
- try {
- parser = mContext.getResources().getLayout(menuRes);
- AttributeSet attrs = Xml.asAttributeSet(parser);
-
- parseMenu(parser, attrs, menu);
- } catch (XmlPullParserException e) {
- throw new InflateException("Error inflating menu XML", e);
- } catch (IOException e) {
- throw new InflateException("Error inflating menu XML", e);
- } finally {
- if (parser != null) parser.close();
- }
- }
-
- /**
- * Called internally to fill the given menu. If a sub menu is seen, it will
- * call this recursively.
- */
- private void parseMenu(XmlPullParser parser, AttributeSet attrs, Menu menu)
- throws XmlPullParserException, IOException {
- MenuState menuState = new MenuState(menu);
-
- int eventType = parser.getEventType();
- String tagName;
- boolean lookingForEndOfUnknownTag = false;
- String unknownTagName = null;
-
- // This loop will skip to the menu start tag
- do {
- if (eventType == XmlPullParser.START_TAG) {
- tagName = parser.getName();
- if (tagName.equals(XML_MENU)) {
- // Go to next tag
- eventType = parser.next();
- break;
- }
-
- throw new RuntimeException("Expecting menu, got " + tagName);
- }
- eventType = parser.next();
- } while (eventType != XmlPullParser.END_DOCUMENT);
-
- boolean reachedEndOfMenu = false;
- while (!reachedEndOfMenu) {
- switch (eventType) {
- case XmlPullParser.START_TAG:
- if (lookingForEndOfUnknownTag) {
- break;
- }
-
- tagName = parser.getName();
- if (tagName.equals(XML_GROUP)) {
- menuState.readGroup(attrs);
- } else if (tagName.equals(XML_ITEM)) {
- menuState.readItem(attrs);
- } else if (tagName.equals(XML_MENU)) {
- // A menu start tag denotes a submenu for an item
- SubMenu subMenu = menuState.addSubMenuItem();
-
- // Parse the submenu into returned SubMenu
- parseMenu(parser, attrs, subMenu);
- } else {
- lookingForEndOfUnknownTag = true;
- unknownTagName = tagName;
- }
- break;
-
- case XmlPullParser.END_TAG:
- tagName = parser.getName();
- if (lookingForEndOfUnknownTag && tagName.equals(unknownTagName)) {
- lookingForEndOfUnknownTag = false;
- unknownTagName = null;
- } else if (tagName.equals(XML_GROUP)) {
- menuState.resetGroup();
- } else if (tagName.equals(XML_ITEM)) {
- // Add the item if it hasn't been added (if the item was
- // a submenu, it would have been added already)
- if (!menuState.hasAddedItem()) {
- menuState.addItem();
- }
- } else if (tagName.equals(XML_MENU)) {
- reachedEndOfMenu = true;
- }
- break;
-
- case XmlPullParser.END_DOCUMENT:
- throw new RuntimeException("Unexpected end of document");
- }
-
- eventType = parser.next();
- }
- }
-
- /**
- * State for the current menu.
- * <p>
- * Groups can not be nested unless there is another menu (which will have
- * its state class).
- */
- private class MenuState {
- private Menu menu;
-
- /*
- * Group state is set on items as they are added, allowing an item to
- * override its group state. (As opposed to set on items at the group end tag.)
- */
- private int groupId;
- private int groupCategory;
- private int groupOrder;
- private int groupCheckable;
- private boolean groupVisible;
- private boolean groupEnabled;
-
- private boolean itemAdded;
- private int itemId;
- private int itemCategoryOrder;
- private String itemTitle;
- private String itemTitleCondensed;
- private int itemIconResId;
- private char itemAlphabeticShortcut;
- private char itemNumericShortcut;
- /**
- * Sync to attrs.xml enum:
- * - 0: none
- * - 1: all
- * - 2: exclusive
- */
- private int itemCheckable;
- private boolean itemChecked;
- private boolean itemVisible;
- private boolean itemEnabled;
-
- private static final int defaultGroupId = NO_ID;
- private static final int defaultItemId = NO_ID;
- private static final int defaultItemCategory = 0;
- private static final int defaultItemOrder = 0;
- private static final int defaultItemCheckable = 0;
- private static final boolean defaultItemChecked = false;
- private static final boolean defaultItemVisible = true;
- private static final boolean defaultItemEnabled = true;
-
- public MenuState(final Menu menu) {
- this.menu = menu;
-
- resetGroup();
- }
-
- public void resetGroup() {
- groupId = defaultGroupId;
- groupCategory = defaultItemCategory;
- groupOrder = defaultItemOrder;
- groupCheckable = defaultItemCheckable;
- groupVisible = defaultItemVisible;
- groupEnabled = defaultItemEnabled;
- }
-
- /**
- * Called when the parser is pointing to a group tag.
- */
- public void readGroup(AttributeSet attrs) {
- TypedArray a = mContext.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.MenuGroup);
-
- groupId = a.getResourceId(com.android.internal.R.styleable.MenuGroup_id, defaultGroupId);
- groupCategory = a.getInt(com.android.internal.R.styleable.MenuGroup_menuCategory, defaultItemCategory);
- groupOrder = a.getInt(com.android.internal.R.styleable.MenuGroup_orderInCategory, defaultItemOrder);
- groupCheckable = a.getInt(com.android.internal.R.styleable.MenuGroup_checkableBehavior, defaultItemCheckable);
- groupVisible = a.getBoolean(com.android.internal.R.styleable.MenuGroup_visible, defaultItemVisible);
- groupEnabled = a.getBoolean(com.android.internal.R.styleable.MenuGroup_enabled, defaultItemEnabled);
-
- a.recycle();
- }
-
- /**
- * Called when the parser is pointing to an item tag.
- */
- public void readItem(AttributeSet attrs) {
- TypedArray a = mContext.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.MenuItem);
-
- // Inherit attributes from the group as default value
- itemId = a.getResourceId(com.android.internal.R.styleable.MenuItem_id, defaultItemId);
- final int category = a.getInt(com.android.internal.R.styleable.MenuItem_menuCategory, groupCategory);
- final int order = a.getInt(com.android.internal.R.styleable.MenuItem_orderInCategory, groupOrder);
- itemCategoryOrder = (category & Menu.CATEGORY_MASK) | (order & Menu.USER_MASK);
- itemTitle = a.getString(com.android.internal.R.styleable.MenuItem_title);
- itemTitleCondensed = a.getString(com.android.internal.R.styleable.MenuItem_titleCondensed);
- itemIconResId = a.getResourceId(com.android.internal.R.styleable.MenuItem_icon, 0);
- itemAlphabeticShortcut =
- getShortcut(a.getString(com.android.internal.R.styleable.MenuItem_alphabeticShortcut));
- itemNumericShortcut =
- getShortcut(a.getString(com.android.internal.R.styleable.MenuItem_numericShortcut));
- if (a.hasValue(com.android.internal.R.styleable.MenuItem_checkable)) {
- // Item has attribute checkable, use it
- itemCheckable = a.getBoolean(com.android.internal.R.styleable.MenuItem_checkable, false) ? 1 : 0;
- } else {
- // Item does not have attribute, use the group's (group can have one more state
- // for checkable that represents the exclusive checkable)
- itemCheckable = groupCheckable;
- }
- itemChecked = a.getBoolean(com.android.internal.R.styleable.MenuItem_checked, defaultItemChecked);
- itemVisible = a.getBoolean(com.android.internal.R.styleable.MenuItem_visible, groupVisible);
- itemEnabled = a.getBoolean(com.android.internal.R.styleable.MenuItem_enabled, groupEnabled);
-
- a.recycle();
-
- itemAdded = false;
- }
-
- private char getShortcut(String shortcutString) {
- if (shortcutString == null) {
- return 0;
- } else {
- return shortcutString.charAt(0);
- }
- }
-
- private void setItem(MenuItem item) {
- item.setChecked(itemChecked)
- .setVisible(itemVisible)
- .setEnabled(itemEnabled)
- .setCheckable(itemCheckable >= 1)
- .setTitleCondensed(itemTitleCondensed)
- .setIcon(itemIconResId)
- .setAlphabeticShortcut(itemAlphabeticShortcut)
- .setNumericShortcut(itemNumericShortcut);
-
- if (itemCheckable >= 2) {
- ((MenuItemImpl) item).setExclusiveCheckable(true);
- }
- }
-
- public void addItem() {
- itemAdded = true;
- setItem(menu.add(groupId, itemId, itemCategoryOrder, itemTitle));
- }
-
- public SubMenu addSubMenuItem() {
- itemAdded = true;
- SubMenu subMenu = menu.addSubMenu(groupId, itemId, itemCategoryOrder, itemTitle);
- setItem(subMenu.getItem());
- return subMenu;
- }
-
- public boolean hasAddedItem() {
- return itemAdded;
- }
- }
-
-}
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
deleted file mode 100644
index fcebec5..0000000
--- a/core/java/android/view/MenuItem.java
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.View.OnCreateContextMenuListener;
-
-/**
- * Interface for direct access to a previously created menu item.
- * <p>
- * An Item is returned by calling one of the {@link android.view.Menu#add}
- * methods.
- * <p>
- * For a feature set of specific menu types, see {@link Menu}.
- */
-public interface MenuItem {
- /**
- * Interface definition for a callback to be invoked when a menu item is
- * clicked.
- *
- * @see Activity#onContextItemSelected(MenuItem)
- * @see Activity#onOptionsItemSelected(MenuItem)
- */
- public interface OnMenuItemClickListener {
- /**
- * Called when a menu item has been invoked. This is the first code
- * that is executed; if it returns true, no other callbacks will be
- * executed.
- *
- * @param item The menu item that was invoked.
- *
- * @return Return true to consume this click and prevent others from
- * executing.
- */
- public boolean onMenuItemClick(MenuItem item);
- }
-
- /**
- * Return the identifier for this menu item. The identifier can not
- * be changed after the menu is created.
- *
- * @return The menu item's identifier.
- */
- public int getItemId();
-
- /**
- * Return the group identifier that this menu item is part of. The group
- * identifier can not be changed after the menu is created.
- *
- * @return The menu item's group identifier.
- */
- public int getGroupId();
-
- /**
- * Return the category and order within the category of this item. This
- * item will be shown before all items (within its category) that have
- * order greater than this value.
- * <p>
- * An order integer contains the item's category (the upper bits of the
- * integer; set by or/add the category with the order within the
- * category) and the ordering of the item within that category (the
- * lower bits). Example categories are {@link Menu#CATEGORY_SYSTEM},
- * {@link Menu#CATEGORY_SECONDARY}, {@link Menu#CATEGORY_ALTERNATIVE},
- * {@link Menu#CATEGORY_CONTAINER}. See {@link Menu} for a full list.
- *
- * @return The order of this item.
- */
- public int getOrder();
-
- /**
- * Change the title associated with this item.
- *
- * @param title The new text to be displayed.
- * @return This Item so additional setters can be called.
- */
- public MenuItem setTitle(CharSequence title);
-
- /**
- * Change the title associated with this item.
- * <p>
- * Some menu types do not sufficient space to show the full title, and
- * instead a condensed title is preferred. See {@link Menu} for more
- * information.
- *
- * @param title The resource id of the new text to be displayed.
- * @return This Item so additional setters can be called.
- * @see #setTitleCondensed(CharSequence)
- */
-
- public MenuItem setTitle(int title);
-
- /**
- * Retrieve the current title of the item.
- *
- * @return The title.
- */
- public CharSequence getTitle();
-
- /**
- * Change the condensed title associated with this item. The condensed
- * title is used in situations where the normal title may be too long to
- * be displayed.
- *
- * @param title The new text to be displayed as the condensed title.
- * @return This Item so additional setters can be called.
- */
- public MenuItem setTitleCondensed(CharSequence title);
-
- /**
- * Retrieve the current condensed title of the item. If a condensed
- * title was never set, it will return the normal title.
- *
- * @return The condensed title, if it exists.
- * Otherwise the normal title.
- */
- public CharSequence getTitleCondensed();
-
- /**
- * Change the icon associated with this item. This icon will not always be
- * shown, so the title should be sufficient in describing this item. See
- * {@link Menu} for the menu types that support icons.
- *
- * @param icon The new icon (as a Drawable) to be displayed.
- * @return This Item so additional setters can be called.
- */
- public MenuItem setIcon(Drawable icon);
-
- /**
- * Change the icon associated with this item. This icon will not always be
- * shown, so the title should be sufficient in describing this item. See
- * {@link Menu} for the menu types that support icons.
- * <p>
- * This method will set the resource ID of the icon which will be used to
- * lazily get the Drawable when this item is being shown.
- *
- * @param iconRes The new icon (as a resource ID) to be displayed.
- * @return This Item so additional setters can be called.
- */
- public MenuItem setIcon(int iconRes);
-
- /**
- * Returns the icon for this item as a Drawable (getting it from resources if it hasn't been
- * loaded before).
- *
- * @return The icon as a Drawable.
- */
- public Drawable getIcon();
-
- /**
- * Change the Intent associated with this item. By default there is no
- * Intent associated with a menu item. If you set one, and nothing
- * else handles the item, then the default behavior will be to call
- * {@link android.content.Context#startActivity} with the given Intent.
- *
- * <p>Note that setIntent() can not be used with the versions of
- * {@link Menu#add} that take a Runnable, because {@link Runnable#run}
- * does not return a value so there is no way to tell if it handled the
- * item. In this case it is assumed that the Runnable always handles
- * the item, and the intent will never be started.
- *
- * @see #getIntent
- * @param intent The Intent to associated with the item. This Intent
- * object is <em>not</em> copied, so be careful not to
- * modify it later.
- * @return This Item so additional setters can be called.
- */
- public MenuItem setIntent(Intent intent);
-
- /**
- * Return the Intent associated with this item. This returns a
- * reference to the Intent which you can change as desired to modify
- * what the Item is holding.
- *
- * @see #setIntent
- * @return Returns the last value supplied to {@link #setIntent}, or
- * null.
- */
- public Intent getIntent();
-
- /**
- * Change both the numeric and alphabetic shortcut associated with this
- * item. Note that the shortcut will be triggered when the key that
- * generates the given character is pressed alone or along with with the alt
- * key. Also note that case is not significant and that alphabetic shortcut
- * characters will be displayed in lower case.
- * <p>
- * See {@link Menu} for the menu types that support shortcuts.
- *
- * @param numericChar The numeric shortcut key. This is the shortcut when
- * using a numeric (e.g., 12-key) keyboard.
- * @param alphaChar The alphabetic shortcut key. This is the shortcut when
- * using a keyboard with alphabetic keys.
- * @return This Item so additional setters can be called.
- */
- public MenuItem setShortcut(char numericChar, char alphaChar);
-
- /**
- * Change the numeric shortcut associated with this item.
- * <p>
- * See {@link Menu} for the menu types that support shortcuts.
- *
- * @param numericChar The numeric shortcut key. This is the shortcut when
- * using a 12-key (numeric) keyboard.
- * @return This Item so additional setters can be called.
- */
- public MenuItem setNumericShortcut(char numericChar);
-
- /**
- * Return the char for this menu item's numeric (12-key) shortcut.
- *
- * @return Numeric character to use as a shortcut.
- */
- public char getNumericShortcut();
-
- /**
- * Change the alphabetic shortcut associated with this item. The shortcut
- * will be triggered when the key that generates the given character is
- * pressed alone or along with with the alt key. Case is not significant and
- * shortcut characters will be displayed in lower case. Note that menu items
- * with the characters '\b' or '\n' as shortcuts will get triggered by the
- * Delete key or Carriage Return key, respectively.
- * <p>
- * See {@link Menu} for the menu types that support shortcuts.
- *
- * @param alphaChar The alphabetic shortcut key. This is the shortcut when
- * using a keyboard with alphabetic keys.
- * @return This Item so additional setters can be called.
- */
- public MenuItem setAlphabeticShortcut(char alphaChar);
-
- /**
- * Return the char for this menu item's alphabetic shortcut.
- *
- * @return Alphabetic character to use as a shortcut.
- */
- public char getAlphabeticShortcut();
-
- /**
- * Control whether this item can display a check mark. Setting this does
- * not actually display a check mark (see {@link #setChecked} for that);
- * rather, it ensures there is room in the item in which to display a
- * check mark.
- * <p>
- * See {@link Menu} for the menu types that support check marks.
- *
- * @param checkable Set to true to allow a check mark, false to
- * disallow. The default is false.
- * @see #setChecked
- * @see #isCheckable
- * @see Menu#setGroupCheckable
- * @return This Item so additional setters can be called.
- */
- public MenuItem setCheckable(boolean checkable);
-
- /**
- * Return whether the item can currently display a check mark.
- *
- * @return If a check mark can be displayed, returns true.
- *
- * @see #setCheckable
- */
- public boolean isCheckable();
-
- /**
- * Control whether this item is shown with a check mark. Note that you
- * must first have enabled checking with {@link #setCheckable} or else
- * the check mark will not appear. If this item is a member of a group that contains
- * mutually-exclusive items (set via {@link Menu#setGroupCheckable(int, boolean, boolean)},
- * the other items in the group will be unchecked.
- * <p>
- * See {@link Menu} for the menu types that support check marks.
- *
- * @see #setCheckable
- * @see #isChecked
- * @see Menu#setGroupCheckable
- * @param checked Set to true to display a check mark, false to hide
- * it. The default value is false.
- * @return This Item so additional setters can be called.
- */
- public MenuItem setChecked(boolean checked);
-
- /**
- * Return whether the item is currently displaying a check mark.
- *
- * @return If a check mark is displayed, returns true.
- *
- * @see #setChecked
- */
- public boolean isChecked();
-
- /**
- * Sets the visibility of the menu item. Even if a menu item is not visible,
- * it may still be invoked via its shortcut (to completely disable an item,
- * set it to invisible and {@link #setEnabled(boolean) disabled}).
- *
- * @param visible If true then the item will be visible; if false it is
- * hidden.
- * @return This Item so additional setters can be called.
- */
- public MenuItem setVisible(boolean visible);
-
- /**
- * Return the visibility of the menu item.
- *
- * @return If true the item is visible; else it is hidden.
- */
- public boolean isVisible();
-
- /**
- * Sets whether the menu item is enabled. Disabling a menu item will not
- * allow it to be invoked via its shortcut. The menu item will still be
- * visible.
- *
- * @param enabled If true then the item will be invokable; if false it is
- * won't be invokable.
- * @return This Item so additional setters can be called.
- */
- public MenuItem setEnabled(boolean enabled);
-
- /**
- * Return the enabled state of the menu item.
- *
- * @return If true the item is enabled and hence invokable; else it is not.
- */
- public boolean isEnabled();
-
- /**
- * Check whether this item has an associated sub-menu. I.e. it is a
- * sub-menu of another menu.
- *
- * @return If true this item has a menu; else it is a
- * normal item.
- */
- public boolean hasSubMenu();
-
- /**
- * Get the sub-menu to be invoked when this item is selected, if it has
- * one. See {@link #hasSubMenu()}.
- *
- * @return The associated menu if there is one, else null
- */
- public SubMenu getSubMenu();
-
- /**
- * Set a custom listener for invocation of this menu item. In most
- * situations, it is more efficient and easier to use
- * {@link Activity#onOptionsItemSelected(MenuItem)} or
- * {@link Activity#onContextItemSelected(MenuItem)}.
- *
- * @param menuItemClickListener The object to receive invokations.
- * @return This Item so additional setters can be called.
- * @see Activity#onOptionsItemSelected(MenuItem)
- * @see Activity#onContextItemSelected(MenuItem)
- */
- public MenuItem setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener menuItemClickListener);
-
- /**
- * Gets the extra information linked to this menu item. This extra
- * information is set by the View that added this menu item to the
- * menu.
- *
- * @see OnCreateContextMenuListener
- * @return The extra information linked to the View that added this
- * menu item to the menu. This can be null.
- */
- public ContextMenuInfo getMenuInfo();
-} \ No newline at end of file
diff --git a/core/java/android/view/MotionEvent.aidl b/core/java/android/view/MotionEvent.aidl
deleted file mode 100644
index 3c89988..0000000
--- a/core/java/android/view/MotionEvent.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android.view.KeyEvent.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.view;
-
-parcelable MotionEvent;
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
deleted file mode 100644
index 882a079..0000000
--- a/core/java/android/view/MotionEvent.java
+++ /dev/null
@@ -1,685 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.SystemClock;
-import android.util.Config;
-
-/**
- * Object used to report movement (mouse, pen, finger, trackball) events. This
- * class may hold either absolute or relative movements, depending on what
- * it is being used for.
- */
-public final class MotionEvent implements Parcelable {
- /**
- * Constant for {@link #getAction}: A pressed gesture has started, the
- * motion contains the initial starting location.
- */
- public static final int ACTION_DOWN = 0;
- /**
- * Constant for {@link #getAction}: A pressed gesture has finished, the
- * motion contains the final release location as well as any intermediate
- * points since the last down or move event.
- */
- public static final int ACTION_UP = 1;
- /**
- * Constant for {@link #getAction}: A change has happened during a
- * press gesture (between {@link #ACTION_DOWN} and {@link #ACTION_UP}).
- * The motion contains the most recent point, as well as any intermediate
- * points since the last down or move event.
- */
- public static final int ACTION_MOVE = 2;
- /**
- * Constant for {@link #getAction}: The current gesture has been aborted.
- * You will not receive any more points in it. You should treat this as
- * an up event, but not perform any action that you normally would.
- */
- public static final int ACTION_CANCEL = 3;
- /**
- * Constant for {@link #getAction}: A movement has happened outside of the
- * normal bounds of the UI element. This does not provide a full gesture,
- * but only the initial location of the movement/touch.
- */
- public static final int ACTION_OUTSIDE = 4;
-
- private static final boolean TRACK_RECYCLED_LOCATION = false;
-
- /**
- * Flag indicating the motion event intersected the top edge of the screen.
- */
- public static final int EDGE_TOP = 0x00000001;
-
- /**
- * Flag indicating the motion event intersected the bottom edge of the screen.
- */
- public static final int EDGE_BOTTOM = 0x00000002;
-
- /**
- * Flag indicating the motion event intersected the left edge of the screen.
- */
- public static final int EDGE_LEFT = 0x00000004;
-
- /**
- * Flag indicating the motion event intersected the right edge of the screen.
- */
- public static final int EDGE_RIGHT = 0x00000008;
-
- static private final int MAX_RECYCLED = 10;
- static private Object gRecyclerLock = new Object();
- static private int gRecyclerUsed = 0;
- static private MotionEvent gRecyclerTop = null;
-
- private long mDownTime;
- private long mEventTime;
- private int mAction;
- private float mX;
- private float mY;
- private float mRawX;
- private float mRawY;
- private float mPressure;
- private float mSize;
- private int mMetaState;
- private int mNumHistory;
- private float[] mHistory;
- private long[] mHistoryTimes;
- private float mXPrecision;
- private float mYPrecision;
- private int mDeviceId;
- private int mEdgeFlags;
-
- private MotionEvent mNext;
- private RuntimeException mRecycledLocation;
- private boolean mRecycled;
-
- private MotionEvent() {
- }
-
- static private MotionEvent obtain() {
- synchronized (gRecyclerLock) {
- if (gRecyclerTop == null) {
- return new MotionEvent();
- }
- MotionEvent ev = gRecyclerTop;
- gRecyclerTop = ev.mNext;
- gRecyclerUsed--;
- ev.mRecycledLocation = null;
- ev.mRecycled = false;
- return ev;
- }
- }
-
- /**
- * Create a new MotionEvent, filling in all of the basic values that
- * define the motion.
- *
- * @param downTime The time (in ms) when the user originally pressed down to start
- * a stream of position events. This must be obtained from {@link SystemClock#uptimeMillis()}.
- * @param eventTime The the time (in ms) when this specific event was generated. This
- * must be obtained from {@link SystemClock#uptimeMillis()}.
- * @param action The kind of action being performed -- one of either
- * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
- * {@link #ACTION_CANCEL}.
- * @param x The X coordinate of this event.
- * @param y The Y coordinate of this event.
- * @param pressure The current pressure of this event. The pressure generally
- * ranges from 0 (no pressure at all) to 1 (normal pressure), however
- * values higher than 1 may be generated depending on the calibration of
- * the input device.
- * @param size A scaled value of the approximate size of the area being pressed when
- * touched with the finger. The actual value in pixels corresponding to the finger
- * touch is normalized with a device specific range of values
- * and scaled to a value between 0 and 1.
- * @param metaState The state of any meta / modifier keys that were in effect when
- * the event was generated.
- * @param xPrecision The precision of the X coordinate being reported.
- * @param yPrecision The precision of the Y coordinate being reported.
- * @param deviceId The id for the device that this event came from. An id of
- * zero indicates that the event didn't come from a physical device; other
- * numbers are arbitrary and you shouldn't depend on the values.
- * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
- * MotionEvent.
- */
- static public MotionEvent obtain(long downTime, long eventTime, int action,
- float x, float y, float pressure, float size, int metaState,
- float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
- MotionEvent ev = obtain();
- ev.mDeviceId = deviceId;
- ev.mEdgeFlags = edgeFlags;
- ev.mDownTime = downTime;
- ev.mEventTime = eventTime;
- ev.mAction = action;
- ev.mX = ev.mRawX = x;
- ev.mY = ev.mRawY = y;
- ev.mPressure = pressure;
- ev.mSize = size;
- ev.mMetaState = metaState;
- ev.mXPrecision = xPrecision;
- ev.mYPrecision = yPrecision;
-
- return ev;
- }
-
- /**
- * Create a new MotionEvent, filling in a subset of the basic motion
- * values. Those not specified here are: device id (always 0), pressure
- * and size (always 1), x and y precision (always 1), and edgeFlags (always 0).
- *
- * @param downTime The time (in ms) when the user originally pressed down to start
- * a stream of position events. This must be obtained from {@link SystemClock#uptimeMillis()}.
- * @param eventTime The the time (in ms) when this specific event was generated. This
- * must be obtained from {@link SystemClock#uptimeMillis()}.
- * @param action The kind of action being performed -- one of either
- * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
- * {@link #ACTION_CANCEL}.
- * @param x The X coordinate of this event.
- * @param y The Y coordinate of this event.
- * @param metaState The state of any meta / modifier keys that were in effect when
- * the event was generated.
- */
- static public MotionEvent obtain(long downTime, long eventTime, int action,
- float x, float y, int metaState) {
- MotionEvent ev = obtain();
- ev.mDeviceId = 0;
- ev.mEdgeFlags = 0;
- ev.mDownTime = downTime;
- ev.mEventTime = eventTime;
- ev.mAction = action;
- ev.mX = ev.mRawX = x;
- ev.mY = ev.mRawY = y;
- ev.mPressure = 1.0f;
- ev.mSize = 1.0f;
- ev.mMetaState = metaState;
- ev.mXPrecision = 1.0f;
- ev.mYPrecision = 1.0f;
-
- return ev;
- }
-
- /**
- * Create a new MotionEvent, copying from an existing one.
- */
- static public MotionEvent obtain(MotionEvent o) {
- MotionEvent ev = obtain();
- ev.mDeviceId = o.mDeviceId;
- ev.mEdgeFlags = o.mEdgeFlags;
- ev.mDownTime = o.mDownTime;
- ev.mEventTime = o.mEventTime;
- ev.mAction = o.mAction;
- ev.mX = o.mX;
- ev.mRawX = o.mRawX;
- ev.mY = o.mY;
- ev.mRawY = o.mRawY;
- ev.mPressure = o.mPressure;
- ev.mSize = o.mSize;
- ev.mMetaState = o.mMetaState;
- ev.mXPrecision = o.mXPrecision;
- ev.mYPrecision = o.mYPrecision;
- final int N = o.mNumHistory;
- ev.mNumHistory = N;
- if (N > 0) {
- // could be more efficient about this...
- ev.mHistory = (float[])o.mHistory.clone();
- ev.mHistoryTimes = (long[])o.mHistoryTimes.clone();
- }
- return ev;
- }
-
- /**
- * Recycle the MotionEvent, to be re-used by a later caller. After calling
- * this function you must not ever touch the event again.
- */
- public void recycle() {
- // Ensure recycle is only called once!
- if (TRACK_RECYCLED_LOCATION) {
- if (mRecycledLocation != null) {
- throw new RuntimeException(toString() + " recycled twice!", mRecycledLocation);
- }
- mRecycledLocation = new RuntimeException("Last recycled here");
- } else if (mRecycled) {
- throw new RuntimeException(toString() + " recycled twice!");
- }
-
- //Log.w("MotionEvent", "Recycling event " + this, mRecycledLocation);
- synchronized (gRecyclerLock) {
- if (gRecyclerUsed < MAX_RECYCLED) {
- gRecyclerUsed++;
- mNumHistory = 0;
- mNext = gRecyclerTop;
- gRecyclerTop = this;
- }
- }
- }
-
- /**
- * Return the kind of action being performed -- one of either
- * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
- * {@link #ACTION_CANCEL}.
- */
- public final int getAction() {
- return mAction;
- }
-
- /**
- * Returns the time (in ms) when the user originally pressed down to start
- * a stream of position events.
- */
- public final long getDownTime() {
- return mDownTime;
- }
-
- /**
- * Returns the time (in ms) when this specific event was generated.
- */
- public final long getEventTime() {
- return mEventTime;
- }
-
- /**
- * Returns the X coordinate of this event. Whole numbers are pixels; the
- * value may have a fraction for input devices that are sub-pixel precise.
- */
- public final float getX() {
- return mX;
- }
-
- /**
- * Returns the Y coordinate of this event. Whole numbers are pixels; the
- * value may have a fraction for input devices that are sub-pixel precise.
- */
- public final float getY() {
- return mY;
- }
-
- /**
- * Returns the current pressure of this event. The pressure generally
- * ranges from 0 (no pressure at all) to 1 (normal pressure), however
- * values higher than 1 may be generated depending on the calibration of
- * the input device.
- */
- public final float getPressure() {
- return mPressure;
- }
-
- /**
- * Returns a scaled value of the approximate size, of the area being pressed when
- * touched with the finger. The actual value in pixels corresponding to the finger
- * touch is normalized with the device specific range of values
- * and scaled to a value between 0 and 1. The value of size can be used to
- * determine fat touch events.
- */
- public final float getSize() {
- return mSize;
- }
-
- /**
- * Returns the state of any meta / modifier keys that were in effect when
- * the event was generated. This is the same values as those
- * returned by {@link KeyEvent#getMetaState() KeyEvent.getMetaState}.
- *
- * @return an integer in which each bit set to 1 represents a pressed
- * meta key
- *
- * @see KeyEvent#getMetaState()
- */
- public final int getMetaState() {
- return mMetaState;
- }
-
- /**
- * Returns the original raw X coordinate of this event. For touch
- * events on the screen, this is the original location of the event
- * on the screen, before it had been adjusted for the containing window
- * and views.
- */
- public final float getRawX() {
- return mRawX;
- }
-
- /**
- * Returns the original raw Y coordinate of this event. For touch
- * events on the screen, this is the original location of the event
- * on the screen, before it had been adjusted for the containing window
- * and views.
- */
- public final float getRawY() {
- return mRawY;
- }
-
- /**
- * Return the precision of the X coordinates being reported. You can
- * multiple this number with {@link #getX} to find the actual hardware
- * value of the X coordinate.
- * @return Returns the precision of X coordinates being reported.
- */
- public final float getXPrecision() {
- return mXPrecision;
- }
-
- /**
- * Return the precision of the Y coordinates being reported. You can
- * multiple this number with {@link #getY} to find the actual hardware
- * value of the Y coordinate.
- * @return Returns the precision of Y coordinates being reported.
- */
- public final float getYPrecision() {
- return mYPrecision;
- }
-
- /**
- * Returns the number of historical points in this event. These are
- * movements that have occurred between this event and the previous event.
- * This only applies to ACTION_MOVE events -- all other actions will have
- * a size of 0.
- *
- * @return Returns the number of historical points in the event.
- */
- public final int getHistorySize() {
- return mNumHistory;
- }
-
- /**
- * Returns the time that a historical movement occurred between this event
- * and the previous event. Only applies to ACTION_MOVE events.
- *
- * @param pos Which historical value to return; must be less than
- * {@link #getHistorySize}
- *
- * @see #getHistorySize
- * @see #getEventTime
- */
- public final long getHistoricalEventTime(int pos) {
- return mHistoryTimes[pos];
- }
-
- /**
- * Returns a historical X coordinate that occurred between this event
- * and the previous event. Only applies to ACTION_MOVE events.
- *
- * @param pos Which historical value to return; must be less than
- * {@link #getHistorySize}
- *
- * @see #getHistorySize
- * @see #getX
- */
- public final float getHistoricalX(int pos) {
- return mHistory[pos*4];
- }
-
- /**
- * Returns a historical Y coordinate that occurred between this event
- * and the previous event. Only applies to ACTION_MOVE events.
- *
- * @param pos Which historical value to return; must be less than
- * {@link #getHistorySize}
- *
- * @see #getHistorySize
- * @see #getY
- */
- public final float getHistoricalY(int pos) {
- return mHistory[pos*4 + 1];
- }
-
- /**
- * Returns a historical pressure coordinate that occurred between this event
- * and the previous event. Only applies to ACTION_MOVE events.
- *
- * @param pos Which historical value to return; must be less than
- * {@link #getHistorySize}
- *
- * @see #getHistorySize
- * @see #getPressure
- */
- public final float getHistoricalPressure(int pos) {
- return mHistory[pos*4 + 2];
- }
-
- /**
- * Returns a historical size coordinate that occurred between this event
- * and the previous event. Only applies to ACTION_MOVE events.
- *
- * @param pos Which historical value to return; must be less than
- * {@link #getHistorySize}
- *
- * @see #getHistorySize
- * @see #getSize
- */
- public final float getHistoricalSize(int pos) {
- return mHistory[pos*4 + 3];
- }
-
- /**
- * Return the id for the device that this event came from. An id of
- * zero indicates that the event didn't come from a physical device; other
- * numbers are arbitrary and you shouldn't depend on the values.
- */
- public final int getDeviceId() {
- return mDeviceId;
- }
-
- /**
- * Returns a bitfield indicating which edges, if any, where touched by this
- * MotionEvent. For touch events, clients can use this to determine if the
- * user's finger was touching the edge of the display.
- *
- * @see #EDGE_LEFT
- * @see #EDGE_TOP
- * @see #EDGE_RIGHT
- * @see #EDGE_BOTTOM
- */
- public final int getEdgeFlags() {
- return mEdgeFlags;
- }
-
-
- /**
- * Sets the bitfield indicating which edges, if any, where touched by this
- * MotionEvent.
- *
- * @see #getEdgeFlags()
- */
- public final void setEdgeFlags(int flags) {
- mEdgeFlags = flags;
- }
-
- /**
- * Sets this event's action.
- */
- public final void setAction(int action) {
- mAction = action;
- }
-
- /**
- * Adjust this event's location.
- * @param deltaX Amount to add to the current X coordinate of the event.
- * @param deltaY Amount to add to the current Y coordinate of the event.
- */
- public final void offsetLocation(float deltaX, float deltaY) {
- mX += deltaX;
- mY += deltaY;
- final int N = mNumHistory*4;
- if (N <= 0) {
- return;
- }
- final float[] pos = mHistory;
- for (int i=0; i<N; i+=4) {
- pos[i] += deltaX;
- pos[i+1] += deltaY;
- }
- }
-
- /**
- * Set this event's location. Applies {@link #offsetLocation} with a
- * delta from the current location to the given new location.
- *
- * @param x New absolute X location.
- * @param y New absolute Y location.
- */
- public final void setLocation(float x, float y) {
- float deltaX = x-mX;
- float deltaY = y-mY;
- if (deltaX != 0 || deltaY != 0) {
- offsetLocation(deltaX, deltaY);
- }
- }
-
- /**
- * Add a new movement to the batch of movements in this event. The event's
- * current location, position and size is updated to the new values. In
- * the future, the current values in the event will be added to a list of
- * historic values.
- *
- * @param x The new X position.
- * @param y The new Y position.
- * @param pressure The new pressure.
- * @param size The new size.
- */
- public final void addBatch(long eventTime, float x, float y,
- float pressure, float size, int metaState) {
- float[] history = mHistory;
- long[] historyTimes = mHistoryTimes;
- int N;
- int avail;
- if (history == null) {
- mHistory = history = new float[8*4];
- mHistoryTimes = historyTimes = new long[8];
- mNumHistory = N = 0;
- avail = 8;
- } else {
- N = mNumHistory;
- avail = history.length/4;
- if (N == avail) {
- avail += 8;
- float[] newHistory = new float[avail*4];
- System.arraycopy(history, 0, newHistory, 0, N*4);
- mHistory = history = newHistory;
- long[] newHistoryTimes = new long[avail];
- System.arraycopy(historyTimes, 0, newHistoryTimes, 0, N);
- mHistoryTimes = historyTimes = newHistoryTimes;
- }
- }
-
- historyTimes[N] = mEventTime;
-
- final int pos = N*4;
- history[pos] = mX;
- history[pos+1] = mY;
- history[pos+2] = mPressure;
- history[pos+3] = mSize;
- mNumHistory = N+1;
-
- mEventTime = eventTime;
- mX = mRawX = x;
- mY = mRawY = y;
- mPressure = pressure;
- mSize = size;
- mMetaState |= metaState;
- }
-
- @Override
- public String toString() {
- return "MotionEvent{" + Integer.toHexString(System.identityHashCode(this))
- + " action=" + mAction + " x=" + mX
- + " y=" + mY + " pressure=" + mPressure + " size=" + mSize + "}";
- }
-
- public static final Parcelable.Creator<MotionEvent> CREATOR
- = new Parcelable.Creator<MotionEvent>() {
- public MotionEvent createFromParcel(Parcel in) {
- MotionEvent ev = obtain();
- ev.readFromParcel(in);
- return ev;
- }
-
- public MotionEvent[] newArray(int size) {
- return new MotionEvent[size];
- }
- };
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeLong(mDownTime);
- out.writeLong(mEventTime);
- out.writeInt(mAction);
- out.writeFloat(mX);
- out.writeFloat(mY);
- out.writeFloat(mPressure);
- out.writeFloat(mSize);
- out.writeInt(mMetaState);
- out.writeFloat(mRawX);
- out.writeFloat(mRawY);
- final int N = mNumHistory;
- out.writeInt(N);
- if (N > 0) {
- final int N4 = N*4;
- int i;
- float[] history = mHistory;
- for (i=0; i<N4; i++) {
- out.writeFloat(history[i]);
- }
- long[] times = mHistoryTimes;
- for (i=0; i<N; i++) {
- out.writeLong(times[i]);
- }
- }
- out.writeFloat(mXPrecision);
- out.writeFloat(mYPrecision);
- out.writeInt(mDeviceId);
- out.writeInt(mEdgeFlags);
- }
-
- private void readFromParcel(Parcel in) {
- mDownTime = in.readLong();
- mEventTime = in.readLong();
- mAction = in.readInt();
- mX = in.readFloat();
- mY = in.readFloat();
- mPressure = in.readFloat();
- mSize = in.readFloat();
- mMetaState = in.readInt();
- mRawX = in.readFloat();
- mRawY = in.readFloat();
- final int N = in.readInt();
- if ((mNumHistory=N) > 0) {
- final int N4 = N*4;
- float[] history = mHistory;
- if (history == null || history.length < N4) {
- mHistory = history = new float[N4 + (4*4)];
- }
- for (int i=0; i<N4; i++) {
- history[i] = in.readFloat();
- }
- long[] times = mHistoryTimes;
- if (times == null || times.length < N) {
- mHistoryTimes = times = new long[N + 4];
- }
- for (int i=0; i<N; i++) {
- times[i] = in.readLong();
- }
- }
- mXPrecision = in.readFloat();
- mYPrecision = in.readFloat();
- mDeviceId = in.readInt();
- mEdgeFlags = in.readInt();
- }
-
-}
-
diff --git a/core/java/android/view/OrientationEventListener.java b/core/java/android/view/OrientationEventListener.java
deleted file mode 100755
index 391ba1e..0000000
--- a/core/java/android/view/OrientationEventListener.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.content.Context;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.util.Config;
-import android.util.Log;
-
-/**
- * Helper class for receiving notifications from the SensorManager when
- * the orientation of the device has changed.
- */
-public abstract class OrientationEventListener {
- private static final String TAG = "OrientationEventListener";
- private static final boolean DEBUG = false;
- private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
- private int mOrientation = ORIENTATION_UNKNOWN;
- private SensorManager mSensorManager;
- private boolean mEnabled = false;
- private int mRate;
- private Sensor mSensor;
- private SensorEventListener mSensorEventListener;
- private OrientationListener mOldListener;
-
- /**
- * Returned from onOrientationChanged when the device orientation cannot be determined
- * (typically when the device is in a close to flat position).
- *
- * @see #onOrientationChanged
- */
- public static final int ORIENTATION_UNKNOWN = -1;
-
- /**
- * Creates a new OrientationEventListener.
- *
- * @param context for the OrientationEventListener.
- */
- public OrientationEventListener(Context context) {
- this(context, SensorManager.SENSOR_DELAY_NORMAL);
- }
-
- /**
- * Creates a new OrientationEventListener.
- *
- * @param context for the OrientationEventListener.
- * @param rate at which sensor events are processed (see also
- * {@link android.hardware.SensorManager SensorManager}). Use the default
- * value of {@link android.hardware.SensorManager#SENSOR_DELAY_NORMAL
- * SENSOR_DELAY_NORMAL} for simple screen orientation change detection.
- */
- public OrientationEventListener(Context context, int rate) {
- mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
- mRate = rate;
- mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- if (mSensor != null) {
- // Create listener only if sensors do exist
- mSensorEventListener = new SensorEventListenerImpl();
- }
- }
-
- void registerListener(OrientationListener lis) {
- mOldListener = lis;
- }
-
- /**
- * Enables the OrientationEventListener so it will monitor the sensor and call
- * {@link #onOrientationChanged} when the device orientation changes.
- */
- public void enable() {
- if (mSensor == null) {
- Log.w(TAG, "Cannot detect sensors. Not enabled");
- return;
- }
- if (mEnabled == false) {
- if (localLOGV) Log.d(TAG, "OrientationEventListener enabled");
- mSensorManager.registerListener(mSensorEventListener, mSensor, mRate);
- mEnabled = true;
- }
- }
-
- /**
- * Disables the OrientationEventListener.
- */
- public void disable() {
- if (mSensor == null) {
- Log.w(TAG, "Cannot detect sensors. Invalid disable");
- return;
- }
- if (mEnabled == true) {
- if (localLOGV) Log.d(TAG, "OrientationEventListener disabled");
- mSensorManager.unregisterListener(mSensorEventListener);
- mEnabled = false;
- }
- }
-
- class SensorEventListenerImpl implements SensorEventListener {
- private static final int _DATA_X = 0;
- private static final int _DATA_Y = 1;
- private static final int _DATA_Z = 2;
-
- public void onSensorChanged(SensorEvent event) {
- float[] values = event.values;
- int orientation = ORIENTATION_UNKNOWN;
- float X = -values[_DATA_X];
- float Y = -values[_DATA_Y];
- float Z = -values[_DATA_Z];
- float magnitude = X*X + Y*Y;
- // Don't trust the angle if the magnitude is small compared to the y value
- if (magnitude * 4 >= Z*Z) {
- float OneEightyOverPi = 57.29577957855f;
- float angle = (float)Math.atan2(-Y, X) * OneEightyOverPi;
- orientation = 90 - (int)Math.round(angle);
- // normalize to 0 - 359 range
- while (orientation >= 360) {
- orientation -= 360;
- }
- while (orientation < 0) {
- orientation += 360;
- }
- }
- if (mOldListener != null) {
- mOldListener.onSensorChanged(Sensor.TYPE_ACCELEROMETER, event.values);
- }
- if (orientation != mOrientation) {
- mOrientation = orientation;
- onOrientationChanged(orientation);
- }
- }
-
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
-
- }
- }
-
- /*
- * Returns true if sensor is enabled and false otherwise
- */
- public boolean canDetectOrientation() {
- return mSensor != null;
- }
-
- /**
- * Called when the orientation of the device has changed.
- * orientation parameter is in degrees, ranging from 0 to 359.
- * orientation is 0 degrees when the device is oriented in its natural position,
- * 90 degrees when its left side is at the top, 180 degrees when it is upside down,
- * and 270 degrees when its right side is to the top.
- * {@link #ORIENTATION_UNKNOWN} is returned when the device is close to flat
- * and the orientation cannot be determined.
- *
- * @param orientation The new orientation of the device.
- *
- * @see #ORIENTATION_UNKNOWN
- */
- abstract public void onOrientationChanged(int orientation);
-}
diff --git a/core/java/android/view/OrientationListener.java b/core/java/android/view/OrientationListener.java
deleted file mode 100644
index ce8074e..0000000
--- a/core/java/android/view/OrientationListener.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.content.Context;
-import android.hardware.SensorListener;
-
-/**
- * Helper class for receiving notifications from the SensorManager when
- * the orientation of the device has changed.
- * @deprecated use {@link android.view.OrientationEventListener} instead.
- * This class internally uses the OrientationEventListener.
- */
-@Deprecated
-public abstract class OrientationListener implements SensorListener {
- private OrientationEventListener mOrientationEventLis;
-
- /**
- * Returned from onOrientationChanged when the device orientation cannot be determined
- * (typically when the device is in a close to flat position).
- *
- * @see #onOrientationChanged
- */
- public static final int ORIENTATION_UNKNOWN = OrientationEventListener.ORIENTATION_UNKNOWN;
-
- /**
- * Creates a new OrientationListener.
- *
- * @param context for the OrientationListener.
- */
- public OrientationListener(Context context) {
- mOrientationEventLis = new OrientationEventListenerInternal(context);
- }
-
- /**
- * Creates a new OrientationListener.
- *
- * @param context for the OrientationListener.
- * @param rate at which sensor events are processed (see also
- * {@link android.hardware.SensorManager SensorManager}). Use the default
- * value of {@link android.hardware.SensorManager#SENSOR_DELAY_NORMAL
- * SENSOR_DELAY_NORMAL} for simple screen orientation change detection.
- */
- public OrientationListener(Context context, int rate) {
- mOrientationEventLis = new OrientationEventListenerInternal(context, rate);
- }
-
- class OrientationEventListenerInternal extends OrientationEventListener {
- OrientationEventListenerInternal(Context context) {
- super(context);
- }
-
- OrientationEventListenerInternal(Context context, int rate) {
- super(context, rate);
- // register so that onSensorChanged gets invoked
- registerListener(OrientationListener.this);
- }
-
- public void onOrientationChanged(int orientation) {
- OrientationListener.this.onOrientationChanged(orientation);
- }
- }
-
- /**
- * Enables the OrientationListener so it will monitor the sensor and call
- * {@link #onOrientationChanged} when the device orientation changes.
- */
- public void enable() {
- mOrientationEventLis.enable();
- }
-
- /**
- * Disables the OrientationListener.
- */
- public void disable() {
- mOrientationEventLis.disable();
- }
-
- public void onAccuracyChanged(int sensor, int accuracy) {
- }
-
- public void onSensorChanged(int sensor, float[] values) {
- // just ignore the call here onOrientationChanged is invoked anyway
- }
-
-
- /**
- * Look at {@link android.view.OrientationEventListener#onOrientationChanged}
- * for method description and usage
- * @param orientation The new orientation of the device.
- *
- * @see #ORIENTATION_UNKNOWN
- */
- abstract public void onOrientationChanged(int orientation);
-
-}
diff --git a/core/java/android/view/RawInputEvent.java b/core/java/android/view/RawInputEvent.java
deleted file mode 100644
index 30da83e..0000000
--- a/core/java/android/view/RawInputEvent.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/**
- *
- */
-package android.view;
-
-/**
- * @hide
- * This really belongs in services.jar; WindowManagerPolicy should go there too.
- */
-public class RawInputEvent {
- // Event class as defined by EventHub.
- public static final int CLASS_KEYBOARD = 0x00000001;
- public static final int CLASS_ALPHAKEY = 0x00000002;
- public static final int CLASS_TOUCHSCREEN = 0x00000004;
- public static final int CLASS_TRACKBALL = 0x00000008;
-
- // More special classes for QueuedEvent below.
- public static final int CLASS_CONFIGURATION_CHANGED = 0x10000000;
-
- // Event types.
-
- public static final int EV_SYN = 0x00;
- public static final int EV_KEY = 0x01;
- public static final int EV_REL = 0x02;
- public static final int EV_ABS = 0x03;
- public static final int EV_MSC = 0x04;
- public static final int EV_SW = 0x05;
- public static final int EV_LED = 0x11;
- public static final int EV_SND = 0x12;
- public static final int EV_REP = 0x14;
- public static final int EV_FF = 0x15;
- public static final int EV_PWR = 0x16;
- public static final int EV_FF_STATUS = 0x17;
-
- // Platform-specific event types.
-
- public static final int EV_DEVICE_ADDED = 0x10000000;
- public static final int EV_DEVICE_REMOVED = 0x20000000;
-
- // Special key (EV_KEY) scan codes for pointer buttons.
-
- public static final int BTN_FIRST = 0x100;
-
- public static final int BTN_MISC = 0x100;
- public static final int BTN_0 = 0x100;
- public static final int BTN_1 = 0x101;
- public static final int BTN_2 = 0x102;
- public static final int BTN_3 = 0x103;
- public static final int BTN_4 = 0x104;
- public static final int BTN_5 = 0x105;
- public static final int BTN_6 = 0x106;
- public static final int BTN_7 = 0x107;
- public static final int BTN_8 = 0x108;
- public static final int BTN_9 = 0x109;
-
- public static final int BTN_MOUSE = 0x110;
- public static final int BTN_LEFT = 0x110;
- public static final int BTN_RIGHT = 0x111;
- public static final int BTN_MIDDLE = 0x112;
- public static final int BTN_SIDE = 0x113;
- public static final int BTN_EXTRA = 0x114;
- public static final int BTN_FORWARD = 0x115;
- public static final int BTN_BACK = 0x116;
- public static final int BTN_TASK = 0x117;
-
- public static final int BTN_JOYSTICK = 0x120;
- public static final int BTN_TRIGGER = 0x120;
- public static final int BTN_THUMB = 0x121;
- public static final int BTN_THUMB2 = 0x122;
- public static final int BTN_TOP = 0x123;
- public static final int BTN_TOP2 = 0x124;
- public static final int BTN_PINKIE = 0x125;
- public static final int BTN_BASE = 0x126;
- public static final int BTN_BASE2 = 0x127;
- public static final int BTN_BASE3 = 0x128;
- public static final int BTN_BASE4 = 0x129;
- public static final int BTN_BASE5 = 0x12a;
- public static final int BTN_BASE6 = 0x12b;
- public static final int BTN_DEAD = 0x12f;
-
- public static final int BTN_GAMEPAD = 0x130;
- public static final int BTN_A = 0x130;
- public static final int BTN_B = 0x131;
- public static final int BTN_C = 0x132;
- public static final int BTN_X = 0x133;
- public static final int BTN_Y = 0x134;
- public static final int BTN_Z = 0x135;
- public static final int BTN_TL = 0x136;
- public static final int BTN_TR = 0x137;
- public static final int BTN_TL2 = 0x138;
- public static final int BTN_TR2 = 0x139;
- public static final int BTN_SELECT = 0x13a;
- public static final int BTN_START = 0x13b;
- public static final int BTN_MODE = 0x13c;
- public static final int BTN_THUMBL = 0x13d;
- public static final int BTN_THUMBR = 0x13e;
-
- public static final int BTN_DIGI = 0x140;
- public static final int BTN_TOOL_PEN = 0x140;
- public static final int BTN_TOOL_RUBBER = 0x141;
- public static final int BTN_TOOL_BRUSH = 0x142;
- public static final int BTN_TOOL_PENCIL = 0x143;
- public static final int BTN_TOOL_AIRBRUSH = 0x144;
- public static final int BTN_TOOL_FINGER = 0x145;
- public static final int BTN_TOOL_MOUSE = 0x146;
- public static final int BTN_TOOL_LENS = 0x147;
- public static final int BTN_TOUCH = 0x14a;
- public static final int BTN_STYLUS = 0x14b;
- public static final int BTN_STYLUS2 = 0x14c;
- public static final int BTN_TOOL_DOUBLETAP = 0x14d;
- public static final int BTN_TOOL_TRIPLETAP = 0x14e;
-
- public static final int BTN_WHEEL = 0x150;
- public static final int BTN_GEAR_DOWN = 0x150;
- public static final int BTN_GEAR_UP = 0x151;
-
- public static final int BTN_LAST = 0x15f;
-
- // Relative axes (EV_REL) scan codes.
-
- public static final int REL_X = 0x00;
- public static final int REL_Y = 0x01;
- public static final int REL_Z = 0x02;
- public static final int REL_RX = 0x03;
- public static final int REL_RY = 0x04;
- public static final int REL_RZ = 0x05;
- public static final int REL_HWHEEL = 0x06;
- public static final int REL_DIAL = 0x07;
- public static final int REL_WHEEL = 0x08;
- public static final int REL_MISC = 0x09;
- public static final int REL_MAX = 0x0f;
-
- // Absolute axes (EV_ABS) scan codes.
-
- public static final int ABS_X = 0x00;
- public static final int ABS_Y = 0x01;
- public static final int ABS_Z = 0x02;
- public static final int ABS_RX = 0x03;
- public static final int ABS_RY = 0x04;
- public static final int ABS_RZ = 0x05;
- public static final int ABS_THROTTLE = 0x06;
- public static final int ABS_RUDDER = 0x07;
- public static final int ABS_WHEEL = 0x08;
- public static final int ABS_GAS = 0x09;
- public static final int ABS_BRAKE = 0x0a;
- public static final int ABS_HAT0X = 0x10;
- public static final int ABS_HAT0Y = 0x11;
- public static final int ABS_HAT1X = 0x12;
- public static final int ABS_HAT1Y = 0x13;
- public static final int ABS_HAT2X = 0x14;
- public static final int ABS_HAT2Y = 0x15;
- public static final int ABS_HAT3X = 0x16;
- public static final int ABS_HAT3Y = 0x17;
- public static final int ABS_PRESSURE = 0x18;
- public static final int ABS_DISTANCE = 0x19;
- public static final int ABS_TILT_X = 0x1a;
- public static final int ABS_TILT_Y = 0x1b;
- public static final int ABS_TOOL_WIDTH = 0x1c;
- public static final int ABS_VOLUME = 0x20;
- public static final int ABS_MISC = 0x28;
- public static final int ABS_MAX = 0x3f;
-
- public int deviceId;
- public int type;
- public int scancode;
- public int keycode;
- public int flags;
- public int value;
- public long when;
-}
diff --git a/core/java/android/view/RemotableViewMethod.java b/core/java/android/view/RemotableViewMethod.java
deleted file mode 100644
index 4318290..0000000
--- a/core/java/android/view/RemotableViewMethod.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * @hide
- * This annotation indicates that a method on a subclass of View
- * is alllowed to be used with the {@link android.widget.RemoteViews} mechanism.
- */
-@Target({ ElementType.METHOD })
-@Retention(RetentionPolicy.RUNTIME)
-public @interface RemotableViewMethod {
-}
-
-
-
diff --git a/core/java/android/view/SoundEffectConstants.java b/core/java/android/view/SoundEffectConstants.java
deleted file mode 100644
index 4a77af4..0000000
--- a/core/java/android/view/SoundEffectConstants.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-/**
- * Constants to be used to play sound effects via {@link View#playSoundEffect(int)}
- */
-public class SoundEffectConstants {
-
- private SoundEffectConstants() {}
-
- public static final int CLICK = 0;
-
- public static final int NAVIGATION_LEFT = 1;
- public static final int NAVIGATION_UP = 2;
- public static final int NAVIGATION_RIGHT = 3;
- public static final int NAVIGATION_DOWN = 4;
-
- /**
- * Get the sonification constant for the focus directions.
- * @param direction One of {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
- * {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT}, {@link View#FOCUS_FORWARD}
- * or {@link View#FOCUS_BACKWARD}
-
- * @return The appropriate sonification constant.
- */
- public static int getContantForFocusDirection(int direction) {
- switch (direction) {
- case View.FOCUS_RIGHT:
- return SoundEffectConstants.NAVIGATION_RIGHT;
- case View.FOCUS_FORWARD:
- case View.FOCUS_DOWN:
- return SoundEffectConstants.NAVIGATION_DOWN;
- case View.FOCUS_LEFT:
- return SoundEffectConstants.NAVIGATION_LEFT;
- case View.FOCUS_BACKWARD:
- case View.FOCUS_UP:
- return SoundEffectConstants.NAVIGATION_UP;
- }
- throw new IllegalArgumentException("direction must be one of "
- + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, FOCUS_BACKWARD}.");
- }
-}
diff --git a/core/java/android/view/SubMenu.java b/core/java/android/view/SubMenu.java
deleted file mode 100644
index e981486..0000000
--- a/core/java/android/view/SubMenu.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.graphics.drawable.Drawable;
-
-/**
- * Subclass of {@link Menu} for sub menus.
- * <p>
- * Sub menus do not support item icons, or nested sub menus.
- */
-
-public interface SubMenu extends Menu {
- /**
- * Sets the submenu header's title to the title given in <var>titleRes</var>
- * resource identifier.
- *
- * @param titleRes The string resource identifier used for the title.
- * @return This SubMenu so additional setters can be called.
- */
- public SubMenu setHeaderTitle(int titleRes);
-
- /**
- * Sets the submenu header's title to the title given in <var>title</var>.
- *
- * @param title The character sequence used for the title.
- * @return This SubMenu so additional setters can be called.
- */
- public SubMenu setHeaderTitle(CharSequence title);
-
- /**
- * Sets the submenu header's icon to the icon given in <var>iconRes</var>
- * resource id.
- *
- * @param iconRes The resource identifier used for the icon.
- * @return This SubMenu so additional setters can be called.
- */
- public SubMenu setHeaderIcon(int iconRes);
-
- /**
- * Sets the submenu header's icon to the icon given in <var>icon</var>
- * {@link Drawable}.
- *
- * @param icon The {@link Drawable} used for the icon.
- * @return This SubMenu so additional setters can be called.
- */
- public SubMenu setHeaderIcon(Drawable icon);
-
- /**
- * Sets the header of the submenu to the {@link View} given in
- * <var>view</var>. This replaces the header title and icon (and those
- * replace this).
- *
- * @param view The {@link View} used for the header.
- * @return This SubMenu so additional setters can be called.
- */
- public SubMenu setHeaderView(View view);
-
- /**
- * Clears the header of the submenu.
- */
- public void clearHeader();
-
- /**
- * Change the icon associated with this submenu's item in its parent menu.
- *
- * @see MenuItem#setIcon(int)
- * @param iconRes The new icon (as a resource ID) to be displayed.
- * @return This SubMenu so additional setters can be called.
- */
- public SubMenu setIcon(int iconRes);
-
- /**
- * Change the icon associated with this submenu's item in its parent menu.
- *
- * @see MenuItem#setIcon(Drawable)
- * @param icon The new icon (as a Drawable) to be displayed.
- * @return This SubMenu so additional setters can be called.
- */
- public SubMenu setIcon(Drawable icon);
-
- /**
- * Gets the {@link MenuItem} that represents this submenu in the parent
- * menu. Use this for setting additional item attributes.
- *
- * @return The {@link MenuItem} that launches the submenu when invoked.
- */
- public MenuItem getItem();
-}
diff --git a/core/java/android/view/Surface.aidl b/core/java/android/view/Surface.aidl
deleted file mode 100644
index 90bf37a..0000000
--- a/core/java/android/view/Surface.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/view/Surface.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.view;
-
-parcelable Surface;
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
deleted file mode 100644
index 54ccf33..0000000
--- a/core/java/android/view/Surface.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.graphics.*;
-import android.os.Parcelable;
-import android.os.Parcel;
-import android.util.Log;
-
-/**
- * Handle on to a raw buffer that is being managed by the screen compositor.
- */
-public class Surface implements Parcelable {
- private static final String LOG_TAG = "Surface";
-
- /* flags used in constructor (keep in sync with ISurfaceComposer.h) */
-
- /** Surface is created hidden */
- public static final int HIDDEN = 0x00000004;
-
- /** The surface is to be used by hardware accelerators or DMA engines */
- public static final int HARDWARE = 0x00000010;
-
- /** Implies "HARDWARE", the surface is to be used by the GPU
- * additionally the backbuffer is never preserved for these
- * surfaces. */
- public static final int GPU = 0x00000028;
-
- /** The surface contains secure content, special measures will
- * be taken to disallow the surface's content to be copied from
- * another process. In particular, screenshots and VNC servers will
- * be disabled, but other measures can take place, for instance the
- * surface might not be hardware accelerated. */
- public static final int SECURE = 0x00000080;
-
- /** Creates a surface where color components are interpreted as
- * "non pre-multiplied" by their alpha channel. Of course this flag is
- * meaningless for surfaces without an alpha channel. By default
- * surfaces are pre-multiplied, which means that each color component is
- * already multiplied by its alpha value. In this case the blending
- * equation used is:
- *
- * DEST = SRC + DEST * (1-SRC_ALPHA)
- *
- * By contrast, non pre-multiplied surfaces use the following equation:
- *
- * DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA)
- *
- * pre-multiplied surfaces must always be used if transparent pixels are
- * composited on top of each-other into the surface. A pre-multiplied
- * surface can never lower the value of the alpha component of a given
- * pixel.
- *
- * In some rare situations, a non pre-multiplied surface is preferable.
- *
- */
- public static final int NON_PREMULTIPLIED = 0x00000100;
-
- /**
- * Creates a surface without a rendering buffer. Instead, the content
- * of the surface must be pushed by an external entity. This is type
- * of surface can be used for efficient camera preview or movie
- * play back.
- */
- public static final int PUSH_BUFFERS = 0x00000200;
-
- /** Creates a normal surface. This is the default */
- public static final int FX_SURFACE_NORMAL = 0x00000000;
-
- /** Creates a Blur surface. Everything behind this surface is blurred
- * by some amount. The quality and refresh speed of the blur effect
- * is not settable or guaranteed.
- * It is an error to lock a Blur surface, since it doesn't have
- * a backing store.
- */
- public static final int FX_SURFACE_BLUR = 0x00010000;
-
- /** Creates a Dim surface. Everything behind this surface is dimmed
- * by the amount specified in setAlpha().
- * It is an error to lock a Dim surface, since it doesn't have
- * a backing store.
- */
- public static final int FX_SURFACE_DIM = 0x00020000;
-
- /** Mask used for FX values above */
- public static final int FX_SURFACE_MASK = 0x000F0000;
-
- /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */
-
- /** Hide the surface. Equivalent to calling hide() */
- public static final int SURFACE_HIDDEN = 0x01;
-
- /** Freeze the surface. Equivalent to calling freeze() */
- public static final int SURACE_FROZEN = 0x02;
-
- /** Enable dithering when compositing this surface */
- public static final int SURFACE_DITHER = 0x04;
-
- public static final int SURFACE_BLUR_FREEZE= 0x10;
-
- /* orientations for setOrientation() */
- public static final int ROTATION_0 = 0;
- public static final int ROTATION_90 = 1;
- public static final int ROTATION_180 = 2;
- public static final int ROTATION_270 = 3;
-
- @SuppressWarnings("unused")
- private int mSurface;
- @SuppressWarnings("unused")
- private int mSaveCount;
- @SuppressWarnings("unused")
- private Canvas mCanvas;
-
- /**
- * Exception thrown when a surface couldn't be created or resized
- */
- public static class OutOfResourcesException extends Exception {
- public OutOfResourcesException() {
- }
- public OutOfResourcesException(String name) {
- super(name);
- }
- }
-
- /*
- * We use a class initializer to allow the native code to cache some
- * field offsets.
- */
- native private static void nativeClassInit();
- static { nativeClassInit(); }
-
-
- /**
- * create a surface
- * {@hide}
- */
- public Surface(SurfaceSession s,
- int pid, int display, int w, int h, int format, int flags)
- throws OutOfResourcesException {
- mCanvas = new Canvas();
- init(s,pid,display,w,h,format,flags);
- }
-
- /**
- * Create an empty surface, which will later be filled in by
- * readFromParcel().
- * {@hide}
- */
- public Surface() {
- mCanvas = new Canvas();
- }
-
- /**
- * Copy another surface to this one. This surface now holds a reference
- * to the same data as the original surface, and is -not- the owner.
- * {@hide}
- */
- public native void copyFrom(Surface o);
-
- /**
- * Does this object hold a valid surface? Returns true if it holds
- * a physical surface, so lockCanvas() will succeed. Otherwise
- * returns false.
- */
- public native boolean isValid();
-
- /** Call this free the surface up. {@hide} */
- public native void clear();
-
- /** draw into a surface */
- public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException {
- /* the dirty rectangle may be expanded to the surface's size, if
- * for instance it has been resized or if the bits were lost, since
- * the last call.
- */
- return lockCanvasNative(dirty);
- }
-
- private native Canvas lockCanvasNative(Rect dirty);
-
- /** unlock the surface and asks a page flip */
- public native void unlockCanvasAndPost(Canvas canvas);
-
- /**
- * unlock the surface. the screen won't be updated until
- * post() or postAll() is called
- */
- public native void unlockCanvas(Canvas canvas);
-
- /** start/end a transaction {@hide} */
- public static native void openTransaction();
- /** {@hide} */
- public static native void closeTransaction();
-
- /**
- * Freezes the specified display, No updating of the screen will occur
- * until unfreezeDisplay() is called. Everything else works as usual though,
- * in particular transactions.
- * @param display
- * {@hide}
- */
- public static native void freezeDisplay(int display);
-
- /**
- * resume updating the specified display.
- * @param display
- * {@hide}
- */
- public static native void unfreezeDisplay(int display);
-
- /**
- * set the orientation of the given display.
- * @param display
- * @param orientation
- */
- public static native void setOrientation(int display, int orientation);
-
- /**
- * set surface parameters.
- * needs to be inside open/closeTransaction block
- */
- public native void setLayer(int zorder);
- public native void setPosition(int x, int y);
- public native void setSize(int w, int h);
-
- public native void hide();
- public native void show();
- public native void setTransparentRegionHint(Region region);
- public native void setAlpha(float alpha);
- public native void setMatrix(float dsdx, float dtdx,
- float dsdy, float dtdy);
-
- public native void freeze();
- public native void unfreeze();
-
- public native void setFreezeTint(int tint);
-
- public native void setFlags(int flags, int mask);
-
- @Override
- public String toString() {
- return "Surface(native-token=" + mSurface + ")";
- }
-
- private Surface(Parcel source) throws OutOfResourcesException {
- init(source);
- }
-
- public int describeContents() {
- return 0;
- }
-
- public native void readFromParcel(Parcel source);
- public native void writeToParcel(Parcel dest, int flags);
-
- public static final Parcelable.Creator<Surface> CREATOR
- = new Parcelable.Creator<Surface>()
- {
- public Surface createFromParcel(Parcel source) {
- try {
- return new Surface(source);
- } catch (Exception e) {
- Log.e(LOG_TAG, "Exception creating surface from parcel", e);
- }
- return null;
- }
-
- public Surface[] newArray(int size) {
- return new Surface[size];
- }
- };
-
- /* no user serviceable parts here ... */
- @Override
- protected void finalize() throws Throwable {
- clear();
- }
-
- private native void init(SurfaceSession s,
- int pid, int display, int w, int h, int format, int flags)
- throws OutOfResourcesException;
-
- private native void init(Parcel source);
-}
diff --git a/core/java/android/view/SurfaceHolder.java b/core/java/android/view/SurfaceHolder.java
deleted file mode 100644
index 3d0dda3..0000000
--- a/core/java/android/view/SurfaceHolder.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_NORMAL;
-import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_HARDWARE;
-import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_GPU;
-import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_PUSH_BUFFERS;
-
-/**
- * Abstract interface to someone holding a display surface. Allows you to
- * control the surface size and format, edit the pixels in the surface, and
- * monitor changes to the surface. This interface is typically available
- * through the {@link SurfaceView} class.
- *
- * <p>When using this interface from a thread different than the one running
- * its {@link SurfaceView}, you will want to carefully read the
- * {@link #lockCanvas} and {@link Callback#surfaceCreated Callback.surfaceCreated}.
- */
-public interface SurfaceHolder {
- /**
- * Surface type.
- *
- * @see #SURFACE_TYPE_NORMAL
- * @see #SURFACE_TYPE_HARDWARE
- * @see #SURFACE_TYPE_GPU
- * @see #SURFACE_TYPE_PUSH_BUFFERS
- */
-
- /** Surface type: creates a regular surface, usually in main, non
- * contiguous, cached/buffered RAM. */
- public static final int SURFACE_TYPE_NORMAL = MEMORY_TYPE_NORMAL;
- /** Surface type: creates a suited to be used with DMA engines and
- * hardware accelerators. */
- public static final int SURFACE_TYPE_HARDWARE = MEMORY_TYPE_HARDWARE;
- /** Surface type: creates a surface suited to be used with the GPU */
- public static final int SURFACE_TYPE_GPU = MEMORY_TYPE_GPU;
- /** Surface type: creates a "push" surface, that is a surface that
- * doesn't owns its buffers. With such a surface lockCanvas will fail. */
- public static final int SURFACE_TYPE_PUSH_BUFFERS = MEMORY_TYPE_PUSH_BUFFERS;
-
- /**
- * Exception that is thrown from {@link #lockCanvas} when called on a Surface
- * whose is SURFACE_TYPE_PUSH_BUFFERS.
- */
- public static class BadSurfaceTypeException extends RuntimeException {
- public BadSurfaceTypeException() {
- }
-
- public BadSurfaceTypeException(String name) {
- super(name);
- }
- }
-
- /**
- * A client may implement this interface to receive information about
- * changes to the surface. When used with a {@link SurfaceView}, the
- * Surface being held is only available between calls to
- * {@link #surfaceCreated(SurfaceHolder)} and
- * {@link #surfaceDestroyed(SurfaceHolder). The Callback is set with
- * {@link SurfaceHolder#addCallback SurfaceHolder.addCallback} method.
- */
- public interface Callback {
- /**
- * This is called immediately after the surface is first created.
- * Implementations of this should start up whatever rendering code
- * they desire. Note that only one thread can ever draw into
- * a {@link Surface}, so you should not draw into the Surface here
- * if your normal rendering will be in another thread.
- *
- * @param holder The SurfaceHolder whose surface is being created.
- */
- public void surfaceCreated(SurfaceHolder holder);
-
- /**
- * This is called immediately after any structural changes (format or
- * size) have been made to the surface. You should at this point update
- * the imagery in the surface. This method is always called at least
- * once, after {@link #surfaceCreated}.
- *
- * @param holder The SurfaceHolder whose surface has changed.
- * @param format The new PixelFormat of the surface.
- * @param width The new width of the surface.
- * @param height The new height of the surface.
- */
- public void surfaceChanged(SurfaceHolder holder, int format, int width,
- int height);
-
- /**
- * This is called immediately before a surface is being destroyed. After
- * returning from this call, you should no longer try to access this
- * surface. If you have a rendering thread that directly accesses
- * the surface, you must ensure that thread is no longer touching the
- * Surface before returning from this function.
- *
- * @param holder The SurfaceHolder whose surface is being destroyed.
- */
- public void surfaceDestroyed(SurfaceHolder holder);
- }
-
- /**
- * Add a Callback interface for this holder. There can several Callback
- * interfaces associated to a holder.
- *
- * @param callback The new Callback interface.
- */
- public void addCallback(Callback callback);
-
- /**
- * Removes a previously added Callback interface from this holder.
- *
- * @param callback The Callback interface to remove.
- */
- public void removeCallback(Callback callback);
-
- /**
- * Use this method to find out if the surface is in the process of being
- * created from Callback methods. This is intended to be used with
- * {@link Callback#surfaceChanged}.
- *
- * @return true if the surface is in the process of being created.
- */
- public boolean isCreating();
-
- /**
- * Sets the surface's type. Surfaces intended to be used with OpenGL ES
- * should be of SURFACE_TYPE_GPU, surfaces accessed by DMA engines and
- * hardware accelerators should be of type SURFACE_TYPE_HARDWARE.
- * Failing to set the surface's type appropriately could result in
- * degraded performance or failure.
- *
- * @param type The surface's memory type.
- */
- public void setType(int type);
-
- /**
- * Make the surface a fixed size. It will never change from this size.
- * When working with a {link SurfaceView}, this must be called from the
- * same thread running the SurfaceView's window.
- *
- * @param width The surface's width.
- * @param height The surface's height.
- */
- public void setFixedSize(int width, int height);
-
- /**
- * Allow the surface to resized based on layout of its container (this is
- * the default). When this is enabled, you should monitor
- * {@link Callback#surfaceChanged} for changes to the size of the surface.
- * When working with a {link SurfaceView}, this must be called from the
- * same thread running the SurfaceView's window.
- */
- public void setSizeFromLayout();
-
- /**
- * Set the desired PixelFormat of the surface. The default is OPAQUE.
- * When working with a {link SurfaceView}, this must be called from the
- * same thread running the SurfaceView's window.
- *
- * @param format A constant from PixelFormat.
- *
- * @see android.graphics.PixelFormat
- */
- public void setFormat(int format);
-
- /**
- * Enable or disable option to keep the screen turned on while this
- * surface is displayed. The default is false, allowing it to turn off.
- * Enabling the option effectivelty.
- * This is safe to call from any thread.
- *
- * @param screenOn Supply to true to force the screen to stay on, false
- * to allow it to turn off.
- */
- public void setKeepScreenOn(boolean screenOn);
-
- /**
- * Start editing the pixels in the surface. The returned Canvas can be used
- * to draw into the surface's bitmap. A null is returned if the surface has
- * not been created or otherwise can not be edited. You will usually need
- * to implement {@link Callback#surfaceCreated Callback.surfaceCreated}
- * to find out when the Surface is available for use.
- *
- * <p>The content of the Surface is never preserved between unlockCanvas() and
- * lockCanvas(), for this reason, every pixel within the Surface area
- * must be written. The only exception to this rule is when a dirty
- * rectangle is specified, in which case, non dirty pixels will be
- * preserved.
- *
- * <p>If you call this repeatedly when the Surface is not ready (before
- * {@link Callback#surfaceCreated Callback.surfaceCreated} or after
- * {@link Callback#surfaceDestroyed Callback.surfaceDestroyed}), your calls
- * will be throttled to a slow rate in order to avoid consuming CPU.
- *
- * <p>If null is not returned, this function internally holds a lock until
- * the corresponding {@link #unlockCanvasAndPost} call, preventing
- * {@link SurfaceView} from creating, destroying, or modifying the surface
- * while it is being drawn. This can be more convenience than accessing
- * the Surface directly, as you do not need to do special synchronization
- * with a drawing thread in {@link Callback#surfaceDestroyed
- * Callback.surfaceDestroyed}.
- *
- * @return Canvas Use to draw into the surface.
- */
- public Canvas lockCanvas();
-
-
- /**
- * Just like {@link #lockCanvas()} but allows to specify a dirty rectangle.
- * Every
- * pixel within that rectangle must be written; however pixels outside
- * the dirty rectangle will be preserved by the next call to lockCanvas().
- *
- * @see android.view.SurfaceHolder#lockCanvas
- *
- * @param dirty Area of the Surface that will be modified.
- * @return Canvas Use to draw into the surface.
- */
- public Canvas lockCanvas(Rect dirty);
-
- /**
- * Finish editing pixels in the surface. After this call, the surface's
- * current pixels will be shown on the screen, but its content is lost,
- * in particular there is no guarantee that the content of the Surface
- * will remain unchanged when lockCanvas() is called again.
- *
- * @see #lockCanvas()
- *
- * @param canvas The Canvas previously returned by lockCanvas().
- */
- public void unlockCanvasAndPost(Canvas canvas);
-
- /**
- * Retrieve the current size of the surface. Note: do not modify the
- * returned Rect. This is only safe to call from the thread of
- * {@link SurfaceView}'s window, or while inside of
- * {@link #lockCanvas()}.
- *
- * @return Rect The surface's dimensions. The left and top are always 0.
- */
- public Rect getSurfaceFrame();
-
- /**
- * Direct access to the surface object. The Surface may not always be
- * available -- for example when using a {@link SurfaceView} the holder's
- * Surface is not created until the view has been attached to the window
- * manager and performed a layout in order to determine the dimensions
- * and screen position of the Surface. You will thus usually need
- * to implement {@link Callback#surfaceCreated Callback.surfaceCreated}
- * to find out when the Surface is available for use.
- *
- * <p>Note that if you directly access the Surface from another thread,
- * it is critical that you correctly implement
- * {@link Callback#surfaceCreated Callback.surfaceCreated} and
- * {@link Callback#surfaceDestroyed Callback.surfaceDestroyed} to ensure
- * that thread only accesses the Surface while it is valid, and that the
- * Surface does not get destroyed while the thread is using it.
- *
- * <p>This method is intended to be used by frameworks which often need
- * direct access to the Surface object (usually to pass it to native code).
- * When designing APIs always use SurfaceHolder to pass surfaces around
- * as opposed to the Surface object itself. A rule of thumb is that
- * application code should never have to call this method.
- *
- * @return Surface The surface.
- */
- public Surface getSurface();
-}
diff --git a/core/java/android/view/SurfaceSession.java b/core/java/android/view/SurfaceSession.java
deleted file mode 100644
index 2a04675..0000000
--- a/core/java/android/view/SurfaceSession.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-
-/**
- * An instance of this class represents a connection to the surface
- * flinger, in which you can create one or more Surface instances that will
- * be composited to the screen.
- * {@hide}
- */
-public class SurfaceSession {
- /** Create a new connection with the surface flinger. */
- public SurfaceSession() {
- init();
- }
-
- /** Forcibly detach native resources associated with this object.
- * Unlike destroy(), after this call any surfaces that were created
- * from the session will no longer work. The session itself is destroyed.
- */
- public native void kill();
-
- /* no user serviceable parts here ... */
- @Override
- protected void finalize() throws Throwable {
- destroy();
- }
-
- private native void init();
- private native void destroy();
-
- private int mClient;
-}
-
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
deleted file mode 100644
index e928998..0000000
--- a/core/java/android/view/SurfaceView.java
+++ /dev/null
@@ -1,614 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.os.Handler;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.ParcelFileDescriptor;
-import android.util.AttributeSet;
-import android.util.Config;
-import android.util.Log;
-import java.util.ArrayList;
-
-import java.util.concurrent.locks.ReentrantLock;
-import java.lang.ref.WeakReference;
-
-/**
- * Provides a dedicated drawing surface embedded inside of a view hierarchy.
- * You can control the format of this surface and, if you like, its size; the
- * SurfaceView takes care of placing the surface at the correct location on the
- * screen
- *
- * <p>The surface is Z ordered so that it is behind the window holding its
- * SurfaceView; the SurfaceView punches a hole in its window to allow its
- * surface to be displayed. The view hierarchy will take care of correctly
- * compositing with the Surface any siblings of the SurfaceView that would
- * normally appear on top of it. This can be used to place overlays such as
- * buttons on top of the Surface, though note however that it can have an
- * impact on performance since a full alpha-blended composite will be performed
- * each time the Surface changes.
- *
- * <p>Access to the underlying surface is provided via the SurfaceHolder interface,
- * which can be retrieved by calling {@link #getHolder}.
- *
- * <p>The Surface will be created for you while the SurfaceView's window is
- * visible; you should implement {@link SurfaceHolder.Callback#surfaceCreated}
- * and {@link SurfaceHolder.Callback#surfaceDestroyed} to discover when the
- * Surface is created and destroyed as the window is shown and hidden.
- *
- * <p>One of the purposes of this class is to provide a surface in which a
- * secondary thread can render in to the screen. If you are going to use it
- * this way, you need to be aware of some threading semantics:
- *
- * <ul>
- * <li> All SurfaceView and
- * {@link SurfaceHolder.Callback SurfaceHolder.Callback} methods will be called
- * from the thread running the SurfaceView's window (typically the main thread
- * of the application). They thus need to correctly synchronize with any
- * state that is also touched by the drawing thread.
- * <li> You must ensure that the drawing thread only touches the underlying
- * Surface while it is valid -- between
- * {@link SurfaceHolder.Callback#surfaceCreated SurfaceHolder.Callback.surfaceCreated()}
- * and
- * {@link SurfaceHolder.Callback#surfaceDestroyed SurfaceHolder.Callback.surfaceDestroyed()}.
- * </ul>
- */
-public class SurfaceView extends View {
- static private final String TAG = "SurfaceView";
- static private final boolean DEBUG = false;
- static private final boolean localLOGV = DEBUG ? true : Config.LOGV;
-
- final ArrayList<SurfaceHolder.Callback> mCallbacks
- = new ArrayList<SurfaceHolder.Callback>();
-
- final int[] mLocation = new int[2];
-
- final ReentrantLock mSurfaceLock = new ReentrantLock();
- final Surface mSurface = new Surface();
- boolean mDrawingStopped = true;
-
- final WindowManager.LayoutParams mLayout
- = new WindowManager.LayoutParams();
- IWindowSession mSession;
- MyWindow mWindow;
- final Rect mVisibleInsets = new Rect();
- final Rect mWinFrame = new Rect();
- final Rect mContentInsets = new Rect();
-
- static final int KEEP_SCREEN_ON_MSG = 1;
- static final int GET_NEW_SURFACE_MSG = 2;
-
- boolean mIsCreating = false;
-
- final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case KEEP_SCREEN_ON_MSG: {
- setKeepScreenOn(msg.arg1 != 0);
- } break;
- case GET_NEW_SURFACE_MSG: {
- handleGetNewSurface();
- } break;
- }
- }
- };
-
- boolean mRequestedVisible = false;
- int mRequestedWidth = -1;
- int mRequestedHeight = -1;
- int mRequestedFormat = PixelFormat.OPAQUE;
- int mRequestedType = -1;
-
- boolean mHaveFrame = false;
- boolean mDestroyReportNeeded = false;
- boolean mNewSurfaceNeeded = false;
- long mLastLockTime = 0;
-
- boolean mVisible = false;
- int mLeft = -1;
- int mTop = -1;
- int mWidth = -1;
- int mHeight = -1;
- int mFormat = -1;
- int mType = -1;
- final Rect mSurfaceFrame = new Rect();
-
- public SurfaceView(Context context) {
- super(context);
- setWillNotDraw(true);
- }
-
- public SurfaceView(Context context, AttributeSet attrs) {
- super(context, attrs);
- setWillNotDraw(true);
- }
-
- public SurfaceView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- setWillNotDraw(true);
- }
-
- /**
- * Return the SurfaceHolder providing access and control over this
- * SurfaceView's underlying surface.
- *
- * @return SurfaceHolder The holder of the surface.
- */
- public SurfaceHolder getHolder() {
- return mSurfaceHolder;
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- mParent.requestTransparentRegion(this);
- mSession = getWindowSession();
- mLayout.token = getWindowToken();
- mLayout.setTitle("SurfaceView");
- }
-
- @Override
- protected void onWindowVisibilityChanged(int visibility) {
- super.onWindowVisibilityChanged(visibility);
- mRequestedVisible = visibility == VISIBLE;
- updateWindow(false);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- mRequestedVisible = false;
- updateWindow(false);
- mHaveFrame = false;
- if (mWindow != null) {
- try {
- mSession.remove(mWindow);
- } catch (RemoteException ex) {
- }
- mWindow = null;
- }
- mSession = null;
- mLayout.token = null;
-
- super.onDetachedFromWindow();
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int width = getDefaultSize(mRequestedWidth, widthMeasureSpec);
- int height = getDefaultSize(mRequestedHeight, heightMeasureSpec);
- setMeasuredDimension(width, height);
- }
-
- @Override
- protected void onScrollChanged(int l, int t, int oldl, int oldt) {
- super.onScrollChanged(l, t, oldl, oldt);
- updateWindow(false);
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- updateWindow(false);
- }
-
- @Override
- public boolean gatherTransparentRegion(Region region) {
- boolean opaque = true;
- if ((mPrivateFlags & SKIP_DRAW) == 0) {
- // this view draws, remove it from the transparent region
- opaque = super.gatherTransparentRegion(region);
- } else if (region != null) {
- int w = getWidth();
- int h = getHeight();
- if (w>0 && h>0) {
- getLocationInWindow(mLocation);
- // otherwise, punch a hole in the whole hierarchy
- int l = mLocation[0];
- int t = mLocation[1];
- region.op(l, t, l+w, t+h, Region.Op.UNION);
- }
- }
- if (PixelFormat.formatHasAlpha(mRequestedFormat)) {
- opaque = false;
- }
- return opaque;
- }
-
- @Override
- public void draw(Canvas canvas) {
- // draw() is not called when SKIP_DRAW is set
- if ((mPrivateFlags & SKIP_DRAW) == 0) {
- // punch a whole in the view-hierarchy below us
- canvas.drawColor(0, PorterDuff.Mode.CLEAR);
- }
- super.draw(canvas);
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- // if SKIP_DRAW is cleared, draw() has already punched a hole
- if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
- // punch a whole in the view-hierarchy below us
- canvas.drawColor(0, PorterDuff.Mode.CLEAR);
- }
- // reposition ourselves where the surface is
- mHaveFrame = true;
- updateWindow(false);
- super.dispatchDraw(canvas);
- }
-
- private void updateWindow(boolean force) {
- if (!mHaveFrame) {
- return;
- }
-
- int myWidth = mRequestedWidth;
- if (myWidth <= 0) myWidth = getWidth();
- int myHeight = mRequestedHeight;
- if (myHeight <= 0) myHeight = getHeight();
-
- getLocationInWindow(mLocation);
- final boolean creating = mWindow == null;
- final boolean formatChanged = mFormat != mRequestedFormat;
- final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
- final boolean visibleChanged = mVisible != mRequestedVisible
- || mNewSurfaceNeeded;
- final boolean typeChanged = mType != mRequestedType;
- if (force || creating || formatChanged || sizeChanged || visibleChanged
- || typeChanged || mLeft != mLocation[0] || mTop != mLocation[1]) {
-
- if (localLOGV) Log.i(TAG, "Changes: creating=" + creating
- + " format=" + formatChanged + " size=" + sizeChanged
- + " visible=" + visibleChanged
- + " left=" + (mLeft != mLocation[0])
- + " top=" + (mTop != mLocation[1]));
-
- try {
- final boolean visible = mVisible = mRequestedVisible;
- mLeft = mLocation[0];
- mTop = mLocation[1];
- mWidth = myWidth;
- mHeight = myHeight;
- mFormat = mRequestedFormat;
- mType = mRequestedType;
-
- mLayout.x = mLeft;
- mLayout.y = mTop;
- mLayout.width = getWidth();
- mLayout.height = getHeight();
- mLayout.format = mRequestedFormat;
- mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
- | WindowManager.LayoutParams.FLAG_SCALED
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- ;
-
- mLayout.memoryType = mRequestedType;
-
- if (mWindow == null) {
- mWindow = new MyWindow(this);
- mLayout.type = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
- mLayout.gravity = Gravity.LEFT|Gravity.TOP;
- mSession.add(mWindow, mLayout,
- mVisible ? VISIBLE : GONE, mContentInsets);
- }
-
- if (visibleChanged && (!visible || mNewSurfaceNeeded)) {
- reportSurfaceDestroyed();
- }
-
- mNewSurfaceNeeded = false;
-
- mSurfaceLock.lock();
- mDrawingStopped = !visible;
- final int relayoutResult = mSession.relayout(
- mWindow, mLayout, mWidth, mHeight,
- visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets,
- mVisibleInsets, mSurface);
- if (localLOGV) Log.i(TAG, "New surface: " + mSurface
- + ", vis=" + visible + ", frame=" + mWinFrame);
- mSurfaceFrame.left = 0;
- mSurfaceFrame.top = 0;
- mSurfaceFrame.right = mWinFrame.width();
- mSurfaceFrame.bottom = mWinFrame.height();
- mSurfaceLock.unlock();
-
- try {
- if (visible) {
- mDestroyReportNeeded = true;
-
- SurfaceHolder.Callback callbacks[];
- synchronized (mCallbacks) {
- callbacks = new SurfaceHolder.Callback[mCallbacks.size()];
- mCallbacks.toArray(callbacks);
- }
-
- if (visibleChanged) {
- mIsCreating = true;
- for (SurfaceHolder.Callback c : callbacks) {
- c.surfaceCreated(mSurfaceHolder);
- }
- }
- if (creating || formatChanged || sizeChanged
- || visibleChanged) {
- for (SurfaceHolder.Callback c : callbacks) {
- c.surfaceChanged(mSurfaceHolder, mFormat, mWidth, mHeight);
- }
- }
- }
- } finally {
- mIsCreating = false;
- if (creating || (relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) {
- mSession.finishDrawing(mWindow);
- }
- }
- } catch (RemoteException ex) {
- }
- if (localLOGV) Log.v(
- TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
- " w=" + mLayout.width + " h=" + mLayout.height +
- ", frame=" + mSurfaceFrame);
- }
- }
-
- private void reportSurfaceDestroyed() {
- if (mDestroyReportNeeded) {
- mDestroyReportNeeded = false;
- SurfaceHolder.Callback callbacks[];
- synchronized (mCallbacks) {
- callbacks = new SurfaceHolder.Callback[mCallbacks.size()];
- mCallbacks.toArray(callbacks);
- }
- for (SurfaceHolder.Callback c : callbacks) {
- c.surfaceDestroyed(mSurfaceHolder);
- }
- }
- super.onDetachedFromWindow();
- }
-
- void handleGetNewSurface() {
- mNewSurfaceNeeded = true;
- updateWindow(false);
- }
-
- private static class MyWindow extends IWindow.Stub {
- private WeakReference<SurfaceView> mSurfaceView;
-
- public MyWindow(SurfaceView surfaceView) {
- mSurfaceView = new WeakReference<SurfaceView>(surfaceView);
- }
-
- public void resized(int w, int h, Rect coveredInsets,
- Rect visibleInsets, boolean reportDraw) {
- SurfaceView surfaceView = mSurfaceView.get();
- if (surfaceView != null) {
- if (localLOGV) Log.v(
- "SurfaceView", surfaceView + " got resized: w=" +
- w + " h=" + h + ", cur w=" + mCurWidth + " h=" + mCurHeight);
- synchronized (this) {
- if (mCurWidth != w || mCurHeight != h) {
- mCurWidth = w;
- mCurHeight = h;
- }
- if (reportDraw) {
- try {
- surfaceView.mSession.finishDrawing(surfaceView.mWindow);
- } catch (RemoteException e) {
- }
- }
- }
- }
- }
-
- public void dispatchKey(KeyEvent event) {
- SurfaceView surfaceView = mSurfaceView.get();
- if (surfaceView != null) {
- //Log.w("SurfaceView", "Unexpected key event in surface: " + event);
- if (surfaceView.mSession != null && surfaceView.mSurface != null) {
- try {
- surfaceView.mSession.finishKey(surfaceView.mWindow);
- } catch (RemoteException ex) {
- }
- }
- }
- }
-
- public void dispatchPointer(MotionEvent event, long eventTime) {
- Log.w("SurfaceView", "Unexpected pointer event in surface: " + event);
- //if (mSession != null && mSurface != null) {
- // try {
- // //mSession.finishKey(mWindow);
- // } catch (RemoteException ex) {
- // }
- //}
- }
-
- public void dispatchTrackball(MotionEvent event, long eventTime) {
- Log.w("SurfaceView", "Unexpected trackball event in surface: " + event);
- //if (mSession != null && mSurface != null) {
- // try {
- // //mSession.finishKey(mWindow);
- // } catch (RemoteException ex) {
- // }
- //}
- }
-
- public void dispatchAppVisibility(boolean visible) {
- // The point of SurfaceView is to let the app control the surface.
- }
-
- public void dispatchGetNewSurface() {
- SurfaceView surfaceView = mSurfaceView.get();
- if (surfaceView != null) {
- Message msg = surfaceView.mHandler.obtainMessage(GET_NEW_SURFACE_MSG);
- surfaceView.mHandler.sendMessage(msg);
- }
- }
-
- public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
- Log.w("SurfaceView", "Unexpected focus in surface: focus=" + hasFocus + ", touchEnabled=" + touchEnabled);
- }
-
- public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
- }
-
- int mCurWidth = -1;
- int mCurHeight = -1;
- }
-
- private SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
-
- private static final String LOG_TAG = "SurfaceHolder";
-
- public boolean isCreating() {
- return mIsCreating;
- }
-
- public void addCallback(Callback callback) {
- synchronized (mCallbacks) {
- // This is a linear search, but in practice we'll
- // have only a couple callbacks, so it doesn't matter.
- if (mCallbacks.contains(callback) == false) {
- mCallbacks.add(callback);
- }
- }
- }
-
- public void removeCallback(Callback callback) {
- synchronized (mCallbacks) {
- mCallbacks.remove(callback);
- }
- }
-
- public void setFixedSize(int width, int height) {
- if (mRequestedWidth != width || mRequestedHeight != height) {
- mRequestedWidth = width;
- mRequestedHeight = height;
- requestLayout();
- }
- }
-
- public void setSizeFromLayout() {
- if (mRequestedWidth != -1 || mRequestedHeight != -1) {
- mRequestedWidth = mRequestedHeight = -1;
- requestLayout();
- }
- }
-
- public void setFormat(int format) {
- mRequestedFormat = format;
- if (mWindow != null) {
- updateWindow(false);
- }
- }
-
- public void setType(int type) {
- switch (type) {
- case SURFACE_TYPE_NORMAL:
- case SURFACE_TYPE_HARDWARE:
- case SURFACE_TYPE_GPU:
- case SURFACE_TYPE_PUSH_BUFFERS:
- mRequestedType = type;
- if (mWindow != null) {
- updateWindow(false);
- }
- break;
- }
- }
-
- public void setKeepScreenOn(boolean screenOn) {
- Message msg = mHandler.obtainMessage(KEEP_SCREEN_ON_MSG);
- msg.arg1 = screenOn ? 1 : 0;
- mHandler.sendMessage(msg);
- }
-
- public Canvas lockCanvas() {
- return internalLockCanvas(null);
- }
-
- public Canvas lockCanvas(Rect dirty) {
- return internalLockCanvas(dirty);
- }
-
- private final Canvas internalLockCanvas(Rect dirty) {
- if (mType == SURFACE_TYPE_PUSH_BUFFERS) {
- throw new BadSurfaceTypeException(
- "Surface type is SURFACE_TYPE_PUSH_BUFFERS");
- }
- mSurfaceLock.lock();
-
- if (localLOGV) Log.i(TAG, "Locking canvas... stopped="
- + mDrawingStopped + ", win=" + mWindow);
-
- Canvas c = null;
- if (!mDrawingStopped && mWindow != null) {
- Rect frame = dirty != null ? dirty : mSurfaceFrame;
- try {
- c = mSurface.lockCanvas(frame);
- } catch (Exception e) {
- Log.e(LOG_TAG, "Exception locking surface", e);
- }
- }
-
- if (localLOGV) Log.i(TAG, "Returned canvas: " + c);
- if (c != null) {
- mLastLockTime = SystemClock.uptimeMillis();
- return c;
- }
-
- // If the Surface is not ready to be drawn, then return null,
- // but throttle calls to this function so it isn't called more
- // than every 100ms.
- long now = SystemClock.uptimeMillis();
- long nextTime = mLastLockTime + 100;
- if (nextTime > now) {
- try {
- Thread.sleep(nextTime-now);
- } catch (InterruptedException e) {
- }
- now = SystemClock.uptimeMillis();
- }
- mLastLockTime = now;
- mSurfaceLock.unlock();
-
- return null;
- }
-
- public void unlockCanvasAndPost(Canvas canvas) {
- mSurface.unlockCanvasAndPost(canvas);
- mSurfaceLock.unlock();
- }
-
- public Surface getSurface() {
- return mSurface;
- }
-
- public Rect getSurfaceFrame() {
- return mSurfaceFrame;
- }
- };
-}
-
diff --git a/core/java/android/view/TouchDelegate.java b/core/java/android/view/TouchDelegate.java
deleted file mode 100644
index 27b49db..0000000
--- a/core/java/android/view/TouchDelegate.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.graphics.Rect;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-
-/**
- * Helper class to handle situations where you want a view to have a larger touch area than its
- * actual view bounds. The view whose touch area is changed is called the delegate view. This
- * class should be used by an ancestor of the delegate. To use a TouchDelegate, first create an
- * instance that specifies the bounds that should be mapped to the delegate and the delegate
- * view itself.
- * <p>
- * The ancestor should then forward all of its touch events received in its
- * {@link android.view.View#onTouchEvent(MotionEvent)} to {@link #onTouchEvent(MotionEvent)}.
- * </p>
- */
-public class TouchDelegate {
-
- /**
- * View that should receive forwarded touch events
- */
- private View mDelegateView;
-
- /**
- * Bounds in local coordinates of the containing view that should be mapped to the delegate
- * view. This rect is used for initial hit testing.
- */
- private Rect mBounds;
-
- /**
- * mBounds inflated to include some slop. This rect is to track whether the motion events
- * should be considered to be be within the delegate view.
- */
- private Rect mSlopBounds;
-
- /**
- * True if the delegate had been targeted on a down event (intersected mBounds).
- */
- private boolean mDelegateTargeted;
-
- /**
- * The touchable region of the View extends above its actual extent.
- */
- public static final int ABOVE = 1;
-
- /**
- * The touchable region of the View extends below its actual extent.
- */
- public static final int BELOW = 2;
-
- /**
- * The touchable region of the View extends to the left of its
- * actual extent.
- */
- public static final int TO_LEFT = 4;
-
- /**
- * The touchable region of the View extends to the right of its
- * actual extent.
- */
- public static final int TO_RIGHT = 8;
-
- private int mSlop;
-
- /**
- * Constructor
- *
- * @param bounds Bounds in local coordinates of the containing view that should be mapped to
- * the delegate view
- * @param delegateView The view that should receive motion events
- */
- public TouchDelegate(Rect bounds, View delegateView) {
- mBounds = bounds;
-
- mSlop = ViewConfiguration.get(delegateView.getContext()).getScaledTouchSlop();
- mSlopBounds = new Rect(bounds);
- mSlopBounds.inset(-mSlop, -mSlop);
- mDelegateView = delegateView;
- }
-
- /**
- * Will forward touch events to the delegate view if the event is within the bounds
- * specified in the constructor.
- *
- * @param event The touch event to forward
- * @return True if the event was forwarded to the delegate, false otherwise.
- */
- public boolean onTouchEvent(MotionEvent event) {
- int x = (int)event.getX();
- int y = (int)event.getY();
- boolean sendToDelegate = false;
- boolean hit = true;
- boolean handled = false;
-
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- Rect bounds = mBounds;
-
- if (bounds.contains(x, y)) {
- mDelegateTargeted = true;
- sendToDelegate = true;
- }
- break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_MOVE:
- sendToDelegate = mDelegateTargeted;
- if (sendToDelegate) {
- Rect slopBounds = mSlopBounds;
- if (!slopBounds.contains(x, y)) {
- hit = false;
- }
- }
- break;
- case MotionEvent.ACTION_CANCEL:
- sendToDelegate = mDelegateTargeted;
- mDelegateTargeted = false;
- break;
- }
- if (sendToDelegate) {
- final View delegateView = mDelegateView;
-
- if (hit) {
- // Offset event coordinates to be inside the target view
- event.setLocation(delegateView.getWidth() / 2, delegateView.getHeight() / 2);
- } else {
- // Offset event coordinates to be outside the target view (in case it does
- // something like tracking pressed state)
- int slop = mSlop;
- event.setLocation(-(slop * 2), -(slop * 2));
- }
- handled = delegateView.dispatchTouchEvent(event);
- }
- return handled;
- }
-}
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
deleted file mode 100644
index c80167e..0000000
--- a/core/java/android/view/VelocityTracker.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.util.Config;
-import android.util.Log;
-
-/**
- * Helper for tracking the velocity of touch events, for implementing
- * flinging and other such gestures. Use {@link #obtain} to retrieve a
- * new instance of the class when you are going to begin tracking, put
- * the motion events you receive into it with {@link #addMovement(MotionEvent)},
- * and when you want to determine the velocity call
- * {@link #computeCurrentVelocity(int)} and then {@link #getXVelocity()}
- * and {@link #getXVelocity()}.
- */
-public final class VelocityTracker {
- static final String TAG = "VelocityTracker";
- static final boolean DEBUG = false;
- static final boolean localLOGV = DEBUG || Config.LOGV;
-
- static final int NUM_PAST = 10;
- static final int LONGEST_PAST_TIME = 200;
-
- static final VelocityTracker[] mPool = new VelocityTracker[1];
-
- final float mPastX[] = new float[NUM_PAST];
- final float mPastY[] = new float[NUM_PAST];
- final long mPastTime[] = new long[NUM_PAST];
-
- float mYVelocity;
- float mXVelocity;
-
- /**
- * Retrieve a new VelocityTracker object to watch the velocity of a
- * motion. Be sure to call {@link #recycle} when done. You should
- * generally only maintain an active object while tracking a movement,
- * so that the VelocityTracker can be re-used elsewhere.
- *
- * @return Returns a new VelocityTracker.
- */
- static public VelocityTracker obtain() {
- synchronized (mPool) {
- VelocityTracker vt = mPool[0];
- if (vt != null) {
- vt.clear();
- return vt;
- }
- return new VelocityTracker();
- }
- }
-
- /**
- * Return a VelocityTracker object back to be re-used by others. You must
- * not touch the object after calling this function.
- */
- public void recycle() {
- synchronized (mPool) {
- mPool[0] = this;
- }
- }
-
- private VelocityTracker() {
- }
-
- /**
- * Reset the velocity tracker back to its initial state.
- */
- public void clear() {
- mPastTime[0] = 0;
- }
-
- /**
- * Add a user's movement to the tracker. You should call this for the
- * initial {@link MotionEvent#ACTION_DOWN}, the following
- * {@link MotionEvent#ACTION_MOVE} events that you receive, and the
- * final {@link MotionEvent#ACTION_UP}. You can, however, call this
- * for whichever events you desire.
- *
- * @param ev The MotionEvent you received and would like to track.
- */
- public void addMovement(MotionEvent ev) {
- long time = ev.getEventTime();
- final int N = ev.getHistorySize();
- for (int i=0; i<N; i++) {
- addPoint(ev.getHistoricalX(i), ev.getHistoricalY(i),
- ev.getHistoricalEventTime(i));
- }
- addPoint(ev.getX(), ev.getY(), time);
- }
-
- private void addPoint(float x, float y, long time) {
- int drop = -1;
- int i;
- if (localLOGV) Log.v(TAG, "Adding past y=" + y + " time=" + time);
- final long[] pastTime = mPastTime;
- for (i=0; i<NUM_PAST; i++) {
- if (pastTime[i] == 0) {
- break;
- } else if (pastTime[i] < time-LONGEST_PAST_TIME) {
- if (localLOGV) Log.v(TAG, "Dropping past too old at "
- + i + " time=" + pastTime[i]);
- drop = i;
- }
- }
- if (localLOGV) Log.v(TAG, "Add index: " + i);
- if (i == NUM_PAST && drop < 0) {
- drop = 0;
- }
- if (drop == i) drop--;
- final float[] pastX = mPastX;
- final float[] pastY = mPastY;
- if (drop >= 0) {
- if (localLOGV) Log.v(TAG, "Dropping up to #" + drop);
- final int start = drop+1;
- final int count = NUM_PAST-drop-1;
- System.arraycopy(pastX, start, pastX, 0, count);
- System.arraycopy(pastY, start, pastY, 0, count);
- System.arraycopy(pastTime, start, pastTime, 0, count);
- i -= (drop+1);
- }
- pastX[i] = x;
- pastY[i] = y;
- pastTime[i] = time;
- i++;
- if (i < NUM_PAST) {
- pastTime[i] = 0;
- }
- }
-
- /**
- * Compute the current velocity based on the points that have been
- * collected. Only call this when you actually want to retrieve velocity
- * information, as it is relatively expensive. You can then retrieve
- * the velocity with {@link #getXVelocity()} and
- * {@link #getYVelocity()}.
- *
- * @param units The units you would like the velocity in. A value of 1
- * provides pixels per millisecond, 1000 provides pixels per second, etc.
- */
- public void computeCurrentVelocity(int units) {
- final float[] pastX = mPastX;
- final float[] pastY = mPastY;
- final long[] pastTime = mPastTime;
-
- // Kind-of stupid.
- final float oldestX = pastX[0];
- final float oldestY = pastY[0];
- final long oldestTime = pastTime[0];
- float accumX = 0;
- float accumY = 0;
- int N=0;
- while (N < NUM_PAST) {
- if (pastTime[N] == 0) {
- break;
- }
- N++;
- }
- // Skip the last received event, since it is probably pretty noisy.
- if (N > 3) N--;
-
- for (int i=1; i < N; i++) {
- final int dur = (int)(pastTime[i] - oldestTime);
- if (dur == 0) continue;
- float dist = pastX[i] - oldestX;
- float vel = (dist/dur) * units; // pixels/frame.
- if (accumX == 0) accumX = vel;
- else accumX = (accumX + vel) * .5f;
-
- dist = pastY[i] - oldestY;
- vel = (dist/dur) * units; // pixels/frame.
- if (accumY == 0) accumY = vel;
- else accumY = (accumY + vel) * .5f;
- }
- mXVelocity = accumX;
- mYVelocity = accumY;
-
- if (localLOGV) Log.v(TAG, "Y velocity=" + mYVelocity +" X velocity="
- + mXVelocity + " N=" + N);
- }
-
- /**
- * Retrieve the last computed X velocity. You must first call
- * {@link #computeCurrentVelocity(int)} before calling this function.
- *
- * @return The previously computed X velocity.
- */
- public float getXVelocity() {
- return mXVelocity;
- }
-
- /**
- * Retrieve the last computed Y velocity. You must first call
- * {@link #computeCurrentVelocity(int)} before calling this function.
- *
- * @return The previously computed Y velocity.
- */
- public float getYVelocity() {
- return mYVelocity;
- }
-}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
deleted file mode 100644
index 5ed3a7e..0000000
--- a/core/java/android/view/View.java
+++ /dev/null
@@ -1,8067 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.LinearGradient;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.graphics.Shader;
-import android.graphics.Point;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.util.AttributeSet;
-import android.util.EventLog;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.animation.Animation;
-import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.EditorInfo;
-import android.widget.ScrollBarDrawable;
-
-import com.android.internal.R;
-import com.android.internal.view.menu.MenuBuilder;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * <p>
- * This class represents the basic building block for user interface components. A View
- * occupies a rectangular area on the screen and is responsible for drawing and
- * event handling. View is the base class for <em>widgets</em>, which are
- * used to create interactive UI components (buttons, text fields, etc.). The
- * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
- * are invisible containers that hold other Views (or other ViewGroups) and define
- * their layout properties.
- * </p>
- *
- * <div class="special">
- * <p>For an introduction to using this class to develop your
- * application's user interface, read the Developer Guide documentation on
- * <strong><a href="{@docRoot}guide/topics/ui/index.html">User Interface</a></strong>. Special topics
- * include:
- * <br/><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a>
- * <br/><a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a>
- * <br/><a href="{@docRoot}guide/topics/ui/layout-objects.html">Common Layout Objects</a>
- * <br/><a href="{@docRoot}guide/topics/ui/binding.html">Binding to Data with AdapterView</a>
- * <br/><a href="{@docRoot}guide/topics/ui/ui-events.html">Handling UI Events</a>
- * <br/><a href="{@docRoot}guide/topics/ui/themes.html">Applying Styles and Themes</a>
- * <br/><a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>
- * <br/><a href="{@docRoot}guide/topics/ui/how-android-draws.html">How Android Draws Views</a>.
- * </p>
- * </div>
- *
- * <a name="Using"></a>
- * <h3>Using Views</h3>
- * <p>
- * All of the views in a window are arranged in a single tree. You can add views
- * either from code or by specifying a tree of views in one or more XML layout
- * files. There are many specialized subclasses of views that act as controls or
- * are capable of displaying text, images, or other content.
- * </p>
- * <p>
- * Once you have created a tree of views, there are typically a few types of
- * common operations you may wish to perform:
- * <ul>
- * <li><strong>Set properties:</strong> for example setting the text of a
- * {@link android.widget.TextView}. The available properties and the methods
- * that set them will vary among the different subclasses of views. Note that
- * properties that are known at build time can be set in the XML layout
- * files.</li>
- * <li><strong>Set focus:</strong> The framework will handled moving focus in
- * response to user input. To force focus to a specific view, call
- * {@link #requestFocus}.</li>
- * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
- * that will be notified when something interesting happens to the view. For
- * example, all views will let you set a listener to be notified when the view
- * gains or loses focus. You can register such a listener using
- * {@link #setOnFocusChangeListener}. Other view subclasses offer more
- * specialized listeners. For example, a Button exposes a listener to notify
- * clients when the button is clicked.</li>
- * <li><strong>Set visibility:</strong> You can hide or show views using
- * {@link #setVisibility}.</li>
- * </ul>
- * </p>
- * <p><em>
- * Note: The Android framework is responsible for measuring, laying out and
- * drawing views. You should not call methods that perform these actions on
- * views yourself unless you are actually implementing a
- * {@link android.view.ViewGroup}.
- * </em></p>
- *
- * <a name="Lifecycle"></a>
- * <h3>Implementing a Custom View</h3>
- *
- * <p>
- * To implement a custom view, you will usually begin by providing overrides for
- * some of the standard methods that the framework calls on all views. You do
- * not need to override all of these methods. In fact, you can start by just
- * overriding {@link #onDraw(android.graphics.Canvas)}.
- * <table border="2" width="85%" align="center" cellpadding="5">
- * <thead>
- * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
- * </thead>
- *
- * <tbody>
- * <tr>
- * <td rowspan="2">Creation</td>
- * <td>Constructors</td>
- * <td>There is a form of the constructor that are called when the view
- * is created from code and a form that is called when the view is
- * inflated from a layout file. The second form should parse and apply
- * any attributes defined in the layout file.
- * </td>
- * </tr>
- * <tr>
- * <td><code>{@link #onFinishInflate()}</code></td>
- * <td>Called after a view and all of its children has been inflated
- * from XML.</td>
- * </tr>
- *
- * <tr>
- * <td rowspan="3">Layout</td>
- * <td><code>{@link #onMeasure}</code></td>
- * <td>Called to determine the size requirements for this view and all
- * of its children.
- * </td>
- * </tr>
- * <tr>
- * <td><code>{@link #onLayout}</code></td>
- * <td>Called when this view should assign a size and position to all
- * of its children.
- * </td>
- * </tr>
- * <tr>
- * <td><code>{@link #onSizeChanged}</code></td>
- * <td>Called when the size of this view has changed.
- * </td>
- * </tr>
- *
- * <tr>
- * <td>Drawing</td>
- * <td><code>{@link #onDraw}</code></td>
- * <td>Called when the view should render its content.
- * </td>
- * </tr>
- *
- * <tr>
- * <td rowspan="4">Event processing</td>
- * <td><code>{@link #onKeyDown}</code></td>
- * <td>Called when a new key event occurs.
- * </td>
- * </tr>
- * <tr>
- * <td><code>{@link #onKeyUp}</code></td>
- * <td>Called when a key up event occurs.
- * </td>
- * </tr>
- * <tr>
- * <td><code>{@link #onTrackballEvent}</code></td>
- * <td>Called when a trackball motion event occurs.
- * </td>
- * </tr>
- * <tr>
- * <td><code>{@link #onTouchEvent}</code></td>
- * <td>Called when a touch screen motion event occurs.
- * </td>
- * </tr>
- *
- * <tr>
- * <td rowspan="2">Focus</td>
- * <td><code>{@link #onFocusChanged}</code></td>
- * <td>Called when the view gains or loses focus.
- * </td>
- * </tr>
- *
- * <tr>
- * <td><code>{@link #onWindowFocusChanged}</code></td>
- * <td>Called when the window containing the view gains or loses focus.
- * </td>
- * </tr>
- *
- * <tr>
- * <td rowspan="3">Attaching</td>
- * <td><code>{@link #onAttachedToWindow()}</code></td>
- * <td>Called when the view is attached to a window.
- * </td>
- * </tr>
- *
- * <tr>
- * <td><code>{@link #onDetachedFromWindow}</code></td>
- * <td>Called when the view is detached from its window.
- * </td>
- * </tr>
- *
- * <tr>
- * <td><code>{@link #onWindowVisibilityChanged}</code></td>
- * <td>Called when the visibility of the window containing the view
- * has changed.
- * </td>
- * </tr>
- * </tbody>
- *
- * </table>
- * </p>
- *
- * <a name="IDs"></a>
- * <h3>IDs</h3>
- * Views may have an integer id associated with them. These ids are typically
- * assigned in the layout XML files, and are used to find specific views within
- * the view tree. A common pattern is to:
- * <ul>
- * <li>Define a Button in the layout file and assign it a unique ID.
- * <pre>
- * &lt;Button id="@+id/my_button"
- * android:layout_width="wrap_content"
- * android:layout_height="wrap_content"
- * android:text="@string/my_button_text"/&gt;
- * </pre></li>
- * <li>From the onCreate method of an Activity, find the Button
- * <pre class="prettyprint">
- * Button myButton = (Button) findViewById(R.id.my_button);
- * </pre></li>
- * </ul>
- * <p>
- * View IDs need not be unique throughout the tree, but it is good practice to
- * ensure that they are at least unique within the part of the tree you are
- * searching.
- * </p>
- *
- * <a name="Position"></a>
- * <h3>Position</h3>
- * <p>
- * The geometry of a view is that of a rectangle. A view has a location,
- * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
- * two dimensions, expressed as a width and a height. The unit for location
- * and dimensions is the pixel.
- * </p>
- *
- * <p>
- * It is possible to retrieve the location of a view by invoking the methods
- * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
- * coordinate of the rectangle representing the view. The latter returns the
- * top, or Y, coordinate of the rectangle representing the view. These methods
- * both return the location of the view relative to its parent. For instance,
- * when getLeft() returns 20, that means the view is located 20 pixels to the
- * right of the left edge of its direct parent.
- * </p>
- *
- * <p>
- * In addition, several convenience methods are offered to avoid unnecessary
- * computations, namely {@link #getRight()} and {@link #getBottom()}.
- * These methods return the coordinates of the right and bottom edges of the
- * rectangle representing the view. For instance, calling {@link #getRight()}
- * is similar to the following computation: <code>getLeft() + getWidth()</code>
- * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
- * </p>
- *
- * <a name="SizePaddingMargins"></a>
- * <h3>Size, padding and margins</h3>
- * <p>
- * The size of a view is expressed with a width and a height. A view actually
- * possess two pairs of width and height values.
- * </p>
- *
- * <p>
- * The first pair is known as <em>measured width</em> and
- * <em>measured height</em>. These dimensions define how big a view wants to be
- * within its parent (see <a href="#Layout">Layout</a> for more details.) The
- * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
- * and {@link #getMeasuredHeight()}.
- * </p>
- *
- * <p>
- * The second pair is simply known as <em>width</em> and <em>height</em>, or
- * sometimes <em>drawing width</em> and <em>drawing height</em>. These
- * dimensions define the actual size of the view on screen, at drawing time and
- * after layout. These values may, but do not have to, be different from the
- * measured width and height. The width and height can be obtained by calling
- * {@link #getWidth()} and {@link #getHeight()}.
- * </p>
- *
- * <p>
- * To measure its dimensions, a view takes into account its padding. The padding
- * is expressed in pixels for the left, top, right and bottom parts of the view.
- * Padding can be used to offset the content of the view by a specific amount of
- * pixels. For instance, a left padding of 2 will push the view's content by
- * 2 pixels to the right of the left edge. Padding can be set using the
- * {@link #setPadding(int, int, int, int)} method and queried by calling
- * {@link #getPaddingLeft()}, {@link #getPaddingTop()},
- * {@link #getPaddingRight()} and {@link #getPaddingBottom()}.
- * </p>
- *
- * <p>
- * Even though a view can define a padding, it does not provide any support for
- * margins. However, view groups provide such a support. Refer to
- * {@link android.view.ViewGroup} and
- * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
- * </p>
- *
- * <a name="Layout"></a>
- * <h3>Layout</h3>
- * <p>
- * Layout is a two pass process: a measure pass and a layout pass. The measuring
- * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
- * of the view tree. Each view pushes dimension specifications down the tree
- * during the recursion. At the end of the measure pass, every view has stored
- * its measurements. The second pass happens in
- * {@link #layout(int,int,int,int)} and is also top-down. During
- * this pass each parent is responsible for positioning all of its children
- * using the sizes computed in the measure pass.
- * </p>
- *
- * <p>
- * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
- * {@link #getMeasuredHeight()} values must be set, along with those for all of
- * that view's descendants. A view's measured width and measured height values
- * must respect the constraints imposed by the view's parents. This guarantees
- * that at the end of the measure pass, all parents accept all of their
- * children's measurements. A parent view may call measure() more than once on
- * its children. For example, the parent may measure each child once with
- * unspecified dimensions to find out how big they want to be, then call
- * measure() on them again with actual numbers if the sum of all the children's
- * unconstrained sizes is too big or too small.
- * </p>
- *
- * <p>
- * The measure pass uses two classes to communicate dimensions. The
- * {@link MeasureSpec} class is used by views to tell their parents how they
- * want to be measured and positioned. The base LayoutParams class just
- * describes how big the view wants to be for both width and height. For each
- * dimension, it can specify one of:
- * <ul>
- * <li> an exact number
- * <li>FILL_PARENT, which means the view wants to be as big as its parent
- * (minus padding)
- * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
- * enclose its content (plus padding).
- * </ul>
- * There are subclasses of LayoutParams for different subclasses of ViewGroup.
- * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
- * an X and Y value.
- * </p>
- *
- * <p>
- * MeasureSpecs are used to push requirements down the tree from parent to
- * child. A MeasureSpec can be in one of three modes:
- * <ul>
- * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
- * of a child view. For example, a LinearLayout may call measure() on its child
- * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
- * tall the child view wants to be given a width of 240 pixels.
- * <li>EXACTLY: This is used by the parent to impose an exact size on the
- * child. The child must use this size, and guarantee that all of its
- * descendants will fit within this size.
- * <li>AT_MOST: This is used by the parent to impose a maximum size on the
- * child. The child must gurantee that it and all of its descendants will fit
- * within this size.
- * </ul>
- * </p>
- *
- * <p>
- * To intiate a layout, call {@link #requestLayout}. This method is typically
- * called by a view on itself when it believes that is can no longer fit within
- * its current bounds.
- * </p>
- *
- * <a name="Drawing"></a>
- * <h3>Drawing</h3>
- * <p>
- * Drawing is handled by walking the tree and rendering each view that
- * intersects the the invalid region. Because the tree is traversed in-order,
- * this means that parents will draw before (i.e., behind) their children, with
- * siblings drawn in the order they appear in the tree.
- * If you set a background drawable for a View, then the View will draw it for you
- * before calling back to its <code>onDraw()</code> method.
- * </p>
- *
- * <p>
- * Note that the framework will not draw views that are not in the invalid region.
- * </p>
- *
- * <p>
- * To force a view to draw, call {@link #invalidate()}.
- * </p>
- *
- * <a name="EventHandlingThreading"></a>
- * <h3>Event Handling and Threading</h3>
- * <p>
- * The basic cycle of a view is as follows:
- * <ol>
- * <li>An event comes in and is dispatched to the appropriate view. The view
- * handles the event and notifies any listeners.</li>
- * <li>If in the course of processing the event, the view's bounds may need
- * to be changed, the view will call {@link #requestLayout()}.</li>
- * <li>Similarly, if in the course of processing the event the view's appearance
- * may need to be changed, the view will call {@link #invalidate()}.</li>
- * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
- * the framework will take care of measuring, laying out, and drawing the tree
- * as appropriate.</li>
- * </ol>
- * </p>
- *
- * <p><em>Note: The entire view tree is single threaded. You must always be on
- * the UI thread when calling any method on any view.</em>
- * If you are doing work on other threads and want to update the state of a view
- * from that thread, you should use a {@link Handler}.
- * </p>
- *
- * <a name="FocusHandling"></a>
- * <h3>Focus Handling</h3>
- * <p>
- * The framework will handle routine focus movement in response to user input.
- * This includes changing the focus as views are removed or hidden, or as new
- * views become available. Views indicate their willingness to take focus
- * through the {@link #isFocusable} method. To change whether a view can take
- * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below)
- * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
- * and can change this via {@link #setFocusableInTouchMode(boolean)}.
- * </p>
- * <p>
- * Focus movement is based on an algorithm which finds the nearest neighbor in a
- * given direction. In rare cases, the default algorithm may not match the
- * intended behavior of the developer. In these situations, you can provide
- * explicit overrides by using these XML attributes in the layout file:
- * <pre>
- * nextFocusDown
- * nextFocusLeft
- * nextFocusRight
- * nextFocusUp
- * </pre>
- * </p>
- *
- *
- * <p>
- * To get a particular view to take focus, call {@link #requestFocus()}.
- * </p>
- *
- * <a name="TouchMode"></a>
- * <h3>Touch Mode</h3>
- * <p>
- * When a user is navigating a user interface via directional keys such as a D-pad, it is
- * necessary to give focus to actionable items such as buttons so the user can see
- * what will take input. If the device has touch capabilities, however, and the user
- * begins interacting with the interface by touching it, it is no longer necessary to
- * always highlight, or give focus to, a particular view. This motivates a mode
- * for interaction named 'touch mode'.
- * </p>
- * <p>
- * For a touch capable device, once the user touches the screen, the device
- * will enter touch mode. From this point onward, only views for which
- * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
- * Other views that are touchable, like buttons, will not take focus when touched; they will
- * only fire the on click listeners.
- * </p>
- * <p>
- * Any time a user hits a directional key, such as a D-pad direction, the view device will
- * exit touch mode, and find a view to take focus, so that the user may resume interacting
- * with the user interface without touching the screen again.
- * </p>
- * <p>
- * The touch mode state is maintained across {@link android.app.Activity}s. Call
- * {@link #isInTouchMode} to see whether the device is currently in touch mode.
- * </p>
- *
- * <a name="Scrolling"></a>
- * <h3>Scrolling</h3>
- * <p>
- * The framework provides basic support for views that wish to internally
- * scroll their content. This includes keeping track of the X and Y scroll
- * offset as well as mechanisms for drawing scrollbars. See
- * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)} for more details.
- * </p>
- *
- * <a name="Tags"></a>
- * <h3>Tags</h3>
- * <p>
- * Unlike IDs, tags are not used to identify views. Tags are essentially an
- * extra piece of information that can be associated with a view. They are most
- * often used as a convenience to store data related to views in the views
- * themselves rather than by putting them in a separate structure.
- * </p>
- *
- * <a name="Animation"></a>
- * <h3>Animation</h3>
- * <p>
- * You can attach an {@link Animation} object to a view using
- * {@link #setAnimation(Animation)} or
- * {@link #startAnimation(Animation)}. The animation can alter the scale,
- * rotation, translation and alpha of a view over time. If the animation is
- * attached to a view that has children, the animation will affect the entire
- * subtree rooted by that node. When an animation is started, the framework will
- * take care of redrawing the appropriate views until the animation completes.
- * </p>
- *
- * @attr ref android.R.styleable#View_fitsSystemWindows
- * @attr ref android.R.styleable#View_nextFocusDown
- * @attr ref android.R.styleable#View_nextFocusLeft
- * @attr ref android.R.styleable#View_nextFocusRight
- * @attr ref android.R.styleable#View_nextFocusUp
- * @attr ref android.R.styleable#View_scrollX
- * @attr ref android.R.styleable#View_scrollY
- * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
- * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
- * @attr ref android.R.styleable#View_scrollbarSize
- * @attr ref android.R.styleable#View_scrollbars
- * @attr ref android.R.styleable#View_scrollbarThumbVertical
- * @attr ref android.R.styleable#View_scrollbarTrackVertical
- * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
- * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
- *
- * @see android.view.ViewGroup
- */
-public class View implements Drawable.Callback, KeyEvent.Callback {
- private static final boolean DBG = false;
-
- /**
- * The logging tag used by this class with android.util.Log.
- */
- protected static final String VIEW_LOG_TAG = "View";
-
- /**
- * Used to mark a View that has no ID.
- */
- public static final int NO_ID = -1;
-
- /**
- * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
- * calling setFlags.
- */
- private static final int NOT_FOCUSABLE = 0x00000000;
-
- /**
- * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
- * setFlags.
- */
- private static final int FOCUSABLE = 0x00000001;
-
- /**
- * Mask for use with setFlags indicating bits used for focus.
- */
- private static final int FOCUSABLE_MASK = 0x00000001;
-
- /**
- * This view will adjust its padding to fit sytem windows (e.g. status bar)
- */
- private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
-
- /**
- * This view is visible. Use with {@link #setVisibility}.
- */
- public static final int VISIBLE = 0x00000000;
-
- /**
- * This view is invisible, but it still takes up space for layout purposes.
- * Use with {@link #setVisibility}.
- */
- public static final int INVISIBLE = 0x00000004;
-
- /**
- * This view is invisible, and it doesn't take any space for layout
- * purposes. Use with {@link #setVisibility}.
- */
- public static final int GONE = 0x00000008;
-
- /**
- * Mask for use with setFlags indicating bits used for visibility.
- * {@hide}
- */
- static final int VISIBILITY_MASK = 0x0000000C;
-
- private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
-
- /**
- * This view is enabled. Intrepretation varies by subclass.
- * Use with ENABLED_MASK when calling setFlags.
- * {@hide}
- */
- static final int ENABLED = 0x00000000;
-
- /**
- * This view is disabled. Intrepretation varies by subclass.
- * Use with ENABLED_MASK when calling setFlags.
- * {@hide}
- */
- static final int DISABLED = 0x00000020;
-
- /**
- * Mask for use with setFlags indicating bits used for indicating whether
- * this view is enabled
- * {@hide}
- */
- static final int ENABLED_MASK = 0x00000020;
-
- /**
- * This view won't draw. {@link #onDraw} won't be called and further
- * optimizations
- * will be performed. It is okay to have this flag set and a background.
- * Use with DRAW_MASK when calling setFlags.
- * {@hide}
- */
- static final int WILL_NOT_DRAW = 0x00000080;
-
- /**
- * Mask for use with setFlags indicating bits used for indicating whether
- * this view is will draw
- * {@hide}
- */
- static final int DRAW_MASK = 0x00000080;
-
- /**
- * <p>This view doesn't show scrollbars.</p>
- * {@hide}
- */
- static final int SCROLLBARS_NONE = 0x00000000;
-
- /**
- * <p>This view shows horizontal scrollbars.</p>
- * {@hide}
- */
- static final int SCROLLBARS_HORIZONTAL = 0x00000100;
-
- /**
- * <p>This view shows vertical scrollbars.</p>
- * {@hide}
- */
- static final int SCROLLBARS_VERTICAL = 0x00000200;
-
- /**
- * <p>Mask for use with setFlags indicating bits used for indicating which
- * scrollbars are enabled.</p>
- * {@hide}
- */
- static final int SCROLLBARS_MASK = 0x00000300;
-
- // note 0x00000400 and 0x00000800 are now available for next flags...
-
- /**
- * <p>This view doesn't show fading edges.</p>
- * {@hide}
- */
- static final int FADING_EDGE_NONE = 0x00000000;
-
- /**
- * <p>This view shows horizontal fading edges.</p>
- * {@hide}
- */
- static final int FADING_EDGE_HORIZONTAL = 0x00001000;
-
- /**
- * <p>This view shows vertical fading edges.</p>
- * {@hide}
- */
- static final int FADING_EDGE_VERTICAL = 0x00002000;
-
- /**
- * <p>Mask for use with setFlags indicating bits used for indicating which
- * fading edges are enabled.</p>
- * {@hide}
- */
- static final int FADING_EDGE_MASK = 0x00003000;
-
- /**
- * <p>Indicates this view can be clicked. When clickable, a View reacts
- * to clicks by notifying the OnClickListener.<p>
- * {@hide}
- */
- static final int CLICKABLE = 0x00004000;
-
- /**
- * <p>Indicates this view is caching its drawing into a bitmap.</p>
- * {@hide}
- */
- static final int DRAWING_CACHE_ENABLED = 0x00008000;
-
- /**
- * <p>Indicates that no icicle should be saved for this view.<p>
- * {@hide}
- */
- static final int SAVE_DISABLED = 0x000010000;
-
- /**
- * <p>Mask for use with setFlags indicating bits used for the saveEnabled
- * property.</p>
- * {@hide}
- */
- static final int SAVE_DISABLED_MASK = 0x000010000;
-
- /**
- * <p>Indicates that no drawing cache should ever be created for this view.<p>
- * {@hide}
- */
- static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
-
- /**
- * <p>Indicates this view can take / keep focus when int touch mode.</p>
- * {@hide}
- */
- static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
-
- /**
- * <p>Enables low quality mode for the drawing cache.</p>
- */
- public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
-
- /**
- * <p>Enables high quality mode for the drawing cache.</p>
- */
- public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
-
- /**
- * <p>Enables automatic quality mode for the drawing cache.</p>
- */
- public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
-
- private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
- DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
- };
-
- /**
- * <p>Mask for use with setFlags indicating bits used for the cache
- * quality property.</p>
- * {@hide}
- */
- static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
-
- /**
- * <p>
- * Indicates this view can be long clicked. When long clickable, a View
- * reacts to long clicks by notifying the OnLongClickListener or showing a
- * context menu.
- * </p>
- * {@hide}
- */
- static final int LONG_CLICKABLE = 0x00200000;
-
- /**
- * <p>Indicates that this view gets its drawable states from its direct parent
- * and ignores its original internal states.</p>
- *
- * @hide
- */
- static final int DUPLICATE_PARENT_STATE = 0x00400000;
-
- /**
- * The scrollbar style to display the scrollbars inside the content area,
- * without increasing the padding. The scrollbars will be overlaid with
- * translucency on the view's content.
- */
- public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
-
- /**
- * The scrollbar style to display the scrollbars inside the padded area,
- * increasing the padding of the view. The scrollbars will not overlap the
- * content area of the view.
- */
- public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
-
- /**
- * The scrollbar style to display the scrollbars at the edge of the view,
- * without increasing the padding. The scrollbars will be overlaid with
- * translucency.
- */
- public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
-
- /**
- * The scrollbar style to display the scrollbars at the edge of the view,
- * increasing the padding of the view. The scrollbars will only overlap the
- * background, if any.
- */
- public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
-
- /**
- * Mask to check if the scrollbar style is overlay or inset.
- * {@hide}
- */
- static final int SCROLLBARS_INSET_MASK = 0x01000000;
-
- /**
- * Mask to check if the scrollbar style is inside or outside.
- * {@hide}
- */
- static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
-
- /**
- * Mask for scrollbar style.
- * {@hide}
- */
- static final int SCROLLBARS_STYLE_MASK = 0x03000000;
-
- /**
- * View flag indicating that the screen should remain on while the
- * window containing this view is visible to the user. This effectively
- * takes care of automatically setting the WindowManager's
- * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
- */
- public static final int KEEP_SCREEN_ON = 0x04000000;
-
- /**
- * View flag indicating whether this view should have sound effects enabled
- * for events such as clicking and touching.
- */
- public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
-
- /**
- * View flag indicating whether this view should have haptic feedback
- * enabled for events such as long presses.
- */
- public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
-
- /**
- * Use with {@link #focusSearch}. Move focus to the previous selectable
- * item.
- */
- public static final int FOCUS_BACKWARD = 0x00000001;
-
- /**
- * Use with {@link #focusSearch}. Move focus to the next selectable
- * item.
- */
- public static final int FOCUS_FORWARD = 0x00000002;
-
- /**
- * Use with {@link #focusSearch}. Move focus to the left.
- */
- public static final int FOCUS_LEFT = 0x00000011;
-
- /**
- * Use with {@link #focusSearch}. Move focus up.
- */
- public static final int FOCUS_UP = 0x00000021;
-
- /**
- * Use with {@link #focusSearch}. Move focus to the right.
- */
- public static final int FOCUS_RIGHT = 0x00000042;
-
- /**
- * Use with {@link #focusSearch}. Move focus down.
- */
- public static final int FOCUS_DOWN = 0x00000082;
-
- /**
- * Base View state sets
- */
- // Singles
- /**
- * Indicates the view has no states set. States are used with
- * {@link android.graphics.drawable.Drawable} to change the drawing of the
- * view depending on its state.
- *
- * @see android.graphics.drawable.Drawable
- * @see #getDrawableState()
- */
- protected static final int[] EMPTY_STATE_SET = {};
- /**
- * Indicates the view is enabled. States are used with
- * {@link android.graphics.drawable.Drawable} to change the drawing of the
- * view depending on its state.
- *
- * @see android.graphics.drawable.Drawable
- * @see #getDrawableState()
- */
- protected static final int[] ENABLED_STATE_SET = {R.attr.state_enabled};
- /**
- * Indicates the view is focused. States are used with
- * {@link android.graphics.drawable.Drawable} to change the drawing of the
- * view depending on its state.
- *
- * @see android.graphics.drawable.Drawable
- * @see #getDrawableState()
- */
- protected static final int[] FOCUSED_STATE_SET = {R.attr.state_focused};
- /**
- * Indicates the view is selected. States are used with
- * {@link android.graphics.drawable.Drawable} to change the drawing of the
- * view depending on its state.
- *
- * @see android.graphics.drawable.Drawable
- * @see #getDrawableState()
- */
- protected static final int[] SELECTED_STATE_SET = {R.attr.state_selected};
- /**
- * Indicates the view is pressed. States are used with
- * {@link android.graphics.drawable.Drawable} to change the drawing of the
- * view depending on its state.
- *
- * @see android.graphics.drawable.Drawable
- * @see #getDrawableState()
- * @hide
- */
- protected static final int[] PRESSED_STATE_SET = {R.attr.state_pressed};
- /**
- * Indicates the view's window has focus. States are used with
- * {@link android.graphics.drawable.Drawable} to change the drawing of the
- * view depending on its state.
- *
- * @see android.graphics.drawable.Drawable
- * @see #getDrawableState()
- */
- protected static final int[] WINDOW_FOCUSED_STATE_SET =
- {R.attr.state_window_focused};
- // Doubles
- /**
- * Indicates the view is enabled and has the focus.
- *
- * @see #ENABLED_STATE_SET
- * @see #FOCUSED_STATE_SET
- */
- protected static final int[] ENABLED_FOCUSED_STATE_SET =
- stateSetUnion(ENABLED_STATE_SET, FOCUSED_STATE_SET);
- /**
- * Indicates the view is enabled and selected.
- *
- * @see #ENABLED_STATE_SET
- * @see #SELECTED_STATE_SET
- */
- protected static final int[] ENABLED_SELECTED_STATE_SET =
- stateSetUnion(ENABLED_STATE_SET, SELECTED_STATE_SET);
- /**
- * Indicates the view is enabled and that its window has focus.
- *
- * @see #ENABLED_STATE_SET
- * @see #WINDOW_FOCUSED_STATE_SET
- */
- protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET =
- stateSetUnion(ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
- /**
- * Indicates the view is focused and selected.
- *
- * @see #FOCUSED_STATE_SET
- * @see #SELECTED_STATE_SET
- */
- protected static final int[] FOCUSED_SELECTED_STATE_SET =
- stateSetUnion(FOCUSED_STATE_SET, SELECTED_STATE_SET);
- /**
- * Indicates the view has the focus and that its window has the focus.
- *
- * @see #FOCUSED_STATE_SET
- * @see #WINDOW_FOCUSED_STATE_SET
- */
- protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET =
- stateSetUnion(FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
- /**
- * Indicates the view is selected and that its window has the focus.
- *
- * @see #SELECTED_STATE_SET
- * @see #WINDOW_FOCUSED_STATE_SET
- */
- protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET =
- stateSetUnion(SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
- // Triples
- /**
- * Indicates the view is enabled, focused and selected.
- *
- * @see #ENABLED_STATE_SET
- * @see #FOCUSED_STATE_SET
- * @see #SELECTED_STATE_SET
- */
- protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET =
- stateSetUnion(ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
- /**
- * Indicates the view is enabled, focused and its window has the focus.
- *
- * @see #ENABLED_STATE_SET
- * @see #FOCUSED_STATE_SET
- * @see #WINDOW_FOCUSED_STATE_SET
- */
- protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET =
- stateSetUnion(ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
- /**
- * Indicates the view is enabled, selected and its window has the focus.
- *
- * @see #ENABLED_STATE_SET
- * @see #SELECTED_STATE_SET
- * @see #WINDOW_FOCUSED_STATE_SET
- */
- protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET =
- stateSetUnion(ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
- /**
- * Indicates the view is focused, selected and its window has the focus.
- *
- * @see #FOCUSED_STATE_SET
- * @see #SELECTED_STATE_SET
- * @see #WINDOW_FOCUSED_STATE_SET
- */
- protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
- stateSetUnion(FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
- /**
- * Indicates the view is enabled, focused, selected and its window
- * has the focus.
- *
- * @see #ENABLED_STATE_SET
- * @see #FOCUSED_STATE_SET
- * @see #SELECTED_STATE_SET
- * @see #WINDOW_FOCUSED_STATE_SET
- */
- protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
- stateSetUnion(ENABLED_FOCUSED_SELECTED_STATE_SET,
- WINDOW_FOCUSED_STATE_SET);
-
- /**
- * Indicates the view is pressed and its window has the focus.
- *
- * @see #PRESSED_STATE_SET
- * @see #WINDOW_FOCUSED_STATE_SET
- */
- protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET =
- stateSetUnion(PRESSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
-
- /**
- * Indicates the view is pressed and selected.
- *
- * @see #PRESSED_STATE_SET
- * @see #SELECTED_STATE_SET
- */
- protected static final int[] PRESSED_SELECTED_STATE_SET =
- stateSetUnion(PRESSED_STATE_SET, SELECTED_STATE_SET);
-
- /**
- * Indicates the view is pressed, selected and its window has the focus.
- *
- * @see #PRESSED_STATE_SET
- * @see #SELECTED_STATE_SET
- * @see #WINDOW_FOCUSED_STATE_SET
- */
- protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
- stateSetUnion(PRESSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
-
- /**
- * Indicates the view is pressed and focused.
- *
- * @see #PRESSED_STATE_SET
- * @see #FOCUSED_STATE_SET
- */
- protected static final int[] PRESSED_FOCUSED_STATE_SET =
- stateSetUnion(PRESSED_STATE_SET, FOCUSED_STATE_SET);
-
- /**
- * Indicates the view is pressed, focused and its window has the focus.
- *
- * @see #PRESSED_STATE_SET
- * @see #FOCUSED_STATE_SET
- * @see #WINDOW_FOCUSED_STATE_SET
- */
- protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET =
- stateSetUnion(PRESSED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
-
- /**
- * Indicates the view is pressed, focused and selected.
- *
- * @see #PRESSED_STATE_SET
- * @see #SELECTED_STATE_SET
- * @see #FOCUSED_STATE_SET
- */
- protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET =
- stateSetUnion(PRESSED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
-
- /**
- * Indicates the view is pressed, focused, selected and its window has the focus.
- *
- * @see #PRESSED_STATE_SET
- * @see #FOCUSED_STATE_SET
- * @see #SELECTED_STATE_SET
- * @see #WINDOW_FOCUSED_STATE_SET
- */
- protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
- stateSetUnion(PRESSED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
-
- /**
- * Indicates the view is pressed and enabled.
- *
- * @see #PRESSED_STATE_SET
- * @see #ENABLED_STATE_SET
- */
- protected static final int[] PRESSED_ENABLED_STATE_SET =
- stateSetUnion(PRESSED_STATE_SET, ENABLED_STATE_SET);
-
- /**
- * Indicates the view is pressed, enabled and its window has the focus.
- *
- * @see #PRESSED_STATE_SET
- * @see #ENABLED_STATE_SET
- * @see #WINDOW_FOCUSED_STATE_SET
- */
- protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET =
- stateSetUnion(PRESSED_ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
-
- /**
- * Indicates the view is pressed, enabled and selected.
- *
- * @see #PRESSED_STATE_SET
- * @see #ENABLED_STATE_SET
- * @see #SELECTED_STATE_SET
- */
- protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET =
- stateSetUnion(PRESSED_ENABLED_STATE_SET, SELECTED_STATE_SET);
-
- /**
- * Indicates the view is pressed, enabled, selected and its window has the
- * focus.
- *
- * @see #PRESSED_STATE_SET
- * @see #ENABLED_STATE_SET
- * @see #SELECTED_STATE_SET
- * @see #WINDOW_FOCUSED_STATE_SET
- */
- protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET =
- stateSetUnion(PRESSED_ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
-
- /**
- * Indicates the view is pressed, enabled and focused.
- *
- * @see #PRESSED_STATE_SET
- * @see #ENABLED_STATE_SET
- * @see #FOCUSED_STATE_SET
- */
- protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET =
- stateSetUnion(PRESSED_ENABLED_STATE_SET, FOCUSED_STATE_SET);
-
- /**
- * Indicates the view is pressed, enabled, focused and its window has the
- * focus.
- *
- * @see #PRESSED_STATE_SET
- * @see #ENABLED_STATE_SET
- * @see #FOCUSED_STATE_SET
- * @see #WINDOW_FOCUSED_STATE_SET
- */
- protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET =
- stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
-
- /**
- * Indicates the view is pressed, enabled, focused and selected.
- *
- * @see #PRESSED_STATE_SET
- * @see #ENABLED_STATE_SET
- * @see #SELECTED_STATE_SET
- * @see #FOCUSED_STATE_SET
- */
- protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET =
- stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
-
- /**
- * Indicates the view is pressed, enabled, focused, selected and its window
- * has the focus.
- *
- * @see #PRESSED_STATE_SET
- * @see #ENABLED_STATE_SET
- * @see #SELECTED_STATE_SET
- * @see #FOCUSED_STATE_SET
- * @see #WINDOW_FOCUSED_STATE_SET
- */
- protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
- stateSetUnion(PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
-
- /**
- * The order here is very important to {@link #getDrawableState()}
- */
- private static final int[][] VIEW_STATE_SETS = {
- EMPTY_STATE_SET, // 0 0 0 0 0
- WINDOW_FOCUSED_STATE_SET, // 0 0 0 0 1
- SELECTED_STATE_SET, // 0 0 0 1 0
- SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 0 0 1 1
- FOCUSED_STATE_SET, // 0 0 1 0 0
- FOCUSED_WINDOW_FOCUSED_STATE_SET, // 0 0 1 0 1
- FOCUSED_SELECTED_STATE_SET, // 0 0 1 1 0
- FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 0 1 1 1
- ENABLED_STATE_SET, // 0 1 0 0 0
- ENABLED_WINDOW_FOCUSED_STATE_SET, // 0 1 0 0 1
- ENABLED_SELECTED_STATE_SET, // 0 1 0 1 0
- ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 1 0 1 1
- ENABLED_FOCUSED_STATE_SET, // 0 1 1 0 0
- ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET, // 0 1 1 0 1
- ENABLED_FOCUSED_SELECTED_STATE_SET, // 0 1 1 1 0
- ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 1 1 1 1
- PRESSED_STATE_SET, // 1 0 0 0 0
- PRESSED_WINDOW_FOCUSED_STATE_SET, // 1 0 0 0 1
- PRESSED_SELECTED_STATE_SET, // 1 0 0 1 0
- PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 0 0 1 1
- PRESSED_FOCUSED_STATE_SET, // 1 0 1 0 0
- PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET, // 1 0 1 0 1
- PRESSED_FOCUSED_SELECTED_STATE_SET, // 1 0 1 1 0
- PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 0 1 1 1
- PRESSED_ENABLED_STATE_SET, // 1 1 0 0 0
- PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET, // 1 1 0 0 1
- PRESSED_ENABLED_SELECTED_STATE_SET, // 1 1 0 1 0
- PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 1 0 1 1
- PRESSED_ENABLED_FOCUSED_STATE_SET, // 1 1 1 0 0
- PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET, // 1 1 1 0 1
- PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, // 1 1 1 1 0
- PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 1 1 1 1
- };
-
- /**
- * Used by views that contain lists of items. This state indicates that
- * the view is showing the last item.
- * @hide
- */
- protected static final int[] LAST_STATE_SET = {R.attr.state_last};
- /**
- * Used by views that contain lists of items. This state indicates that
- * the view is showing the first item.
- * @hide
- */
- protected static final int[] FIRST_STATE_SET = {R.attr.state_first};
- /**
- * Used by views that contain lists of items. This state indicates that
- * the view is showing the middle item.
- * @hide
- */
- protected static final int[] MIDDLE_STATE_SET = {R.attr.state_middle};
- /**
- * Used by views that contain lists of items. This state indicates that
- * the view is showing only one item.
- * @hide
- */
- protected static final int[] SINGLE_STATE_SET = {R.attr.state_single};
- /**
- * Used by views that contain lists of items. This state indicates that
- * the view is pressed and showing the last item.
- * @hide
- */
- protected static final int[] PRESSED_LAST_STATE_SET = {R.attr.state_last, R.attr.state_pressed};
- /**
- * Used by views that contain lists of items. This state indicates that
- * the view is pressed and showing the first item.
- * @hide
- */
- protected static final int[] PRESSED_FIRST_STATE_SET = {R.attr.state_first, R.attr.state_pressed};
- /**
- * Used by views that contain lists of items. This state indicates that
- * the view is pressed and showing the middle item.
- * @hide
- */
- protected static final int[] PRESSED_MIDDLE_STATE_SET = {R.attr.state_middle, R.attr.state_pressed};
- /**
- * Used by views that contain lists of items. This state indicates that
- * the view is pressed and showing only one item.
- * @hide
- */
- protected static final int[] PRESSED_SINGLE_STATE_SET = {R.attr.state_single, R.attr.state_pressed};
-
- /**
- * Temporary Rect currently for use in setBackground(). This will probably
- * be extended in the future to hold our own class with more than just
- * a Rect. :)
- */
- static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
-
- /**
- * The animation currently associated with this view.
- * @hide
- */
- protected Animation mCurrentAnimation = null;
-
- /**
- * Width as measured during measure pass.
- * {@hide}
- */
- @ViewDebug.ExportedProperty
- protected int mMeasuredWidth;
-
- /**
- * Height as measured during measure pass.
- * {@hide}
- */
- @ViewDebug.ExportedProperty
- protected int mMeasuredHeight;
-
- /**
- * The view's identifier.
- * {@hide}
- *
- * @see #setId(int)
- * @see #getId()
- */
- @ViewDebug.ExportedProperty(resolveId = true)
- int mID = NO_ID;
-
- /**
- * The view's tag.
- * {@hide}
- *
- * @see #setTag(Object)
- * @see #getTag()
- */
- protected Object mTag;
-
- // for mPrivateFlags:
- /** {@hide} */
- static final int WANTS_FOCUS = 0x00000001;
- /** {@hide} */
- static final int FOCUSED = 0x00000002;
- /** {@hide} */
- static final int SELECTED = 0x00000004;
- /** {@hide} */
- static final int IS_ROOT_NAMESPACE = 0x00000008;
- /** {@hide} */
- static final int HAS_BOUNDS = 0x00000010;
- /** {@hide} */
- static final int DRAWN = 0x00000020;
- /**
- * When this flag is set, this view is running an animation on behalf of its
- * children and should therefore not cancel invalidate requests, even if they
- * lie outside of this view's bounds.
- *
- * {@hide}
- */
- static final int DRAW_ANIMATION = 0x00000040;
- /** {@hide} */
- static final int SKIP_DRAW = 0x00000080;
- /** {@hide} */
- static final int ONLY_DRAWS_BACKGROUND = 0x00000100;
- /** {@hide} */
- static final int REQUEST_TRANSPARENT_REGIONS = 0x00000200;
- /** {@hide} */
- static final int DRAWABLE_STATE_DIRTY = 0x00000400;
- /** {@hide} */
- static final int MEASURED_DIMENSION_SET = 0x00000800;
- /** {@hide} */
- static final int FORCE_LAYOUT = 0x00001000;
-
- private static final int LAYOUT_REQUIRED = 0x00002000;
-
- private static final int PRESSED = 0x00004000;
-
- /** {@hide} */
- static final int DRAWING_CACHE_VALID = 0x00008000;
- /**
- * Flag used to indicate that this view should be drawn once more (and only once
- * more) after its animation has completed.
- * {@hide}
- */
- static final int ANIMATION_STARTED = 0x00010000;
-
- private static final int SAVE_STATE_CALLED = 0x00020000;
-
- /**
- * Indicates that the View returned true when onSetAlpha() was called and that
- * the alpha must be restored.
- * {@hide}
- */
- static final int ALPHA_SET = 0x00040000;
-
- /**
- * Set by {@link #setScrollContainer(boolean)}.
- */
- static final int SCROLL_CONTAINER = 0x00080000;
-
- /**
- * Set by {@link #setScrollContainer(boolean)}.
- */
- static final int SCROLL_CONTAINER_ADDED = 0x00100000;
-
- /**
- * The parent this view is attached to.
- * {@hide}
- *
- * @see #getParent()
- */
- protected ViewParent mParent;
-
- /**
- * {@hide}
- */
- AttachInfo mAttachInfo;
-
- /**
- * {@hide}
- */
- @ViewDebug.ExportedProperty
- int mPrivateFlags;
-
- /**
- * Count of how many windows this view has been attached to.
- */
- int mWindowAttachCount;
-
- /**
- * The layout parameters associated with this view and used by the parent
- * {@link android.view.ViewGroup} to determine how this view should be
- * laid out.
- * {@hide}
- */
- protected ViewGroup.LayoutParams mLayoutParams;
-
- /**
- * The view flags hold various views states.
- * {@hide}
- */
- @ViewDebug.ExportedProperty
- int mViewFlags;
-
- /**
- * The distance in pixels from the left edge of this view's parent
- * to the left edge of this view.
- * {@hide}
- */
- @ViewDebug.ExportedProperty
- protected int mLeft;
- /**
- * The distance in pixels from the left edge of this view's parent
- * to the right edge of this view.
- * {@hide}
- */
- @ViewDebug.ExportedProperty
- protected int mRight;
- /**
- * The distance in pixels from the top edge of this view's parent
- * to the top edge of this view.
- * {@hide}
- */
- @ViewDebug.ExportedProperty
- protected int mTop;
- /**
- * The distance in pixels from the top edge of this view's parent
- * to the bottom edge of this view.
- * {@hide}
- */
- @ViewDebug.ExportedProperty
- protected int mBottom;
-
- /**
- * The offset, in pixels, by which the content of this view is scrolled
- * horizontally.
- * {@hide}
- */
- @ViewDebug.ExportedProperty
- protected int mScrollX;
- /**
- * The offset, in pixels, by which the content of this view is scrolled
- * vertically.
- * {@hide}
- */
- @ViewDebug.ExportedProperty
- protected int mScrollY;
-
- /**
- * The left padding in pixels, that is the distance in pixels between the
- * left edge of this view and the left edge of its content.
- * {@hide}
- */
- @ViewDebug.ExportedProperty
- protected int mPaddingLeft;
- /**
- * The right padding in pixels, that is the distance in pixels between the
- * right edge of this view and the right edge of its content.
- * {@hide}
- */
- @ViewDebug.ExportedProperty
- protected int mPaddingRight;
- /**
- * The top padding in pixels, that is the distance in pixels between the
- * top edge of this view and the top edge of its content.
- * {@hide}
- */
- @ViewDebug.ExportedProperty
- protected int mPaddingTop;
- /**
- * The bottom padding in pixels, that is the distance in pixels between the
- * bottom edge of this view and the bottom edge of its content.
- * {@hide}
- */
- @ViewDebug.ExportedProperty
- protected int mPaddingBottom;
-
- /**
- * Cache the paddingRight set by the user to append to the scrollbar's size.
- */
- @ViewDebug.ExportedProperty
- int mUserPaddingRight;
-
- /**
- * Cache the paddingBottom set by the user to append to the scrollbar's size.
- */
- @ViewDebug.ExportedProperty
- int mUserPaddingBottom;
-
- private int mOldWidthMeasureSpec = Integer.MIN_VALUE;
- private int mOldHeightMeasureSpec = Integer.MIN_VALUE;
-
- private Resources mResources = null;
-
- private Drawable mBGDrawable;
-
- private int mBackgroundResource;
- private boolean mBackgroundSizeChanged;
-
- /**
- * Listener used to dispatch focus change events.
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected OnFocusChangeListener mOnFocusChangeListener;
-
- /**
- * Listener used to dispatch click events.
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected OnClickListener mOnClickListener;
-
- /**
- * Listener used to dispatch long click events.
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected OnLongClickListener mOnLongClickListener;
-
- /**
- * Listener used to build the context menu.
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected OnCreateContextMenuListener mOnCreateContextMenuListener;
-
- private OnKeyListener mOnKeyListener;
-
- private OnTouchListener mOnTouchListener;
-
- /**
- * The application environment this view lives in.
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected Context mContext;
-
- private ScrollabilityCache mScrollCache;
-
- private int[] mDrawableState = null;
-
- private Bitmap mDrawingCache;
-
- /**
- * When this view has focus and the next focus is {@link #FOCUS_LEFT},
- * the user may specify which view to go to next.
- */
- private int mNextFocusLeftId = View.NO_ID;
-
- /**
- * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
- * the user may specify which view to go to next.
- */
- private int mNextFocusRightId = View.NO_ID;
-
- /**
- * When this view has focus and the next focus is {@link #FOCUS_UP},
- * the user may specify which view to go to next.
- */
- private int mNextFocusUpId = View.NO_ID;
-
- /**
- * When this view has focus and the next focus is {@link #FOCUS_DOWN},
- * the user may specify which view to go to next.
- */
- private int mNextFocusDownId = View.NO_ID;
-
- private CheckForLongPress mPendingCheckForLongPress;
- private UnsetPressedState mUnsetPressedState;
-
- /**
- * Whether the long press's action has been invoked. The tap's action is invoked on the
- * up event while a long press is invoked as soon as the long press duration is reached, so
- * a long press could be performed before the tap is checked, in which case the tap's action
- * should not be invoked.
- */
- private boolean mHasPerformedLongPress;
-
- /**
- * The minimum height of the view. We'll try our best to have the height
- * of this view to at least this amount.
- */
- @ViewDebug.ExportedProperty
- private int mMinHeight;
-
- /**
- * The minimum width of the view. We'll try our best to have the width
- * of this view to at least this amount.
- */
- @ViewDebug.ExportedProperty
- private int mMinWidth;
-
- /**
- * The delegate to handle touch events that are physically in this view
- * but should be handled by another view.
- */
- private TouchDelegate mTouchDelegate = null;
-
- /**
- * Solid color to use as a background when creating the drawing cache. Enables
- * the cache to use 16 bit bitmaps instead of 32 bit.
- */
- private int mDrawingCacheBackgroundColor = 0;
-
- /**
- * Special tree observer used when mAttachInfo is null.
- */
- private ViewTreeObserver mFloatingTreeObserver;
-
- // Used for debug only
- static long sInstanceCount = 0;
-
- /**
- * Simple constructor to use when creating a view from code.
- *
- * @param context The Context the view is running in, through which it can
- * access the current theme, resources, etc.
- */
- public View(Context context) {
- mContext = context;
- mResources = context != null ? context.getResources() : null;
- mViewFlags = SOUND_EFFECTS_ENABLED|HAPTIC_FEEDBACK_ENABLED;
- ++sInstanceCount;
- }
-
- /**
- * Constructor that is called when inflating a view from XML. This is called
- * when a view is being constructed from an XML file, supplying attributes
- * that were specified in the XML file. This version uses a default style of
- * 0, so the only attribute values applied are those in the Context's Theme
- * and the given AttributeSet.
- *
- * <p>
- * The method onFinishInflate() will be called after all children have been
- * added.
- *
- * @param context The Context the view is running in, through which it can
- * access the current theme, resources, etc.
- * @param attrs The attributes of the XML tag that is inflating the view.
- * @see #View(Context, AttributeSet, int)
- */
- public View(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- /**
- * Perform inflation from XML and apply a class-specific base style. This
- * constructor of View allows subclasses to use their own base style when
- * they are inflating. For example, a Button class's constructor would call
- * this version of the super class constructor and supply
- * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
- * the theme's button style to modify all of the base view attributes (in
- * particular its background) as well as the Button class's attributes.
- *
- * @param context The Context the view is running in, through which it can
- * access the current theme, resources, etc.
- * @param attrs The attributes of the XML tag that is inflating the view.
- * @param defStyle The default style to apply to this view. If 0, no style
- * will be applied (beyond what is included in the theme). This may
- * either be an attribute resource, whose value will be retrieved
- * from the current theme, or an explicit style resource.
- * @see #View(Context, AttributeSet)
- */
- public View(Context context, AttributeSet attrs, int defStyle) {
- this(context);
-
- TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
- defStyle, 0);
-
- Drawable background = null;
-
- int leftPadding = -1;
- int topPadding = -1;
- int rightPadding = -1;
- int bottomPadding = -1;
-
- int padding = -1;
-
- int viewFlagValues = 0;
- int viewFlagMasks = 0;
-
- boolean setScrollContainer = false;
-
- int x = 0;
- int y = 0;
-
- int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
-
- final int N = a.getIndexCount();
- for (int i = 0; i < N; i++) {
- int attr = a.getIndex(i);
- switch (attr) {
- case com.android.internal.R.styleable.View_background:
- background = a.getDrawable(attr);
- break;
- case com.android.internal.R.styleable.View_padding:
- padding = a.getDimensionPixelSize(attr, -1);
- break;
- case com.android.internal.R.styleable.View_paddingLeft:
- leftPadding = a.getDimensionPixelSize(attr, -1);
- break;
- case com.android.internal.R.styleable.View_paddingTop:
- topPadding = a.getDimensionPixelSize(attr, -1);
- break;
- case com.android.internal.R.styleable.View_paddingRight:
- rightPadding = a.getDimensionPixelSize(attr, -1);
- break;
- case com.android.internal.R.styleable.View_paddingBottom:
- bottomPadding = a.getDimensionPixelSize(attr, -1);
- break;
- case com.android.internal.R.styleable.View_scrollX:
- x = a.getDimensionPixelOffset(attr, 0);
- break;
- case com.android.internal.R.styleable.View_scrollY:
- y = a.getDimensionPixelOffset(attr, 0);
- break;
- case com.android.internal.R.styleable.View_id:
- mID = a.getResourceId(attr, NO_ID);
- break;
- case com.android.internal.R.styleable.View_tag:
- mTag = a.getText(attr);
- break;
- case com.android.internal.R.styleable.View_fitsSystemWindows:
- if (a.getBoolean(attr, false)) {
- viewFlagValues |= FITS_SYSTEM_WINDOWS;
- viewFlagMasks |= FITS_SYSTEM_WINDOWS;
- }
- break;
- case com.android.internal.R.styleable.View_focusable:
- if (a.getBoolean(attr, false)) {
- viewFlagValues |= FOCUSABLE;
- viewFlagMasks |= FOCUSABLE_MASK;
- }
- break;
- case com.android.internal.R.styleable.View_focusableInTouchMode:
- if (a.getBoolean(attr, false)) {
- viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
- viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
- }
- break;
- case com.android.internal.R.styleable.View_clickable:
- if (a.getBoolean(attr, false)) {
- viewFlagValues |= CLICKABLE;
- viewFlagMasks |= CLICKABLE;
- }
- break;
- case com.android.internal.R.styleable.View_longClickable:
- if (a.getBoolean(attr, false)) {
- viewFlagValues |= LONG_CLICKABLE;
- viewFlagMasks |= LONG_CLICKABLE;
- }
- break;
- case com.android.internal.R.styleable.View_saveEnabled:
- if (!a.getBoolean(attr, true)) {
- viewFlagValues |= SAVE_DISABLED;
- viewFlagMasks |= SAVE_DISABLED_MASK;
- }
- break;
- case com.android.internal.R.styleable.View_duplicateParentState:
- if (a.getBoolean(attr, false)) {
- viewFlagValues |= DUPLICATE_PARENT_STATE;
- viewFlagMasks |= DUPLICATE_PARENT_STATE;
- }
- break;
- case com.android.internal.R.styleable.View_visibility:
- final int visibility = a.getInt(attr, 0);
- if (visibility != 0) {
- viewFlagValues |= VISIBILITY_FLAGS[visibility];
- viewFlagMasks |= VISIBILITY_MASK;
- }
- break;
- case com.android.internal.R.styleable.View_drawingCacheQuality:
- final int cacheQuality = a.getInt(attr, 0);
- if (cacheQuality != 0) {
- viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
- viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
- }
- break;
- case com.android.internal.R.styleable.View_soundEffectsEnabled:
- if (!a.getBoolean(attr, true)) {
- viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
- viewFlagMasks |= SOUND_EFFECTS_ENABLED;
- }
- case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
- if (!a.getBoolean(attr, true)) {
- viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
- viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
- }
- case R.styleable.View_scrollbars:
- final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
- if (scrollbars != SCROLLBARS_NONE) {
- viewFlagValues |= scrollbars;
- viewFlagMasks |= SCROLLBARS_MASK;
- initializeScrollbars(a);
- }
- break;
- case R.styleable.View_fadingEdge:
- final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
- if (fadingEdge != FADING_EDGE_NONE) {
- viewFlagValues |= fadingEdge;
- viewFlagMasks |= FADING_EDGE_MASK;
- initializeFadingEdge(a);
- }
- break;
- case R.styleable.View_scrollbarStyle:
- scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
- if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
- viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
- viewFlagMasks |= SCROLLBARS_STYLE_MASK;
- }
- break;
- case R.styleable.View_isScrollContainer:
- setScrollContainer = true;
- if (a.getBoolean(attr, false)) {
- setScrollContainer(true);
- }
- break;
- case com.android.internal.R.styleable.View_keepScreenOn:
- if (a.getBoolean(attr, false)) {
- viewFlagValues |= KEEP_SCREEN_ON;
- viewFlagMasks |= KEEP_SCREEN_ON;
- }
- break;
- case R.styleable.View_nextFocusLeft:
- mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
- break;
- case R.styleable.View_nextFocusRight:
- mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
- break;
- case R.styleable.View_nextFocusUp:
- mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
- break;
- case R.styleable.View_nextFocusDown:
- mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
- break;
- case R.styleable.View_minWidth:
- mMinWidth = a.getDimensionPixelSize(attr, 0);
- break;
- case R.styleable.View_minHeight:
- mMinHeight = a.getDimensionPixelSize(attr, 0);
- break;
- }
- }
-
- if (background != null) {
- setBackgroundDrawable(background);
- }
-
- if (padding >= 0) {
- leftPadding = padding;
- topPadding = padding;
- rightPadding = padding;
- bottomPadding = padding;
- }
-
- // If the user specified the padding (either with android:padding or
- // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
- // use the default padding or the padding from the background drawable
- // (stored at this point in mPadding*)
- setPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
- topPadding >= 0 ? topPadding : mPaddingTop,
- rightPadding >= 0 ? rightPadding : mPaddingRight,
- bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
-
- if (viewFlagMasks != 0) {
- setFlags(viewFlagValues, viewFlagMasks);
- }
-
- // Needs to be called after mViewFlags is set
- if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
- recomputePadding();
- }
-
- if (x != 0 || y != 0) {
- scrollTo(x, y);
- }
-
- if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
- setScrollContainer(true);
- }
-
- a.recycle();
- }
-
- /**
- * Non-public constructor for use in testing
- */
- View() {
- }
-
- @Override
- protected void finalize() throws Throwable {
- super.finalize();
- --sInstanceCount;
- }
-
- /**
- * <p>
- * Initializes the fading edges from a given set of styled attributes. This
- * method should be called by subclasses that need fading edges and when an
- * instance of these subclasses is created programmatically rather than
- * being inflated from XML. This method is automatically called when the XML
- * is inflated.
- * </p>
- *
- * @param a the styled attributes set to initialize the fading edges from
- */
- protected void initializeFadingEdge(TypedArray a) {
- initScrollCache();
-
- mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
- R.styleable.View_fadingEdgeLength,
- ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
- }
-
- /**
- * Returns the size of the vertical faded edges used to indicate that more
- * content in this view is visible.
- *
- * @return The size in pixels of the vertical faded edge or 0 if vertical
- * faded edges are not enabled for this view.
- * @attr ref android.R.styleable#View_fadingEdgeLength
- */
- public int getVerticalFadingEdgeLength() {
- if (isVerticalFadingEdgeEnabled()) {
- ScrollabilityCache cache = mScrollCache;
- if (cache != null) {
- return cache.fadingEdgeLength;
- }
- }
- return 0;
- }
-
- /**
- * Set the size of the faded edge used to indicate that more content in this
- * view is available. Will not change whether the fading edge is enabled; use
- * {@link #setVerticalFadingEdgeEnabled} or {@link #setHorizontalFadingEdgeEnabled}
- * to enable the fading edge for the vertical or horizontal fading edges.
- *
- * @param length The size in pixels of the faded edge used to indicate that more
- * content in this view is visible.
- */
- public void setFadingEdgeLength(int length) {
- initScrollCache();
- mScrollCache.fadingEdgeLength = length;
- }
-
- /**
- * Returns the size of the horizontal faded edges used to indicate that more
- * content in this view is visible.
- *
- * @return The size in pixels of the horizontal faded edge or 0 if horizontal
- * faded edges are not enabled for this view.
- * @attr ref android.R.styleable#View_fadingEdgeLength
- */
- public int getHorizontalFadingEdgeLength() {
- if (isHorizontalFadingEdgeEnabled()) {
- ScrollabilityCache cache = mScrollCache;
- if (cache != null) {
- return cache.fadingEdgeLength;
- }
- }
- return 0;
- }
-
- /**
- * Returns the width of the vertical scrollbar.
- *
- * @return The width in pixels of the vertical scrollbar or 0 if there
- * is no vertical scrollbar.
- */
- public int getVerticalScrollbarWidth() {
- ScrollabilityCache cache = mScrollCache;
- if (cache != null) {
- ScrollBarDrawable scrollBar = cache.scrollBar;
- if (scrollBar != null) {
- int size = scrollBar.getSize(true);
- if (size <= 0) {
- size = cache.scrollBarSize;
- }
- return size;
- }
- return 0;
- }
- return 0;
- }
-
- /**
- * Returns the height of the horizontal scrollbar.
- *
- * @return The height in pixels of the horizontal scrollbar or 0 if
- * there is no horizontal scrollbar.
- */
- protected int getHorizontalScrollbarHeight() {
- ScrollabilityCache cache = mScrollCache;
- if (cache != null) {
- ScrollBarDrawable scrollBar = cache.scrollBar;
- if (scrollBar != null) {
- int size = scrollBar.getSize(false);
- if (size <= 0) {
- size = cache.scrollBarSize;
- }
- return size;
- }
- return 0;
- }
- return 0;
- }
-
- /**
- * <p>
- * Initializes the scrollbars from a given set of styled attributes. This
- * method should be called by subclasses that need scrollbars and when an
- * instance of these subclasses is created programmatically rather than
- * being inflated from XML. This method is automatically called when the XML
- * is inflated.
- * </p>
- *
- * @param a the styled attributes set to initialize the scrollbars from
- */
- protected void initializeScrollbars(TypedArray a) {
- initScrollCache();
-
- if (mScrollCache.scrollBar == null) {
- mScrollCache.scrollBar = new ScrollBarDrawable();
- }
-
- final ScrollabilityCache scrollabilityCache = mScrollCache;
-
- scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
- com.android.internal.R.styleable.View_scrollbarSize,
- ViewConfiguration.get(mContext).getScaledScrollBarSize());
-
- Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
- scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
-
- Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
- if (thumb != null) {
- scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
- }
-
- boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
- false);
- if (alwaysDraw) {
- scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
- }
-
- track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
- scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
-
- thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
- if (thumb != null) {
- scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
- }
-
- alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
- false);
- if (alwaysDraw) {
- scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
- }
-
- // Re-apply user/background padding so that scrollbar(s) get added
- recomputePadding();
- }
-
- /**
- * <p>
- * Initalizes the scrollability cache if necessary.
- * </p>
- */
- private void initScrollCache() {
- if (mScrollCache == null) {
- mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext));
- }
- }
-
- /**
- * Register a callback to be invoked when focus of this view changed.
- *
- * @param l The callback that will run.
- */
- public void setOnFocusChangeListener(OnFocusChangeListener l) {
- mOnFocusChangeListener = l;
- }
-
- /**
- * Returns the focus-change callback registered for this view.
- *
- * @return The callback, or null if one is not registered.
- */
- public OnFocusChangeListener getOnFocusChangeListener() {
- return mOnFocusChangeListener;
- }
-
- /**
- * Register a callback to be invoked when this view is clicked. If this view is not
- * clickable, it becomes clickable.
- *
- * @param l The callback that will run
- *
- * @see #setClickable(boolean)
- */
- public void setOnClickListener(OnClickListener l) {
- if (!isClickable()) {
- setClickable(true);
- }
- mOnClickListener = l;
- }
-
- /**
- * Register a callback to be invoked when this view is clicked and held. If this view is not
- * long clickable, it becomes long clickable.
- *
- * @param l The callback that will run
- *
- * @see #setLongClickable(boolean)
- */
- public void setOnLongClickListener(OnLongClickListener l) {
- if (!isLongClickable()) {
- setLongClickable(true);
- }
- mOnLongClickListener = l;
- }
-
- /**
- * Register a callback to be invoked when the context menu for this view is
- * being built. If this view is not long clickable, it becomes long clickable.
- *
- * @param l The callback that will run
- *
- */
- public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
- if (!isLongClickable()) {
- setLongClickable(true);
- }
- mOnCreateContextMenuListener = l;
- }
-
- /**
- * Call this view's OnClickListener, if it is defined.
- *
- * @return True there was an assigned OnClickListener that was called, false
- * otherwise is returned.
- */
- public boolean performClick() {
- if (mOnClickListener != null) {
- playSoundEffect(SoundEffectConstants.CLICK);
- mOnClickListener.onClick(this);
- return true;
- }
-
- return false;
- }
-
- /**
- * Call this view's OnLongClickListener, if it is defined. Invokes the context menu
- * if the OnLongClickListener did not consume the event.
- *
- * @return True there was an assigned OnLongClickListener that was called, false
- * otherwise is returned.
- */
- public boolean performLongClick() {
- boolean handled = false;
- if (mOnLongClickListener != null) {
- handled = mOnLongClickListener.onLongClick(View.this);
- }
- if (!handled) {
- handled = showContextMenu();
- }
- if (handled) {
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- }
- return handled;
- }
-
- /**
- * Bring up the context menu for this view.
- *
- * @return Whether a context menu was displayed.
- */
- public boolean showContextMenu() {
- return getParent().showContextMenuForChild(this);
- }
-
- /**
- * Register a callback to be invoked when a key is pressed in this view.
- * @param l the key listener to attach to this view
- */
- public void setOnKeyListener(OnKeyListener l) {
- mOnKeyListener = l;
- }
-
- /**
- * Register a callback to be invoked when a touch event is sent to this view.
- * @param l the touch listener to attach to this view
- */
- public void setOnTouchListener(OnTouchListener l) {
- mOnTouchListener = l;
- }
-
- /**
- * Give this view focus. This will cause {@link #onFocusChanged} to be called.
- *
- * Note: this does not check whether this {@link View} should get focus, it just
- * gives it focus no matter what. It should only be called internally by framework
- * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
- *
- * @param direction values are View.FOCUS_UP, View.FOCUS_DOWN,
- * View.FOCUS_LEFT or View.FOCUS_RIGHT. This is the direction which
- * focus moved when requestFocus() is called. It may not always
- * apply, in which case use the default View.FOCUS_DOWN.
- * @param previouslyFocusedRect The rectangle of the view that had focus
- * prior in this View's coordinate system.
- */
- void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
- if (DBG) {
- System.out.println(this + " requestFocus()");
- }
-
- if ((mPrivateFlags & FOCUSED) == 0) {
- mPrivateFlags |= FOCUSED;
-
- if (mParent != null) {
- mParent.requestChildFocus(this, this);
- }
-
- onFocusChanged(true, direction, previouslyFocusedRect);
- refreshDrawableState();
- }
- }
-
- /**
- * Request that a rectangle of this view be visible on the screen,
- * scrolling if necessary just enough.
- *
- * <p>A View should call this if it maintains some notion of which part
- * of its content is interesting. For example, a text editing view
- * should call this when its cursor moves.
- *
- * @param rectangle The rectangle.
- * @return Whether any parent scrolled.
- */
- public boolean requestRectangleOnScreen(Rect rectangle) {
- return requestRectangleOnScreen(rectangle, false);
- }
-
- /**
- * Request that a rectangle of this view be visible on the screen,
- * scrolling if necessary just enough.
- *
- * <p>A View should call this if it maintains some notion of which part
- * of its content is interesting. For example, a text editing view
- * should call this when its cursor moves.
- *
- * <p>When <code>immediate</code> is set to true, scrolling will not be
- * animated.
- *
- * @param rectangle The rectangle.
- * @param immediate True to forbid animated scrolling, false otherwise
- * @return Whether any parent scrolled.
- */
- public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
- View child = this;
- ViewParent parent = mParent;
- boolean scrolled = false;
- while (parent != null) {
- scrolled |= parent.requestChildRectangleOnScreen(child,
- rectangle, immediate);
-
- // offset rect so next call has the rectangle in the
- // coordinate system of its direct child.
- rectangle.offset(child.getLeft(), child.getTop());
- rectangle.offset(-child.getScrollX(), -child.getScrollY());
-
- if (!(parent instanceof View)) {
- break;
- }
-
- child = (View) parent;
- parent = child.getParent();
- }
- return scrolled;
- }
-
- /**
- * Called when this view wants to give up focus. This will cause
- * {@link #onFocusChanged} to be called.
- */
- public void clearFocus() {
- if (DBG) {
- System.out.println(this + " clearFocus()");
- }
-
- if ((mPrivateFlags & FOCUSED) != 0) {
- mPrivateFlags &= ~FOCUSED;
-
- if (mParent != null) {
- mParent.clearChildFocus(this);
- }
-
- onFocusChanged(false, 0, null);
- refreshDrawableState();
- }
- }
-
- /**
- * Called to clear the focus of a view that is about to be removed.
- * Doesn't call clearChildFocus, which prevents this view from taking
- * focus again before it has been removed from the parent
- */
- void clearFocusForRemoval() {
- if ((mPrivateFlags & FOCUSED) != 0) {
- mPrivateFlags &= ~FOCUSED;
-
- onFocusChanged(false, 0, null);
- refreshDrawableState();
- }
- }
-
- /**
- * Called internally by the view system when a new view is getting focus.
- * This is what clears the old focus.
- */
- void unFocus() {
- if (DBG) {
- System.out.println(this + " unFocus()");
- }
-
- if ((mPrivateFlags & FOCUSED) != 0) {
- mPrivateFlags &= ~FOCUSED;
-
- onFocusChanged(false, 0, null);
- refreshDrawableState();
- }
- }
-
- /**
- * Returns true if this view has focus iteself, or is the ancestor of the
- * view that has focus.
- *
- * @return True if this view has or contains focus, false otherwise.
- */
- @ViewDebug.ExportedProperty
- public boolean hasFocus() {
- return (mPrivateFlags & FOCUSED) != 0;
- }
-
- /**
- * Returns true if this view is focusable or if it contains a reachable View
- * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
- * is a View whose parents do not block descendants focus.
- *
- * Only {@link #VISIBLE} views are considered focusable.
- *
- * @return True if the view is focusable or if the view contains a focusable
- * View, false otherwise.
- *
- * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
- */
- public boolean hasFocusable() {
- return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
- }
-
- /**
- * Called by the view system when the focus state of this view changes.
- * When the focus change event is caused by directional navigation, direction
- * and previouslyFocusedRect provide insight into where the focus is coming from.
- * When overriding, be sure to call up through to the super class so that
- * the standard focus handling will occur.
- *
- * @param gainFocus True if the View has focus; false otherwise.
- * @param direction The direction focus has moved when requestFocus()
- * is called to give this view focus. Values are
- * View.FOCUS_UP, View.FOCUS_DOWN, View.FOCUS_LEFT or
- * View.FOCUS_RIGHT. It may not always apply, in which
- * case use the default.
- * @param previouslyFocusedRect The rectangle, in this view's coordinate
- * system, of the previously focused view. If applicable, this will be
- * passed in as finer grained information about where the focus is coming
- * from (in addition to direction). Will be <code>null</code> otherwise.
- */
- protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (!gainFocus) {
- if (isPressed()) {
- setPressed(false);
- }
- if (imm != null && mAttachInfo != null
- && mAttachInfo.mHasWindowFocus) {
- imm.focusOut(this);
- }
- } else if (imm != null && mAttachInfo != null
- && mAttachInfo.mHasWindowFocus) {
- imm.focusIn(this);
- }
-
- invalidate();
- if (mOnFocusChangeListener != null) {
- mOnFocusChangeListener.onFocusChange(this, gainFocus);
- }
- }
-
- /**
- * Returns true if this view has focus
- *
- * @return True if this view has focus, false otherwise.
- */
- @ViewDebug.ExportedProperty
- public boolean isFocused() {
- return (mPrivateFlags & FOCUSED) != 0;
- }
-
- /**
- * Find the view in the hierarchy rooted at this view that currently has
- * focus.
- *
- * @return The view that currently has focus, or null if no focused view can
- * be found.
- */
- public View findFocus() {
- return (mPrivateFlags & FOCUSED) != 0 ? this : null;
- }
-
- /**
- * Change whether this view is one of the set of scrollable containers in
- * its window. This will be used to determine whether the window can
- * resize or must pan when a soft input area is open -- scrollable
- * containers allow the window to use resize mode since the container
- * will appropriately shrink.
- */
- public void setScrollContainer(boolean isScrollContainer) {
- if (isScrollContainer) {
- if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) {
- mAttachInfo.mScrollContainers.add(this);
- mPrivateFlags |= SCROLL_CONTAINER_ADDED;
- }
- mPrivateFlags |= SCROLL_CONTAINER;
- } else {
- if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
- mAttachInfo.mScrollContainers.remove(this);
- }
- mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED);
- }
- }
-
- /**
- * Returns the quality of the drawing cache.
- *
- * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
- * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
- *
- * @see #setDrawingCacheQuality(int)
- * @see #setDrawingCacheEnabled(boolean)
- * @see #isDrawingCacheEnabled()
- *
- * @attr ref android.R.styleable#View_drawingCacheQuality
- */
- public int getDrawingCacheQuality() {
- return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
- }
-
- /**
- * Set the drawing cache quality of this view. This value is used only when the
- * drawing cache is enabled
- *
- * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
- * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
- *
- * @see #getDrawingCacheQuality()
- * @see #setDrawingCacheEnabled(boolean)
- * @see #isDrawingCacheEnabled()
- *
- * @attr ref android.R.styleable#View_drawingCacheQuality
- */
- public void setDrawingCacheQuality(int quality) {
- setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
- }
-
- /**
- * Returns whether the screen should remain on, corresponding to the current
- * value of {@link #KEEP_SCREEN_ON}.
- *
- * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
- *
- * @see #setKeepScreenOn(boolean)
- *
- * @attr ref android.R.styleable#View_keepScreenOn
- */
- public boolean getKeepScreenOn() {
- return (mViewFlags & KEEP_SCREEN_ON) != 0;
- }
-
- /**
- * Controls whether the screen should remain on, modifying the
- * value of {@link #KEEP_SCREEN_ON}.
- *
- * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
- *
- * @see #getKeepScreenOn()
- *
- * @attr ref android.R.styleable#View_keepScreenOn
- */
- public void setKeepScreenOn(boolean keepScreenOn) {
- setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
- }
-
- /**
- * @return The user specified next focus ID.
- *
- * @attr ref android.R.styleable#View_nextFocusLeft
- */
- public int getNextFocusLeftId() {
- return mNextFocusLeftId;
- }
-
- /**
- * Set the id of the view to use for the next focus
- *
- * @param nextFocusLeftId
- *
- * @attr ref android.R.styleable#View_nextFocusLeft
- */
- public void setNextFocusLeftId(int nextFocusLeftId) {
- mNextFocusLeftId = nextFocusLeftId;
- }
-
- /**
- * @return The user specified next focus ID.
- *
- * @attr ref android.R.styleable#View_nextFocusRight
- */
- public int getNextFocusRightId() {
- return mNextFocusRightId;
- }
-
- /**
- * Set the id of the view to use for the next focus
- *
- * @param nextFocusRightId
- *
- * @attr ref android.R.styleable#View_nextFocusRight
- */
- public void setNextFocusRightId(int nextFocusRightId) {
- mNextFocusRightId = nextFocusRightId;
- }
-
- /**
- * @return The user specified next focus ID.
- *
- * @attr ref android.R.styleable#View_nextFocusUp
- */
- public int getNextFocusUpId() {
- return mNextFocusUpId;
- }
-
- /**
- * Set the id of the view to use for the next focus
- *
- * @param nextFocusUpId
- *
- * @attr ref android.R.styleable#View_nextFocusUp
- */
- public void setNextFocusUpId(int nextFocusUpId) {
- mNextFocusUpId = nextFocusUpId;
- }
-
- /**
- * @return The user specified next focus ID.
- *
- * @attr ref android.R.styleable#View_nextFocusDown
- */
- public int getNextFocusDownId() {
- return mNextFocusDownId;
- }
-
- /**
- * Set the id of the view to use for the next focus
- *
- * @param nextFocusDownId
- *
- * @attr ref android.R.styleable#View_nextFocusDown
- */
- public void setNextFocusDownId(int nextFocusDownId) {
- mNextFocusDownId = nextFocusDownId;
- }
-
- /**
- * Returns the visibility of this view and all of its ancestors
- *
- * @return True if this view and all of its ancestors are {@link #VISIBLE}
- */
- public boolean isShown() {
- View current = this;
- //noinspection ConstantConditions
- do {
- if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
- return false;
- }
- ViewParent parent = current.mParent;
- if (parent == null) {
- return false; // We are not attached to the view root
- }
- if (!(parent instanceof View)) {
- return true;
- }
- current = (View) parent;
- } while (current != null);
-
- return false;
- }
-
- /**
- * Apply the insets for system windows to this view, if the FITS_SYSTEM_WINDOWS flag
- * is set
- *
- * @param insets Insets for system windows
- *
- * @return True if this view applied the insets, false otherwise
- */
- protected boolean fitSystemWindows(Rect insets) {
- if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
- mPaddingLeft = insets.left;
- mPaddingTop = insets.top;
- mPaddingRight = insets.right;
- mPaddingBottom = insets.bottom;
- requestLayout();
- return true;
- }
- return false;
- }
-
- /**
- * Returns the visibility status for this view.
- *
- * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
- * @attr ref android.R.styleable#View_visibility
- */
- @ViewDebug.ExportedProperty(mapping = {
- @ViewDebug.IntToString(from = 0, to = "VISIBLE"),
- @ViewDebug.IntToString(from = 4, to = "INVISIBLE"),
- @ViewDebug.IntToString(from = 8, to = "GONE")
- })
- public int getVisibility() {
- return mViewFlags & VISIBILITY_MASK;
- }
-
- /**
- * Set the enabled state of this view.
- *
- * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
- * @attr ref android.R.styleable#View_visibility
- */
- @RemotableViewMethod
- public void setVisibility(int visibility) {
- setFlags(visibility, VISIBILITY_MASK);
- if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false);
- }
-
- /**
- * Returns the enabled status for this view. The interpretation of the
- * enabled state varies by subclass.
- *
- * @return True if this view is enabled, false otherwise.
- */
- @ViewDebug.ExportedProperty
- public boolean isEnabled() {
- return (mViewFlags & ENABLED_MASK) == ENABLED;
- }
-
- /**
- * Set the enabled state of this view. The interpretation of the enabled
- * state varies by subclass.
- *
- * @param enabled True if this view is enabled, false otherwise.
- */
- public void setEnabled(boolean enabled) {
- setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
-
- /*
- * The View most likely has to change its appearance, so refresh
- * the drawable state.
- */
- refreshDrawableState();
-
- // Invalidate too, since the default behavior for views is to be
- // be drawn at 50% alpha rather than to change the drawable.
- invalidate();
- }
-
- /**
- * Set whether this view can receive the focus.
- *
- * Setting this to false will also ensure that this view is not focusable
- * in touch mode.
- *
- * @param focusable If true, this view can receive the focus.
- *
- * @see #setFocusableInTouchMode(boolean)
- * @attr ref android.R.styleable#View_focusable
- */
- public void setFocusable(boolean focusable) {
- if (!focusable) {
- setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
- }
- setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
- }
-
- /**
- * Set whether this view can receive focus while in touch mode.
- *
- * Setting this to true will also ensure that this view is focusable.
- *
- * @param focusableInTouchMode If true, this view can receive the focus while
- * in touch mode.
- *
- * @see #setFocusable(boolean)
- * @attr ref android.R.styleable#View_focusableInTouchMode
- */
- public void setFocusableInTouchMode(boolean focusableInTouchMode) {
- // Focusable in touch mode should always be set before the focusable flag
- // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
- // which, in touch mode, will not successfully request focus on this view
- // because the focusable in touch mode flag is not set
- setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
- if (focusableInTouchMode) {
- setFlags(FOCUSABLE, FOCUSABLE_MASK);
- }
- }
-
- /**
- * Set whether this view should have sound effects enabled for events such as
- * clicking and touching.
- *
- * <p>You may wish to disable sound effects for a view if you already play sounds,
- * for instance, a dial key that plays dtmf tones.
- *
- * @param soundEffectsEnabled whether sound effects are enabled for this view.
- * @see #isSoundEffectsEnabled()
- * @see #playSoundEffect(int)
- * @attr ref android.R.styleable#View_soundEffectsEnabled
- */
- public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
- setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
- }
-
- /**
- * @return whether this view should have sound effects enabled for events such as
- * clicking and touching.
- *
- * @see #setSoundEffectsEnabled(boolean)
- * @see #playSoundEffect(int)
- * @attr ref android.R.styleable#View_soundEffectsEnabled
- */
- @ViewDebug.ExportedProperty
- public boolean isSoundEffectsEnabled() {
- return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
- }
-
- /**
- * Set whether this view should have haptic feedback for events such as
- * long presses.
- *
- * <p>You may wish to disable haptic feedback if your view already controls
- * its own haptic feedback.
- *
- * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
- * @see #isHapticFeedbackEnabled()
- * @see #performHapticFeedback(int)
- * @attr ref android.R.styleable#View_hapticFeedbackEnabled
- */
- public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
- setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
- }
-
- /**
- * @return whether this view should have haptic feedback enabled for events
- * long presses.
- *
- * @see #setHapticFeedbackEnabled(boolean)
- * @see #performHapticFeedback(int)
- * @attr ref android.R.styleable#View_hapticFeedbackEnabled
- */
- @ViewDebug.ExportedProperty
- public boolean isHapticFeedbackEnabled() {
- return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
- }
-
- /**
- * If this view doesn't do any drawing on its own, set this flag to
- * allow further optimizations. By default, this flag is not set on
- * View, but could be set on some View subclasses such as ViewGroup.
- *
- * Typically, if you override {@link #onDraw} you should clear this flag.
- *
- * @param willNotDraw whether or not this View draw on its own
- */
- public void setWillNotDraw(boolean willNotDraw) {
- setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
- }
-
- /**
- * Returns whether or not this View draws on its own.
- *
- * @return true if this view has nothing to draw, false otherwise
- */
- @ViewDebug.ExportedProperty
- public boolean willNotDraw() {
- return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
- }
-
- /**
- * When a View's drawing cache is enabled, drawing is redirected to an
- * offscreen bitmap. Some views, like an ImageView, must be able to
- * bypass this mechanism if they already draw a single bitmap, to avoid
- * unnecessary usage of the memory.
- *
- * @param willNotCacheDrawing true if this view does not cache its
- * drawing, false otherwise
- */
- public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
- setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
- }
-
- /**
- * Returns whether or not this View can cache its drawing or not.
- *
- * @return true if this view does not cache its drawing, false otherwise
- */
- @ViewDebug.ExportedProperty
- public boolean willNotCacheDrawing() {
- return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
- }
-
- /**
- * Indicates whether this view reacts to click events or not.
- *
- * @return true if the view is clickable, false otherwise
- *
- * @see #setClickable(boolean)
- * @attr ref android.R.styleable#View_clickable
- */
- @ViewDebug.ExportedProperty
- public boolean isClickable() {
- return (mViewFlags & CLICKABLE) == CLICKABLE;
- }
-
- /**
- * Enables or disables click events for this view. When a view
- * is clickable it will change its state to "pressed" on every click.
- * Subclasses should set the view clickable to visually react to
- * user's clicks.
- *
- * @param clickable true to make the view clickable, false otherwise
- *
- * @see #isClickable()
- * @attr ref android.R.styleable#View_clickable
- */
- public void setClickable(boolean clickable) {
- setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
- }
-
- /**
- * Indicates whether this view reacts to long click events or not.
- *
- * @return true if the view is long clickable, false otherwise
- *
- * @see #setLongClickable(boolean)
- * @attr ref android.R.styleable#View_longClickable
- */
- public boolean isLongClickable() {
- return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
- }
-
- /**
- * Enables or disables long click events for this view. When a view is long
- * clickable it reacts to the user holding down the button for a longer
- * duration than a tap. This event can either launch the listener or a
- * context menu.
- *
- * @param longClickable true to make the view long clickable, false otherwise
- * @see #isLongClickable()
- * @attr ref android.R.styleable#View_longClickable
- */
- public void setLongClickable(boolean longClickable) {
- setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
- }
-
- /**
- * Sets the pressed that for this view.
- *
- * @see #isClickable()
- * @see #setClickable(boolean)
- *
- * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
- * the View's internal state from a previously set "pressed" state.
- */
- public void setPressed(boolean pressed) {
- if (pressed) {
- mPrivateFlags |= PRESSED;
- } else {
- mPrivateFlags &= ~PRESSED;
- }
- refreshDrawableState();
- dispatchSetPressed(pressed);
- }
-
- /**
- * Dispatch setPressed to all of this View's children.
- *
- * @see #setPressed(boolean)
- *
- * @param pressed The new pressed state
- */
- protected void dispatchSetPressed(boolean pressed) {
- }
-
- /**
- * Indicates whether the view is currently in pressed state. Unless
- * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
- * the pressed state.
- *
- * @see #setPressed
- * @see #isClickable()
- * @see #setClickable(boolean)
- *
- * @return true if the view is currently pressed, false otherwise
- */
- public boolean isPressed() {
- return (mPrivateFlags & PRESSED) == PRESSED;
- }
-
- /**
- * Indicates whether this view will save its state (that is,
- * whether its {@link #onSaveInstanceState} method will be called).
- *
- * @return Returns true if the view state saving is enabled, else false.
- *
- * @see #setSaveEnabled(boolean)
- * @attr ref android.R.styleable#View_saveEnabled
- */
- public boolean isSaveEnabled() {
- return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
- }
-
- /**
- * Controls whether the saving of this view's state is
- * enabled (that is, whether its {@link #onSaveInstanceState} method
- * will be called). Note that even if freezing is enabled, the
- * view still must have an id assigned to it (via {@link #setId setId()})
- * for its state to be saved. This flag can only disable the
- * saving of this view; any child views may still have their state saved.
- *
- * @param enabled Set to false to <em>disable</em> state saving, or true
- * (the default) to allow it.
- *
- * @see #isSaveEnabled()
- * @see #setId(int)
- * @see #onSaveInstanceState()
- * @attr ref android.R.styleable#View_saveEnabled
- */
- public void setSaveEnabled(boolean enabled) {
- setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
- }
-
-
- /**
- * Returns whether this View is able to take focus.
- *
- * @return True if this view can take focus, or false otherwise.
- * @attr ref android.R.styleable#View_focusable
- */
- @ViewDebug.ExportedProperty
- public final boolean isFocusable() {
- return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
- }
-
- /**
- * When a view is focusable, it may not want to take focus when in touch mode.
- * For example, a button would like focus when the user is navigating via a D-pad
- * so that the user can click on it, but once the user starts touching the screen,
- * the button shouldn't take focus
- * @return Whether the view is focusable in touch mode.
- * @attr ref android.R.styleable#View_focusableInTouchMode
- */
- @ViewDebug.ExportedProperty
- public final boolean isFocusableInTouchMode() {
- return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
- }
-
- /**
- * Find the nearest view in the specified direction that can take focus.
- * This does not actually give focus to that view.
- *
- * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
- *
- * @return The nearest focusable in the specified direction, or null if none
- * can be found.
- */
- public View focusSearch(int direction) {
- if (mParent != null) {
- return mParent.focusSearch(this, direction);
- } else {
- return null;
- }
- }
-
- /**
- * This method is the last chance for the focused view and its ancestors to
- * respond to an arrow key. This is called when the focused view did not
- * consume the key internally, nor could the view system find a new view in
- * the requested direction to give focus to.
- *
- * @param focused The currently focused view.
- * @param direction The direction focus wants to move. One of FOCUS_UP,
- * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
- * @return True if the this view consumed this unhandled move.
- */
- public boolean dispatchUnhandledMove(View focused, int direction) {
- return false;
- }
-
- /**
- * If a user manually specified the next view id for a particular direction,
- * use the root to look up the view. Once a view is found, it is cached
- * for future lookups.
- * @param root The root view of the hierarchy containing this view.
- * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
- * @return The user specified next view, or null if there is none.
- */
- View findUserSetNextFocus(View root, int direction) {
- switch (direction) {
- case FOCUS_LEFT:
- if (mNextFocusLeftId == View.NO_ID) return null;
- return findViewShouldExist(root, mNextFocusLeftId);
- case FOCUS_RIGHT:
- if (mNextFocusRightId == View.NO_ID) return null;
- return findViewShouldExist(root, mNextFocusRightId);
- case FOCUS_UP:
- if (mNextFocusUpId == View.NO_ID) return null;
- return findViewShouldExist(root, mNextFocusUpId);
- case FOCUS_DOWN:
- if (mNextFocusDownId == View.NO_ID) return null;
- return findViewShouldExist(root, mNextFocusDownId);
- }
- return null;
- }
-
- private static View findViewShouldExist(View root, int childViewId) {
- View result = root.findViewById(childViewId);
- if (result == null) {
- Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified "
- + "by user for id " + childViewId);
- }
- return result;
- }
-
- /**
- * Find and return all focusable views that are descendants of this view,
- * possibly including this view if it is focusable itself.
- *
- * @param direction The direction of the focus
- * @return A list of focusable views
- */
- public ArrayList<View> getFocusables(int direction) {
- ArrayList<View> result = new ArrayList<View>(24);
- addFocusables(result, direction);
- return result;
- }
-
- /**
- * Add any focusable views that are descendants of this view (possibly
- * including this view if it is focusable itself) to views. If we are in touch mode,
- * only add views that are also focusable in touch mode.
- *
- * @param views Focusable views found so far
- * @param direction The direction of the focus
- */
- public void addFocusables(ArrayList<View> views, int direction) {
- if (!isFocusable()) return;
-
- if (isInTouchMode() && !isFocusableInTouchMode()) return;
-
- views.add(this);
- }
-
- /**
- * Find and return all touchable views that are descendants of this view,
- * possibly including this view if it is touchable itself.
- *
- * @return A list of touchable views
- */
- public ArrayList<View> getTouchables() {
- ArrayList<View> result = new ArrayList<View>();
- addTouchables(result);
- return result;
- }
-
- /**
- * Add any touchable views that are descendants of this view (possibly
- * including this view if it is touchable itself) to views.
- *
- * @param views Touchable views found so far
- */
- public void addTouchables(ArrayList<View> views) {
- final int viewFlags = mViewFlags;
-
- if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
- && (viewFlags & ENABLED_MASK) == ENABLED) {
- views.add(this);
- }
- }
-
- /**
- * Call this to try to give focus to a specific view or to one of its
- * descendants.
- *
- * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false),
- * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode})
- * while the device is in touch mode.
- *
- * See also {@link #focusSearch}, which is what you call to say that you
- * have focus, and you want your parent to look for the next one.
- *
- * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
- * {@link #FOCUS_DOWN} and <code>null</code>.
- *
- * @return Whether this view or one of its descendants actually took focus.
- */
- public final boolean requestFocus() {
- return requestFocus(View.FOCUS_DOWN);
- }
-
-
- /**
- * Call this to try to give focus to a specific view or to one of its
- * descendants and give it a hint about what direction focus is heading.
- *
- * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false),
- * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode})
- * while the device is in touch mode.
- *
- * See also {@link #focusSearch}, which is what you call to say that you
- * have focus, and you want your parent to look for the next one.
- *
- * This is equivalent to calling {@link #requestFocus(int, Rect)} with
- * <code>null</code> set for the previously focused rectangle.
- *
- * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
- * @return Whether this view or one of its descendants actually took focus.
- */
- public final boolean requestFocus(int direction) {
- return requestFocus(direction, null);
- }
-
- /**
- * Call this to try to give focus to a specific view or to one of its descendants
- * and give it hints about the direction and a specific rectangle that the focus
- * is coming from. The rectangle can help give larger views a finer grained hint
- * about where focus is coming from, and therefore, where to show selection, or
- * forward focus change internally.
- *
- * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false),
- * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode})
- * while the device is in touch mode.
- *
- * A View will not take focus if it is not visible.
- *
- * A View will not take focus if one of its parents has {@link android.view.ViewGroup#getDescendantFocusability()}
- * equal to {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
- *
- * See also {@link #focusSearch}, which is what you call to say that you
- * have focus, and you want your parent to look for the next one.
- *
- * You may wish to override this method if your custom {@link View} has an internal
- * {@link View} that it wishes to forward the request to.
- *
- * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
- * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
- * to give a finer grained hint about where focus is coming from. May be null
- * if there is no hint.
- * @return Whether this view or one of its descendants actually took focus.
- */
- public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
- // need to be focusable
- if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
- (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
- return false;
- }
-
- // need to be focusable in touch mode if in touch mode
- if (isInTouchMode() &&
- (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
- return false;
- }
-
- // need to not have any parents blocking us
- if (hasAncestorThatBlocksDescendantFocus()) {
- return false;
- }
-
- handleFocusGainInternal(direction, previouslyFocusedRect);
- return true;
- }
-
- /**
- * Call this to try to give focus to a specific view or to one of its descendants. This is a
- * special variant of {@link #requestFocus() } that will allow views that are not focuable in
- * touch mode to request focus when they are touched.
- *
- * @return Whether this view or one of its descendants actually took focus.
- *
- * @see #isInTouchMode()
- *
- */
- public final boolean requestFocusFromTouch() {
- // Leave touch mode if we need to
- if (isInTouchMode()) {
- View root = getRootView();
- if (root != null) {
- ViewRoot viewRoot = (ViewRoot)root.getParent();
- if (viewRoot != null) {
- viewRoot.ensureTouchMode(false);
- }
- }
- }
- return requestFocus(View.FOCUS_DOWN);
- }
-
- /**
- * @return Whether any ancestor of this view blocks descendant focus.
- */
- private boolean hasAncestorThatBlocksDescendantFocus() {
- ViewParent ancestor = mParent;
- while (ancestor instanceof ViewGroup) {
- final ViewGroup vgAncestor = (ViewGroup) ancestor;
- if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
- return true;
- } else {
- ancestor = vgAncestor.getParent();
- }
- }
- return false;
- }
-
- /**
- * capture information of this view for later analysis: developement only
- * check dynamic switch to make sure we only dump view
- * when ViewDebug.SYSTEM_PROPERTY_CAPTURE_VIEW) is set
- */
- private static void captureViewInfo(String subTag, View v) {
- if (v == null ||
- SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_VIEW, 0) == 0) {
- return;
- }
- ViewDebug.dumpCapturedView(subTag, v);
- }
-
- /**
- * Dispatch a key event before it is processed by any input method
- * associated with the view hierarchy. This can be used to intercept
- * key events in special situations before the IME consumes them; a
- * typical example would be handling the BACK key to update the application's
- * UI instead of allowing the IME to see it and close itself.
- *
- * @param event The key event to be dispatched.
- * @return True if the event was handled, false otherwise.
- */
- public boolean dispatchKeyEventPreIme(KeyEvent event) {
- return onKeyPreIme(event.getKeyCode(), event);
- }
-
- /**
- * Dispatch a key event to the next view on the focus path. This path runs
- * from the top of the view tree down to the currently focused view. If this
- * view has focus, it will dispatch to itself. Otherwise it will dispatch
- * the next node down the focus path. This method also fires any key
- * listeners.
- *
- * @param event The key event to be dispatched.
- * @return True if the event was handled, false otherwise.
- */
- public boolean dispatchKeyEvent(KeyEvent event) {
- // If any attached key listener a first crack at the event.
- //noinspection SimplifiableIfStatement
-
- if (android.util.Config.LOGV) {
- captureViewInfo("captureViewKeyEvent", this);
- }
-
- if (mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
- && mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
- return true;
- }
-
- return event.dispatch(this);
- }
-
- /**
- * Dispatches a key shortcut event.
- *
- * @param event The key event to be dispatched.
- * @return True if the event was handled by the view, false otherwise.
- */
- public boolean dispatchKeyShortcutEvent(KeyEvent event) {
- return onKeyShortcut(event.getKeyCode(), event);
- }
-
- /**
- * Pass the touch screen motion event down to the target view, or this
- * view if it is the target.
- *
- * @param event The motion event to be dispatched.
- * @return True if the event was handled by the view, false otherwise.
- */
- public boolean dispatchTouchEvent(MotionEvent event) {
- if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
- mOnTouchListener.onTouch(this, event)) {
- return true;
- }
- return onTouchEvent(event);
- }
-
- /**
- * Pass a trackball motion event down to the focused view.
- *
- * @param event The motion event to be dispatched.
- * @return True if the event was handled by the view, false otherwise.
- */
- public boolean dispatchTrackballEvent(MotionEvent event) {
- //Log.i("view", "view=" + this + ", " + event.toString());
- return onTrackballEvent(event);
- }
-
- /**
- * Called when the window containing this view gains or loses window focus.
- * ViewGroups should override to route to their children.
- *
- * @param hasFocus True if the window containing this view now has focus,
- * false otherwise.
- */
- public void dispatchWindowFocusChanged(boolean hasFocus) {
- onWindowFocusChanged(hasFocus);
- }
-
- /**
- * Called when the window containing this view gains or loses focus. Note
- * that this is separate from view focus: to receive key events, both
- * your view and its window must have focus. If a window is displayed
- * on top of yours that takes input focus, then your own window will lose
- * focus but the view focus will remain unchanged.
- *
- * @param hasWindowFocus True if the window containing this view now has
- * focus, false otherwise.
- */
- public void onWindowFocusChanged(boolean hasWindowFocus) {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (!hasWindowFocus) {
- if (isPressed()) {
- setPressed(false);
- }
- if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
- imm.focusOut(this);
- }
- } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
- imm.focusIn(this);
- }
- refreshDrawableState();
- }
-
- /**
- * Returns true if this view is in a window that currently has window focus.
- * Note that this is not the same as the view itself having focus.
- *
- * @return True if this view is in a window that currently has window focus.
- */
- public boolean hasWindowFocus() {
- return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
- }
-
- /**
- * Dispatch a window visibility change down the view hierarchy.
- * ViewGroups should override to route to their children.
- *
- * @param visibility The new visibility of the window.
- *
- * @see #onWindowVisibilityChanged
- */
- public void dispatchWindowVisibilityChanged(int visibility) {
- onWindowVisibilityChanged(visibility);
- }
-
- /**
- * Called when the window containing has change its visibility
- * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note
- * that this tells you whether or not your window is being made visible
- * to the window manager; this does <em>not</em> tell you whether or not
- * your window is obscured by other windows on the screen, even if it
- * is itself visible.
- *
- * @param visibility The new visibility of the window.
- */
- protected void onWindowVisibilityChanged(int visibility) {
- }
-
- /**
- * Returns the current visibility of the window this view is attached to
- * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
- *
- * @return Returns the current visibility of the view's window.
- */
- public int getWindowVisibility() {
- return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
- }
-
- /**
- * Retrieve the overall visible display size in which the window this view is
- * attached to has been positioned in. This takes into account screen
- * decorations above the window, for both cases where the window itself
- * is being position inside of them or the window is being placed under
- * then and covered insets are used for the window to position its content
- * inside. In effect, this tells you the available area where content can
- * be placed and remain visible to users.
- *
- * <p>This function requires an IPC back to the window manager to retrieve
- * the requested information, so should not be used in performance critical
- * code like drawing.
- *
- * @param outRect Filled in with the visible display frame. If the view
- * is not attached to a window, this is simply the raw display size.
- */
- public void getWindowVisibleDisplayFrame(Rect outRect) {
- if (mAttachInfo != null) {
- try {
- mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
- } catch (RemoteException e) {
- return;
- }
- // XXX This is really broken, and probably all needs to be done
- // in the window manager, and we need to know more about whether
- // we want the area behind or in front of the IME.
- final Rect insets = mAttachInfo.mVisibleInsets;
- outRect.left += insets.left;
- outRect.top += insets.top;
- outRect.right -= insets.right;
- outRect.bottom -= insets.bottom;
- return;
- }
- Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
- outRect.set(0, 0, d.getWidth(), d.getHeight());
- }
-
- /**
- * Private function to aggregate all per-view attributes in to the view
- * root.
- */
- void dispatchCollectViewAttributes(int visibility) {
- performCollectViewAttributes(visibility);
- }
-
- void performCollectViewAttributes(int visibility) {
- //noinspection PointlessBitwiseExpression
- if (((visibility | mViewFlags) & (VISIBILITY_MASK | KEEP_SCREEN_ON))
- == (VISIBLE | KEEP_SCREEN_ON)) {
- mAttachInfo.mKeepScreenOn = true;
- }
- }
-
- void needGlobalAttributesUpdate(boolean force) {
- AttachInfo ai = mAttachInfo;
- if (ai != null) {
- if (ai.mKeepScreenOn || force) {
- ai.mRecomputeGlobalAttributes = true;
- }
- }
- }
-
- /**
- * Returns whether the device is currently in touch mode. Touch mode is entered
- * once the user begins interacting with the device by touch, and affects various
- * things like whether focus is always visible to the user.
- *
- * @return Whether the device is in touch mode.
- */
- @ViewDebug.ExportedProperty
- public boolean isInTouchMode() {
- if (mAttachInfo != null) {
- return mAttachInfo.mInTouchMode;
- } else {
- return ViewRoot.isInTouchMode();
- }
- }
-
- /**
- * Returns the context the view is running in, through which it can
- * access the current theme, resources, etc.
- *
- * @return The view's Context.
- */
- @ViewDebug.CapturedViewProperty
- public final Context getContext() {
- return mContext;
- }
-
- /**
- * Handle a key event before it is processed by any input method
- * associated with the view hierarchy. This can be used to intercept
- * key events in special situations before the IME consumes them; a
- * typical example would be handling the BACK key to update the application's
- * UI instead of allowing the IME to see it and close itself.
- *
- * @param keyCode The value in event.getKeyCode().
- * @param event Description of the key event.
- * @return If you handled the event, return true. If you want to allow the
- * event to be handled by the next receiver, return false.
- */
- public boolean onKeyPreIme(int keyCode, KeyEvent event) {
- return false;
- }
-
- /**
- * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
- * KeyEvent.Callback.onKeyMultiple()}: perform press of the view
- * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
- * is released, if the view is enabled and clickable.
- *
- * @param keyCode A key code that represents the button pressed, from
- * {@link android.view.KeyEvent}.
- * @param event The KeyEvent object that defines the button action.
- */
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- boolean result = false;
-
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_ENTER: {
- if ((mViewFlags & ENABLED_MASK) == DISABLED) {
- return true;
- }
- // Long clickable items don't necessarily have to be clickable
- if (((mViewFlags & CLICKABLE) == CLICKABLE ||
- (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
- (event.getRepeatCount() == 0)) {
- setPressed(true);
- if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
- postCheckForLongClick();
- }
- return true;
- }
- break;
- }
- }
- return result;
- }
-
- /**
- * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
- * KeyEvent.Callback.onKeyMultiple()}: perform clicking of the view
- * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
- * {@link KeyEvent#KEYCODE_ENTER} is released.
- *
- * @param keyCode A key code that represents the button pressed, from
- * {@link android.view.KeyEvent}.
- * @param event The KeyEvent object that defines the button action.
- */
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- boolean result = false;
-
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_ENTER: {
- if ((mViewFlags & ENABLED_MASK) == DISABLED) {
- return true;
- }
- if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
- setPressed(false);
-
- if (!mHasPerformedLongPress) {
- // This is a tap, so remove the longpress check
- if (mPendingCheckForLongPress != null) {
- removeCallbacks(mPendingCheckForLongPress);
- }
-
- result = performClick();
- }
- }
- break;
- }
- }
- return result;
- }
-
- /**
- * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
- * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
- * the event).
- *
- * @param keyCode A key code that represents the button pressed, from
- * {@link android.view.KeyEvent}.
- * @param repeatCount The number of times the action was made.
- * @param event The KeyEvent object that defines the button action.
- */
- public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
- return false;
- }
-
- /**
- * Called when an unhandled key shortcut event occurs.
- *
- * @param keyCode The value in event.getKeyCode().
- * @param event Description of the key event.
- * @return If you handled the event, return true. If you want to allow the
- * event to be handled by the next receiver, return false.
- */
- public boolean onKeyShortcut(int keyCode, KeyEvent event) {
- return false;
- }
-
- /**
- * Check whether the called view is a text editor, in which case it
- * would make sense to automatically display a soft input window for
- * it. Subclasses should override this if they implement
- * {@link #onCreateInputConnection(EditorInfo)} to return true if
- * a call on that method would return a non-null InputConnection. The
- * default implementation always returns false.
- *
- * @return Returns true if this view is a text editor, else false.
- */
- public boolean onCheckIsTextEditor() {
- return false;
- }
-
- /**
- * Create a new InputConnection for an InputMethod to interact
- * with the view. The default implementation returns null, since it doesn't
- * support input methods. You can override this to implement such support.
- * This is only needed for views that take focus and text input.
- *
- * <p>When implementing this, you probably also want to implement
- * {@link #onCheckIsTextEditor()} to indicate you will return a
- * non-null InputConnection.
- *
- * @param outAttrs Fill in with attribute information about the connection.
- */
- public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
- return null;
- }
-
- /**
- * Show the context menu for this view. It is not safe to hold on to the
- * menu after returning from this method.
- *
- * @param menu The context menu to populate
- */
- public void createContextMenu(ContextMenu menu) {
- ContextMenuInfo menuInfo = getContextMenuInfo();
-
- // Sets the current menu info so all items added to menu will have
- // my extra info set.
- ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
-
- onCreateContextMenu(menu);
- if (mOnCreateContextMenuListener != null) {
- mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
- }
-
- // Clear the extra information so subsequent items that aren't mine don't
- // have my extra info.
- ((MenuBuilder)menu).setCurrentMenuInfo(null);
-
- if (mParent != null) {
- mParent.createContextMenu(menu);
- }
- }
-
- /**
- * Views should implement this if they have extra information to associate
- * with the context menu. The return result is supplied as a parameter to
- * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
- * callback.
- *
- * @return Extra information about the item for which the context menu
- * should be shown. This information will vary across different
- * subclasses of View.
- */
- protected ContextMenuInfo getContextMenuInfo() {
- return null;
- }
-
- /**
- * Views should implement this if the view itself is going to add items to
- * the context menu.
- *
- * @param menu the context menu to populate
- */
- protected void onCreateContextMenu(ContextMenu menu) {
- }
-
- /**
- * Implement this method to handle trackball motion events. The
- * <em>relative</em> movement of the trackball since the last event
- * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
- * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so
- * that a movement of 1 corresponds to the user pressing one DPAD key (so
- * they will often be fractional values, representing the more fine-grained
- * movement information available from a trackball).
- *
- * @param event The motion event.
- * @return True if the event was handled, false otherwise.
- */
- public boolean onTrackballEvent(MotionEvent event) {
- return false;
- }
-
- /**
- * Implement this method to handle touch screen motion events.
- *
- * @param event The motion event.
- * @return True if the event was handled, false otherwise.
- */
- public boolean onTouchEvent(MotionEvent event) {
- final int viewFlags = mViewFlags;
-
- if ((viewFlags & ENABLED_MASK) == DISABLED) {
- // A disabled view that is clickable still consumes the touch
- // events, it just doesn't respond to them.
- return (((viewFlags & CLICKABLE) == CLICKABLE ||
- (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
- }
-
- if (mTouchDelegate != null) {
- if (mTouchDelegate.onTouchEvent(event)) {
- return true;
- }
- }
-
- if (((viewFlags & CLICKABLE) == CLICKABLE ||
- (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_UP:
- if ((mPrivateFlags & PRESSED) != 0) {
- // take focus if we don't have it already and we should in
- // touch mode.
- boolean focusTaken = false;
- if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
- focusTaken = requestFocus();
- }
-
- if (!mHasPerformedLongPress) {
- // This is a tap, so remove the longpress check
- if (mPendingCheckForLongPress != null) {
- removeCallbacks(mPendingCheckForLongPress);
- }
-
- // Only perform take click actions if we were in the pressed state
- if (!focusTaken) {
- performClick();
- }
- }
-
- if (mUnsetPressedState == null) {
- mUnsetPressedState = new UnsetPressedState();
- }
-
- if (!post(mUnsetPressedState)) {
- // If the post failed, unpress right now
- mUnsetPressedState.run();
- }
- }
- break;
-
- case MotionEvent.ACTION_DOWN:
- mPrivateFlags |= PRESSED;
- refreshDrawableState();
- if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
- postCheckForLongClick();
- }
- break;
-
- case MotionEvent.ACTION_CANCEL:
- mPrivateFlags &= ~PRESSED;
- refreshDrawableState();
- break;
-
- case MotionEvent.ACTION_MOVE:
- final int x = (int) event.getX();
- final int y = (int) event.getY();
-
- // Be lenient about moving outside of buttons
- int slop = ViewConfiguration.get(mContext).getScaledTouchSlop();
- if ((x < 0 - slop) || (x >= getWidth() + slop) ||
- (y < 0 - slop) || (y >= getHeight() + slop)) {
- // Outside button
- if ((mPrivateFlags & PRESSED) != 0) {
- // Remove any future long press checks
- if (mPendingCheckForLongPress != null) {
- removeCallbacks(mPendingCheckForLongPress);
- }
-
- // Need to switch from pressed to not pressed
- mPrivateFlags &= ~PRESSED;
- refreshDrawableState();
- }
- } else {
- // Inside button
- if ((mPrivateFlags & PRESSED) == 0) {
- // Need to switch from not pressed to pressed
- mPrivateFlags |= PRESSED;
- refreshDrawableState();
- }
- }
- break;
- }
- return true;
- }
-
- return false;
- }
-
- /**
- * Cancels a pending long press. Your subclass can use this if you
- * want the context menu to come up if the user presses and holds
- * at the same place, but you don't want it to come up if they press
- * and then move around enough to cause scrolling.
- */
- public void cancelLongPress() {
- if (mPendingCheckForLongPress != null) {
- removeCallbacks(mPendingCheckForLongPress);
- }
- }
-
- /**
- * Sets the TouchDelegate for this View.
- */
- public void setTouchDelegate(TouchDelegate delegate) {
- mTouchDelegate = delegate;
- }
-
- /**
- * Gets the TouchDelegate for this View.
- */
- public TouchDelegate getTouchDelegate() {
- return mTouchDelegate;
- }
-
- /**
- * Set flags controlling behavior of this view.
- *
- * @param flags Constant indicating the value which should be set
- * @param mask Constant indicating the bit range that should be changed
- */
- void setFlags(int flags, int mask) {
- int old = mViewFlags;
- mViewFlags = (mViewFlags & ~mask) | (flags & mask);
-
- int changed = mViewFlags ^ old;
- if (changed == 0) {
- return;
- }
- int privateFlags = mPrivateFlags;
-
- /* Check if the FOCUSABLE bit has changed */
- if (((changed & FOCUSABLE_MASK) != 0) &&
- ((privateFlags & HAS_BOUNDS) !=0)) {
- if (((old & FOCUSABLE_MASK) == FOCUSABLE)
- && ((privateFlags & FOCUSED) != 0)) {
- /* Give up focus if we are no longer focusable */
- clearFocus();
- } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
- && ((privateFlags & FOCUSED) == 0)) {
- /*
- * Tell the view system that we are now available to take focus
- * if no one else already has it.
- */
- if (mParent != null) mParent.focusableViewAvailable(this);
- }
- }
-
- if ((flags & VISIBILITY_MASK) == VISIBLE) {
- if ((changed & VISIBILITY_MASK) != 0) {
- /*
- * If this view is becoming visible, set the DRAWN flag so that
- * the next invalidate() will not be skipped.
- */
- mPrivateFlags |= DRAWN;
-
- needGlobalAttributesUpdate(true);
-
- // a view becoming visible is worth notifying the parent
- // about in case nothing has focus. even if this specific view
- // isn't focusable, it may contain something that is, so let
- // the root view try to give this focus if nothing else does.
- if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
- mParent.focusableViewAvailable(this);
- }
- }
- }
-
- /* Check if the GONE bit has changed */
- if ((changed & GONE) != 0) {
- needGlobalAttributesUpdate(false);
- requestLayout();
- invalidate();
-
- if (((mViewFlags & VISIBILITY_MASK) == GONE) && hasFocus()) {
- clearFocus();
- }
- if (mAttachInfo != null) {
- mAttachInfo.mViewVisibilityChanged = true;
- }
- }
-
- /* Check if the VISIBLE bit has changed */
- if ((changed & INVISIBLE) != 0) {
- needGlobalAttributesUpdate(false);
- invalidate();
-
- if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
- // root view becoming invisible shouldn't clear focus
- if (getRootView() != this) {
- clearFocus();
- }
- }
- if (mAttachInfo != null) {
- mAttachInfo.mViewVisibilityChanged = true;
- }
- }
-
- if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
- if (mDrawingCache != null) {
- mDrawingCache.recycle();
- }
- mDrawingCache = null;
- }
-
- if ((changed & DRAWING_CACHE_ENABLED) != 0) {
- if (mDrawingCache != null) {
- mDrawingCache.recycle();
- }
- mDrawingCache = null;
- mPrivateFlags &= ~DRAWING_CACHE_VALID;
- }
-
- if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
- if (mDrawingCache != null) {
- mDrawingCache.recycle();
- }
- mDrawingCache = null;
- mPrivateFlags &= ~DRAWING_CACHE_VALID;
- }
-
- if ((changed & DRAW_MASK) != 0) {
- if ((mViewFlags & WILL_NOT_DRAW) != 0) {
- if (mBGDrawable != null) {
- mPrivateFlags &= ~SKIP_DRAW;
- mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
- } else {
- mPrivateFlags |= SKIP_DRAW;
- }
- } else {
- mPrivateFlags &= ~SKIP_DRAW;
- }
- requestLayout();
- invalidate();
- }
-
- if ((changed & KEEP_SCREEN_ON) != 0) {
- if (mParent != null) {
- mParent.recomputeViewAttributes(this);
- }
- }
- }
-
- /**
- * Change the view's z order in the tree, so it's on top of other sibling
- * views
- */
- public void bringToFront() {
- if (mParent != null) {
- mParent.bringChildToFront(this);
- }
- }
-
- /**
- * This is called in response to an internal scroll in this view (i.e., the
- * view scrolled its own contents). This is typically as a result of
- * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
- * called.
- *
- * @param l Current horizontal scroll origin.
- * @param t Current vertical scroll origin.
- * @param oldl Previous horizontal scroll origin.
- * @param oldt Previous vertical scroll origin.
- */
- protected void onScrollChanged(int l, int t, int oldl, int oldt) {
- mBackgroundSizeChanged = true;
-
- final AttachInfo ai = mAttachInfo;
- if (ai != null) {
- ai.mViewScrollChanged = true;
- }
- }
-
- /**
- * This is called during layout when the size of this view has changed. If
- * you were just added to the view hierarchy, you're called with the old
- * values of 0.
- *
- * @param w Current width of this view.
- * @param h Current height of this view.
- * @param oldw Old width of this view.
- * @param oldh Old height of this view.
- */
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- }
-
- /**
- * Called by draw to draw the child views. This may be overridden
- * by derived classes to gain control just before its children are drawn
- * (but after its own view has been drawn).
- * @param canvas the canvas on which to draw the view
- */
- protected void dispatchDraw(Canvas canvas) {
- }
-
- /**
- * Gets the parent of this view. Note that the parent is a
- * ViewParent and not necessarily a View.
- *
- * @return Parent of this view.
- */
- public final ViewParent getParent() {
- return mParent;
- }
-
- /**
- * Return the scrolled left position of this view. This is the left edge of
- * the displayed part of your view. You do not need to draw any pixels
- * farther left, since those are outside of the frame of your view on
- * screen.
- *
- * @return The left edge of the displayed part of your view, in pixels.
- */
- public final int getScrollX() {
- return mScrollX;
- }
-
- /**
- * Return the scrolled top position of this view. This is the top edge of
- * the displayed part of your view. You do not need to draw any pixels above
- * it, since those are outside of the frame of your view on screen.
- *
- * @return The top edge of the displayed part of your view, in pixels.
- */
- public final int getScrollY() {
- return mScrollY;
- }
-
- /**
- * Return the width of the your view.
- *
- * @return The width of your view, in pixels.
- */
- @ViewDebug.ExportedProperty
- public final int getWidth() {
- return mRight - mLeft;
- }
-
- /**
- * Return the height of your view.
- *
- * @return The height of your view, in pixels.
- */
- @ViewDebug.ExportedProperty
- public final int getHeight() {
- return mBottom - mTop;
- }
-
- /**
- * Return the visible drawing bounds of your view. Fills in the output
- * rectangle with the values from getScrollX(), getScrollY(),
- * getWidth(), and getHeight().
- *
- * @param outRect The (scrolled) drawing bounds of the view.
- */
- public void getDrawingRect(Rect outRect) {
- outRect.left = mScrollX;
- outRect.top = mScrollY;
- outRect.right = mScrollX + (mRight - mLeft);
- outRect.bottom = mScrollY + (mBottom - mTop);
- }
-
- /**
- * The width of this view as measured in the most recent call to measure().
- * This should be used during measurement and layout calculations only. Use
- * {@link #getWidth()} to see how wide a view is after layout.
- *
- * @return The measured width of this view.
- */
- public final int getMeasuredWidth() {
- return mMeasuredWidth;
- }
-
- /**
- * The height of this view as measured in the most recent call to measure().
- * This should be used during measurement and layout calculations only. Use
- * {@link #getHeight()} to see how tall a view is after layout.
- *
- * @return The measured height of this view.
- */
- public final int getMeasuredHeight() {
- return mMeasuredHeight;
- }
-
- /**
- * Top position of this view relative to its parent.
- *
- * @return The top of this view, in pixels.
- */
- @ViewDebug.CapturedViewProperty
- public final int getTop() {
- return mTop;
- }
-
- /**
- * Bottom position of this view relative to its parent.
- *
- * @return The bottom of this view, in pixels.
- */
- @ViewDebug.CapturedViewProperty
- public final int getBottom() {
- return mBottom;
- }
-
- /**
- * Left position of this view relative to its parent.
- *
- * @return The left edge of this view, in pixels.
- */
- @ViewDebug.CapturedViewProperty
- public final int getLeft() {
- return mLeft;
- }
-
- /**
- * Right position of this view relative to its parent.
- *
- * @return The right edge of this view, in pixels.
- */
- @ViewDebug.CapturedViewProperty
- public final int getRight() {
- return mRight;
- }
-
- /**
- * Hit rectangle in parent's coordinates
- *
- * @param outRect The hit rectangle of the view.
- */
- public void getHitRect(Rect outRect) {
- outRect.set(mLeft, mTop, mRight, mBottom);
- }
-
- /**
- * When a view has focus and the user navigates away from it, the next view is searched for
- * starting from the rectangle filled in by this method.
- *
- * By default, the rectange is the {@link #getDrawingRect})of the view. However, if your
- * view maintains some idea of internal selection, such as a cursor, or a selected row
- * or column, you should override this method and fill in a more specific rectangle.
- *
- * @param r The rectangle to fill in, in this view's coordinates.
- */
- public void getFocusedRect(Rect r) {
- getDrawingRect(r);
- }
-
- /**
- * If some part of this view is not clipped by any of its parents, then
- * return that area in r in global (root) coordinates. To convert r to local
- * coordinates, offset it by -globalOffset (e.g. r.offset(-globalOffset.x,
- * -globalOffset.y)) If the view is completely clipped or translated out,
- * return false.
- *
- * @param r If true is returned, r holds the global coordinates of the
- * visible portion of this view.
- * @param globalOffset If true is returned, globalOffset holds the dx,dy
- * between this view and its root. globalOffet may be null.
- * @return true if r is non-empty (i.e. part of the view is visible at the
- * root level.
- */
- public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
- int width = mRight - mLeft;
- int height = mBottom - mTop;
- if (width > 0 && height > 0) {
- r.set(0, 0, width, height);
- if (globalOffset != null) {
- globalOffset.set(-mScrollX, -mScrollY);
- }
- return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
- }
- return false;
- }
-
- public final boolean getGlobalVisibleRect(Rect r) {
- return getGlobalVisibleRect(r, null);
- }
-
- public final boolean getLocalVisibleRect(Rect r) {
- Point offset = new Point();
- if (getGlobalVisibleRect(r, offset)) {
- r.offset(-offset.x, -offset.y); // make r local
- return true;
- }
- return false;
- }
-
- /**
- * Offset this view's vertical location by the specified number of pixels.
- *
- * @param offset the number of pixels to offset the view by
- */
- public void offsetTopAndBottom(int offset) {
- mTop += offset;
- mBottom += offset;
- }
-
- /**
- * Offset this view's horizontal location by the specified amount of pixels.
- *
- * @param offset the numer of pixels to offset the view by
- */
- public void offsetLeftAndRight(int offset) {
- mLeft += offset;
- mRight += offset;
- }
-
- /**
- * Get the LayoutParams associated with this view. All views should have
- * layout parameters. These supply parameters to the <i>parent</i> of this
- * view specifying how it should be arranged. There are many subclasses of
- * ViewGroup.LayoutParams, and these correspond to the different subclasses
- * of ViewGroup that are responsible for arranging their children.
- * @return The LayoutParams associated with this view
- */
- @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
- public ViewGroup.LayoutParams getLayoutParams() {
- return mLayoutParams;
- }
-
- /**
- * Set the layout parameters associated with this view. These supply
- * parameters to the <i>parent</i> of this view specifying how it should be
- * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
- * correspond to the different subclasses of ViewGroup that are responsible
- * for arranging their children.
- *
- * @param params the layout parameters for this view
- */
- public void setLayoutParams(ViewGroup.LayoutParams params) {
- if (params == null) {
- throw new NullPointerException("params == null");
- }
- mLayoutParams = params;
- requestLayout();
- }
-
- /**
- * Set the scrolled position of your view. This will cause a call to
- * {@link #onScrollChanged(int, int, int, int)} and the view will be
- * invalidated.
- * @param x the x position to scroll to
- * @param y the y position to scroll to
- */
- public void scrollTo(int x, int y) {
- if (mScrollX != x || mScrollY != y) {
- int oldX = mScrollX;
- int oldY = mScrollY;
- mScrollX = x;
- mScrollY = y;
- onScrollChanged(mScrollX, mScrollY, oldX, oldY);
- invalidate();
- }
- }
-
- /**
- * Move the scrolled position of your view. This will cause a call to
- * {@link #onScrollChanged(int, int, int, int)} and the view will be
- * invalidated.
- * @param x the amount of pixels to scroll by horizontally
- * @param y the amount of pixels to scroll by vertically
- */
- public void scrollBy(int x, int y) {
- scrollTo(mScrollX + x, mScrollY + y);
- }
-
- /**
- * Mark the the area defined by dirty as needing to be drawn. If the view is
- * visible, {@link #onDraw} will be called at some point in the future.
- * This must be called from a UI thread. To call from a non-UI thread, call
- * {@link #postInvalidate()}.
- *
- * WARNING: This method is destructive to dirty.
- * @param dirty the rectangle representing the bounds of the dirty region
- */
- public void invalidate(Rect dirty) {
- if (ViewDebug.TRACE_HIERARCHY) {
- ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
- }
-
- if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
- mPrivateFlags &= ~DRAWING_CACHE_VALID;
- final ViewParent p = mParent;
- final AttachInfo ai = mAttachInfo;
- if (p != null && ai != null) {
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
- final Rect r = ai.mTmpInvalRect;
- r.set(dirty.left - scrollX, dirty.top - scrollY,
- dirty.right - scrollX, dirty.bottom - scrollY);
- mParent.invalidateChild(this, r);
- }
- }
- }
-
- /**
- * Mark the the area defined by the rect (l,t,r,b) as needing to be drawn.
- * The coordinates of the dirty rect are relative to the view.
- * If the view is visible, {@link #onDraw} will be called at some point
- * in the future. This must be called from a UI thread. To call
- * from a non-UI thread, call {@link #postInvalidate()}.
- * @param l the left position of the dirty region
- * @param t the top position of the dirty region
- * @param r the right position of the dirty region
- * @param b the bottom position of the dirty region
- */
- public void invalidate(int l, int t, int r, int b) {
- if (ViewDebug.TRACE_HIERARCHY) {
- ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
- }
-
- if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
- mPrivateFlags &= ~DRAWING_CACHE_VALID;
- final ViewParent p = mParent;
- final AttachInfo ai = mAttachInfo;
- if (p != null && ai != null && l < r && t < b) {
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
- final Rect tmpr = ai.mTmpInvalRect;
- tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
- p.invalidateChild(this, tmpr);
- }
- }
- }
-
- /**
- * Invalidate the whole view. If the view is visible, {@link #onDraw} will
- * be called at some point in the future. This must be called from a
- * UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
- */
- public void invalidate() {
- if (ViewDebug.TRACE_HIERARCHY) {
- ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
- }
-
- if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
- mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID;
- final ViewParent p = mParent;
- final AttachInfo ai = mAttachInfo;
- if (p != null && ai != null) {
- final Rect r = ai.mTmpInvalRect;
- r.set(0, 0, mRight - mLeft, mBottom - mTop);
- // Don't call invalidate -- we don't want to internally scroll
- // our own bounds
- p.invalidateChild(this, r);
- }
- }
- }
-
- /**
- * @return A handler associated with the thread running the View. This
- * handler can be used to pump events in the UI events queue.
- */
- public Handler getHandler() {
- if (mAttachInfo != null) {
- return mAttachInfo.mHandler;
- }
- return null;
- }
-
- /**
- * Causes the Runnable to be added to the message queue.
- * The runnable will be run on the user interface thread.
- *
- * @param action The Runnable that will be executed.
- *
- * @return Returns true if the Runnable was successfully placed in to the
- * message queue. Returns false on failure, usually because the
- * looper processing the message queue is exiting.
- */
- public boolean post(Runnable action) {
- Handler handler;
- if (mAttachInfo != null) {
- handler = mAttachInfo.mHandler;
- } else {
- // Assume that post will succeed later
- ViewRoot.getRunQueue().post(action);
- return true;
- }
-
- return handler.post(action);
- }
-
- /**
- * Causes the Runnable to be added to the message queue, to be run
- * after the specified amount of time elapses.
- * The runnable will be run on the user interface thread.
- *
- * @param action The Runnable that will be executed.
- * @param delayMillis The delay (in milliseconds) until the Runnable
- * will be executed.
- *
- * @return true if the Runnable was successfully placed in to the
- * message queue. Returns false on failure, usually because the
- * looper processing the message queue is exiting. Note that a
- * result of true does not mean the Runnable will be processed --
- * if the looper is quit before the delivery time of the message
- * occurs then the message will be dropped.
- */
- public boolean postDelayed(Runnable action, long delayMillis) {
- Handler handler;
- if (mAttachInfo != null) {
- handler = mAttachInfo.mHandler;
- } else {
- // Assume that post will succeed later
- ViewRoot.getRunQueue().postDelayed(action, delayMillis);
- return true;
- }
-
- return handler.postDelayed(action, delayMillis);
- }
-
- /**
- * Removes the specified Runnable from the message queue.
- *
- * @param action The Runnable to remove from the message handling queue
- *
- * @return true if this view could ask the Handler to remove the Runnable,
- * false otherwise. When the returned value is true, the Runnable
- * may or may not have been actually removed from the message queue
- * (for instance, if the Runnable was not in the queue already.)
- */
- public boolean removeCallbacks(Runnable action) {
- Handler handler;
- if (mAttachInfo != null) {
- handler = mAttachInfo.mHandler;
- } else {
- // Assume that post will succeed later
- ViewRoot.getRunQueue().removeCallbacks(action);
- return true;
- }
-
- handler.removeCallbacks(action);
- return true;
- }
-
- /**
- * Cause an invalidate to happen on a subsequent cycle through the event loop.
- * Use this to invalidate the View from a non-UI thread.
- *
- * @see #invalidate()
- */
- public void postInvalidate() {
- postInvalidateDelayed(0);
- }
-
- /**
- * Cause an invalidate of the specified area to happen on a subsequent cycle
- * through the event loop. Use this to invalidate the View from a non-UI thread.
- *
- * @param left The left coordinate of the rectangle to invalidate.
- * @param top The top coordinate of the rectangle to invalidate.
- * @param right The right coordinate of the rectangle to invalidate.
- * @param bottom The bottom coordinate of the rectangle to invalidate.
- *
- * @see #invalidate(int, int, int, int)
- * @see #invalidate(Rect)
- */
- public void postInvalidate(int left, int top, int right, int bottom) {
- postInvalidateDelayed(0, left, top, right, bottom);
- }
-
- /**
- * Cause an invalidate to happen on a subsequent cycle through the event
- * loop. Waits for the specified amount of time.
- *
- * @param delayMilliseconds the duration in milliseconds to delay the
- * invalidation by
- */
- public void postInvalidateDelayed(long delayMilliseconds) {
- // We try only with the AttachInfo because there's no point in invalidating
- // if we are not attached to our window
- if (mAttachInfo != null) {
- Message msg = Message.obtain();
- msg.what = AttachInfo.INVALIDATE_MSG;
- msg.obj = this;
- mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
- }
- }
-
- /**
- * Cause an invalidate of the specified area to happen on a subsequent cycle
- * through the event loop. Waits for the specified amount of time.
- *
- * @param delayMilliseconds the duration in milliseconds to delay the
- * invalidation by
- * @param left The left coordinate of the rectangle to invalidate.
- * @param top The top coordinate of the rectangle to invalidate.
- * @param right The right coordinate of the rectangle to invalidate.
- * @param bottom The bottom coordinate of the rectangle to invalidate.
- */
- public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
- int right, int bottom) {
-
- // We try only with the AttachInfo because there's no point in invalidating
- // if we are not attached to our window
- if (mAttachInfo != null) {
- final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
- info.target = this;
- info.left = left;
- info.top = top;
- info.right = right;
- info.bottom = bottom;
-
- final Message msg = Message.obtain();
- msg.what = AttachInfo.INVALIDATE_RECT_MSG;
- msg.obj = info;
- mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
- }
- }
-
- /**
- * Called by a parent to request that a child update its values for mScrollX
- * and mScrollY if necessary. This will typically be done if the child is
- * animating a scroll using a {@link android.widget.Scroller Scroller}
- * object.
- */
- public void computeScroll() {
- }
-
- /**
- * <p>Indicate whether the horizontal edges are faded when the view is
- * scrolled horizontally.</p>
- *
- * @return true if the horizontal edges should are faded on scroll, false
- * otherwise
- *
- * @see #setHorizontalFadingEdgeEnabled(boolean)
- * @attr ref android.R.styleable#View_fadingEdge
- */
- public boolean isHorizontalFadingEdgeEnabled() {
- return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
- }
-
- /**
- * <p>Define whether the horizontal edges should be faded when this view
- * is scrolled horizontally.</p>
- *
- * @param horizontalFadingEdgeEnabled true if the horizontal edges should
- * be faded when the view is scrolled
- * horizontally
- *
- * @see #isHorizontalFadingEdgeEnabled()
- * @attr ref android.R.styleable#View_fadingEdge
- */
- public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
- if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
- if (horizontalFadingEdgeEnabled) {
- initScrollCache();
- }
-
- mViewFlags ^= FADING_EDGE_HORIZONTAL;
- }
- }
-
- /**
- * <p>Indicate whether the vertical edges are faded when the view is
- * scrolled horizontally.</p>
- *
- * @return true if the vertical edges should are faded on scroll, false
- * otherwise
- *
- * @see #setVerticalFadingEdgeEnabled(boolean)
- * @attr ref android.R.styleable#View_fadingEdge
- */
- public boolean isVerticalFadingEdgeEnabled() {
- return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
- }
-
- /**
- * <p>Define whether the vertical edges should be faded when this view
- * is scrolled vertically.</p>
- *
- * @param verticalFadingEdgeEnabled true if the vertical edges should
- * be faded when the view is scrolled
- * vertically
- *
- * @see #isVerticalFadingEdgeEnabled()
- * @attr ref android.R.styleable#View_fadingEdge
- */
- public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
- if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
- if (verticalFadingEdgeEnabled) {
- initScrollCache();
- }
-
- mViewFlags ^= FADING_EDGE_VERTICAL;
- }
- }
-
- /**
- * Returns the strength, or intensity, of the top faded edge. The strength is
- * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
- * returns 0.0 or 1.0 but no value in between.
- *
- * Subclasses should override this method to provide a smoother fade transition
- * when scrolling occurs.
- *
- * @return the intensity of the top fade as a float between 0.0f and 1.0f
- */
- protected float getTopFadingEdgeStrength() {
- return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
- }
-
- /**
- * Returns the strength, or intensity, of the bottom faded edge. The strength is
- * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
- * returns 0.0 or 1.0 but no value in between.
- *
- * Subclasses should override this method to provide a smoother fade transition
- * when scrolling occurs.
- *
- * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
- */
- protected float getBottomFadingEdgeStrength() {
- return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
- computeVerticalScrollRange() ? 1.0f : 0.0f;
- }
-
- /**
- * Returns the strength, or intensity, of the left faded edge. The strength is
- * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
- * returns 0.0 or 1.0 but no value in between.
- *
- * Subclasses should override this method to provide a smoother fade transition
- * when scrolling occurs.
- *
- * @return the intensity of the left fade as a float between 0.0f and 1.0f
- */
- protected float getLeftFadingEdgeStrength() {
- return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
- }
-
- /**
- * Returns the strength, or intensity, of the right faded edge. The strength is
- * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
- * returns 0.0 or 1.0 but no value in between.
- *
- * Subclasses should override this method to provide a smoother fade transition
- * when scrolling occurs.
- *
- * @return the intensity of the right fade as a float between 0.0f and 1.0f
- */
- protected float getRightFadingEdgeStrength() {
- return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
- computeHorizontalScrollRange() ? 1.0f : 0.0f;
- }
-
- /**
- * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
- * scrollbar is not drawn by default.</p>
- *
- * @return true if the horizontal scrollbar should be painted, false
- * otherwise
- *
- * @see #setHorizontalScrollBarEnabled(boolean)
- */
- public boolean isHorizontalScrollBarEnabled() {
- return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
- }
-
- /**
- * <p>Define whether the horizontal scrollbar should be drawn or not. The
- * scrollbar is not drawn by default.</p>
- *
- * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
- * be painted
- *
- * @see #isHorizontalScrollBarEnabled()
- */
- public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
- if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
- mViewFlags ^= SCROLLBARS_HORIZONTAL;
- recomputePadding();
- }
- }
-
- /**
- * <p>Indicate whether the vertical scrollbar should be drawn or not. The
- * scrollbar is not drawn by default.</p>
- *
- * @return true if the vertical scrollbar should be painted, false
- * otherwise
- *
- * @see #setVerticalScrollBarEnabled(boolean)
- */
- public boolean isVerticalScrollBarEnabled() {
- return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
- }
-
- /**
- * <p>Define whether the vertical scrollbar should be drawn or not. The
- * scrollbar is not drawn by default.</p>
- *
- * @param verticalScrollBarEnabled true if the vertical scrollbar should
- * be painted
- *
- * @see #isVerticalScrollBarEnabled()
- */
- public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
- if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
- mViewFlags ^= SCROLLBARS_VERTICAL;
- recomputePadding();
- }
- }
-
- private void recomputePadding() {
- setPadding(mPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
- }
-
- /**
- * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
- * inset. When inset, they add to the padding of the view. And the scrollbars
- * can be drawn inside the padding area or on the edge of the view. For example,
- * if a view has a background drawable and you want to draw the scrollbars
- * inside the padding specified by the drawable, you can use
- * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
- * appear at the edge of the view, ignoring the padding, then you can use
- * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
- * @param style the style of the scrollbars. Should be one of
- * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
- * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
- * @see #SCROLLBARS_INSIDE_OVERLAY
- * @see #SCROLLBARS_INSIDE_INSET
- * @see #SCROLLBARS_OUTSIDE_OVERLAY
- * @see #SCROLLBARS_OUTSIDE_INSET
- */
- public void setScrollBarStyle(int style) {
- if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
- mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
- recomputePadding();
- }
- }
-
- /**
- * <p>Returns the current scrollbar style.</p>
- * @return the current scrollbar style
- * @see #SCROLLBARS_INSIDE_OVERLAY
- * @see #SCROLLBARS_INSIDE_INSET
- * @see #SCROLLBARS_OUTSIDE_OVERLAY
- * @see #SCROLLBARS_OUTSIDE_INSET
- */
- public int getScrollBarStyle() {
- return mViewFlags & SCROLLBARS_STYLE_MASK;
- }
-
- /**
- * <p>Compute the horizontal range that the horizontal scrollbar
- * represents.</p>
- *
- * <p>The range is expressed in arbitrary units that must be the same as the
- * units used by {@link #computeHorizontalScrollExtent()} and
- * {@link #computeHorizontalScrollOffset()}.</p>
- *
- * <p>The default range is the drawing width of this view.</p>
- *
- * @return the total horizontal range represented by the horizontal
- * scrollbar
- *
- * @see #computeHorizontalScrollExtent()
- * @see #computeHorizontalScrollOffset()
- * @see android.widget.ScrollBarDrawable
- */
- protected int computeHorizontalScrollRange() {
- return getWidth();
- }
-
- /**
- * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
- * within the horizontal range. This value is used to compute the position
- * of the thumb within the scrollbar's track.</p>
- *
- * <p>The range is expressed in arbitrary units that must be the same as the
- * units used by {@link #computeHorizontalScrollRange()} and
- * {@link #computeHorizontalScrollExtent()}.</p>
- *
- * <p>The default offset is the scroll offset of this view.</p>
- *
- * @return the horizontal offset of the scrollbar's thumb
- *
- * @see #computeHorizontalScrollRange()
- * @see #computeHorizontalScrollExtent()
- * @see android.widget.ScrollBarDrawable
- */
- protected int computeHorizontalScrollOffset() {
- return mScrollX;
- }
-
- /**
- * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
- * within the horizontal range. This value is used to compute the length
- * of the thumb within the scrollbar's track.</p>
- *
- * <p>The range is expressed in arbitrary units that must be the same as the
- * units used by {@link #computeHorizontalScrollRange()} and
- * {@link #computeHorizontalScrollOffset()}.</p>
- *
- * <p>The default extent is the drawing width of this view.</p>
- *
- * @return the horizontal extent of the scrollbar's thumb
- *
- * @see #computeHorizontalScrollRange()
- * @see #computeHorizontalScrollOffset()
- * @see android.widget.ScrollBarDrawable
- */
- protected int computeHorizontalScrollExtent() {
- return getWidth();
- }
-
- /**
- * <p>Compute the vertical range that the vertical scrollbar represents.</p>
- *
- * <p>The range is expressed in arbitrary units that must be the same as the
- * units used by {@link #computeVerticalScrollExtent()} and
- * {@link #computeVerticalScrollOffset()}.</p>
- *
- * @return the total vertical range represented by the vertical scrollbar
- *
- * <p>The default range is the drawing height of this view.</p>
- *
- * @see #computeVerticalScrollExtent()
- * @see #computeVerticalScrollOffset()
- * @see android.widget.ScrollBarDrawable
- */
- protected int computeVerticalScrollRange() {
- return getHeight();
- }
-
- /**
- * <p>Compute the vertical offset of the vertical scrollbar's thumb
- * within the horizontal range. This value is used to compute the position
- * of the thumb within the scrollbar's track.</p>
- *
- * <p>The range is expressed in arbitrary units that must be the same as the
- * units used by {@link #computeVerticalScrollRange()} and
- * {@link #computeVerticalScrollExtent()}.</p>
- *
- * <p>The default offset is the scroll offset of this view.</p>
- *
- * @return the vertical offset of the scrollbar's thumb
- *
- * @see #computeVerticalScrollRange()
- * @see #computeVerticalScrollExtent()
- * @see android.widget.ScrollBarDrawable
- */
- protected int computeVerticalScrollOffset() {
- return mScrollY;
- }
-
- /**
- * <p>Compute the vertical extent of the horizontal scrollbar's thumb
- * within the vertical range. This value is used to compute the length
- * of the thumb within the scrollbar's track.</p>
- *
- * <p>The range is expressed in arbitrary units that must be the same as the
- * units used by {@link #computeHorizontalScrollRange()} and
- * {@link #computeVerticalScrollOffset()}.</p>
- *
- * <p>The default extent is the drawing height of this view.</p>
- *
- * @return the vertical extent of the scrollbar's thumb
- *
- * @see #computeVerticalScrollRange()
- * @see #computeVerticalScrollOffset()
- * @see android.widget.ScrollBarDrawable
- */
- protected int computeVerticalScrollExtent() {
- return getHeight();
- }
-
- /**
- * <p>Request the drawing of the horizontal and the vertical scrollbar. The
- * scrollbars are painted only if they have been awakened first.</p>
- *
- * @param canvas the canvas on which to draw the scrollbars
- */
- private void onDrawScrollBars(Canvas canvas) {
- // scrollbars are drawn only when the animation is running
- final ScrollabilityCache cache = mScrollCache;
- if (cache != null) {
- final int viewFlags = mViewFlags;
-
- final boolean drawHorizontalScrollBar =
- (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
- final boolean drawVerticalScrollBar =
- (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
- && !isVerticalScrollBarHidden();
-
- if (drawVerticalScrollBar || drawHorizontalScrollBar) {
- final int width = mRight - mLeft;
- final int height = mBottom - mTop;
-
- final ScrollBarDrawable scrollBar = cache.scrollBar;
- int size = scrollBar.getSize(false);
- if (size <= 0) {
- size = cache.scrollBarSize;
- }
-
- if (drawHorizontalScrollBar) {
- onDrawHorizontalScrollBar(canvas, scrollBar, width, height, size);
- }
-
- if (drawVerticalScrollBar) {
- onDrawVerticalScrollBar(canvas, scrollBar, width, height, size);
- }
- }
- }
- }
-
- /**
- * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
- * FastScroller is visible.
- * @return whether to temporarily hide the vertical scrollbar
- * @hide
- */
- protected boolean isVerticalScrollBarHidden() {
- return false;
- }
-
- /**
- * <p>Draw the horizontal scrollbar if
- * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
- *
- * <p>The length of the scrollbar and its thumb is computed according to the
- * values returned by {@link #computeHorizontalScrollRange()},
- * {@link #computeHorizontalScrollExtent()} and
- * {@link #computeHorizontalScrollOffset()}. Refer to
- * {@link android.widget.ScrollBarDrawable} for more information about how
- * these values relate to each other.</p>
- *
- * @param canvas the canvas on which to draw the scrollbar
- * @param scrollBar the scrollbar's drawable
- * @param width the width of the drawing surface
- * @param height the height of the drawing surface
- * @param size the size of the scrollbar
- *
- * @see #isHorizontalScrollBarEnabled()
- * @see #computeHorizontalScrollRange()
- * @see #computeHorizontalScrollExtent()
- * @see #computeHorizontalScrollOffset()
- * @see android.widget.ScrollBarDrawable
- */
- private void onDrawHorizontalScrollBar(Canvas canvas, ScrollBarDrawable scrollBar, int width,
- int height, int size) {
-
- final int viewFlags = mViewFlags;
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
- final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
- final int top = scrollY + height - size - (mUserPaddingBottom & inside);
-
- final int verticalScrollBarGap =
- (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL ?
- getVerticalScrollbarWidth() : 0;
-
- scrollBar.setBounds(scrollX + (mPaddingLeft & inside) + getScrollBarPaddingLeft(), top,
- scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap, top + size);
- scrollBar.setParameters(
- computeHorizontalScrollRange(),
- computeHorizontalScrollOffset(),
- computeHorizontalScrollExtent(), false);
- scrollBar.draw(canvas);
- }
-
- /**
- * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
- * returns true.</p>
- *
- * <p>The length of the scrollbar and its thumb is computed according to the
- * values returned by {@link #computeVerticalScrollRange()},
- * {@link #computeVerticalScrollExtent()} and
- * {@link #computeVerticalScrollOffset()}. Refer to
- * {@link android.widget.ScrollBarDrawable} for more information about how
- * these values relate to each other.</p>
- *
- * @param canvas the canvas on which to draw the scrollbar
- * @param scrollBar the scrollbar's drawable
- * @param width the width of the drawing surface
- * @param height the height of the drawing surface
- * @param size the size of the scrollbar
- *
- * @see #isVerticalScrollBarEnabled()
- * @see #computeVerticalScrollRange()
- * @see #computeVerticalScrollExtent()
- * @see #computeVerticalScrollOffset()
- * @see android.widget.ScrollBarDrawable
- */
- private void onDrawVerticalScrollBar(Canvas canvas, ScrollBarDrawable scrollBar, int width,
- int height, int size) {
-
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
- final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
- // TODO: Deal with RTL languages to position scrollbar on left
- final int left = scrollX + width - size - (mUserPaddingRight & inside);
-
- scrollBar.setBounds(left, scrollY + (mPaddingTop & inside),
- left + size, scrollY + height - (mUserPaddingBottom & inside));
- scrollBar.setParameters(
- computeVerticalScrollRange(),
- computeVerticalScrollOffset(),
- computeVerticalScrollExtent(), true);
- scrollBar.draw(canvas);
- }
-
- /**
- * Implement this to do your drawing.
- *
- * @param canvas the canvas on which the background will be drawn
- */
- protected void onDraw(Canvas canvas) {
- }
-
- /*
- * Caller is responsible for calling requestLayout if necessary.
- * (This allows addViewInLayout to not request a new layout.)
- */
- void assignParent(ViewParent parent) {
- if (mParent == null) {
- mParent = parent;
- } else if (parent == null) {
- mParent = null;
- } else {
- throw new RuntimeException("view " + this + " being added, but"
- + " it already has a parent");
- }
- }
-
- /**
- * This is called when the view is attached to a window. At this point it
- * has a Surface and will start drawing. Note that this function is
- * guaranteed to be called before {@link #onDraw}, however it may be called
- * any time before the first onDraw -- including before or after
- * {@link #onMeasure}.
- *
- * @see #onDetachedFromWindow()
- */
- protected void onAttachedToWindow() {
- if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
- mParent.requestTransparentRegion(this);
- }
- }
-
- /**
- * This is called when the view is detached from a window. At this point it
- * no longer has a surface for drawing.
- *
- * @see #onAttachedToWindow()
- */
- protected void onDetachedFromWindow() {
- if (mPendingCheckForLongPress != null) {
- removeCallbacks(mPendingCheckForLongPress);
- }
- destroyDrawingCache();
- }
-
- /**
- * @return The number of times this view has been attached to a window
- */
- protected int getWindowAttachCount() {
- return mWindowAttachCount;
- }
-
- /**
- * Retrieve a unique token identifying the window this view is attached to.
- * @return Return the window's token for use in
- * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
- */
- public IBinder getWindowToken() {
- return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
- }
-
- /**
- * Retrieve a unique token identifying the top-level "real" window of
- * the window that this view is attached to. That is, this is like
- * {@link #getWindowToken}, except if the window this view in is a panel
- * window (attached to another containing window), then the token of
- * the containing window is returned instead.
- *
- * @return Returns the associated window token, either
- * {@link #getWindowToken()} or the containing window's token.
- */
- public IBinder getApplicationWindowToken() {
- AttachInfo ai = mAttachInfo;
- if (ai != null) {
- IBinder appWindowToken = ai.mPanelParentWindowToken;
- if (appWindowToken == null) {
- appWindowToken = ai.mWindowToken;
- }
- return appWindowToken;
- }
- return null;
- }
-
- /**
- * Retrieve private session object this view hierarchy is using to
- * communicate with the window manager.
- * @return the session object to communicate with the window manager
- */
- /*package*/ IWindowSession getWindowSession() {
- return mAttachInfo != null ? mAttachInfo.mSession : null;
- }
-
- /**
- * @param info the {@link android.view.View.AttachInfo} to associated with
- * this view
- */
- void dispatchAttachedToWindow(AttachInfo info, int visibility) {
- //System.out.println("Attached! " + this);
- mAttachInfo = info;
- mWindowAttachCount++;
- if (mFloatingTreeObserver != null) {
- info.mTreeObserver.merge(mFloatingTreeObserver);
- mFloatingTreeObserver = null;
- }
- if ((mPrivateFlags&SCROLL_CONTAINER) != 0) {
- mAttachInfo.mScrollContainers.add(this);
- mPrivateFlags |= SCROLL_CONTAINER_ADDED;
- }
- performCollectViewAttributes(visibility);
- onAttachedToWindow();
- int vis = info.mWindowVisibility;
- if (vis != GONE) {
- onWindowVisibilityChanged(vis);
- }
- }
-
- void dispatchDetachedFromWindow() {
- //System.out.println("Detached! " + this);
- AttachInfo info = mAttachInfo;
- if (info != null) {
- int vis = info.mWindowVisibility;
- if (vis != GONE) {
- onWindowVisibilityChanged(GONE);
- }
- }
-
- onDetachedFromWindow();
- if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
- mAttachInfo.mScrollContainers.remove(this);
- mPrivateFlags &= ~SCROLL_CONTAINER_ADDED;
- }
- mAttachInfo = null;
- }
-
- /**
- * Store this view hierarchy's frozen state into the given container.
- *
- * @param container The SparseArray in which to save the view's state.
- *
- * @see #restoreHierarchyState
- * @see #dispatchSaveInstanceState
- * @see #onSaveInstanceState
- */
- public void saveHierarchyState(SparseArray<Parcelable> container) {
- dispatchSaveInstanceState(container);
- }
-
- /**
- * Called by {@link #saveHierarchyState} to store the state for this view and its children.
- * May be overridden to modify how freezing happens to a view's children; for example, some
- * views may want to not store state for their children.
- *
- * @param container The SparseArray in which to save the view's state.
- *
- * @see #dispatchRestoreInstanceState
- * @see #saveHierarchyState
- * @see #onSaveInstanceState
- */
- protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
- if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
- mPrivateFlags &= ~SAVE_STATE_CALLED;
- Parcelable state = onSaveInstanceState();
- if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
- throw new IllegalStateException(
- "Derived class did not call super.onSaveInstanceState()");
- }
- if (state != null) {
- // Log.i("View", "Freezing #" + Integer.toHexString(mID)
- // + ": " + state);
- container.put(mID, state);
- }
- }
- }
-
- /**
- * Hook allowing a view to generate a representation of its internal state
- * that can later be used to create a new instance with that same state.
- * This state should only contain information that is not persistent or can
- * not be reconstructed later. For example, you will never store your
- * current position on screen because that will be computed again when a
- * new instance of the view is placed in its view hierarchy.
- * <p>
- * Some examples of things you may store here: the current cursor position
- * in a text view (but usually not the text itself since that is stored in a
- * content provider or other persistent storage), the currently selected
- * item in a list view.
- *
- * @return Returns a Parcelable object containing the view's current dynamic
- * state, or null if there is nothing interesting to save. The
- * default implementation returns null.
- * @see #onRestoreInstanceState
- * @see #saveHierarchyState
- * @see #dispatchSaveInstanceState
- * @see #setSaveEnabled(boolean)
- */
- protected Parcelable onSaveInstanceState() {
- mPrivateFlags |= SAVE_STATE_CALLED;
- return BaseSavedState.EMPTY_STATE;
- }
-
- /**
- * Restore this view hierarchy's frozen state from the given container.
- *
- * @param container The SparseArray which holds previously frozen states.
- *
- * @see #saveHierarchyState
- * @see #dispatchRestoreInstanceState
- * @see #onRestoreInstanceState
- */
- public void restoreHierarchyState(SparseArray<Parcelable> container) {
- dispatchRestoreInstanceState(container);
- }
-
- /**
- * Called by {@link #restoreHierarchyState} to retrieve the state for this view and its
- * children. May be overridden to modify how restoreing happens to a view's children; for
- * example, some views may want to not store state for their children.
- *
- * @param container The SparseArray which holds previously saved state.
- *
- * @see #dispatchSaveInstanceState
- * @see #restoreHierarchyState
- * @see #onRestoreInstanceState
- */
- protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
- if (mID != NO_ID) {
- Parcelable state = container.get(mID);
- if (state != null) {
- // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
- // + ": " + state);
- mPrivateFlags &= ~SAVE_STATE_CALLED;
- onRestoreInstanceState(state);
- if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
- throw new IllegalStateException(
- "Derived class did not call super.onRestoreInstanceState()");
- }
- }
- }
- }
-
- /**
- * Hook allowing a view to re-apply a representation of its internal state that had previously
- * been generated by {@link #onSaveInstanceState}. This function will never be called with a
- * null state.
- *
- * @param state The frozen state that had previously been returned by
- * {@link #onSaveInstanceState}.
- *
- * @see #onSaveInstanceState
- * @see #restoreHierarchyState
- * @see #dispatchRestoreInstanceState
- */
- protected void onRestoreInstanceState(Parcelable state) {
- mPrivateFlags |= SAVE_STATE_CALLED;
- if (state != BaseSavedState.EMPTY_STATE && state != null) {
- throw new IllegalArgumentException("Wrong state class -- expecting View State");
- }
- }
-
- /**
- * <p>Return the time at which the drawing of the view hierarchy started.</p>
- *
- * @return the drawing start time in milliseconds
- */
- public long getDrawingTime() {
- return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
- }
-
- /**
- * <p>Enables or disables the duplication of the parent's state into this view. When
- * duplication is enabled, this view gets its drawable state from its parent rather
- * than from its own internal properties.</p>
- *
- * <p>Note: in the current implementation, setting this property to true after the
- * view was added to a ViewGroup might have no effect at all. This property should
- * always be used from XML or set to true before adding this view to a ViewGroup.</p>
- *
- * <p>Note: if this view's parent addStateFromChildren property is enabled and this
- * property is enabled, an exception will be thrown.</p>
- *
- * @param enabled True to enable duplication of the parent's drawable state, false
- * to disable it.
- *
- * @see #getDrawableState()
- * @see #isDuplicateParentStateEnabled()
- */
- public void setDuplicateParentStateEnabled(boolean enabled) {
- setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
- }
-
- /**
- * <p>Indicates whether this duplicates its drawable state from its parent.</p>
- *
- * @return True if this view's drawable state is duplicated from the parent,
- * false otherwise
- *
- * @see #getDrawableState()
- * @see #setDuplicateParentStateEnabled(boolean)
- */
- public boolean isDuplicateParentStateEnabled() {
- return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
- }
-
- /**
- * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
- * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
- * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
- * the cache is enabled. To benefit from the cache, you must request the drawing cache by
- * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
- * null.</p>
- *
- * @param enabled true to enable the drawing cache, false otherwise
- *
- * @see #isDrawingCacheEnabled()
- * @see #getDrawingCache()
- * @see #buildDrawingCache()
- */
- public void setDrawingCacheEnabled(boolean enabled) {
- setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
- }
-
- /**
- * <p>Indicates whether the drawing cache is enabled for this view.</p>
- *
- * @return true if the drawing cache is enabled
- *
- * @see #setDrawingCacheEnabled(boolean)
- * @see #getDrawingCache()
- */
- @ViewDebug.ExportedProperty
- public boolean isDrawingCacheEnabled() {
- return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
- }
-
- /**
- * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
- * is null when caching is disabled. If caching is enabled and the cache is not ready,
- * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
- * draw from the cache when the cache is enabled. To benefit from the cache, you must
- * request the drawing cache by calling this method and draw it on screen if the
- * returned bitmap is not null.</p>
- *
- * @return a bitmap representing this view or null if cache is disabled
- *
- * @see #setDrawingCacheEnabled(boolean)
- * @see #isDrawingCacheEnabled()
- * @see #buildDrawingCache()
- * @see #destroyDrawingCache()
- */
- public Bitmap getDrawingCache() {
- if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
- return null;
- }
- if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED &&
- ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mDrawingCache == null)) {
- buildDrawingCache();
- }
- return mDrawingCache;
- }
-
- /**
- * <p>Frees the resources used by the drawing cache. If you call
- * {@link #buildDrawingCache()} manually without calling
- * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
- * should cleanup the cache with this method afterwards.</p>
- *
- * @see #setDrawingCacheEnabled(boolean)
- * @see #buildDrawingCache()
- * @see #getDrawingCache()
- */
- public void destroyDrawingCache() {
- if (mDrawingCache != null) {
- mDrawingCache.recycle();
- mDrawingCache = null;
- }
- }
-
- /**
- * Setting a solid background color for the drawing cache's bitmaps will improve
- * perfromance and memory usage. Note, though that this should only be used if this
- * view will always be drawn on top of a solid color.
- *
- * @param color The background color to use for the drawing cache's bitmap
- *
- * @see #setDrawingCacheEnabled(boolean)
- * @see #buildDrawingCache()
- * @see #getDrawingCache()
- */
- public void setDrawingCacheBackgroundColor(int color) {
- mDrawingCacheBackgroundColor = color;
- }
-
- /**
- * @see #setDrawingCacheBackgroundColor(int)
- *
- * @return The background color to used for the drawing cache's bitmap
- */
- public int getDrawingCacheBackgroundColor() {
- return mDrawingCacheBackgroundColor;
- }
-
- /**
- * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
- *
- * <p>If you call {@link #buildDrawingCache()} manually without calling
- * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
- * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
- *
- * @see #getDrawingCache()
- * @see #destroyDrawingCache()
- */
- public void buildDrawingCache() {
- if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mDrawingCache == null) {
- if (ViewDebug.TRACE_HIERARCHY) {
- ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE);
- }
- if (ViewRoot.PROFILE_DRAWING) {
- EventLog.writeEvent(60002, hashCode());
- }
-
- final int width = mRight - mLeft;
- final int height = mBottom - mTop;
-
- final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
- final boolean opaque = drawingCacheBackgroundColor != 0 ||
- (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE);
-
- if (width <= 0 || height <= 0 ||
- (width * height * (opaque ? 2 : 4) >= // Projected bitmap size in bytes
- ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
- if (mDrawingCache != null) {
- mDrawingCache.recycle();
- }
- mDrawingCache = null;
- return;
- }
-
- boolean clear = true;
- Bitmap bitmap = mDrawingCache;
-
- if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
-
- Bitmap.Config quality;
- if (!opaque) {
- switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
- case DRAWING_CACHE_QUALITY_AUTO:
- quality = Bitmap.Config.ARGB_8888;
- break;
- case DRAWING_CACHE_QUALITY_LOW:
- quality = Bitmap.Config.ARGB_4444;
- break;
- case DRAWING_CACHE_QUALITY_HIGH:
- quality = Bitmap.Config.ARGB_8888;
- break;
- default:
- quality = Bitmap.Config.ARGB_8888;
- break;
- }
- } else {
- quality = Bitmap.Config.RGB_565;
- }
-
- // Try to cleanup memory
- if (mDrawingCache != null) {
- mDrawingCache.recycle();
- }
-
- try {
- mDrawingCache = bitmap = Bitmap.createBitmap(width, height, quality);
- } catch (OutOfMemoryError e) {
- // If there is not enough memory to create the bitmap cache, just
- // ignore the issue as bitmap caches are not required to draw the
- // view hierarchy
- mDrawingCache = null;
- return;
- }
-
- clear = drawingCacheBackgroundColor != 0;
- }
-
- Canvas canvas;
- final AttachInfo attachInfo = mAttachInfo;
- if (attachInfo != null) {
- canvas = attachInfo.mCanvas;
- if (canvas == null) {
- canvas = new Canvas();
- }
- canvas.setBitmap(bitmap);
- // Temporarily clobber the cached Canvas in case one of our children
- // is also using a drawing cache. Without this, the children would
- // steal the canvas by attaching their own bitmap to it and bad, bad
- // thing would happen (invisible views, corrupted drawings, etc.)
- attachInfo.mCanvas = null;
- } else {
- // This case should hopefully never or seldom happen
- canvas = new Canvas(bitmap);
- }
-
- if (clear) {
- bitmap.eraseColor(drawingCacheBackgroundColor);
- }
-
- computeScroll();
- final int restoreCount = canvas.save();
- canvas.translate(-mScrollX, -mScrollY);
-
- mPrivateFlags |= DRAWN;
-
- // Fast path for layouts with no backgrounds
- if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
- if (ViewDebug.TRACE_HIERARCHY) {
- ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
- }
- dispatchDraw(canvas);
- } else {
- draw(canvas);
- }
-
- canvas.restoreToCount(restoreCount);
-
- if (attachInfo != null) {
- // Restore the cached Canvas for our siblings
- attachInfo.mCanvas = canvas;
- }
- mPrivateFlags |= DRAWING_CACHE_VALID;
- }
- }
-
- /**
- * Indicates whether this View is currently in edit mode. A View is usually
- * in edit mode when displayed within a developer tool. For instance, if
- * this View is being drawn by a visual user interface builder, this method
- * should return true.
- *
- * Subclasses should check the return value of this method to provide
- * different behaviors if their normal behavior might interfere with the
- * host environment. For instance: the class spawns a thread in its
- * constructor, the drawing code relies on device-specific features, etc.
- *
- * This method is usually checked in the drawing code of custom widgets.
- *
- * @return True if this View is in edit mode, false otherwise.
- */
- public boolean isInEditMode() {
- return false;
- }
-
- /**
- * If the View draws content inside its padding and enables fading edges,
- * it needs to support padding offsets. Padding offsets are added to the
- * fading edges to extend the length of the fade so that it covers pixels
- * drawn inside the padding.
- *
- * Subclasses of this class should override this method if they need
- * to draw content inside the padding.
- *
- * @return True if padding offset must be applied, false otherwise.
- *
- * @see #getLeftPaddingOffset()
- * @see #getRightPaddingOffset()
- * @see #getTopPaddingOffset()
- * @see #getBottomPaddingOffset()
- *
- * @since CURRENT
- */
- protected boolean isPaddingOffsetRequired() {
- return false;
- }
-
- /**
- * Amount by which to extend the left fading region. Called only when
- * {@link #isPaddingOffsetRequired()} returns true.
- *
- * @return The left padding offset in pixels.
- *
- * @see #isPaddingOffsetRequired()
- *
- * @since CURRENT
- */
- protected int getLeftPaddingOffset() {
- return 0;
- }
-
- /**
- * Amount by which to extend the right fading region. Called only when
- * {@link #isPaddingOffsetRequired()} returns true.
- *
- * @return The right padding offset in pixels.
- *
- * @see #isPaddingOffsetRequired()
- *
- * @since CURRENT
- */
- protected int getRightPaddingOffset() {
- return 0;
- }
-
- /**
- * Amount by which to extend the top fading region. Called only when
- * {@link #isPaddingOffsetRequired()} returns true.
- *
- * @return The top padding offset in pixels.
- *
- * @see #isPaddingOffsetRequired()
- *
- * @since CURRENT
- */
- protected int getTopPaddingOffset() {
- return 0;
- }
-
- /**
- * Amount by which to extend the bottom fading region. Called only when
- * {@link #isPaddingOffsetRequired()} returns true.
- *
- * @return The bottom padding offset in pixels.
- *
- * @see #isPaddingOffsetRequired()
- *
- * @since CURRENT
- */
- protected int getBottomPaddingOffset() {
- return 0;
- }
-
- /**
- * Manually render this view (and all of its children) to the given Canvas.
- * The view must have already done a full layout before this function is
- * called. When implementing a view, do not override this method; instead,
- * you should implement {@link #onDraw}.
- *
- * @param canvas The Canvas to which the View is rendered.
- */
- public void draw(Canvas canvas) {
- if (ViewDebug.TRACE_HIERARCHY) {
- ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
- }
-
- mPrivateFlags |= DRAWN;
-
- /*
- * Draw traversal performs several drawing steps which must be executed
- * in the appropriate order:
- *
- * 1. Draw the background
- * 2. If necessary, save the canvas' layers to prepare for fading
- * 3. Draw view's content
- * 4. Draw children
- * 5. If necessary, draw the fading edges and restore layers
- * 6. Draw decorations (scrollbars for instance)
- */
-
- // Step 1, draw the background, if needed
- int saveCount;
-
- final Drawable background = mBGDrawable;
- if (background != null) {
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
-
- if (mBackgroundSizeChanged) {
- background.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
- mBackgroundSizeChanged = false;
- }
-
- if ((scrollX | scrollY) == 0) {
- background.draw(canvas);
- } else {
- canvas.translate(scrollX, scrollY);
- background.draw(canvas);
- canvas.translate(-scrollX, -scrollY);
- }
- }
-
- // skip step 2 & 5 if possible (common case)
- final int viewFlags = mViewFlags;
- boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
- boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
- if (!verticalEdges && !horizontalEdges) {
- // Step 3, draw the content
- onDraw(canvas);
-
- // Step 4, draw the children
- dispatchDraw(canvas);
-
- // Step 6, draw decorations (scrollbars)
- onDrawScrollBars(canvas);
-
- // we're done...
- return;
- }
-
- /*
- * Here we do the full fledged routine...
- * (this is an uncommon case where speed matters less,
- * this is why we repeat some of the tests that have been
- * done above)
- */
-
- boolean drawTop = false;
- boolean drawBottom = false;
- boolean drawLeft = false;
- boolean drawRight = false;
-
- float topFadeStrength = 0.0f;
- float bottomFadeStrength = 0.0f;
- float leftFadeStrength = 0.0f;
- float rightFadeStrength = 0.0f;
-
- // Step 2, save the canvas' layers
- int paddingLeft = mPaddingLeft;
- int paddingTop = mPaddingTop;
-
- final boolean offsetRequired = isPaddingOffsetRequired();
- if (offsetRequired) {
- paddingLeft += getLeftPaddingOffset();
- paddingTop += getTopPaddingOffset();
- }
-
- int left = mScrollX + paddingLeft;
- int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
- int top = mScrollY + paddingTop;
- int bottom = top + mBottom - mTop - mPaddingBottom - paddingTop;
-
- if (offsetRequired) {
- right += getRightPaddingOffset();
- bottom += getBottomPaddingOffset();
- }
-
- final ScrollabilityCache scrollabilityCache = mScrollCache;
- int length = scrollabilityCache.fadingEdgeLength;
-
- // clip the fade length if top and bottom fades overlap
- // overlapping fades produce odd-looking artifacts
- if (verticalEdges && (top + length > bottom - length)) {
- length = (bottom - top) / 2;
- }
-
- // also clip horizontal fades if necessary
- if (horizontalEdges && (left + length > right - length)) {
- length = (right - left) / 2;
- }
-
- if (verticalEdges) {
- topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
- drawTop = topFadeStrength >= 0.0f;
- bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
- drawBottom = bottomFadeStrength >= 0.0f;
- }
-
- if (horizontalEdges) {
- leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
- drawLeft = leftFadeStrength >= 0.0f;
- rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
- drawRight = rightFadeStrength >= 0.0f;
- }
-
- saveCount = canvas.getSaveCount();
-
- int solidColor = getSolidColor();
- if (solidColor == 0) {
- final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
-
- if (drawTop) {
- canvas.saveLayer(left, top, right, top + length, null, flags);
- }
-
- if (drawBottom) {
- canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
- }
-
- if (drawLeft) {
- canvas.saveLayer(left, top, left + length, bottom, null, flags);
- }
-
- if (drawRight) {
- canvas.saveLayer(right - length, top, right, bottom, null, flags);
- }
- } else {
- scrollabilityCache.setFadeColor(solidColor);
- }
-
- // Step 3, draw the content
- onDraw(canvas);
-
- // Step 4, draw the children
- dispatchDraw(canvas);
-
- // Step 5, draw the fade effect and restore layers
- final Paint p = scrollabilityCache.paint;
- final Matrix matrix = scrollabilityCache.matrix;
- final Shader fade = scrollabilityCache.shader;
- final float fadeHeight = scrollabilityCache.fadingEdgeLength;
-
- if (drawTop) {
- matrix.setScale(1, fadeHeight * topFadeStrength);
- matrix.postTranslate(left, top);
- fade.setLocalMatrix(matrix);
- canvas.drawRect(left, top, right, top + length, p);
- }
-
- if (drawBottom) {
- matrix.setScale(1, fadeHeight * bottomFadeStrength);
- matrix.postRotate(180);
- matrix.postTranslate(left, bottom);
- fade.setLocalMatrix(matrix);
- canvas.drawRect(left, bottom - length, right, bottom, p);
- }
-
- if (drawLeft) {
- matrix.setScale(1, fadeHeight * leftFadeStrength);
- matrix.postRotate(-90);
- matrix.postTranslate(left, top);
- fade.setLocalMatrix(matrix);
- canvas.drawRect(left, top, left + length, bottom, p);
- }
-
- if (drawRight) {
- matrix.setScale(1, fadeHeight * rightFadeStrength);
- matrix.postRotate(90);
- matrix.postTranslate(right, top);
- fade.setLocalMatrix(matrix);
- canvas.drawRect(right - length, top, right, bottom, p);
- }
-
- canvas.restoreToCount(saveCount);
-
- // Step 6, draw decorations (scrollbars)
- onDrawScrollBars(canvas);
- }
-
- /**
- * Override this if your view is known to always be drawn on top of a solid color background,
- * and needs to draw fading edges. Returning a non-zero color enables the view system to
- * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
- * should be set to 0xFF.
- *
- * @see #setVerticalFadingEdgeEnabled
- * @see #setHorizontalFadingEdgeEnabled
- *
- * @return The known solid color background for this view, or 0 if the color may vary
- */
- public int getSolidColor() {
- return 0;
- }
-
- /**
- * Build a human readable string representation of the specified view flags.
- *
- * @param flags the view flags to convert to a string
- * @return a String representing the supplied flags
- */
- private static String printFlags(int flags) {
- String output = "";
- int numFlags = 0;
- if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
- output += "TAKES_FOCUS";
- numFlags++;
- }
-
- switch (flags & VISIBILITY_MASK) {
- case INVISIBLE:
- if (numFlags > 0) {
- output += " ";
- }
- output += "INVISIBLE";
- // USELESS HERE numFlags++;
- break;
- case GONE:
- if (numFlags > 0) {
- output += " ";
- }
- output += "GONE";
- // USELESS HERE numFlags++;
- break;
- default:
- break;
- }
- return output;
- }
-
- /**
- * Build a human readable string representation of the specified private
- * view flags.
- *
- * @param privateFlags the private view flags to convert to a string
- * @return a String representing the supplied flags
- */
- private static String printPrivateFlags(int privateFlags) {
- String output = "";
- int numFlags = 0;
-
- if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) {
- output += "WANTS_FOCUS";
- numFlags++;
- }
-
- if ((privateFlags & FOCUSED) == FOCUSED) {
- if (numFlags > 0) {
- output += " ";
- }
- output += "FOCUSED";
- numFlags++;
- }
-
- if ((privateFlags & SELECTED) == SELECTED) {
- if (numFlags > 0) {
- output += " ";
- }
- output += "SELECTED";
- numFlags++;
- }
-
- if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) {
- if (numFlags > 0) {
- output += " ";
- }
- output += "IS_ROOT_NAMESPACE";
- numFlags++;
- }
-
- if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
- if (numFlags > 0) {
- output += " ";
- }
- output += "HAS_BOUNDS";
- numFlags++;
- }
-
- if ((privateFlags & DRAWN) == DRAWN) {
- if (numFlags > 0) {
- output += " ";
- }
- output += "DRAWN";
- // USELESS HERE numFlags++;
- }
- return output;
- }
-
- /**
- * <p>Indicates whether or not this view's layout will be requested during
- * the next hierarchy layout pass.</p>
- *
- * @return true if the layout will be forced during next layout pass
- */
- public boolean isLayoutRequested() {
- return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT;
- }
-
- /**
- * Assign a size and position to a view and all of its
- * descendants
- *
- * <p>This is the second phase of the layout mechanism.
- * (The first is measuring). In this phase, each parent calls
- * layout on all of its children to position them.
- * This is typically done using the child measurements
- * that were stored in the measure pass().
- *
- * Derived classes with children should override
- * onLayout. In that method, they should
- * call layout on each of their their children.
- *
- * @param l Left position, relative to parent
- * @param t Top position, relative to parent
- * @param r Right position, relative to parent
- * @param b Bottom position, relative to parent
- */
- public final void layout(int l, int t, int r, int b) {
- boolean changed = setFrame(l, t, r, b);
- if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
- if (ViewDebug.TRACE_HIERARCHY) {
- ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT);
- }
-
- onLayout(changed, l, t, r, b);
- mPrivateFlags &= ~LAYOUT_REQUIRED;
- }
- mPrivateFlags &= ~FORCE_LAYOUT;
- }
-
- /**
- * Called from layout when this view should
- * assign a size and position to each of its children.
- *
- * Derived classes with children should override
- * this method and call layout on each of
- * their their children.
- * @param changed This is a new size or position for this view
- * @param left Left position, relative to parent
- * @param top Top position, relative to parent
- * @param right Right position, relative to parent
- * @param bottom Bottom position, relative to parent
- */
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- }
-
- /**
- * Assign a size and position to this view.
- *
- * This is called from layout.
- *
- * @param left Left position, relative to parent
- * @param top Top position, relative to parent
- * @param right Right position, relative to parent
- * @param bottom Bottom position, relative to parent
- * @return true if the new size and position are different than the
- * previous ones
- * {@hide}
- */
- protected boolean setFrame(int left, int top, int right, int bottom) {
- boolean changed = false;
-
- if (DBG) {
- System.out.println(this + " View.setFrame(" + left + "," + top + ","
- + right + "," + bottom + ")");
- }
-
- if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
- changed = true;
-
- // Remember our drawn bit
- int drawn = mPrivateFlags & DRAWN;
-
- // Invalidate our old position
- invalidate();
-
-
- int oldWidth = mRight - mLeft;
- int oldHeight = mBottom - mTop;
-
- mLeft = left;
- mTop = top;
- mRight = right;
- mBottom = bottom;
-
- mPrivateFlags |= HAS_BOUNDS;
-
- int newWidth = right - left;
- int newHeight = bottom - top;
-
- if (newWidth != oldWidth || newHeight != oldHeight) {
- onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
- }
-
- if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
- // If we are visible, force the DRAWN bit to on so that
- // this invalidate will go through (at least to our parent).
- // This is because someone may have invalidated this view
- // before this call to setFrame came in, therby clearing
- // the DRAWN bit.
- mPrivateFlags |= DRAWN;
- invalidate();
- }
-
- // Reset drawn bit to original value (invalidate turns it off)
- mPrivateFlags |= drawn;
-
- mBackgroundSizeChanged = true;
- }
- return changed;
- }
-
- /**
- * Finalize inflating a view from XML. This is called as the last phase
- * of inflation, after all child views have been added.
- *
- * <p>Even if the subclass overrides onFinishInflate, they should always be
- * sure to call the super method, so that we get called.
- */
- protected void onFinishInflate() {
- }
-
- /**
- * Returns the resources associated with this view.
- *
- * @return Resources object.
- */
- public Resources getResources() {
- return mResources;
- }
-
- /**
- * Invalidates the specified Drawable.
- *
- * @param drawable the drawable to invalidate
- */
- public void invalidateDrawable(Drawable drawable) {
- if (verifyDrawable(drawable)) {
- final Rect dirty = drawable.getBounds();
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
-
- invalidate(dirty.left + scrollX, dirty.top + scrollY,
- dirty.right + scrollX, dirty.bottom + scrollY);
- }
- }
-
- /**
- * Schedules an action on a drawable to occur at a specified time.
- *
- * @param who the recipient of the action
- * @param what the action to run on the drawable
- * @param when the time at which the action must occur. Uses the
- * {@link SystemClock#uptimeMillis} timebase.
- */
- public void scheduleDrawable(Drawable who, Runnable what, long when) {
- if (verifyDrawable(who) && what != null && mAttachInfo != null) {
- mAttachInfo.mHandler.postAtTime(what, who, when);
- }
- }
-
- /**
- * Cancels a scheduled action on a drawable.
- *
- * @param who the recipient of the action
- * @param what the action to cancel
- */
- public void unscheduleDrawable(Drawable who, Runnable what) {
- if (verifyDrawable(who) && what != null && mAttachInfo != null) {
- mAttachInfo.mHandler.removeCallbacks(what, who);
- }
- }
-
- /**
- * Unschedule any events associated with the given Drawable. This can be
- * used when selecting a new Drawable into a view, so that the previous
- * one is completely unscheduled.
- *
- * @param who The Drawable to unschedule.
- *
- * @see #drawableStateChanged
- */
- public void unscheduleDrawable(Drawable who) {
- if (mAttachInfo != null) {
- mAttachInfo.mHandler.removeCallbacksAndMessages(who);
- }
- }
-
- /**
- * If your view subclass is displaying its own Drawable objects, it should
- * override this function and return true for any Drawable it is
- * displaying. This allows animations for those drawables to be
- * scheduled.
- *
- * <p>Be sure to call through to the super class when overriding this
- * function.
- *
- * @param who The Drawable to verify. Return true if it is one you are
- * displaying, else return the result of calling through to the
- * super class.
- *
- * @return boolean If true than the Drawable is being displayed in the
- * view; else false and it is not allowed to animate.
- *
- * @see #unscheduleDrawable
- * @see #drawableStateChanged
- */
- protected boolean verifyDrawable(Drawable who) {
- return who == mBGDrawable;
- }
-
- /**
- * This function is called whenever the state of the view changes in such
- * a way that it impacts the state of drawables being shown.
- *
- * <p>Be sure to call through to the superclass when overriding this
- * function.
- *
- * @see Drawable#setState
- */
- protected void drawableStateChanged() {
- Drawable d = mBGDrawable;
- if (d != null && d.isStateful()) {
- d.setState(getDrawableState());
- }
- }
-
- /**
- * Call this to force a view to update its drawable state. This will cause
- * drawableStateChanged to be called on this view. Views that are interested
- * in the new state should call getDrawableState.
- *
- * @see #drawableStateChanged
- * @see #getDrawableState
- */
- public void refreshDrawableState() {
- mPrivateFlags |= DRAWABLE_STATE_DIRTY;
- drawableStateChanged();
-
- ViewParent parent = mParent;
- if (parent != null) {
- parent.childDrawableStateChanged(this);
- }
- }
-
- /**
- * Return an array of resource IDs of the drawable states representing the
- * current state of the view.
- *
- * @return The current drawable state
- *
- * @see Drawable#setState
- * @see #drawableStateChanged
- * @see #onCreateDrawableState
- */
- public final int[] getDrawableState() {
- if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
- return mDrawableState;
- } else {
- mDrawableState = onCreateDrawableState(0);
- mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;
- return mDrawableState;
- }
- }
-
- /**
- * Generate the new {@link android.graphics.drawable.Drawable} state for
- * this view. This is called by the view
- * system when the cached Drawable state is determined to be invalid. To
- * retrieve the current state, you should use {@link #getDrawableState}.
- *
- * @param extraSpace if non-zero, this is the number of extra entries you
- * would like in the returned array in which you can place your own
- * states.
- *
- * @return Returns an array holding the current {@link Drawable} state of
- * the view.
- *
- * @see #mergeDrawableStates
- */
- protected int[] onCreateDrawableState(int extraSpace) {
- if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
- mParent instanceof View) {
- return ((View) mParent).onCreateDrawableState(extraSpace);
- }
-
- int[] drawableState;
-
- int privateFlags = mPrivateFlags;
-
- int viewStateIndex = (((privateFlags & PRESSED) != 0) ? 1 : 0);
-
- viewStateIndex = (viewStateIndex << 1)
- + (((mViewFlags & ENABLED_MASK) == ENABLED) ? 1 : 0);
-
- viewStateIndex = (viewStateIndex << 1) + (isFocused() ? 1 : 0);
-
- viewStateIndex = (viewStateIndex << 1)
- + (((privateFlags & SELECTED) != 0) ? 1 : 0);
-
- final boolean hasWindowFocus = hasWindowFocus();
- viewStateIndex = (viewStateIndex << 1) + (hasWindowFocus ? 1 : 0);
-
- drawableState = VIEW_STATE_SETS[viewStateIndex];
-
- //noinspection ConstantIfStatement
- if (false) {
- Log.i("View", "drawableStateIndex=" + viewStateIndex);
- Log.i("View", toString()
- + " pressed=" + ((privateFlags & PRESSED) != 0)
- + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
- + " fo=" + hasFocus()
- + " sl=" + ((privateFlags & SELECTED) != 0)
- + " wf=" + hasWindowFocus
- + ": " + Arrays.toString(drawableState));
- }
-
- if (extraSpace == 0) {
- return drawableState;
- }
-
- final int[] fullState;
- if (drawableState != null) {
- fullState = new int[drawableState.length + extraSpace];
- System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
- } else {
- fullState = new int[extraSpace];
- }
-
- return fullState;
- }
-
- /**
- * Merge your own state values in <var>additionalState</var> into the base
- * state values <var>baseState</var> that were returned by
- * {@link #onCreateDrawableState}.
- *
- * @param baseState The base state values returned by
- * {@link #onCreateDrawableState}, which will be modified to also hold your
- * own additional state values.
- *
- * @param additionalState The additional state values you would like
- * added to <var>baseState</var>; this array is not modified.
- *
- * @return As a convenience, the <var>baseState</var> array you originally
- * passed into the function is returned.
- *
- * @see #onCreateDrawableState
- */
- protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
- final int N = baseState.length;
- int i = N - 1;
- while (i >= 0 && baseState[i] == 0) {
- i--;
- }
- System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
- return baseState;
- }
-
- /**
- * Sets the background color for this view.
- * @param color the color of the background
- */
- public void setBackgroundColor(int color) {
- setBackgroundDrawable(new ColorDrawable(color));
- }
-
- /**
- * Set the background to a given resource. The resource should refer to
- * a Drawable object.
- * @param resid The identifier of the resource.
- * @attr ref android.R.styleable#View_background
- */
- public void setBackgroundResource(int resid) {
- if (resid != 0 && resid == mBackgroundResource) {
- return;
- }
-
- Drawable d= null;
- if (resid != 0) {
- d = mResources.getDrawable(resid);
- }
- setBackgroundDrawable(d);
-
- mBackgroundResource = resid;
- }
-
- /**
- * Set the background to a given Drawable, or remove the background. If the
- * background has padding, this View's padding is set to the background's
- * padding. However, when a background is removed, this View's padding isn't
- * touched. If setting the padding is desired, please use
- * {@link #setPadding(int, int, int, int)}.
- *
- * @param d The Drawable to use as the background, or null to remove the
- * background
- */
- public void setBackgroundDrawable(Drawable d) {
- boolean requestLayout = false;
-
- mBackgroundResource = 0;
-
- /*
- * Regardless of whether we're setting a new background or not, we want
- * to clear the previous drawable.
- */
- if (mBGDrawable != null) {
- mBGDrawable.setCallback(null);
- unscheduleDrawable(mBGDrawable);
- }
-
- if (d != null) {
- Rect padding = sThreadLocal.get();
- if (padding == null) {
- padding = new Rect();
- sThreadLocal.set(padding);
- }
- if (d.getPadding(padding)) {
- setPadding(padding.left, padding.top, padding.right, padding.bottom);
- }
-
- // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or
- // if it has a different minimum size, we should layout again
- if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() ||
- mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) {
- requestLayout = true;
- }
-
- d.setCallback(this);
- if (d.isStateful()) {
- d.setState(getDrawableState());
- }
- d.setVisible(getVisibility() == VISIBLE, false);
- mBGDrawable = d;
-
- if ((mPrivateFlags & SKIP_DRAW) != 0) {
- mPrivateFlags &= ~SKIP_DRAW;
- mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
- requestLayout = true;
- }
- } else {
- /* Remove the background */
- mBGDrawable = null;
-
- if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
- /*
- * This view ONLY drew the background before and we're removing
- * the background, so now it won't draw anything
- * (hence we SKIP_DRAW)
- */
- mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
- mPrivateFlags |= SKIP_DRAW;
- }
-
- /*
- * When the background is set, we try to apply its padding to this
- * View. When the background is removed, we don't touch this View's
- * padding. This is noted in the Javadocs. Hence, we don't need to
- * requestLayout(), the invalidate() below is sufficient.
- */
-
- // The old background's minimum size could have affected this
- // View's layout, so let's requestLayout
- requestLayout = true;
- }
-
- if (requestLayout) {
- requestLayout();
- }
-
- mBackgroundSizeChanged = true;
- invalidate();
- }
-
- /**
- * Gets the background drawable
- * @return The drawable used as the background for this view, if any.
- */
- public Drawable getBackground() {
- return mBGDrawable;
- }
-
- private int getScrollBarPaddingLeft() {
- // TODO: Deal with RTL languages
- return 0;
- }
-
- /*
- * Returns the pixels occupied by the vertical scrollbar, if not overlaid
- */
- private int getScrollBarPaddingRight() {
- // TODO: Deal with RTL languages
- if ((mViewFlags & SCROLLBARS_VERTICAL) == 0) {
- return 0;
- }
- return (mViewFlags & SCROLLBARS_INSET_MASK) == 0 ? 0 : getVerticalScrollbarWidth();
- }
-
- /*
- * Returns the pixels occupied by the horizontal scrollbar, if not overlaid
- */
- private int getScrollBarPaddingBottom() {
- if ((mViewFlags & SCROLLBARS_HORIZONTAL) == 0) {
- return 0;
- }
- return (mViewFlags & SCROLLBARS_INSET_MASK) == 0 ? 0 : getHorizontalScrollbarHeight();
- }
-
- /**
- * Sets the padding. The view may add on the space required to display
- * the scrollbars, depending on the style and visibility of the scrollbars.
- * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
- * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
- * from the values set in this call.
- *
- * @attr ref android.R.styleable#View_padding
- * @attr ref android.R.styleable#View_paddingBottom
- * @attr ref android.R.styleable#View_paddingLeft
- * @attr ref android.R.styleable#View_paddingRight
- * @attr ref android.R.styleable#View_paddingTop
- * @param left the left padding in pixels
- * @param top the top padding in pixels
- * @param right the right padding in pixels
- * @param bottom the bottom padding in pixels
- */
- public void setPadding(int left, int top, int right, int bottom) {
- boolean changed = false;
-
- mUserPaddingRight = right;
- mUserPaddingBottom = bottom;
-
- if (mPaddingLeft != left + getScrollBarPaddingLeft()) {
- changed = true;
- mPaddingLeft = left;
- }
- if (mPaddingTop != top) {
- changed = true;
- mPaddingTop = top;
- }
- if (mPaddingRight != right + getScrollBarPaddingRight()) {
- changed = true;
- mPaddingRight = right + getScrollBarPaddingRight();
- }
- if (mPaddingBottom != bottom + getScrollBarPaddingBottom()) {
- changed = true;
- mPaddingBottom = bottom + getScrollBarPaddingBottom();
- }
-
- if (changed) {
- requestLayout();
- }
- }
-
- /**
- * Returns the top padding of this view.
- *
- * @return the top padding in pixels
- */
- public int getPaddingTop() {
- return mPaddingTop;
- }
-
- /**
- * Returns the bottom padding of this view. If there are inset and enabled
- * scrollbars, this value may include the space required to display the
- * scrollbars as well.
- *
- * @return the bottom padding in pixels
- */
- public int getPaddingBottom() {
- return mPaddingBottom;
- }
-
- /**
- * Returns the left padding of this view. If there are inset and enabled
- * scrollbars, this value may include the space required to display the
- * scrollbars as well.
- *
- * @return the left padding in pixels
- */
- public int getPaddingLeft() {
- return mPaddingLeft;
- }
-
- /**
- * Returns the right padding of this view. If there are inset and enabled
- * scrollbars, this value may include the space required to display the
- * scrollbars as well.
- *
- * @return the right padding in pixels
- */
- public int getPaddingRight() {
- return mPaddingRight;
- }
-
- /**
- * Changes the selection state of this view. A view can be selected or not.
- * Note that selection is not the same as focus. Views are typically
- * selected in the context of an AdapterView like ListView or GridView;
- * the selected view is the view that is highlighted.
- *
- * @param selected true if the view must be selected, false otherwise
- */
- public void setSelected(boolean selected) {
- if (((mPrivateFlags & SELECTED) != 0) != selected) {
- mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0);
- invalidate();
- refreshDrawableState();
- dispatchSetSelected(selected);
- }
- }
-
- /**
- * Dispatch setSelected to all of this View's children.
- *
- * @see #setSelected(boolean)
- *
- * @param selected The new selected state
- */
- protected void dispatchSetSelected(boolean selected) {
- }
-
- /**
- * Indicates the selection state of this view.
- *
- * @return true if the view is selected, false otherwise
- */
- @ViewDebug.ExportedProperty
- public boolean isSelected() {
- return (mPrivateFlags & SELECTED) != 0;
- }
-
- /**
- * Returns the ViewTreeObserver for this view's hierarchy. The view tree
- * observer can be used to get notifications when global events, like
- * layout, happen.
- *
- * The returned ViewTreeObserver observer is not guaranteed to remain
- * valid for the lifetime of this View. If the caller of this method keeps
- * a long-lived reference to ViewTreeObserver, it should always check for
- * the return value of {@link ViewTreeObserver#isAlive()}.
- *
- * @return The ViewTreeObserver for this view's hierarchy.
- */
- public ViewTreeObserver getViewTreeObserver() {
- if (mAttachInfo != null) {
- return mAttachInfo.mTreeObserver;
- }
- if (mFloatingTreeObserver == null) {
- mFloatingTreeObserver = new ViewTreeObserver();
- }
- return mFloatingTreeObserver;
- }
-
- /**
- * <p>Finds the topmost view in the current view hierarchy.</p>
- *
- * @return the topmost view containing this view
- */
- public View getRootView() {
- if (mAttachInfo != null) {
- final View v = mAttachInfo.mRootView;
- if (v != null) {
- return v;
- }
- }
-
- View parent = this;
-
- while (parent.mParent != null && parent.mParent instanceof View) {
- parent = (View) parent.mParent;
- }
-
- return parent;
- }
-
- /**
- * <p>Computes the coordinates of this view on the screen. The argument
- * must be an array of two integers. After the method returns, the array
- * contains the x and y location in that order.</p>
- *
- * @param location an array of two integers in which to hold the coordinates
- */
- public void getLocationOnScreen(int[] location) {
- getLocationInWindow(location);
-
- final AttachInfo info = mAttachInfo;
- location[0] += info.mWindowLeft;
- location[1] += info.mWindowTop;
- }
-
- /**
- * <p>Computes the coordinates of this view in its window. The argument
- * must be an array of two integers. After the method returns, the array
- * contains the x and y location in that order.</p>
- *
- * @param location an array of two integers in which to hold the coordinates
- */
- public void getLocationInWindow(int[] location) {
- if (location == null || location.length < 2) {
- throw new IllegalArgumentException("location must be an array of "
- + "two integers");
- }
-
- location[0] = mLeft;
- location[1] = mTop;
-
- ViewParent viewParent = mParent;
- while (viewParent instanceof View) {
- final View view = (View)viewParent;
- location[0] += view.mLeft - view.mScrollX;
- location[1] += view.mTop - view.mScrollY;
- viewParent = view.mParent;
- }
-
- if (viewParent instanceof ViewRoot) {
- // *cough*
- final ViewRoot vr = (ViewRoot)viewParent;
- location[1] -= vr.mCurScrollY;
- }
- }
-
- /**
- * {@hide}
- * @param id the id of the view to be found
- * @return the view of the specified id, null if cannot be found
- */
- protected View findViewTraversal(int id) {
- if (id == mID) {
- return this;
- }
- return null;
- }
-
- /**
- * {@hide}
- * @param tag the tag of the view to be found
- * @return the view of specified tag, null if cannot be found
- */
- protected View findViewWithTagTraversal(Object tag) {
- if (tag != null && tag.equals(mTag)) {
- return this;
- }
- return null;
- }
-
- /**
- * Look for a child view with the given id. If this view has the given
- * id, return this view.
- *
- * @param id The id to search for.
- * @return The view that has the given id in the hierarchy or null
- */
- public final View findViewById(int id) {
- if (id < 0) {
- return null;
- }
- return findViewTraversal(id);
- }
-
- /**
- * Look for a child view with the given tag. If this view has the given
- * tag, return this view.
- *
- * @param tag The tag to search for, using "tag.equals(getTag())".
- * @return The View that has the given tag in the hierarchy or null
- */
- public final View findViewWithTag(Object tag) {
- if (tag == null) {
- return null;
- }
- return findViewWithTagTraversal(tag);
- }
-
- /**
- * Sets the identifier for this view. The identifier does not have to be
- * unique in this view's hierarchy. The identifier should be a positive
- * number.
- *
- * @see #NO_ID
- * @see #getId
- * @see #findViewById
- *
- * @param id a number used to identify the view
- *
- * @attr ref android.R.styleable#View_id
- */
- public void setId(int id) {
- mID = id;
- }
-
- /**
- * {@hide}
- *
- * @param isRoot true if the view belongs to the root namespace, false
- * otherwise
- */
- public void setIsRootNamespace(boolean isRoot) {
- if (isRoot) {
- mPrivateFlags |= IS_ROOT_NAMESPACE;
- } else {
- mPrivateFlags &= ~IS_ROOT_NAMESPACE;
- }
- }
-
- /**
- * {@hide}
- *
- * @return true if the view belongs to the root namespace, false otherwise
- */
- public boolean isRootNamespace() {
- return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0;
- }
-
- /**
- * Returns this view's identifier.
- *
- * @return a positive integer used to identify the view or {@link #NO_ID}
- * if the view has no ID
- *
- * @see #setId
- * @see #findViewById
- * @attr ref android.R.styleable#View_id
- */
- @ViewDebug.CapturedViewProperty
- public int getId() {
- return mID;
- }
-
- /**
- * Returns this view's tag.
- *
- * @return the Object stored in this view as a tag
- */
- @ViewDebug.ExportedProperty
- public Object getTag() {
- return mTag;
- }
-
- /**
- * Sets the tag associated with this view. A tag can be used to mark
- * a view in its hierarchy and does not have to be unique within the
- * hierarchy. Tags can also be used to store data within a view without
- * resorting to another data structure.
- *
- * @param tag an Object to tag the view with
- */
- public void setTag(final Object tag) {
- mTag = tag;
- }
-
- /**
- * Prints information about this view in the log output, with the tag
- * {@link #VIEW_LOG_TAG}.
- *
- * @hide
- */
- public void debug() {
- debug(0);
- }
-
- /**
- * Prints information about this view in the log output, with the tag
- * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
- * indentation defined by the <code>depth</code>.
- *
- * @param depth the indentation level
- *
- * @hide
- */
- protected void debug(int depth) {
- String output = debugIndent(depth - 1);
-
- output += "+ " + this;
- int id = getId();
- if (id != -1) {
- output += " (id=" + id + ")";
- }
- Object tag = getTag();
- if (tag != null) {
- output += " (tag=" + tag + ")";
- }
- Log.d(VIEW_LOG_TAG, output);
-
- if ((mPrivateFlags & FOCUSED) != 0) {
- output = debugIndent(depth) + " FOCUSED";
- Log.d(VIEW_LOG_TAG, output);
- }
-
- output = debugIndent(depth);
- output += "frame={" + mLeft + ", " + mTop + ", " + mRight
- + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
- + "} ";
- Log.d(VIEW_LOG_TAG, output);
-
- if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
- || mPaddingBottom != 0) {
- output = debugIndent(depth);
- output += "padding={" + mPaddingLeft + ", " + mPaddingTop
- + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
- Log.d(VIEW_LOG_TAG, output);
- }
-
- output = debugIndent(depth);
- output += "mMeasureWidth=" + mMeasuredWidth +
- " mMeasureHeight=" + mMeasuredHeight;
- Log.d(VIEW_LOG_TAG, output);
-
- output = debugIndent(depth);
- if (mLayoutParams == null) {
- output += "BAD! no layout params";
- } else {
- output = mLayoutParams.debug(output);
- }
- Log.d(VIEW_LOG_TAG, output);
-
- output = debugIndent(depth);
- output += "flags={";
- output += View.printFlags(mViewFlags);
- output += "}";
- Log.d(VIEW_LOG_TAG, output);
-
- output = debugIndent(depth);
- output += "privateFlags={";
- output += View.printPrivateFlags(mPrivateFlags);
- output += "}";
- Log.d(VIEW_LOG_TAG, output);
- }
-
- /**
- * Creates an string of whitespaces used for indentation.
- *
- * @param depth the indentation level
- * @return a String containing (depth * 2 + 3) * 2 white spaces
- *
- * @hide
- */
- protected static String debugIndent(int depth) {
- StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
- for (int i = 0; i < (depth * 2) + 3; i++) {
- spaces.append(' ').append(' ');
- }
- return spaces.toString();
- }
-
- /**
- * <p>Return the offset of the widget's text baseline from the widget's top
- * boundary. If this widget does not support baseline alignment, this
- * method returns -1. </p>
- *
- * @return the offset of the baseline within the widget's bounds or -1
- * if baseline alignment is not supported
- */
- @ViewDebug.ExportedProperty
- public int getBaseline() {
- return -1;
- }
-
- /**
- * Call this when something has changed which has invalidated the
- * layout of this view. This will schedule a layout pass of the view
- * tree.
- */
- public void requestLayout() {
- if (ViewDebug.TRACE_HIERARCHY) {
- ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT);
- }
-
- mPrivateFlags |= FORCE_LAYOUT;
-
- if (mParent != null && !mParent.isLayoutRequested()) {
- mParent.requestLayout();
- }
- }
-
- /**
- * Forces this view to be laid out during the next layout pass.
- * This method does not call requestLayout() or forceLayout()
- * on the parent.
- */
- public void forceLayout() {
- mPrivateFlags |= FORCE_LAYOUT;
- }
-
- /**
- * <p>
- * This is called to find out how big a view should be. The parent
- * supplies constraint information in the width and height parameters.
- * </p>
- *
- * <p>
- * The actual mesurement work of a view is performed in
- * {@link #onMeasure(int, int)}, called by this method. Therefore, only
- * {@link #onMeasure(int, int)} can and must be overriden by subclasses.
- * </p>
- *
- *
- * @param widthMeasureSpec Horizontal space requirements as imposed by the
- * parent
- * @param heightMeasureSpec Vertical space requirements as imposed by the
- * parent
- *
- * @see #onMeasure(int, int)
- */
- public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
- if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
- widthMeasureSpec != mOldWidthMeasureSpec ||
- heightMeasureSpec != mOldHeightMeasureSpec) {
-
- // first clears the measured dimension flag
- mPrivateFlags &= ~MEASURED_DIMENSION_SET;
-
- if (ViewDebug.TRACE_HIERARCHY) {
- ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
- }
-
- // measure ourselves, this should set the measured dimension flag back
- onMeasure(widthMeasureSpec, heightMeasureSpec);
-
- // flag not set, setMeasuredDimension() was not invoked, we raise
- // an exception to warn the developer
- if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
- throw new IllegalStateException("onMeasure() did not set the"
- + " measured dimension by calling"
- + " setMeasuredDimension()");
- }
-
- mPrivateFlags |= LAYOUT_REQUIRED;
- }
-
- mOldWidthMeasureSpec = widthMeasureSpec;
- mOldHeightMeasureSpec = heightMeasureSpec;
- }
-
- /**
- * <p>
- * Measure the view and its content to determine the measured width and the
- * measured height. This method is invoked by {@link #measure(int, int)} and
- * should be overriden by subclasses to provide accurate and efficient
- * measurement of their contents.
- * </p>
- *
- * <p>
- * <strong>CONTRACT:</strong> When overriding this method, you
- * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
- * measured width and height of this view. Failure to do so will trigger an
- * <code>IllegalStateException</code>, thrown by
- * {@link #measure(int, int)}. Calling the superclass'
- * {@link #onMeasure(int, int)} is a valid use.
- * </p>
- *
- * <p>
- * The base class implementation of measure defaults to the background size,
- * unless a larger size is allowed by the MeasureSpec. Subclasses should
- * override {@link #onMeasure(int, int)} to provide better measurements of
- * their content.
- * </p>
- *
- * <p>
- * If this method is overridden, it is the subclass's responsibility to make
- * sure the measured height and width are at least the view's minimum height
- * and width ({@link #getSuggestedMinimumHeight()} and
- * {@link #getSuggestedMinimumWidth()}).
- * </p>
- *
- * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
- * The requirements are encoded with
- * {@link android.view.View.MeasureSpec}.
- * @param heightMeasureSpec vertical space requirements as imposed by the parent.
- * The requirements are encoded with
- * {@link android.view.View.MeasureSpec}.
- *
- * @see #getMeasuredWidth()
- * @see #getMeasuredHeight()
- * @see #setMeasuredDimension(int, int)
- * @see #getSuggestedMinimumHeight()
- * @see #getSuggestedMinimumWidth()
- * @see android.view.View.MeasureSpec#getMode(int)
- * @see android.view.View.MeasureSpec#getSize(int)
- */
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
- getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
- }
-
- /**
- * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
- * measured width and measured height. Failing to do so will trigger an
- * exception at measurement time.</p>
- *
- * @param measuredWidth the measured width of this view
- * @param measuredHeight the measured height of this view
- */
- protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
- mMeasuredWidth = measuredWidth;
- mMeasuredHeight = measuredHeight;
-
- mPrivateFlags |= MEASURED_DIMENSION_SET;
- }
-
- /**
- * Utility to reconcile a desired size with constraints imposed by a MeasureSpec.
- * Will take the desired size, unless a different size is imposed by the constraints.
- *
- * @param size How big the view wants to be
- * @param measureSpec Constraints imposed by the parent
- * @return The size this view should be.
- */
- public static int resolveSize(int size, int measureSpec) {
- int result = size;
- int specMode = MeasureSpec.getMode(measureSpec);
- int specSize = MeasureSpec.getSize(measureSpec);
- switch (specMode) {
- case MeasureSpec.UNSPECIFIED:
- result = size;
- break;
- case MeasureSpec.AT_MOST:
- result = Math.min(size, specSize);
- break;
- case MeasureSpec.EXACTLY:
- result = specSize;
- break;
- }
- return result;
- }
-
- /**
- * Utility to return a default size. Uses the supplied size if the
- * MeasureSpec imposed no contraints. Will get larger if allowed
- * by the MeasureSpec.
- *
- * @param size Default size for this view
- * @param measureSpec Constraints imposed by the parent
- * @return The size this view should be.
- */
- public static int getDefaultSize(int size, int measureSpec) {
- int result = size;
- int specMode = MeasureSpec.getMode(measureSpec);
- int specSize = MeasureSpec.getSize(measureSpec);
-
- switch (specMode) {
- case MeasureSpec.UNSPECIFIED:
- result = size;
- break;
- case MeasureSpec.AT_MOST:
- case MeasureSpec.EXACTLY:
- result = specSize;
- break;
- }
- return result;
- }
-
- /**
- * Returns the suggested minimum height that the view should use. This
- * returns the maximum of the view's minimum height
- * and the background's minimum height
- * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
- * <p>
- * When being used in {@link #onMeasure(int, int)}, the caller should still
- * ensure the returned height is within the requirements of the parent.
- *
- * @return The suggested minimum height of the view.
- */
- protected int getSuggestedMinimumHeight() {
- int suggestedMinHeight = mMinHeight;
-
- if (mBGDrawable != null) {
- final int bgMinHeight = mBGDrawable.getMinimumHeight();
- if (suggestedMinHeight < bgMinHeight) {
- suggestedMinHeight = bgMinHeight;
- }
- }
-
- return suggestedMinHeight;
- }
-
- /**
- * Returns the suggested minimum width that the view should use. This
- * returns the maximum of the view's minimum width)
- * and the background's minimum width
- * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
- * <p>
- * When being used in {@link #onMeasure(int, int)}, the caller should still
- * ensure the returned width is within the requirements of the parent.
- *
- * @return The suggested minimum width of the view.
- */
- protected int getSuggestedMinimumWidth() {
- int suggestedMinWidth = mMinWidth;
-
- if (mBGDrawable != null) {
- final int bgMinWidth = mBGDrawable.getMinimumWidth();
- if (suggestedMinWidth < bgMinWidth) {
- suggestedMinWidth = bgMinWidth;
- }
- }
-
- return suggestedMinWidth;
- }
-
- /**
- * Sets the minimum height of the view. It is not guaranteed the view will
- * be able to achieve this minimum height (for example, if its parent layout
- * constrains it with less available height).
- *
- * @param minHeight The minimum height the view will try to be.
- */
- public void setMinimumHeight(int minHeight) {
- mMinHeight = minHeight;
- }
-
- /**
- * Sets the minimum width of the view. It is not guaranteed the view will
- * be able to achieve this minimum width (for example, if its parent layout
- * constrains it with less available width).
- *
- * @param minWidth The minimum width the view will try to be.
- */
- public void setMinimumWidth(int minWidth) {
- mMinWidth = minWidth;
- }
-
- /**
- * Get the animation currently associated with this view.
- *
- * @return The animation that is currently playing or
- * scheduled to play for this view.
- */
- public Animation getAnimation() {
- return mCurrentAnimation;
- }
-
- /**
- * Start the specified animation now.
- *
- * @param animation the animation to start now
- */
- public void startAnimation(Animation animation) {
- animation.setStartTime(Animation.START_ON_FIRST_FRAME);
- setAnimation(animation);
- invalidate();
- }
-
- /**
- * Cancels any animations for this view.
- */
- public void clearAnimation() {
- mCurrentAnimation = null;
- }
-
- /**
- * Sets the next animation to play for this view.
- * If you want the animation to play immediately, use
- * startAnimation. This method provides allows fine-grained
- * control over the start time and invalidation, but you
- * must make sure that 1) the animation has a start time set, and
- * 2) the view will be invalidated when the animation is supposed to
- * start.
- *
- * @param animation The next animation, or null.
- */
- public void setAnimation(Animation animation) {
- mCurrentAnimation = animation;
- if (animation != null) {
- animation.reset();
- }
- }
-
- /**
- * Invoked by a parent ViewGroup to notify the start of the animation
- * currently associated with this view. If you override this method,
- * always call super.onAnimationStart();
- *
- * @see #setAnimation(android.view.animation.Animation)
- * @see #getAnimation()
- */
- protected void onAnimationStart() {
- mPrivateFlags |= ANIMATION_STARTED;
- }
-
- /**
- * Invoked by a parent ViewGroup to notify the end of the animation
- * currently associated with this view. If you override this method,
- * always call super.onAnimationEnd();
- *
- * @see #setAnimation(android.view.animation.Animation)
- * @see #getAnimation()
- */
- protected void onAnimationEnd() {
- mPrivateFlags &= ~ANIMATION_STARTED;
- }
-
- /**
- * Invoked if there is a Transform that involves alpha. Subclass that can
- * draw themselves with the specified alpha should return true, and then
- * respect that alpha when their onDraw() is called. If this returns false
- * then the view may be redirected to draw into an offscreen buffer to
- * fulfill the request, which will look fine, but may be slower than if the
- * subclass handles it internally. The default implementation returns false.
- *
- * @param alpha The alpha (0..255) to apply to the view's drawing
- * @return true if the view can draw with the specified alpha.
- */
- protected boolean onSetAlpha(int alpha) {
- return false;
- }
-
- /**
- * This is used by the RootView to perform an optimization when
- * the view hierarchy contains one or several SurfaceView.
- * SurfaceView is always considered transparent, but its children are not,
- * therefore all View objects remove themselves from the global transparent
- * region (passed as a parameter to this function).
- *
- * @param region The transparent region for this ViewRoot (window).
- *
- * @return Returns true if the effective visibility of the view at this
- * point is opaque, regardless of the transparent region; returns false
- * if it is possible for underlying windows to be seen behind the view.
- *
- * {@hide}
- */
- public boolean gatherTransparentRegion(Region region) {
- final AttachInfo attachInfo = mAttachInfo;
- if (region != null && attachInfo != null) {
- final int pflags = mPrivateFlags;
- if ((pflags & SKIP_DRAW) == 0) {
- // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
- // remove it from the transparent region.
- final int[] location = attachInfo.mTransparentLocation;
- getLocationInWindow(location);
- region.op(location[0], location[1], location[0] + mRight - mLeft,
- location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
- } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBGDrawable != null) {
- // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
- // exists, so we remove the background drawable's non-transparent
- // parts from this transparent region.
- applyDrawableToTransparentRegion(mBGDrawable, region);
- }
- }
- return true;
- }
-
- /**
- * Play a sound effect for this view.
- *
- * <p>The framework will play sound effects for some built in actions, such as
- * clicking, but you may wish to play these effects in your widget,
- * for instance, for internal navigation.
- *
- * <p>The sound effect will only be played if sound effects are enabled by the user, and
- * {@link #isSoundEffectsEnabled()} is true.
- *
- * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
- */
- public void playSoundEffect(int soundConstant) {
- if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
- return;
- }
- mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
- }
-
- /**
- * Provide haptic feedback to the user for this view.
- *
- * <p>The framework will provide haptic feedback for some built in actions,
- * such as long presses, but you may wish to provide feedback for your
- * own widget.
- *
- * <p>The feedback will only be performed if
- * {@link #isHapticFeedbackEnabled()} is true.
- *
- * @param feedbackConstant One of the constants defined in
- * {@link HapticFeedbackConstants}
- */
- public boolean performHapticFeedback(int feedbackConstant) {
- return performHapticFeedback(feedbackConstant, 0);
- }
-
- /**
- * Like {@link #performHapticFeedback(int)}, with additional options.
- *
- * @param feedbackConstant One of the constants defined in
- * {@link HapticFeedbackConstants}
- * @param flags Additional flags as per {@link HapticFeedbackConstants}.
- */
- public boolean performHapticFeedback(int feedbackConstant, int flags) {
- if (mAttachInfo == null) {
- return false;
- }
- if ((flags&HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
- && !isHapticFeedbackEnabled()) {
- return false;
- }
- return mAttachInfo.mRootCallbacks.performHapticFeedback(
- feedbackConstant,
- (flags&HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
- }
-
- /**
- * Given a Drawable whose bounds have been set to draw into this view,
- * update a Region being computed for {@link #gatherTransparentRegion} so
- * that any non-transparent parts of the Drawable are removed from the
- * given transparent region.
- *
- * @param dr The Drawable whose transparency is to be applied to the region.
- * @param region A Region holding the current transparency information,
- * where any parts of the region that are set are considered to be
- * transparent. On return, this region will be modified to have the
- * transparency information reduced by the corresponding parts of the
- * Drawable that are not transparent.
- * {@hide}
- */
- public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
- if (DBG) {
- Log.i("View", "Getting transparent region for: " + this);
- }
- final Region r = dr.getTransparentRegion();
- final Rect db = dr.getBounds();
- final AttachInfo attachInfo = mAttachInfo;
- if (r != null && attachInfo != null) {
- final int w = getRight()-getLeft();
- final int h = getBottom()-getTop();
- if (db.left > 0) {
- //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
- r.op(0, 0, db.left, h, Region.Op.UNION);
- }
- if (db.right < w) {
- //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
- r.op(db.right, 0, w, h, Region.Op.UNION);
- }
- if (db.top > 0) {
- //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
- r.op(0, 0, w, db.top, Region.Op.UNION);
- }
- if (db.bottom < h) {
- //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
- r.op(0, db.bottom, w, h, Region.Op.UNION);
- }
- final int[] location = attachInfo.mTransparentLocation;
- getLocationInWindow(location);
- r.translate(location[0], location[1]);
- region.op(r, Region.Op.INTERSECT);
- } else {
- region.op(db, Region.Op.DIFFERENCE);
- }
- }
-
- private void postCheckForLongClick() {
- mHasPerformedLongPress = false;
-
- if (mPendingCheckForLongPress == null) {
- mPendingCheckForLongPress = new CheckForLongPress();
- }
- mPendingCheckForLongPress.rememberWindowAttachCount();
- postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout());
- }
-
- private static int[] stateSetUnion(final int[] stateSet1,
- final int[] stateSet2) {
- final int stateSet1Length = stateSet1.length;
- final int stateSet2Length = stateSet2.length;
- final int[] newSet = new int[stateSet1Length + stateSet2Length];
- int k = 0;
- int i = 0;
- int j = 0;
- // This is a merge of the two input state sets and assumes that the
- // input sets are sorted by the order imposed by ViewDrawableStates.
- for (int viewState : R.styleable.ViewDrawableStates) {
- if (i < stateSet1Length && stateSet1[i] == viewState) {
- newSet[k++] = viewState;
- i++;
- } else if (j < stateSet2Length && stateSet2[j] == viewState) {
- newSet[k++] = viewState;
- j++;
- }
- if (k > 1) {
- assert(newSet[k - 1] > newSet[k - 2]);
- }
- }
- return newSet;
- }
-
- /**
- * Inflate a view from an XML resource. This convenience method wraps the {@link
- * LayoutInflater} class, which provides a full range of options for view inflation.
- *
- * @param context The Context object for your activity or application.
- * @param resource The resource ID to inflate
- * @param root A view group that will be the parent. Used to properly inflate the
- * layout_* parameters.
- * @see LayoutInflater
- */
- public static View inflate(Context context, int resource, ViewGroup root) {
- LayoutInflater factory = LayoutInflater.from(context);
- return factory.inflate(resource, root);
- }
-
- /**
- * A MeasureSpec encapsulates the layout requirements passed from parent to child.
- * Each MeasureSpec represents a requirement for either the width or the height.
- * A MeasureSpec is comprised of a size and a mode. There are three possible
- * modes:
- * <dl>
- * <dt>UNSPECIFIED</dt>
- * <dd>
- * The parent has not imposed any constraint on the child. It can be whatever size
- * it wants.
- * </dd>
- *
- * <dt>EXACTLY</dt>
- * <dd>
- * The parent has determined an exact size for the child. The child is going to be
- * given those bounds regardless of how big it wants to be.
- * </dd>
- *
- * <dt>AT_MOST</dt>
- * <dd>
- * The child can be as large as it wants up to the specified size.
- * </dd>
- * </dl>
- *
- * MeasureSpecs are implemented as ints to reduce object allocation. This class
- * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
- */
- public static class MeasureSpec {
- private static final int MODE_SHIFT = 30;
- private static final int MODE_MASK = 0x3 << MODE_SHIFT;
-
- /**
- * Measure specification mode: The parent has not imposed any constraint
- * on the child. It can be whatever size it wants.
- */
- public static final int UNSPECIFIED = 0 << MODE_SHIFT;
-
- /**
- * Measure specification mode: The parent has determined an exact size
- * for the child. The child is going to be given those bounds regardless
- * of how big it wants to be.
- */
- public static final int EXACTLY = 1 << MODE_SHIFT;
-
- /**
- * Measure specification mode: The child can be as large as it wants up
- * to the specified size.
- */
- public static final int AT_MOST = 2 << MODE_SHIFT;
-
- /**
- * Creates a measure specification based on the supplied size and mode.
- *
- * The mode must always be one of the following:
- * <ul>
- * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
- * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
- * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
- * </ul>
- *
- * @param size the size of the measure specification
- * @param mode the mode of the measure specification
- * @return the measure specification based on size and mode
- */
- public static int makeMeasureSpec(int size, int mode) {
- return size + mode;
- }
-
- /**
- * Extracts the mode from the supplied measure specification.
- *
- * @param measureSpec the measure specification to extract the mode from
- * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
- * {@link android.view.View.MeasureSpec#AT_MOST} or
- * {@link android.view.View.MeasureSpec#EXACTLY}
- */
- public static int getMode(int measureSpec) {
- return (measureSpec & MODE_MASK);
- }
-
- /**
- * Extracts the size from the supplied measure specification.
- *
- * @param measureSpec the measure specification to extract the size from
- * @return the size in pixels defined in the supplied measure specification
- */
- public static int getSize(int measureSpec) {
- return (measureSpec & ~MODE_MASK);
- }
-
- /**
- * Returns a String representation of the specified measure
- * specification.
- *
- * @param measureSpec the measure specification to convert to a String
- * @return a String with the following format: "MeasureSpec: MODE SIZE"
- */
- public static String toString(int measureSpec) {
- int mode = getMode(measureSpec);
- int size = getSize(measureSpec);
-
- StringBuilder sb = new StringBuilder("MeasureSpec: ");
-
- if (mode == UNSPECIFIED)
- sb.append("UNSPECIFIED ");
- else if (mode == EXACTLY)
- sb.append("EXACTLY ");
- else if (mode == AT_MOST)
- sb.append("AT_MOST ");
- else
- sb.append(mode).append(" ");
-
- sb.append(size);
- return sb.toString();
- }
- }
-
- class CheckForLongPress implements Runnable {
-
- private int mOriginalWindowAttachCount;
-
- public void run() {
- if (isPressed() && (mParent != null) && hasWindowFocus()
- && mOriginalWindowAttachCount == mWindowAttachCount) {
- if (performLongClick()) {
- mHasPerformedLongPress = true;
- }
- }
- }
-
- public void rememberWindowAttachCount() {
- mOriginalWindowAttachCount = mWindowAttachCount;
- }
- }
-
- /**
- * Interface definition for a callback to be invoked when a key event is
- * dispatched to this view. The callback will be invoked before the key
- * event is given to the view.
- */
- public interface OnKeyListener {
- /**
- * Called when a key is dispatched to a view. This allows listeners to
- * get a chance to respond before the target view.
- *
- * @param v The view the key has been dispatched to.
- * @param keyCode The code for the physical key that was pressed
- * @param event The KeyEvent object containing full information about
- * the event.
- * @return True if the listener has consumed the event, false otherwise.
- */
- boolean onKey(View v, int keyCode, KeyEvent event);
- }
-
- /**
- * Interface definition for a callback to be invoked when a touch event is
- * dispatched to this view. The callback will be invoked before the touch
- * event is given to the view.
- */
- public interface OnTouchListener {
- /**
- * Called when a touch event is dispatched to a view. This allows listeners to
- * get a chance to respond before the target view.
- *
- * @param v The view the touch event has been dispatched to.
- * @param event The MotionEvent object containing full information about
- * the event.
- * @return True if the listener has consumed the event, false otherwise.
- */
- boolean onTouch(View v, MotionEvent event);
- }
-
- /**
- * Interface definition for a callback to be invoked when a view has been clicked and held.
- */
- public interface OnLongClickListener {
- /**
- * Called when a view has been clicked and held.
- *
- * @param v The view that was clicked and held.
- *
- * return True if the callback consumed the long click, false otherwise
- */
- boolean onLongClick(View v);
- }
-
- /**
- * Interface definition for a callback to be invoked when the focus state of
- * a view changed.
- */
- public interface OnFocusChangeListener {
- /**
- * Called when the focus state of a view has changed.
- *
- * @param v The view whose state has changed.
- * @param hasFocus The new focus state of v.
- */
- void onFocusChange(View v, boolean hasFocus);
- }
-
- /**
- * Interface definition for a callback to be invoked when a view is clicked.
- */
- public interface OnClickListener {
- /**
- * Called when a view has been clicked.
- *
- * @param v The view that was clicked.
- */
- void onClick(View v);
- }
-
- /**
- * Interface definition for a callback to be invoked when the context menu
- * for this view is being built.
- */
- public interface OnCreateContextMenuListener {
- /**
- * Called when the context menu for this view is being built. It is not
- * safe to hold onto the menu after this method returns.
- *
- * @param menu The context menu that is being built
- * @param v The view for which the context menu is being built
- * @param menuInfo Extra information about the item for which the
- * context menu should be shown. This information will vary
- * depending on the class of v.
- */
- void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
- }
-
- private final class UnsetPressedState implements Runnable {
- public void run() {
- setPressed(false);
- }
- }
-
- /**
- * Base class for derived classes that want to save and restore their own
- * state in {@link android.view.View#onSaveInstanceState()}.
- */
- public static class BaseSavedState extends AbsSavedState {
- /**
- * Constructor used when reading from a parcel. Reads the state of the superclass.
- *
- * @param source
- */
- public BaseSavedState(Parcel source) {
- super(source);
- }
-
- /**
- * Constructor called by derived classes when creating their SavedState objects
- *
- * @param superState The state of the superclass of this view
- */
- public BaseSavedState(Parcelable superState) {
- super(superState);
- }
-
- public static final Parcelable.Creator<BaseSavedState> CREATOR =
- new Parcelable.Creator<BaseSavedState>() {
- public BaseSavedState createFromParcel(Parcel in) {
- return new BaseSavedState(in);
- }
-
- public BaseSavedState[] newArray(int size) {
- return new BaseSavedState[size];
- }
- };
- }
-
- /**
- * A set of information given to a view when it is attached to its parent
- * window.
- */
- static class AttachInfo {
-
- interface Callbacks {
- void playSoundEffect(int effectId);
- boolean performHapticFeedback(int effectId, boolean always);
- }
-
- /**
- * InvalidateInfo is used to post invalidate(int, int, int, int) messages
- * to a Handler. This class contains the target (View) to invalidate and
- * the coordinates of the dirty rectangle.
- *
- * For performance purposes, this class also implements a pool of up to
- * POOL_LIMIT objects that get reused. This reduces memory allocations
- * whenever possible.
- *
- * The pool is implemented as a linked list of InvalidateInfo object with
- * the root pointing to the next available InvalidateInfo. If the root
- * is null (i.e. when all instances from the pool have been acquired),
- * then a new InvalidateInfo is created and returned to the caller.
- *
- * An InvalidateInfo is sent back to the pool by calling its release()
- * method. If the pool is full the object is simply discarded.
- *
- * This implementation follows the object pool pattern used in the
- * MotionEvent class.
- */
- static class InvalidateInfo {
- private static final int POOL_LIMIT = 10;
- private static final Object sLock = new Object();
-
- private static int sAcquiredCount = 0;
- private static InvalidateInfo sRoot;
-
- private InvalidateInfo next;
-
- View target;
-
- int left;
- int top;
- int right;
- int bottom;
-
- static InvalidateInfo acquire() {
- synchronized (sLock) {
- if (sRoot == null) {
- return new InvalidateInfo();
- }
-
- InvalidateInfo info = sRoot;
- sRoot = info.next;
- sAcquiredCount--;
-
- return info;
- }
- }
-
- void release() {
- synchronized (sLock) {
- if (sAcquiredCount < POOL_LIMIT) {
- sAcquiredCount++;
- next = sRoot;
- sRoot = this;
- }
- }
- }
- }
-
- final IWindowSession mSession;
-
- final IWindow mWindow;
-
- final IBinder mWindowToken;
-
- final Callbacks mRootCallbacks;
-
- /**
- * The top view of the hierarchy.
- */
- View mRootView;
-
- IBinder mPanelParentWindowToken;
- Surface mSurface;
-
- /**
- * Left position of this view's window
- */
- int mWindowLeft;
-
- /**
- * Top position of this view's window
- */
- int mWindowTop;
-
- /**
- * For windows that are full-screen but using insets to layout inside
- * of the screen decorations, these are the current insets for the
- * content of the window.
- */
- final Rect mContentInsets = new Rect();
-
- /**
- * For windows that are full-screen but using insets to layout inside
- * of the screen decorations, these are the current insets for the
- * actual visible parts of the window.
- */
- final Rect mVisibleInsets = new Rect();
-
- /**
- * The internal insets given by this window. This value is
- * supplied by the client (through
- * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
- * be given to the window manager when changed to be used in laying
- * out windows behind it.
- */
- final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
- = new ViewTreeObserver.InternalInsetsInfo();
-
- /**
- * All views in the window's hierarchy that serve as scroll containers,
- * used to determine if the window can be resized or must be panned
- * to adjust for a soft input area.
- */
- final ArrayList<View> mScrollContainers = new ArrayList<View>();
-
- /**
- * Indicates whether the view's window currently has the focus.
- */
- boolean mHasWindowFocus;
-
- /**
- * The current visibility of the window.
- */
- int mWindowVisibility;
-
- /**
- * Indicates the time at which drawing started to occur.
- */
- long mDrawingTime;
-
- /**
- * Indicates whether the view's window is currently in touch mode.
- */
- boolean mInTouchMode;
-
- /**
- * Indicates that ViewRoot should trigger a global layout change
- * the next time it performs a traversal
- */
- boolean mRecomputeGlobalAttributes;
-
- /**
- * Set to true when attributes (like mKeepScreenOn) need to be
- * recomputed.
- */
- boolean mAttributesChanged;
-
- /**
- * Set during a traveral if any views want to keep the screen on.
- */
- boolean mKeepScreenOn;
-
- /**
- * Set if the visibility of any views has changed.
- */
- boolean mViewVisibilityChanged;
-
- /**
- * Set to true if a view has been scrolled.
- */
- boolean mViewScrollChanged;
-
- /**
- * Global to the view hierarchy used as a temporary for dealing with
- * x/y points in the transparent region computations.
- */
- final int[] mTransparentLocation = new int[2];
-
- /**
- * Global to the view hierarchy used as a temporary for dealing with
- * x/y points in the ViewGroup.invalidateChild implementation.
- */
- final int[] mInvalidateChildLocation = new int[2];
-
- /**
- * The view tree observer used to dispatch global events like
- * layout, pre-draw, touch mode change, etc.
- */
- final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
-
- /**
- * A Canvas used by the view hierarchy to perform bitmap caching.
- */
- Canvas mCanvas;
-
- /**
- * A Handler supplied by a view's {@link android.view.ViewRoot}. This
- * handler can be used to pump events in the UI events queue.
- */
- final Handler mHandler;
-
- /**
- * Identifier for messages requesting the view to be invalidated.
- * Such messages should be sent to {@link #mHandler}.
- */
- static final int INVALIDATE_MSG = 0x1;
-
- /**
- * Identifier for messages requesting the view to invalidate a region.
- * Such messages should be sent to {@link #mHandler}.
- */
- static final int INVALIDATE_RECT_MSG = 0x2;
-
- /**
- * Temporary for use in computing invalidate rectangles while
- * calling up the hierarchy.
- */
- final Rect mTmpInvalRect = new Rect();
-
- /**
- * Creates a new set of attachment information with the specified
- * events handler and thread.
- *
- * @param handler the events handler the view must use
- */
- AttachInfo(IWindowSession session, IWindow window,
- Handler handler, Callbacks effectPlayer) {
- mSession = session;
- mWindow = window;
- mWindowToken = window.asBinder();
- mHandler = handler;
- mRootCallbacks = effectPlayer;
- }
- }
-
- /**
- * <p>ScrollabilityCache holds various fields used by a View when scrolling
- * is supported. This avoids keeping too many unused fields in most
- * instances of View.</p>
- */
- private static class ScrollabilityCache {
- public int fadingEdgeLength;
-
- public int scrollBarSize;
- public ScrollBarDrawable scrollBar;
-
- public final Paint paint;
- public final Matrix matrix;
- public Shader shader;
-
- private int mLastColor;
-
- public ScrollabilityCache(ViewConfiguration configuration) {
- fadingEdgeLength = configuration.getScaledFadingEdgeLength();
- scrollBarSize = configuration.getScaledScrollBarSize();
-
- paint = new Paint();
- matrix = new Matrix();
- // use use a height of 1, and then wack the matrix each time we
- // actually use it.
- shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
-
- paint.setShader(shader);
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
- }
-
- public void setFadeColor(int color) {
- if (color != 0 && color != mLastColor) {
- mLastColor = color;
- color |= 0xFF000000;
-
- shader = new LinearGradient(0, 0, 0, 1, color, 0, Shader.TileMode.CLAMP);
-
- paint.setShader(shader);
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
- }
- }
- }
-}
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
deleted file mode 100644
index 2f7b0d1..0000000
--- a/core/java/android/view/ViewConfiguration.java
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.content.Context;
-import android.util.DisplayMetrics;
-import android.util.SparseArray;
-
-/**
- * Contains methods to standard constants used in the UI for timeouts, sizes, and distances.
- */
-public class ViewConfiguration {
- /**
- * Defines the width of the horizontal scrollbar and the height of the vertical scrollbar in
- * pixels
- */
- private static final int SCROLL_BAR_SIZE = 10;
-
- /**
- * Defines the length of the fading edges in pixels
- */
- private static final int FADING_EDGE_LENGTH = 12;
-
- /**
- * Defines the duration in milliseconds of the pressed state in child
- * components.
- */
- private static final int PRESSED_STATE_DURATION = 85;
-
- /**
- * Defines the duration in milliseconds before a press turns into
- * a long press
- */
- private static final int LONG_PRESS_TIMEOUT = 500;
-
- /**
- * Defines the duration in milliseconds a user needs to hold down the
- * appropriate button to bring up the global actions dialog (power off,
- * lock screen, etc).
- */
- private static final int GLOBAL_ACTIONS_KEY_TIMEOUT = 500;
-
- /**
- * Defines the duration in milliseconds we will wait to see if a touch event
- * is a top or a scroll. If the user does not move within this interval, it is
- * considered to be a tap.
- */
- private static final int TAP_TIMEOUT = 100;
-
- /**
- * Defines the duration in milliseconds we will wait to see if a touch event
- * is a jump tap. If the user does not complete the jump tap within this interval, it is
- * considered to be a tap.
- */
- private static final int JUMP_TAP_TIMEOUT = 500;
-
- /**
- * Defines the duration in milliseconds between the first tap's up event and
- * the second tap's down event for an interaction to be considered a
- * double-tap.
- */
- private static final int DOUBLE_TAP_TIMEOUT = 300;
-
- /**
- * Defines the duration in milliseconds we want to display zoom controls in response
- * to a user panning within an application.
- */
- private static final int ZOOM_CONTROLS_TIMEOUT = 3000;
-
- /**
- * Inset in pixels to look for touchable content when the user touches the edge of the screen
- */
- private static final int EDGE_SLOP = 12;
-
- /**
- * Distance a touch can wander before we think the user is scrolling in pixels
- */
- private static final int TOUCH_SLOP = 25;
-
- /**
- * Distance between the first touch and second touch to still be considered a double tap
- */
- private static final int DOUBLE_TAP_SLOP = 100;
-
- /**
- * Distance a touch needs to be outside of a window's bounds for it to
- * count as outside for purposes of dismissing the window.
- */
- private static final int WINDOW_TOUCH_SLOP = 16;
-
- /**
- * Minimum velocity to initiate a fling, as measured in pixels per second
- */
- private static final int MINIMUM_FLING_VELOCITY = 50;
-
- /**
- * The maximum size of View's drawing cache, expressed in bytes. This size
- * should be at least equal to the size of the screen in ARGB888 format.
- */
- @Deprecated
- private static final int MAXIMUM_DRAWING_CACHE_SIZE = 320 * 480 * 4; // HVGA screen, ARGB8888
-
- /**
- * The coefficient of friction applied to flings/scrolls.
- */
- private static float SCROLL_FRICTION = 0.015f;
-
- private final int mEdgeSlop;
- private final int mFadingEdgeLength;
- private final int mMinimumFlingVelocity;
- private final int mScrollbarSize;
- private final int mTouchSlop;
- private final int mDoubleTapSlop;
- private final int mWindowTouchSlop;
- private final int mMaximumDrawingCacheSize;
-
- private static final SparseArray<ViewConfiguration> sConfigurations =
- new SparseArray<ViewConfiguration>(2);
-
- /**
- * @deprecated Use {@link android.view.ViewConfiguration#get(android.content.Context)} instead.
- */
- @Deprecated
- public ViewConfiguration() {
- mEdgeSlop = EDGE_SLOP;
- mFadingEdgeLength = FADING_EDGE_LENGTH;
- mMinimumFlingVelocity = MINIMUM_FLING_VELOCITY;
- mScrollbarSize = SCROLL_BAR_SIZE;
- mTouchSlop = TOUCH_SLOP;
- mDoubleTapSlop = DOUBLE_TAP_SLOP;
- mWindowTouchSlop = WINDOW_TOUCH_SLOP;
- //noinspection deprecation
- mMaximumDrawingCacheSize = MAXIMUM_DRAWING_CACHE_SIZE;
- }
-
- /**
- * Creates a new configuration for the specified context. The configuration depends on
- * various parameters of the context, like the dimension of the display or the density
- * of the display.
- *
- * @param context The application context used to initialize this view configuration.
- *
- * @see #get(android.content.Context)
- * @see android.util.DisplayMetrics
- */
- private ViewConfiguration(Context context) {
- final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
- final float density = metrics.density;
-
- mEdgeSlop = (int) (density * EDGE_SLOP + 0.5f);
- mFadingEdgeLength = (int) (density * FADING_EDGE_LENGTH + 0.5f);
- mMinimumFlingVelocity = (int) (density * MINIMUM_FLING_VELOCITY + 0.5f);
- mScrollbarSize = (int) (density * SCROLL_BAR_SIZE + 0.5f);
- mTouchSlop = (int) (density * TOUCH_SLOP + 0.5f);
- mDoubleTapSlop = (int) (density * DOUBLE_TAP_SLOP + 0.5f);
- mWindowTouchSlop = (int) (density * WINDOW_TOUCH_SLOP + 0.5f);
-
- // Size of the screen in bytes, in ARGB_8888 format
- mMaximumDrawingCacheSize = 4 * metrics.widthPixels * metrics.heightPixels;
- }
-
- /**
- * Returns a configuration for the specified context. The configuration depends on
- * various parameters of the context, like the dimension of the display or the
- * density of the display.
- *
- * @param context The application context used to initialize the view configuration.
- */
- public static ViewConfiguration get(Context context) {
- final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
- final int density = (int) (100.0f * metrics.density);
-
- ViewConfiguration configuration = sConfigurations.get(density);
- if (configuration == null) {
- configuration = new ViewConfiguration(context);
- sConfigurations.put(density, configuration);
- }
-
- return configuration;
- }
-
- /**
- * @return The width of the horizontal scrollbar and the height of the vertical
- * scrollbar in pixels
- *
- * @deprecated Use {@link #getScaledScrollBarSize()} instead.
- */
- @Deprecated
- public static int getScrollBarSize() {
- return SCROLL_BAR_SIZE;
- }
-
- /**
- * @return The width of the horizontal scrollbar and the height of the vertical
- * scrollbar in pixels
- */
- public int getScaledScrollBarSize() {
- return mScrollbarSize;
- }
-
- /**
- * @return Defines the length of the fading edges in pixels
- *
- * @deprecated Use {@link #getScaledFadingEdgeLength()} instead.
- */
- @Deprecated
- public static int getFadingEdgeLength() {
- return FADING_EDGE_LENGTH;
- }
-
- /**
- * @return Defines the length of the fading edges in pixels
- */
- public int getScaledFadingEdgeLength() {
- return mFadingEdgeLength;
- }
-
- /**
- * @return Defines the duration in milliseconds of the pressed state in child
- * components.
- */
- public static int getPressedStateDuration() {
- return PRESSED_STATE_DURATION;
- }
-
- /**
- * @return Defines the duration in milliseconds before a press turns into
- * a long press
- */
- public static int getLongPressTimeout() {
- return LONG_PRESS_TIMEOUT;
- }
-
- /**
- * @return Defines the duration in milliseconds we will wait to see if a touch event
- * is a top or a scroll. If the user does not move within this interval, it is
- * considered to be a tap.
- */
- public static int getTapTimeout() {
- return TAP_TIMEOUT;
- }
-
- /**
- * @return Defines the duration in milliseconds we will wait to see if a touch event
- * is a jump tap. If the user does not move within this interval, it is
- * considered to be a tap.
- */
- public static int getJumpTapTimeout() {
- return JUMP_TAP_TIMEOUT;
- }
-
- /**
- * @return Defines the duration in milliseconds between the first tap's up event and
- * the second tap's down event for an interaction to be considered a
- * double-tap.
- * @hide pending API council
- */
- public static int getDoubleTapTimeout() {
- return DOUBLE_TAP_TIMEOUT;
- }
-
- /**
- * @return Inset in pixels to look for touchable content when the user touches the edge of the
- * screen
- *
- * @deprecated Use {@link #getScaledEdgeSlop()} instead.
- */
- @Deprecated
- public static int getEdgeSlop() {
- return EDGE_SLOP;
- }
-
- /**
- * @return Inset in pixels to look for touchable content when the user touches the edge of the
- * screen
- */
- public int getScaledEdgeSlop() {
- return mEdgeSlop;
- }
-
- /**
- * @return Distance a touch can wander before we think the user is scrolling in pixels
- *
- * @deprecated Use {@link #getScaledTouchSlop()} instead.
- */
- @Deprecated
- public static int getTouchSlop() {
- return TOUCH_SLOP;
- }
-
- /**
- * @return Distance a touch can wander before we think the user is scrolling in pixels
- */
- public int getScaledTouchSlop() {
- return mTouchSlop;
- }
-
- /**
- * @return Distance between the first touch and second touch to still be
- * considered a double tap
- * @deprecated Use {@link #getScaledDoubleTapSlop()} instead.
- * @hide The only client of this should be GestureDetector, which needs this
- * for clients that still use its deprecated constructor.
- */
- @Deprecated
- public static int getDoubleTapSlop() {
- return DOUBLE_TAP_SLOP;
- }
-
- /**
- * @return Distance between the first touch and second touch to still be
- * considered a double tap
- * @hide pending API council
- */
- public int getScaledDoubleTapSlop() {
- return mDoubleTapSlop;
- }
-
- /**
- * @return Distance a touch must be outside the bounds of a window for it
- * to be counted as outside the window for purposes of dismissing that
- * window.
- *
- * @deprecated Use {@link #getScaledWindowTouchSlop()} instead.
- */
- @Deprecated
- public static int getWindowTouchSlop() {
- return WINDOW_TOUCH_SLOP;
- }
-
- /**
- * @return Distance a touch must be outside the bounds of a window for it
- * to be counted as outside the window for purposes of dismissing that
- * window.
- */
- public int getScaledWindowTouchSlop() {
- return mWindowTouchSlop;
- }
-
- /**
- * @return Minimum velocity to initiate a fling, as measured in pixels per second.
- *
- * @deprecated Use {@link #getScaledMinimumFlingVelocity()} instead.
- */
- @Deprecated
- public static int getMinimumFlingVelocity() {
- return MINIMUM_FLING_VELOCITY;
- }
-
- /**
- * @return Minimum velocity to initiate a fling, as measured in pixels per second.
- */
- public int getScaledMinimumFlingVelocity() {
- return mMinimumFlingVelocity;
- }
-
- /**
- * The maximum drawing cache size expressed in bytes.
- *
- * @return the maximum size of View's drawing cache expressed in bytes
- *
- * @deprecated Use {@link #getScaledMaximumDrawingCacheSize()} instead.
- */
- @Deprecated
- public static int getMaximumDrawingCacheSize() {
- //noinspection deprecation
- return MAXIMUM_DRAWING_CACHE_SIZE;
- }
-
- /**
- * The maximum drawing cache size expressed in bytes.
- *
- * @return the maximum size of View's drawing cache expressed in bytes
- */
- public int getScaledMaximumDrawingCacheSize() {
- return mMaximumDrawingCacheSize;
- }
-
- /**
- * The amount of time that the zoom controls should be
- * displayed on the screen expressed in milliseconds.
- *
- * @return the time the zoom controls should be visible expressed
- * in milliseconds.
- */
- public static long getZoomControlsTimeout() {
- return ZOOM_CONTROLS_TIMEOUT;
- }
-
- /**
- * The amount of time a user needs to press the relevant key to bring up
- * the global actions dialog.
- *
- * @return how long a user needs to press the relevant key to bring up
- * the global actions dialog.
- */
- public static long getGlobalActionKeyTimeout() {
- return GLOBAL_ACTIONS_KEY_TIMEOUT;
- }
-
- /**
- * The amount of friction applied to scrolls and flings.
- *
- * @return A scalar dimensionless value representing the coefficient of
- * friction.
- */
- public static float getScrollFriction() {
- return SCROLL_FRICTION;
- }
-}
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
deleted file mode 100644
index 883c7bd..0000000
--- a/core/java/android/view/ViewDebug.java
+++ /dev/null
@@ -1,1128 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.util.Log;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.os.Environment;
-
-import java.io.File;
-import java.io.BufferedWriter;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.FileOutputStream;
-import java.io.DataOutputStream;
-import java.io.OutputStreamWriter;
-import java.io.BufferedOutputStream;
-import java.io.OutputStream;
-import java.util.List;
-import java.util.LinkedList;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.lang.annotation.Target;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
-
-/**
- * Various debugging/tracing tools related to {@link View} and the view hierarchy.
- */
-public class ViewDebug {
- /**
- * Enables or disables view hierarchy tracing. Any invoker of
- * {@link #trace(View, android.view.ViewDebug.HierarchyTraceType)} should first
- * check that this value is set to true as not to affect performance.
- */
- public static final boolean TRACE_HIERARCHY = false;
-
- /**
- * Enables or disables view recycler tracing. Any invoker of
- * {@link #trace(View, android.view.ViewDebug.RecyclerTraceType, int[])} should first
- * check that this value is set to true as not to affect performance.
- */
- public static final boolean TRACE_RECYCLER = false;
-
- /**
- * The system property of dynamic switch for capturing view information
- * when it is set, we dump interested fields and methods for the view on focus
- */
- static final String SYSTEM_PROPERTY_CAPTURE_VIEW = "debug.captureview";
-
- /**
- * The system property of dynamic switch for capturing event information
- * when it is set, we log key events, touch/motion and trackball events
- */
- static final String SYSTEM_PROPERTY_CAPTURE_EVENT = "debug.captureevent";
-
- /**
- * This annotation can be used to mark fields and methods to be dumped by
- * the view server. Only non-void methods with no arguments can be annotated
- * by this annotation.
- */
- @Target({ ElementType.FIELD, ElementType.METHOD })
- @Retention(RetentionPolicy.RUNTIME)
- public @interface ExportedProperty {
- /**
- * When resolveId is true, and if the annotated field/method return value
- * is an int, the value is converted to an Android's resource name.
- *
- * @return true if the property's value must be transformed into an Android
- * resource name, false otherwise
- */
- boolean resolveId() default false;
-
- /**
- * A mapping can be defined to map int values to specific strings. For
- * instance, View.getVisibility() returns 0, 4 or 8. However, these values
- * actually mean VISIBLE, INVISIBLE and GONE. A mapping can be used to see
- * these human readable values:
- *
- * <pre>
- * @ViewDebug.ExportedProperty(mapping = {
- * @ViewDebug.IntToString(from = 0, to = "VISIBLE"),
- * @ViewDebug.IntToString(from = 4, to = "INVISIBLE"),
- * @ViewDebug.IntToString(from = 8, to = "GONE")
- * })
- * public int getVisibility() { ...
- * <pre>
- *
- * @return An array of int to String mappings
- *
- * @see android.view.ViewDebug.IntToString
- */
- IntToString[] mapping() default { };
-
- /**
- * When deep export is turned on, this property is not dumped. Instead, the
- * properties contained in this property are dumped. Each child property
- * is prefixed with the name of this property.
- *
- * @return true if the properties of this property should be dumped
- *
- * @see #prefix()
- */
- boolean deepExport() default false;
-
- /**
- * The prefix to use on child properties when deep export is enabled
- *
- * @return a prefix as a String
- *
- * @see #deepExport()
- */
- String prefix() default "";
- }
-
- /**
- * Defines a mapping from an int value to a String. Such a mapping can be used
- * in a @ExportedProperty to provide more meaningful values to the end user.
- *
- * @see android.view.ViewDebug.ExportedProperty
- */
- @Target({ ElementType.TYPE })
- @Retention(RetentionPolicy.RUNTIME)
- public @interface IntToString {
- /**
- * The original int value to map to a String.
- *
- * @return An arbitrary int value.
- */
- int from();
-
- /**
- * The String to use in place of the original int value.
- *
- * @return An arbitrary non-null String.
- */
- String to();
- }
-
- /**
- * This annotation can be used to mark fields and methods to be dumped when
- * the view is captured. Methods with this annotation must have no arguments
- * and must return <some type of data>.
- *
- * @hide pending API Council approval
- */
- @Target({ ElementType.FIELD, ElementType.METHOD })
- @Retention(RetentionPolicy.RUNTIME)
- public @interface CapturedViewProperty {
- /**
- * When retrieveReturn is true, we need to retrieve second level methods
- * e.g., we need myView.getFirstLevelMethod().getSecondLevelMethod()
- * we will set retrieveReturn = true on the annotation of
- * myView.getFirstLevelMethod()
- * @return true if we need the second level methods
- */
- boolean retrieveReturn() default false;
- }
-
- private static HashMap<Class<?>, Method[]> mCapturedViewMethodsForClasses = null;
- private static HashMap<Class<?>, Field[]> mCapturedViewFieldsForClasses = null;
-
- // Maximum delay in ms after which we stop trying to capture a View's drawing
- private static final int CAPTURE_TIMEOUT = 4000;
-
- private static final String REMOTE_COMMAND_CAPTURE = "CAPTURE";
- private static final String REMOTE_COMMAND_DUMP = "DUMP";
- private static final String REMOTE_COMMAND_INVALIDATE = "INVALIDATE";
- private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT";
-
- private static HashMap<Class<?>, Field[]> sFieldsForClasses;
- private static HashMap<Class<?>, Method[]> sMethodsForClasses;
-
- /**
- * Defines the type of hierarhcy trace to output to the hierarchy traces file.
- */
- public enum HierarchyTraceType {
- INVALIDATE,
- INVALIDATE_CHILD,
- INVALIDATE_CHILD_IN_PARENT,
- REQUEST_LAYOUT,
- ON_LAYOUT,
- ON_MEASURE,
- DRAW,
- BUILD_CACHE
- }
-
- private static BufferedWriter sHierarchyTraces;
- private static ViewRoot sHierarhcyRoot;
- private static String sHierarchyTracePrefix;
-
- /**
- * Defines the type of recycler trace to output to the recycler traces file.
- */
- public enum RecyclerTraceType {
- NEW_VIEW,
- BIND_VIEW,
- RECYCLE_FROM_ACTIVE_HEAP,
- RECYCLE_FROM_SCRAP_HEAP,
- MOVE_TO_ACTIVE_HEAP,
- MOVE_TO_SCRAP_HEAP,
- MOVE_FROM_ACTIVE_TO_SCRAP_HEAP
- }
-
- private static class RecyclerTrace {
- public int view;
- public RecyclerTraceType type;
- public int position;
- public int indexOnScreen;
- }
-
- private static View sRecyclerOwnerView;
- private static List<View> sRecyclerViews;
- private static List<RecyclerTrace> sRecyclerTraces;
- private static String sRecyclerTracePrefix;
-
- /**
- * Returns the number of instanciated Views.
- *
- * @return The number of Views instanciated in the current process.
- *
- * @hide
- */
- public static long getViewInstanceCount() {
- return View.sInstanceCount;
- }
-
- /**
- * Returns the number of instanciated ViewRoots.
- *
- * @return The number of ViewRoots instanciated in the current process.
- *
- * @hide
- */
- public static long getViewRootInstanceCount() {
- return ViewRoot.getInstanceCount();
- }
-
- /**
- * Outputs a trace to the currently opened recycler traces. The trace records the type of
- * recycler action performed on the supplied view as well as a number of parameters.
- *
- * @param view the view to trace
- * @param type the type of the trace
- * @param parameters parameters depending on the type of the trace
- */
- public static void trace(View view, RecyclerTraceType type, int... parameters) {
- if (sRecyclerOwnerView == null || sRecyclerViews == null) {
- return;
- }
-
- if (!sRecyclerViews.contains(view)) {
- sRecyclerViews.add(view);
- }
-
- final int index = sRecyclerViews.indexOf(view);
-
- RecyclerTrace trace = new RecyclerTrace();
- trace.view = index;
- trace.type = type;
- trace.position = parameters[0];
- trace.indexOnScreen = parameters[1];
-
- sRecyclerTraces.add(trace);
- }
-
- /**
- * Starts tracing the view recycler of the specified view. The trace is identified by a prefix,
- * used to build the traces files names: <code>/EXTERNAL/view-recycler/PREFIX.traces</code> and
- * <code>/EXTERNAL/view-recycler/PREFIX.recycler</code>.
- *
- * Only one view recycler can be traced at the same time. After calling this method, any
- * other invocation will result in a <code>IllegalStateException</code> unless
- * {@link #stopRecyclerTracing()} is invoked before.
- *
- * Traces files are created only after {@link #stopRecyclerTracing()} is invoked.
- *
- * This method will return immediately if TRACE_RECYCLER is false.
- *
- * @param prefix the traces files name prefix
- * @param view the view whose recycler must be traced
- *
- * @see #stopRecyclerTracing()
- * @see #trace(View, android.view.ViewDebug.RecyclerTraceType, int[])
- */
- public static void startRecyclerTracing(String prefix, View view) {
- //noinspection PointlessBooleanExpression,ConstantConditions
- if (!TRACE_RECYCLER) {
- return;
- }
-
- if (sRecyclerOwnerView != null) {
- throw new IllegalStateException("You must call stopRecyclerTracing() before running" +
- " a new trace!");
- }
-
- sRecyclerTracePrefix = prefix;
- sRecyclerOwnerView = view;
- sRecyclerViews = new ArrayList<View>();
- sRecyclerTraces = new LinkedList<RecyclerTrace>();
- }
-
- /**
- * Stops the current view recycer tracing.
- *
- * Calling this method creates the file <code>/EXTERNAL/view-recycler/PREFIX.traces</code>
- * containing all the traces (or method calls) relative to the specified view's recycler.
- *
- * Calling this method creates the file <code>/EXTERNAL/view-recycler/PREFIX.recycler</code>
- * containing all of the views used by the recycler of the view supplied to
- * {@link #startRecyclerTracing(String, View)}.
- *
- * This method will return immediately if TRACE_RECYCLER is false.
- *
- * @see #startRecyclerTracing(String, View)
- * @see #trace(View, android.view.ViewDebug.RecyclerTraceType, int[])
- */
- public static void stopRecyclerTracing() {
- //noinspection PointlessBooleanExpression,ConstantConditions
- if (!TRACE_RECYCLER) {
- return;
- }
-
- if (sRecyclerOwnerView == null || sRecyclerViews == null) {
- throw new IllegalStateException("You must call startRecyclerTracing() before" +
- " stopRecyclerTracing()!");
- }
-
- File recyclerDump = new File(Environment.getExternalStorageDirectory(), "view-recycler/");
- recyclerDump.mkdirs();
-
- recyclerDump = new File(recyclerDump, sRecyclerTracePrefix + ".recycler");
- try {
- final BufferedWriter out = new BufferedWriter(new FileWriter(recyclerDump), 8 * 1024);
-
- for (View view : sRecyclerViews) {
- final String name = view.getClass().getName();
- out.write(name);
- out.newLine();
- }
-
- out.close();
- } catch (IOException e) {
- Log.e("View", "Could not dump recycler content");
- return;
- }
-
- recyclerDump = new File(Environment.getExternalStorageDirectory(), "view-recycler/");
- recyclerDump = new File(recyclerDump, sRecyclerTracePrefix + ".traces");
- try {
- final FileOutputStream file = new FileOutputStream(recyclerDump);
- final DataOutputStream out = new DataOutputStream(file);
-
- for (RecyclerTrace trace : sRecyclerTraces) {
- out.writeInt(trace.view);
- out.writeInt(trace.type.ordinal());
- out.writeInt(trace.position);
- out.writeInt(trace.indexOnScreen);
- out.flush();
- }
-
- out.close();
- } catch (IOException e) {
- Log.e("View", "Could not dump recycler traces");
- return;
- }
-
- sRecyclerViews.clear();
- sRecyclerViews = null;
-
- sRecyclerTraces.clear();
- sRecyclerTraces = null;
-
- sRecyclerOwnerView = null;
- }
-
- /**
- * Outputs a trace to the currently opened traces file. The trace contains the class name
- * and instance's hashcode of the specified view as well as the supplied trace type.
- *
- * @param view the view to trace
- * @param type the type of the trace
- */
- public static void trace(View view, HierarchyTraceType type) {
- if (sHierarchyTraces == null) {
- return;
- }
-
- try {
- sHierarchyTraces.write(type.name());
- sHierarchyTraces.write(' ');
- sHierarchyTraces.write(view.getClass().getName());
- sHierarchyTraces.write('@');
- sHierarchyTraces.write(Integer.toHexString(view.hashCode()));
- sHierarchyTraces.newLine();
- } catch (IOException e) {
- Log.w("View", "Error while dumping trace of type " + type + " for view " + view);
- }
- }
-
- /**
- * Starts tracing the view hierarchy of the specified view. The trace is identified by a prefix,
- * used to build the traces files names: <code>/EXTERNAL/view-hierarchy/PREFIX.traces</code> and
- * <code>/EXTERNAL/view-hierarchy/PREFIX.tree</code>.
- *
- * Only one view hierarchy can be traced at the same time. After calling this method, any
- * other invocation will result in a <code>IllegalStateException</code> unless
- * {@link #stopHierarchyTracing()} is invoked before.
- *
- * Calling this method creates the file <code>/EXTERNAL/view-hierarchy/PREFIX.traces</code>
- * containing all the traces (or method calls) relative to the specified view's hierarchy.
- *
- * This method will return immediately if TRACE_HIERARCHY is false.
- *
- * @param prefix the traces files name prefix
- * @param view the view whose hierarchy must be traced
- *
- * @see #stopHierarchyTracing()
- * @see #trace(View, android.view.ViewDebug.HierarchyTraceType)
- */
- public static void startHierarchyTracing(String prefix, View view) {
- //noinspection PointlessBooleanExpression,ConstantConditions
- if (!TRACE_HIERARCHY) {
- return;
- }
-
- if (sHierarhcyRoot != null) {
- throw new IllegalStateException("You must call stopHierarchyTracing() before running" +
- " a new trace!");
- }
-
- File hierarchyDump = new File(Environment.getExternalStorageDirectory(), "view-hierarchy/");
- hierarchyDump.mkdirs();
-
- hierarchyDump = new File(hierarchyDump, prefix + ".traces");
- sHierarchyTracePrefix = prefix;
-
- try {
- sHierarchyTraces = new BufferedWriter(new FileWriter(hierarchyDump), 8 * 1024);
- } catch (IOException e) {
- Log.e("View", "Could not dump view hierarchy");
- return;
- }
-
- sHierarhcyRoot = (ViewRoot) view.getRootView().getParent();
- }
-
- /**
- * Stops the current view hierarchy tracing. This method closes the file
- * <code>/EXTERNAL/view-hierarchy/PREFIX.traces</code>.
- *
- * Calling this method creates the file <code>/EXTERNAL/view-hierarchy/PREFIX.tree</code>
- * containing the view hierarchy of the view supplied to
- * {@link #startHierarchyTracing(String, View)}.
- *
- * This method will return immediately if TRACE_HIERARCHY is false.
- *
- * @see #startHierarchyTracing(String, View)
- * @see #trace(View, android.view.ViewDebug.HierarchyTraceType)
- */
- public static void stopHierarchyTracing() {
- //noinspection PointlessBooleanExpression,ConstantConditions
- if (!TRACE_HIERARCHY) {
- return;
- }
-
- if (sHierarhcyRoot == null || sHierarchyTraces == null) {
- throw new IllegalStateException("You must call startHierarchyTracing() before" +
- " stopHierarchyTracing()!");
- }
-
- try {
- sHierarchyTraces.close();
- } catch (IOException e) {
- Log.e("View", "Could not write view traces");
- }
- sHierarchyTraces = null;
-
- File hierarchyDump = new File(Environment.getExternalStorageDirectory(), "view-hierarchy/");
- hierarchyDump.mkdirs();
- hierarchyDump = new File(hierarchyDump, sHierarchyTracePrefix + ".tree");
-
- BufferedWriter out;
- try {
- out = new BufferedWriter(new FileWriter(hierarchyDump), 8 * 1024);
- } catch (IOException e) {
- Log.e("View", "Could not dump view hierarchy");
- return;
- }
-
- View view = sHierarhcyRoot.getView();
- if (view instanceof ViewGroup) {
- ViewGroup group = (ViewGroup) view;
- dumpViewHierarchy(group, out, 0);
- try {
- out.close();
- } catch (IOException e) {
- Log.e("View", "Could not dump view hierarchy");
- }
- }
-
- sHierarhcyRoot = null;
- }
-
- static void dispatchCommand(View view, String command, String parameters,
- OutputStream clientStream) throws IOException {
-
- // Paranoid but safe...
- view = view.getRootView();
-
- if (REMOTE_COMMAND_DUMP.equalsIgnoreCase(command)) {
- dump(view, clientStream);
- } else {
- final String[] params = parameters.split(" ");
- if (REMOTE_COMMAND_CAPTURE.equalsIgnoreCase(command)) {
- capture(view, clientStream, params[0]);
- } else if (REMOTE_COMMAND_INVALIDATE.equalsIgnoreCase(command)) {
- invalidate(view, params[0]);
- } else if (REMOTE_COMMAND_REQUEST_LAYOUT.equalsIgnoreCase(command)) {
- requestLayout(view, params[0]);
- }
- }
- }
-
- private static View findViewByHashCode(View root, String parameter) {
- final String[] ids = parameter.split("@");
- final String className = ids[0];
- final int hashCode = Integer.parseInt(ids[1], 16);
-
- View view = root.getRootView();
- if (view instanceof ViewGroup) {
- return findView((ViewGroup) view, className, hashCode);
- }
-
- return null;
- }
-
- private static void invalidate(View root, String parameter) {
- final View view = findViewByHashCode(root, parameter);
- if (view != null) {
- view.postInvalidate();
- }
- }
-
- private static void requestLayout(View root, String parameter) {
- final View view = findViewByHashCode(root, parameter);
- if (view != null) {
- root.post(new Runnable() {
- public void run() {
- view.requestLayout();
- }
- });
- }
- }
-
- private static void capture(View root, final OutputStream clientStream, String parameter)
- throws IOException {
-
- final CountDownLatch latch = new CountDownLatch(1);
- final View captureView = findViewByHashCode(root, parameter);
-
- if (captureView != null) {
- final Bitmap[] cache = new Bitmap[1];
-
- final boolean hasCache = captureView.isDrawingCacheEnabled();
- final boolean willNotCache = captureView.willNotCacheDrawing();
-
- if (willNotCache) {
- captureView.setWillNotCacheDrawing(false);
- }
-
- root.post(new Runnable() {
- public void run() {
- try {
- if (!hasCache) {
- captureView.buildDrawingCache();
- }
-
- cache[0] = captureView.getDrawingCache();
- } finally {
- latch.countDown();
- }
- }
- });
-
- try {
- latch.await(CAPTURE_TIMEOUT, TimeUnit.MILLISECONDS);
-
- if (cache[0] != null) {
- BufferedOutputStream out = null;
- try {
- out = new BufferedOutputStream(clientStream, 32 * 1024);
- cache[0].compress(Bitmap.CompressFormat.PNG, 100, out);
- out.flush();
- } finally {
- if (out != null) {
- out.close();
- }
- }
- }
- } catch (InterruptedException e) {
- Log.w("View", "Could not complete the capture of the view " + captureView);
- } finally {
- if (willNotCache) {
- captureView.setWillNotCacheDrawing(true);
- }
- if (!hasCache) {
- captureView.destroyDrawingCache();
- }
- }
- }
- }
-
- private static void dump(View root, OutputStream clientStream) throws IOException {
- BufferedWriter out = null;
- try {
- out = new BufferedWriter(new OutputStreamWriter(clientStream), 32 * 1024);
- View view = root.getRootView();
- if (view instanceof ViewGroup) {
- ViewGroup group = (ViewGroup) view;
- dumpViewHierarchyWithProperties(group, out, 0);
- }
- out.write("DONE.");
- out.newLine();
- } finally {
- if (out != null) {
- out.close();
- }
- }
- }
-
- private static View findView(ViewGroup group, String className, int hashCode) {
- if (isRequestedView(group, className, hashCode)) {
- return group;
- }
-
- final int count = group.getChildCount();
- for (int i = 0; i < count; i++) {
- final View view = group.getChildAt(i);
- if (view instanceof ViewGroup) {
- final View found = findView((ViewGroup) view, className, hashCode);
- if (found != null) {
- return found;
- }
- } else if (isRequestedView(view, className, hashCode)) {
- return view;
- }
- }
-
- return null;
- }
-
- private static boolean isRequestedView(View view, String className, int hashCode) {
- return view.getClass().getName().equals(className) && view.hashCode() == hashCode;
- }
-
- private static void dumpViewHierarchyWithProperties(ViewGroup group,
- BufferedWriter out, int level) {
- if (!dumpViewWithProperties(group, out, level)) {
- return;
- }
-
- final int count = group.getChildCount();
- for (int i = 0; i < count; i++) {
- final View view = group.getChildAt(i);
- if (view instanceof ViewGroup) {
- dumpViewHierarchyWithProperties((ViewGroup) view, out, level + 1);
- } else {
- dumpViewWithProperties(view, out, level + 1);
- }
- }
- }
-
- private static boolean dumpViewWithProperties(View view, BufferedWriter out, int level) {
- try {
- for (int i = 0; i < level; i++) {
- out.write(' ');
- }
- out.write(view.getClass().getName());
- out.write('@');
- out.write(Integer.toHexString(view.hashCode()));
- out.write(' ');
- dumpViewProperties(view, out);
- out.newLine();
- } catch (IOException e) {
- Log.w("View", "Error while dumping hierarchy tree");
- return false;
- }
- return true;
- }
-
- private static Field[] getExportedPropertyFields(Class<?> klass) {
- if (sFieldsForClasses == null) {
- sFieldsForClasses = new HashMap<Class<?>, Field[]>();
- }
- final HashMap<Class<?>, Field[]> map = sFieldsForClasses;
-
- Field[] fields = map.get(klass);
- if (fields != null) {
- return fields;
- }
-
- final ArrayList<Field> foundFields = new ArrayList<Field>();
- fields = klass.getDeclaredFields();
-
- int count = fields.length;
- for (int i = 0; i < count; i++) {
- final Field field = fields[i];
- if (field.isAnnotationPresent(ExportedProperty.class)) {
- field.setAccessible(true);
- foundFields.add(field);
- }
- }
-
- fields = foundFields.toArray(new Field[foundFields.size()]);
- map.put(klass, fields);
-
- return fields;
- }
-
- private static Method[] getExportedPropertyMethods(Class<?> klass) {
- if (sMethodsForClasses == null) {
- sMethodsForClasses = new HashMap<Class<?>, Method[]>();
- }
- final HashMap<Class<?>, Method[]> map = sMethodsForClasses;
-
- Method[] methods = map.get(klass);
- if (methods != null) {
- return methods;
- }
-
- final ArrayList<Method> foundMethods = new ArrayList<Method>();
- methods = klass.getDeclaredMethods();
-
- int count = methods.length;
- for (int i = 0; i < count; i++) {
- final Method method = methods[i];
- if (method.getParameterTypes().length == 0 &&
- method.isAnnotationPresent(ExportedProperty.class) &&
- method.getReturnType() != Void.class) {
- method.setAccessible(true);
- foundMethods.add(method);
- }
- }
-
- methods = foundMethods.toArray(new Method[foundMethods.size()]);
- map.put(klass, methods);
-
- return methods;
- }
-
- private static void dumpViewProperties(Object view, BufferedWriter out) throws IOException {
- dumpViewProperties(view, out, "");
- }
-
- private static void dumpViewProperties(Object view, BufferedWriter out, String prefix)
- throws IOException {
- Class<?> klass = view.getClass();
-
- do {
- exportFields(view, out, klass, prefix);
- exportMethods(view, out, klass, prefix);
- klass = klass.getSuperclass();
- } while (klass != Object.class);
- }
-
- private static void exportMethods(Object view, BufferedWriter out, Class<?> klass,
- String prefix) throws IOException {
-
- final Method[] methods = getExportedPropertyMethods(klass);
-
- int count = methods.length;
- for (int i = 0; i < count; i++) {
- final Method method = methods[i];
- //noinspection EmptyCatchBlock
- try {
- // TODO: This should happen on the UI thread
- Object methodValue = method.invoke(view, (Object[]) null);
- final Class<?> returnType = method.getReturnType();
-
- if (returnType == int.class) {
- ExportedProperty property = method.getAnnotation(ExportedProperty.class);
- if (property.resolveId() && view instanceof View) {
- final Resources resources = ((View) view).getContext().getResources();
- final int id = (Integer) methodValue;
- if (id >= 0) {
- try {
- methodValue = resources.getResourceTypeName(id) + '/' +
- resources.getResourceEntryName(id);
- } catch (Resources.NotFoundException e) {
- methodValue = "UNKNOWN";
- }
- } else {
- methodValue = "NO_ID";
- }
- } else {
- final IntToString[] mapping = property.mapping();
- if (mapping.length > 0) {
- final int intValue = (Integer) methodValue;
- boolean mapped = false;
- int mappingCount = mapping.length;
- for (int j = 0; j < mappingCount; j++) {
- final IntToString mapper = mapping[j];
- if (mapper.from() == intValue) {
- methodValue = mapper.to();
- mapped = true;
- break;
- }
- }
-
- if (!mapped) {
- methodValue = intValue;
- }
- }
- }
- } else if (!returnType.isPrimitive()) {
- ExportedProperty property = method.getAnnotation(ExportedProperty.class);
- if (property.deepExport()) {
- dumpViewProperties(methodValue, out, prefix + property.prefix());
- continue;
- }
- }
-
- out.write(prefix);
- out.write(method.getName());
- out.write("()=");
-
- if (methodValue != null) {
- final String value = methodValue.toString().replace("\n", "\\n");
- out.write(String.valueOf(value.length()));
- out.write(",");
- out.write(value);
- } else {
- out.write("4,null");
- }
-
- out.write(' ');
- } catch (IllegalAccessException e) {
- } catch (InvocationTargetException e) {
- }
- }
- }
-
- private static void exportFields(Object view, BufferedWriter out, Class<?> klass, String prefix)
- throws IOException {
- final Field[] fields = getExportedPropertyFields(klass);
-
- int count = fields.length;
- for (int i = 0; i < count; i++) {
- final Field field = fields[i];
-
- //noinspection EmptyCatchBlock
- try {
- Object fieldValue = null;
- final Class<?> type = field.getType();
-
- if (type == int.class) {
- ExportedProperty property = field.getAnnotation(ExportedProperty.class);
- if (property.resolveId() && view instanceof View) {
- final Resources resources = ((View) view).getContext().getResources();
- final int id = field.getInt(view);
- if (id >= 0) {
- try {
- fieldValue = resources.getResourceTypeName(id) + '/' +
- resources.getResourceEntryName(id);
- } catch (Resources.NotFoundException e) {
- fieldValue = "UNKNOWN";
- }
- } else {
- fieldValue = "NO_ID";
- }
- } else {
- final IntToString[] mapping = property.mapping();
- if (mapping.length > 0) {
- final int intValue = field.getInt(view);
- int mappingCount = mapping.length;
- for (int j = 0; j < mappingCount; j++) {
- final IntToString mapped = mapping[j];
- if (mapped.from() == intValue) {
- fieldValue = mapped.to();
- break;
- }
- }
-
- if (fieldValue == null) {
- fieldValue = intValue;
- }
- }
- }
- } else if (!type.isPrimitive()) {
- ExportedProperty property = field.getAnnotation(ExportedProperty.class);
- if (property.deepExport()) {
- dumpViewProperties(field.get(view), out, prefix + property.prefix());
- continue;
- }
- }
-
- if (fieldValue == null) {
- fieldValue = field.get(view);
- }
-
- out.write(prefix);
- out.write(field.getName());
- out.write('=');
-
- if (fieldValue != null) {
- final String value = fieldValue.toString().replace("\n", "\\n");
- out.write(String.valueOf(value.length()));
- out.write(",");
- out.write(value);
- } else {
- out.write("4,null");
- }
-
- out.write(' ');
- } catch (IllegalAccessException e) {
- }
- }
- }
-
- private static void dumpViewHierarchy(ViewGroup group, BufferedWriter out, int level) {
- if (!dumpView(group, out, level)) {
- return;
- }
-
- final int count = group.getChildCount();
- for (int i = 0; i < count; i++) {
- final View view = group.getChildAt(i);
- if (view instanceof ViewGroup) {
- dumpViewHierarchy((ViewGroup) view, out, level + 1);
- } else {
- dumpView(view, out, level + 1);
- }
- }
- }
-
- private static boolean dumpView(Object view, BufferedWriter out, int level) {
- try {
- for (int i = 0; i < level; i++) {
- out.write(' ');
- }
- out.write(view.getClass().getName());
- out.write('@');
- out.write(Integer.toHexString(view.hashCode()));
- out.newLine();
- } catch (IOException e) {
- Log.w("View", "Error while dumping hierarchy tree");
- return false;
- }
- return true;
- }
-
- private static Field[] capturedViewGetPropertyFields(Class<?> klass) {
- if (mCapturedViewFieldsForClasses == null) {
- mCapturedViewFieldsForClasses = new HashMap<Class<?>, Field[]>();
- }
- final HashMap<Class<?>, Field[]> map = mCapturedViewFieldsForClasses;
-
- Field[] fields = map.get(klass);
- if (fields != null) {
- return fields;
- }
-
- final ArrayList<Field> foundFields = new ArrayList<Field>();
- fields = klass.getFields();
-
- int count = fields.length;
- for (int i = 0; i < count; i++) {
- final Field field = fields[i];
- if (field.isAnnotationPresent(CapturedViewProperty.class)) {
- field.setAccessible(true);
- foundFields.add(field);
- }
- }
-
- fields = foundFields.toArray(new Field[foundFields.size()]);
- map.put(klass, fields);
-
- return fields;
- }
-
- private static Method[] capturedViewGetPropertyMethods(Class<?> klass) {
- if (mCapturedViewMethodsForClasses == null) {
- mCapturedViewMethodsForClasses = new HashMap<Class<?>, Method[]>();
- }
- final HashMap<Class<?>, Method[]> map = mCapturedViewMethodsForClasses;
-
- Method[] methods = map.get(klass);
- if (methods != null) {
- return methods;
- }
-
- final ArrayList<Method> foundMethods = new ArrayList<Method>();
- methods = klass.getMethods();
-
- int count = methods.length;
- for (int i = 0; i < count; i++) {
- final Method method = methods[i];
- if (method.getParameterTypes().length == 0 &&
- method.isAnnotationPresent(CapturedViewProperty.class) &&
- method.getReturnType() != Void.class) {
- method.setAccessible(true);
- foundMethods.add(method);
- }
- }
-
- methods = foundMethods.toArray(new Method[foundMethods.size()]);
- map.put(klass, methods);
-
- return methods;
- }
-
- private static String capturedViewExportMethods(Object obj, Class<?> klass,
- String prefix) {
-
- if (obj == null) {
- return "null";
- }
-
- StringBuilder sb = new StringBuilder();
- final Method[] methods = capturedViewGetPropertyMethods(klass);
-
- int count = methods.length;
- for (int i = 0; i < count; i++) {
- final Method method = methods[i];
- try {
- Object methodValue = method.invoke(obj, (Object[]) null);
- final Class<?> returnType = method.getReturnType();
-
- CapturedViewProperty property = method.getAnnotation(CapturedViewProperty.class);
- if (property.retrieveReturn()) {
- //we are interested in the second level data only
- sb.append(capturedViewExportMethods(methodValue, returnType, method.getName() + "#"));
- } else {
- sb.append(prefix);
- sb.append(method.getName());
- sb.append("()=");
-
- if (methodValue != null) {
- final String value = methodValue.toString().replace("\n", "\\n");
- sb.append(value);
- } else {
- sb.append("null");
- }
- sb.append("; ");
- }
- } catch (IllegalAccessException e) {
- //Exception IllegalAccess, it is OK here
- //we simply ignore this method
- } catch (InvocationTargetException e) {
- //Exception InvocationTarget, it is OK here
- //we simply ignore this method
- }
- }
- return sb.toString();
- }
-
- private static String capturedViewExportFields(Object obj, Class<?> klass, String prefix) {
-
- if (obj == null) {
- return "null";
- }
-
- StringBuilder sb = new StringBuilder();
- final Field[] fields = capturedViewGetPropertyFields(klass);
-
- int count = fields.length;
- for (int i = 0; i < count; i++) {
- final Field field = fields[i];
- try {
- Object fieldValue = field.get(obj);
-
- sb.append(prefix);
- sb.append(field.getName());
- sb.append("=");
-
- if (fieldValue != null) {
- final String value = fieldValue.toString().replace("\n", "\\n");
- sb.append(value);
- } else {
- sb.append("null");
- }
- sb.append(' ');
- } catch (IllegalAccessException e) {
- //Exception IllegalAccess, it is OK here
- //we simply ignore this field
- }
- }
- return sb.toString();
- }
-
- /**
- * dump view info for id based instrument test generation
- * (and possibly further data analysis). The results are dumped
- * to the log.
- * @param tag for log
- * @param view for dump
- *
- * @hide pending API Council approval
- */
- public static void dumpCapturedView(String tag, Object view) {
- Class<?> klass = view.getClass();
- StringBuilder sb = new StringBuilder(klass.getName() + ": ");
- sb.append(capturedViewExportFields(view, klass, ""));
- sb.append(capturedViewExportMethods(view, klass, ""));
- Log.d(tag, sb.toString());
- }
-}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
deleted file mode 100644
index 70cc2a9..0000000
--- a/core/java/android/view/ViewGroup.java
+++ /dev/null
@@ -1,3478 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import com.android.internal.R;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.graphics.RectF;
-import android.os.Parcelable;
-import android.os.SystemClock;
-import android.util.AttributeSet;
-import android.util.EventLog;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-import android.view.animation.LayoutAnimationController;
-import android.view.animation.Transformation;
-
-import java.util.ArrayList;
-
-/**
- * <p>
- * A <code>ViewGroup</code> is a special view that can contain other views
- * (called children.) The view group is the base class for layouts and views
- * containers. This class also defines the
- * {@link android.view.ViewGroup.LayoutParams} class which serves as the base
- * class for layouts parameters.
- * </p>
- *
- * <p>
- * Also see {@link LayoutParams} for layout attributes.
- * </p>
- */
-public abstract class ViewGroup extends View implements ViewParent, ViewManager {
- private static final boolean DBG = false;
-
- /**
- * Views which have been hidden or removed which need to be animated on
- * their way out.
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected ArrayList<View> mDisappearingChildren;
-
- /**
- * Listener used to propagate events indicating when children are added
- * and/or removed from a view group.
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected OnHierarchyChangeListener mOnHierarchyChangeListener;
-
- // The view contained within this ViewGroup that has or contains focus.
- private View mFocused;
-
- // The current transformation to apply on the child being drawn
- private Transformation mChildTransformation;
- private RectF mInvalidateRegion;
-
- // Target of Motion events
- private View mMotionTarget;
- private final Rect mTempRect = new Rect();
-
- // Layout animation
- private LayoutAnimationController mLayoutAnimationController;
- private Animation.AnimationListener mAnimationListener;
-
- /**
- * Internal flags.
- *
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected int mGroupFlags;
-
- // When set, ViewGroup invalidates only the child's rectangle
- // Set by default
- private static final int FLAG_CLIP_CHILDREN = 0x1;
-
- // When set, ViewGroup excludes the padding area from the invalidate rectangle
- // Set by default
- private static final int FLAG_CLIP_TO_PADDING = 0x2;
-
- // When set, dispatchDraw() will invoke invalidate(); this is set by drawChild() when
- // a child needs to be invalidated and FLAG_OPTIMIZE_INVALIDATE is set
- private static final int FLAG_INVALIDATE_REQUIRED = 0x4;
-
- // When set, dispatchDraw() will run the layout animation and unset the flag
- private static final int FLAG_RUN_ANIMATION = 0x8;
-
- // When set, there is either no layout animation on the ViewGroup or the layout
- // animation is over
- // Set by default
- private static final int FLAG_ANIMATION_DONE = 0x10;
-
- // If set, this ViewGroup has padding; if unset there is no padding and we don't need
- // to clip it, even if FLAG_CLIP_TO_PADDING is set
- private static final int FLAG_PADDING_NOT_NULL = 0x20;
-
- // When set, this ViewGroup caches its children in a Bitmap before starting a layout animation
- // Set by default
- private static final int FLAG_ANIMATION_CACHE = 0x40;
-
- // When set, this ViewGroup converts calls to invalidate(Rect) to invalidate() during a
- // layout animation; this avoid clobbering the hierarchy
- // Automatically set when the layout animation starts, depending on the animation's
- // characteristics
- private static final int FLAG_OPTIMIZE_INVALIDATE = 0x80;
-
- // When set, the next call to drawChild() will clear mChildTransformation's matrix
- private static final int FLAG_CLEAR_TRANSFORMATION = 0x100;
-
- // When set, this ViewGroup invokes mAnimationListener.onAnimationEnd() and removes
- // the children's Bitmap caches if necessary
- // This flag is set when the layout animation is over (after FLAG_ANIMATION_DONE is set)
- private static final int FLAG_NOTIFY_ANIMATION_LISTENER = 0x200;
-
- /**
- * When set, the drawing method will call {@link #getChildDrawingOrder(int, int)}
- * to get the index of the child to draw for that iteration.
- */
- protected static final int FLAG_USE_CHILD_DRAWING_ORDER = 0x400;
-
- /**
- * When set, this ViewGroup supports static transformations on children; this causes
- * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} to be
- * invoked when a child is drawn.
- *
- * Any subclass overriding
- * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} should
- * set this flags in {@link #mGroupFlags}.
- *
- * {@hide}
- */
- protected static final int FLAG_SUPPORT_STATIC_TRANSFORMATIONS = 0x800;
-
- // When the previous drawChild() invocation used an alpha value that was lower than
- // 1.0 and set it in mCachePaint
- private static final int FLAG_ALPHA_LOWER_THAN_ONE = 0x1000;
-
- /**
- * When set, this ViewGroup's drawable states also include those
- * of its children.
- */
- private static final int FLAG_ADD_STATES_FROM_CHILDREN = 0x2000;
-
- /**
- * When set, this ViewGroup tries to always draw its children using their drawing cache.
- */
- private static final int FLAG_ALWAYS_DRAWN_WITH_CACHE = 0x4000;
-
- /**
- * When set, and if FLAG_ALWAYS_DRAWN_WITH_CACHE is not set, this ViewGroup will try to
- * draw its children with their drawing cache.
- */
- private static final int FLAG_CHILDREN_DRAWN_WITH_CACHE = 0x8000;
-
- /**
- * When set, this group will go through its list of children to notify them of
- * any drawable state change.
- */
- private static final int FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE = 0x10000;
-
- private static final int FLAG_MASK_FOCUSABILITY = 0x60000;
-
- /**
- * This view will get focus before any of its descendants.
- */
- public static final int FOCUS_BEFORE_DESCENDANTS = 0x20000;
-
- /**
- * This view will get focus only if none of its descendants want it.
- */
- public static final int FOCUS_AFTER_DESCENDANTS = 0x40000;
-
- /**
- * This view will block any of its descendants from getting focus, even
- * if they are focusable.
- */
- public static final int FOCUS_BLOCK_DESCENDANTS = 0x60000;
-
- /**
- * Used to map between enum in attrubutes and flag values.
- */
- private static final int[] DESCENDANT_FOCUSABILITY_FLAGS =
- {FOCUS_BEFORE_DESCENDANTS, FOCUS_AFTER_DESCENDANTS,
- FOCUS_BLOCK_DESCENDANTS};
-
- /**
- * When set, this ViewGroup should not intercept touch events.
- */
- private static final int FLAG_DISALLOW_INTERCEPT = 0x80000;
-
- /**
- * Indicates which types of drawing caches are to be kept in memory.
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected int mPersistentDrawingCache;
-
- /**
- * Used to indicate that no drawing cache should be kept in memory.
- */
- public static final int PERSISTENT_NO_CACHE = 0x0;
-
- /**
- * Used to indicate that the animation drawing cache should be kept in memory.
- */
- public static final int PERSISTENT_ANIMATION_CACHE = 0x1;
-
- /**
- * Used to indicate that the scrolling drawing cache should be kept in memory.
- */
- public static final int PERSISTENT_SCROLLING_CACHE = 0x2;
-
- /**
- * Used to indicate that all drawing caches should be kept in memory.
- */
- public static final int PERSISTENT_ALL_CACHES = 0x3;
-
- /**
- * We clip to padding when FLAG_CLIP_TO_PADDING and FLAG_PADDING_NOT_NULL
- * are set at the same time.
- */
- protected static final int CLIP_TO_PADDING_MASK = FLAG_CLIP_TO_PADDING | FLAG_PADDING_NOT_NULL;
-
- // Index of the child's left position in the mLocation array
- private static final int CHILD_LEFT_INDEX = 0;
- // Index of the child's top position in the mLocation array
- private static final int CHILD_TOP_INDEX = 1;
-
- // Child views of this ViewGroup
- private View[] mChildren;
- // Number of valid children in the mChildren array, the rest should be null or not
- // considered as children
- private int mChildrenCount;
-
- private static final int ARRAY_INITIAL_CAPACITY = 12;
- private static final int ARRAY_CAPACITY_INCREMENT = 12;
-
- // Used to draw cached views
- private final Paint mCachePaint = new Paint();
-
- public ViewGroup(Context context) {
- super(context);
- initViewGroup();
- }
-
- public ViewGroup(Context context, AttributeSet attrs) {
- super(context, attrs);
- initViewGroup();
- initFromAttributes(context, attrs);
- }
-
- public ViewGroup(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- initViewGroup();
- initFromAttributes(context, attrs);
- }
-
- private void initViewGroup() {
- // ViewGroup doesn't draw by default
- setFlags(WILL_NOT_DRAW, DRAW_MASK);
- mGroupFlags |= FLAG_CLIP_CHILDREN;
- mGroupFlags |= FLAG_CLIP_TO_PADDING;
- mGroupFlags |= FLAG_ANIMATION_DONE;
- mGroupFlags |= FLAG_ANIMATION_CACHE;
- mGroupFlags |= FLAG_ALWAYS_DRAWN_WITH_CACHE;
-
- setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS);
-
- mChildren = new View[ARRAY_INITIAL_CAPACITY];
- mChildrenCount = 0;
-
- mCachePaint.setDither(false);
-
- mPersistentDrawingCache = PERSISTENT_SCROLLING_CACHE;
- }
-
- private void initFromAttributes(Context context, AttributeSet attrs) {
- TypedArray a = context.obtainStyledAttributes(attrs,
- R.styleable.ViewGroup);
-
- final int N = a.getIndexCount();
- for (int i = 0; i < N; i++) {
- int attr = a.getIndex(i);
- switch (attr) {
- case R.styleable.ViewGroup_clipChildren:
- setClipChildren(a.getBoolean(attr, true));
- break;
- case R.styleable.ViewGroup_clipToPadding:
- setClipToPadding(a.getBoolean(attr, true));
- break;
- case R.styleable.ViewGroup_animationCache:
- setAnimationCacheEnabled(a.getBoolean(attr, true));
- break;
- case R.styleable.ViewGroup_persistentDrawingCache:
- setPersistentDrawingCache(a.getInt(attr, PERSISTENT_SCROLLING_CACHE));
- break;
- case R.styleable.ViewGroup_addStatesFromChildren:
- setAddStatesFromChildren(a.getBoolean(attr, false));
- break;
- case R.styleable.ViewGroup_alwaysDrawnWithCache:
- setAlwaysDrawnWithCacheEnabled(a.getBoolean(attr, true));
- break;
- case R.styleable.ViewGroup_layoutAnimation:
- int id = a.getResourceId(attr, -1);
- if (id > 0) {
- setLayoutAnimation(AnimationUtils.loadLayoutAnimation(mContext, id));
- }
- break;
- case R.styleable.ViewGroup_descendantFocusability:
- setDescendantFocusability(DESCENDANT_FOCUSABILITY_FLAGS[a.getInt(attr, 0)]);
- break;
- }
- }
-
- a.recycle();
- }
-
- /**
- * Gets the descendant focusability of this view group. The descendant
- * focusability defines the relationship between this view group and its
- * descendants when looking for a view to take focus in
- * {@link #requestFocus(int, android.graphics.Rect)}.
- *
- * @return one of {@link #FOCUS_BEFORE_DESCENDANTS}, {@link #FOCUS_AFTER_DESCENDANTS},
- * {@link #FOCUS_BLOCK_DESCENDANTS}.
- */
- @ViewDebug.ExportedProperty(mapping = {
- @ViewDebug.IntToString(from = FOCUS_BEFORE_DESCENDANTS, to = "FOCUS_BEFORE_DESCENDANTS"),
- @ViewDebug.IntToString(from = FOCUS_AFTER_DESCENDANTS, to = "FOCUS_AFTER_DESCENDANTS"),
- @ViewDebug.IntToString(from = FOCUS_BLOCK_DESCENDANTS, to = "FOCUS_BLOCK_DESCENDANTS")
- })
- public int getDescendantFocusability() {
- return mGroupFlags & FLAG_MASK_FOCUSABILITY;
- }
-
- /**
- * Set the descendant focusability of this view group. This defines the relationship
- * between this view group and its descendants when looking for a view to
- * take focus in {@link #requestFocus(int, android.graphics.Rect)}.
- *
- * @param focusability one of {@link #FOCUS_BEFORE_DESCENDANTS}, {@link #FOCUS_AFTER_DESCENDANTS},
- * {@link #FOCUS_BLOCK_DESCENDANTS}.
- */
- public void setDescendantFocusability(int focusability) {
- switch (focusability) {
- case FOCUS_BEFORE_DESCENDANTS:
- case FOCUS_AFTER_DESCENDANTS:
- case FOCUS_BLOCK_DESCENDANTS:
- break;
- default:
- throw new IllegalArgumentException("must be one of FOCUS_BEFORE_DESCENDANTS, "
- + "FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS");
- }
- mGroupFlags &= ~FLAG_MASK_FOCUSABILITY;
- mGroupFlags |= (focusability & FLAG_MASK_FOCUSABILITY);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
- if (mFocused != null) {
- mFocused.unFocus();
- mFocused = null;
- }
- super.handleFocusGainInternal(direction, previouslyFocusedRect);
- }
-
- /**
- * {@inheritDoc}
- */
- public void requestChildFocus(View child, View focused) {
- if (DBG) {
- System.out.println(this + " requestChildFocus()");
- }
- if (getDescendantFocusability() == FOCUS_BLOCK_DESCENDANTS) {
- return;
- }
-
- // Unfocus us, if necessary
- super.unFocus();
-
- // We had a previous notion of who had focus. Clear it.
- if (mFocused != child) {
- if (mFocused != null) {
- mFocused.unFocus();
- }
-
- mFocused = child;
- }
- if (mParent != null) {
- mParent.requestChildFocus(this, focused);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void focusableViewAvailable(View v) {
- if (mParent != null
- // shortcut: don't report a new focusable view if we block our descendants from
- // getting focus
- && (getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS)
- // shortcut: don't report a new focusable view if we already are focused
- // (and we don't prefer our descendants)
- //
- // note: knowing that mFocused is non-null is not a good enough reason
- // to break the traversal since in that case we'd actually have to find
- // the focused view and make sure it wasn't FOCUS_AFTER_DESCENDANTS and
- // an ancestor of v; this will get checked for at ViewRoot
- && !(isFocused() && getDescendantFocusability() != FOCUS_AFTER_DESCENDANTS)) {
- mParent.focusableViewAvailable(v);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean showContextMenuForChild(View originalView) {
- return mParent != null && mParent.showContextMenuForChild(originalView);
- }
-
- /**
- * Find the nearest view in the specified direction that wants to take
- * focus.
- *
- * @param focused The view that currently has focus
- * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and
- * FOCUS_RIGHT, or 0 for not applicable.
- */
- public View focusSearch(View focused, int direction) {
- if (isRootNamespace()) {
- // root namespace means we should consider ourselves the top of the
- // tree for focus searching; otherwise we could be focus searching
- // into other tabs. see LocalActivityManager and TabHost for more info
- return FocusFinder.getInstance().findNextFocus(this, focused, direction);
- } else if (mParent != null) {
- return mParent.focusSearch(focused, direction);
- }
- return null;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean dispatchUnhandledMove(View focused, int direction) {
- return mFocused != null &&
- mFocused.dispatchUnhandledMove(focused, direction);
- }
-
- /**
- * {@inheritDoc}
- */
- public void clearChildFocus(View child) {
- if (DBG) {
- System.out.println(this + " clearChildFocus()");
- }
-
- mFocused = null;
- if (mParent != null) {
- mParent.clearChildFocus(this);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void clearFocus() {
- super.clearFocus();
-
- // clear any child focus if it exists
- if (mFocused != null) {
- mFocused.clearFocus();
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- void unFocus() {
- if (DBG) {
- System.out.println(this + " unFocus()");
- }
-
- super.unFocus();
- if (mFocused != null) {
- mFocused.unFocus();
- }
- mFocused = null;
- }
-
- /**
- * Returns the focused child of this view, if any. The child may have focus
- * or contain focus.
- *
- * @return the focused child or null.
- */
- public View getFocusedChild() {
- return mFocused;
- }
-
- /**
- * Returns true if this view has or contains focus
- *
- * @return true if this view has or contains focus
- */
- @Override
- public boolean hasFocus() {
- return (mPrivateFlags & FOCUSED) != 0 || mFocused != null;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see android.view.View#findFocus()
- */
- @Override
- public View findFocus() {
- if (DBG) {
- System.out.println("Find focus in " + this + ": flags="
- + isFocused() + ", child=" + mFocused);
- }
-
- if (isFocused()) {
- return this;
- }
-
- if (mFocused != null) {
- return mFocused.findFocus();
- }
- return null;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean hasFocusable() {
- if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
- return false;
- }
-
- if (isFocusable()) {
- return true;
- }
-
- final int descendantFocusability = getDescendantFocusability();
- if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
- final int count = mChildrenCount;
- final View[] children = mChildren;
-
- for (int i = 0; i < count; i++) {
- final View child = children[i];
- if (child.hasFocusable()) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void addFocusables(ArrayList<View> views, int direction) {
- final int focusableCount = views.size();
-
- final int descendantFocusability = getDescendantFocusability();
-
- if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
- final int count = mChildrenCount;
- final View[] children = mChildren;
-
- for (int i = 0; i < count; i++) {
- final View child = children[i];
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
- child.addFocusables(views, direction);
- }
- }
- }
-
- // we add ourselves (if focusable) in all cases except for when we are
- // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable. this is
- // to avoid the focus search finding layouts when a more precise search
- // among the focusable children would be more interesting.
- if (
- descendantFocusability != FOCUS_AFTER_DESCENDANTS ||
- // No focusable descendants
- (focusableCount == views.size())) {
- super.addFocusables(views, direction);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void dispatchWindowFocusChanged(boolean hasFocus) {
- super.dispatchWindowFocusChanged(hasFocus);
- final int count = mChildrenCount;
- final View[] children = mChildren;
- for (int i = 0; i < count; i++) {
- children[i].dispatchWindowFocusChanged(hasFocus);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void addTouchables(ArrayList<View> views) {
- super.addTouchables(views);
-
- final int count = mChildrenCount;
- final View[] children = mChildren;
-
- for (int i = 0; i < count; i++) {
- final View child = children[i];
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
- child.addTouchables(views);
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void dispatchWindowVisibilityChanged(int visibility) {
- super.dispatchWindowVisibilityChanged(visibility);
- final int count = mChildrenCount;
- final View[] children = mChildren;
- for (int i = 0; i < count; i++) {
- children[i].dispatchWindowVisibilityChanged(visibility);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void recomputeViewAttributes(View child) {
- ViewParent parent = mParent;
- if (parent != null) parent.recomputeViewAttributes(this);
- }
-
- @Override
- void dispatchCollectViewAttributes(int visibility) {
- visibility |= mViewFlags&VISIBILITY_MASK;
- super.dispatchCollectViewAttributes(visibility);
- final int count = mChildrenCount;
- final View[] children = mChildren;
- for (int i = 0; i < count; i++) {
- children[i].dispatchCollectViewAttributes(visibility);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void bringChildToFront(View child) {
- int index = indexOfChild(child);
- if (index >= 0) {
- removeFromArray(index);
- addInArray(child, mChildrenCount);
- child.mParent = this;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean dispatchKeyEventPreIme(KeyEvent event) {
- if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
- return super.dispatchKeyEventPreIme(event);
- } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
- return mFocused.dispatchKeyEventPreIme(event);
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
- return super.dispatchKeyEvent(event);
- } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
- return mFocused.dispatchKeyEvent(event);
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean dispatchKeyShortcutEvent(KeyEvent event) {
- if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
- return super.dispatchKeyShortcutEvent(event);
- } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
- return mFocused.dispatchKeyShortcutEvent(event);
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean dispatchTrackballEvent(MotionEvent event) {
- if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
- return super.dispatchTrackballEvent(event);
- } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
- return mFocused.dispatchTrackballEvent(event);
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- final int action = ev.getAction();
- final float xf = ev.getX();
- final float yf = ev.getY();
- final float scrolledXFloat = xf + mScrollX;
- final float scrolledYFloat = yf + mScrollY;
- final Rect frame = mTempRect;
-
- boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
-
- if (action == MotionEvent.ACTION_DOWN) {
- if (mMotionTarget != null) {
- // this is weird, we got a pen down, but we thought it was
- // already down!
- // XXX: We should probably send an ACTION_UP to the current
- // target.
- mMotionTarget = null;
- }
- // If we're disallowing intercept or if we're allowing and we didn't
- // intercept
- if (disallowIntercept || !onInterceptTouchEvent(ev)) {
- // reset this event's action (just to protect ourselves)
- ev.setAction(MotionEvent.ACTION_DOWN);
- // We know we want to dispatch the event down, find a child
- // who can handle it, start with the front-most child.
- final int scrolledXInt = (int) scrolledXFloat;
- final int scrolledYInt = (int) scrolledYFloat;
- final View[] children = mChildren;
- final int count = mChildrenCount;
- for (int i = count - 1; i >= 0; i--) {
- final View child = children[i];
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
- || child.getAnimation() != null) {
- child.getHitRect(frame);
- if (frame.contains(scrolledXInt, scrolledYInt)) {
- // offset the event to the view's coordinate system
- final float xc = scrolledXFloat - child.mLeft;
- final float yc = scrolledYFloat - child.mTop;
- ev.setLocation(xc, yc);
- if (child.dispatchTouchEvent(ev)) {
- // Event handled, we have a target now.
- mMotionTarget = child;
- return true;
- }
- // The event didn't get handled, try the next view.
- // Don't reset the event's location, it's not
- // necessary here.
- }
- }
- }
- }
- }
-
- boolean isUpOrCancel = (action == MotionEvent.ACTION_UP) ||
- (action == MotionEvent.ACTION_CANCEL);
-
- if (isUpOrCancel) {
- // Note, we've already copied the previous state to our local
- // variable, so this takes effect on the next event
- mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
- }
-
- // The event wasn't an ACTION_DOWN, dispatch it to our target if
- // we have one.
- final View target = mMotionTarget;
- if (target == null) {
- // We don't have a target, this means we're handling the
- // event as a regular view.
- ev.setLocation(xf, yf);
- return super.dispatchTouchEvent(ev);
- }
-
- // if have a target, see if we're allowed to and want to intercept its
- // events
- if (!disallowIntercept && onInterceptTouchEvent(ev)) {
- final float xc = scrolledXFloat - (float) target.mLeft;
- final float yc = scrolledYFloat - (float) target.mTop;
- ev.setAction(MotionEvent.ACTION_CANCEL);
- ev.setLocation(xc, yc);
- if (!target.dispatchTouchEvent(ev)) {
- // target didn't handle ACTION_CANCEL. not much we can do
- // but they should have.
- }
- // clear the target
- mMotionTarget = null;
- // Don't dispatch this event to our own view, because we already
- // saw it when intercepting; we just want to give the following
- // event to the normal onTouchEvent().
- return true;
- }
-
- if (isUpOrCancel) {
- mMotionTarget = null;
- }
-
- // finally offset the event to the target's coordinate system and
- // dispatch the event.
- final float xc = scrolledXFloat - (float) target.mLeft;
- final float yc = scrolledYFloat - (float) target.mTop;
- ev.setLocation(xc, yc);
-
- return target.dispatchTouchEvent(ev);
- }
-
- /**
- * {@inheritDoc}
- */
- public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
-
- if (disallowIntercept == ((mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0)) {
- // We're already in this state, assume our ancestors are too
- return;
- }
-
- if (disallowIntercept) {
- mGroupFlags |= FLAG_DISALLOW_INTERCEPT;
- } else {
- mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
- }
-
- // Pass it up to our parent
- if (mParent != null) {
- mParent.requestDisallowInterceptTouchEvent(disallowIntercept);
- }
- }
-
- /**
- * Implement this method to intercept all touch screen motion events. This
- * allows you to watch events as they are dispatched to your children, and
- * take ownership of the current gesture at any point.
- *
- * <p>Using this function takes some care, as it has a fairly complicated
- * interaction with {@link View#onTouchEvent(MotionEvent)
- * View.onTouchEvent(MotionEvent)}, and using it requires implementing
- * that method as well as this one in the correct way. Events will be
- * received in the following order:
- *
- * <ol>
- * <li> You will receive the down event here.
- * <li> The down event will be handled either by a child of this view
- * group, or given to your own onTouchEvent() method to handle; this means
- * you should implement onTouchEvent() to return true, so you will
- * continue to see the rest of the gesture (instead of looking for
- * a parent view to handle it). Also, by returning true from
- * onTouchEvent(), you will not receive any following
- * events in onInterceptTouchEvent() and all touch processing must
- * happen in onTouchEvent() like normal.
- * <li> For as long as you return false from this function, each following
- * event (up to and including the final up) will be delivered first here
- * and then to the target's onTouchEvent().
- * <li> If you return true from here, you will not receive any
- * following events: the target view will receive the same event but
- * with the action {@link MotionEvent#ACTION_CANCEL}, and all further
- * events will be delivered to your onTouchEvent() method and no longer
- * appear here.
- * </ol>
- *
- * @param ev The motion event being dispatched down the hierarchy.
- * @return Return true to steal motion events from the children and have
- * them dispatched to this ViewGroup through onTouchEvent().
- * The current target will receive an ACTION_CANCEL event, and no further
- * messages will be delivered here.
- */
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- return false;
- }
-
- /**
- * {@inheritDoc}
- *
- * Looks for a view to give focus to respecting the setting specified by
- * {@link #getDescendantFocusability()}.
- *
- * Uses {@link #onRequestFocusInDescendants(int, android.graphics.Rect)} to
- * find focus within the children of this group when appropriate.
- *
- * @see #FOCUS_BEFORE_DESCENDANTS
- * @see #FOCUS_AFTER_DESCENDANTS
- * @see #FOCUS_BLOCK_DESCENDANTS
- * @see #onRequestFocusInDescendants
- */
- @Override
- public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
- if (DBG) {
- System.out.println(this + " ViewGroup.requestFocus direction="
- + direction);
- }
- int descendantFocusability = getDescendantFocusability();
-
- switch (descendantFocusability) {
- case FOCUS_BLOCK_DESCENDANTS:
- return super.requestFocus(direction, previouslyFocusedRect);
- case FOCUS_BEFORE_DESCENDANTS: {
- final boolean took = super.requestFocus(direction, previouslyFocusedRect);
- return took ? took : onRequestFocusInDescendants(direction, previouslyFocusedRect);
- }
- case FOCUS_AFTER_DESCENDANTS: {
- final boolean took = onRequestFocusInDescendants(direction, previouslyFocusedRect);
- return took ? took : super.requestFocus(direction, previouslyFocusedRect);
- }
- default:
- throw new IllegalStateException("descendant focusability must be "
- + "one of FOCUS_BEFORE_DESCENDANTS, FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS "
- + "but is " + descendantFocusability);
- }
- }
-
- /**
- * Look for a descendant to call {@link View#requestFocus} on.
- * Called by {@link ViewGroup#requestFocus(int, android.graphics.Rect)}
- * when it wants to request focus within its children. Override this to
- * customize how your {@link ViewGroup} requests focus within its children.
- * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
- * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
- * to give a finer grained hint about where focus is coming from. May be null
- * if there is no hint.
- * @return Whether focus was taken.
- */
- @SuppressWarnings({"ConstantConditions"})
- protected boolean onRequestFocusInDescendants(int direction,
- Rect previouslyFocusedRect) {
- int index;
- int increment;
- int end;
- int count = mChildrenCount;
- if ((direction & FOCUS_FORWARD) != 0) {
- index = 0;
- increment = 1;
- end = count;
- } else {
- index = count - 1;
- increment = -1;
- end = -1;
- }
- final View[] children = mChildren;
- for (int i = index; i != end; i += increment) {
- View child = children[i];
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
- if (child.requestFocus(direction, previouslyFocusedRect)) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- void dispatchAttachedToWindow(AttachInfo info, int visibility) {
- super.dispatchAttachedToWindow(info, visibility);
- visibility |= mViewFlags & VISIBILITY_MASK;
- final int count = mChildrenCount;
- final View[] children = mChildren;
- for (int i = 0; i < count; i++) {
- children[i].dispatchAttachedToWindow(info, visibility);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- void dispatchDetachedFromWindow() {
- // If we still have a motion target, we are still in the process of
- // dispatching motion events to a child; we need to get rid of that
- // child to avoid dispatching events to it after the window is torn
- // down. To make sure we keep the child in a consistent state, we
- // first send it an ACTION_CANCEL motion event.
- if (mMotionTarget != null) {
- final long now = SystemClock.uptimeMillis();
- final MotionEvent event = MotionEvent.obtain(now, now,
- MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
- mMotionTarget.dispatchTouchEvent(event);
- event.recycle();
- mMotionTarget = null;
- }
-
- final int count = mChildrenCount;
- final View[] children = mChildren;
- for (int i = 0; i < count; i++) {
- children[i].dispatchDetachedFromWindow();
- }
- super.dispatchDetachedFromWindow();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setPadding(int left, int top, int right, int bottom) {
- super.setPadding(left, top, right, bottom);
-
- if ((mPaddingLeft | mPaddingTop | mPaddingRight | mPaddingRight) != 0) {
- mGroupFlags |= FLAG_PADDING_NOT_NULL;
- } else {
- mGroupFlags &= ~FLAG_PADDING_NOT_NULL;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
- super.dispatchSaveInstanceState(container);
- final int count = mChildrenCount;
- final View[] children = mChildren;
- for (int i = 0; i < count; i++) {
- children[i].dispatchSaveInstanceState(container);
- }
- }
-
- /**
- * Perform dispatching of a {@link #saveHierarchyState freeze()} to only this view,
- * not to its children. For use when overriding
- * {@link #dispatchSaveInstanceState dispatchFreeze()} to allow subclasses to freeze
- * their own state but not the state of their children.
- *
- * @param container the container
- */
- protected void dispatchFreezeSelfOnly(SparseArray<Parcelable> container) {
- super.dispatchSaveInstanceState(container);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
- super.dispatchRestoreInstanceState(container);
- final int count = mChildrenCount;
- final View[] children = mChildren;
- for (int i = 0; i < count; i++) {
- children[i].dispatchRestoreInstanceState(container);
- }
- }
-
- /**
- * Perform dispatching of a {@link #restoreHierarchyState thaw()} to only this view,
- * not to its children. For use when overriding
- * {@link #dispatchRestoreInstanceState dispatchThaw()} to allow subclasses to thaw
- * their own state but not the state of their children.
- *
- * @param container the container
- */
- protected void dispatchThawSelfOnly(SparseArray<Parcelable> container) {
- super.dispatchRestoreInstanceState(container);
- }
-
- /**
- * Enables or disables the drawing cache for each child of this view group.
- *
- * @param enabled true to enable the cache, false to dispose of it
- */
- protected void setChildrenDrawingCacheEnabled(boolean enabled) {
- if (enabled || (mPersistentDrawingCache & PERSISTENT_ALL_CACHES) != PERSISTENT_ALL_CACHES) {
- final View[] children = mChildren;
- final int count = mChildrenCount;
- for (int i = 0; i < count; i++) {
- children[i].setDrawingCacheEnabled(enabled);
- }
- }
- }
-
- @Override
- protected void onAnimationStart() {
- super.onAnimationStart();
-
- // When this ViewGroup's animation starts, build the cache for the children
- if ((mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE) {
- final int count = mChildrenCount;
- final View[] children = mChildren;
-
- for (int i = 0; i < count; i++) {
- final View child = children[i];
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
- child.setDrawingCacheEnabled(true);
- child.buildDrawingCache();
- }
- }
-
- mGroupFlags |= FLAG_CHILDREN_DRAWN_WITH_CACHE;
- }
- }
-
- @Override
- protected void onAnimationEnd() {
- super.onAnimationEnd();
-
- // When this ViewGroup's animation ends, destroy the cache of the children
- if ((mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE) {
- mGroupFlags &= ~FLAG_CHILDREN_DRAWN_WITH_CACHE;
-
- if ((mPersistentDrawingCache & PERSISTENT_ANIMATION_CACHE) == 0) {
- setChildrenDrawingCacheEnabled(false);
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void dispatchDraw(Canvas canvas) {
- final int count = mChildrenCount;
- final View[] children = mChildren;
- int flags = mGroupFlags;
-
- if ((flags & FLAG_RUN_ANIMATION) != 0 && canAnimate()) {
- final boolean cache = (mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE;
-
- for (int i = 0; i < count; i++) {
- final View child = children[i];
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
- final LayoutParams params = child.getLayoutParams();
- attachLayoutAnimationParameters(child, params, i, count);
- bindLayoutAnimation(child);
- if (cache) {
- child.setDrawingCacheEnabled(true);
- child.buildDrawingCache();
- }
- }
- }
-
- final LayoutAnimationController controller = mLayoutAnimationController;
- if (controller.willOverlap()) {
- mGroupFlags |= FLAG_OPTIMIZE_INVALIDATE;
- }
-
- controller.start();
-
- mGroupFlags &= ~FLAG_RUN_ANIMATION;
- mGroupFlags &= ~FLAG_ANIMATION_DONE;
-
- if (cache) {
- mGroupFlags |= FLAG_CHILDREN_DRAWN_WITH_CACHE;
- }
-
- if (mAnimationListener != null) {
- mAnimationListener.onAnimationStart(controller.getAnimation());
- }
- }
-
- int saveCount = 0;
- final boolean clipToPadding = (flags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;
- if (clipToPadding) {
- saveCount = canvas.save();
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
- canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop,
- scrollX + mRight - mLeft - mPaddingRight,
- scrollY + mBottom - mTop - mPaddingBottom);
-
- }
-
- // We will draw our child's animation, let's reset the flag
- mPrivateFlags &= ~DRAW_ANIMATION;
- mGroupFlags &= ~FLAG_INVALIDATE_REQUIRED;
-
- boolean more = false;
- final long drawingTime = getDrawingTime();
-
- if ((flags & FLAG_USE_CHILD_DRAWING_ORDER) == 0) {
- for (int i = 0; i < count; i++) {
- final View child = children[i];
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
- more |= drawChild(canvas, child, drawingTime);
- }
- }
- } else {
- for (int i = 0; i < count; i++) {
- final View child = children[getChildDrawingOrder(count, i)];
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
- more |= drawChild(canvas, child, drawingTime);
- }
- }
- }
-
- // Draw any disappearing views that have animations
- if (mDisappearingChildren != null) {
- final ArrayList<View> disappearingChildren = mDisappearingChildren;
- final int disappearingCount = disappearingChildren.size() - 1;
- // Go backwards -- we may delete as animations finish
- for (int i = disappearingCount; i >= 0; i--) {
- final View child = disappearingChildren.get(i);
- more |= drawChild(canvas, child, drawingTime);
- }
- }
-
- if (clipToPadding) {
- canvas.restoreToCount(saveCount);
- }
-
- // mGroupFlags might have been updated by drawChild()
- flags = mGroupFlags;
-
- if ((flags & FLAG_INVALIDATE_REQUIRED) == FLAG_INVALIDATE_REQUIRED) {
- invalidate();
- }
-
- if ((flags & FLAG_ANIMATION_DONE) == 0 && (flags & FLAG_NOTIFY_ANIMATION_LISTENER) == 0 &&
- mLayoutAnimationController.isDone() && !more) {
- // We want to erase the drawing cache and notify the listener after the
- // next frame is drawn because one extra invalidate() is caused by
- // drawChild() after the animation is over
- mGroupFlags |= FLAG_NOTIFY_ANIMATION_LISTENER;
- final Runnable end = new Runnable() {
- public void run() {
- notifyAnimationListener();
- }
- };
- post(end);
- }
- }
-
- /**
- * Returns the index of the child to draw for this iteration. Override this
- * if you want to change the drawing order of children. By default, it
- * returns i.
- * <p>
- * NOTE: In order for this method to be called, the
- * {@link #FLAG_USE_CHILD_DRAWING_ORDER} must be set.
- *
- * @param i The current iteration.
- * @return The index of the child to draw this iteration.
- */
- protected int getChildDrawingOrder(int childCount, int i) {
- return i;
- }
-
- private void notifyAnimationListener() {
- mGroupFlags &= ~FLAG_NOTIFY_ANIMATION_LISTENER;
- mGroupFlags |= FLAG_ANIMATION_DONE;
-
- if (mAnimationListener != null) {
- final Runnable end = new Runnable() {
- public void run() {
- mAnimationListener.onAnimationEnd(mLayoutAnimationController.getAnimation());
- }
- };
- post(end);
- }
-
- if ((mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE) {
- mGroupFlags &= ~FLAG_CHILDREN_DRAWN_WITH_CACHE;
- if ((mPersistentDrawingCache & PERSISTENT_ANIMATION_CACHE) == 0) {
- setChildrenDrawingCacheEnabled(false);
- }
- }
-
- invalidate();
- }
-
- /**
- * Draw one child of this View Group. This method is responsible for getting
- * the canvas in the right state. This includes clipping, translating so
- * that the child's scrolled origin is at 0, 0, and applying any animation
- * transformations.
- *
- * @param canvas The canvas on which to draw the child
- * @param child Who to draw
- * @param drawingTime The time at which draw is occuring
- * @return True if an invalidate() was issued
- */
- protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
- boolean more = false;
-
- final int cl = child.mLeft;
- final int ct = child.mTop;
- final int cr = child.mRight;
- final int cb = child.mBottom;
-
- final int flags = mGroupFlags;
-
- if ((flags & FLAG_CLEAR_TRANSFORMATION) == FLAG_CLEAR_TRANSFORMATION) {
- if (mChildTransformation != null) {
- mChildTransformation.clear();
- }
- mGroupFlags &= ~FLAG_CLEAR_TRANSFORMATION;
- }
-
- Transformation transformToApply = null;
- final Animation a = child.getAnimation();
- boolean concatMatrix = false;
-
- final int childWidth = cr - cl;
- final int childHeight = cb - ct;
-
- if (a != null) {
- if (mInvalidateRegion == null) {
- mInvalidateRegion = new RectF();
- }
- final RectF region = mInvalidateRegion;
-
- final boolean initialized = a.isInitialized();
- if (!initialized) {
- a.initialize(childWidth, childHeight, getWidth(), getHeight());
- a.initializeInvalidateRegion(0, 0, childWidth, childHeight);
- child.onAnimationStart();
- }
-
- if (mChildTransformation == null) {
- mChildTransformation = new Transformation();
- }
- more = a.getTransformation(drawingTime, mChildTransformation);
- transformToApply = mChildTransformation;
-
- concatMatrix = a.willChangeTransformationMatrix();
-
- if (more) {
- if (!a.willChangeBounds()) {
- if ((flags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) ==
- FLAG_OPTIMIZE_INVALIDATE) {
- mGroupFlags |= FLAG_INVALIDATE_REQUIRED;
- } else if ((flags & FLAG_INVALIDATE_REQUIRED) == 0) {
- // The child need to draw an animation, potentially offscreen, so
- // make sure we do not cancel invalidate requests
- mPrivateFlags |= DRAW_ANIMATION;
- invalidate(cl, ct, cr, cb);
- }
- } else {
- a.getInvalidateRegion(0, 0, childWidth, childHeight, region, transformToApply);
-
- // The child need to draw an animation, potentially offscreen, so
- // make sure we do not cancel invalidate requests
- mPrivateFlags |= DRAW_ANIMATION;
- // Enlarge the invalidate region to account for rounding errors
- // in Animation#getInvalidateRegion(); Using 0.5f is unfortunately
- // not enough for some types of animations (e.g. scale down.)
- final int left = cl + (int) (region.left - 1.0f);
- final int top = ct + (int) (region.top - 1.0f);
- invalidate(left, top,
- left + (int) (region.width() + 1.0f),
- top + (int) (region.height() + 1.0f));
- }
- }
- } else if ((flags & FLAG_SUPPORT_STATIC_TRANSFORMATIONS) ==
- FLAG_SUPPORT_STATIC_TRANSFORMATIONS) {
- if (mChildTransformation == null) {
- mChildTransformation = new Transformation();
- }
- final boolean hasTransform = getChildStaticTransformation(child, mChildTransformation);
- if (hasTransform) {
- final int transformType = mChildTransformation.getTransformationType();
- transformToApply = transformType != Transformation.TYPE_IDENTITY ?
- mChildTransformation : null;
- concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
- }
- }
-
- if (!concatMatrix && canvas.quickReject(cl, ct, cr, cb, Canvas.EdgeType.BW) &&
- (child.mPrivateFlags & DRAW_ANIMATION) == 0) {
- return more;
- }
-
- child.computeScroll();
-
- final int sx = child.mScrollX;
- final int sy = child.mScrollY;
-
- Bitmap cache = null;
- if ((flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE ||
- (flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) {
- cache = child.getDrawingCache();
- }
-
- final boolean hasNoCache = cache == null;
-
- final int restoreTo = canvas.save();
- if (hasNoCache) {
- canvas.translate(cl - sx, ct - sy);
- } else {
- canvas.translate(cl, ct);
- }
-
- float alpha = 1.0f;
-
- if (transformToApply != null) {
- if (concatMatrix) {
- int transX = 0;
- int transY = 0;
- if (hasNoCache) {
- transX = -sx;
- transY = -sy;
- }
- // Undo the scroll translation, apply the transformation matrix,
- // then redo the scroll translate to get the correct result.
- canvas.translate(-transX, -transY);
- canvas.concat(transformToApply.getMatrix());
- canvas.translate(transX, transY);
- mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
- }
-
- alpha = transformToApply.getAlpha();
- if (alpha < 1.0f) {
- mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
- }
-
- if (alpha < 1.0f && hasNoCache) {
- final int multipliedAlpha = (int) (255 * alpha);
- if (!child.onSetAlpha(multipliedAlpha)) {
- canvas.saveLayerAlpha(sx, sy, sx + cr - cl, sy + cb - ct, multipliedAlpha,
- Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
- } else {
- child.mPrivateFlags |= ALPHA_SET;
- }
- }
- } else if ((child.mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
- child.onSetAlpha(255);
- }
-
- if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {
- if (hasNoCache) {
- canvas.clipRect(sx, sy, sx + childWidth, sy + childHeight);
- } else {
- canvas.clipRect(0, 0, childWidth, childHeight);
- }
- }
-
- // Clear the flag as early as possible to allow draw() implementations
- // to call invalidate() successfully when doing animations
- child.mPrivateFlags |= DRAWN;
-
- if (hasNoCache) {
- // Fast path for layouts with no backgrounds
- if ((child.mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
- if (ViewDebug.TRACE_HIERARCHY) {
- ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
- }
- child.dispatchDraw(canvas);
- } else {
- child.draw(canvas);
- }
- } else {
- final Paint cachePaint = mCachePaint;
- if (alpha < 1.0f) {
- cachePaint.setAlpha((int) (alpha * 255));
- mGroupFlags |= FLAG_ALPHA_LOWER_THAN_ONE;
- } else if ((flags & FLAG_ALPHA_LOWER_THAN_ONE) == FLAG_ALPHA_LOWER_THAN_ONE) {
- cachePaint.setAlpha(255);
- mGroupFlags &= ~FLAG_ALPHA_LOWER_THAN_ONE;
- }
- if (ViewRoot.PROFILE_DRAWING) {
- EventLog.writeEvent(60003, hashCode());
- }
- canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
- }
-
- canvas.restoreToCount(restoreTo);
-
- if (a != null && !more) {
- child.onSetAlpha(255);
- finishAnimatingView(child, a);
- }
-
- return more;
- }
-
- /**
- * By default, children are clipped to their bounds before drawing. This
- * allows view groups to override this behavior for animations, etc.
- *
- * @param clipChildren true to clip children to their bounds,
- * false otherwise
- * @attr ref android.R.styleable#ViewGroup_clipChildren
- */
- public void setClipChildren(boolean clipChildren) {
- setBooleanFlag(FLAG_CLIP_CHILDREN, clipChildren);
- }
-
- /**
- * By default, children are clipped to the padding of the ViewGroup. This
- * allows view groups to override this behavior
- *
- * @param clipToPadding true to clip children to the padding of the
- * group, false otherwise
- * @attr ref android.R.styleable#ViewGroup_clipToPadding
- */
- public void setClipToPadding(boolean clipToPadding) {
- setBooleanFlag(FLAG_CLIP_TO_PADDING, clipToPadding);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void dispatchSetSelected(boolean selected) {
- final View[] children = mChildren;
- final int count = mChildrenCount;
- for (int i = 0; i < count; i++) {
- children[i].setSelected(selected);
- }
- }
-
- @Override
- protected void dispatchSetPressed(boolean pressed) {
- final View[] children = mChildren;
- final int count = mChildrenCount;
- for (int i = 0; i < count; i++) {
- children[i].setPressed(pressed);
- }
- }
-
- /**
- * When this property is set to true, this ViewGroup supports static transformations on
- * children; this causes
- * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} to be
- * invoked when a child is drawn.
- *
- * Any subclass overriding
- * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} should
- * set this property to true.
- *
- * @param enabled True to enable static transformations on children, false otherwise.
- *
- * @see #FLAG_SUPPORT_STATIC_TRANSFORMATIONS
- */
- protected void setStaticTransformationsEnabled(boolean enabled) {
- setBooleanFlag(FLAG_SUPPORT_STATIC_TRANSFORMATIONS, enabled);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #setStaticTransformationsEnabled(boolean)
- */
- protected boolean getChildStaticTransformation(View child, Transformation t) {
- return false;
- }
-
- /**
- * {@hide}
- */
- @Override
- protected View findViewTraversal(int id) {
- if (id == mID) {
- return this;
- }
-
- final View[] where = mChildren;
- final int len = mChildrenCount;
-
- for (int i = 0; i < len; i++) {
- View v = where[i];
-
- if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
- v = v.findViewById(id);
-
- if (v != null) {
- return v;
- }
- }
- }
-
- return null;
- }
-
- /**
- * {@hide}
- */
- @Override
- protected View findViewWithTagTraversal(Object tag) {
- if (tag != null && tag.equals(mTag)) {
- return this;
- }
-
- final View[] where = mChildren;
- final int len = mChildrenCount;
-
- for (int i = 0; i < len; i++) {
- View v = where[i];
-
- if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
- v = v.findViewWithTag(tag);
-
- if (v != null) {
- return v;
- }
- }
- }
-
- return null;
- }
-
- /**
- * Adds a child view. If no layout parameters are already set on the child, the
- * default parameters for this ViewGroup are set on the child.
- *
- * @param child the child view to add
- *
- * @see #generateDefaultLayoutParams()
- */
- public void addView(View child) {
- addView(child, -1);
- }
-
- /**
- * Adds a child view. If no layout parameters are already set on the child, the
- * default parameters for this ViewGroup are set on the child.
- *
- * @param child the child view to add
- * @param index the position at which to add the child
- *
- * @see #generateDefaultLayoutParams()
- */
- public void addView(View child, int index) {
- LayoutParams params = child.getLayoutParams();
- if (params == null) {
- params = generateDefaultLayoutParams();
- if (params == null) {
- throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
- }
- }
- addView(child, index, params);
- }
-
- /**
- * Adds a child view with this ViewGroup's default layout parameters and the
- * specified width and height.
- *
- * @param child the child view to add
- */
- public void addView(View child, int width, int height) {
- final LayoutParams params = generateDefaultLayoutParams();
- params.width = width;
- params.height = height;
- addView(child, -1, params);
- }
-
- /**
- * Adds a child view with the specified layout parameters.
- *
- * @param child the child view to add
- * @param params the layout parameters to set on the child
- */
- public void addView(View child, LayoutParams params) {
- addView(child, -1, params);
- }
-
- /**
- * Adds a child view with the specified layout parameters.
- *
- * @param child the child view to add
- * @param index the position at which to add the child
- * @param params the layout parameters to set on the child
- */
- public void addView(View child, int index, LayoutParams params) {
- if (DBG) {
- System.out.println(this + " addView");
- }
-
- // addViewInner() will call child.requestLayout() when setting the new LayoutParams
- // therefore, we call requestLayout() on ourselves before, so that the child's request
- // will be blocked at our level
- requestLayout();
- invalidate();
- addViewInner(child, index, params, false);
- }
-
- /**
- * {@inheritDoc}
- */
- public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
- if (!checkLayoutParams(params)) {
- throw new IllegalArgumentException("Invalid LayoutParams supplied to " + this);
- }
- if (view.mParent != this) {
- throw new IllegalArgumentException("Given view not a child of " + this);
- }
- view.setLayoutParams(params);
- }
-
- /**
- * {@inheritDoc}
- */
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p != null;
- }
-
- /**
- * Interface definition for a callback to be invoked when the hierarchy
- * within this view changed. The hierarchy changes whenever a child is added
- * to or removed from this view.
- */
- public interface OnHierarchyChangeListener {
- /**
- * Called when a new child is added to a parent view.
- *
- * @param parent the view in which a child was added
- * @param child the new child view added in the hierarchy
- */
- void onChildViewAdded(View parent, View child);
-
- /**
- * Called when a child is removed from a parent view.
- *
- * @param parent the view from which the child was removed
- * @param child the child removed from the hierarchy
- */
- void onChildViewRemoved(View parent, View child);
- }
-
- /**
- * Register a callback to be invoked when a child is added to or removed
- * from this view.
- *
- * @param listener the callback to invoke on hierarchy change
- */
- public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
- mOnHierarchyChangeListener = listener;
- }
-
- /**
- * Adds a view during layout. This is useful if in your onLayout() method,
- * you need to add more views (as does the list view for example).
- *
- * If index is negative, it means put it at the end of the list.
- *
- * @param child the view to add to the group
- * @param index the index at which the child must be added
- * @param params the layout parameters to associate with the child
- * @return true if the child was added, false otherwise
- */
- protected boolean addViewInLayout(View child, int index, LayoutParams params) {
- return addViewInLayout(child, index, params, false);
- }
-
- /**
- * Adds a view during layout. This is useful if in your onLayout() method,
- * you need to add more views (as does the list view for example).
- *
- * If index is negative, it means put it at the end of the list.
- *
- * @param child the view to add to the group
- * @param index the index at which the child must be added
- * @param params the layout parameters to associate with the child
- * @param preventRequestLayout if true, calling this method will not trigger a
- * layout request on child
- * @return true if the child was added, false otherwise
- */
- protected boolean addViewInLayout(View child, int index, LayoutParams params,
- boolean preventRequestLayout) {
- child.mParent = null;
- addViewInner(child, index, params, preventRequestLayout);
- child.mPrivateFlags |= DRAWN;
- return true;
- }
-
- /**
- * Prevents the specified child to be laid out during the next layout pass.
- *
- * @param child the child on which to perform the cleanup
- */
- protected void cleanupLayoutState(View child) {
- child.mPrivateFlags &= ~View.FORCE_LAYOUT;
- }
-
- private void addViewInner(View child, int index, LayoutParams params,
- boolean preventRequestLayout) {
-
- if (child.getParent() != null) {
- throw new IllegalStateException("The specified child already has a parent. " +
- "You must call removeView() on the child's parent first.");
- }
-
- if (!checkLayoutParams(params)) {
- params = generateLayoutParams(params);
- }
-
- if (preventRequestLayout) {
- child.mLayoutParams = params;
- } else {
- child.setLayoutParams(params);
- }
-
- if (index < 0) {
- index = mChildrenCount;
- }
-
- addInArray(child, index);
-
- // tell our children
- if (preventRequestLayout) {
- child.assignParent(this);
- } else {
- child.mParent = this;
- }
-
- if (child.hasFocus()) {
- requestChildFocus(child, child.findFocus());
- }
-
- AttachInfo ai = mAttachInfo;
- if (ai != null) {
- boolean lastKeepOn = ai.mKeepScreenOn;
- ai.mKeepScreenOn = false;
- child.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK));
- if (ai.mKeepScreenOn) {
- needGlobalAttributesUpdate(true);
- }
- ai.mKeepScreenOn = lastKeepOn;
- }
-
- if (mOnHierarchyChangeListener != null) {
- mOnHierarchyChangeListener.onChildViewAdded(this, child);
- }
-
- if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) {
- mGroupFlags |= FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE;
- }
- }
-
- private void addInArray(View child, int index) {
- View[] children = mChildren;
- final int count = mChildrenCount;
- final int size = children.length;
- if (index == count) {
- if (size == count) {
- mChildren = new View[size + ARRAY_CAPACITY_INCREMENT];
- System.arraycopy(children, 0, mChildren, 0, size);
- children = mChildren;
- }
- children[mChildrenCount++] = child;
- } else if (index < count) {
- if (size == count) {
- mChildren = new View[size + ARRAY_CAPACITY_INCREMENT];
- System.arraycopy(children, 0, mChildren, 0, index);
- System.arraycopy(children, index, mChildren, index + 1, count - index);
- children = mChildren;
- } else {
- System.arraycopy(children, index, children, index + 1, count - index);
- }
- children[index] = child;
- mChildrenCount++;
- } else {
- throw new IndexOutOfBoundsException("index=" + index + " count=" + count);
- }
- }
-
- // This method also sets the child's mParent to null
- private void removeFromArray(int index) {
- final View[] children = mChildren;
- children[index].mParent = null;
- final int count = mChildrenCount;
- if (index == count - 1) {
- children[--mChildrenCount] = null;
- } else if (index >= 0 && index < count) {
- System.arraycopy(children, index + 1, children, index, count - index - 1);
- children[--mChildrenCount] = null;
- } else {
- throw new IndexOutOfBoundsException();
- }
- }
-
- // This method also sets the children's mParent to null
- private void removeFromArray(int start, int count) {
- final View[] children = mChildren;
- final int childrenCount = mChildrenCount;
-
- start = Math.max(0, start);
- final int end = Math.min(childrenCount, start + count);
-
- if (start == end) {
- return;
- }
-
- if (end == childrenCount) {
- for (int i = start; i < end; i++) {
- children[i].mParent = null;
- children[i] = null;
- }
- } else {
- for (int i = start; i < end; i++) {
- children[i].mParent = null;
- }
-
- // Since we're looping above, we might as well do the copy, but is arraycopy()
- // faster than the extra 2 bounds checks we would do in the loop?
- System.arraycopy(children, end, children, start, childrenCount - end);
-
- for (int i = childrenCount - (end - start); i < childrenCount; i++) {
- children[i] = null;
- }
- }
-
- mChildrenCount -= (end - start);
- }
-
- private void bindLayoutAnimation(View child) {
- Animation a = mLayoutAnimationController.getAnimationForView(child);
- child.setAnimation(a);
- }
-
- /**
- * Subclasses should override this method to set layout animation
- * parameters on the supplied child.
- *
- * @param child the child to associate with animation parameters
- * @param params the child's layout parameters which hold the animation
- * parameters
- * @param index the index of the child in the view group
- * @param count the number of children in the view group
- */
- protected void attachLayoutAnimationParameters(View child,
- LayoutParams params, int index, int count) {
- LayoutAnimationController.AnimationParameters animationParams =
- params.layoutAnimationParameters;
- if (animationParams == null) {
- animationParams = new LayoutAnimationController.AnimationParameters();
- params.layoutAnimationParameters = animationParams;
- }
-
- animationParams.count = count;
- animationParams.index = index;
- }
-
- /**
- * {@inheritDoc}
- */
- public void removeView(View view) {
- removeViewInternal(view);
- requestLayout();
- invalidate();
- }
-
- /**
- * Removes a view during layout. This is useful if in your onLayout() method,
- * you need to remove more views.
- *
- * @param view the view to remove from the group
- */
- public void removeViewInLayout(View view) {
- removeViewInternal(view);
- }
-
- /**
- * Removes a range of views during layout. This is useful if in your onLayout() method,
- * you need to remove more views.
- *
- * @param start the index of the first view to remove from the group
- * @param count the number of views to remove from the group
- */
- public void removeViewsInLayout(int start, int count) {
- removeViewsInternal(start, count);
- }
-
- /**
- * Removes the view at the specified position in the group.
- *
- * @param index the position in the group of the view to remove
- */
- public void removeViewAt(int index) {
- removeViewInternal(index, getChildAt(index));
- requestLayout();
- invalidate();
- }
-
- /**
- * Removes the specified range of views from the group.
- *
- * @param start the first position in the group of the range of views to remove
- * @param count the number of views to remove
- */
- public void removeViews(int start, int count) {
- removeViewsInternal(start, count);
- requestLayout();
- invalidate();
- }
-
- private void removeViewInternal(View view) {
- final int index = indexOfChild(view);
- if (index >= 0) {
- removeViewInternal(index, view);
- }
- }
-
- private void removeViewInternal(int index, View view) {
- boolean clearChildFocus = false;
- if (view == mFocused) {
- view.clearFocusForRemoval();
- clearChildFocus = true;
- }
-
- if (view.getAnimation() != null) {
- addDisappearingView(view);
- } else if (view.mAttachInfo != null) {
- view.dispatchDetachedFromWindow();
- }
-
- if (mOnHierarchyChangeListener != null) {
- mOnHierarchyChangeListener.onChildViewRemoved(this, view);
- }
-
- needGlobalAttributesUpdate(false);
-
- removeFromArray(index);
-
- if (clearChildFocus) {
- clearChildFocus(view);
- }
- }
-
- private void removeViewsInternal(int start, int count) {
- final OnHierarchyChangeListener onHierarchyChangeListener = mOnHierarchyChangeListener;
- final boolean notifyListener = onHierarchyChangeListener != null;
- final View focused = mFocused;
- final boolean detach = mAttachInfo != null;
- View clearChildFocus = null;
-
- final View[] children = mChildren;
- final int end = start + count;
-
- for (int i = start; i < end; i++) {
- final View view = children[i];
-
- if (view == focused) {
- view.clearFocusForRemoval();
- clearChildFocus = view;
- }
-
- if (view.getAnimation() != null) {
- addDisappearingView(view);
- } else if (detach) {
- view.dispatchDetachedFromWindow();
- }
-
- needGlobalAttributesUpdate(false);
-
- if (notifyListener) {
- onHierarchyChangeListener.onChildViewRemoved(this, view);
- }
- }
-
- removeFromArray(start, count);
-
- if (clearChildFocus != null) {
- clearChildFocus(clearChildFocus);
- }
- }
-
- /**
- * Call this method to remove all child views from the
- * ViewGroup.
- */
- public void removeAllViews() {
- removeAllViewsInLayout();
- requestLayout();
- invalidate();
- }
-
- /**
- * Called by a ViewGroup subclass to remove child views from itself,
- * when it must first know its size on screen before it can calculate how many
- * child views it will render. An example is a Gallery or a ListView, which
- * may "have" 50 children, but actually only render the number of children
- * that can currently fit inside the object on screen. Do not call
- * this method unless you are extending ViewGroup and understand the
- * view measuring and layout pipeline.
- */
- public void removeAllViewsInLayout() {
- final int count = mChildrenCount;
- if (count <= 0) {
- return;
- }
-
- final View[] children = mChildren;
- mChildrenCount = 0;
-
- final OnHierarchyChangeListener listener = mOnHierarchyChangeListener;
- final boolean notify = listener != null;
- final View focused = mFocused;
- final boolean detach = mAttachInfo != null;
- View clearChildFocus = null;
-
- needGlobalAttributesUpdate(false);
-
- for (int i = count - 1; i >= 0; i--) {
- final View view = children[i];
-
- if (view == focused) {
- view.clearFocusForRemoval();
- clearChildFocus = view;
- }
-
- if (view.getAnimation() != null) {
- addDisappearingView(view);
- } else if (detach) {
- view.dispatchDetachedFromWindow();
- }
-
- if (notify) {
- listener.onChildViewRemoved(this, view);
- }
-
- view.mParent = null;
- children[i] = null;
- }
-
- if (clearChildFocus != null) {
- clearChildFocus(clearChildFocus);
- }
- }
-
- /**
- * Finishes the removal of a detached view. This method will dispatch the detached from
- * window event and notify the hierarchy change listener.
- *
- * @param child the child to be definitely removed from the view hierarchy
- * @param animate if true and the view has an animation, the view is placed in the
- * disappearing views list, otherwise, it is detached from the window
- *
- * @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)
- * @see #detachAllViewsFromParent()
- * @see #detachViewFromParent(View)
- * @see #detachViewFromParent(int)
- */
- protected void removeDetachedView(View child, boolean animate) {
- if (child == mFocused) {
- child.clearFocus();
- }
-
- if (animate && child.getAnimation() != null) {
- addDisappearingView(child);
- } else if (child.mAttachInfo != null) {
- child.dispatchDetachedFromWindow();
- }
-
- if (mOnHierarchyChangeListener != null) {
- mOnHierarchyChangeListener.onChildViewRemoved(this, child);
- }
- }
-
- /**
- * Attaches a view to this view group. Attaching a view assigns this group as the parent,
- * sets the layout parameters and puts the view in the list of children so it can be retrieved
- * by calling {@link #getChildAt(int)}.
- *
- * This method should be called only for view which were detached from their parent.
- *
- * @param child the child to attach
- * @param index the index at which the child should be attached
- * @param params the layout parameters of the child
- *
- * @see #removeDetachedView(View, boolean)
- * @see #detachAllViewsFromParent()
- * @see #detachViewFromParent(View)
- * @see #detachViewFromParent(int)
- */
- protected void attachViewToParent(View child, int index, LayoutParams params) {
- child.mLayoutParams = params;
-
- if (index < 0) {
- index = mChildrenCount;
- }
-
- addInArray(child, index);
-
- child.mParent = this;
- child.mPrivateFlags |= DRAWN;
-
- if (child.hasFocus()) {
- requestChildFocus(child, child.findFocus());
- }
- }
-
- /**
- * Detaches a view from its parent. Detaching a view should be temporary and followed
- * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
- * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached,
- * its parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}.
- *
- * @param child the child to detach
- *
- * @see #detachViewFromParent(int)
- * @see #detachViewsFromParent(int, int)
- * @see #detachAllViewsFromParent()
- * @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)
- * @see #removeDetachedView(View, boolean)
- */
- protected void detachViewFromParent(View child) {
- removeFromArray(indexOfChild(child));
- }
-
- /**
- * Detaches a view from its parent. Detaching a view should be temporary and followed
- * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
- * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached,
- * its parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}.
- *
- * @param index the index of the child to detach
- *
- * @see #detachViewFromParent(View)
- * @see #detachAllViewsFromParent()
- * @see #detachViewsFromParent(int, int)
- * @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)
- * @see #removeDetachedView(View, boolean)
- */
- protected void detachViewFromParent(int index) {
- removeFromArray(index);
- }
-
- /**
- * Detaches a range of view from their parent. Detaching a view should be temporary and followed
- * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
- * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached, its
- * parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}.
- *
- * @param start the first index of the childrend range to detach
- * @param count the number of children to detach
- *
- * @see #detachViewFromParent(View)
- * @see #detachViewFromParent(int)
- * @see #detachAllViewsFromParent()
- * @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)
- * @see #removeDetachedView(View, boolean)
- */
- protected void detachViewsFromParent(int start, int count) {
- removeFromArray(start, count);
- }
-
- /**
- * Detaches all views from the parent. Detaching a view should be temporary and followed
- * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
- * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached,
- * its parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}.
- *
- * @see #detachViewFromParent(View)
- * @see #detachViewFromParent(int)
- * @see #detachViewsFromParent(int, int)
- * @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)
- * @see #removeDetachedView(View, boolean)
- */
- protected void detachAllViewsFromParent() {
- final int count = mChildrenCount;
- if (count <= 0) {
- return;
- }
-
- final View[] children = mChildren;
- mChildrenCount = 0;
-
- for (int i = count - 1; i >= 0; i--) {
- children[i].mParent = null;
- children[i] = null;
- }
- }
-
- /**
- * Don't call or override this method. It is used for the implementation of
- * the view hierarchy.
- */
- public final void invalidateChild(View child, final Rect dirty) {
- if (ViewDebug.TRACE_HIERARCHY) {
- ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE_CHILD);
- }
-
- ViewParent parent = this;
-
- final AttachInfo attachInfo = mAttachInfo;
- if (attachInfo != null) {
- final int[] location = attachInfo.mInvalidateChildLocation;
- location[CHILD_LEFT_INDEX] = child.mLeft;
- location[CHILD_TOP_INDEX] = child.mTop;
-
- // If the child is drawing an animation, we want to copy this flag onto
- // ourselves and the parent to make sure the invalidate request goes
- // through
- final boolean drawAnimation = (child.mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION;
-
- do {
- if (drawAnimation && parent instanceof View) {
- ((View) parent).mPrivateFlags |= DRAW_ANIMATION;
- }
- parent = parent.invalidateChildInParent(location, dirty);
- } while (parent != null);
- }
- }
-
- /**
- * Don't call or override this method. It is used for the implementation of
- * the view hierarchy.
- *
- * This implementation returns null if this ViewGroup does not have a parent,
- * if this ViewGroup is already fully invalidated or if the dirty rectangle
- * does not intersect with this ViewGroup's bounds.
- */
- public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {
- if (ViewDebug.TRACE_HIERARCHY) {
- ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE_CHILD_IN_PARENT);
- }
-
- if ((mPrivateFlags & DRAWN) == DRAWN) {
- if ((mGroupFlags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) !=
- FLAG_OPTIMIZE_INVALIDATE) {
- dirty.offset(location[CHILD_LEFT_INDEX] - mScrollX,
- location[CHILD_TOP_INDEX] - mScrollY);
-
- final int left = mLeft;
- final int top = mTop;
-
- if (dirty.intersect(0, 0, mRight - left, mBottom - top) ||
- (mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) {
- mPrivateFlags &= ~DRAWING_CACHE_VALID;
-
- location[CHILD_LEFT_INDEX] = left;
- location[CHILD_TOP_INDEX] = top;
-
- return mParent;
- }
- } else {
- mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID;
-
- location[CHILD_LEFT_INDEX] = mLeft;
- location[CHILD_TOP_INDEX] = mTop;
-
- dirty.set(0, 0, mRight - location[CHILD_LEFT_INDEX],
- mBottom - location[CHILD_TOP_INDEX]);
-
- return mParent;
- }
- }
-
- return null;
- }
-
- /**
- * Offset a rectangle that is in a descendant's coordinate
- * space into our coordinate space.
- * @param descendant A descendant of this view
- * @param rect A rectangle defined in descendant's coordinate space.
- */
- public final void offsetDescendantRectToMyCoords(View descendant, Rect rect) {
- offsetRectBetweenParentAndChild(descendant, rect, true, false);
- }
-
- /**
- * Offset a rectangle that is in our coordinate space into an ancestor's
- * coordinate space.
- * @param descendant A descendant of this view
- * @param rect A rectangle defined in descendant's coordinate space.
- */
- public final void offsetRectIntoDescendantCoords(View descendant, Rect rect) {
- offsetRectBetweenParentAndChild(descendant, rect, false, false);
- }
-
- /**
- * Helper method that offsets a rect either from parent to descendant or
- * descendant to parent.
- */
- void offsetRectBetweenParentAndChild(View descendant, Rect rect,
- boolean offsetFromChildToParent, boolean clipToBounds) {
-
- // already in the same coord system :)
- if (descendant == this) {
- return;
- }
-
- ViewParent theParent = descendant.mParent;
-
- // search and offset up to the parent
- while ((theParent != null)
- && (theParent instanceof View)
- && (theParent != this)) {
-
- if (offsetFromChildToParent) {
- rect.offset(descendant.mLeft - descendant.mScrollX,
- descendant.mTop - descendant.mScrollY);
- if (clipToBounds) {
- View p = (View) theParent;
- rect.intersect(0, 0, p.mRight - p.mLeft, p.mBottom - p.mTop);
- }
- } else {
- if (clipToBounds) {
- View p = (View) theParent;
- rect.intersect(0, 0, p.mRight - p.mLeft, p.mBottom - p.mTop);
- }
- rect.offset(descendant.mScrollX - descendant.mLeft,
- descendant.mScrollY - descendant.mTop);
- }
-
- descendant = (View) theParent;
- theParent = descendant.mParent;
- }
-
- // now that we are up to this view, need to offset one more time
- // to get into our coordinate space
- if (theParent == this) {
- if (offsetFromChildToParent) {
- rect.offset(descendant.mLeft - descendant.mScrollX,
- descendant.mTop - descendant.mScrollY);
- } else {
- rect.offset(descendant.mScrollX - descendant.mLeft,
- descendant.mScrollY - descendant.mTop);
- }
- } else {
- throw new IllegalArgumentException("parameter must be a descendant of this view");
- }
- }
-
- /**
- * Offset the vertical location of all children of this view by the specified number of pixels.
- *
- * @param offset the number of pixels to offset
- *
- * @hide
- */
- public void offsetChildrenTopAndBottom(int offset) {
- final int count = mChildrenCount;
- final View[] children = mChildren;
-
- for (int i = 0; i < count; i++) {
- final View v = children[i];
- v.mTop += offset;
- v.mBottom += offset;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) {
- int dx = child.mLeft - mScrollX;
- int dy = child.mTop - mScrollY;
- if (offset != null) {
- offset.x += dx;
- offset.y += dy;
- }
- r.offset(dx, dy);
- return r.intersect(0, 0, mRight - mLeft, mBottom - mTop) &&
- (mParent == null || mParent.getChildVisibleRect(this, r, offset));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected abstract void onLayout(boolean changed,
- int l, int t, int r, int b);
-
- /**
- * Indicates whether the view group has the ability to animate its children
- * after the first layout.
- *
- * @return true if the children can be animated, false otherwise
- */
- protected boolean canAnimate() {
- return mLayoutAnimationController != null;
- }
-
- /**
- * Runs the layout animation. Calling this method triggers a relayout of
- * this view group.
- */
- public void startLayoutAnimation() {
- if (mLayoutAnimationController != null) {
- mGroupFlags |= FLAG_RUN_ANIMATION;
- requestLayout();
- }
- }
-
- /**
- * Schedules the layout animation to be played after the next layout pass
- * of this view group. This can be used to restart the layout animation
- * when the content of the view group changes or when the activity is
- * paused and resumed.
- */
- public void scheduleLayoutAnimation() {
- mGroupFlags |= FLAG_RUN_ANIMATION;
- }
-
- /**
- * Sets the layout animation controller used to animate the group's
- * children after the first layout.
- *
- * @param controller the animation controller
- */
- public void setLayoutAnimation(LayoutAnimationController controller) {
- mLayoutAnimationController = controller;
- if (mLayoutAnimationController != null) {
- mGroupFlags |= FLAG_RUN_ANIMATION;
- }
- }
-
- /**
- * Returns the layout animation controller used to animate the group's
- * children.
- *
- * @return the current animation controller
- */
- public LayoutAnimationController getLayoutAnimation() {
- return mLayoutAnimationController;
- }
-
- /**
- * Indicates whether the children's drawing cache is used during a layout
- * animation. By default, the drawing cache is enabled but this will prevent
- * nested layout animations from working. To nest animations, you must disable
- * the cache.
- *
- * @return true if the animation cache is enabled, false otherwise
- *
- * @see #setAnimationCacheEnabled(boolean)
- * @see View#setDrawingCacheEnabled(boolean)
- */
- @ViewDebug.ExportedProperty
- public boolean isAnimationCacheEnabled() {
- return (mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE;
- }
-
- /**
- * Enables or disables the children's drawing cache during a layout animation.
- * By default, the drawing cache is enabled but this will prevent nested
- * layout animations from working. To nest animations, you must disable the
- * cache.
- *
- * @param enabled true to enable the animation cache, false otherwise
- *
- * @see #isAnimationCacheEnabled()
- * @see View#setDrawingCacheEnabled(boolean)
- */
- public void setAnimationCacheEnabled(boolean enabled) {
- setBooleanFlag(FLAG_ANIMATION_CACHE, enabled);
- }
-
- /**
- * Indicates whether this ViewGroup will always try to draw its children using their
- * drawing cache. By default this property is enabled.
- *
- * @return true if the animation cache is enabled, false otherwise
- *
- * @see #setAlwaysDrawnWithCacheEnabled(boolean)
- * @see #setChildrenDrawnWithCacheEnabled(boolean)
- * @see View#setDrawingCacheEnabled(boolean)
- */
- @ViewDebug.ExportedProperty
- public boolean isAlwaysDrawnWithCacheEnabled() {
- return (mGroupFlags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE;
- }
-
- /**
- * Indicates whether this ViewGroup will always try to draw its children using their
- * drawing cache. This property can be set to true when the cache rendering is
- * slightly different from the children's normal rendering. Renderings can be different,
- * for instance, when the cache's quality is set to low.
- *
- * When this property is disabled, the ViewGroup will use the drawing cache of its
- * children only when asked to. It's usually the task of subclasses to tell ViewGroup
- * when to start using the drawing cache and when to stop using it.
- *
- * @param always true to always draw with the drawing cache, false otherwise
- *
- * @see #isAlwaysDrawnWithCacheEnabled()
- * @see #setChildrenDrawnWithCacheEnabled(boolean)
- * @see View#setDrawingCacheEnabled(boolean)
- * @see View#setDrawingCacheQuality(int)
- */
- public void setAlwaysDrawnWithCacheEnabled(boolean always) {
- setBooleanFlag(FLAG_ALWAYS_DRAWN_WITH_CACHE, always);
- }
-
- /**
- * Indicates whether the ViewGroup is currently drawing its children using
- * their drawing cache.
- *
- * @return true if children should be drawn with their cache, false otherwise
- *
- * @see #setAlwaysDrawnWithCacheEnabled(boolean)
- * @see #setChildrenDrawnWithCacheEnabled(boolean)
- */
- @ViewDebug.ExportedProperty
- protected boolean isChildrenDrawnWithCacheEnabled() {
- return (mGroupFlags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE;
- }
-
- /**
- * Tells the ViewGroup to draw its children using their drawing cache. This property
- * is ignored when {@link #isAlwaysDrawnWithCacheEnabled()} is true. A child's drawing cache
- * will be used only if it has been enabled.
- *
- * Subclasses should call this method to start and stop using the drawing cache when
- * they perform performance sensitive operations, like scrolling or animating.
- *
- * @param enabled true if children should be drawn with their cache, false otherwise
- *
- * @see #setAlwaysDrawnWithCacheEnabled(boolean)
- * @see #isChildrenDrawnWithCacheEnabled()
- */
- protected void setChildrenDrawnWithCacheEnabled(boolean enabled) {
- setBooleanFlag(FLAG_CHILDREN_DRAWN_WITH_CACHE, enabled);
- }
-
- private void setBooleanFlag(int flag, boolean value) {
- if (value) {
- mGroupFlags |= flag;
- } else {
- mGroupFlags &= ~flag;
- }
- }
-
- /**
- * Returns an integer indicating what types of drawing caches are kept in memory.
- *
- * @see #setPersistentDrawingCache(int)
- * @see #setAnimationCacheEnabled(boolean)
- *
- * @return one or a combination of {@link #PERSISTENT_NO_CACHE},
- * {@link #PERSISTENT_ANIMATION_CACHE}, {@link #PERSISTENT_SCROLLING_CACHE}
- * and {@link #PERSISTENT_ALL_CACHES}
- */
- @ViewDebug.ExportedProperty(mapping = {
- @ViewDebug.IntToString(from = PERSISTENT_NO_CACHE, to = "NONE"),
- @ViewDebug.IntToString(from = PERSISTENT_ALL_CACHES, to = "ANIMATION"),
- @ViewDebug.IntToString(from = PERSISTENT_SCROLLING_CACHE, to = "SCROLLING"),
- @ViewDebug.IntToString(from = PERSISTENT_ALL_CACHES, to = "ALL")
- })
- public int getPersistentDrawingCache() {
- return mPersistentDrawingCache;
- }
-
- /**
- * Indicates what types of drawing caches should be kept in memory after
- * they have been created.
- *
- * @see #getPersistentDrawingCache()
- * @see #setAnimationCacheEnabled(boolean)
- *
- * @param drawingCacheToKeep one or a combination of {@link #PERSISTENT_NO_CACHE},
- * {@link #PERSISTENT_ANIMATION_CACHE}, {@link #PERSISTENT_SCROLLING_CACHE}
- * and {@link #PERSISTENT_ALL_CACHES}
- */
- public void setPersistentDrawingCache(int drawingCacheToKeep) {
- mPersistentDrawingCache = drawingCacheToKeep & PERSISTENT_ALL_CACHES;
- }
-
- /**
- * Returns a new set of layout parameters based on the supplied attributes set.
- *
- * @param attrs the attributes to build the layout parameters from
- *
- * @return an instance of {@link android.view.ViewGroup.LayoutParams} or one
- * of its descendants
- */
- public LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new LayoutParams(getContext(), attrs);
- }
-
- /**
- * Returns a safe set of layout parameters based on the supplied layout params.
- * When a ViewGroup is passed a View whose layout params do not pass the test of
- * {@link #checkLayoutParams(android.view.ViewGroup.LayoutParams)}, this method
- * is invoked. This method should return a new set of layout params suitable for
- * this ViewGroup, possibly by copying the appropriate attributes from the
- * specified set of layout params.
- *
- * @param p The layout parameters to convert into a suitable set of layout parameters
- * for this ViewGroup.
- *
- * @return an instance of {@link android.view.ViewGroup.LayoutParams} or one
- * of its descendants
- */
- protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return p;
- }
-
- /**
- * Returns a set of default layout parameters. These parameters are requested
- * when the View passed to {@link #addView(View)} has no layout parameters
- * already set. If null is returned, an exception is thrown from addView.
- *
- * @return a set of default layout parameters or null
- */
- protected LayoutParams generateDefaultLayoutParams() {
- return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void debug(int depth) {
- super.debug(depth);
- String output;
-
- if (mFocused != null) {
- output = debugIndent(depth);
- output += "mFocused";
- Log.d(VIEW_LOG_TAG, output);
- }
- if (mChildrenCount != 0) {
- output = debugIndent(depth);
- output += "{";
- Log.d(VIEW_LOG_TAG, output);
- }
- int count = mChildrenCount;
- for (int i = 0; i < count; i++) {
- View child = mChildren[i];
- child.debug(depth + 1);
- }
-
- if (mChildrenCount != 0) {
- output = debugIndent(depth);
- output += "}";
- Log.d(VIEW_LOG_TAG, output);
- }
- }
-
- /**
- * Returns the position in the group of the specified child view.
- *
- * @param child the view for which to get the position
- * @return a positive integer representing the position of the view in the
- * group, or -1 if the view does not exist in the group
- */
- public int indexOfChild(View child) {
- final int count = mChildrenCount;
- final View[] children = mChildren;
- for (int i = 0; i < count; i++) {
- if (children[i] == child) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Returns the number of children in the group.
- *
- * @return a positive integer representing the number of children in
- * the group
- */
- public int getChildCount() {
- return mChildrenCount;
- }
-
- /**
- * Returns the view at the specified position in the group.
- *
- * @param index the position at which to get the view from
- * @return the view at the specified position or null if the position
- * does not exist within the group
- */
- public View getChildAt(int index) {
- try {
- return mChildren[index];
- } catch (IndexOutOfBoundsException ex) {
- return null;
- }
- }
-
- /**
- * Ask all of the children of this view to measure themselves, taking into
- * account both the MeasureSpec requirements for this view and its padding.
- * We skip children that are in the GONE state The heavy lifting is done in
- * getChildMeasureSpec.
- *
- * @param widthMeasureSpec The width requirements for this view
- * @param heightMeasureSpec The height requirements for this view
- */
- protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
- final int size = mChildrenCount;
- final View[] children = mChildren;
- for (int i = 0; i < size; ++i) {
- final View child = children[i];
- if ((child.mViewFlags & VISIBILITY_MASK) != GONE) {
- measureChild(child, widthMeasureSpec, heightMeasureSpec);
- }
- }
- }
-
- /**
- * Ask one of the children of this view to measure itself, taking into
- * account both the MeasureSpec requirements for this view and its padding.
- * The heavy lifting is done in getChildMeasureSpec.
- *
- * @param child The child to measure
- * @param parentWidthMeasureSpec The width requirements for this view
- * @param parentHeightMeasureSpec The height requirements for this view
- */
- protected void measureChild(View child, int parentWidthMeasureSpec,
- int parentHeightMeasureSpec) {
- final LayoutParams lp = child.getLayoutParams();
-
- final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
- mPaddingLeft + mPaddingRight, lp.width);
- final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
- mPaddingTop + mPaddingBottom, lp.height);
-
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- }
-
- /**
- * Ask one of the children of this view to measure itself, taking into
- * account both the MeasureSpec requirements for this view and its padding
- * and margins. The child must have MarginLayoutParams The heavy lifting is
- * done in getChildMeasureSpec.
- *
- * @param child The child to measure
- * @param parentWidthMeasureSpec The width requirements for this view
- * @param widthUsed Extra space that has been used up by the parent
- * horizontally (possibly by other children of the parent)
- * @param parentHeightMeasureSpec The height requirements for this view
- * @param heightUsed Extra space that has been used up by the parent
- * vertically (possibly by other children of the parent)
- */
- protected void measureChildWithMargins(View child,
- int parentWidthMeasureSpec, int widthUsed,
- int parentHeightMeasureSpec, int heightUsed) {
- final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
-
- final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
- mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
- + widthUsed, lp.width);
- final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
- mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin
- + heightUsed, lp.height);
-
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- }
-
- /**
- * Does the hard part of measureChildren: figuring out the MeasureSpec to
- * pass to a particular child. This method figures out the right MeasureSpec
- * for one dimension (height or width) of one child view.
- *
- * The goal is to combine information from our MeasureSpec with the
- * LayoutParams of the child to get the best possible results. For example,
- * if the this view knows its size (because its MeasureSpec has a mode of
- * EXACTLY), and the child has indicated in its LayoutParams that it wants
- * to be the same size as the parent, the parent should ask the child to
- * layout given an exact size.
- *
- * @param spec The requirements for this view
- * @param padding The padding of this view for the current dimension and
- * margins, if applicable
- * @param childDimension How big the child wants to be in the current
- * dimension
- * @return a MeasureSpec integer for the child
- */
- public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
- int specMode = MeasureSpec.getMode(spec);
- int specSize = MeasureSpec.getSize(spec);
-
- int size = Math.max(0, specSize - padding);
-
- int resultSize = 0;
- int resultMode = 0;
-
- switch (specMode) {
- // Parent has imposed an exact size on us
- case MeasureSpec.EXACTLY:
- if (childDimension >= 0) {
- resultSize = childDimension;
- resultMode = MeasureSpec.EXACTLY;
- } else if (childDimension == LayoutParams.FILL_PARENT) {
- // Child wants to be our size. So be it.
- resultSize = size;
- resultMode = MeasureSpec.EXACTLY;
- } else if (childDimension == LayoutParams.WRAP_CONTENT) {
- // Child wants to determine its own size. It can't be
- // bigger than us.
- resultSize = size;
- resultMode = MeasureSpec.AT_MOST;
- }
- break;
-
- // Parent has imposed a maximum size on us
- case MeasureSpec.AT_MOST:
- if (childDimension >= 0) {
- // Child wants a specific size... so be it
- resultSize = childDimension;
- resultMode = MeasureSpec.EXACTLY;
- } else if (childDimension == LayoutParams.FILL_PARENT) {
- // Child wants to be our size, but our size is not fixed.
- // Constrain child to not be bigger than us.
- resultSize = size;
- resultMode = MeasureSpec.AT_MOST;
- } else if (childDimension == LayoutParams.WRAP_CONTENT) {
- // Child wants to determine its own size. It can't be
- // bigger than us.
- resultSize = size;
- resultMode = MeasureSpec.AT_MOST;
- }
- break;
-
- // Parent asked to see how big we want to be
- case MeasureSpec.UNSPECIFIED:
- if (childDimension >= 0) {
- // Child wants a specific size... let him have it
- resultSize = childDimension;
- resultMode = MeasureSpec.EXACTLY;
- } else if (childDimension == LayoutParams.FILL_PARENT) {
- // Child wants to be our size... find out how big it should
- // be
- resultSize = 0;
- resultMode = MeasureSpec.UNSPECIFIED;
- } else if (childDimension == LayoutParams.WRAP_CONTENT) {
- // Child wants to determine its own size.... find out how
- // big it should be
- resultSize = 0;
- resultMode = MeasureSpec.UNSPECIFIED;
- }
- break;
- }
- return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
- }
-
-
- /**
- * Removes any pending animations for views that have been removed. Call
- * this if you don't want animations for exiting views to stack up.
- */
- public void clearDisappearingChildren() {
- if (mDisappearingChildren != null) {
- mDisappearingChildren.clear();
- }
- }
-
- /**
- * Add a view which is removed from mChildren but still needs animation
- *
- * @param v View to add
- */
- private void addDisappearingView(View v) {
- ArrayList<View> disappearingChildren = mDisappearingChildren;
-
- if (disappearingChildren == null) {
- disappearingChildren = mDisappearingChildren = new ArrayList<View>();
- }
-
- disappearingChildren.add(v);
- }
-
- /**
- * Cleanup a view when its animation is done. This may mean removing it from
- * the list of disappearing views.
- *
- * @param view The view whose animation has finished
- * @param animation The animation, cannot be null
- */
- private void finishAnimatingView(final View view, Animation animation) {
- final ArrayList<View> disappearingChildren = mDisappearingChildren;
- if (disappearingChildren != null) {
- if (disappearingChildren.contains(view)) {
- disappearingChildren.remove(view);
-
- if (view.mAttachInfo != null) {
- view.dispatchDetachedFromWindow();
- }
-
- view.clearAnimation();
- mGroupFlags |= FLAG_INVALIDATE_REQUIRED;
- }
- }
-
- if (animation != null && !animation.getFillAfter()) {
- view.clearAnimation();
- }
-
- if ((view.mPrivateFlags & ANIMATION_STARTED) == ANIMATION_STARTED) {
- view.onAnimationEnd();
- // Should be performed by onAnimationEnd() but this avoid an infinite loop,
- // so we'd rather be safe than sorry
- view.mPrivateFlags &= ~ANIMATION_STARTED;
- // Draw one more frame after the animation is done
- mGroupFlags |= FLAG_INVALIDATE_REQUIRED;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean gatherTransparentRegion(Region region) {
- // If no transparent regions requested, we are always opaque.
- final boolean meOpaque = (mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) == 0;
- if (meOpaque && region == null) {
- // The caller doesn't care about the region, so stop now.
- return true;
- }
- super.gatherTransparentRegion(region);
- final View[] children = mChildren;
- final int count = mChildrenCount;
- boolean noneOfTheChildrenAreTransparent = true;
- for (int i = 0; i < count; i++) {
- final View child = children[i];
- if ((child.mViewFlags & VISIBILITY_MASK) != GONE || child.getAnimation() != null) {
- if (!child.gatherTransparentRegion(region)) {
- noneOfTheChildrenAreTransparent = false;
- }
- }
- }
- return meOpaque || noneOfTheChildrenAreTransparent;
- }
-
- /**
- * {@inheritDoc}
- */
- public void requestTransparentRegion(View child) {
- if (child != null) {
- child.mPrivateFlags |= View.REQUEST_TRANSPARENT_REGIONS;
- if (mParent != null) {
- mParent.requestTransparentRegion(this);
- }
- }
- }
-
-
- @Override
- protected boolean fitSystemWindows(Rect insets) {
- boolean done = super.fitSystemWindows(insets);
- if (!done) {
- final int count = mChildrenCount;
- final View[] children = mChildren;
- for (int i = 0; i < count; i++) {
- done = children[i].fitSystemWindows(insets);
- if (done) {
- break;
- }
- }
- }
- return done;
- }
-
- /**
- * Returns the animation listener to which layout animation events are
- * sent.
- *
- * @return an {@link android.view.animation.Animation.AnimationListener}
- */
- public Animation.AnimationListener getLayoutAnimationListener() {
- return mAnimationListener;
- }
-
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
-
- if ((mGroupFlags & FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE) != 0) {
- if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) != 0) {
- throw new IllegalStateException("addStateFromChildren cannot be enabled if a"
- + " child has duplicateParentState set to true");
- }
-
- final View[] children = mChildren;
- final int count = mChildrenCount;
-
- for (int i = 0; i < count; i++) {
- final View child = children[i];
- if ((child.mViewFlags & DUPLICATE_PARENT_STATE) != 0) {
- child.refreshDrawableState();
- }
- }
- }
- }
-
- @Override
- protected int[] onCreateDrawableState(int extraSpace) {
- if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) == 0) {
- return super.onCreateDrawableState(extraSpace);
- }
-
- int need = 0;
- int n = getChildCount();
- for (int i = 0; i < n; i++) {
- int[] childState = getChildAt(i).getDrawableState();
-
- if (childState != null) {
- need += childState.length;
- }
- }
-
- int[] state = super.onCreateDrawableState(extraSpace + need);
-
- for (int i = 0; i < n; i++) {
- int[] childState = getChildAt(i).getDrawableState();
-
- if (childState != null) {
- state = mergeDrawableStates(state, childState);
- }
- }
-
- return state;
- }
-
- /**
- * Sets whether this ViewGroup's drawable states also include
- * its children's drawable states. This is used, for example, to
- * make a group appear to be focused when its child EditText or button
- * is focused.
- */
- public void setAddStatesFromChildren(boolean addsStates) {
- if (addsStates) {
- mGroupFlags |= FLAG_ADD_STATES_FROM_CHILDREN;
- } else {
- mGroupFlags &= ~FLAG_ADD_STATES_FROM_CHILDREN;
- }
-
- refreshDrawableState();
- }
-
- /**
- * Returns whether this ViewGroup's drawable states also include
- * its children's drawable states. This is used, for example, to
- * make a group appear to be focused when its child EditText or button
- * is focused.
- */
- public boolean addStatesFromChildren() {
- return (mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) != 0;
- }
-
- /**
- * If {link #addStatesFromChildren} is true, refreshes this group's
- * drawable state (to include the states from its children).
- */
- public void childDrawableStateChanged(View child) {
- if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) != 0) {
- refreshDrawableState();
- }
- }
-
- /**
- * Specifies the animation listener to which layout animation events must
- * be sent. Only
- * {@link android.view.animation.Animation.AnimationListener#onAnimationStart(Animation)}
- * and
- * {@link android.view.animation.Animation.AnimationListener#onAnimationEnd(Animation)}
- * are invoked.
- *
- * @param animationListener the layout animation listener
- */
- public void setLayoutAnimationListener(Animation.AnimationListener animationListener) {
- mAnimationListener = animationListener;
- }
-
- /**
- * LayoutParams are used by views to tell their parents how they want to be
- * laid out. See
- * {@link android.R.styleable#ViewGroup_Layout ViewGroup Layout Attributes}
- * for a list of all child view attributes that this class supports.
- *
- * <p>
- * The base LayoutParams class just describes how big the view wants to be
- * for both width and height. For each dimension, it can specify one of:
- * <ul>
- * <li> an exact number
- * <li>FILL_PARENT, which means the view wants to be as big as its parent
- * (minus padding)
- * <li> WRAP_CONTENT, which means that the view wants to be just big enough
- * to enclose its content (plus padding)
- * </ul>
- * There are subclasses of LayoutParams for different subclasses of
- * ViewGroup. For example, AbsoluteLayout has its own subclass of
- * LayoutParams which adds an X and Y value.
- *
- * @attr ref android.R.styleable#ViewGroup_Layout_layout_height
- * @attr ref android.R.styleable#ViewGroup_Layout_layout_width
- */
- public static class LayoutParams {
- /**
- * Special value for the height or width requested by a View.
- * FILL_PARENT means that the view wants to fill the available space
- * within the parent, taking the parent's padding into account.
- */
- public static final int FILL_PARENT = -1;
-
- /**
- * Special value for the height or width requested by a View.
- * WRAP_CONTENT means that the view wants to be just large enough to fit
- * its own internal content, taking its own padding into account.
- */
- public static final int WRAP_CONTENT = -2;
-
- /**
- * Information about how wide the view wants to be. Can be an exact
- * size, or one of the constants FILL_PARENT or WRAP_CONTENT.
- */
- @ViewDebug.ExportedProperty(mapping = {
- @ViewDebug.IntToString(from = FILL_PARENT, to = "FILL_PARENT"),
- @ViewDebug.IntToString(from = WRAP_CONTENT, to = "WRAP_CONTENT")
- })
- public int width;
-
- /**
- * Information about how tall the view wants to be. Can be an exact
- * size, or one of the constants FILL_PARENT or WRAP_CONTENT.
- */
- @ViewDebug.ExportedProperty(mapping = {
- @ViewDebug.IntToString(from = FILL_PARENT, to = "FILL_PARENT"),
- @ViewDebug.IntToString(from = WRAP_CONTENT, to = "WRAP_CONTENT")
- })
- public int height;
-
- /**
- * Used to animate layouts.
- */
- public LayoutAnimationController.AnimationParameters layoutAnimationParameters;
-
- /**
- * Creates a new set of layout parameters. The values are extracted from
- * the supplied attributes set and context. The XML attributes mapped
- * to this set of layout parameters are:
- *
- * <ul>
- * <li><code>layout_width</code>: the width, either an exact value,
- * {@link #WRAP_CONTENT} or {@link #FILL_PARENT}</li>
- * <li><code>layout_height</code>: the height, either an exact value,
- * {@link #WRAP_CONTENT} or {@link #FILL_PARENT}</li>
- * </ul>
- *
- * @param c the application environment
- * @param attrs the set of attributes from which to extract the layout
- * parameters' values
- */
- public LayoutParams(Context c, AttributeSet attrs) {
- TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ViewGroup_Layout);
- setBaseAttributes(a,
- R.styleable.ViewGroup_Layout_layout_width,
- R.styleable.ViewGroup_Layout_layout_height);
- a.recycle();
- }
-
- /**
- * Creates a new set of layout parameters with the specified width
- * and height.
- *
- * @param width the width, either {@link #FILL_PARENT},
- * {@link #WRAP_CONTENT} or a fixed size in pixels
- * @param height the height, either {@link #FILL_PARENT},
- * {@link #WRAP_CONTENT} or a fixed size in pixels
- */
- public LayoutParams(int width, int height) {
- this.width = width;
- this.height = height;
- }
-
- /**
- * Copy constructor. Clones the width and height values of the source.
- *
- * @param source The layout params to copy from.
- */
- public LayoutParams(LayoutParams source) {
- this.width = source.width;
- this.height = source.height;
- }
-
- /**
- * Used internally by MarginLayoutParams.
- * @hide
- */
- LayoutParams() {
- }
-
- /**
- * Extracts the layout parameters from the supplied attributes.
- *
- * @param a the style attributes to extract the parameters from
- * @param widthAttr the identifier of the width attribute
- * @param heightAttr the identifier of the height attribute
- */
- protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
- width = a.getLayoutDimension(widthAttr, "layout_width");
- height = a.getLayoutDimension(heightAttr, "layout_height");
- }
-
- /**
- * Returns a String representation of this set of layout parameters.
- *
- * @param output the String to prepend to the internal representation
- * @return a String with the following format: output +
- * "ViewGroup.LayoutParams={ width=WIDTH, height=HEIGHT }"
- *
- * @hide
- */
- public String debug(String output) {
- return output + "ViewGroup.LayoutParams={ width="
- + sizeToString(width) + ", height=" + sizeToString(height) + " }";
- }
-
- /**
- * Converts the specified size to a readable String.
- *
- * @param size the size to convert
- * @return a String instance representing the supplied size
- *
- * @hide
- */
- protected static String sizeToString(int size) {
- if (size == WRAP_CONTENT) {
- return "wrap-content";
- }
- if (size == FILL_PARENT) {
- return "fill-parent";
- }
- return String.valueOf(size);
- }
- }
-
- /**
- * Per-child layout information for layouts that support margins.
- * See
- * {@link android.R.styleable#ViewGroup_MarginLayout ViewGroup Margin Layout Attributes}
- * for a list of all child view attributes that this class supports.
- */
- public static class MarginLayoutParams extends ViewGroup.LayoutParams {
- /**
- * The left margin in pixels of the child.
- */
- @ViewDebug.ExportedProperty
- public int leftMargin;
-
- /**
- * The top margin in pixels of the child.
- */
- @ViewDebug.ExportedProperty
- public int topMargin;
-
- /**
- * The right margin in pixels of the child.
- */
- @ViewDebug.ExportedProperty
- public int rightMargin;
-
- /**
- * The bottom margin in pixels of the child.
- */
- @ViewDebug.ExportedProperty
- public int bottomMargin;
-
- /**
- * Creates a new set of layout parameters. The values are extracted from
- * the supplied attributes set and context.
- *
- * @param c the application environment
- * @param attrs the set of attributes from which to extract the layout
- * parameters' values
- */
- public MarginLayoutParams(Context c, AttributeSet attrs) {
- super();
-
- TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ViewGroup_MarginLayout);
- setBaseAttributes(a,
- R.styleable.ViewGroup_MarginLayout_layout_width,
- R.styleable.ViewGroup_MarginLayout_layout_height);
-
- int margin = a.getDimensionPixelSize(
- com.android.internal.R.styleable.ViewGroup_MarginLayout_layout_margin, -1);
- if (margin >= 0) {
- leftMargin = margin;
- topMargin = margin;
- rightMargin= margin;
- bottomMargin = margin;
- } else {
- leftMargin = a.getDimensionPixelSize(
- R.styleable.ViewGroup_MarginLayout_layout_marginLeft, 0);
- topMargin = a.getDimensionPixelSize(
- R.styleable.ViewGroup_MarginLayout_layout_marginTop, 0);
- rightMargin = a.getDimensionPixelSize(
- R.styleable.ViewGroup_MarginLayout_layout_marginRight, 0);
- bottomMargin = a.getDimensionPixelSize(
- R.styleable.ViewGroup_MarginLayout_layout_marginBottom, 0);
- }
-
- a.recycle();
- }
-
- /**
- * {@inheritDoc}
- */
- public MarginLayoutParams(int width, int height) {
- super(width, height);
- }
-
- /**
- * Copy constructor. Clones the width, height and margin values of the source.
- *
- * @param source The layout params to copy from.
- */
- public MarginLayoutParams(MarginLayoutParams source) {
- this.width = source.width;
- this.height = source.height;
-
- this.leftMargin = source.leftMargin;
- this.topMargin = source.topMargin;
- this.rightMargin = source.rightMargin;
- this.bottomMargin = source.bottomMargin;
- }
-
- /**
- * {@inheritDoc}
- */
- public MarginLayoutParams(LayoutParams source) {
- super(source);
- }
-
- /**
- * Sets the margins, in pixels.
- *
- * @param left the left margin size
- * @param top the top margin size
- * @param right the right margin size
- * @param bottom the bottom margin size
- *
- * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginLeft
- * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginTop
- * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginRight
- * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginBottom
- */
- public void setMargins(int left, int top, int right, int bottom) {
- leftMargin = left;
- topMargin = top;
- rightMargin = right;
- bottomMargin = bottom;
- }
- }
-}
diff --git a/core/java/android/view/ViewManager.java b/core/java/android/view/ViewManager.java
deleted file mode 100644
index 7f318c1..0000000
--- a/core/java/android/view/ViewManager.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-/** Interface to let you add and remove child views to an Activity. To get an instance
- * of this class, call {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- */
-public interface ViewManager
-{
- public void addView(View view, ViewGroup.LayoutParams params);
- public void updateViewLayout(View view, ViewGroup.LayoutParams params);
- public void removeView(View view);
-}
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
deleted file mode 100644
index b456c5d..0000000
--- a/core/java/android/view/ViewParent.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.graphics.Rect;
-
-/**
- * Defines the responsibilities for a class that will be a parent of a View.
- * This is the API that a view sees when it wants to interact with its parent.
- *
- */
-public interface ViewParent {
- /**
- * Called when something has changed which has invalidated the layout of a
- * child of this view parent. This will schedule a layout pass of the view
- * tree.
- */
- public void requestLayout();
-
- /**
- * Indicates whether layout was requested on this view parent.
- *
- * @return true if layout was requested, false otherwise
- */
- public boolean isLayoutRequested();
-
- /**
- * Called when a child wants the view hierarchy to gather and report
- * transparent regions to the window compositor. Views that "punch" holes in
- * the view hierarchy, such as SurfaceView can use this API to improve
- * performance of the system. When no such a view is present in the
- * hierarchy, this optimization in unnecessary and might slightly reduce the
- * view hierarchy performance.
- *
- * @param child the view requesting the transparent region computation
- *
- */
- public void requestTransparentRegion(View child);
-
- /**
- * All or part of a child is dirty and needs to be redrawn.
- *
- * @param child The child which is dirty
- * @param r The area within the child that is invalid
- */
- public void invalidateChild(View child, Rect r);
-
- /**
- * All or part of a child is dirty and needs to be redrawn.
- *
- * The location array is an array of two int values which respectively
- * define the left and the top position of the dirty child.
- *
- * This method must return the parent of this ViewParent if the specified
- * rectangle must be invalidated in the parent. If the specified rectangle
- * does not require invalidation in the parent or if the parent does not
- * exist, this method must return null.
- *
- * When this method returns a non-null value, the location array must
- * have been updated with the left and top coordinates of this ViewParent.
- *
- * @param location An array of 2 ints containing the left and top
- * coordinates of the child to invalidate
- * @param r The area within the child that is invalid
- *
- * @return the parent of this ViewParent or null
- */
- public ViewParent invalidateChildInParent(int[] location, Rect r);
-
- /**
- * Returns the parent if it exists, or null.
- *
- * @return a ViewParent or null if this ViewParent does not have a parent
- */
- public ViewParent getParent();
-
- /**
- * Called when a child of this parent wants focus
- *
- * @param child The child of this ViewParent that wants focus. This view
- * will contain the focused view. It is not necessarily the view that
- * actually has focus.
- * @param focused The view that is a descendant of child that actually has
- * focus
- */
- public void requestChildFocus(View child, View focused);
-
- /**
- * Tell view hierarchy that the global view attributes need to be
- * re-evaluated.
- *
- * @param child View whose attributes have changed.
- */
- public void recomputeViewAttributes(View child);
-
- /**
- * Called when a child of this parent is giving up focus
- *
- * @param child The view that is giving up focus
- */
- public void clearChildFocus(View child);
-
- public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset);
-
- /**
- * Find the nearest view in the specified direction that wants to take focus
- *
- * @param v The view that currently has focus
- * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
- */
- public View focusSearch(View v, int direction);
-
- /**
- * Change the z order of the child so it's on top of all other children
- *
- * @param child
- */
- public void bringChildToFront(View child);
-
- /**
- * Tells the parent that a new focusable view has become available. This is
- * to handle transitions from the case where there are no focusable views to
- * the case where the first focusable view appears.
- *
- * @param v The view that has become newly focusable
- */
- public void focusableViewAvailable(View v);
-
- /**
- * Bring up a context menu for the specified view or its ancestors.
- * <p>
- * In most cases, a subclass does not need to override this. However, if
- * the subclass is added directly to the window manager (for example,
- * {@link ViewManager#addView(View, android.view.ViewGroup.LayoutParams)})
- * then it should override this and show the context menu.
- *
- * @param originalView The source view where the context menu was first invoked
- * @return true if a context menu was displayed
- */
- public boolean showContextMenuForChild(View originalView);
-
- /**
- * Have the parent populate the specified context menu if it has anything to
- * add (and then recurse on its parent).
- *
- * @param menu The menu to populate
- */
- public void createContextMenu(ContextMenu menu);
-
- /**
- * This method is called on the parent when a child's drawable state
- * has changed.
- *
- * @param child The child whose drawable state has changed.
- */
- public void childDrawableStateChanged(View child);
-
- /**
- * Called when a child does not want this parent and its ancestors to
- * intercept touch events with
- * {@link ViewGroup#onInterceptTouchEvent(MotionEvent)}.
- * <p>
- * This parent should pass this call onto its parents. This parent must obey
- * this request for the duration of the touch (that is, only clear the flag
- * after this parent has received an up or a cancel.
- *
- * @param disallowIntercept True if the child does not want the parent to
- * intercept touch events.
- */
- public void requestDisallowInterceptTouchEvent(boolean disallowIntercept);
-
- /**
- * Called when a child of this group wants a particular rectangle to be
- * positioned onto the screen. {@link ViewGroup}s overriding this can trust
- * that:
- * <ul>
- * <li>child will be a direct child of this group</li>
- * <li>rectangle will be in the child's coordinates</li>
- * </ul>
- *
- * <p>{@link ViewGroup}s overriding this should uphold the contract:</p>
- * <ul>
- * <li>nothing will change if the rectangle is already visible</li>
- * <li>the view port will be scrolled only just enough to make the
- * rectangle visible</li>
- * <ul>
- *
- * @param child The direct child making the request.
- * @param rectangle The rectangle in the child's coordinates the child
- * wishes to be on the screen.
- * @param immediate True to forbid animated or delayed scrolling,
- * false otherwise
- * @return Whether the group scrolled to handle the operation
- */
- public boolean requestChildRectangleOnScreen(View child, Rect rectangle,
- boolean immediate);
-}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
deleted file mode 100644
index 3cfaf1b..0000000
--- a/core/java/android/view/ViewRoot.java
+++ /dev/null
@@ -1,2845 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import com.android.internal.view.IInputMethodCallback;
-import com.android.internal.view.IInputMethodSession;
-
-import android.graphics.Canvas;
-import android.graphics.PixelFormat;
-import android.graphics.Point;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.os.*;
-import android.os.Process;
-import android.os.SystemProperties;
-import android.util.AndroidRuntimeException;
-import android.util.Config;
-import android.util.Log;
-import android.util.EventLog;
-import android.util.SparseArray;
-import android.util.DisplayMetrics;
-import android.view.View.MeasureSpec;
-import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.Scroller;
-import android.content.pm.PackageManager;
-import android.content.Context;
-import android.app.ActivityManagerNative;
-import android.Manifest;
-import android.media.AudioManager;
-
-import java.lang.ref.WeakReference;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-
-import javax.microedition.khronos.egl.*;
-import javax.microedition.khronos.opengles.*;
-import static javax.microedition.khronos.opengles.GL10.*;
-
-/**
- * The top of a view hierarchy, implementing the needed protocol between View
- * and the WindowManager. This is for the most part an internal implementation
- * detail of {@link WindowManagerImpl}.
- *
- * {@hide}
- */
-@SuppressWarnings({"EmptyCatchBlock"})
-public final class ViewRoot extends Handler implements ViewParent,
- View.AttachInfo.Callbacks {
- private static final String TAG = "ViewRoot";
- private static final boolean DBG = false;
- @SuppressWarnings({"ConstantConditionalExpression"})
- private static final boolean LOCAL_LOGV = false ? Config.LOGD : Config.LOGV;
- /** @noinspection PointlessBooleanExpression*/
- private static final boolean DEBUG_DRAW = false || LOCAL_LOGV;
- private static final boolean DEBUG_LAYOUT = false || LOCAL_LOGV;
- private static final boolean DEBUG_INPUT_RESIZE = false || LOCAL_LOGV;
- private static final boolean DEBUG_ORIENTATION = false || LOCAL_LOGV;
- private static final boolean DEBUG_TRACKBALL = false || LOCAL_LOGV;
- private static final boolean DEBUG_IMF = false || LOCAL_LOGV;
- private static final boolean WATCH_POINTER = false;
-
- static final boolean PROFILE_DRAWING = false;
- private static final boolean PROFILE_LAYOUT = false;
- // profiles real fps (times between draws) and displays the result
- private static final boolean SHOW_FPS = false;
- // used by SHOW_FPS
- private static int sDrawTime;
-
- /**
- * Maximum time we allow the user to roll the trackball enough to generate
- * a key event, before resetting the counters.
- */
- static final int MAX_TRACKBALL_DELAY = 250;
-
- static long sInstanceCount = 0;
-
- static IWindowSession sWindowSession;
-
- static final Object mStaticInit = new Object();
- static boolean mInitialized = false;
-
- static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<RunQueue>();
-
- long mLastTrackballTime = 0;
- final TrackballAxis mTrackballAxisX = new TrackballAxis();
- final TrackballAxis mTrackballAxisY = new TrackballAxis();
-
- final int[] mTmpLocation = new int[2];
-
- final InputMethodCallback mInputMethodCallback;
- final SparseArray<Object> mPendingEvents = new SparseArray<Object>();
- int mPendingEventSeq = 0;
-
- final Thread mThread;
-
- final WindowLeaked mLocation;
-
- final WindowManager.LayoutParams mWindowAttributes = new WindowManager.LayoutParams();
-
- final W mWindow;
-
- View mView;
- View mFocusedView;
- View mRealFocusedView; // this is not set to null in touch mode
- int mViewVisibility;
- boolean mAppVisible = true;
-
- final Region mTransparentRegion;
- final Region mPreviousTransparentRegion;
-
- int mWidth;
- int mHeight;
- Rect mDirty; // will be a graphics.Region soon
-
- final View.AttachInfo mAttachInfo;
-
- final Rect mTempRect; // used in the transaction to not thrash the heap.
- final Rect mVisRect; // used to retrieve visible rect of focused view.
- final Point mVisPoint; // used to retrieve global offset of focused view.
-
- boolean mTraversalScheduled;
- boolean mWillDrawSoon;
- boolean mLayoutRequested;
- boolean mFirst;
- boolean mReportNextDraw;
- boolean mFullRedrawNeeded;
- boolean mNewSurfaceNeeded;
- boolean mHasHadWindowFocus;
-
- boolean mWindowAttributesChanged = false;
-
- // These can be accessed by any thread, must be protected with a lock.
- Surface mSurface;
-
- boolean mAdded;
- boolean mAddedTouchMode;
-
- /*package*/ int mAddNesting;
-
- // These are accessed by multiple threads.
- final Rect mWinFrame; // frame given by window manager.
-
- final Rect mPendingVisibleInsets = new Rect();
- final Rect mPendingContentInsets = new Rect();
- final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
- = new ViewTreeObserver.InternalInsetsInfo();
-
- boolean mScrollMayChange;
- int mSoftInputMode;
- View mLastScrolledFocus;
- int mScrollY;
- int mCurScrollY;
- Scroller mScroller;
-
- EGL10 mEgl;
- EGLDisplay mEglDisplay;
- EGLContext mEglContext;
- EGLSurface mEglSurface;
- GL11 mGL;
- Canvas mGlCanvas;
- boolean mUseGL;
- boolean mGlWanted;
-
- final ViewConfiguration mViewConfiguration;
-
- /**
- * see {@link #playSoundEffect(int)}
- */
- AudioManager mAudioManager;
-
- private final float mDensity;
-
- public ViewRoot(Context context) {
- super();
-
- ++sInstanceCount;
-
- // Initialize the statics when this class is first instantiated. This is
- // done here instead of in the static block because Zygote does not
- // allow the spawning of threads.
- synchronized (mStaticInit) {
- if (!mInitialized) {
- try {
- InputMethodManager imm = InputMethodManager.getInstance(context);
- sWindowSession = IWindowManager.Stub.asInterface(
- ServiceManager.getService("window"))
- .openSession(imm.getClient(), imm.getInputContext());
- mInitialized = true;
- } catch (RemoteException e) {
- }
- }
- }
-
- mThread = Thread.currentThread();
- mLocation = new WindowLeaked(null);
- mLocation.fillInStackTrace();
- mWidth = -1;
- mHeight = -1;
- mDirty = new Rect();
- mTempRect = new Rect();
- mVisRect = new Rect();
- mVisPoint = new Point();
- mWinFrame = new Rect();
- mWindow = new W(this);
- mInputMethodCallback = new InputMethodCallback(this);
- mViewVisibility = View.GONE;
- mTransparentRegion = new Region();
- mPreviousTransparentRegion = new Region();
- mFirst = true; // true for the first time the view is added
- mSurface = new Surface();
- mAdded = false;
- mAttachInfo = new View.AttachInfo(sWindowSession, mWindow, this, this);
- mViewConfiguration = ViewConfiguration.get(context);
- mDensity = context.getResources().getDisplayMetrics().density;
- }
-
- @Override
- protected void finalize() throws Throwable {
- super.finalize();
- --sInstanceCount;
- }
-
- public static long getInstanceCount() {
- return sInstanceCount;
- }
-
- // FIXME for perf testing only
- private boolean mProfile = false;
-
- /**
- * Call this to profile the next traversal call.
- * FIXME for perf testing only. Remove eventually
- */
- public void profile() {
- mProfile = true;
- }
-
- /**
- * Indicates whether we are in touch mode. Calling this method triggers an IPC
- * call and should be avoided whenever possible.
- *
- * @return True, if the device is in touch mode, false otherwise.
- *
- * @hide
- */
- static boolean isInTouchMode() {
- if (mInitialized) {
- try {
- return sWindowSession.getInTouchMode();
- } catch (RemoteException e) {
- }
- }
- return false;
- }
-
- private void initializeGL() {
- initializeGLInner();
- int err = mEgl.eglGetError();
- if (err != EGL10.EGL_SUCCESS) {
- // give-up on using GL
- destroyGL();
- mGlWanted = false;
- }
- }
-
- private void initializeGLInner() {
- final EGL10 egl = (EGL10) EGLContext.getEGL();
- mEgl = egl;
-
- /*
- * Get to the default display.
- */
- final EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
- mEglDisplay = eglDisplay;
-
- /*
- * We can now initialize EGL for that display
- */
- int[] version = new int[2];
- egl.eglInitialize(eglDisplay, version);
-
- /*
- * Specify a configuration for our opengl session
- * and grab the first configuration that matches is
- */
- final int[] configSpec = {
- EGL10.EGL_RED_SIZE, 5,
- EGL10.EGL_GREEN_SIZE, 6,
- EGL10.EGL_BLUE_SIZE, 5,
- EGL10.EGL_DEPTH_SIZE, 0,
- EGL10.EGL_NONE
- };
- final EGLConfig[] configs = new EGLConfig[1];
- final int[] num_config = new int[1];
- egl.eglChooseConfig(eglDisplay, configSpec, configs, 1, num_config);
- final EGLConfig config = configs[0];
-
- /*
- * Create an OpenGL ES context. This must be done only once, an
- * OpenGL context is a somewhat heavy object.
- */
- final EGLContext context = egl.eglCreateContext(eglDisplay, config,
- EGL10.EGL_NO_CONTEXT, null);
- mEglContext = context;
-
- /*
- * Create an EGL surface we can render into.
- */
- final EGLSurface surface = egl.eglCreateWindowSurface(eglDisplay, config, mHolder, null);
- mEglSurface = surface;
-
- /*
- * Before we can issue GL commands, we need to make sure
- * the context is current and bound to a surface.
- */
- egl.eglMakeCurrent(eglDisplay, surface, surface, context);
-
- /*
- * Get to the appropriate GL interface.
- * This is simply done by casting the GL context to either
- * GL10 or GL11.
- */
- final GL11 gl = (GL11) context.getGL();
- mGL = gl;
- mGlCanvas = new Canvas(gl);
- mUseGL = true;
- }
-
- private void destroyGL() {
- // inform skia that the context is gone
- nativeAbandonGlCaches();
-
- mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
- mEgl.eglDestroyContext(mEglDisplay, mEglContext);
- mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
- mEgl.eglTerminate(mEglDisplay);
- mEglContext = null;
- mEglSurface = null;
- mEglDisplay = null;
- mEgl = null;
- mGlCanvas = null;
- mGL = null;
- mUseGL = false;
- }
-
- private void checkEglErrors() {
- if (mUseGL) {
- int err = mEgl.eglGetError();
- if (err != EGL10.EGL_SUCCESS) {
- // something bad has happened revert to
- // normal rendering.
- destroyGL();
- if (err != EGL11.EGL_CONTEXT_LOST) {
- // we'll try again if it was context lost
- mGlWanted = false;
- }
- }
- }
- }
-
- /**
- * We have one child
- */
- public void setView(View view, WindowManager.LayoutParams attrs,
- View panelParentView) {
- synchronized (this) {
- if (mView == null) {
- mWindowAttributes.copyFrom(attrs);
- mSoftInputMode = attrs.softInputMode;
- mWindowAttributesChanged = true;
- mView = view;
- mAttachInfo.mRootView = view;
- if (panelParentView != null) {
- mAttachInfo.mPanelParentWindowToken
- = panelParentView.getApplicationWindowToken();
- }
- mAdded = true;
- int res; /* = WindowManagerImpl.ADD_OKAY; */
-
- // Schedule the first layout -before- adding to the window
- // manager, to make sure we do the relayout before receiving
- // any other events from the system.
- requestLayout();
-
- try {
- res = sWindowSession.add(mWindow, attrs,
- getHostVisibility(), mAttachInfo.mContentInsets);
- } catch (RemoteException e) {
- mAdded = false;
- mView = null;
- mAttachInfo.mRootView = null;
- unscheduleTraversals();
- throw new RuntimeException("Adding window failed", e);
- }
- mPendingContentInsets.set(mAttachInfo.mContentInsets);
- mPendingVisibleInsets.set(0, 0, 0, 0);
- if (Config.LOGV) Log.v("ViewRoot", "Added window " + mWindow);
- if (res < WindowManagerImpl.ADD_OKAY) {
- mView = null;
- mAttachInfo.mRootView = null;
- mAdded = false;
- unscheduleTraversals();
- switch (res) {
- case WindowManagerImpl.ADD_BAD_APP_TOKEN:
- case WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN:
- throw new WindowManagerImpl.BadTokenException(
- "Unable to add window -- token " + attrs.token
- + " is not valid; is your activity running?");
- case WindowManagerImpl.ADD_NOT_APP_TOKEN:
- throw new WindowManagerImpl.BadTokenException(
- "Unable to add window -- token " + attrs.token
- + " is not for an application");
- case WindowManagerImpl.ADD_APP_EXITING:
- throw new WindowManagerImpl.BadTokenException(
- "Unable to add window -- app for token " + attrs.token
- + " is exiting");
- case WindowManagerImpl.ADD_DUPLICATE_ADD:
- throw new WindowManagerImpl.BadTokenException(
- "Unable to add window -- window " + mWindow
- + " has already been added");
- case WindowManagerImpl.ADD_STARTING_NOT_NEEDED:
- // Silently ignore -- we would have just removed it
- // right away, anyway.
- return;
- case WindowManagerImpl.ADD_MULTIPLE_SINGLETON:
- throw new WindowManagerImpl.BadTokenException(
- "Unable to add window " + mWindow +
- " -- another window of this type already exists");
- case WindowManagerImpl.ADD_PERMISSION_DENIED:
- throw new WindowManagerImpl.BadTokenException(
- "Unable to add window " + mWindow +
- " -- permission denied for this window type");
- }
- throw new RuntimeException(
- "Unable to add window -- unknown error code " + res);
- }
- view.assignParent(this);
- mAddedTouchMode = (res&WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE) != 0;
- mAppVisible = (res&WindowManagerImpl.ADD_FLAG_APP_VISIBLE) != 0;
- }
- }
- }
-
- public View getView() {
- return mView;
- }
-
- final WindowLeaked getLocation() {
- return mLocation;
- }
-
- void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {
- synchronized (this) {
- mWindowAttributes.copyFrom(attrs);
- if (newView) {
- mSoftInputMode = attrs.softInputMode;
- requestLayout();
- }
- mWindowAttributesChanged = true;
- scheduleTraversals();
- }
- }
-
- void handleAppVisibility(boolean visible) {
- if (mAppVisible != visible) {
- mAppVisible = visible;
- scheduleTraversals();
- }
- }
-
- void handleGetNewSurface() {
- mNewSurfaceNeeded = true;
- mFullRedrawNeeded = true;
- scheduleTraversals();
- }
-
- /**
- * {@inheritDoc}
- */
- public void requestLayout() {
- checkThread();
- mLayoutRequested = true;
- scheduleTraversals();
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isLayoutRequested() {
- return mLayoutRequested;
- }
-
- public void invalidateChild(View child, Rect dirty) {
- checkThread();
- if (LOCAL_LOGV) Log.v(TAG, "Invalidate child: " + dirty);
- if (mCurScrollY != 0) {
- mTempRect.set(dirty);
- mTempRect.offset(0, -mCurScrollY);
- dirty = mTempRect;
- }
- mDirty.union(dirty);
- if (!mWillDrawSoon) {
- scheduleTraversals();
- }
- }
-
- public ViewParent getParent() {
- return null;
- }
-
- public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {
- invalidateChild(null, dirty);
- return null;
- }
-
- public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) {
- if (child != mView) {
- throw new RuntimeException("child is not mine, honest!");
- }
- // Note: don't apply scroll offset, because we want to know its
- // visibility in the virtual canvas being given to the view hierarchy.
- return r.intersect(0, 0, mWidth, mHeight);
- }
-
- public void bringChildToFront(View child) {
- }
-
- public void scheduleTraversals() {
- if (!mTraversalScheduled) {
- mTraversalScheduled = true;
- sendEmptyMessage(DO_TRAVERSAL);
- }
- }
-
- public void unscheduleTraversals() {
- if (mTraversalScheduled) {
- mTraversalScheduled = false;
- removeMessages(DO_TRAVERSAL);
- }
- }
-
- int getHostVisibility() {
- return mAppVisible ? mView.getVisibility() : View.GONE;
- }
-
- private void performTraversals() {
- // cache mView since it is used so much below...
- final View host = mView;
-
- if (DBG) {
- System.out.println("======================================");
- System.out.println("performTraversals");
- host.debug();
- }
-
- if (host == null || !mAdded)
- return;
-
- mTraversalScheduled = false;
- mWillDrawSoon = true;
- boolean windowResizesToFitContent = false;
- boolean fullRedrawNeeded = mFullRedrawNeeded;
- boolean newSurface = false;
- WindowManager.LayoutParams lp = mWindowAttributes;
-
- int desiredWindowWidth;
- int desiredWindowHeight;
- int childWidthMeasureSpec;
- int childHeightMeasureSpec;
-
- final View.AttachInfo attachInfo = mAttachInfo;
-
- final int viewVisibility = getHostVisibility();
- boolean viewVisibilityChanged = mViewVisibility != viewVisibility
- || mNewSurfaceNeeded;
-
- WindowManager.LayoutParams params = null;
- if (mWindowAttributesChanged) {
- mWindowAttributesChanged = false;
- params = lp;
- }
-
- if (mFirst) {
- fullRedrawNeeded = true;
- mLayoutRequested = true;
-
- Display d = new Display(0);
- desiredWindowWidth = d.getWidth();
- desiredWindowHeight = d.getHeight();
-
- // For the very first time, tell the view hierarchy that it
- // is attached to the window. Note that at this point the surface
- // object is not initialized to its backing store, but soon it
- // will be (assuming the window is visible).
- attachInfo.mSurface = mSurface;
- attachInfo.mHasWindowFocus = false;
- attachInfo.mWindowVisibility = viewVisibility;
- attachInfo.mRecomputeGlobalAttributes = false;
- attachInfo.mKeepScreenOn = false;
- viewVisibilityChanged = false;
- host.dispatchAttachedToWindow(attachInfo, 0);
- getRunQueue().executeActions(attachInfo.mHandler);
- //Log.i(TAG, "Screen on initialized: " + attachInfo.mKeepScreenOn);
- } else {
- desiredWindowWidth = mWinFrame.width();
- desiredWindowHeight = mWinFrame.height();
- if (desiredWindowWidth != mWidth || desiredWindowHeight != mHeight) {
- if (DEBUG_ORIENTATION) Log.v("ViewRoot",
- "View " + host + " resized to: " + mWinFrame);
- fullRedrawNeeded = true;
- mLayoutRequested = true;
- windowResizesToFitContent = true;
- }
- }
-
- if (viewVisibilityChanged) {
- attachInfo.mWindowVisibility = viewVisibility;
- host.dispatchWindowVisibilityChanged(viewVisibility);
- if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
- if (mUseGL) {
- destroyGL();
- }
- }
- if (viewVisibility == View.GONE) {
- // After making a window gone, we will count it as being
- // shown for the first time the next time it gets focus.
- mHasHadWindowFocus = false;
- }
- }
-
- boolean insetsChanged = false;
-
- if (mLayoutRequested) {
- if (mFirst) {
- host.fitSystemWindows(mAttachInfo.mContentInsets);
- // make sure touch mode code executes by setting cached value
- // to opposite of the added touch mode.
- mAttachInfo.mInTouchMode = !mAddedTouchMode;
- ensureTouchModeLocally(mAddedTouchMode);
- } else {
- if (!mAttachInfo.mContentInsets.equals(mPendingContentInsets)) {
- mAttachInfo.mContentInsets.set(mPendingContentInsets);
- host.fitSystemWindows(mAttachInfo.mContentInsets);
- insetsChanged = true;
- if (DEBUG_LAYOUT) Log.v(TAG, "Content insets changing to: "
- + mAttachInfo.mContentInsets);
- }
- if (!mAttachInfo.mVisibleInsets.equals(mPendingVisibleInsets)) {
- mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets);
- if (DEBUG_LAYOUT) Log.v(TAG, "Visible insets changing to: "
- + mAttachInfo.mVisibleInsets);
- }
- if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
- || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
- windowResizesToFitContent = true;
-
- Display d = new Display(0);
- desiredWindowWidth = d.getWidth();
- desiredWindowHeight = d.getHeight();
- }
- }
-
- childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width);
- childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
-
- // Ask host how big it wants to be
- if (DEBUG_ORIENTATION || DEBUG_LAYOUT) Log.v("ViewRoot",
- "Measuring " + host + " in display " + desiredWindowWidth
- + "x" + desiredWindowHeight + "...");
- host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
-
- if (DBG) {
- System.out.println("======================================");
- System.out.println("performTraversals -- after measure");
- host.debug();
- }
- }
-
- if (attachInfo.mRecomputeGlobalAttributes) {
- //Log.i(TAG, "Computing screen on!");
- attachInfo.mRecomputeGlobalAttributes = false;
- boolean oldVal = attachInfo.mKeepScreenOn;
- attachInfo.mKeepScreenOn = false;
- host.dispatchCollectViewAttributes(0);
- if (attachInfo.mKeepScreenOn != oldVal) {
- params = lp;
- //Log.i(TAG, "Keep screen on changed: " + attachInfo.mKeepScreenOn);
- }
- }
-
- if (mFirst || attachInfo.mViewVisibilityChanged) {
- attachInfo.mViewVisibilityChanged = false;
- int resizeMode = mSoftInputMode &
- WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
- // If we are in auto resize mode, then we need to determine
- // what mode to use now.
- if (resizeMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
- final int N = attachInfo.mScrollContainers.size();
- for (int i=0; i<N; i++) {
- if (attachInfo.mScrollContainers.get(i).isShown()) {
- resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
- }
- }
- if (resizeMode == 0) {
- resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
- }
- if ((lp.softInputMode &
- WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) != resizeMode) {
- lp.softInputMode = (lp.softInputMode &
- ~WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) |
- resizeMode;
- params = lp;
- }
- }
- }
-
- if (params != null && (host.mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) != 0) {
- if (!PixelFormat.formatHasAlpha(params.format)) {
- params.format = PixelFormat.TRANSLUCENT;
- }
- }
-
- boolean windowShouldResize = mLayoutRequested && windowResizesToFitContent
- && (mWidth != host.mMeasuredWidth || mHeight != host.mMeasuredHeight);
-
- final boolean computesInternalInsets =
- attachInfo.mTreeObserver.hasComputeInternalInsetsListeners();
- boolean insetsPending = false;
- int relayoutResult = 0;
- if (mFirst || windowShouldResize || insetsChanged
- || viewVisibilityChanged || params != null) {
-
- if (viewVisibility == View.VISIBLE) {
- // If this window is giving internal insets to the window
- // manager, and it is being added or changing its visibility,
- // then we want to first give the window manager "fake"
- // insets to cause it to effectively ignore the content of
- // the window during layout. This avoids it briefly causing
- // other windows to resize/move based on the raw frame of the
- // window, waiting until we can finish laying out this window
- // and get back to the window manager with the ultimately
- // computed insets.
- insetsPending = computesInternalInsets
- && (mFirst || viewVisibilityChanged);
-
- if (mWindowAttributes.memoryType == WindowManager.LayoutParams.MEMORY_TYPE_GPU) {
- if (params == null) {
- params = mWindowAttributes;
- }
- mGlWanted = true;
- }
- }
-
- final Rect frame = mWinFrame;
- boolean initialized = false;
- boolean contentInsetsChanged = false;
- boolean visibleInsetsChanged = false;
- try {
- boolean hadSurface = mSurface.isValid();
- int fl = 0;
- if (params != null) {
- fl = params.flags;
- if (attachInfo.mKeepScreenOn) {
- params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
- }
- }
- relayoutResult = sWindowSession.relayout(
- mWindow, params, host.mMeasuredWidth, host.mMeasuredHeight,
- viewVisibility, insetsPending, frame,
- mPendingContentInsets, mPendingVisibleInsets, mSurface);
- if (params != null) {
- params.flags = fl;
- }
-
- if (DEBUG_LAYOUT) Log.v(TAG, "relayout: frame=" + frame.toShortString()
- + " content=" + mPendingContentInsets.toShortString()
- + " visible=" + mPendingVisibleInsets.toShortString()
- + " surface=" + mSurface);
-
- contentInsetsChanged = !mPendingContentInsets.equals(
- mAttachInfo.mContentInsets);
- visibleInsetsChanged = !mPendingVisibleInsets.equals(
- mAttachInfo.mVisibleInsets);
- if (contentInsetsChanged) {
- mAttachInfo.mContentInsets.set(mPendingContentInsets);
- host.fitSystemWindows(mAttachInfo.mContentInsets);
- if (DEBUG_LAYOUT) Log.v(TAG, "Content insets changing to: "
- + mAttachInfo.mContentInsets);
- }
- if (visibleInsetsChanged) {
- mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets);
- if (DEBUG_LAYOUT) Log.v(TAG, "Visible insets changing to: "
- + mAttachInfo.mVisibleInsets);
- }
-
- if (!hadSurface) {
- if (mSurface.isValid()) {
- // If we are creating a new surface, then we need to
- // completely redraw it. Also, when we get to the
- // point of drawing it we will hold off and schedule
- // a new traversal instead. This is so we can tell the
- // window manager about all of the windows being displayed
- // before actually drawing them, so it can display then
- // all at once.
- newSurface = true;
- fullRedrawNeeded = true;
-
- if (mGlWanted && !mUseGL) {
- initializeGL();
- initialized = mGlCanvas != null;
- }
- }
- } else if (!mSurface.isValid()) {
- // If the surface has been removed, then reset the scroll
- // positions.
- mLastScrolledFocus = null;
- mScrollY = mCurScrollY = 0;
- if (mScroller != null) {
- mScroller.abortAnimation();
- }
- }
- } catch (RemoteException e) {
- }
- if (DEBUG_ORIENTATION) Log.v(
- "ViewRoot", "Relayout returned: frame=" + mWinFrame + ", surface=" + mSurface);
-
- attachInfo.mWindowLeft = frame.left;
- attachInfo.mWindowTop = frame.top;
-
- // !!FIXME!! This next section handles the case where we did not get the
- // window size we asked for. We should avoid this by getting a maximum size from
- // the window session beforehand.
- mWidth = frame.width();
- mHeight = frame.height();
-
- if (initialized) {
- mGlCanvas.setViewport(mWidth, mHeight);
- }
-
- boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
- (relayoutResult&WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE) != 0);
- if (focusChangedDueToTouchMode || mWidth != host.mMeasuredWidth
- || mHeight != host.mMeasuredHeight || contentInsetsChanged) {
- childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
- childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
-
- if (DEBUG_LAYOUT) Log.v(TAG, "Ooops, something changed! mWidth="
- + mWidth + " measuredWidth=" + host.mMeasuredWidth
- + " mHeight=" + mHeight
- + " measuredHeight" + host.mMeasuredHeight
- + " coveredInsetsChanged=" + contentInsetsChanged);
-
- // Ask host how big it wants to be
- host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
-
- // Implementation of weights from WindowManager.LayoutParams
- // We just grow the dimensions as needed and re-measure if
- // needs be
- int width = host.mMeasuredWidth;
- int height = host.mMeasuredHeight;
- boolean measureAgain = false;
-
- if (lp.horizontalWeight > 0.0f) {
- width += (int) ((mWidth - width) * lp.horizontalWeight);
- childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width,
- MeasureSpec.EXACTLY);
- measureAgain = true;
- }
- if (lp.verticalWeight > 0.0f) {
- height += (int) ((mHeight - height) * lp.verticalWeight);
- childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
- MeasureSpec.EXACTLY);
- measureAgain = true;
- }
-
- if (measureAgain) {
- if (DEBUG_LAYOUT) Log.v(TAG,
- "And hey let's measure once more: width=" + width
- + " height=" + height);
- host.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- }
-
- mLayoutRequested = true;
- }
- }
-
- final boolean didLayout = mLayoutRequested;
- boolean triggerGlobalLayoutListener = didLayout
- || attachInfo.mRecomputeGlobalAttributes;
- if (didLayout) {
- mLayoutRequested = false;
- mScrollMayChange = true;
- if (DEBUG_ORIENTATION || DEBUG_LAYOUT) Log.v(
- "ViewRoot", "Laying out " + host + " to (" +
- host.mMeasuredWidth + ", " + host.mMeasuredHeight + ")");
- long startTime;
- if (PROFILE_LAYOUT) {
- startTime = SystemClock.elapsedRealtime();
- }
-
- host.layout(0, 0, host.mMeasuredWidth, host.mMeasuredHeight);
-
- if (PROFILE_LAYOUT) {
- EventLog.writeEvent(60001, SystemClock.elapsedRealtime() - startTime);
- }
-
- // By this point all views have been sized and positionned
- // We can compute the transparent area
-
- if ((host.mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) != 0) {
- // start out transparent
- // TODO: AVOID THAT CALL BY CACHING THE RESULT?
- host.getLocationInWindow(mTmpLocation);
- mTransparentRegion.set(mTmpLocation[0], mTmpLocation[1],
- mTmpLocation[0] + host.mRight - host.mLeft,
- mTmpLocation[1] + host.mBottom - host.mTop);
-
- host.gatherTransparentRegion(mTransparentRegion);
- if (!mTransparentRegion.equals(mPreviousTransparentRegion)) {
- mPreviousTransparentRegion.set(mTransparentRegion);
- // reconfigure window manager
- try {
- sWindowSession.setTransparentRegion(mWindow, mTransparentRegion);
- } catch (RemoteException e) {
- }
- }
- }
-
-
- if (DBG) {
- System.out.println("======================================");
- System.out.println("performTraversals -- after setFrame");
- host.debug();
- }
- }
-
- if (triggerGlobalLayoutListener) {
- attachInfo.mRecomputeGlobalAttributes = false;
- attachInfo.mTreeObserver.dispatchOnGlobalLayout();
- }
-
- if (computesInternalInsets) {
- ViewTreeObserver.InternalInsetsInfo insets = attachInfo.mGivenInternalInsets;
- final Rect givenContent = attachInfo.mGivenInternalInsets.contentInsets;
- final Rect givenVisible = attachInfo.mGivenInternalInsets.visibleInsets;
- givenContent.left = givenContent.top = givenContent.right
- = givenContent.bottom = givenVisible.left = givenVisible.top
- = givenVisible.right = givenVisible.bottom = 0;
- attachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets);
- if (insetsPending || !mLastGivenInsets.equals(insets)) {
- mLastGivenInsets.set(insets);
- try {
- sWindowSession.setInsets(mWindow, insets.mTouchableInsets,
- insets.contentInsets, insets.visibleInsets);
- } catch (RemoteException e) {
- }
- }
- }
-
- if (mFirst) {
- // handle first focus request
- if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: mView.hasFocus()="
- + mView.hasFocus());
- if (mView != null) {
- if (!mView.hasFocus()) {
- mView.requestFocus(View.FOCUS_FORWARD);
- mFocusedView = mRealFocusedView = mView.findFocus();
- if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: requested focused view="
- + mFocusedView);
- } else {
- mRealFocusedView = mView.findFocus();
- if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: existing focused view="
- + mRealFocusedView);
- }
- }
- }
-
- mFirst = false;
- mWillDrawSoon = false;
- mNewSurfaceNeeded = false;
- mViewVisibility = viewVisibility;
-
- boolean cancelDraw = attachInfo.mTreeObserver.dispatchOnPreDraw();
-
- if (!cancelDraw && !newSurface) {
- mFullRedrawNeeded = false;
- draw(fullRedrawNeeded);
-
- if ((relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0
- || mReportNextDraw) {
- if (LOCAL_LOGV) {
- Log.v("ViewRoot", "FINISHED DRAWING: " + mWindowAttributes.getTitle());
- }
- mReportNextDraw = false;
- try {
- sWindowSession.finishDrawing(mWindow);
- } catch (RemoteException e) {
- }
- }
- } else {
- // We were supposed to report when we are done drawing. Since we canceled the
- // draw, remember it here.
- if ((relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) {
- mReportNextDraw = true;
- }
- if (fullRedrawNeeded) {
- mFullRedrawNeeded = true;
- }
- // Try again
- scheduleTraversals();
- }
- }
-
- public void requestTransparentRegion(View child) {
- // the test below should not fail unless someone is messing with us
- checkThread();
- if (mView == child) {
- mView.mPrivateFlags |= View.REQUEST_TRANSPARENT_REGIONS;
- // Need to make sure we re-evaluate the window attributes next
- // time around, to ensure the window has the correct format.
- mWindowAttributesChanged = true;
- }
- }
-
- /**
- * Figures out the measure spec for the root view in a window based on it's
- * layout params.
- *
- * @param windowSize
- * The available width or height of the window
- *
- * @param rootDimension
- * The layout params for one dimension (width or height) of the
- * window.
- *
- * @return The measure spec to use to measure the root view.
- */
- private int getRootMeasureSpec(int windowSize, int rootDimension) {
- int measureSpec;
- switch (rootDimension) {
-
- case ViewGroup.LayoutParams.FILL_PARENT:
- // Window can't resize. Force root view to be windowSize.
- measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY);
- break;
- case ViewGroup.LayoutParams.WRAP_CONTENT:
- // Window can resize. Set max size for root view.
- measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST);
- break;
- default:
- // Window wants to be an exact size. Force root view to be that size.
- measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY);
- break;
- }
- return measureSpec;
- }
-
- private void draw(boolean fullRedrawNeeded) {
- Surface surface = mSurface;
- if (surface == null || !surface.isValid()) {
- return;
- }
-
- scrollToRectOrFocus(null, false);
-
- if (mAttachInfo.mViewScrollChanged) {
- mAttachInfo.mViewScrollChanged = false;
- mAttachInfo.mTreeObserver.dispatchOnScrollChanged();
- }
-
- int yoff;
- final boolean scrolling = mScroller != null
- && mScroller.computeScrollOffset();
- if (scrolling) {
- yoff = mScroller.getCurrY();
- } else {
- yoff = mScrollY;
- }
- if (mCurScrollY != yoff) {
- mCurScrollY = yoff;
- fullRedrawNeeded = true;
- }
-
- Rect dirty = mDirty;
- if (mUseGL) {
- if (!dirty.isEmpty()) {
- Canvas canvas = mGlCanvas;
- if (mGL!=null && canvas != null) {
- mGL.glDisable(GL_SCISSOR_TEST);
- mGL.glClearColor(0, 0, 0, 0);
- mGL.glClear(GL_COLOR_BUFFER_BIT);
- mGL.glEnable(GL_SCISSOR_TEST);
-
- mAttachInfo.mDrawingTime = SystemClock.uptimeMillis();
- canvas.translate(0, -yoff);
- mView.mPrivateFlags |= View.DRAWN;
- mView.draw(canvas);
- canvas.translate(0, yoff);
-
- mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
- checkEglErrors();
-
- if (SHOW_FPS) {
- int now = (int)SystemClock.elapsedRealtime();
- if (sDrawTime != 0) {
- nativeShowFPS(canvas, now - sDrawTime);
- }
- sDrawTime = now;
- }
- }
- }
- if (scrolling) {
- mFullRedrawNeeded = true;
- scheduleTraversals();
- }
- return;
- }
-
- if (fullRedrawNeeded)
- dirty.union(0, 0, mWidth, mHeight);
-
- if (DEBUG_ORIENTATION || DEBUG_DRAW) {
- Log.v("ViewRoot", "Draw " + mView + "/"
- + mWindowAttributes.getTitle()
- + ": dirty={" + dirty.left + "," + dirty.top
- + "," + dirty.right + "," + dirty.bottom + "} surface="
- + surface + " surface.isValid()=" + surface.isValid());
- }
-
- Canvas canvas;
- try {
- canvas = surface.lockCanvas(dirty);
- // TODO: Do this in native
- canvas.setDensityScale(mDensity);
- } catch (Surface.OutOfResourcesException e) {
- Log.e("ViewRoot", "OutOfResourcesException locking surface", e);
- // TODO: we should ask the window manager to do something!
- // for now we just do nothing
- return;
- }
-
- try {
- if (!dirty.isEmpty()) {
- long startTime;
-
- if (DEBUG_ORIENTATION || DEBUG_DRAW) {
- Log.v("ViewRoot", "Surface " + surface + " drawing to bitmap w="
- + canvas.getWidth() + ", h=" + canvas.getHeight());
- //canvas.drawARGB(255, 255, 0, 0);
- }
-
- if (PROFILE_DRAWING) {
- startTime = SystemClock.elapsedRealtime();
- }
-
- // If this bitmap's format includes an alpha channel, we
- // need to clear it before drawing so that the child will
- // properly re-composite its drawing on a transparent
- // background. This automatically respects the clip/dirty region
- if (!canvas.isOpaque()) {
- canvas.drawColor(0xff0000ff, PorterDuff.Mode.CLEAR);
- } else if (yoff != 0) {
- // If we are applying an offset, we need to clear the area
- // where the offset doesn't appear to avoid having garbage
- // left in the blank areas.
- canvas.drawColor(0, PorterDuff.Mode.CLEAR);
- }
-
- dirty.setEmpty();
- mAttachInfo.mDrawingTime = SystemClock.uptimeMillis();
- canvas.translate(0, -yoff);
- mView.mPrivateFlags |= View.DRAWN;
- mView.draw(canvas);
- canvas.translate(0, yoff);
-
- if (SHOW_FPS) {
- int now = (int)SystemClock.elapsedRealtime();
- if (sDrawTime != 0) {
- nativeShowFPS(canvas, now - sDrawTime);
- }
- sDrawTime = now;
- }
-
- if (PROFILE_DRAWING) {
- EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime);
- }
- }
-
- } finally {
- surface.unlockCanvasAndPost(canvas);
- }
-
- if (LOCAL_LOGV) {
- Log.v("ViewRoot", "Surface " + surface + " unlockCanvasAndPost");
- }
-
- if (scrolling) {
- mFullRedrawNeeded = true;
- scheduleTraversals();
- }
- }
-
- boolean scrollToRectOrFocus(Rect rectangle, boolean immediate) {
- final View.AttachInfo attachInfo = mAttachInfo;
- final Rect ci = attachInfo.mContentInsets;
- final Rect vi = attachInfo.mVisibleInsets;
- int scrollY = 0;
- boolean handled = false;
-
- if (vi.left > ci.left || vi.top > ci.top
- || vi.right > ci.right || vi.bottom > ci.bottom) {
- // We'll assume that we aren't going to change the scroll
- // offset, since we want to avoid that unless it is actually
- // going to make the focus visible... otherwise we scroll
- // all over the place.
- scrollY = mScrollY;
- // We can be called for two different situations: during a draw,
- // to update the scroll position if the focus has changed (in which
- // case 'rectangle' is null), or in response to a
- // requestChildRectangleOnScreen() call (in which case 'rectangle'
- // is non-null and we just want to scroll to whatever that
- // rectangle is).
- View focus = mRealFocusedView;
- if (focus != mLastScrolledFocus) {
- // If the focus has changed, then ignore any requests to scroll
- // to a rectangle; first we want to make sure the entire focus
- // view is visible.
- rectangle = null;
- }
- if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Eval scroll: focus=" + focus
- + " rectangle=" + rectangle + " ci=" + ci
- + " vi=" + vi);
- if (focus == mLastScrolledFocus && !mScrollMayChange
- && rectangle == null) {
- // Optimization: if the focus hasn't changed since last
- // time, and no layout has happened, then just leave things
- // as they are.
- if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Keeping scroll y="
- + mScrollY + " vi=" + vi.toShortString());
- } else if (focus != null) {
- // We need to determine if the currently focused view is
- // within the visible part of the window and, if not, apply
- // a pan so it can be seen.
- mLastScrolledFocus = focus;
- mScrollMayChange = false;
- if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Need to scroll?");
- // Try to find the rectangle from the focus view.
- if (focus.getGlobalVisibleRect(mVisRect, null)) {
- if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Root w="
- + mView.getWidth() + " h=" + mView.getHeight()
- + " ci=" + ci.toShortString()
- + " vi=" + vi.toShortString());
- if (rectangle == null) {
- focus.getFocusedRect(mTempRect);
- if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Focus " + focus
- + ": focusRect=" + mTempRect.toShortString());
- ((ViewGroup) mView).offsetDescendantRectToMyCoords(
- focus, mTempRect);
- if (DEBUG_INPUT_RESIZE) Log.v(TAG,
- "Focus in window: focusRect="
- + mTempRect.toShortString()
- + " visRect=" + mVisRect.toShortString());
- } else {
- mTempRect.set(rectangle);
- if (DEBUG_INPUT_RESIZE) Log.v(TAG,
- "Request scroll to rect: "
- + mTempRect.toShortString()
- + " visRect=" + mVisRect.toShortString());
- }
- if (mTempRect.intersect(mVisRect)) {
- if (DEBUG_INPUT_RESIZE) Log.v(TAG,
- "Focus window visible rect: "
- + mTempRect.toShortString());
- if (mTempRect.height() >
- (mView.getHeight()-vi.top-vi.bottom)) {
- // If the focus simply is not going to fit, then
- // best is probably just to leave things as-is.
- if (DEBUG_INPUT_RESIZE) Log.v(TAG,
- "Too tall; leaving scrollY=" + scrollY);
- } else if ((mTempRect.top-scrollY) < vi.top) {
- scrollY -= vi.top - (mTempRect.top-scrollY);
- if (DEBUG_INPUT_RESIZE) Log.v(TAG,
- "Top covered; scrollY=" + scrollY);
- } else if ((mTempRect.bottom-scrollY)
- > (mView.getHeight()-vi.bottom)) {
- scrollY += (mTempRect.bottom-scrollY)
- - (mView.getHeight()-vi.bottom);
- if (DEBUG_INPUT_RESIZE) Log.v(TAG,
- "Bottom covered; scrollY=" + scrollY);
- }
- handled = true;
- }
- }
- }
- }
-
- if (scrollY != mScrollY) {
- if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Pan scroll changed: old="
- + mScrollY + " , new=" + scrollY);
- if (!immediate) {
- if (mScroller == null) {
- mScroller = new Scroller(mView.getContext());
- }
- mScroller.startScroll(0, mScrollY, 0, scrollY-mScrollY);
- } else if (mScroller != null) {
- mScroller.abortAnimation();
- }
- mScrollY = scrollY;
- }
-
- return handled;
- }
-
- public void requestChildFocus(View child, View focused) {
- checkThread();
- if (mFocusedView != focused) {
- mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(mFocusedView, focused);
- scheduleTraversals();
- }
- mFocusedView = mRealFocusedView = focused;
- if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Request child focus: focus now "
- + mFocusedView);
- }
-
- public void clearChildFocus(View child) {
- checkThread();
-
- View oldFocus = mFocusedView;
-
- if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Clearing child focus");
- mFocusedView = mRealFocusedView = null;
- if (mView != null && !mView.hasFocus()) {
- // If a view gets the focus, the listener will be invoked from requestChildFocus()
- if (!mView.requestFocus(View.FOCUS_FORWARD)) {
- mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
- }
- } else if (oldFocus != null) {
- mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
- }
- }
-
-
- public void focusableViewAvailable(View v) {
- checkThread();
-
- if (mView != null && !mView.hasFocus()) {
- v.requestFocus();
- } else {
- // the one case where will transfer focus away from the current one
- // is if the current view is a view group that prefers to give focus
- // to its children first AND the view is a descendant of it.
- mFocusedView = mView.findFocus();
- boolean descendantsHaveDibsOnFocus =
- (mFocusedView instanceof ViewGroup) &&
- (((ViewGroup) mFocusedView).getDescendantFocusability() ==
- ViewGroup.FOCUS_AFTER_DESCENDANTS);
- if (descendantsHaveDibsOnFocus && isViewDescendantOf(v, mFocusedView)) {
- // If a view gets the focus, the listener will be invoked from requestChildFocus()
- v.requestFocus();
- }
- }
- }
-
- public void recomputeViewAttributes(View child) {
- checkThread();
- if (mView == child) {
- mAttachInfo.mRecomputeGlobalAttributes = true;
- if (!mWillDrawSoon) {
- scheduleTraversals();
- }
- }
- }
-
- void dispatchDetachedFromWindow() {
- if (Config.LOGV) Log.v("ViewRoot", "Detaching in " + this + " of " + mSurface);
-
- if (mView != null) {
- mView.dispatchDetachedFromWindow();
- }
-
- mView = null;
- mAttachInfo.mRootView = null;
-
- if (mUseGL) {
- destroyGL();
- }
-
- try {
- sWindowSession.remove(mWindow);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Return true if child is an ancestor of parent, (or equal to the parent).
- */
- private static boolean isViewDescendantOf(View child, View parent) {
- if (child == parent) {
- return true;
- }
-
- final ViewParent theParent = child.getParent();
- return (theParent instanceof ViewGroup) && isViewDescendantOf((View) theParent, parent);
- }
-
-
- public final static int DO_TRAVERSAL = 1000;
- public final static int DIE = 1001;
- public final static int RESIZED = 1002;
- public final static int RESIZED_REPORT = 1003;
- public final static int WINDOW_FOCUS_CHANGED = 1004;
- public final static int DISPATCH_KEY = 1005;
- public final static int DISPATCH_POINTER = 1006;
- public final static int DISPATCH_TRACKBALL = 1007;
- public final static int DISPATCH_APP_VISIBILITY = 1008;
- public final static int DISPATCH_GET_NEW_SURFACE = 1009;
- public final static int FINISHED_EVENT = 1010;
- public final static int DISPATCH_KEY_FROM_IME = 1011;
- public final static int FINISH_INPUT_CONNECTION = 1012;
- public final static int CHECK_FOCUS = 1013;
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case View.AttachInfo.INVALIDATE_MSG:
- ((View) msg.obj).invalidate();
- break;
- case View.AttachInfo.INVALIDATE_RECT_MSG:
- final View.AttachInfo.InvalidateInfo info = (View.AttachInfo.InvalidateInfo) msg.obj;
- info.target.invalidate(info.left, info.top, info.right, info.bottom);
- info.release();
- break;
- case DO_TRAVERSAL:
- if (mProfile) {
- Debug.startMethodTracing("ViewRoot");
- }
-
- performTraversals();
-
- if (mProfile) {
- Debug.stopMethodTracing();
- mProfile = false;
- }
- break;
- case FINISHED_EVENT:
- handleFinishedEvent(msg.arg1, msg.arg2 != 0);
- break;
- case DISPATCH_KEY:
- if (LOCAL_LOGV) Log.v(
- "ViewRoot", "Dispatching key "
- + msg.obj + " to " + mView);
- deliverKeyEvent((KeyEvent)msg.obj, true);
- break;
- case DISPATCH_POINTER:
- MotionEvent event = (MotionEvent)msg.obj;
-
- boolean didFinish;
- if (event == null) {
- try {
- event = sWindowSession.getPendingPointerMove(mWindow);
- } catch (RemoteException e) {
- }
- didFinish = true;
- } else {
- didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;
- }
-
- try {
- boolean handled;
- if (mView != null && mAdded && event != null) {
-
- // enter touch mode on the down
- boolean isDown = event.getAction() == MotionEvent.ACTION_DOWN;
- if (isDown) {
- ensureTouchMode(true);
- }
- if(Config.LOGV) {
- captureMotionLog("captureDispatchPointer", event);
- }
- event.offsetLocation(0, mCurScrollY);
- handled = mView.dispatchTouchEvent(event);
- if (!handled && isDown) {
- int edgeSlop = mViewConfiguration.getScaledEdgeSlop();
-
- final int edgeFlags = event.getEdgeFlags();
- int direction = View.FOCUS_UP;
- int x = (int)event.getX();
- int y = (int)event.getY();
- final int[] deltas = new int[2];
-
- if ((edgeFlags & MotionEvent.EDGE_TOP) != 0) {
- direction = View.FOCUS_DOWN;
- if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
- deltas[0] = edgeSlop;
- x += edgeSlop;
- } else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
- deltas[0] = -edgeSlop;
- x -= edgeSlop;
- }
- } else if ((edgeFlags & MotionEvent.EDGE_BOTTOM) != 0) {
- direction = View.FOCUS_UP;
- if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
- deltas[0] = edgeSlop;
- x += edgeSlop;
- } else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
- deltas[0] = -edgeSlop;
- x -= edgeSlop;
- }
- } else if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
- direction = View.FOCUS_RIGHT;
- } else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
- direction = View.FOCUS_LEFT;
- }
-
- if (edgeFlags != 0 && mView instanceof ViewGroup) {
- View nearest = FocusFinder.getInstance().findNearestTouchable(
- ((ViewGroup) mView), x, y, direction, deltas);
- if (nearest != null) {
- event.offsetLocation(deltas[0], deltas[1]);
- event.setEdgeFlags(0);
- mView.dispatchTouchEvent(event);
- }
- }
- }
- }
- } finally {
- if (!didFinish) {
- try {
- sWindowSession.finishKey(mWindow);
- } catch (RemoteException e) {
- }
- }
- if (event != null) {
- event.recycle();
- }
- if (LOCAL_LOGV || WATCH_POINTER) Log.i(TAG, "Done dispatching!");
- // Let the exception fall through -- the looper will catch
- // it and take care of the bad app for us.
- }
- break;
- case DISPATCH_TRACKBALL:
- deliverTrackballEvent((MotionEvent)msg.obj);
- break;
- case DISPATCH_APP_VISIBILITY:
- handleAppVisibility(msg.arg1 != 0);
- break;
- case DISPATCH_GET_NEW_SURFACE:
- handleGetNewSurface();
- break;
- case RESIZED:
- Rect coveredInsets = ((Rect[])msg.obj)[0];
- Rect visibleInsets = ((Rect[])msg.obj)[1];
- if (mWinFrame.width() == msg.arg1 && mWinFrame.height() == msg.arg2
- && mPendingContentInsets.equals(coveredInsets)
- && mPendingVisibleInsets.equals(visibleInsets)) {
- break;
- }
- // fall through...
- case RESIZED_REPORT:
- if (mAdded) {
- mWinFrame.left = 0;
- mWinFrame.right = msg.arg1;
- mWinFrame.top = 0;
- mWinFrame.bottom = msg.arg2;
- mPendingContentInsets.set(((Rect[])msg.obj)[0]);
- mPendingVisibleInsets.set(((Rect[])msg.obj)[1]);
- if (msg.what == RESIZED_REPORT) {
- mReportNextDraw = true;
- }
- requestLayout();
- }
- break;
- case WINDOW_FOCUS_CHANGED: {
- if (mAdded) {
- boolean hasWindowFocus = msg.arg1 != 0;
- mAttachInfo.mHasWindowFocus = hasWindowFocus;
- if (hasWindowFocus) {
- boolean inTouchMode = msg.arg2 != 0;
- ensureTouchModeLocally(inTouchMode);
-
- if (mGlWanted) {
- checkEglErrors();
- // we lost the gl context, so recreate it.
- if (mGlWanted && !mUseGL) {
- initializeGL();
- if (mGlCanvas != null) {
- mGlCanvas.setViewport(mWidth, mHeight);
- }
- }
- }
- }
-
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (mView != null) {
- if (hasWindowFocus && imm != null) {
- imm.startGettingWindowFocus();
- }
- mView.dispatchWindowFocusChanged(hasWindowFocus);
- }
-
- // Note: must be done after the focus change callbacks,
- // so all of the view state is set up correctly.
- if (hasWindowFocus) {
- if (imm != null) {
- imm.onWindowFocus(mView, mView.findFocus(),
- mWindowAttributes.softInputMode,
- !mHasHadWindowFocus, mWindowAttributes.flags);
- }
- // Clear the forward bit. We can just do this directly, since
- // the window manager doesn't care about it.
- mWindowAttributes.softInputMode &=
- ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
- ((WindowManager.LayoutParams)mView.getLayoutParams())
- .softInputMode &=
- ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
- mHasHadWindowFocus = true;
- }
- }
- } break;
- case DIE:
- dispatchDetachedFromWindow();
- break;
- case DISPATCH_KEY_FROM_IME:
- if (LOCAL_LOGV) Log.v(
- "ViewRoot", "Dispatching key "
- + msg.obj + " from IME to " + mView);
- deliverKeyEventToViewHierarchy((KeyEvent)msg.obj, false);
- break;
- case FINISH_INPUT_CONNECTION: {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) {
- imm.reportFinishInputConnection((InputConnection)msg.obj);
- }
- } break;
- case CHECK_FOCUS: {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) {
- imm.checkFocus((View)msg.obj);
- }
- } break;
- }
- }
-
- /**
- * Something in the current window tells us we need to change the touch mode. For
- * example, we are not in touch mode, and the user touches the screen.
- *
- * If the touch mode has changed, tell the window manager, and handle it locally.
- *
- * @param inTouchMode Whether we want to be in touch mode.
- * @return True if the touch mode changed and focus changed was changed as a result
- */
- boolean ensureTouchMode(boolean inTouchMode) {
- if (DBG) Log.d("touchmode", "ensureTouchMode(" + inTouchMode + "), current "
- + "touch mode is " + mAttachInfo.mInTouchMode);
- if (mAttachInfo.mInTouchMode == inTouchMode) return false;
-
- // tell the window manager
- try {
- sWindowSession.setInTouchMode(inTouchMode);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
-
- // handle the change
- return ensureTouchModeLocally(inTouchMode);
- }
-
- /**
- * Ensure that the touch mode for this window is set, and if it is changing,
- * take the appropriate action.
- * @param inTouchMode Whether we want to be in touch mode.
- * @return True if the touch mode changed and focus changed was changed as a result
- */
- private boolean ensureTouchModeLocally(boolean inTouchMode) {
- if (DBG) Log.d("touchmode", "ensureTouchModeLocally(" + inTouchMode + "), current "
- + "touch mode is " + mAttachInfo.mInTouchMode);
-
- if (mAttachInfo.mInTouchMode == inTouchMode) return false;
-
- mAttachInfo.mInTouchMode = inTouchMode;
- mAttachInfo.mTreeObserver.dispatchOnTouchModeChanged(inTouchMode);
-
- return (inTouchMode) ? enterTouchMode() : leaveTouchMode();
- }
-
- private boolean enterTouchMode() {
- if (mView != null) {
- if (mView.hasFocus()) {
- // note: not relying on mFocusedView here because this could
- // be when the window is first being added, and mFocused isn't
- // set yet.
- final View focused = mView.findFocus();
- if (focused != null && !focused.isFocusableInTouchMode()) {
-
- final ViewGroup ancestorToTakeFocus =
- findAncestorToTakeFocusInTouchMode(focused);
- if (ancestorToTakeFocus != null) {
- // there is an ancestor that wants focus after its descendants that
- // is focusable in touch mode.. give it focus
- return ancestorToTakeFocus.requestFocus();
- } else {
- // nothing appropriate to have focus in touch mode, clear it out
- mView.unFocus();
- mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(focused, null);
- mFocusedView = null;
- return true;
- }
- }
- }
- }
- return false;
- }
-
-
- /**
- * Find an ancestor of focused that wants focus after its descendants and is
- * focusable in touch mode.
- * @param focused The currently focused view.
- * @return An appropriate view, or null if no such view exists.
- */
- private ViewGroup findAncestorToTakeFocusInTouchMode(View focused) {
- ViewParent parent = focused.getParent();
- while (parent instanceof ViewGroup) {
- final ViewGroup vgParent = (ViewGroup) parent;
- if (vgParent.getDescendantFocusability() == ViewGroup.FOCUS_AFTER_DESCENDANTS
- && vgParent.isFocusableInTouchMode()) {
- return vgParent;
- }
- if (vgParent.isRootNamespace()) {
- return null;
- } else {
- parent = vgParent.getParent();
- }
- }
- return null;
- }
-
- private boolean leaveTouchMode() {
- if (mView != null) {
- if (mView.hasFocus()) {
- // i learned the hard way to not trust mFocusedView :)
- mFocusedView = mView.findFocus();
- if (!(mFocusedView instanceof ViewGroup)) {
- // some view has focus, let it keep it
- return false;
- } else if (((ViewGroup)mFocusedView).getDescendantFocusability() !=
- ViewGroup.FOCUS_AFTER_DESCENDANTS) {
- // some view group has focus, and doesn't prefer its children
- // over itself for focus, so let them keep it.
- return false;
- }
- }
-
- // find the best view to give focus to in this brave new non-touch-mode
- // world
- final View focused = focusSearch(null, View.FOCUS_DOWN);
- if (focused != null) {
- return focused.requestFocus(View.FOCUS_DOWN);
- }
- }
- return false;
- }
-
-
- private void deliverTrackballEvent(MotionEvent event) {
- boolean didFinish;
- if (event == null) {
- try {
- event = sWindowSession.getPendingTrackballMove(mWindow);
- } catch (RemoteException e) {
- }
- didFinish = true;
- } else {
- didFinish = false;
- }
-
- if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event);
-
- boolean handled = false;
- try {
- if (event == null) {
- handled = true;
- } else if (mView != null && mAdded) {
- handled = mView.dispatchTrackballEvent(event);
- if (!handled) {
- // we could do something here, like changing the focus
- // or something?
- }
- }
- } finally {
- if (handled) {
- if (!didFinish) {
- try {
- sWindowSession.finishKey(mWindow);
- } catch (RemoteException e) {
- }
- }
- if (event != null) {
- event.recycle();
- }
- // If we reach this, we delivered a trackball event to mView and
- // mView consumed it. Because we will not translate the trackball
- // event into a key event, touch mode will not exit, so we exit
- // touch mode here.
- ensureTouchMode(false);
- //noinspection ReturnInsideFinallyBlock
- return;
- }
- // Let the exception fall through -- the looper will catch
- // it and take care of the bad app for us.
- }
-
- final TrackballAxis x = mTrackballAxisX;
- final TrackballAxis y = mTrackballAxisY;
-
- long curTime = SystemClock.uptimeMillis();
- if ((mLastTrackballTime+MAX_TRACKBALL_DELAY) < curTime) {
- // It has been too long since the last movement,
- // so restart at the beginning.
- x.reset(0);
- y.reset(0);
- mLastTrackballTime = curTime;
- }
-
- try {
- final int action = event.getAction();
- final int metastate = event.getMetaState();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- x.reset(2);
- y.reset(2);
- deliverKeyEvent(new KeyEvent(curTime, curTime,
- KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER,
- 0, metastate), false);
- break;
- case MotionEvent.ACTION_UP:
- x.reset(2);
- y.reset(2);
- deliverKeyEvent(new KeyEvent(curTime, curTime,
- KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER,
- 0, metastate), false);
- break;
- }
-
- if (DEBUG_TRACKBALL) Log.v(TAG, "TB X=" + x.position + " step="
- + x.step + " dir=" + x.dir + " acc=" + x.acceleration
- + " move=" + event.getX()
- + " / Y=" + y.position + " step="
- + y.step + " dir=" + y.dir + " acc=" + y.acceleration
- + " move=" + event.getY());
- final float xOff = x.collect(event.getX(), event.getEventTime(), "X");
- final float yOff = y.collect(event.getY(), event.getEventTime(), "Y");
-
- // Generate DPAD events based on the trackball movement.
- // We pick the axis that has moved the most as the direction of
- // the DPAD. When we generate DPAD events for one axis, then the
- // other axis is reset -- we don't want to perform DPAD jumps due
- // to slight movements in the trackball when making major movements
- // along the other axis.
- int keycode = 0;
- int movement = 0;
- float accel = 1;
- if (xOff > yOff) {
- movement = x.generate((2/event.getXPrecision()));
- if (movement != 0) {
- keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_RIGHT
- : KeyEvent.KEYCODE_DPAD_LEFT;
- accel = x.acceleration;
- y.reset(2);
- }
- } else if (yOff > 0) {
- movement = y.generate((2/event.getYPrecision()));
- if (movement != 0) {
- keycode = movement > 0 ? KeyEvent.KEYCODE_DPAD_DOWN
- : KeyEvent.KEYCODE_DPAD_UP;
- accel = y.acceleration;
- x.reset(2);
- }
- }
-
- if (keycode != 0) {
- if (movement < 0) movement = -movement;
- int accelMovement = (int)(movement * accel);
- if (DEBUG_TRACKBALL) Log.v(TAG, "Move: movement=" + movement
- + " accelMovement=" + accelMovement
- + " accel=" + accel);
- if (accelMovement > movement) {
- if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
- + keycode);
- movement--;
- deliverKeyEvent(new KeyEvent(curTime, curTime,
- KeyEvent.ACTION_MULTIPLE, keycode,
- accelMovement-movement, metastate), false);
- }
- while (movement > 0) {
- if (DEBUG_TRACKBALL) Log.v("foo", "Delivering fake DPAD: "
- + keycode);
- movement--;
- curTime = SystemClock.uptimeMillis();
- deliverKeyEvent(new KeyEvent(curTime, curTime,
- KeyEvent.ACTION_DOWN, keycode, 0, event.getMetaState()), false);
- deliverKeyEvent(new KeyEvent(curTime, curTime,
- KeyEvent.ACTION_UP, keycode, 0, metastate), false);
- }
- mLastTrackballTime = curTime;
- }
- } finally {
- if (!didFinish) {
- try {
- sWindowSession.finishKey(mWindow);
- } catch (RemoteException e) {
- }
- if (event != null) {
- event.recycle();
- }
- }
- // Let the exception fall through -- the looper will catch
- // it and take care of the bad app for us.
- }
- }
-
- /**
- * @param keyCode The key code
- * @return True if the key is directional.
- */
- static boolean isDirectional(int keyCode) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- return true;
- }
- return false;
- }
-
- /**
- * Returns true if this key is a keyboard key.
- * @param keyEvent The key event.
- * @return whether this key is a keyboard key.
- */
- private static boolean isKeyboardKey(KeyEvent keyEvent) {
- final int convertedKey = keyEvent.getUnicodeChar();
- return convertedKey > 0;
- }
-
-
-
- /**
- * See if the key event means we should leave touch mode (and leave touch
- * mode if so).
- * @param event The key event.
- * @return Whether this key event should be consumed (meaning the act of
- * leaving touch mode alone is considered the event).
- */
- private boolean checkForLeavingTouchModeAndConsume(KeyEvent event) {
- if (event.getAction() != KeyEvent.ACTION_DOWN) {
- return false;
- }
-
- // only relevant if we are in touch mode
- if (!mAttachInfo.mInTouchMode) {
- return false;
- }
-
- // if something like an edit text has focus and the user is typing,
- // leave touch mode
- //
- // note: the condition of not being a keyboard key is kind of a hacky
- // approximation of whether we think the focused view will want the
- // key; if we knew for sure whether the focused view would consume
- // the event, that would be better.
- if (isKeyboardKey(event) && mView != null && mView.hasFocus()) {
- mFocusedView = mView.findFocus();
- if ((mFocusedView instanceof ViewGroup)
- && ((ViewGroup) mFocusedView).getDescendantFocusability() ==
- ViewGroup.FOCUS_AFTER_DESCENDANTS) {
- // something has focus, but is holding it weakly as a container
- return false;
- }
- if (ensureTouchMode(false)) {
- throw new IllegalStateException("should not have changed focus "
- + "when leaving touch mode while a view has focus.");
- }
- return false;
- }
-
- if (isDirectional(event.getKeyCode())) {
- // no view has focus, so we leave touch mode (and find something
- // to give focus to). the event is consumed if we were able to
- // find something to give focus to.
- return ensureTouchMode(false);
- }
- return false;
- }
-
- /**
- * log motion events
- */
- private static void captureMotionLog(String subTag, MotionEvent ev) {
- //check dynamic switch
- if (ev == null ||
- SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_EVENT, 0) == 0) {
- return;
- }
-
- StringBuilder sb = new StringBuilder(subTag + ": ");
- sb.append(ev.getDownTime()).append(',');
- sb.append(ev.getEventTime()).append(',');
- sb.append(ev.getAction()).append(',');
- sb.append(ev.getX()).append(',');
- sb.append(ev.getY()).append(',');
- sb.append(ev.getPressure()).append(',');
- sb.append(ev.getSize()).append(',');
- sb.append(ev.getMetaState()).append(',');
- sb.append(ev.getXPrecision()).append(',');
- sb.append(ev.getYPrecision()).append(',');
- sb.append(ev.getDeviceId()).append(',');
- sb.append(ev.getEdgeFlags());
- Log.d(TAG, sb.toString());
- }
- /**
- * log motion events
- */
- private static void captureKeyLog(String subTag, KeyEvent ev) {
- //check dynamic switch
- if (ev == null ||
- SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_EVENT, 0) == 0) {
- return;
- }
- StringBuilder sb = new StringBuilder(subTag + ": ");
- sb.append(ev.getDownTime()).append(',');
- sb.append(ev.getEventTime()).append(',');
- sb.append(ev.getAction()).append(',');
- sb.append(ev.getKeyCode()).append(',');
- sb.append(ev.getRepeatCount()).append(',');
- sb.append(ev.getMetaState()).append(',');
- sb.append(ev.getDeviceId()).append(',');
- sb.append(ev.getScanCode());
- Log.d(TAG, sb.toString());
- }
-
- int enqueuePendingEvent(Object event, boolean sendDone) {
- int seq = mPendingEventSeq+1;
- if (seq < 0) seq = 0;
- mPendingEventSeq = seq;
- mPendingEvents.put(seq, event);
- return sendDone ? seq : -seq;
- }
-
- Object retrievePendingEvent(int seq) {
- if (seq < 0) seq = -seq;
- Object event = mPendingEvents.get(seq);
- if (event != null) {
- mPendingEvents.remove(seq);
- }
- return event;
- }
-
- private void deliverKeyEvent(KeyEvent event, boolean sendDone) {
- // If mView is null, we just consume the key event because it doesn't
- // make sense to do anything else with it.
- boolean handled = mView != null
- ? mView.dispatchKeyEventPreIme(event) : true;
- if (handled) {
- if (sendDone) {
- if (LOCAL_LOGV) Log.v(
- "ViewRoot", "Telling window manager key is finished");
- try {
- sWindowSession.finishKey(mWindow);
- } catch (RemoteException e) {
- }
- }
- return;
- }
- // If it is possible for this window to interact with the input
- // method window, then we want to first dispatch our key events
- // to the input method.
- if (WindowManager.LayoutParams.mayUseInputMethod(
- mWindowAttributes.flags)) {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null && mView != null) {
- int seq = enqueuePendingEvent(event, sendDone);
- if (DEBUG_IMF) Log.v(TAG, "Sending key event to IME: seq="
- + seq + " event=" + event);
- imm.dispatchKeyEvent(mView.getContext(), seq, event,
- mInputMethodCallback);
- return;
- }
- }
- deliverKeyEventToViewHierarchy(event, sendDone);
- }
-
- void handleFinishedEvent(int seq, boolean handled) {
- final KeyEvent event = (KeyEvent)retrievePendingEvent(seq);
- if (DEBUG_IMF) Log.v(TAG, "IME finished event: seq=" + seq
- + " handled=" + handled + " event=" + event);
- if (event != null) {
- final boolean sendDone = seq >= 0;
- if (!handled) {
- deliverKeyEventToViewHierarchy(event, sendDone);
- return;
- } else if (sendDone) {
- if (LOCAL_LOGV) Log.v(
- "ViewRoot", "Telling window manager key is finished");
- try {
- sWindowSession.finishKey(mWindow);
- } catch (RemoteException e) {
- }
- }
- }
- }
-
- private void deliverKeyEventToViewHierarchy(KeyEvent event, boolean sendDone) {
- try {
- if (mView != null && mAdded) {
- final int action = event.getAction();
- boolean isDown = (action == KeyEvent.ACTION_DOWN);
-
- if (checkForLeavingTouchModeAndConsume(event)) {
- return;
- }
-
- if (Config.LOGV) {
- captureKeyLog("captureDispatchKeyEvent", event);
- }
- boolean keyHandled = mView.dispatchKeyEvent(event);
-
- if (!keyHandled && isDown) {
- int direction = 0;
- switch (event.getKeyCode()) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- direction = View.FOCUS_LEFT;
- break;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- direction = View.FOCUS_RIGHT;
- break;
- case KeyEvent.KEYCODE_DPAD_UP:
- direction = View.FOCUS_UP;
- break;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- direction = View.FOCUS_DOWN;
- break;
- }
-
- if (direction != 0) {
-
- View focused = mView != null ? mView.findFocus() : null;
- if (focused != null) {
- View v = focused.focusSearch(direction);
- boolean focusPassed = false;
- if (v != null && v != focused) {
- // do the math the get the interesting rect
- // of previous focused into the coord system of
- // newly focused view
- focused.getFocusedRect(mTempRect);
- ((ViewGroup) mView).offsetDescendantRectToMyCoords(focused, mTempRect);
- ((ViewGroup) mView).offsetRectIntoDescendantCoords(v, mTempRect);
- focusPassed = v.requestFocus(direction, mTempRect);
- }
-
- if (!focusPassed) {
- mView.dispatchUnhandledMove(focused, direction);
- } else {
- playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
- }
- }
- }
- }
- }
-
- } finally {
- if (sendDone) {
- if (LOCAL_LOGV) Log.v(
- "ViewRoot", "Telling window manager key is finished");
- try {
- sWindowSession.finishKey(mWindow);
- } catch (RemoteException e) {
- }
- }
- // Let the exception fall through -- the looper will catch
- // it and take care of the bad app for us.
- }
- }
-
- private AudioManager getAudioManager() {
- if (mView == null) {
- throw new IllegalStateException("getAudioManager called when there is no mView");
- }
- if (mAudioManager == null) {
- mAudioManager = (AudioManager) mView.getContext().getSystemService(Context.AUDIO_SERVICE);
- }
- return mAudioManager;
- }
-
- /**
- * {@inheritDoc}
- */
- public void playSoundEffect(int effectId) {
- checkThread();
-
- final AudioManager audioManager = getAudioManager();
-
- switch (effectId) {
- case SoundEffectConstants.CLICK:
- audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
- return;
- case SoundEffectConstants.NAVIGATION_DOWN:
- audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN);
- return;
- case SoundEffectConstants.NAVIGATION_LEFT:
- audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT);
- return;
- case SoundEffectConstants.NAVIGATION_RIGHT:
- audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT);
- return;
- case SoundEffectConstants.NAVIGATION_UP:
- audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP);
- return;
- default:
- throw new IllegalArgumentException("unknown effect id " + effectId +
- " not defined in " + SoundEffectConstants.class.getCanonicalName());
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean performHapticFeedback(int effectId, boolean always) {
- try {
- return sWindowSession.performHapticFeedback(mWindow, effectId, always);
- } catch (RemoteException e) {
- return false;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public View focusSearch(View focused, int direction) {
- checkThread();
- if (!(mView instanceof ViewGroup)) {
- return null;
- }
- return FocusFinder.getInstance().findNextFocus((ViewGroup) mView, focused, direction);
- }
-
- public void debug() {
- mView.debug();
- }
-
- public void die(boolean immediate) {
- checkThread();
- if (Config.LOGV) Log.v("ViewRoot", "DIE in " + this + " of " + mSurface);
- synchronized (this) {
- if (mAdded && !mFirst) {
- int viewVisibility = mView.getVisibility();
- boolean viewVisibilityChanged = mViewVisibility != viewVisibility;
- if (mWindowAttributesChanged || viewVisibilityChanged) {
- // If layout params have been changed, first give them
- // to the window manager to make sure it has the correct
- // animation info.
- try {
- if ((sWindowSession.relayout(
- mWindow, mWindowAttributes,
- mView.mMeasuredWidth, mView.mMeasuredHeight,
- viewVisibility, false, mWinFrame, mPendingContentInsets,
- mPendingVisibleInsets, mSurface)
- &WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) {
- sWindowSession.finishDrawing(mWindow);
- }
- } catch (RemoteException e) {
- }
- }
-
- mSurface = null;
- }
- if (mAdded) {
- mAdded = false;
- if (immediate) {
- dispatchDetachedFromWindow();
- } else if (mView != null) {
- sendEmptyMessage(DIE);
- }
- }
- }
- }
-
- public void dispatchFinishedEvent(int seq, boolean handled) {
- Message msg = obtainMessage(FINISHED_EVENT);
- msg.arg1 = seq;
- msg.arg2 = handled ? 1 : 0;
- sendMessage(msg);
- }
-
- public void dispatchResized(int w, int h, Rect coveredInsets,
- Rect visibleInsets, boolean reportDraw) {
- if (DEBUG_LAYOUT) Log.v(TAG, "Resizing " + this + ": w=" + w
- + " h=" + h + " coveredInsets=" + coveredInsets.toShortString()
- + " visibleInsets=" + visibleInsets.toShortString()
- + " reportDraw=" + reportDraw);
- Message msg = obtainMessage(reportDraw ? RESIZED_REPORT :RESIZED);
- msg.arg1 = w;
- msg.arg2 = h;
- msg.obj = new Rect[] { new Rect(coveredInsets), new Rect(visibleInsets) };
- sendMessage(msg);
- }
-
- public void dispatchKey(KeyEvent event) {
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- //noinspection ConstantConditions
- if (false && event.getKeyCode() == KeyEvent.KEYCODE_CAMERA) {
- if (Config.LOGD) Log.d("keydisp",
- "===================================================");
- if (Config.LOGD) Log.d("keydisp", "Focused view Hierarchy is:");
- debug();
-
- if (Config.LOGD) Log.d("keydisp",
- "===================================================");
- }
- }
-
- Message msg = obtainMessage(DISPATCH_KEY);
- msg.obj = event;
-
- if (LOCAL_LOGV) Log.v(
- "ViewRoot", "sending key " + event + " to " + mView);
-
- sendMessageAtTime(msg, event.getEventTime());
- }
-
- public void dispatchPointer(MotionEvent event, long eventTime) {
- Message msg = obtainMessage(DISPATCH_POINTER);
- msg.obj = event;
- sendMessageAtTime(msg, eventTime);
- }
-
- public void dispatchTrackball(MotionEvent event, long eventTime) {
- Message msg = obtainMessage(DISPATCH_TRACKBALL);
- msg.obj = event;
- sendMessageAtTime(msg, eventTime);
- }
-
- public void dispatchAppVisibility(boolean visible) {
- Message msg = obtainMessage(DISPATCH_APP_VISIBILITY);
- msg.arg1 = visible ? 1 : 0;
- sendMessage(msg);
- }
-
- public void dispatchGetNewSurface() {
- Message msg = obtainMessage(DISPATCH_GET_NEW_SURFACE);
- sendMessage(msg);
- }
-
- public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
- Message msg = Message.obtain();
- msg.what = WINDOW_FOCUS_CHANGED;
- msg.arg1 = hasFocus ? 1 : 0;
- msg.arg2 = inTouchMode ? 1 : 0;
- sendMessage(msg);
- }
-
- public boolean showContextMenuForChild(View originalView) {
- return false;
- }
-
- public void createContextMenu(ContextMenu menu) {
- }
-
- public void childDrawableStateChanged(View child) {
- }
-
- protected Rect getWindowFrame() {
- return mWinFrame;
- }
-
- void checkThread() {
- if (mThread != Thread.currentThread()) {
- throw new CalledFromWrongThreadException(
- "Only the original thread that created a view hierarchy can touch its views.");
- }
- }
-
- public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
- // ViewRoot never intercepts touch event, so this can be a no-op
- }
-
- public boolean requestChildRectangleOnScreen(View child, Rect rectangle,
- boolean immediate) {
- return scrollToRectOrFocus(rectangle, immediate);
- }
-
- static class InputMethodCallback extends IInputMethodCallback.Stub {
- private WeakReference<ViewRoot> mViewRoot;
-
- public InputMethodCallback(ViewRoot viewRoot) {
- mViewRoot = new WeakReference<ViewRoot>(viewRoot);
- }
-
- public void finishedEvent(int seq, boolean handled) {
- final ViewRoot viewRoot = mViewRoot.get();
- if (viewRoot != null) {
- viewRoot.dispatchFinishedEvent(seq, handled);
- }
- }
-
- public void sessionCreated(IInputMethodSession session) throws RemoteException {
- // Stub -- not for use in the client.
- }
- }
-
- static class W extends IWindow.Stub {
- private WeakReference<ViewRoot> mViewRoot;
-
- public W(ViewRoot viewRoot) {
- mViewRoot = new WeakReference<ViewRoot>(viewRoot);
- }
-
- public void resized(int w, int h, Rect coveredInsets,
- Rect visibleInsets, boolean reportDraw) {
- final ViewRoot viewRoot = mViewRoot.get();
- if (viewRoot != null) {
- viewRoot.dispatchResized(w, h, coveredInsets,
- visibleInsets, reportDraw);
- }
- }
-
- public void dispatchKey(KeyEvent event) {
- final ViewRoot viewRoot = mViewRoot.get();
- if (viewRoot != null) {
- viewRoot.dispatchKey(event);
- }
- }
-
- public void dispatchPointer(MotionEvent event, long eventTime) {
- final ViewRoot viewRoot = mViewRoot.get();
- if (viewRoot != null) {
- viewRoot.dispatchPointer(event, eventTime);
- }
- }
-
- public void dispatchTrackball(MotionEvent event, long eventTime) {
- final ViewRoot viewRoot = mViewRoot.get();
- if (viewRoot != null) {
- viewRoot.dispatchTrackball(event, eventTime);
- }
- }
-
- public void dispatchAppVisibility(boolean visible) {
- final ViewRoot viewRoot = mViewRoot.get();
- if (viewRoot != null) {
- viewRoot.dispatchAppVisibility(visible);
- }
- }
-
- public void dispatchGetNewSurface() {
- final ViewRoot viewRoot = mViewRoot.get();
- if (viewRoot != null) {
- viewRoot.dispatchGetNewSurface();
- }
- }
-
- public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
- final ViewRoot viewRoot = mViewRoot.get();
- if (viewRoot != null) {
- viewRoot.windowFocusChanged(hasFocus, inTouchMode);
- }
- }
-
- private static int checkCallingPermission(String permission) {
- if (!Process.supportsProcesses()) {
- return PackageManager.PERMISSION_GRANTED;
- }
-
- try {
- return ActivityManagerNative.getDefault().checkPermission(
- permission, Binder.getCallingPid(), Binder.getCallingUid());
- } catch (RemoteException e) {
- return PackageManager.PERMISSION_DENIED;
- }
- }
-
- public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
- final ViewRoot viewRoot = mViewRoot.get();
- if (viewRoot != null) {
- final View view = viewRoot.mView;
- if (view != null) {
- if (checkCallingPermission(Manifest.permission.DUMP) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Insufficient permissions to invoke"
- + " executeCommand() from pid=" + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- }
-
- OutputStream clientStream = null;
- try {
- clientStream = new ParcelFileDescriptor.AutoCloseOutputStream(out);
- ViewDebug.dispatchCommand(view, command, parameters, clientStream);
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (clientStream != null) {
- try {
- clientStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- }
- }
- }
-
- /**
- * Maintains state information for a single trackball axis, generating
- * discrete (DPAD) movements based on raw trackball motion.
- */
- static final class TrackballAxis {
- /**
- * The maximum amount of acceleration we will apply.
- */
- static final float MAX_ACCELERATION = 20;
-
- /**
- * The maximum amount of time (in milliseconds) between events in order
- * for us to consider the user to be doing fast trackball movements,
- * and thus apply an acceleration.
- */
- static final long FAST_MOVE_TIME = 150;
-
- /**
- * Scaling factor to the time (in milliseconds) between events to how
- * much to multiple/divide the current acceleration. When movement
- * is < FAST_MOVE_TIME this multiplies the acceleration; when >
- * FAST_MOVE_TIME it divides it.
- */
- static final float ACCEL_MOVE_SCALING_FACTOR = (1.0f/40);
-
- float position;
- float absPosition;
- float acceleration = 1;
- long lastMoveTime = 0;
- int step;
- int dir;
- int nonAccelMovement;
-
- void reset(int _step) {
- position = 0;
- acceleration = 1;
- lastMoveTime = 0;
- step = _step;
- dir = 0;
- }
-
- /**
- * Add trackball movement into the state. If the direction of movement
- * has been reversed, the state is reset before adding the
- * movement (so that you don't have to compensate for any previously
- * collected movement before see the result of the movement in the
- * new direction).
- *
- * @return Returns the absolute value of the amount of movement
- * collected so far.
- */
- float collect(float off, long time, String axis) {
- long normTime;
- if (off > 0) {
- normTime = (long)(off * FAST_MOVE_TIME);
- if (dir < 0) {
- if (DEBUG_TRACKBALL) Log.v(TAG, axis + " reversed to positive!");
- position = 0;
- step = 0;
- acceleration = 1;
- lastMoveTime = 0;
- }
- dir = 1;
- } else if (off < 0) {
- normTime = (long)((-off) * FAST_MOVE_TIME);
- if (dir > 0) {
- if (DEBUG_TRACKBALL) Log.v(TAG, axis + " reversed to negative!");
- position = 0;
- step = 0;
- acceleration = 1;
- lastMoveTime = 0;
- }
- dir = -1;
- } else {
- normTime = 0;
- }
-
- // The number of milliseconds between each movement that is
- // considered "normal" and will not result in any acceleration
- // or deceleration, scaled by the offset we have here.
- if (normTime > 0) {
- long delta = time - lastMoveTime;
- lastMoveTime = time;
- float acc = acceleration;
- if (delta < normTime) {
- // The user is scrolling rapidly, so increase acceleration.
- float scale = (normTime-delta) * ACCEL_MOVE_SCALING_FACTOR;
- if (scale > 1) acc *= scale;
- if (DEBUG_TRACKBALL) Log.v(TAG, axis + " accelerate: off="
- + off + " normTime=" + normTime + " delta=" + delta
- + " scale=" + scale + " acc=" + acc);
- acceleration = acc < MAX_ACCELERATION ? acc : MAX_ACCELERATION;
- } else {
- // The user is scrolling slowly, so decrease acceleration.
- float scale = (delta-normTime) * ACCEL_MOVE_SCALING_FACTOR;
- if (scale > 1) acc /= scale;
- if (DEBUG_TRACKBALL) Log.v(TAG, axis + " deccelerate: off="
- + off + " normTime=" + normTime + " delta=" + delta
- + " scale=" + scale + " acc=" + acc);
- acceleration = acc > 1 ? acc : 1;
- }
- }
- position += off;
- return (absPosition = Math.abs(position));
- }
-
- /**
- * Generate the number of discrete movement events appropriate for
- * the currently collected trackball movement.
- *
- * @param precision The minimum movement required to generate the
- * first discrete movement.
- *
- * @return Returns the number of discrete movements, either positive
- * or negative, or 0 if there is not enough trackball movement yet
- * for a discrete movement.
- */
- int generate(float precision) {
- int movement = 0;
- nonAccelMovement = 0;
- do {
- final int dir = position >= 0 ? 1 : -1;
- switch (step) {
- // If we are going to execute the first step, then we want
- // to do this as soon as possible instead of waiting for
- // a full movement, in order to make things look responsive.
- case 0:
- if (absPosition < precision) {
- return movement;
- }
- movement += dir;
- nonAccelMovement += dir;
- step = 1;
- break;
- // If we have generated the first movement, then we need
- // to wait for the second complete trackball motion before
- // generating the second discrete movement.
- case 1:
- if (absPosition < 2) {
- return movement;
- }
- movement += dir;
- nonAccelMovement += dir;
- position += dir > 0 ? -2 : 2;
- absPosition = Math.abs(position);
- step = 2;
- break;
- // After the first two, we generate discrete movements
- // consistently with the trackball, applying an acceleration
- // if the trackball is moving quickly. This is a simple
- // acceleration on top of what we already compute based
- // on how quickly the wheel is being turned, to apply
- // a longer increasing acceleration to continuous movement
- // in one direction.
- default:
- if (absPosition < 1) {
- return movement;
- }
- movement += dir;
- position += dir >= 0 ? -1 : 1;
- absPosition = Math.abs(position);
- float acc = acceleration;
- acc *= 1.1f;
- acceleration = acc < MAX_ACCELERATION ? acc : acceleration;
- break;
- }
- } while (true);
- }
- }
-
- public static final class CalledFromWrongThreadException extends AndroidRuntimeException {
- public CalledFromWrongThreadException(String msg) {
- super(msg);
- }
- }
-
- private SurfaceHolder mHolder = new SurfaceHolder() {
- // we only need a SurfaceHolder for opengl. it would be nice
- // to implement everything else though, especially the callback
- // support (opengl doesn't make use of it right now, but eventually
- // will).
- public Surface getSurface() {
- return mSurface;
- }
-
- public boolean isCreating() {
- return false;
- }
-
- public void addCallback(Callback callback) {
- }
-
- public void removeCallback(Callback callback) {
- }
-
- public void setFixedSize(int width, int height) {
- }
-
- public void setSizeFromLayout() {
- }
-
- public void setFormat(int format) {
- }
-
- public void setType(int type) {
- }
-
- public void setKeepScreenOn(boolean screenOn) {
- }
-
- public Canvas lockCanvas() {
- return null;
- }
-
- public Canvas lockCanvas(Rect dirty) {
- return null;
- }
-
- public void unlockCanvasAndPost(Canvas canvas) {
- }
- public Rect getSurfaceFrame() {
- return null;
- }
- };
-
- static RunQueue getRunQueue() {
- RunQueue rq = sRunQueues.get();
- if (rq != null) {
- return rq;
- }
- rq = new RunQueue();
- sRunQueues.set(rq);
- return rq;
- }
-
- /**
- * @hide
- */
- static final class RunQueue {
- private final ArrayList<HandlerAction> mActions = new ArrayList<HandlerAction>();
-
- void post(Runnable action) {
- postDelayed(action, 0);
- }
-
- void postDelayed(Runnable action, long delayMillis) {
- HandlerAction handlerAction = new HandlerAction();
- handlerAction.action = action;
- handlerAction.delay = delayMillis;
-
- synchronized (mActions) {
- mActions.add(handlerAction);
- }
- }
-
- void removeCallbacks(Runnable action) {
- final HandlerAction handlerAction = new HandlerAction();
- handlerAction.action = action;
-
- synchronized (mActions) {
- final ArrayList<HandlerAction> actions = mActions;
-
- while (actions.remove(handlerAction)) {
- // Keep going
- }
- }
- }
-
- void executeActions(Handler handler) {
- synchronized (mActions) {
- final ArrayList<HandlerAction> actions = mActions;
- final int count = actions.size();
-
- for (int i = 0; i < count; i++) {
- final HandlerAction handlerAction = actions.get(i);
- handler.postDelayed(handlerAction.action, handlerAction.delay);
- }
-
- mActions.clear();
- }
- }
-
- private static class HandlerAction {
- Runnable action;
- long delay;
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- HandlerAction that = (HandlerAction) o;
-
- return !(action != null ? !action.equals(that.action) : that.action != null);
-
- }
-
- @Override
- public int hashCode() {
- int result = action != null ? action.hashCode() : 0;
- result = 31 * result + (int) (delay ^ (delay >>> 32));
- return result;
- }
- }
- }
-
- private static native void nativeShowFPS(Canvas canvas, int durationMillis);
-
- // inform skia to just abandon its texture cache IDs
- // doesn't call glDeleteTextures
- private static native void nativeAbandonGlCaches();
-}
diff --git a/core/java/android/view/ViewStub.java b/core/java/android/view/ViewStub.java
deleted file mode 100644
index e159de4..0000000
--- a/core/java/android/view/ViewStub.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-
-import com.android.internal.R;
-
-/**
- * A ViewStub is an invisible, zero-sized View that can be used to lazily inflate
- * layout resources at runtime.
- *
- * When a ViewStub is made visible, or when {@link #inflate()} is invoked, the layout resource
- * is inflated. The ViewStub then replaces itself in its parent with the inflated View or Views.
- * Therefore, the ViewStub exists in the view hierarchy until {@link #setVisibility(int)} or
- * {@link #inflate()} is invoked.
- *
- * The inflated View is added to the ViewStub's parent with the ViewStub's layout
- * parameters. Similarly, you can define/override the inflate View's id by using the
- * ViewStub's inflatedId property. For instance:
- *
- * <pre>
- * &lt;ViewStub android:id="@+id/stub"
- * android:inflatedId="@+id/subTree"
- * android:layout="@layout/mySubTree"
- * android:layout_width="120dip"
- * android:layout_height="40dip" /&gt;
- * </pre>
- *
- * The ViewStub thus defined can be found using the id "stub." After inflation of
- * the layout resource "mySubTree," the ViewStub is removed from its parent. The
- * View created by inflating the layout resource "mySubTree" can be found using the
- * id "subTree," specified by the inflatedId property. The inflated View is finally
- * assigned a width of 120dip and a height of 40dip.
- *
- * The preferred way to perform the inflation of the layout resource is the following:
- *
- * <pre>
- * ViewStub stub = (ViewStub) findViewById(R.id.stub);
- * View inflated = stub.inflate();
- * </pre>
- *
- * When {@link #inflate()} is invoked, the ViewStub is replaced by the inflated View
- * and the inflated View is returned. This lets applications get a reference to the
- * inflated View without executing an extra findViewById().
- *
- * @attr ref android.R.styleable#ViewStub_inflatedId
- * @attr ref android.R.styleable#ViewStub_layout
- */
-public final class ViewStub extends View {
- private int mLayoutResource = 0;
- private int mInflatedId;
-
- private OnInflateListener mInflateListener;
-
- public ViewStub(Context context) {
- initialize(context);
- }
-
- /**
- * Creates a new ViewStub with the specified layout resource.
- *
- * @param context The application's environment.
- * @param layoutResource The reference to a layout resource that will be inflated.
- */
- public ViewStub(Context context, int layoutResource) {
- mLayoutResource = layoutResource;
- initialize(context);
- }
-
- public ViewStub(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- @SuppressWarnings({"UnusedDeclaration"})
- public ViewStub(Context context, AttributeSet attrs, int defStyle) {
- TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ViewStub,
- defStyle, 0);
-
- mInflatedId = a.getResourceId(R.styleable.ViewStub_inflatedId, NO_ID);
- mLayoutResource = a.getResourceId(R.styleable.ViewStub_layout, 0);
-
- a.recycle();
-
- a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View, defStyle, 0);
- mID = a.getResourceId(R.styleable.View_id, NO_ID);
- a.recycle();
-
- initialize(context);
- }
-
- private void initialize(Context context) {
- mContext = context;
- setVisibility(GONE);
- setWillNotDraw(true);
- }
-
- /**
- * Returns the id taken by the inflated view. If the inflated id is
- * {@link View#NO_ID}, the inflated view keeps its original id.
- *
- * @return A positive integer used to identify the inflated view or
- * {@link #NO_ID} if the inflated view should keep its id.
- *
- * @see #setInflatedId(int)
- * @attr ref android.R.styleable#ViewStub_inflatedId
- */
- public int getInflatedId() {
- return mInflatedId;
- }
-
- /**
- * Defines the id taken by the inflated view. If the inflated id is
- * {@link View#NO_ID}, the inflated view keeps its original id.
- *
- * @param inflatedId A positive integer used to identify the inflated view or
- * {@link #NO_ID} if the inflated view should keep its id.
- *
- * @see #getInflatedId()
- * @attr ref android.R.styleable#ViewStub_inflatedId
- */
- public void setInflatedId(int inflatedId) {
- mInflatedId = inflatedId;
- }
-
- /**
- * Returns the layout resource that will be used by {@link #setVisibility(int)} or
- * {@link #inflate()} to replace this StubbedView
- * in its parent by another view.
- *
- * @return The layout resource identifier used to inflate the new View.
- *
- * @see #setLayoutResource(int)
- * @see #setVisibility(int)
- * @see #inflate()
- * @attr ref android.R.styleable#ViewStub_layout
- */
- public int getLayoutResource() {
- return mLayoutResource;
- }
-
- /**
- * Specifies the layout resource to inflate when this StubbedView becomes visible or invisible
- * or when {@link #inflate()} is invoked. The View created by inflating the layout resource is
- * used to replace this StubbedView in its parent.
- *
- * @param layoutResource A valid layout resource identifier (different from 0.)
- *
- * @see #getLayoutResource()
- * @see #setVisibility(int)
- * @see #inflate()
- * @attr ref android.R.styleable#ViewStub_layout
- */
- public void setLayoutResource(int layoutResource) {
- mLayoutResource = layoutResource;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- setMeasuredDimension(0, 0);
- }
-
- @Override
- public void draw(Canvas canvas) {
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- }
-
- /**
- * When visibility is set to {@link #VISIBLE} or {@link #INVISIBLE},
- * {@link #inflate()} is invoked and this StubbedView is replaced in its parent
- * by the inflated layout resource.
- *
- * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
- *
- * @see #inflate()
- */
- @Override
- public void setVisibility(int visibility) {
- super.setVisibility(visibility);
-
- if (visibility == VISIBLE || visibility == INVISIBLE) {
- inflate();
- }
- }
-
- /**
- * Inflates the layout resource identified by {@link #getLayoutResource()}
- * and replaces this StubbedView in its parent by the inflated layout resource.
- *
- * @return The inflated layout resource.
- *
- */
- public View inflate() {
- final ViewParent viewParent = getParent();
-
- if (viewParent != null && viewParent instanceof ViewGroup) {
- if (mLayoutResource != 0) {
- final ViewGroup parent = (ViewGroup) viewParent;
- final LayoutInflater factory = LayoutInflater.from(mContext);
- final View view = factory.inflate(mLayoutResource, parent,
- false);
-
- if (mInflatedId != NO_ID) {
- view.setId(mInflatedId);
- }
-
- final int index = parent.indexOfChild(this);
- parent.removeViewInLayout(this);
-
- final ViewGroup.LayoutParams layoutParams = getLayoutParams();
- if (layoutParams != null) {
- parent.addView(view, index, layoutParams);
- } else {
- parent.addView(view, index);
- }
-
- if (mInflateListener != null) {
- mInflateListener.onInflate(this, view);
- }
-
- return view;
- } else {
- throw new IllegalArgumentException("ViewStub must have a valid layoutResource");
- }
- } else {
- throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent");
- }
- }
-
- /**
- * Specifies the inflate listener to be notified after this ViewStub successfully
- * inflated its layout resource.
- *
- * @param inflateListener The OnInflateListener to notify of successful inflation.
- *
- * @see android.view.ViewStub.OnInflateListener
- */
- public void setOnInflateListener(OnInflateListener inflateListener) {
- mInflateListener = inflateListener;
- }
-
- /**
- * Listener used to receive a notification after a ViewStub has successfully
- * inflated its layout resource.
- *
- * @see android.view.ViewStub#setOnInflateListener(android.view.ViewStub.OnInflateListener)
- */
- public static interface OnInflateListener {
- /**
- * Invoked after a ViewStub successfully inflated its layout resource.
- * This method is invoked after the inflated view was added to the
- * hierarchy but before the layout pass.
- *
- * @param stub The ViewStub that initiated the inflation.
- * @param inflated The inflated View.
- */
- void onInflate(ViewStub stub, View inflated);
- }
-}
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
deleted file mode 100644
index 47b52e4..0000000
--- a/core/java/android/view/ViewTreeObserver.java
+++ /dev/null
@@ -1,613 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.graphics.Rect;
-
-import java.util.ArrayList;
-
-/**
- * A view tree observer is used to register listeners that can be notified of global
- * changes in the view tree. Such global events include, but are not limited to,
- * layout of the whole tree, beginning of the drawing pass, touch mode change....
- *
- * A ViewTreeObserver should never be instantiated by applications as it is provided
- * by the views hierarchy. Refer to {@link android.view.View#getViewTreeObserver()}
- * for more information.
- */
-public final class ViewTreeObserver {
- private ArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners;
- private ArrayList<OnGlobalLayoutListener> mOnGlobalLayoutListeners;
- private ArrayList<OnPreDrawListener> mOnPreDrawListeners;
- private ArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners;
- private ArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
- private ArrayList<OnScrollChangedListener> mOnScrollChangedListeners;
-
- private boolean mAlive = true;
-
- /**
- * Interface definition for a callback to be invoked when the focus state within
- * the view tree changes.
- */
- public interface OnGlobalFocusChangeListener {
- /**
- * Callback method to be invoked when the focus changes in the view tree. When
- * the view tree transitions from touch mode to non-touch mode, oldFocus is null.
- * When the view tree transitions from non-touch mode to touch mode, newFocus is
- * null. When focus changes in non-touch mode (without transition from or to
- * touch mode) either oldFocus or newFocus can be null.
- *
- * @param oldFocus The previously focused view, if any.
- * @param newFocus The newly focused View, if any.
- */
- public void onGlobalFocusChanged(View oldFocus, View newFocus);
- }
-
- /**
- * Interface definition for a callback to be invoked when the global layout state
- * or the visibility of views within the view tree changes.
- */
- public interface OnGlobalLayoutListener {
- /**
- * Callback method to be invoked when the global layout state or the visibility of views
- * within the view tree changes
- */
- public void onGlobalLayout();
- }
-
- /**
- * Interface definition for a callback to be invoked when the view tree is about to be drawn.
- */
- public interface OnPreDrawListener {
- /**
- * Callback method to be invoked when the view tree is about to be drawn. At this point, all
- * views in the tree have been measured and given a frame. Clients can use this to adjust
- * their scroll bounds or even to request a new layout before drawing occurs.
- *
- * @return Return true to proceed with the current drawing pass, or false to cancel.
- *
- * @see android.view.View#onMeasure
- * @see android.view.View#onLayout
- * @see android.view.View#onDraw
- */
- public boolean onPreDraw();
- }
-
- /**
- * Interface definition for a callback to be invoked when the touch mode changes.
- */
- public interface OnTouchModeChangeListener {
- /**
- * Callback method to be invoked when the touch mode changes.
- *
- * @param isInTouchMode True if the view hierarchy is now in touch mode, false otherwise.
- */
- public void onTouchModeChanged(boolean isInTouchMode);
- }
-
- /**
- * Interface definition for a callback to be invoked when
- * something in the view tree has been scrolled.
- *
- * @hide pending API council approval
- */
- public interface OnScrollChangedListener {
- /**
- * Callback method to be invoked when something in the view tree
- * has been scrolled.
- */
- public void onScrollChanged();
- }
-
- /**
- * Parameters used with OnComputeInternalInsetsListener.
- * {@hide pending API Council approval}
- */
- public final static class InternalInsetsInfo {
- /**
- * Offsets from the frame of the window at which the content of
- * windows behind it should be placed.
- */
- public final Rect contentInsets = new Rect();
-
- /**
- * Offsets from the fram of the window at which windows behind it
- * are visible.
- */
- public final Rect visibleInsets = new Rect();
-
- /**
- * Option for {@link #setTouchableInsets(int)}: the entire window frame
- * can be touched.
- */
- public static final int TOUCHABLE_INSETS_FRAME = 0;
-
- /**
- * Option for {@link #setTouchableInsets(int)}: the area inside of
- * the content insets can be touched.
- */
- public static final int TOUCHABLE_INSETS_CONTENT = 1;
-
- /**
- * Option for {@link #setTouchableInsets(int)}: the area inside of
- * the visible insets can be touched.
- */
- public static final int TOUCHABLE_INSETS_VISIBLE = 2;
-
- /**
- * Set which parts of the window can be touched: either
- * {@link #TOUCHABLE_INSETS_FRAME}, {@link #TOUCHABLE_INSETS_CONTENT},
- * or {@link #TOUCHABLE_INSETS_VISIBLE}.
- */
- public void setTouchableInsets(int val) {
- mTouchableInsets = val;
- }
-
- public int getTouchableInsets() {
- return mTouchableInsets;
- }
-
- int mTouchableInsets;
-
- void reset() {
- final Rect givenContent = contentInsets;
- final Rect givenVisible = visibleInsets;
- givenContent.left = givenContent.top = givenContent.right
- = givenContent.bottom = givenVisible.left = givenVisible.top
- = givenVisible.right = givenVisible.bottom = 0;
- mTouchableInsets = TOUCHABLE_INSETS_FRAME;
- }
-
- @Override public boolean equals(Object o) {
- try {
- if (o == null) {
- return false;
- }
- InternalInsetsInfo other = (InternalInsetsInfo)o;
- if (!contentInsets.equals(other.contentInsets)) {
- return false;
- }
- if (!visibleInsets.equals(other.visibleInsets)) {
- return false;
- }
- return mTouchableInsets == other.mTouchableInsets;
- } catch (ClassCastException e) {
- return false;
- }
- }
-
- void set(InternalInsetsInfo other) {
- contentInsets.set(other.contentInsets);
- visibleInsets.set(other.visibleInsets);
- mTouchableInsets = other.mTouchableInsets;
- }
- }
-
- /**
- * Interface definition for a callback to be invoked when layout has
- * completed and the client can compute its interior insets.
- * {@hide pending API Council approval}
- */
- public interface OnComputeInternalInsetsListener {
- /**
- * Callback method to be invoked when layout has completed and the
- * client can compute its interior insets.
- *
- * @param inoutInfo Should be filled in by the implementation with
- * the information about the insets of the window. This is called
- * with whatever values the previous OnComputeInternalInsetsListener
- * returned, if there are multiple such listeners in the window.
- */
- public void onComputeInternalInsets(InternalInsetsInfo inoutInfo);
- }
-
- /**
- * Creates a new ViewTreeObserver. This constructor should not be called
- */
- ViewTreeObserver() {
- }
-
- /**
- * Merges all the listeners registered on the specified observer with the listeners
- * registered on this object. After this method is invoked, the specified observer
- * will return false in {@link #isAlive()} and should not be used anymore.
- *
- * @param observer The ViewTreeObserver whose listeners must be added to this observer
- */
- void merge(ViewTreeObserver observer) {
- if (observer.mOnGlobalFocusListeners != null) {
- if (mOnGlobalFocusListeners != null) {
- mOnGlobalFocusListeners.addAll(observer.mOnGlobalFocusListeners);
- } else {
- mOnGlobalFocusListeners = observer.mOnGlobalFocusListeners;
- }
- }
-
- if (observer.mOnGlobalLayoutListeners != null) {
- if (mOnGlobalLayoutListeners != null) {
- mOnGlobalLayoutListeners.addAll(observer.mOnGlobalLayoutListeners);
- } else {
- mOnGlobalLayoutListeners = observer.mOnGlobalLayoutListeners;
- }
- }
-
- if (observer.mOnPreDrawListeners != null) {
- if (mOnPreDrawListeners != null) {
- mOnPreDrawListeners.addAll(observer.mOnPreDrawListeners);
- } else {
- mOnPreDrawListeners = observer.mOnPreDrawListeners;
- }
- }
-
- if (observer.mOnTouchModeChangeListeners != null) {
- if (mOnTouchModeChangeListeners != null) {
- mOnTouchModeChangeListeners.addAll(observer.mOnTouchModeChangeListeners);
- } else {
- mOnTouchModeChangeListeners = observer.mOnTouchModeChangeListeners;
- }
- }
-
- if (observer.mOnComputeInternalInsetsListeners != null) {
- if (mOnComputeInternalInsetsListeners != null) {
- mOnComputeInternalInsetsListeners.addAll(observer.mOnComputeInternalInsetsListeners);
- } else {
- mOnComputeInternalInsetsListeners = observer.mOnComputeInternalInsetsListeners;
- }
- }
-
- observer.kill();
- }
-
- /**
- * Register a callback to be invoked when the focus state within the view tree changes.
- *
- * @param listener The callback to add
- *
- * @throws IllegalStateException If {@link #isAlive()} returns false
- */
- public void addOnGlobalFocusChangeListener(OnGlobalFocusChangeListener listener) {
- checkIsAlive();
-
- if (mOnGlobalFocusListeners == null) {
- mOnGlobalFocusListeners = new ArrayList<OnGlobalFocusChangeListener>();
- }
-
- mOnGlobalFocusListeners.add(listener);
- }
-
- /**
- * Remove a previously installed focus change callback.
- *
- * @param victim The callback to remove
- *
- * @throws IllegalStateException If {@link #isAlive()} returns false
- *
- * @see #addOnGlobalFocusChangeListener(OnGlobalFocusChangeListener)
- */
- public void removeOnGlobalFocusChangeListener(OnGlobalFocusChangeListener victim) {
- checkIsAlive();
- if (mOnGlobalFocusListeners == null) {
- return;
- }
- mOnGlobalFocusListeners.remove(victim);
- }
-
- /**
- * Register a callback to be invoked when the global layout state or the visibility of views
- * within the view tree changes
- *
- * @param listener The callback to add
- *
- * @throws IllegalStateException If {@link #isAlive()} returns false
- */
- public void addOnGlobalLayoutListener(OnGlobalLayoutListener listener) {
- checkIsAlive();
-
- if (mOnGlobalLayoutListeners == null) {
- mOnGlobalLayoutListeners = new ArrayList<OnGlobalLayoutListener>();
- }
-
- mOnGlobalLayoutListeners.add(listener);
- }
-
- /**
- * Remove a previously installed global layout callback
- *
- * @param victim The callback to remove
- *
- * @throws IllegalStateException If {@link #isAlive()} returns false
- *
- * @see #addOnGlobalLayoutListener(OnGlobalLayoutListener)
- */
- public void removeGlobalOnLayoutListener(OnGlobalLayoutListener victim) {
- checkIsAlive();
- if (mOnGlobalLayoutListeners == null) {
- return;
- }
- mOnGlobalLayoutListeners.remove(victim);
- }
-
- /**
- * Register a callback to be invoked when the view tree is about to be drawn
- *
- * @param listener The callback to add
- *
- * @throws IllegalStateException If {@link #isAlive()} returns false
- */
- public void addOnPreDrawListener(OnPreDrawListener listener) {
- checkIsAlive();
-
- if (mOnPreDrawListeners == null) {
- mOnPreDrawListeners = new ArrayList<OnPreDrawListener>();
- }
-
- mOnPreDrawListeners.add(listener);
- }
-
- /**
- * Remove a previously installed pre-draw callback
- *
- * @param victim The callback to remove
- *
- * @throws IllegalStateException If {@link #isAlive()} returns false
- *
- * @see #addOnPreDrawListener(OnPreDrawListener)
- */
- public void removeOnPreDrawListener(OnPreDrawListener victim) {
- checkIsAlive();
- if (mOnPreDrawListeners == null) {
- return;
- }
- mOnPreDrawListeners.remove(victim);
- }
-
- /**
- * Register a callback to be invoked when a view has been scrolled.
- *
- * @param listener The callback to add
- *
- * @throws IllegalStateException If {@link #isAlive()} returns false
- *
- * @hide pending API council approval
- */
- public void addOnScrollChangedListener(OnScrollChangedListener listener) {
- checkIsAlive();
-
- if (mOnScrollChangedListeners == null) {
- mOnScrollChangedListeners = new ArrayList<OnScrollChangedListener>();
- }
-
- mOnScrollChangedListeners.add(listener);
- }
-
- /**
- * Remove a previously installed scroll-changed callback
- *
- * @param victim The callback to remove
- *
- * @throws IllegalStateException If {@link #isAlive()} returns false
- *
- * @see #addOnScrollChangedListener(OnScrollChangedListener)
- *
- * @hide pending API council approval
- */
- public void removeOnScrollChangedListener(OnScrollChangedListener victim) {
- checkIsAlive();
- if (mOnScrollChangedListeners == null) {
- return;
- }
- mOnScrollChangedListeners.remove(victim);
- }
-
- /**
- * Register a callback to be invoked when the invoked when the touch mode changes.
- *
- * @param listener The callback to add
- *
- * @throws IllegalStateException If {@link #isAlive()} returns false
- */
- public void addOnTouchModeChangeListener(OnTouchModeChangeListener listener) {
- checkIsAlive();
-
- if (mOnTouchModeChangeListeners == null) {
- mOnTouchModeChangeListeners = new ArrayList<OnTouchModeChangeListener>();
- }
-
- mOnTouchModeChangeListeners.add(listener);
- }
-
- /**
- * Remove a previously installed touch mode change callback
- *
- * @param victim The callback to remove
- *
- * @throws IllegalStateException If {@link #isAlive()} returns false
- *
- * @see #addOnTouchModeChangeListener(OnTouchModeChangeListener)
- */
- public void removeOnTouchModeChangeListener(OnTouchModeChangeListener victim) {
- checkIsAlive();
- if (mOnTouchModeChangeListeners == null) {
- return;
- }
- mOnTouchModeChangeListeners.remove(victim);
- }
-
- /**
- * Register a callback to be invoked when the invoked when it is time to
- * compute the window's internal insets.
- *
- * @param listener The callback to add
- *
- * @throws IllegalStateException If {@link #isAlive()} returns false
- * {@hide pending API Council approval}
- */
- public void addOnComputeInternalInsetsListener(OnComputeInternalInsetsListener listener) {
- checkIsAlive();
-
- if (mOnComputeInternalInsetsListeners == null) {
- mOnComputeInternalInsetsListeners = new ArrayList<OnComputeInternalInsetsListener>();
- }
-
- mOnComputeInternalInsetsListeners.add(listener);
- }
-
- /**
- * Remove a previously installed internal insets computation callback
- *
- * @param victim The callback to remove
- *
- * @throws IllegalStateException If {@link #isAlive()} returns false
- *
- * @see #addOnComputeInternalInsetsListener(OnComputeInternalInsetsListener)
- * {@hide pending API Council approval}
- */
- public void removeOnComputeInternalInsetsListener(OnComputeInternalInsetsListener victim) {
- checkIsAlive();
- if (mOnComputeInternalInsetsListeners == null) {
- return;
- }
- mOnComputeInternalInsetsListeners.remove(victim);
- }
-
- private void checkIsAlive() {
- if (!mAlive) {
- throw new IllegalStateException("This ViewTreeObserver is not alive, call "
- + "getViewTreeObserver() again");
- }
- }
-
- /**
- * Indicates whether this ViewTreeObserver is alive. When an observer is not alive,
- * any call to a method (except this one) will throw an exception.
- *
- * If an application keeps a long-lived reference to this ViewTreeObserver, it should
- * always check for the result of this method before calling any other method.
- *
- * @return True if this object is alive and be used, false otherwise.
- */
- public boolean isAlive() {
- return mAlive;
- }
-
- /**
- * Marks this ViewTreeObserver as not alive. After invoking this method, invoking
- * any other method but {@link #isAlive()} and {@link #kill()} will throw an Exception.
- *
- * @hide
- */
- private void kill() {
- mAlive = false;
- }
-
- /**
- * Notifies registered listeners that focus has changed.
- */
- final void dispatchOnGlobalFocusChange(View oldFocus, View newFocus) {
- final ArrayList<OnGlobalFocusChangeListener> globaFocusListeners = mOnGlobalFocusListeners;
- if (globaFocusListeners != null) {
- final int count = globaFocusListeners.size();
- for (int i = count - 1; i >= 0; i--) {
- globaFocusListeners.get(i).onGlobalFocusChanged(oldFocus, newFocus);
- }
- }
- }
-
- /**
- * Notifies registered listeners that a global layout happened. This can be called
- * manually if you are forcing a layout on a View or a hierarchy of Views that are
- * not attached to a Window or in the GONE state.
- */
- public final void dispatchOnGlobalLayout() {
- final ArrayList<OnGlobalLayoutListener> globaLayoutListeners = mOnGlobalLayoutListeners;
- if (globaLayoutListeners != null) {
- final int count = globaLayoutListeners.size();
- for (int i = count - 1; i >= 0; i--) {
- globaLayoutListeners.get(i).onGlobalLayout();
- }
- }
- }
-
- /**
- * Notifies registered listeners that the drawing pass is about to start. If a
- * listener returns true, then the drawing pass is canceled and rescheduled. This can
- * be called manually if you are forcing the drawing on a View or a hierarchy of Views
- * that are not attached to a Window or in the GONE state.
- *
- * @return True if the current draw should be canceled and resceduled, false otherwise.
- */
- public final boolean dispatchOnPreDraw() {
- boolean cancelDraw = false;
- final ArrayList<OnPreDrawListener> preDrawListeners = mOnPreDrawListeners;
- if (preDrawListeners != null) {
- final int count = preDrawListeners.size();
- for (int i = count - 1; i >= 0; i--) {
- cancelDraw |= !preDrawListeners.get(i).onPreDraw();
- }
- }
- return cancelDraw;
- }
-
- /**
- * Notifies registered listeners that the touch mode has changed.
- *
- * @param inTouchMode True if the touch mode is now enabled, false otherwise.
- */
- final void dispatchOnTouchModeChanged(boolean inTouchMode) {
- final ArrayList<OnTouchModeChangeListener> touchModeListeners = mOnTouchModeChangeListeners;
- if (touchModeListeners != null) {
- final int count = touchModeListeners.size();
- for (int i = count - 1; i >= 0; i--) {
- touchModeListeners.get(i).onTouchModeChanged(inTouchMode);
- }
- }
- }
-
- /**
- * Notifies registered listeners that something has scrolled.
- */
- final void dispatchOnScrollChanged() {
- final ArrayList<OnScrollChangedListener> listeners = mOnScrollChangedListeners;
-
- if (listeners != null) {
- for (OnScrollChangedListener scl : mOnScrollChangedListeners) {
- scl.onScrollChanged();
- }
- }
- }
-
- /**
- * Returns whether there are listeners for computing internal insets.
- */
- final boolean hasComputeInternalInsetsListeners() {
- final ArrayList<OnComputeInternalInsetsListener> listeners = mOnComputeInternalInsetsListeners;
- return (listeners != null && listeners.size() > 0);
- }
-
- /**
- * Calls all listeners to compute the current insets.
- */
- final void dispatchOnComputeInternalInsets(InternalInsetsInfo inoutInfo) {
- final ArrayList<OnComputeInternalInsetsListener> listeners = mOnComputeInternalInsetsListeners;
- if (listeners != null) {
- final int count = listeners.size();
- for (int i = count - 1; i >= 0; i--) {
- listeners.get(i).onComputeInternalInsets(inoutInfo);
- }
- }
- }
-}
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
deleted file mode 100644
index a573983..0000000
--- a/core/java/android/view/VolumePanel.java
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.bluetooth.HeadsetBase;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.media.AudioManager;
-import android.media.AudioService;
-import android.media.AudioSystem;
-import android.media.ToneGenerator;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Vibrator;
-import android.util.Config;
-import android.util.Log;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-import android.widget.Toast;
-
-/**
- * Handle the volume up and down keys.
- *
- * This code really should be moved elsewhere.
- *
- * @hide
- */
-public class VolumePanel extends Handler
-{
- private static final String TAG = "VolumePanel";
- private static boolean LOGD = false || Config.LOGD;
-
- /**
- * The delay before playing a sound. This small period exists so the user
- * can press another key (non-volume keys, too) to have it NOT be audible.
- * <p>
- * PhoneWindow will implement this part.
- */
- public static final int PLAY_SOUND_DELAY = 300;
-
- /**
- * The delay before vibrating. This small period exists so if the user is
- * moving to silent mode, it will not emit a short vibrate (it normally
- * would since vibrate is between normal mode and silent mode using hardware
- * keys).
- */
- public static final int VIBRATE_DELAY = 300;
-
- private static final int VIBRATE_DURATION = 300;
- private static final int BEEP_DURATION = 150;
- private static final int MAX_VOLUME = 100;
- private static final int FREE_DELAY = 10000;
-
- private static final int MSG_VOLUME_CHANGED = 0;
- private static final int MSG_FREE_RESOURCES = 1;
- private static final int MSG_PLAY_SOUND = 2;
- private static final int MSG_STOP_SOUNDS = 3;
- private static final int MSG_VIBRATE = 4;
-
- private static final int RINGTONE_VOLUME_TEXT = com.android.internal.R.string.volume_ringtone;
- private static final int MUSIC_VOLUME_TEXT = com.android.internal.R.string.volume_music;
- private static final int INCALL_VOLUME_TEXT = com.android.internal.R.string.volume_call;
- private static final int ALARM_VOLUME_TEXT = com.android.internal.R.string.volume_alarm;
- private static final int UNKNOWN_VOLUME_TEXT = com.android.internal.R.string.volume_unknown;
- private static final int NOTIFICATION_VOLUME_TEXT =
- com.android.internal.R.string.volume_notification;
- private static final int BLUETOOTH_INCALL_VOLUME_TEXT =
- com.android.internal.R.string.volume_bluetooth_call;
-
- protected Context mContext;
- private AudioManager mAudioManager;
- protected AudioService mAudioService;
-
- private final Toast mToast;
- private final View mView;
- private final TextView mMessage;
- private final TextView mAdditionalMessage;
- private final ImageView mSmallStreamIcon;
- private final ImageView mLargeStreamIcon;
- private final ProgressBar mLevel;
-
- // Synchronize when accessing this
- private ToneGenerator mToneGenerators[];
- private Vibrator mVibrator;
-
- public VolumePanel(Context context, AudioService volumeService) {
- mContext = context;
- mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- mAudioService = volumeService;
- mToast = new Toast(context);
-
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = mView = inflater.inflate(com.android.internal.R.layout.volume_adjust, null);
- mMessage = (TextView) view.findViewById(com.android.internal.R.id.message);
- mAdditionalMessage =
- (TextView) view.findViewById(com.android.internal.R.id.additional_message);
- mSmallStreamIcon = (ImageView) view.findViewById(com.android.internal.R.id.other_stream_icon);
- mLargeStreamIcon = (ImageView) view.findViewById(com.android.internal.R.id.ringer_stream_icon);
- mLevel = (ProgressBar) view.findViewById(com.android.internal.R.id.level);
-
- mToneGenerators = new ToneGenerator[AudioSystem.getNumStreamTypes()];
- mVibrator = new Vibrator();
- }
-
- public void postVolumeChanged(int streamType, int flags) {
- if (hasMessages(MSG_VOLUME_CHANGED)) return;
- removeMessages(MSG_FREE_RESOURCES);
- obtainMessage(MSG_VOLUME_CHANGED, streamType, flags).sendToTarget();
- }
-
- /**
- * Override this if you have other work to do when the volume changes (for
- * example, vibrating, playing a sound, etc.). Make sure to call through to
- * the superclass implementation.
- */
- protected void onVolumeChanged(int streamType, int flags) {
-
- if (LOGD) Log.d(TAG, "onVolumeChanged(streamType: " + streamType + ", flags: " + flags + ")");
-
- if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {
- onShowVolumeChanged(streamType, flags);
- }
-
- if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0) {
- removeMessages(MSG_PLAY_SOUND);
- sendMessageDelayed(obtainMessage(MSG_PLAY_SOUND, streamType, flags), PLAY_SOUND_DELAY);
- }
-
- if ((flags & AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE) != 0) {
- removeMessages(MSG_PLAY_SOUND);
- removeMessages(MSG_VIBRATE);
- onStopSounds();
- }
-
- removeMessages(MSG_FREE_RESOURCES);
- sendMessageDelayed(obtainMessage(MSG_FREE_RESOURCES), FREE_DELAY);
- }
-
- protected void onShowVolumeChanged(int streamType, int flags) {
- int index = mAudioService.getStreamVolume(streamType);
- int message = UNKNOWN_VOLUME_TEXT;
- int additionalMessage = 0;
-
- if (LOGD) {
- Log.d(TAG, "onShowVolumeChanged(streamType: " + streamType
- + ", flags: " + flags + "), index: " + index);
- }
-
- // get max volume for progress bar
- int max = mAudioService.getStreamMaxVolume(streamType);
-
- switch (streamType) {
-
- case AudioManager.STREAM_RING: {
- message = RINGTONE_VOLUME_TEXT;
- setRingerIcon(index);
- break;
- }
-
- case AudioManager.STREAM_MUSIC: {
- message = MUSIC_VOLUME_TEXT;
- if (mAudioManager.isBluetoothA2dpOn()) {
- additionalMessage =
- com.android.internal.R.string.volume_music_hint_playing_through_bluetooth;
- setLargeIcon(com.android.internal.R.drawable.ic_volume_bluetooth_ad2p);
- } else {
- setSmallIcon(index);
- }
- break;
- }
-
- case AudioManager.STREAM_VOICE_CALL: {
- /*
- * For in-call voice call volume, there is no inaudible volume.
- * Rescale the UI control so the progress bar doesn't go all
- * the way to zero and don't show the mute icon.
- */
- index++;
- max++;
- message = INCALL_VOLUME_TEXT;
- setSmallIcon(index);
- break;
- }
-
- case AudioManager.STREAM_ALARM: {
- message = ALARM_VOLUME_TEXT;
- setSmallIcon(index);
- break;
- }
-
- case AudioManager.STREAM_NOTIFICATION: {
- message = NOTIFICATION_VOLUME_TEXT;
- setSmallIcon(index);
- break;
- }
-
- case AudioManager.STREAM_BLUETOOTH_SCO: {
- /*
- * For in-call voice call volume, there is no inaudible volume.
- * Rescale the UI control so the progress bar doesn't go all
- * the way to zero and don't show the mute icon.
- */
- index++;
- max++;
- message = BLUETOOTH_INCALL_VOLUME_TEXT;
- setLargeIcon(com.android.internal.R.drawable.ic_volume_bluetooth_in_call);
- break;
- }
- }
-
- String messageString = Resources.getSystem().getString(message);
- if (!mMessage.getText().equals(messageString)) {
- mMessage.setText(messageString);
- }
-
- if (additionalMessage == 0) {
- mAdditionalMessage.setVisibility(View.GONE);
- } else {
- mAdditionalMessage.setVisibility(View.VISIBLE);
- mAdditionalMessage.setText(Resources.getSystem().getString(additionalMessage));
- }
-
- if (max != mLevel.getMax()) {
- mLevel.setMax(max);
- }
- mLevel.setProgress(index);
-
- mToast.setView(mView);
- mToast.setDuration(Toast.LENGTH_SHORT);
- mToast.setGravity(Gravity.TOP, 0, 0);
- mToast.show();
-
- // Do a little vibrate if applicable (only when going into vibrate mode)
- if ((flags & AudioManager.FLAG_VIBRATE) != 0 &&
- mAudioService.isStreamAffectedByRingerMode(streamType) &&
- mAudioService.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE &&
- mAudioService.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)) {
- sendMessageDelayed(obtainMessage(MSG_VIBRATE), VIBRATE_DELAY);
- }
-
- }
-
- protected void onPlaySound(int streamType, int flags) {
-
- if (hasMessages(MSG_STOP_SOUNDS)) {
- removeMessages(MSG_STOP_SOUNDS);
- // Force stop right now
- onStopSounds();
- }
-
- synchronized (this) {
- ToneGenerator toneGen = getOrCreateToneGenerator(streamType);
- toneGen.startTone(ToneGenerator.TONE_PROP_BEEP);
- }
-
- sendMessageDelayed(obtainMessage(MSG_STOP_SOUNDS), BEEP_DURATION);
- }
-
- protected void onStopSounds() {
-
- synchronized (this) {
- int numStreamTypes = AudioSystem.getNumStreamTypes();
- for (int i = numStreamTypes - 1; i >= 0; i--) {
- ToneGenerator toneGen = mToneGenerators[i];
- if (toneGen != null) {
- toneGen.stopTone();
- }
- }
- }
- }
-
- protected void onVibrate() {
-
- // Make sure we ended up in vibrate ringer mode
- if (mAudioService.getRingerMode() != AudioManager.RINGER_MODE_VIBRATE) {
- return;
- }
-
- mVibrator.vibrate(VIBRATE_DURATION);
- }
-
- /**
- * Lock on this VolumePanel instance as long as you use the returned ToneGenerator.
- */
- private ToneGenerator getOrCreateToneGenerator(int streamType) {
- synchronized (this) {
- if (mToneGenerators[streamType] == null) {
- return mToneGenerators[streamType] = new ToneGenerator(streamType, MAX_VOLUME);
- } else {
- return mToneGenerators[streamType];
- }
- }
- }
-
- /**
- * Makes the small icon visible, and hides the large icon.
- *
- * @param index The volume index, where 0 means muted.
- */
- private void setSmallIcon(int index) {
- mLargeStreamIcon.setVisibility(View.GONE);
- mSmallStreamIcon.setVisibility(View.VISIBLE);
-
- mSmallStreamIcon.setImageResource(index == 0
- ? com.android.internal.R.drawable.ic_volume_off_small
- : com.android.internal.R.drawable.ic_volume_small);
- }
-
- /**
- * Makes the large image view visible with the given icon.
- *
- * @param resId The icon to display.
- */
- private void setLargeIcon(int resId) {
- mSmallStreamIcon.setVisibility(View.GONE);
- mLargeStreamIcon.setVisibility(View.VISIBLE);
- mLargeStreamIcon.setImageResource(resId);
- }
-
- /**
- * Makes the ringer icon visible with an icon that is chosen
- * based on the current ringer mode.
- *
- * @param index
- */
- private void setRingerIcon(int index) {
- mSmallStreamIcon.setVisibility(View.GONE);
- mLargeStreamIcon.setVisibility(View.VISIBLE);
-
- int ringerMode = mAudioService.getRingerMode();
- int icon;
-
- if (LOGD) Log.d(TAG, "setRingerIcon(index: " + index+ "), ringerMode: " + ringerMode);
-
- if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
- icon = com.android.internal.R.drawable.ic_volume_off;
- } else if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
- icon = com.android.internal.R.drawable.ic_vibrate;
- } else {
- icon = com.android.internal.R.drawable.ic_volume;
- }
- mLargeStreamIcon.setImageResource(icon);
- }
-
- protected void onFreeResources() {
- // We'll keep the views, just ditch the cached drawable and hence
- // bitmaps
- mSmallStreamIcon.setImageDrawable(null);
- mLargeStreamIcon.setImageDrawable(null);
-
- synchronized (this) {
- for (int i = mToneGenerators.length - 1; i >= 0; i--) {
- if (mToneGenerators[i] != null) {
- mToneGenerators[i].release();
- }
- mToneGenerators[i] = null;
- }
- }
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
-
- case MSG_VOLUME_CHANGED: {
- onVolumeChanged(msg.arg1, msg.arg2);
- break;
- }
-
- case MSG_FREE_RESOURCES: {
- onFreeResources();
- break;
- }
-
- case MSG_STOP_SOUNDS: {
- onStopSounds();
- break;
- }
-
- case MSG_PLAY_SOUND: {
- onPlaySound(msg.arg1, msg.arg2);
- break;
- }
-
- case MSG_VIBRATE: {
- onVibrate();
- break;
- }
-
- }
- }
-
-}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
deleted file mode 100644
index 428de67..0000000
--- a/core/java/android/view/Window.java
+++ /dev/null
@@ -1,1005 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.TypedArray;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.util.Log;
-
-/**
- * Abstract base class for a top-level window look and behavior policy. An
- * instance of this class should be used as the top-level view added to the
- * window manager. It provides standard UI policies such as a background, title
- * area, default key processing, etc.
- *
- * <p>The only existing implementation of this abstract class is
- * android.policy.PhoneWindow, which you should instantiate when needing a
- * Window. Eventually that class will be refactored and a factory method
- * added for creating Window instances without knowing about a particular
- * implementation.
- */
-public abstract class Window {
- /** Flag for the "options panel" feature. This is enabled by default. */
- public static final int FEATURE_OPTIONS_PANEL = 0;
- /** Flag for the "no title" feature, turning off the title at the top
- * of the screen. */
- public static final int FEATURE_NO_TITLE = 1;
- /** Flag for the progress indicator feature */
- public static final int FEATURE_PROGRESS = 2;
- /** Flag for having an icon on the left side of the title bar */
- public static final int FEATURE_LEFT_ICON = 3;
- /** Flag for having an icon on the right side of the title bar */
- public static final int FEATURE_RIGHT_ICON = 4;
- /** Flag for indeterminate progress */
- public static final int FEATURE_INDETERMINATE_PROGRESS = 5;
- /** Flag for the context menu. This is enabled by default. */
- public static final int FEATURE_CONTEXT_MENU = 6;
- /** Flag for custom title. You cannot combine this feature with other title features. */
- public static final int FEATURE_CUSTOM_TITLE = 7;
- /* Flag for asking for an OpenGL enabled window.
- All 2D graphics will be handled by OpenGL ES.
- Private for now, until it is better tested (not shipping in 1.0)
- */
- private static final int FEATURE_OPENGL = 8;
- /** Flag for setting the progress bar's visibility to VISIBLE */
- public static final int PROGRESS_VISIBILITY_ON = -1;
- /** Flag for setting the progress bar's visibility to GONE */
- public static final int PROGRESS_VISIBILITY_OFF = -2;
- /** Flag for setting the progress bar's indeterminate mode on */
- public static final int PROGRESS_INDETERMINATE_ON = -3;
- /** Flag for setting the progress bar's indeterminate mode off */
- public static final int PROGRESS_INDETERMINATE_OFF = -4;
- /** Starting value for the (primary) progress */
- public static final int PROGRESS_START = 0;
- /** Ending value for the (primary) progress */
- public static final int PROGRESS_END = 10000;
- /** Lowest possible value for the secondary progress */
- public static final int PROGRESS_SECONDARY_START = 20000;
- /** Highest possible value for the secondary progress */
- public static final int PROGRESS_SECONDARY_END = 30000;
-
- /** The default features enabled */
- @SuppressWarnings({"PointlessBitwiseExpression"})
- protected static final int DEFAULT_FEATURES = (1 << FEATURE_OPTIONS_PANEL) |
- (1 << FEATURE_CONTEXT_MENU);
-
- /**
- * The ID that the main layout in the XML layout file should have.
- */
- public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content;
-
- private final Context mContext;
-
- private TypedArray mWindowStyle;
- private Callback mCallback;
- private WindowManager mWindowManager;
- private IBinder mAppToken;
- private String mAppName;
- private Window mContainer;
- private Window mActiveChild;
- private boolean mIsActive = false;
- private boolean mHasChildren = false;
- private int mForcedWindowFlags = 0;
-
- private int mFeatures = DEFAULT_FEATURES;
- private int mLocalFeatures = DEFAULT_FEATURES;
-
- private boolean mHaveWindowFormat = false;
- private int mDefaultWindowFormat = PixelFormat.OPAQUE;
-
- private boolean mHasSoftInputMode = false;
-
- // The current window attributes.
- private final WindowManager.LayoutParams mWindowAttributes =
- new WindowManager.LayoutParams();
-
- /**
- * API from a Window back to its caller. This allows the client to
- * intercept key dispatching, panels and menus, etc.
- */
- public interface Callback {
- /**
- * Called to process key events. At the very least your
- * implementation must call
- * {@link android.view.Window#superDispatchKeyEvent} to do the
- * standard key processing.
- *
- * @param event The key event.
- *
- * @return boolean Return true if this event was consumed.
- */
- public boolean dispatchKeyEvent(KeyEvent event);
-
- /**
- * Called to process touch screen events. At the very least your
- * implementation must call
- * {@link android.view.Window#superDispatchTouchEvent} to do the
- * standard touch screen processing.
- *
- * @param event The touch screen event.
- *
- * @return boolean Return true if this event was consumed.
- */
- public boolean dispatchTouchEvent(MotionEvent event);
-
- /**
- * Called to process trackball events. At the very least your
- * implementation must call
- * {@link android.view.Window#superDispatchTrackballEvent} to do the
- * standard trackball processing.
- *
- * @param event The trackball event.
- *
- * @return boolean Return true if this event was consumed.
- */
- public boolean dispatchTrackballEvent(MotionEvent event);
-
- /**
- * Instantiate the view to display in the panel for 'featureId'.
- * You can return null, in which case the default content (typically
- * a menu) will be created for you.
- *
- * @param featureId Which panel is being created.
- *
- * @return view The top-level view to place in the panel.
- *
- * @see #onPreparePanel
- */
- public View onCreatePanelView(int featureId);
-
- /**
- * Initialize the contents of the menu for panel 'featureId'. This is
- * called if onCreatePanelView() returns null, giving you a standard
- * menu in which you can place your items. It is only called once for
- * the panel, the first time it is shown.
- *
- * <p>You can safely hold on to <var>menu</var> (and any items created
- * from it), making modifications to it as desired, until the next
- * time onCreatePanelMenu() is called for this feature.
- *
- * @param featureId The panel being created.
- * @param menu The menu inside the panel.
- *
- * @return boolean You must return true for the panel to be displayed;
- * if you return false it will not be shown.
- */
- public boolean onCreatePanelMenu(int featureId, Menu menu);
-
- /**
- * Prepare a panel to be displayed. This is called right before the
- * panel window is shown, every time it is shown.
- *
- * @param featureId The panel that is being displayed.
- * @param view The View that was returned by onCreatePanelView().
- * @param menu If onCreatePanelView() returned null, this is the Menu
- * being displayed in the panel.
- *
- * @return boolean You must return true for the panel to be displayed;
- * if you return false it will not be shown.
- *
- * @see #onCreatePanelView
- */
- public boolean onPreparePanel(int featureId, View view, Menu menu);
-
- /**
- * Called when a panel's menu is opened by the user. This may also be
- * called when the menu is changing from one type to another (for
- * example, from the icon menu to the expanded menu).
- *
- * @param featureId The panel that the menu is in.
- * @param menu The menu that is opened.
- * @return Return true to allow the menu to open, or false to prevent
- * the menu from opening.
- */
- public boolean onMenuOpened(int featureId, Menu menu);
-
- /**
- * Called when a panel's menu item has been selected by the user.
- *
- * @param featureId The panel that the menu is in.
- * @param item The menu item that was selected.
- *
- * @return boolean Return true to finish processing of selection, or
- * false to perform the normal menu handling (calling its
- * Runnable or sending a Message to its target Handler).
- */
- public boolean onMenuItemSelected(int featureId, MenuItem item);
-
- /**
- * This is called whenever the current window attributes change.
- *
-
- */
- public void onWindowAttributesChanged(WindowManager.LayoutParams attrs);
-
- /**
- * This hook is called whenever the content view of the screen changes
- * (due to a call to
- * {@link Window#setContentView(View, android.view.ViewGroup.LayoutParams)
- * Window.setContentView} or
- * {@link Window#addContentView(View, android.view.ViewGroup.LayoutParams)
- * Window.addContentView}).
- */
- public void onContentChanged();
-
- /**
- * This hook is called whenever the window focus changes.
- *
- * @param hasFocus Whether the window now has focus.
- */
- public void onWindowFocusChanged(boolean hasFocus);
-
- /**
- * Called when a panel is being closed. If another logical subsequent
- * panel is being opened (and this panel is being closed to make room for the subsequent
- * panel), this method will NOT be called.
- *
- * @param featureId The panel that is being displayed.
- * @param menu If onCreatePanelView() returned null, this is the Menu
- * being displayed in the panel.
- */
- public void onPanelClosed(int featureId, Menu menu);
-
- /**
- * Called when the user signals the desire to start a search.
- *
- * @return true if search launched, false if activity refuses (blocks)
- *
- * @see android.app.Activity#onSearchRequested()
- */
- public boolean onSearchRequested();
- }
-
- public Window(Context context) {
- mContext = context;
- }
-
- /**
- * Return the Context this window policy is running in, for retrieving
- * resources and other information.
- *
- * @return Context The Context that was supplied to the constructor.
- */
- public final Context getContext() {
- return mContext;
- }
-
- /**
- * Return the {@link android.R.styleable#Window} attributes from this
- * window's theme.
- */
- public final TypedArray getWindowStyle() {
- synchronized (this) {
- if (mWindowStyle == null) {
- mWindowStyle = mContext.obtainStyledAttributes(
- com.android.internal.R.styleable.Window);
- }
- return mWindowStyle;
- }
- }
-
- /**
- * Set the container for this window. If not set, the DecorWindow
- * operates as a top-level window; otherwise, it negotiates with the
- * container to display itself appropriately.
- *
- * @param container The desired containing Window.
- */
- public void setContainer(Window container) {
- mContainer = container;
- if (container != null) {
- // Embedded screens never have a title.
- mFeatures |= 1<<FEATURE_NO_TITLE;
- mLocalFeatures |= 1<<FEATURE_NO_TITLE;
- container.mHasChildren = true;
- }
- }
-
- /**
- * Return the container for this Window.
- *
- * @return Window The containing window, or null if this is a
- * top-level window.
- */
- public final Window getContainer() {
- return mContainer;
- }
-
- public final boolean hasChildren() {
- return mHasChildren;
- }
-
- /**
- * Set the window manager for use by this Window to, for example,
- * display panels. This is <em>not</em> used for displaying the
- * Window itself -- that must be done by the client.
- *
- * @param wm The ViewManager for adding new windows.
- */
- public void setWindowManager(WindowManager wm,
- IBinder appToken, String appName) {
- mAppToken = appToken;
- mAppName = appName;
- if (wm == null) {
- wm = WindowManagerImpl.getDefault();
- }
- mWindowManager = new LocalWindowManager(wm);
- }
-
- private class LocalWindowManager implements WindowManager {
- LocalWindowManager(WindowManager wm) {
- mWindowManager = wm;
- }
-
- public final void addView(View view, ViewGroup.LayoutParams params) {
- // Let this throw an exception on a bad params.
- WindowManager.LayoutParams wp = (WindowManager.LayoutParams)params;
- CharSequence curTitle = wp.getTitle();
- if (wp.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
- wp.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
- if (wp.token == null) {
- View decor = peekDecorView();
- if (decor != null) {
- wp.token = decor.getWindowToken();
- }
- }
- if (curTitle == null || curTitle.length() == 0) {
- String title;
- if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA) {
- title="Media";
- } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
- title="Panel";
- } else {
- title=Integer.toString(wp.type);
- }
- if (mAppName != null) {
- title += ":" + mAppName;
- }
- wp.setTitle(title);
- }
- } else {
- if (wp.token == null) {
- wp.token = mContainer == null ? mAppToken : mContainer.mAppToken;
- }
- if ((curTitle == null || curTitle.length() == 0)
- && mAppName != null) {
- wp.setTitle(mAppName);
- }
- }
- if (wp.packageName == null) {
- wp.packageName = mContext.getPackageName();
- }
- mWindowManager.addView(view, params);
- }
-
- public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
- mWindowManager.updateViewLayout(view, params);
- }
-
- public final void removeView(View view) {
- mWindowManager.removeView(view);
- }
-
- public final void removeViewImmediate(View view) {
- mWindowManager.removeViewImmediate(view);
- }
-
- public Display getDefaultDisplay() {
- return mWindowManager.getDefaultDisplay();
- }
-
- WindowManager mWindowManager;
- }
-
- /**
- * Return the window manager allowing this Window to display its own
- * windows.
- *
- * @return WindowManager The ViewManager.
- */
- public WindowManager getWindowManager() {
- return mWindowManager;
- }
-
- /**
- * Set the Callback interface for this window, used to intercept key
- * events and other dynamic operations in the window.
- *
- * @param callback The desired Callback interface.
- */
- public void setCallback(Callback callback) {
- mCallback = callback;
- }
-
- /**
- * Return the current Callback interface for this window.
- */
- public final Callback getCallback() {
- return mCallback;
- }
-
- /**
- * Return whether this window is being displayed with a floating style
- * (based on the {@link android.R.attr#windowIsFloating} attribute in
- * the style/theme).
- *
- * @return Returns true if the window is configured to be displayed floating
- * on top of whatever is behind it.
- */
- public abstract boolean isFloating();
-
- /**
- * Set the width and height layout parameters of the window. The default
- * for both of these is FILL_PARENT; you can change them to WRAP_CONTENT to
- * make a window that is not full-screen.
- *
- * @param width The desired layout width of the window.
- * @param height The desired layout height of the window.
- */
- public void setLayout(int width, int height)
- {
- final WindowManager.LayoutParams attrs = getAttributes();
- attrs.width = width;
- attrs.height = height;
- if (mCallback != null) {
- mCallback.onWindowAttributesChanged(attrs);
- }
- }
-
- /**
- * Set the gravity of the window, as per the Gravity constants. This
- * controls how the window manager is positioned in the overall window; it
- * is only useful when using WRAP_CONTENT for the layout width or height.
- *
- * @param gravity The desired gravity constant.
- *
- * @see Gravity
- * @see #setLayout
- */
- public void setGravity(int gravity)
- {
- final WindowManager.LayoutParams attrs = getAttributes();
- attrs.gravity = gravity;
- if (mCallback != null) {
- mCallback.onWindowAttributesChanged(attrs);
- }
- }
-
- /**
- * Set the type of the window, as per the WindowManager.LayoutParams
- * types.
- *
- * @param type The new window type (see WindowManager.LayoutParams).
- */
- public void setType(int type) {
- final WindowManager.LayoutParams attrs = getAttributes();
- attrs.type = type;
- if (mCallback != null) {
- mCallback.onWindowAttributesChanged(attrs);
- }
- }
-
- /**
- * Set the format of window, as per the PixelFormat types. This overrides
- * the default format that is selected by the Window based on its
- * window decorations.
- *
- * @param format The new window format (see PixelFormat). Use
- * PixelFormat.UNKNOWN to allow the Window to select
- * the format.
- *
- * @see PixelFormat
- */
- public void setFormat(int format) {
- final WindowManager.LayoutParams attrs = getAttributes();
- if (format != PixelFormat.UNKNOWN) {
- attrs.format = format;
- mHaveWindowFormat = true;
- } else {
- attrs.format = mDefaultWindowFormat;
- mHaveWindowFormat = false;
- }
- if (mCallback != null) {
- mCallback.onWindowAttributesChanged(attrs);
- }
- }
-
- /**
- * Specify custom animations to use for the window, as per
- * {@link WindowManager.LayoutParams#windowAnimations
- * WindowManager.LayoutParams.windowAnimations}. Providing anything besides
- * 0 here will override the animations the window would
- * normally retrieve from its theme.
- */
- public void setWindowAnimations(int resId) {
- final WindowManager.LayoutParams attrs = getAttributes();
- attrs.windowAnimations = resId;
- if (mCallback != null) {
- mCallback.onWindowAttributesChanged(attrs);
- }
- }
-
- /**
- * Specify an explicit soft input mode to use for the window, as per
- * {@link WindowManager.LayoutParams#softInputMode
- * WindowManager.LayoutParams.softInputMode}. Providing anything besides
- * "unspecified" here will override the input mode the window would
- * normally retrieve from its theme.
- */
- public void setSoftInputMode(int mode) {
- final WindowManager.LayoutParams attrs = getAttributes();
- if (mode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
- attrs.softInputMode = mode;
- mHasSoftInputMode = true;
- } else {
- mHasSoftInputMode = false;
- }
- if (mCallback != null) {
- mCallback.onWindowAttributesChanged(attrs);
- }
- }
-
- /**
- * Convenience function to set the flag bits as specified in flags, as
- * per {@link #setFlags}.
- * @param flags The flag bits to be set.
- * @see #setFlags
- */
- public void addFlags(int flags) {
- setFlags(flags, flags);
- }
-
- /**
- * Convenience function to clear the flag bits as specified in flags, as
- * per {@link #setFlags}.
- * @param flags The flag bits to be cleared.
- * @see #setFlags
- */
- public void clearFlags(int flags) {
- setFlags(0, flags);
- }
-
- /**
- * Set the flags of the window, as per the
- * {@link WindowManager.LayoutParams WindowManager.LayoutParams}
- * flags.
- *
- * <p>Note that some flags must be set before the window decoration is
- * created (by the first call to
- * {@link #setContentView(View, android.view.ViewGroup.LayoutParams)} or
- * {@link #getDecorView()}:
- * {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN} and
- * {@link WindowManager.LayoutParams#FLAG_LAYOUT_INSET_DECOR}. These
- * will be set for you based on the {@link android.R.attr#windowIsFloating}
- * attribute.
- *
- * @param flags The new window flags (see WindowManager.LayoutParams).
- * @param mask Which of the window flag bits to modify.
- */
- public void setFlags(int flags, int mask) {
- final WindowManager.LayoutParams attrs = getAttributes();
- attrs.flags = (attrs.flags&~mask) | (flags&mask);
- mForcedWindowFlags |= mask;
- if (mCallback != null) {
- mCallback.onWindowAttributesChanged(attrs);
- }
- }
-
- /**
- * Specify custom window attributes. <strong>PLEASE NOTE:</strong> the
- * layout params you give here should generally be from values previously
- * retrieved with {@link #getAttributes()}; you probably do not want to
- * blindly create and apply your own, since this will blow away any values
- * set by the framework that you are not interested in.
- *
- * @param a The new window attributes, which will completely override any
- * current values.
- */
- public void setAttributes(WindowManager.LayoutParams a) {
- mWindowAttributes.copyFrom(a);
- if (mCallback != null) {
- mCallback.onWindowAttributesChanged(mWindowAttributes);
- }
- }
-
- /**
- * Retrieve the current window attributes associated with this panel.
- *
- * @return WindowManager.LayoutParams Either the existing window
- * attributes object, or a freshly created one if there is none.
- */
- public final WindowManager.LayoutParams getAttributes() {
- return mWindowAttributes;
- }
-
- /**
- * Return the window flags that have been explicitly set by the client,
- * so will not be modified by {@link #getDecorView}.
- */
- protected final int getForcedWindowFlags() {
- return mForcedWindowFlags;
- }
-
- /**
- * Has the app specified their own soft input mode?
- */
- protected final boolean hasSoftInputMode() {
- return mHasSoftInputMode;
- }
-
- /**
- * Enable extended screen features. This must be called before
- * setContentView(). May be called as many times as desired as long as it
- * is before setContentView(). If not called, no extended features
- * will be available. You can not turn off a feature once it is requested.
- * You canot use other title features with {@link #FEATURE_CUSTOM_TITLE}.
- *
- * @param featureId The desired features, defined as constants by Window.
- * @return The features that are now set.
- */
- public boolean requestFeature(int featureId) {
- final int flag = 1<<featureId;
- mFeatures |= flag;
- mLocalFeatures |= mContainer != null ? (flag&~mContainer.mFeatures) : flag;
- return (mFeatures&flag) != 0;
- }
-
- public final void makeActive() {
- if (mContainer != null) {
- if (mContainer.mActiveChild != null) {
- mContainer.mActiveChild.mIsActive = false;
- }
- mContainer.mActiveChild = this;
- }
- mIsActive = true;
- onActive();
- }
-
- public final boolean isActive()
- {
- return mIsActive;
- }
-
- /**
- * Finds a view that was identified by the id attribute from the XML that
- * was processed in {@link android.app.Activity#onCreate}. This will
- * implicitly call {@link #getDecorView} for you, with all of the
- * associated side-effects.
- *
- * @return The view if found or null otherwise.
- */
- public View findViewById(int id) {
- return getDecorView().findViewById(id);
- }
-
- /**
- * Convenience for
- * {@link #setContentView(View, android.view.ViewGroup.LayoutParams)}
- * to set the screen content from a layout resource. The resource will be
- * inflated, adding all top-level views to the screen.
- *
- * @param layoutResID Resource ID to be inflated.
- * @see #setContentView(View, android.view.ViewGroup.LayoutParams)
- */
- public abstract void setContentView(int layoutResID);
-
- /**
- * Convenience for
- * {@link #setContentView(View, android.view.ViewGroup.LayoutParams)}
- * set the screen content to an explicit view. This view is placed
- * directly into the screen's view hierarchy. It can itself be a complex
- * view hierarhcy.
- *
- * @param view The desired content to display.
- * @see #setContentView(View, android.view.ViewGroup.LayoutParams)
- */
- public abstract void setContentView(View view);
-
- /**
- * Set the screen content to an explicit view. This view is placed
- * directly into the screen's view hierarchy. It can itself be a complex
- * view hierarchy.
- *
- * <p>Note that calling this function "locks in" various characteristics
- * of the window that can not, from this point forward, be changed: the
- * features that have been requested with {@link #requestFeature(int)},
- * and certain window flags as described in {@link #setFlags(int, int)}.
- *
- * @param view The desired content to display.
- * @param params Layout parameters for the view.
- */
- public abstract void setContentView(View view, ViewGroup.LayoutParams params);
-
- /**
- * Variation on
- * {@link #setContentView(View, android.view.ViewGroup.LayoutParams)}
- * to add an additional content view to the screen. Added after any existing
- * ones in the screen -- existing views are NOT removed.
- *
- * @param view The desired content to display.
- * @param params Layout parameters for the view.
- */
- public abstract void addContentView(View view, ViewGroup.LayoutParams params);
-
- /**
- * Return the view in this Window that currently has focus, or null if
- * there are none. Note that this does not look in any containing
- * Window.
- *
- * @return View The current View with focus or null.
- */
- public abstract View getCurrentFocus();
-
- /**
- * Quick access to the {@link LayoutInflater} instance that this Window
- * retrieved from its Context.
- *
- * @return LayoutInflater The shared LayoutInflater.
- */
- public abstract LayoutInflater getLayoutInflater();
-
- public abstract void setTitle(CharSequence title);
-
- public abstract void setTitleColor(int textColor);
-
- public abstract void openPanel(int featureId, KeyEvent event);
-
- public abstract void closePanel(int featureId);
-
- public abstract void togglePanel(int featureId, KeyEvent event);
-
- public abstract boolean performPanelShortcut(int featureId,
- int keyCode,
- KeyEvent event,
- int flags);
- public abstract boolean performPanelIdentifierAction(int featureId,
- int id,
- int flags);
-
- public abstract void closeAllPanels();
-
- public abstract boolean performContextMenuIdentifierAction(int id, int flags);
-
- /**
- * Should be called when the configuration is changed.
- *
- * @param newConfig The new configuration.
- */
- public abstract void onConfigurationChanged(Configuration newConfig);
-
- /**
- * Change the background of this window to a Drawable resource. Setting the
- * background to null will make the window be opaque. To make the window
- * transparent, you can use an empty drawable (for instance a ColorDrawable
- * with the color 0 or the system drawable android:drawable/empty.)
- *
- * @param resid The resource identifier of a drawable resource which will be
- * installed as the new background.
- */
- public void setBackgroundDrawableResource(int resid)
- {
- setBackgroundDrawable(mContext.getResources().getDrawable(resid));
- }
-
- /**
- * Change the background of this window to a custom Drawable. Setting the
- * background to null will make the window be opaque. To make the window
- * transparent, you can use an empty drawable (for instance a ColorDrawable
- * with the color 0 or the system drawable android:drawable/empty.)
- *
- * @param drawable The new Drawable to use for this window's background.
- */
- public abstract void setBackgroundDrawable(Drawable drawable);
-
- /**
- * Set the value for a drawable feature of this window, from a resource
- * identifier. You must have called requestFeauture(featureId) before
- * calling this function.
- *
- * @see android.content.res.Resources#getDrawable(int)
- *
- * @param featureId The desired drawable feature to change, defined as a
- * constant by Window.
- * @param resId Resource identifier of the desired image.
- */
- public abstract void setFeatureDrawableResource(int featureId, int resId);
-
- /**
- * Set the value for a drawable feature of this window, from a URI. You
- * must have called requestFeature(featureId) before calling this
- * function.
- *
- * <p>The only URI currently supported is "content:", specifying an image
- * in a content provider.
- *
- * @see android.widget.ImageView#setImageURI
- *
- * @param featureId The desired drawable feature to change. Features are
- * constants defined by Window.
- * @param uri The desired URI.
- */
- public abstract void setFeatureDrawableUri(int featureId, Uri uri);
-
- /**
- * Set an explicit Drawable value for feature of this window. You must
- * have called requestFeature(featureId) before calling this function.
- *
- * @param featureId The desired drawable feature to change.
- * Features are constants defined by Window.
- * @param drawable A Drawable object to display.
- */
- public abstract void setFeatureDrawable(int featureId, Drawable drawable);
-
- /**
- * Set a custom alpha value for the given drawale feature, controlling how
- * much the background is visible through it.
- *
- * @param featureId The desired drawable feature to change.
- * Features are constants defined by Window.
- * @param alpha The alpha amount, 0 is completely transparent and 255 is
- * completely opaque.
- */
- public abstract void setFeatureDrawableAlpha(int featureId, int alpha);
-
- /**
- * Set the integer value for a feature. The range of the value depends on
- * the feature being set. For FEATURE_PROGRESSS, it should go from 0 to
- * 10000. At 10000 the progress is complete and the indicator hidden.
- *
- * @param featureId The desired feature to change.
- * Features are constants defined by Window.
- * @param value The value for the feature. The interpretation of this
- * value is feature-specific.
- */
- public abstract void setFeatureInt(int featureId, int value);
-
- /**
- * Request that key events come to this activity. Use this if your
- * activity has no views with focus, but the activity still wants
- * a chance to process key events.
- */
- public abstract void takeKeyEvents(boolean get);
-
- /**
- * Used by custom windows, such as Dialog, to pass the key press event
- * further down the view hierarchy. Application developers should
- * not need to implement or call this.
- *
- */
- public abstract boolean superDispatchKeyEvent(KeyEvent event);
-
- /**
- * Used by custom windows, such as Dialog, to pass the touch screen event
- * further down the view hierarchy. Application developers should
- * not need to implement or call this.
- *
- */
- public abstract boolean superDispatchTouchEvent(MotionEvent event);
-
- /**
- * Used by custom windows, such as Dialog, to pass the trackball event
- * further down the view hierarchy. Application developers should
- * not need to implement or call this.
- *
- */
- public abstract boolean superDispatchTrackballEvent(MotionEvent event);
-
- /**
- * Retrieve the top-level window decor view (containing the standard
- * window frame/decorations and the client's content inside of that), which
- * can be added as a window to the window manager.
- *
- * <p><em>Note that calling this function for the first time "locks in"
- * various window characteristics as described in
- * {@link #setContentView(View, android.view.ViewGroup.LayoutParams)}.</em></p>
- *
- * @return Returns the top-level window decor view.
- */
- public abstract View getDecorView();
-
- /**
- * Retrieve the current decor view, but only if it has already been created;
- * otherwise returns null.
- *
- * @return Returns the top-level window decor or null.
- * @see #getDecorView
- */
- public abstract View peekDecorView();
-
- public abstract Bundle saveHierarchyState();
-
- public abstract void restoreHierarchyState(Bundle savedInstanceState);
-
- protected abstract void onActive();
-
- /**
- * Return the feature bits that are enabled. This is the set of features
- * that were given to requestFeature(), and are being handled by this
- * Window itself or its container. That is, it is the set of
- * requested features that you can actually use.
- *
- * <p>To do: add a public version of this API that allows you to check for
- * features by their feature ID.
- *
- * @return int The feature bits.
- */
- protected final int getFeatures()
- {
- return mFeatures;
- }
-
- /**
- * Return the feature bits that are being implemented by this Window.
- * This is the set of features that were given to requestFeature(), and are
- * being handled by only this Window itself, not by its containers.
- *
- * @return int The feature bits.
- */
- protected final int getLocalFeatures()
- {
- return mLocalFeatures;
- }
-
- /**
- * Set the default format of window, as per the PixelFormat types. This
- * is the format that will be used unless the client specifies in explicit
- * format with setFormat();
- *
- * @param format The new window format (see PixelFormat).
- *
- * @see #setFormat
- * @see PixelFormat
- */
- protected void setDefaultWindowFormat(int format) {
- mDefaultWindowFormat = format;
- if (!mHaveWindowFormat) {
- final WindowManager.LayoutParams attrs = getAttributes();
- attrs.format = format;
- if (mCallback != null) {
- mCallback.onWindowAttributesChanged(attrs);
- }
- }
- }
-
- public abstract void setChildDrawable(int featureId, Drawable drawable);
-
- public abstract void setChildInt(int featureId, int value);
-
- /**
- * Is a keypress one of the defined shortcut keys for this window.
- * @param keyCode the key code from {@link android.view.KeyEvent} to check.
- * @param event the {@link android.view.KeyEvent} to use to help check.
- */
- public abstract boolean isShortcutKey(int keyCode, KeyEvent event);
-
- /**
- * @see android.app.Activity#setVolumeControlStream(int)
- */
- public abstract void setVolumeControlStream(int streamType);
-
- /**
- * @see android.app.Activity#getVolumeControlStream()
- */
- public abstract int getVolumeControlStream();
-
-}
diff --git a/core/java/android/view/WindowManager.aidl b/core/java/android/view/WindowManager.aidl
deleted file mode 100755
index 556dc72..0000000
--- a/core/java/android/view/WindowManager.aidl
+++ /dev/null
@@ -1,21 +0,0 @@
-/* //device/java/android/android/view/WindowManager.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.view;
-
-parcelable WindowManager.LayoutParams;
-
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
deleted file mode 100644
index b87cc42..0000000
--- a/core/java/android/view/WindowManager.java
+++ /dev/null
@@ -1,959 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.content.pm.ActivityInfo;
-import android.graphics.PixelFormat;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Log;
-
-
-/**
- * The interface that apps use to talk to the window manager.
- * <p>
- * Use <code>Context.getSystemService(Context.WINDOW_SERVICE)</code> to get one of these.
- *
- * @see android.content.Context#getSystemService
- * @see android.content.Context#WINDOW_SERVICE
- */
-public interface WindowManager extends ViewManager {
- /**
- * Exception that is thrown when trying to add view whose
- * {@link WindowManager.LayoutParams} {@link WindowManager.LayoutParams#token}
- * is invalid.
- */
- public static class BadTokenException extends RuntimeException {
- public BadTokenException() {
- }
-
- public BadTokenException(String name) {
- super(name);
- }
- }
-
- /**
- * Use this method to get the default Display object.
- *
- * @return default Display object
- */
- public Display getDefaultDisplay();
-
- /**
- * Special variation of {@link #removeView} that immediately invokes
- * the given view hierarchy's {@link View#onDetachedFromWindow()
- * View.onDetachedFromWindow()} methods before returning. This is not
- * for normal applications; using it correctly requires great care.
- *
- * @param view The view to be removed.
- */
- public void removeViewImmediate(View view);
-
- public static class LayoutParams extends ViewGroup.LayoutParams
- implements Parcelable {
- /**
- * X position for this window. With the default gravity it is ignored.
- * When using {@link Gravity#LEFT} or {@link Gravity#RIGHT} it provides
- * an offset from the given edge.
- */
- public int x;
-
- /**
- * Y position for this window. With the default gravity it is ignored.
- * When using {@link Gravity#TOP} or {@link Gravity#BOTTOM} it provides
- * an offset from the given edge.
- */
- public int y;
-
- /**
- * Indicates how much of the extra space will be allocated horizontally
- * to the view associated with these LayoutParams. Specify 0 if the view
- * should not be stretched. Otherwise the extra pixels will be pro-rated
- * among all views whose weight is greater than 0.
- */
- public float horizontalWeight;
-
- /**
- * Indicates how much of the extra space will be allocated vertically
- * to the view associated with these LayoutParams. Specify 0 if the view
- * should not be stretched. Otherwise the extra pixels will be pro-rated
- * among all views whose weight is greater than 0.
- */
- public float verticalWeight;
-
- /**
- * The general type of window. There are three main classes of
- * window types:
- * <ul>
- * <li> <strong>Application windows</strong> (ranging from
- * {@link #FIRST_APPLICATION_WINDOW} to
- * {@link #LAST_APPLICATION_WINDOW}) are normal top-level application
- * windows. For these types of windows, the {@link #token} must be
- * set to the token of the activity they are a part of (this will
- * normally be done for you if {@link #token} is null).
- * <li> <strong>Sub-windows</strong> (ranging from
- * {@link #FIRST_SUB_WINDOW} to
- * {@link #LAST_SUB_WINDOW}) are associated with another top-level
- * window. For these types of windows, the {@link #token} must be
- * the token of the window it is attached to.
- * <li> <strong>System windows</strong> (ranging from
- * {@link #FIRST_SYSTEM_WINDOW} to
- * {@link #LAST_SYSTEM_WINDOW}) are special types of windows for
- * use by the system for specific purposes. They should not normally
- * be used by applications, and a special permission is required
- * to use them.
- * </ul>
- *
- * @see #TYPE_BASE_APPLICATION
- * @see #TYPE_APPLICATION
- * @see #TYPE_APPLICATION_STARTING
- * @see #TYPE_APPLICATION_PANEL
- * @see #TYPE_APPLICATION_MEDIA
- * @see #TYPE_APPLICATION_SUB_PANEL
- * @see #TYPE_APPLICATION_ATTACHED_DIALOG
- * @see #TYPE_STATUS_BAR
- * @see #TYPE_SEARCH_BAR
- * @see #TYPE_PHONE
- * @see #TYPE_SYSTEM_ALERT
- * @see #TYPE_KEYGUARD
- * @see #TYPE_TOAST
- * @see #TYPE_SYSTEM_OVERLAY
- * @see #TYPE_PRIORITY_PHONE
- * @see #TYPE_STATUS_BAR_PANEL
- * @see #TYPE_SYSTEM_DIALOG
- * @see #TYPE_KEYGUARD_DIALOG
- * @see #TYPE_SYSTEM_ERROR
- * @see #TYPE_INPUT_METHOD
- * @see #TYPE_INPUT_METHOD_DIALOG
- */
- public int type;
-
- /**
- * Start of window types that represent normal application windows.
- */
- public static final int FIRST_APPLICATION_WINDOW = 1;
-
- /**
- * Window type: an application window that serves as the "base" window
- * of the overall application; all other application windows will
- * appear on top of it.
- */
- public static final int TYPE_BASE_APPLICATION = 1;
-
- /**
- * Window type: a normal application window. The {@link #token} must be
- * an Activity token identifying who the window belongs to.
- */
- public static final int TYPE_APPLICATION = 2;
-
- /**
- * Window type: special application window that is displayed while the
- * application is starting. Not for use by applications themselves;
- * this is used by the system to display something until the
- * application can show its own windows.
- */
- public static final int TYPE_APPLICATION_STARTING = 3;
-
- /**
- * End of types of application windows.
- */
- public static final int LAST_APPLICATION_WINDOW = 99;
-
- /**
- * Start of types of sub-windows. The {@link #token} of these windows
- * must be set to the window they are attached to. These types of
- * windows are kept next to their attached window in Z-order, and their
- * coordinate space is relative to their attached window.
- */
- public static final int FIRST_SUB_WINDOW = 1000;
-
- /**
- * Window type: a panel on top of an application window. These windows
- * appear on top of their attached window.
- */
- public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;
-
- /**
- * Window type: window for showing media (e.g. video). These windows
- * are displayed behind their attached window.
- */
- public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1;
-
- /**
- * Window type: a sub-panel on top of an application window. These
- * windows are displayed on top their attached window and any
- * {@link #TYPE_APPLICATION_PANEL} panels.
- */
- public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2;
-
- /** Window type: like {@link #TYPE_APPLICATION_PANEL}, but layout
- * of the window happens as that of a top-level window, <em>not</em>
- * as a child of its container.
- */
- public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3;
-
- /**
- * End of types of sub-windows.
- */
- public static final int LAST_SUB_WINDOW = 1999;
-
- /**
- * Start of system-specific window types. These are not normally
- * created by applications.
- */
- public static final int FIRST_SYSTEM_WINDOW = 2000;
-
- /**
- * Window type: the status bar. There can be only one status bar
- * window; it is placed at the top of the screen, and all other
- * windows are shifted down so they are below it.
- */
- public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW;
-
- /**
- * Window type: the search bar. There can be only one search bar
- * window; it is placed at the top of the screen.
- */
- public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1;
-
- /**
- * Window type: phone. These are non-application windows providing
- * user interaction with the phone (in particular incoming calls).
- * These windows are normally placed above all applications, but behind
- * the status bar.
- */
- public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2;
-
- /**
- * Window type: system window, such as low power alert. These windows
- * are always on top of application windows.
- */
- public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3;
-
- /**
- * Window type: keyguard window.
- */
- public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4;
-
- /**
- * Window type: transient notifications.
- */
- public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5;
-
- /**
- * Window type: system overlay windows, which need to be displayed
- * on top of everything else. These windows must not take input
- * focus, or they will interfere with the keyguard.
- */
- public static final int TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6;
-
- /**
- * Window type: priority phone UI, which needs to be displayed even if
- * the keyguard is active. These windows must not take input
- * focus, or they will interfere with the keyguard.
- */
- public static final int TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7;
-
- /**
- * Window type: panel that slides out from the status bar
- */
- public static final int TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+8;
-
- /**
- * Window type: panel that slides out from the status bar
- */
- public static final int TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8;
-
- /**
- * Window type: dialogs that the keyguard shows
- */
- public static final int TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9;
-
- /**
- * Window type: internal system error windows, appear on top of
- * everything they can.
- */
- public static final int TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10;
-
- /**
- * Window type: internal input methods windows, which appear above
- * the normal UI. Application windows may be resized or panned to keep
- * the input focus visible while this window is displayed.
- */
- public static final int TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11;
-
- /**
- * Window type: internal input methods dialog windows, which appear above
- * the current input method window.
- */
- public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12;
-
- /**
- * End of types of system windows.
- */
- public static final int LAST_SYSTEM_WINDOW = 2999;
-
- /**
- * Specifies what type of memory buffers should be used by this window.
- * Default is normal.
- *
- * @see #MEMORY_TYPE_NORMAL
- * @see #MEMORY_TYPE_HARDWARE
- * @see #MEMORY_TYPE_GPU
- * @see #MEMORY_TYPE_PUSH_BUFFERS
- */
- public int memoryType;
-
- /** Memory type: The window's surface is allocated in main memory. */
- public static final int MEMORY_TYPE_NORMAL = 0;
- /** Memory type: The window's surface is configured to be accessible
- * by DMA engines and hardware accelerators. */
- public static final int MEMORY_TYPE_HARDWARE = 1;
- /** Memory type: The window's surface is configured to be accessible
- * by graphics accelerators. */
- public static final int MEMORY_TYPE_GPU = 2;
- /** Memory type: The window's surface doesn't own its buffers and
- * therefore cannot be locked. Instead the buffers are pushed to
- * it through native binder calls. */
- public static final int MEMORY_TYPE_PUSH_BUFFERS = 3;
-
- /**
- * Various behavioral options/flags. Default is none.
- *
- * @see #FLAG_BLUR_BEHIND
- * @see #FLAG_DIM_BEHIND
- * @see #FLAG_NOT_FOCUSABLE
- * @see #FLAG_NOT_TOUCHABLE
- * @see #FLAG_NOT_TOUCH_MODAL
- * @see #FLAG_LAYOUT_IN_SCREEN
- * @see #FLAG_DITHER
- * @see #FLAG_KEEP_SCREEN_ON
- * @see #FLAG_FULLSCREEN
- * @see #FLAG_FORCE_NOT_FULLSCREEN
- * @see #FLAG_IGNORE_CHEEK_PRESSES
- */
- public int flags;
-
- /** Window flag: everything behind this window will be dimmed.
- * Use {@link #dimAmount} to control the amount of dim. */
- public static final int FLAG_DIM_BEHIND = 0x00000002;
-
- /** Window flag: blur everything behind this window. */
- public static final int FLAG_BLUR_BEHIND = 0x00000004;
-
- /** Window flag: this window won't ever get key input focus, so the
- * user can not send key or other button events to it. Those will
- * instead go to whatever focusable window is behind it. This flag
- * will also enable {@link #FLAG_NOT_TOUCH_MODAL} whether or not that
- * is explicitly set.
- *
- * <p>Setting this flag also implies that the window will not need to
- * interact with
- * a soft input method, so it will be Z-ordered and positioned
- * independently of any active input method (typically this means it
- * gets Z-ordered on top of the input method, so it can use the full
- * screen for its content and cover the input method if needed. You
- * can use {@link #FLAG_ALT_FOCUSABLE_IM} to modify this behavior. */
- public static final int FLAG_NOT_FOCUSABLE = 0x00000008;
-
- /** Window flag: this window can never receive touch events. */
- public static final int FLAG_NOT_TOUCHABLE = 0x00000010;
-
- /** Window flag: Even when this window is focusable (its
- * {@link #FLAG_NOT_FOCUSABLE is not set), allow any pointer events
- * outside of the window to be sent to the windows behind it. Otherwise
- * it will consume all pointer events itself, regardless of whether they
- * are inside of the window. */
- public static final int FLAG_NOT_TOUCH_MODAL = 0x00000020;
-
- /** Window flag: When set, if the device is asleep when the touch
- * screen is pressed, you will receive this first touch event. Usually
- * the first touch event is consumed by the system since the user can
- * not see what they are pressing on.
- */
- public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040;
-
- /** Window flag: as long as this window is visible to the user, keep
- * the device's screen turned on and bright. */
- public static final int FLAG_KEEP_SCREEN_ON = 0x00000080;
-
- /** Window flag: place the window within the entire screen, ignoring
- * decorations around the border (a.k.a. the status bar). The
- * window must correctly position its contents to take the screen
- * decoration into account. This flag is normally set for you
- * by Window as described in {@link Window#setFlags}. */
- public static final int FLAG_LAYOUT_IN_SCREEN = 0x00000100;
-
- /** Window flag: allow window to extend outside of the screen. */
- public static final int FLAG_LAYOUT_NO_LIMITS = 0x00000200;
-
- /** Window flag: Hide all screen decorations (e.g. status bar) while
- * this window is displayed. This allows the window to use the entire
- * display space for itself -- the status bar will be hidden when
- * an app window with this flag set is on the top layer. */
- public static final int FLAG_FULLSCREEN = 0x00000400;
-
- /** Window flag: Override {@link #FLAG_FULLSCREEN and force the
- * screen decorations (such as status bar) to be shown. */
- public static final int FLAG_FORCE_NOT_FULLSCREEN = 0x00000800;
-
- /** Window flag: turn on dithering when compositing this window to
- * the screen. */
- public static final int FLAG_DITHER = 0x00001000;
-
- /** Window flag: don't allow screen shots while this window is
- * displayed. */
- public static final int FLAG_SECURE = 0x00002000;
-
- /** Window flag: a special mode where the layout parameters are used
- * to perform scaling of the surface when it is composited to the
- * screen. */
- public static final int FLAG_SCALED = 0x00004000;
-
- /** Window flag: intended for windows that will often be used when the user is
- * holding the screen against their face, it will aggressively filter the event
- * stream to prevent unintended presses in this situation that may not be
- * desired for a particular window, when such an event stream is detected, the
- * application will receive a CANCEL motion event to indicate this so applications
- * can handle this accordingly by taking no action on the event
- * until the finger is released. */
- public static final int FLAG_IGNORE_CHEEK_PRESSES = 0x00008000;
-
- /** Window flag: a special option only for use in combination with
- * {@link #FLAG_LAYOUT_IN_SCREEN}. When requesting layout in the
- * screen your window may appear on top of or behind screen decorations
- * such as the status bar. By also including this flag, the window
- * manager will report the inset rectangle needed to ensure your
- * content is not covered by screen decorations. This flag is normally
- * set for you by Window as described in {@link Window#setFlags}.*/
- public static final int FLAG_LAYOUT_INSET_DECOR = 0x00010000;
-
- /** Window flag: invert the state of {@link #FLAG_NOT_FOCUSABLE} with
- * respect to how this window interacts with the current method. That
- * is, if FLAG_NOT_FOCUSABLE is set and this flag is set, then the
- * window will behave as if it needs to interact with the input method
- * and thus be placed behind/away from it; if FLAG_NOT_FOCUSABLE is
- * not set and this flag is set, then the window will behave as if it
- * doesn't need to interact with the input method and can be placed
- * to use more space and cover the input method.
- */
- public static final int FLAG_ALT_FOCUSABLE_IM = 0x00020000;
-
- /** Window flag: if you have set {@link #FLAG_NOT_TOUCH_MODAL}, you
- * can set this flag to receive a single special MotionEvent with
- * the action
- * {@link MotionEvent#ACTION_OUTSIDE MotionEvent.ACTION_OUTSIDE} for
- * touches that occur outside of your window. Note that you will not
- * receive the full down/move/up gesture, only the location of the
- * first down as an ACTION_OUTSIDE.
- */
- public static final int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000;
-
- /** Window flag: a special option intended for system dialogs. When
- * this flag is set, the window will demand focus unconditionally when
- * it is created.
- * {@hide} */
- public static final int FLAG_SYSTEM_ERROR = 0x40000000;
-
- /**
- * Given a particular set of window manager flags, determine whether
- * such a window may be a target for an input method when it has
- * focus. In particular, this checks the
- * {@link #FLAG_NOT_FOCUSABLE} and {@link #FLAG_ALT_FOCUSABLE_IM}
- * flags and returns true if the combination of the two corresponds
- * to a window that needs to be behind the input method so that the
- * user can type into it.
- *
- * @param flags The current window manager flags.
- *
- * @return Returns true if such a window should be behind/interact
- * with an input method, false if not.
- */
- public static boolean mayUseInputMethod(int flags) {
- switch (flags&(FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) {
- case 0:
- case FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM:
- return true;
- }
- return false;
- }
-
- /**
- * Mask for {@link #softInputMode} of the bits that determine the
- * desired visibility state of the soft input area for this window.
- */
- public static final int SOFT_INPUT_MASK_STATE = 0x0f;
-
- /**
- * Visibility state for {@link #softInputMode}: no state has been specified.
- */
- public static final int SOFT_INPUT_STATE_UNSPECIFIED = 0;
-
- /**
- * Visibility state for {@link #softInputMode}: please don't change the state of
- * the soft input area.
- */
- public static final int SOFT_INPUT_STATE_UNCHANGED = 1;
-
- /**
- * Visibility state for {@link #softInputMode}: please hide any soft input
- * area when normally appropriate (when the user is navigating
- * forward to your window).
- */
- public static final int SOFT_INPUT_STATE_HIDDEN = 2;
-
- /**
- * Visibility state for {@link #softInputMode}: please always hide any
- * soft input area when this window receives focus.
- */
- public static final int SOFT_INPUT_STATE_ALWAYS_HIDDEN = 3;
-
- /**
- * Visibility state for {@link #softInputMode}: please show the soft
- * input area when normally appropriate (when the user is navigating
- * forward to your window).
- */
- public static final int SOFT_INPUT_STATE_VISIBLE = 4;
-
- /**
- * Visibility state for {@link #softInputMode}: please always make the
- * soft input area visible when this window receives input focus.
- */
- public static final int SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5;
-
- /**
- * Mask for {@link #softInputMode} of the bits that determine the
- * way that the window should be adjusted to accommodate the soft
- * input window.
- */
- public static final int SOFT_INPUT_MASK_ADJUST = 0xf0;
-
- /** Adjustment option for {@link #softInputMode}: nothing specified.
- * The system will try to pick one or
- * the other depending on the contents of the window.
- */
- public static final int SOFT_INPUT_ADJUST_UNSPECIFIED = 0x00;
-
- /** Adjustment option for {@link #softInputMode}: set to allow the
- * window to be resized when an input
- * method is shown, so that its contents are not covered by the input
- * method. This can <em>not<em> be combined with
- * {@link #SOFT_INPUT_ADJUST_PAN}; if
- * neither of these are set, then the system will try to pick one or
- * the other depending on the contents of the window.
- */
- public static final int SOFT_INPUT_ADJUST_RESIZE = 0x10;
-
- /** Adjustment option for {@link #softInputMode}: set to have a window
- * pan when an input method is
- * shown, so it doesn't need to deal with resizing but just panned
- * by the framework to ensure the current input focus is visible. This
- * can <em>not<em> be combined with {@link #SOFT_INPUT_ADJUST_RESIZE}; if
- * neither of these are set, then the system will try to pick one or
- * the other depending on the contents of the window.
- */
- public static final int SOFT_INPUT_ADJUST_PAN = 0x20;
-
- /**
- * Bit for {@link #softInputMode}: set when the user has navigated
- * forward to the window. This is normally set automatically for
- * you by the system, though you may want to set it in certain cases
- * when you are displaying a window yourself. This flag will always
- * be cleared automatically after the window is displayed.
- */
- public static final int SOFT_INPUT_IS_FORWARD_NAVIGATION = 0x100;
-
- /**
- * Desired operating mode for any soft input area. May any combination
- * of:
- *
- * <ul>
- * <li> One of the visibility states
- * {@link #SOFT_INPUT_STATE_UNSPECIFIED}, {@link #SOFT_INPUT_STATE_UNCHANGED},
- * {@link #SOFT_INPUT_STATE_HIDDEN}, {@link #SOFT_INPUT_STATE_ALWAYS_VISIBLE}, or
- * {@link #SOFT_INPUT_STATE_VISIBLE}.
- * <li> One of the adjustment options
- * {@link #SOFT_INPUT_ADJUST_UNSPECIFIED},
- * {@link #SOFT_INPUT_ADJUST_RESIZE}, or
- * {@link #SOFT_INPUT_ADJUST_PAN}.
- */
- public int softInputMode;
-
- /**
- * Placement of window within the screen as per {@link Gravity}
- *
- * @see Gravity
- */
- public int gravity;
-
- /**
- * The horizontal margin, as a percentage of the container's width,
- * between the container and the widget.
- */
- public float horizontalMargin;
-
- /**
- * The vertical margin, as a percentage of the container's height,
- * between the container and the widget.
- */
- public float verticalMargin;
-
- /**
- * The desired bitmap format. May be one of the constants in
- * {@link android.graphics.PixelFormat}. Default is OPAQUE.
- */
- public int format;
-
- /**
- * A style resource defining the animations to use for this window.
- * This must be a system resource; it can not be an application resource
- * because the window manager does not have access to applications.
- */
- public int windowAnimations;
-
- /**
- * An alpha value to apply to this entire window.
- * An alpha of 1.0 means fully opaque and 0.0 means fully transparent
- */
- public float alpha = 1.0f;
-
- /**
- * When {@link #FLAG_DIM_BEHIND} is set, this is the amount of dimming
- * to apply. Range is from 1.0 for completely opaque to 0.0 for no
- * dim.
- */
- public float dimAmount = 1.0f;
-
- /**
- * This can be used to override the user's preferred brightness of
- * the screen. A value of less than 0, the default, means to use the
- * preferred screen brightness. 0 to 1 adjusts the brightness from
- * dark to full bright.
- */
- public float screenBrightness = -1.0f;
-
- /**
- * Identifier for this window. This will usually be filled in for
- * you.
- */
- public IBinder token = null;
-
- /**
- * Name of the package owning this window.
- */
- public String packageName = null;
-
- /**
- * Specific orientation value for a window.
- * May be any of the same values allowed
- * for {@link android.content.pm.ActivityInfo#screenOrientation}.
- * If not set, a default value of
- * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}
- * will be used.
- */
- public int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-
-
- public LayoutParams() {
- super(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
- type = TYPE_APPLICATION;
- format = PixelFormat.OPAQUE;
- }
-
- public LayoutParams(int _type) {
- super(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
- type = _type;
- format = PixelFormat.OPAQUE;
- }
-
- public LayoutParams(int _type, int _flags) {
- super(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
- type = _type;
- flags = _flags;
- format = PixelFormat.OPAQUE;
- }
-
- public LayoutParams(int _type, int _flags, int _format) {
- super(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
- type = _type;
- flags = _flags;
- format = _format;
- }
-
- public LayoutParams(int w, int h, int _type, int _flags, int _format) {
- super(w, h);
- type = _type;
- flags = _flags;
- format = _format;
- }
-
- public LayoutParams(int w, int h, int xpos, int ypos, int _type,
- int _flags, int _format) {
- super(w, h);
- x = xpos;
- y = ypos;
- type = _type;
- flags = _flags;
- format = _format;
- }
-
- public final void setTitle(CharSequence title) {
- if (null == title)
- title = "";
-
- mTitle = TextUtils.stringOrSpannedString(title);
- }
-
- public final CharSequence getTitle() {
- return mTitle;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel out, int parcelableFlags) {
- out.writeInt(width);
- out.writeInt(height);
- out.writeInt(x);
- out.writeInt(y);
- out.writeInt(type);
- out.writeInt(memoryType);
- out.writeInt(flags);
- out.writeInt(softInputMode);
- out.writeInt(gravity);
- out.writeFloat(horizontalMargin);
- out.writeFloat(verticalMargin);
- out.writeInt(format);
- out.writeInt(windowAnimations);
- out.writeFloat(alpha);
- out.writeFloat(dimAmount);
- out.writeFloat(screenBrightness);
- out.writeStrongBinder(token);
- out.writeString(packageName);
- TextUtils.writeToParcel(mTitle, out, parcelableFlags);
- out.writeInt(screenOrientation);
- }
-
- public static final Parcelable.Creator<LayoutParams> CREATOR
- = new Parcelable.Creator<LayoutParams>() {
- public LayoutParams createFromParcel(Parcel in) {
- return new LayoutParams(in);
- }
-
- public LayoutParams[] newArray(int size) {
- return new LayoutParams[size];
- }
- };
-
-
- public LayoutParams(Parcel in) {
- width = in.readInt();
- height = in.readInt();
- x = in.readInt();
- y = in.readInt();
- type = in.readInt();
- memoryType = in.readInt();
- flags = in.readInt();
- softInputMode = in.readInt();
- gravity = in.readInt();
- horizontalMargin = in.readFloat();
- verticalMargin = in.readFloat();
- format = in.readInt();
- windowAnimations = in.readInt();
- alpha = in.readFloat();
- dimAmount = in.readFloat();
- screenBrightness = in.readFloat();
- token = in.readStrongBinder();
- packageName = in.readString();
- mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
- screenOrientation = in.readInt();
- }
-
- public static final int LAYOUT_CHANGED = 1<<0;
- public static final int TYPE_CHANGED = 1<<1;
- public static final int FLAGS_CHANGED = 1<<2;
- public static final int FORMAT_CHANGED = 1<<3;
- public static final int ANIMATION_CHANGED = 1<<4;
- public static final int DIM_AMOUNT_CHANGED = 1<<5;
- public static final int TITLE_CHANGED = 1<<6;
- public static final int ALPHA_CHANGED = 1<<7;
- public static final int MEMORY_TYPE_CHANGED = 1<<8;
- public static final int SOFT_INPUT_MODE_CHANGED = 1<<9;
- public static final int SCREEN_ORIENTATION_CHANGED = 1<<10;
- public static final int SCREEN_BRIGHTNESS_CHANGED = 1<<11;
-
- public final int copyFrom(LayoutParams o) {
- int changes = 0;
-
- if (width != o.width) {
- width = o.width;
- changes |= LAYOUT_CHANGED;
- }
- if (height != o.height) {
- height = o.height;
- changes |= LAYOUT_CHANGED;
- }
- if (x != o.x) {
- x = o.x;
- changes |= LAYOUT_CHANGED;
- }
- if (y != o.y) {
- y = o.y;
- changes |= LAYOUT_CHANGED;
- }
- if (horizontalWeight != o.horizontalWeight) {
- horizontalWeight = o.horizontalWeight;
- changes |= LAYOUT_CHANGED;
- }
- if (verticalWeight != o.verticalWeight) {
- verticalWeight = o.verticalWeight;
- changes |= LAYOUT_CHANGED;
- }
- if (horizontalMargin != o.horizontalMargin) {
- horizontalMargin = o.horizontalMargin;
- changes |= LAYOUT_CHANGED;
- }
- if (verticalMargin != o.verticalMargin) {
- verticalMargin = o.verticalMargin;
- changes |= LAYOUT_CHANGED;
- }
- if (type != o.type) {
- type = o.type;
- changes |= TYPE_CHANGED;
- }
- if (memoryType != o.memoryType) {
- memoryType = o.memoryType;
- changes |= MEMORY_TYPE_CHANGED;
- }
- if (flags != o.flags) {
- flags = o.flags;
- changes |= FLAGS_CHANGED;
- }
- if (softInputMode != o.softInputMode) {
- softInputMode = o.softInputMode;
- changes |= SOFT_INPUT_MODE_CHANGED;
- }
- if (gravity != o.gravity) {
- gravity = o.gravity;
- changes |= LAYOUT_CHANGED;
- }
- if (horizontalMargin != o.horizontalMargin) {
- horizontalMargin = o.horizontalMargin;
- changes |= LAYOUT_CHANGED;
- }
- if (verticalMargin != o.verticalMargin) {
- verticalMargin = o.verticalMargin;
- changes |= LAYOUT_CHANGED;
- }
- if (format != o.format) {
- format = o.format;
- changes |= FORMAT_CHANGED;
- }
- if (windowAnimations != o.windowAnimations) {
- windowAnimations = o.windowAnimations;
- changes |= ANIMATION_CHANGED;
- }
- if (token == null) {
- // NOTE: token only copied if the recipient doesn't
- // already have one.
- token = o.token;
- }
- if (packageName == null) {
- // NOTE: packageName only copied if the recipient doesn't
- // already have one.
- packageName = o.packageName;
- }
- if (!mTitle.equals(o.mTitle)) {
- mTitle = o.mTitle;
- changes |= TITLE_CHANGED;
- }
- if (alpha != o.alpha) {
- alpha = o.alpha;
- changes |= ALPHA_CHANGED;
- }
- if (dimAmount != o.dimAmount) {
- dimAmount = o.dimAmount;
- changes |= DIM_AMOUNT_CHANGED;
- }
- if (screenBrightness != o.screenBrightness) {
- screenBrightness = o.screenBrightness;
- changes |= SCREEN_BRIGHTNESS_CHANGED;
- }
-
- if (screenOrientation != o.screenOrientation) {
- screenOrientation = o.screenOrientation;
- changes |= SCREEN_ORIENTATION_CHANGED;
- }
- return changes;
- }
-
- @Override
- public String debug(String output) {
- output += "Contents of " + this + ":";
- Log.d("Debug", output);
- output = super.debug("");
- Log.d("Debug", output);
- Log.d("Debug", "");
- Log.d("Debug", "WindowManager.LayoutParams={title=" + mTitle + "}");
- return "";
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder(256);
- sb.append("WM.LayoutParams{");
- sb.append("(");
- sb.append(x);
- sb.append(',');
- sb.append(y);
- sb.append(")(");
- sb.append((width==FILL_PARENT?"fill":(width==WRAP_CONTENT?"wrap":width)));
- sb.append('x');
- sb.append((height==FILL_PARENT?"fill":(height==WRAP_CONTENT?"wrap":height)));
- sb.append(")");
- if (softInputMode != 0) {
- sb.append(" sim=#");
- sb.append(Integer.toHexString(softInputMode));
- }
- if (gravity != 0) {
- sb.append(" gr=#");
- sb.append(Integer.toHexString(gravity));
- }
- sb.append(" ty=");
- sb.append(type);
- sb.append(" fl=#");
- sb.append(Integer.toHexString(flags));
- sb.append(" fmt=");
- sb.append(format);
- if (windowAnimations != 0) {
- sb.append(" wanim=0x");
- sb.append(Integer.toHexString(windowAnimations));
- }
- if (screenOrientation != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
- sb.append(" or=");
- sb.append(screenOrientation);
- }
- sb.append('}');
- return sb.toString();
- }
-
- private CharSequence mTitle = "";
- }
-}
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
deleted file mode 100644
index 755d7b8..0000000
--- a/core/java/android/view/WindowManagerImpl.java
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.graphics.PixelFormat;
-import android.os.IBinder;
-import android.util.AndroidRuntimeException;
-import android.util.Config;
-import android.util.Log;
-import android.view.WindowManager;
-import android.view.inputmethod.InputMethodManager;
-
-final class WindowLeaked extends AndroidRuntimeException {
- public WindowLeaked(String msg) {
- super(msg);
- }
-}
-
-/**
- * Low-level communication with the global system window manager. It implements
- * the ViewManager interface, allowing you to add any View subclass as a
- * top-level window on the screen. Additional window manager specific layout
- * parameters are defined for control over how windows are displayed.
- * It also implemens the WindowManager interface, allowing you to control the
- * displays attached to the device.
- *
- * <p>Applications will not normally use WindowManager directly, instead relying
- * on the higher-level facilities in {@link android.app.Activity} and
- * {@link android.app.Dialog}.
- *
- * <p>Even for low-level window manager access, it is almost never correct to use
- * this class. For example, {@link android.app.Activity#getWindowManager}
- * provides a ViewManager for adding windows that are associated with that
- * activity -- the window manager will not normally allow you to add arbitrary
- * windows that are not associated with an activity.
- *
- * @hide
- */
-public class WindowManagerImpl implements WindowManager {
- /**
- * The user is navigating with keys (not the touch screen), so
- * navigational focus should be shown.
- */
- public static final int RELAYOUT_IN_TOUCH_MODE = 0x1;
- /**
- * This is the first time the window is being drawn,
- * so the client must call drawingFinished() when done
- */
- public static final int RELAYOUT_FIRST_TIME = 0x2;
-
- public static final int ADD_FLAG_APP_VISIBLE = 0x2;
- public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_IN_TOUCH_MODE;
-
- public static final int ADD_OKAY = 0;
- public static final int ADD_BAD_APP_TOKEN = -1;
- public static final int ADD_BAD_SUBWINDOW_TOKEN = -2;
- public static final int ADD_NOT_APP_TOKEN = -3;
- public static final int ADD_APP_EXITING = -4;
- public static final int ADD_DUPLICATE_ADD = -5;
- public static final int ADD_STARTING_NOT_NEEDED = -6;
- public static final int ADD_MULTIPLE_SINGLETON = -7;
- public static final int ADD_PERMISSION_DENIED = -8;
-
- public static WindowManagerImpl getDefault()
- {
- return mWindowManager;
- }
-
- public void addView(View view)
- {
- addView(view, new WindowManager.LayoutParams(
- WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.OPAQUE));
- }
-
- public void addView(View view, ViewGroup.LayoutParams params)
- {
- addView(view, params, false);
- }
-
- public void addViewNesting(View view, ViewGroup.LayoutParams params)
- {
- addView(view, params, false);
- }
-
- private void addView(View view, ViewGroup.LayoutParams params, boolean nest)
- {
- if (Config.LOGV) Log.v("WindowManager", "addView view=" + view);
-
- if (!(params instanceof WindowManager.LayoutParams)) {
- throw new IllegalArgumentException(
- "Params must be WindowManager.LayoutParams");
- }
-
- final WindowManager.LayoutParams wparams
- = (WindowManager.LayoutParams)params;
-
- ViewRoot root;
- View panelParentView = null;
-
- synchronized (this) {
- // Here's an odd/questionable case: if someone tries to add a
- // view multiple times, then we simply bump up a nesting count
- // and they need to remove the view the corresponding number of
- // times to have it actually removed from the window manager.
- // This is useful specifically for the notification manager,
- // which can continually add/remove the same view as a
- // notification gets updated.
- int index = findViewLocked(view, false);
- if (index >= 0) {
- if (!nest) {
- throw new IllegalStateException("View " + view
- + " has already been added to the window manager.");
- }
- root = mRoots[index];
- root.mAddNesting++;
- // Update layout parameters.
- view.setLayoutParams(wparams);
- root.setLayoutParams(wparams, true);
- return;
- }
-
- // If this is a panel window, then find the window it is being
- // attached to for future reference.
- if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
- wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
- final int count = mViews != null ? mViews.length : 0;
- for (int i=0; i<count; i++) {
- if (mRoots[i].mWindow.asBinder() == wparams.token) {
- panelParentView = mViews[i];
- }
- }
- }
-
- root = new ViewRoot(view.getContext());
- root.mAddNesting = 1;
-
- view.setLayoutParams(wparams);
-
- if (mViews == null) {
- index = 1;
- mViews = new View[1];
- mRoots = new ViewRoot[1];
- mParams = new WindowManager.LayoutParams[1];
- } else {
- index = mViews.length + 1;
- Object[] old = mViews;
- mViews = new View[index];
- System.arraycopy(old, 0, mViews, 0, index-1);
- old = mRoots;
- mRoots = new ViewRoot[index];
- System.arraycopy(old, 0, mRoots, 0, index-1);
- old = mParams;
- mParams = new WindowManager.LayoutParams[index];
- System.arraycopy(old, 0, mParams, 0, index-1);
- }
- index--;
-
- mViews[index] = view;
- mRoots[index] = root;
- mParams[index] = wparams;
- }
-
- // do this last because it fires off messages to start doing things
- root.setView(view, wparams, panelParentView);
- }
-
- public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
- if (!(params instanceof WindowManager.LayoutParams)) {
- throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
- }
-
- final WindowManager.LayoutParams wparams
- = (WindowManager.LayoutParams)params;
-
- view.setLayoutParams(wparams);
-
- synchronized (this) {
- int index = findViewLocked(view, true);
- ViewRoot root = mRoots[index];
- mParams[index] = wparams;
- root.setLayoutParams(wparams, false);
- }
- }
-
- public void removeView(View view) {
- synchronized (this) {
- int index = findViewLocked(view, true);
- View curView = removeViewLocked(index);
- if (curView == view) {
- return;
- }
-
- throw new IllegalStateException("Calling with view " + view
- + " but the ViewRoot is attached to " + curView);
- }
- }
-
- public void removeViewImmediate(View view) {
- synchronized (this) {
- int index = findViewLocked(view, true);
- ViewRoot root = mRoots[index];
- View curView = root.getView();
-
- root.mAddNesting = 0;
- root.die(true);
- finishRemoveViewLocked(curView, index);
- if (curView == view) {
- return;
- }
-
- throw new IllegalStateException("Calling with view " + view
- + " but the ViewRoot is attached to " + curView);
- }
- }
-
- View removeViewLocked(int index) {
- ViewRoot root = mRoots[index];
- View view = root.getView();
-
- // Don't really remove until we have matched all calls to add().
- root.mAddNesting--;
- if (root.mAddNesting > 0) {
- return view;
- }
-
- InputMethodManager imm = InputMethodManager.getInstance(view.getContext());
- if (imm != null) {
- imm.windowDismissed(mViews[index].getWindowToken());
- }
- root.die(false);
- finishRemoveViewLocked(view, index);
- return view;
- }
-
- void finishRemoveViewLocked(View view, int index) {
- final int count = mViews.length;
-
- // remove it from the list
- View[] tmpViews = new View[count-1];
- removeItem(tmpViews, mViews, index);
- mViews = tmpViews;
-
- ViewRoot[] tmpRoots = new ViewRoot[count-1];
- removeItem(tmpRoots, mRoots, index);
- mRoots = tmpRoots;
-
- WindowManager.LayoutParams[] tmpParams
- = new WindowManager.LayoutParams[count-1];
- removeItem(tmpParams, mParams, index);
- mParams = tmpParams;
-
- view.assignParent(null);
- // func doesn't allow null... does it matter if we clear them?
- //view.setLayoutParams(null);
- }
-
- public void closeAll(IBinder token, String who, String what) {
- synchronized (this) {
- if (mViews == null)
- return;
-
- int count = mViews.length;
- //Log.i("foo", "Closing all windows of " + token);
- for (int i=0; i<count; i++) {
- //Log.i("foo", "@ " + i + " token " + mParams[i].token
- // + " view " + mRoots[i].getView());
- if (token == null || mParams[i].token == token) {
- ViewRoot root = mRoots[i];
- root.mAddNesting = 1;
-
- //Log.i("foo", "Force closing " + root);
- if (who != null) {
- WindowLeaked leak = new WindowLeaked(
- what + " " + who + " has leaked window "
- + root.getView() + " that was originally added here");
- leak.setStackTrace(root.getLocation().getStackTrace());
- Log.e("WindowManager", leak.getMessage(), leak);
- }
-
- removeViewLocked(i);
- i--;
- count--;
- }
- }
- }
- }
-
- public WindowManager.LayoutParams getRootViewLayoutParameter(View view) {
- ViewParent vp = view.getParent();
- while (vp != null && !(vp instanceof ViewRoot)) {
- vp = vp.getParent();
- }
-
- if (vp == null) return null;
-
- ViewRoot vr = (ViewRoot)vp;
-
- int N = mRoots.length;
- for (int i = 0; i < N; ++i) {
- if (mRoots[i] == vr) {
- return mParams[i];
- }
- }
-
- return null;
- }
-
- public void closeAll() {
- closeAll(null, null, null);
- }
-
- public Display getDefaultDisplay() {
- return new Display(Display.DEFAULT_DISPLAY);
- }
-
- private View[] mViews;
- private ViewRoot[] mRoots;
- private WindowManager.LayoutParams[] mParams;
-
- private static void removeItem(Object[] dst, Object[] src, int index)
- {
- if (dst.length > 0) {
- if (index > 0) {
- System.arraycopy(src, 0, dst, 0, index);
- }
- if (index < dst.length) {
- System.arraycopy(src, index+1, dst, index, src.length-index-1);
- }
- }
- }
-
- private int findViewLocked(View view, boolean required)
- {
- synchronized (this) {
- final int count = mViews != null ? mViews.length : 0;
- for (int i=0; i<count; i++) {
- if (mViews[i] == view) {
- return i;
- }
- }
- if (required) {
- throw new IllegalArgumentException(
- "View not attached to window manager");
- }
- return -1;
- }
- }
-
- private static WindowManagerImpl mWindowManager = new WindowManagerImpl();
-}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
deleted file mode 100644
index 0f15b17..0000000
--- a/core/java/android/view/WindowManagerPolicy.java
+++ /dev/null
@@ -1,796 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.os.IBinder;
-import android.os.LocalPowerManager;
-import android.view.animation.Animation;
-
-/**
- * This interface supplies all UI-specific behavior of the window manager. An
- * instance of it is created by the window manager when it starts up, and allows
- * customization of window layering, special window types, key dispatching, and
- * layout.
- *
- * <p>Because this provides deep interaction with the system window manager,
- * specific methods on this interface can be called from a variety of contexts
- * with various restrictions on what they can do. These are encoded through
- * a suffixes at the end of a method encoding the thread the method is called
- * from and any locks that are held when it is being called; if no suffix
- * is attached to a method, then it is not called with any locks and may be
- * called from the main window manager thread or another thread calling into
- * the window manager.
- *
- * <p>The current suffixes are:
- *
- * <dl>
- * <dt> Ti <dd> Called from the input thread. This is the thread that
- * collects pending input events and dispatches them to the appropriate window.
- * It may block waiting for events to be processed, so that the input stream is
- * properly serialized.
- * <dt> Tq <dd> Called from the low-level input queue thread. This is the
- * thread that reads events out of the raw input devices and places them
- * into the global input queue that is read by the <var>Ti</var> thread.
- * This thread should not block for a long period of time on anything but the
- * key driver.
- * <dt> Lw <dd> Called with the main window manager lock held. Because the
- * window manager is a very low-level system service, there are few other
- * system services you can call with this lock held. It is explicitly okay to
- * make calls into the package manager and power manager; it is explicitly not
- * okay to make calls into the activity manager. Note that
- * {@link android.content.Context#checkPermission(String, int, int)} and
- * variations require calling into the activity manager.
- * <dt> Li <dd> Called with the input thread lock held. This lock can be
- * acquired by the window manager while it holds the window lock, so this is
- * even more restrictive than <var>Lw</var>.
- * </dl>
- *
- * @hide
- */
-public interface WindowManagerPolicy {
- public final static int FLAG_WAKE = 0x00000001;
- public final static int FLAG_WAKE_DROPPED = 0x00000002;
- public final static int FLAG_SHIFT = 0x00000004;
- public final static int FLAG_CAPS_LOCK = 0x00000008;
- public final static int FLAG_ALT = 0x00000010;
- public final static int FLAG_ALT_GR = 0x00000020;
- public final static int FLAG_MENU = 0x00000040;
- public final static int FLAG_LAUNCHER = 0x00000080;
-
- public final static int FLAG_WOKE_HERE = 0x10000000;
- public final static int FLAG_BRIGHT_HERE = 0x20000000;
-
- public final static boolean WATCH_POINTER = false;
-
- // flags for interceptKeyTq
- /**
- * Pass this event to the user / app. To be returned from {@link #interceptKeyTq}.
- */
- public final static int ACTION_PASS_TO_USER = 0x00000001;
-
- /**
- * This key event should extend the user activity timeout and turn the lights on.
- * To be returned from {@link #interceptKeyTq}. Do not return this and
- * {@link #ACTION_GO_TO_SLEEP} or {@link #ACTION_PASS_TO_USER}.
- */
- public final static int ACTION_POKE_USER_ACTIVITY = 0x00000002;
-
- /**
- * This key event should put the device to sleep (and engage keyguard if necessary)
- * To be returned from {@link #interceptKeyTq}. Do not return this and
- * {@link #ACTION_POKE_USER_ACTIVITY} or {@link #ACTION_PASS_TO_USER}.
- */
- public final static int ACTION_GO_TO_SLEEP = 0x00000004;
-
- /**
- * Interface to the Window Manager state associated with a particular
- * window. You can hold on to an instance of this interface from the call
- * to prepareAddWindow() until removeWindow().
- */
- public interface WindowState {
- /**
- * Perform standard frame computation. The result can be obtained with
- * getFrame() if so desired. Must be called with the window manager
- * lock held.
- *
- * @param parentFrame The frame of the parent container this window
- * is in, used for computing its basic position.
- * @param displayFrame The frame of the overall display in which this
- * window can appear, used for constraining the overall dimensions
- * of the window.
- * @param contentFrame The frame within the display in which we would
- * like active content to appear. This will cause windows behind to
- * be resized to match the given content frame.
- * @param visibleFrame The frame within the display that the window
- * is actually visible, used for computing its visible insets to be
- * given to windows behind.
- * This can be used as a hint for scrolling (avoiding resizing)
- * the window to make certain that parts of its content
- * are visible.
- */
- public void computeFrameLw(Rect parentFrame, Rect displayFrame,
- Rect contentFrame, Rect visibleFrame);
-
- /**
- * Retrieve the current frame of the window that has been assigned by
- * the window manager. Must be called with the window manager lock held.
- *
- * @return Rect The rectangle holding the window frame.
- */
- public Rect getFrameLw();
-
- /**
- * Retrieve the current frame of the window that is actually shown.
- * Must be called with the window manager lock held.
- *
- * @return Rect The rectangle holding the shown window frame.
- */
- public Rect getShownFrameLw();
-
- /**
- * Retrieve the frame of the display that this window was last
- * laid out in. Must be called with the
- * window manager lock held.
- *
- * @return Rect The rectangle holding the display frame.
- */
- public Rect getDisplayFrameLw();
-
- /**
- * Retrieve the frame of the content area that this window was last
- * laid out in. This is the area in which the content of the window
- * should be placed. It will be smaller than the display frame to
- * account for screen decorations such as a status bar or soft
- * keyboard. Must be called with the
- * window manager lock held.
- *
- * @return Rect The rectangle holding the content frame.
- */
- public Rect getContentFrameLw();
-
- /**
- * Retrieve the frame of the visible area that this window was last
- * laid out in. This is the area of the screen in which the window
- * will actually be fully visible. It will be smaller than the
- * content frame to account for transient UI elements blocking it
- * such as an input method's candidates UI. Must be called with the
- * window manager lock held.
- *
- * @return Rect The rectangle holding the visible frame.
- */
- public Rect getVisibleFrameLw();
-
- /**
- * Returns true if this window is waiting to receive its given
- * internal insets from the client app, and so should not impact the
- * layout of other windows.
- */
- public boolean getGivenInsetsPendingLw();
-
- /**
- * Retrieve the insets given by this window's client for the content
- * area of windows behind it. Must be called with the
- * window manager lock held.
- *
- * @return Rect The left, top, right, and bottom insets, relative
- * to the window's frame, of the actual contents.
- */
- public Rect getGivenContentInsetsLw();
-
- /**
- * Retrieve the insets given by this window's client for the visible
- * area of windows behind it. Must be called with the
- * window manager lock held.
- *
- * @return Rect The left, top, right, and bottom insets, relative
- * to the window's frame, of the actual visible area.
- */
- public Rect getGivenVisibleInsetsLw();
-
- /**
- * Retrieve the current LayoutParams of the window.
- *
- * @return WindowManager.LayoutParams The window's internal LayoutParams
- * instance.
- */
- public WindowManager.LayoutParams getAttrs();
-
- /**
- * Get the layer at which this window's surface will be Z-ordered.
- */
- public int getSurfaceLayer();
-
- /**
- * Return the token for the application (actually activity) that owns
- * this window. May return null for system windows.
- *
- * @return An IApplicationToken identifying the owning activity.
- */
- public IApplicationToken getAppToken();
-
- /**
- * Return true if, at any point, the application token associated with
- * this window has actually displayed any windows. This is most useful
- * with the "starting up" window to determine if any windows were
- * displayed when it is closed.
- *
- * @return Returns true if one or more windows have been displayed,
- * else false.
- */
- public boolean hasAppShownWindows();
-
- /**
- * Return true if the application token has been asked to display an
- * app starting icon as the application is starting up.
- *
- * @return Returns true if setAppStartingIcon() was called for this
- * window's token.
- */
- public boolean hasAppStartingIcon();
-
- /**
- * Return the Window that is being displayed as this window's
- * application token is being started.
- *
- * @return Returns the currently displayed starting window, or null if
- * it was not requested, has not yet been displayed, or has
- * been removed.
- */
- public WindowState getAppStartingWindow();
-
- /**
- * Is this window visible? It is not visible if there is no
- * surface, or we are in the process of running an exit animation
- * that will remove the surface.
- */
- boolean isVisibleLw();
-
- /**
- * Is this window currently visible to the user on-screen? It is
- * displayed either if it is visible or it is currently running an
- * animation before no longer being visible. Must be called with the
- * window manager lock held.
- */
- boolean isDisplayedLw();
-
- /**
- * Returns true if the window is both full screen and opaque. Must be
- * called with the window manager lock held.
- *
- * @param width The width of the screen
- * @param height The height of the screen
- * @param shownFrame If true, this is based on the actual shown frame of
- * the window (taking into account animations); if
- * false, this is based on the currently requested
- * frame, which any current animation will be moving
- * towards.
- * @param onlyOpaque If true, this will only pass if the window is
- * also opaque.
- * @return Returns true if the window is both full screen and opaque
- */
- public boolean fillsScreenLw(int width, int height, boolean shownFrame,
- boolean onlyOpaque);
-
- /**
- * Returns true if this window has been shown on screen at some time in
- * the past. Must be called with the window manager lock held.
- *
- * @return boolean
- */
- public boolean hasDrawnLw();
-
- /**
- * Can be called by the policy to force a window to be hidden,
- * regardless of whether the client or window manager would like
- * it shown. Must be called with the window manager lock held.
- * Returns true if {@link #showLw} was last called for the window.
- */
- public boolean hideLw(boolean doAnimation);
-
- /**
- * Can be called to undo the effect of {@link #hideLw}, allowing a
- * window to be shown as long as the window manager and client would
- * also like it to be shown. Must be called with the window manager
- * lock held.
- * Returns true if {@link #hideLw} was last called for the window.
- */
- public boolean showLw(boolean doAnimation);
- }
-
- /** No transition happening. */
- public final int TRANSIT_NONE = 0;
- /** Window has been added to the screen. */
- public final int TRANSIT_ENTER = 1;
- /** Window has been removed from the screen. */
- public final int TRANSIT_EXIT = 2;
- /** Window has been made visible. */
- public final int TRANSIT_SHOW = 3;
- /** Window has been made invisible. */
- public final int TRANSIT_HIDE = 4;
- /** The "application starting" preview window is no longer needed, and will
- * animate away to show the real window. */
- public final int TRANSIT_PREVIEW_DONE = 5;
- /** A window in a new activity is being opened on top of an existing one
- * in the same task. */
- public final int TRANSIT_ACTIVITY_OPEN = 6;
- /** The window in the top-most activity is being closed to reveal the
- * previous activity in the same task. */
- public final int TRANSIT_ACTIVITY_CLOSE = 7;
- /** A window in a new task is being opened on top of an existing one
- * in another activity's task. */
- public final int TRANSIT_TASK_OPEN = 8;
- /** A window in the top-most activity is being closed to reveal the
- * previous activity in a different task. */
- public final int TRANSIT_TASK_CLOSE = 9;
- /** A window in an existing task is being displayed on top of an existing one
- * in another activity's task. */
- public final int TRANSIT_TASK_TO_FRONT = 10;
- /** A window in an existing task is being put below all other tasks. */
- public final int TRANSIT_TASK_TO_BACK = 11;
-
- /** Screen turned off because of power button */
- public final int OFF_BECAUSE_OF_USER = 1;
- /** Screen turned off because of timeout */
- public final int OFF_BECAUSE_OF_TIMEOUT = 2;
-
- /**
- * Magic constant to {@link IWindowManager#setRotation} to not actually
- * modify the rotation.
- */
- public final int USE_LAST_ROTATION = -1000;
-
- /**
- * Perform initialization of the policy.
- *
- * @param context The system context we are running in.
- * @param powerManager
- */
- public void init(Context context, IWindowManager windowManager,
- LocalPowerManager powerManager);
-
- /**
- * Check permissions when adding a window.
- *
- * @param attrs The window's LayoutParams.
- *
- * @return {@link WindowManagerImpl#ADD_OKAY} if the add can proceed;
- * else an error code, usually
- * {@link WindowManagerImpl#ADD_PERMISSION_DENIED}, to abort the add.
- */
- public int checkAddPermission(WindowManager.LayoutParams attrs);
-
- /**
- * Sanitize the layout parameters coming from a client. Allows the policy
- * to do things like ensure that windows of a specific type can't take
- * input focus.
- *
- * @param attrs The window layout parameters to be modified. These values
- * are modified in-place.
- */
- public void adjustWindowParamsLw(WindowManager.LayoutParams attrs);
-
- /**
- * After the window manager has computed the current configuration based
- * on its knowledge of the display and input devices, it gives the policy
- * a chance to adjust the information contained in it. If you want to
- * leave it as-is, simply do nothing.
- *
- * <p>This method may be called by any thread in the window manager, but
- * no internal locks in the window manager will be held.
- *
- * @param config The Configuration being computed, for you to change as
- * desired.
- */
- public void adjustConfigurationLw(Configuration config);
-
- /**
- * Assign a window type to a layer. Allows you to control how different
- * kinds of windows are ordered on-screen.
- *
- * @param type The type of window being assigned.
- *
- * @return int An arbitrary integer used to order windows, with lower
- * numbers below higher ones.
- */
- public int windowTypeToLayerLw(int type);
-
- /**
- * Return how to Z-order sub-windows in relation to the window they are
- * attached to. Return positive to have them ordered in front, negative for
- * behind.
- *
- * @param type The sub-window type code.
- *
- * @return int Layer in relation to the attached window, where positive is
- * above and negative is below.
- */
- public int subWindowTypeToLayerLw(int type);
-
- /**
- * Called when the system would like to show a UI to indicate that an
- * application is starting. You can use this to add a
- * APPLICATION_STARTING_TYPE window with the given appToken to the window
- * manager (using the normal window manager APIs) that will be shown until
- * the application displays its own window. This is called without the
- * window manager locked so that you can call back into it.
- *
- * @param appToken Token of the application being started.
- * @param packageName The name of the application package being started.
- * @param theme Resource defining the application's overall visual theme.
- * @param nonLocalizedLabel The default title label of the application if
- * no data is found in the resource.
- * @param labelRes The resource ID the application would like to use as its name.
- * @param icon The resource ID the application would like to use as its icon.
- *
- * @return Optionally you can return the View that was used to create the
- * window, for easy removal in removeStartingWindow.
- *
- * @see #removeStartingWindow
- */
- public View addStartingWindow(IBinder appToken, String packageName,
- int theme, CharSequence nonLocalizedLabel,
- int labelRes, int icon);
-
- /**
- * Called when the first window of an application has been displayed, while
- * {@link #addStartingWindow} has created a temporary initial window for
- * that application. You should at this point remove the window from the
- * window manager. This is called without the window manager locked so
- * that you can call back into it.
- *
- * <p>Note: due to the nature of these functions not being called with the
- * window manager locked, you must be prepared for this function to be
- * called multiple times and/or an initial time with a null View window
- * even if you previously returned one.
- *
- * @param appToken Token of the application that has started.
- * @param window Window View that was returned by createStartingWindow.
- *
- * @see #addStartingWindow
- */
- public void removeStartingWindow(IBinder appToken, View window);
-
- /**
- * Prepare for a window being added to the window manager. You can throw an
- * exception here to prevent the window being added, or do whatever setup
- * you need to keep track of the window.
- *
- * @param win The window being added.
- * @param attrs The window's LayoutParams.
- *
- * @return {@link WindowManagerImpl#ADD_OKAY} if the add can proceed, else an
- * error code to abort the add.
- */
- public int prepareAddWindowLw(WindowState win,
- WindowManager.LayoutParams attrs);
-
- /**
- * Called when a window is being removed from a window manager. Must not
- * throw an exception -- clean up as much as possible.
- *
- * @param win The window being removed.
- */
- public void removeWindowLw(WindowState win);
-
- /**
- * Control the animation to run when a window's state changes. Return a
- * non-0 number to force the animation to a specific resource ID, or 0
- * to use the default animation.
- *
- * @param win The window that is changing.
- * @param transit What is happening to the window: {@link #TRANSIT_ENTER},
- * {@link #TRANSIT_EXIT}, {@link #TRANSIT_SHOW}, or
- * {@link #TRANSIT_HIDE}.
- *
- * @return Resource ID of the actual animation to use, or 0 for none.
- */
- public int selectAnimationLw(WindowState win, int transit);
-
- /**
- * Called from the key queue thread before a key is dispatched to the
- * input thread.
- *
- * <p>There are some actions that need to be handled here because they
- * affect the power state of the device, for example, the power keys.
- * Generally, it's best to keep as little as possible in the queue thread
- * because it's the most fragile.
- *
- * @param event the raw input event as read from the driver
- * @param screenIsOn true if the screen is already on
- * @return The bitwise or of the {@link #ACTION_PASS_TO_USER},
- * {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags.
- */
- public int interceptKeyTq(RawInputEvent event, boolean screenIsOn);
-
- /**
- * Called from the input thread before a key is dispatched to a window.
- *
- * <p>Allows you to define
- * behavior for keys that can not be overridden by applications or redirect
- * key events to a different window. This method is called from the
- * input thread, with no locks held.
- *
- * <p>Note that if you change the window a key is dispatched to, the new
- * target window will receive the key event without having input focus.
- *
- * @param win The window that currently has focus. This is where the key
- * event will normally go.
- * @param code Key code.
- * @param metaKeys TODO
- * @param down Is this a key press (true) or release (false)?
- * @param repeatCount Number of times a key down has repeated.
- * @return Returns true if the policy consumed the event and it should
- * not be further dispatched.
- */
- public boolean interceptKeyTi(WindowState win, int code,
- int metaKeys, boolean down, int repeatCount);
-
- /**
- * Called when layout of the windows is about to start.
- *
- * @param displayWidth The current full width of the screen.
- * @param displayHeight The current full height of the screen.
- */
- public void beginLayoutLw(int displayWidth, int displayHeight);
-
- /**
- * Called for each window attached to the window manager as layout is
- * proceeding. The implementation of this function must take care of
- * setting the window's frame, either here or in finishLayout().
- *
- * @param win The window being positioned.
- * @param attrs The LayoutParams of the window.
- * @param attached For sub-windows, the window it is attached to; this
- * window will already have had layoutWindow() called on it
- * so you can use its Rect. Otherwise null.
- */
- public void layoutWindowLw(WindowState win,
- WindowManager.LayoutParams attrs, WindowState attached);
-
-
- /**
- * Return the insets for the areas covered by system windows. These values
- * are computed on the most recent layout, so they are not guaranteed to
- * be correct.
- *
- * @param attrs The LayoutParams of the window.
- * @param contentInset The areas covered by system windows, expressed as positive insets
- *
- */
- public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset);
-
- /**
- * Called when layout of the windows is finished. After this function has
- * returned, all windows given to layoutWindow() <em>must</em> have had a
- * frame assigned.
- */
- public void finishLayoutLw();
-
- /**
- * Called when animation of the windows is about to start.
- *
- * @param displayWidth The current full width of the screen.
- * @param displayHeight The current full height of the screen.
- */
- public void beginAnimationLw(int displayWidth, int displayHeight);
-
- /**
- * Called each time a window is animating.
- *
- * @param win The window being positioned.
- * @param attrs The LayoutParams of the window.
- */
- public void animatingWindowLw(WindowState win,
- WindowManager.LayoutParams attrs);
-
- /**
- * Called when animation of the windows is finished. If in this function you do
- * something that may have modified the animation state of another window,
- * be sure to return true in order to perform another animation frame.
- *
- * @return Return true if animation state may have changed (so that another
- * frame of animation will be run).
- */
- public boolean finishAnimationLw();
-
- /**
- * Called after the screen turns off.
- *
- * @param why {@link #OFF_BECAUSE_OF_USER} or
- * {@link #OFF_BECAUSE_OF_TIMEOUT}.
- */
- public void screenTurnedOff(int why);
-
- /**
- * Called after the screen turns on.
- */
- public void screenTurnedOn();
-
- /**
- * Perform any initial processing of a low-level input event before the
- * window manager handles special keys and generates a high-level event
- * that is dispatched to the application.
- *
- * @param event The input event that has occurred.
- *
- * @return Return true if you have consumed the event and do not want
- * further processing to occur; return false for normal processing.
- */
- public boolean preprocessInputEventTq(RawInputEvent event);
-
- /**
- * Determine whether a given key code is used to cause an app switch
- * to occur (most often the HOME key, also often ENDCALL). If you return
- * true, then the system will go into a special key processing state
- * where it drops any pending events that it cans and adjusts timeouts to
- * try to get to this key as quickly as possible.
- *
- * <p>Note that this function is called from the low-level input queue
- * thread, with either/or the window or input lock held; be very careful
- * about what you do here. You absolutely should never acquire a lock
- * that you would ever hold elsewhere while calling out into the window
- * manager or view hierarchy.
- *
- * @param keycode The key that should be checked for performing an
- * app switch before delivering to the application.
- *
- * @return Return true if this is an app switch key and special processing
- * should happen; return false for normal processing.
- */
- public boolean isAppSwitchKeyTqTiLwLi(int keycode);
-
- /**
- * Determine whether a given key code is used for movement within a UI,
- * and does not generally cause actions to be performed (normally the DPAD
- * movement keys, NOT the DPAD center press key). This is called
- * when {@link #isAppSwitchKeyTiLi} returns true to remove any pending events
- * in the key queue that are not needed to switch applications.
- *
- * <p>Note that this function is called from the low-level input queue
- * thread; be very careful about what you do here.
- *
- * @param keycode The key that is waiting to be delivered to the
- * application.
- *
- * @return Return true if this is a purely navigation key and can be
- * dropped without negative consequences; return false to keep it.
- */
- public boolean isMovementKeyTi(int keycode);
-
- /**
- * Given the current state of the world, should this relative movement
- * wake up the device?
- *
- * @param device The device the movement came from.
- * @param classes The input classes associated with the device.
- * @param event The input event that occurred.
- * @return
- */
- public boolean isWakeRelMovementTq(int device, int classes,
- RawInputEvent event);
-
- /**
- * Given the current state of the world, should this absolute movement
- * wake up the device?
- *
- * @param device The device the movement came from.
- * @param classes The input classes associated with the device.
- * @param event The input event that occurred.
- * @return
- */
- public boolean isWakeAbsMovementTq(int device, int classes,
- RawInputEvent event);
-
- /**
- * Tell the policy if anyone is requesting that keyguard not come on.
- *
- * @param enabled Whether keyguard can be on or not. does not actually
- * turn it on, unless it was previously disabled with this function.
- *
- * @see android.app.KeyguardManager.KeyguardLock#disableKeyguard()
- * @see android.app.KeyguardManager.KeyguardLock#reenableKeyguard()
- */
- public void enableKeyguard(boolean enabled);
-
- /**
- * Callback used by {@link WindowManagerPolicy#exitKeyguardSecurely}
- */
- interface OnKeyguardExitResult {
- void onKeyguardExitResult(boolean success);
- }
-
- /**
- * Tell the policy if anyone is requesting the keyguard to exit securely
- * (this would be called after the keyguard was disabled)
- * @param callback Callback to send the result back.
- * @see android.app.KeyguardManager#exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult)
- */
- void exitKeyguardSecurely(OnKeyguardExitResult callback);
-
- /**
- * Return if keyguard is currently showing.
- */
- public boolean keyguardIsShowingTq();
-
- /**
- * inKeyguardRestrictedKeyInputMode
- *
- * if keyguard screen is showing or in restricted key input mode (i.e. in
- * keyguard password emergency screen). When in such mode, certain keys,
- * such as the Home key and the right soft keys, don't work.
- *
- * @return true if in keyguard restricted input mode.
- */
- public boolean inKeyguardRestrictedKeyInputMode();
-
- /**
- * Given an orientation constant
- * ({@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE
- * ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE} or
- * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_PORTRAIT
- * ActivityInfo.SCREEN_ORIENTATION_PORTRAIT}), return a surface
- * rotation.
- */
- public int rotationForOrientation(int orientation, int lastRotation,
- boolean displayEnabled);
-
- /**
- * Called when the system is mostly done booting to dentermine whether
- * the system should go into safe mode.
- */
- public boolean detectSafeMode();
-
- /**
- * Called when the system is mostly done booting.
- */
- public void systemReady();
-
- /**
- * Called when we have finished booting and can now display the home
- * screen to the user. This wilWl happen after systemReady(), and at
- * this point the display is active.
- */
- public void enableScreenAfterBoot();
-
- /**
- * Returns true if the user's cheek has been pressed against the phone. This is
- * determined by comparing the event's size attribute with a threshold value.
- * For example for a motion event like down or up or move, if the size exceeds
- * the threshold, it is considered as cheek press.
- * @param ev the motion event generated when the cheek is pressed
- * against the phone
- * @return Returns true if the user's cheek has been pressed against the phone
- * screen resulting in an invalid motion event
- */
- public boolean isCheekPressedAgainstScreen(MotionEvent ev);
-
- public void setCurrentOrientation(int newOrientation);
-
- /**
- * Call from application to perform haptic feedback on its window.
- */
- public boolean performHapticFeedback(WindowState win, int effectId, boolean always);
-
- /**
- * Called when we have stopped keeping the screen on because a window
- * requesting this is no longer visible.
- */
- public void screenOnStopped();
-}
diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java
deleted file mode 100755
index 5877932..0000000
--- a/core/java/android/view/WindowOrientationListener.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.content.Context;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.util.Config;
-import android.util.Log;
-
-/**
- * A special helper class used by the WindowManager
- * for receiving notifications from the SensorManager when
- * the orientation of the device has changed.
- * @hide
- */
-public abstract class WindowOrientationListener {
- private static final String TAG = "WindowOrientationListener";
- private static final boolean DEBUG = false;
- private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
- private int mOrientation = ORIENTATION_UNKNOWN;
- private SensorManager mSensorManager;
- private boolean mEnabled = false;
- private int mRate;
- private Sensor mSensor;
- private SensorEventListener mSensorEventListener;
-
- /**
- * Returned from onOrientationChanged when the device orientation cannot be determined
- * (typically when the device is in a close to flat position).
- *
- * @see #onOrientationChanged
- */
- public static final int ORIENTATION_UNKNOWN = -1;
- /*
- * Returned when the device is almost lying flat on a surface
- */
- public static final int ORIENTATION_FLAT = -2;
-
- /**
- * Creates a new WindowOrientationListener.
- *
- * @param context for the WindowOrientationListener.
- */
- public WindowOrientationListener(Context context) {
- this(context, SensorManager.SENSOR_DELAY_NORMAL);
- }
-
- /**
- * Creates a new WindowOrientationListener.
- *
- * @param context for the WindowOrientationListener.
- * @param rate at which sensor events are processed (see also
- * {@link android.hardware.SensorManager SensorManager}). Use the default
- * value of {@link android.hardware.SensorManager#SENSOR_DELAY_NORMAL
- * SENSOR_DELAY_NORMAL} for simple screen orientation change detection.
- */
- public WindowOrientationListener(Context context, int rate) {
- mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
- mRate = rate;
- mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- if (mSensor != null) {
- // Create listener only if sensors do exist
- mSensorEventListener = new SensorEventListenerImpl();
- }
- }
-
- /**
- * Enables the WindowOrientationListener so it will monitor the sensor and call
- * {@link #onOrientationChanged} when the device orientation changes.
- */
- public void enable() {
- if (mSensor == null) {
- Log.w(TAG, "Cannot detect sensors. Not enabled");
- return;
- }
- if (mEnabled == false) {
- if (localLOGV) Log.d(TAG, "WindowOrientationListener enabled");
- mSensorManager.registerListener(mSensorEventListener, mSensor, mRate);
- mEnabled = true;
- }
- }
-
- /**
- * Disables the WindowOrientationListener.
- */
- public void disable() {
- if (mSensor == null) {
- Log.w(TAG, "Cannot detect sensors. Invalid disable");
- return;
- }
- if (mEnabled == true) {
- if (localLOGV) Log.d(TAG, "WindowOrientationListener disabled");
- mSensorManager.unregisterListener(mSensorEventListener);
- mEnabled = false;
- }
- }
-
- class SensorEventListenerImpl implements SensorEventListener {
- private static final int _DATA_X = 0;
- private static final int _DATA_Y = 1;
- private static final int _DATA_Z = 2;
-
- public void onSensorChanged(SensorEvent event) {
- float[] values = event.values;
- int orientation = ORIENTATION_UNKNOWN;
- float X = values[_DATA_X];
- float Y = values[_DATA_Y];
- float Z = values[_DATA_Z];
- float OneEightyOverPi = 57.29577957855f;
- float gravity = (float) Math.sqrt(X*X+Y*Y+Z*Z);
- float zyangle = Math.abs((float)Math.asin(Z/gravity)*OneEightyOverPi);
- // The device is considered flat if the angle is more than 75
- // if the angle is less than 40, its considered too flat to switch
- // orientation. if the angle is between 40 - 75, the orientation is unknown
- if (zyangle < 40) {
- // Check orientation only if the phone is flat enough
- // Don't trust the angle if the magnitude is small compared to the y value
- float angle = (float)Math.atan2(Y, -X) * OneEightyOverPi;
- orientation = 90 - (int)Math.round(angle);
- // normalize to 0 - 359 range
- while (orientation >= 360) {
- orientation -= 360;
- }
- while (orientation < 0) {
- orientation += 360;
- }
- } else if (zyangle >= 75){
- orientation = ORIENTATION_FLAT;
- }
-
- if (orientation != mOrientation) {
- mOrientation = orientation;
- onOrientationChanged(orientation);
- }
- }
-
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
-
- }
- }
-
- /*
- * Returns true if sensor is enabled and false otherwise
- */
- public boolean canDetectOrientation() {
- return mSensor != null;
- }
-
- /**
- * Called when the orientation of the device has changed.
- * orientation parameter is in degrees, ranging from 0 to 359.
- * orientation is 0 degrees when the device is oriented in its natural position,
- * 90 degrees when its left side is at the top, 180 degrees when it is upside down,
- * and 270 degrees when its right side is to the top.
- * {@link #ORIENTATION_UNKNOWN} is returned when the device is close to flat
- * and the orientation cannot be determined.
- *
- * @param orientation The new orientation of the device.
- *
- * @see #ORIENTATION_UNKNOWN
- */
- abstract public void onOrientationChanged(int orientation);
-}
diff --git a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java b/core/java/android/view/animation/AccelerateDecelerateInterpolator.java
deleted file mode 100644
index fdb6f9d..0000000
--- a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-/**
- * An interpolator where the rate of change starts and ends slowly but
- * accelerates through the middle.
- *
- */
-public class AccelerateDecelerateInterpolator implements Interpolator {
- public AccelerateDecelerateInterpolator() {
- }
-
- public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {
- }
-
- public float getInterpolation(float input) {
- return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
- }
-}
diff --git a/core/java/android/view/animation/AccelerateInterpolator.java b/core/java/android/view/animation/AccelerateInterpolator.java
deleted file mode 100644
index b9e293f..0000000
--- a/core/java/android/view/animation/AccelerateInterpolator.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-
-/**
- * An interpolator where the rate of change starts out slowly and
- * and then accelerates.
- *
- */
-public class AccelerateInterpolator implements Interpolator {
- public AccelerateInterpolator() {
- }
-
- /**
- * Constructor
- *
- * @param factor Degree to which the animation should be eased. Seting
- * factor to 1.0f produces a y=x^2 parabola. Increasing factor above
- * 1.0f exaggerates the ease-in effect (i.e., it starts even
- * slower and ends evens faster)
- */
- public AccelerateInterpolator(float factor) {
- mFactor = factor;
- }
-
- public AccelerateInterpolator(Context context, AttributeSet attrs) {
- TypedArray a =
- context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AccelerateInterpolator);
-
- mFactor = a.getFloat(com.android.internal.R.styleable.AccelerateInterpolator_factor, 1.0f);
-
- a.recycle();
- }
-
- public float getInterpolation(float input) {
- if (mFactor == 1.0f) {
- return (float)(input * input);
- } else {
- return (float)Math.pow(input, 2 * mFactor);
- }
- }
-
- private float mFactor = 1.0f;
-}
diff --git a/core/java/android/view/animation/AlphaAnimation.java b/core/java/android/view/animation/AlphaAnimation.java
deleted file mode 100644
index 16a10a4..0000000
--- a/core/java/android/view/animation/AlphaAnimation.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-
-/**
- * An animation that controls the alpha level of an object.
- * Useful for fading things in and out. This animation ends up
- * changing the alpha property of a {@link Transformation}
- *
- */
-public class AlphaAnimation extends Animation {
- private float mFromAlpha;
- private float mToAlpha;
-
- /**
- * Constructor used whan an AlphaAnimation is loaded from a resource.
- *
- * @param context Application context to use
- * @param attrs Attribute set from which to read values
- */
- public AlphaAnimation(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a =
- context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AlphaAnimation);
-
- mFromAlpha = a.getFloat(com.android.internal.R.styleable.AlphaAnimation_fromAlpha, 1.0f);
- mToAlpha = a.getFloat(com.android.internal.R.styleable.AlphaAnimation_toAlpha, 1.0f);
-
- a.recycle();
- }
-
- /**
- * Constructor to use when building an AlphaAnimation from code
- *
- * @param fromAlpha Starting alpha value for the animation, where 1.0 means
- * fully opaque and 0.0 means fully transparent.
- * @param toAlpha Ending alpha value for the animation.
- */
- public AlphaAnimation(float fromAlpha, float toAlpha) {
- mFromAlpha = fromAlpha;
- mToAlpha = toAlpha;
- }
-
- /**
- * Changes the alpha property of the supplied {@link Transformation}
- */
- @Override
- protected void applyTransformation(float interpolatedTime, Transformation t) {
- final float alpha = mFromAlpha;
- t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));
- }
-
- @Override
- public boolean willChangeTransformationMatrix() {
- return false;
- }
-
- @Override
- public boolean willChangeBounds() {
- return false;
- }
-}
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
deleted file mode 100644
index b9c8ec3..0000000
--- a/core/java/android/view/animation/Animation.java
+++ /dev/null
@@ -1,925 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.util.TypedValue;
-import android.graphics.RectF;
-
-/**
- * Abstraction for an Animation that can be applied to Views, Surfaces, or
- * other objects. See the {@link android.view.animation animation package
- * description file}.
- */
-public abstract class Animation implements Cloneable {
- /**
- * Repeat the animation indefinitely.
- */
- public static final int INFINITE = -1;
-
- /**
- * When the animation reaches the end and the repeat count is INFINTE_REPEAT
- * or a positive value, the animation restarts from the beginning.
- */
- public static final int RESTART = 1;
-
- /**
- * When the animation reaches the end and the repeat count is INFINTE_REPEAT
- * or a positive value, the animation plays backward (and then forward again).
- */
- public static final int REVERSE = 2;
-
- /**
- * Can be used as the start time to indicate the start time should be the current
- * time when {@link #getTransformation(long, Transformation)} is invoked for the
- * first animation frame. This can is useful for short animations.
- */
- public static final int START_ON_FIRST_FRAME = -1;
-
- /**
- * The specified dimension is an absolute number of pixels.
- */
- public static final int ABSOLUTE = 0;
-
- /**
- * The specified dimension holds a float and should be multiplied by the
- * height or width of the object being animated.
- */
- public static final int RELATIVE_TO_SELF = 1;
-
- /**
- * The specified dimension holds a float and should be multiplied by the
- * height or width of the parent of the object being animated.
- */
- public static final int RELATIVE_TO_PARENT = 2;
-
- /**
- * Requests that the content being animated be kept in its current Z
- * order.
- */
- public static final int ZORDER_NORMAL = 0;
-
- /**
- * Requests that the content being animated be forced on top of all other
- * content for the duration of the animation.
- */
- public static final int ZORDER_TOP = 1;
-
- /**
- * Requests that the content being animated be forced under all other
- * content for the duration of the animation.
- */
- public static final int ZORDER_BOTTOM = -1;
-
- /**
- * Set by {@link #getTransformation(long, Transformation)} when the animation ends.
- */
- boolean mEnded = false;
-
- /**
- * Set by {@link #getTransformation(long, Transformation)} when the animation starts.
- */
- boolean mStarted = false;
-
- /**
- * Set by {@link #getTransformation(long, Transformation)} when the animation repeats
- * in REVERSE mode.
- */
- boolean mCycleFlip = false;
-
- /**
- * This value must be set to true by {@link #initialize(int, int, int, int)}. It
- * indicates the animation was successfully initialized and can be played.
- */
- boolean mInitialized = false;
-
- /**
- * Indicates whether the animation transformation should be applied before the
- * animation starts.
- */
- boolean mFillBefore = true;
-
- /**
- * Indicates whether the animation transformation should be applied after the
- * animation ends.
- */
- boolean mFillAfter = false;
-
- /**
- * Indicates whether fillAfter should be taken into account.
- */
- boolean mFillEnabled = false;
-
- /**
- * The time in milliseconds at which the animation must start;
- */
- long mStartTime = -1;
-
- /**
- * The delay in milliseconds after which the animation must start. When the
- * start offset is > 0, the start time of the animation is startTime + startOffset.
- */
- long mStartOffset;
-
- /**
- * The duration of one animation cycle in milliseconds.
- */
- long mDuration;
-
- /**
- * The number of times the animation must repeat. By default, an animation repeats
- * indefinitely.
- */
- int mRepeatCount = 0;
-
- /**
- * Indicates how many times the animation was repeated.
- */
- int mRepeated = 0;
-
- /**
- * The behavior of the animation when it repeats. The repeat mode is either
- * {@link #RESTART} or {@link #REVERSE}.
- *
- */
- int mRepeatMode = RESTART;
-
- /**
- * The interpolator used by the animation to smooth the movement.
- */
- Interpolator mInterpolator;
-
- /**
- * The animation listener to be notified when the animation starts, ends or repeats.
- */
- AnimationListener mListener;
-
- /**
- * Desired Z order mode during animation.
- */
- private int mZAdjustment;
-
- private boolean mMore = true;
- private boolean mOneMoreTime = true;
-
- RectF mPreviousRegion = new RectF();
- RectF mRegion = new RectF();
- Transformation mTransformation = new Transformation();
- Transformation mPreviousTransformation = new Transformation();
-
- /**
- * Creates a new animation with a duration of 0ms, the default interpolator, with
- * fillBefore set to true and fillAfter set to false
- */
- public Animation() {
- ensureInterpolator();
- }
-
- /**
- * Creates a new animation whose parameters come from the specified context and
- * attributes set.
- *
- * @param context the application environment
- * @param attrs the set of attributes holding the animation parameters
- */
- public Animation(Context context, AttributeSet attrs) {
- TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Animation);
-
- setDuration((long) a.getInt(com.android.internal.R.styleable.Animation_duration, 0));
- setStartOffset((long) a.getInt(com.android.internal.R.styleable.Animation_startOffset, 0));
-
- setFillEnabled(a.getBoolean(com.android.internal.R.styleable.Animation_fillEnabled, mFillEnabled));
- setFillBefore(a.getBoolean(com.android.internal.R.styleable.Animation_fillBefore, mFillBefore));
- setFillAfter(a.getBoolean(com.android.internal.R.styleable.Animation_fillAfter, mFillAfter));
-
- final int resID = a.getResourceId(com.android.internal.R.styleable.Animation_interpolator, 0);
- if (resID > 0) {
- setInterpolator(context, resID);
- }
-
- setRepeatCount(a.getInt(com.android.internal.R.styleable.Animation_repeatCount, mRepeatCount));
- setRepeatMode(a.getInt(com.android.internal.R.styleable.Animation_repeatMode, RESTART));
-
- setZAdjustment(a.getInt(com.android.internal.R.styleable.Animation_zAdjustment, ZORDER_NORMAL));
-
- ensureInterpolator();
-
- a.recycle();
- }
-
- @Override
- protected Animation clone() throws CloneNotSupportedException {
- final Animation animation = (Animation) super.clone();
- animation.mPreviousRegion = new RectF();
- animation.mRegion = new RectF();
- animation.mTransformation = new Transformation();
- animation.mPreviousTransformation = new Transformation();
- return animation;
- }
-
- /**
- * Reset the initialization state of this animation.
- *
- * @see #initialize(int, int, int, int)
- */
- public void reset() {
- mPreviousRegion.setEmpty();
- mPreviousTransformation.clear();
- mInitialized = false;
- mCycleFlip = false;
- mRepeated = 0;
- mMore = true;
- mOneMoreTime = true;
- }
-
- /**
- * Whether or not the animation has been initialized.
- *
- * @return Has this animation been initialized.
- * @see #initialize(int, int, int, int)
- */
- public boolean isInitialized() {
- return mInitialized;
- }
-
- /**
- * Initialize this animation with the dimensions of the object being
- * animated as well as the objects parents. (This is to support animation
- * sizes being specifed relative to these dimensions.)
- *
- * <p>Objects that interpret a Animations should call this method when
- * the sizes of the object being animated and its parent are known, and
- * before calling {@link #getTransformation}.
- *
- *
- * @param width Width of the object being animated
- * @param height Height of the object being animated
- * @param parentWidth Width of the animated object's parent
- * @param parentHeight Height of the animated object's parent
- */
- public void initialize(int width, int height, int parentWidth, int parentHeight) {
- reset();
- mInitialized = true;
- }
-
- /**
- * Sets the acceleration curve for this animation. The interpolator is loaded as
- * a resource from the specified context.
- *
- * @param context The application environment
- * @param resID The resource identifier of the interpolator to load
- * @attr ref android.R.styleable#Animation_interpolator
- */
- public void setInterpolator(Context context, int resID) {
- setInterpolator(AnimationUtils.loadInterpolator(context, resID));
- }
-
- /**
- * Sets the acceleration curve for this animation. Defaults to a linear
- * interpolation.
- *
- * @param i The interpolator which defines the acceleration curve
- * @attr ref android.R.styleable#Animation_interpolator
- */
- public void setInterpolator(Interpolator i) {
- mInterpolator = i;
- }
-
- /**
- * When this animation should start relative to the start time. This is most
- * useful when composing complex animations using an {@link AnimationSet }
- * where some of the animations components start at different times.
- *
- * @param startOffset When this Animation should start, in milliseconds from
- * the start time of the root AnimationSet.
- * @attr ref android.R.styleable#Animation_startOffset
- */
- public void setStartOffset(long startOffset) {
- mStartOffset = startOffset;
- }
-
- /**
- * How long this animation should last. The duration cannot be negative.
- *
- * @param durationMillis Duration in milliseconds
- *
- * @throw java.lang.IllegalArgumentException if the duration is < 0
- *
- * @attr ref android.R.styleable#Animation_duration
- */
- public void setDuration(long durationMillis) {
- if (durationMillis < 0) {
- throw new IllegalArgumentException("Animation duration cannot be negative");
- }
- mDuration = durationMillis;
- }
-
- /**
- * Ensure that the duration that this animation will run is not longer
- * than <var>durationMillis</var>. In addition to adjusting the duration
- * itself, this ensures that the repeat count also will not make it run
- * longer than the given time.
- *
- * @param durationMillis The maximum duration the animation is allowed
- * to run.
- */
- public void restrictDuration(long durationMillis) {
- if (mStartOffset > durationMillis) {
- mStartOffset = durationMillis;
- mDuration = 0;
- mRepeatCount = 0;
- return;
- }
-
- long dur = mDuration + mStartOffset;
- if (dur > durationMillis) {
- mDuration = dur = durationMillis-mStartOffset;
- }
- if (mRepeatCount < 0 || mRepeatCount > durationMillis
- || (dur*mRepeatCount) > durationMillis) {
- mRepeatCount = (int)(durationMillis/dur);
- }
- }
-
- /**
- * How much to scale the duration by.
- *
- * @param scale The amount to scale the duration.
- */
- public void scaleCurrentDuration(float scale) {
- mDuration = (long) (mDuration * scale);
- }
-
- /**
- * When this animation should start. When the start time is set to
- * {@link #START_ON_FIRST_FRAME}, the animation will start the first time
- * {@link #getTransformation(long, Transformation)} is invoked. The time passed
- * to this method should be obtained by calling
- * {@link AnimationUtils#currentAnimationTimeMillis()} instead of
- * {@link System#currentTimeMillis()}.
- *
- * @param startTimeMillis the start time in milliseconds
- */
- public void setStartTime(long startTimeMillis) {
- mStartTime = startTimeMillis;
- mStarted = mEnded = false;
- mCycleFlip = false;
- mRepeated = 0;
- mMore = true;
- }
-
- /**
- * Convenience method to start the animation the first time
- * {@link #getTransformation(long, Transformation)} is invoked.
- */
- public void start() {
- setStartTime(-1);
- }
-
- /**
- * Convenience method to start the animation at the current time in
- * milliseconds.
- */
- public void startNow() {
- setStartTime(AnimationUtils.currentAnimationTimeMillis());
- }
-
- /**
- * Defines what this animation should do when it reaches the end. This
- * setting is applied only when the repeat count is either greater than
- * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}.
- *
- * @param repeatMode {@link #RESTART} or {@link #REVERSE}
- * @attr ref android.R.styleable#Animation_repeatMode
- */
- public void setRepeatMode(int repeatMode) {
- mRepeatMode = repeatMode;
- }
-
- /**
- * Sets how many times the animation should be repeated. If the repeat
- * count is 0, the animation is never repeated. If the repeat count is
- * greater than 0 or {@link #INFINITE}, the repeat mode will be taken
- * into account. The repeat count if 0 by default.
- *
- * @param repeatCount the number of times the animation should be repeated
- * @attr ref android.R.styleable#Animation_repeatCount
- */
- public void setRepeatCount(int repeatCount) {
- if (repeatCount < 0) {
- repeatCount = INFINITE;
- }
- mRepeatCount = repeatCount;
- }
-
- /**
- * If fillEnabled is true, this animation will apply fillBefore and fillAfter.
- *
- * @return true if the animation will take fillBefore and fillAfter into account
- * @attr ref android.R.styleable#Animation_fillEnabled
- */
- public boolean isFillEnabled() {
- return mFillEnabled;
- }
-
- /**
- * If fillEnabled is true, the animation will apply the value of fillBefore and
- * fillAfter. Otherwise, fillBefore and fillAfter are ignored and the animation
- * transformation is always applied.
- *
- * @param fillEnabled true if the animation should take fillBefore and fillAfter into account
- * @attr ref android.R.styleable#Animation_fillEnabled
- *
- * @see #setFillBefore(boolean)
- * @see #setFillAfter(boolean)
- */
- public void setFillEnabled(boolean fillEnabled) {
- mFillEnabled = fillEnabled;
- }
-
- /**
- * If fillBefore is true, this animation will apply its transformation
- * before the start time of the animation. Defaults to true if not set.
- * Note that this applies when using an {@link
- * android.view.animation.AnimationSet AnimationSet} to chain
- * animations. The transformation is not applied before the AnimationSet
- * itself starts.
- *
- * @param fillBefore true if the animation should apply its transformation before it starts
- * @attr ref android.R.styleable#Animation_fillBefore
- *
- * @see #setFillEnabled(boolean)
- */
- public void setFillBefore(boolean fillBefore) {
- mFillBefore = fillBefore;
- }
-
- /**
- * If fillAfter is true, the transformation that this animation performed
- * will persist when it is finished. Defaults to false if not set.
- * Note that this applies when using an {@link
- * android.view.animation.AnimationSet AnimationSet} to chain
- * animations. The transformation is not applied before the AnimationSet
- * itself starts.
- *
- * @param fillAfter true if the animation should apply its transformation after it ends
- * @attr ref android.R.styleable#Animation_fillAfter
- *
- * @see #setFillEnabled(boolean)
- */
- public void setFillAfter(boolean fillAfter) {
- mFillAfter = fillAfter;
- }
-
- /**
- * Set the Z ordering mode to use while running the animation.
- *
- * @param zAdjustment The desired mode, one of {@link #ZORDER_NORMAL},
- * {@link #ZORDER_TOP}, or {@link #ZORDER_BOTTOM}.
- * @attr ref android.R.styleable#Animation_zAdjustment
- */
- public void setZAdjustment(int zAdjustment) {
- mZAdjustment = zAdjustment;
- }
-
- /**
- * Gets the acceleration curve type for this animation.
- *
- * @return the {@link Interpolator} associated to this animation
- * @attr ref android.R.styleable#Animation_interpolator
- */
- public Interpolator getInterpolator() {
- return mInterpolator;
- }
-
- /**
- * When this animation should start. If the animation has not startet yet,
- * this method might return {@link #START_ON_FIRST_FRAME}.
- *
- * @return the time in milliseconds when the animation should start or
- * {@link #START_ON_FIRST_FRAME}
- */
- public long getStartTime() {
- return mStartTime;
- }
-
- /**
- * How long this animation should last
- *
- * @return the duration in milliseconds of the animation
- * @attr ref android.R.styleable#Animation_duration
- */
- public long getDuration() {
- return mDuration;
- }
-
- /**
- * When this animation should start, relative to StartTime
- *
- * @return the start offset in milliseconds
- * @attr ref android.R.styleable#Animation_startOffset
- */
- public long getStartOffset() {
- return mStartOffset;
- }
-
- /**
- * Defines what this animation should do when it reaches the end.
- *
- * @return either one of {@link #REVERSE} or {@link #RESTART}
- * @attr ref android.R.styleable#Animation_repeatMode
- */
- public int getRepeatMode() {
- return mRepeatMode;
- }
-
- /**
- * Defines how many times the animation should repeat. The default value
- * is 0.
- *
- * @return the number of times the animation should repeat, or {@link #INFINITE}
- * @attr ref android.R.styleable#Animation_repeatCount
- */
- public int getRepeatCount() {
- return mRepeatCount;
- }
-
- /**
- * If fillBefore is true, this animation will apply its transformation
- * before the start time of the animation.
- *
- * @return true if the animation applies its transformation before it starts
- * @attr ref android.R.styleable#Animation_fillBefore
- */
- public boolean getFillBefore() {
- return mFillBefore;
- }
-
- /**
- * If fillAfter is true, this animation will apply its transformation
- * after the end time of the animation.
- *
- * @return true if the animation applies its transformation after it ends
- * @attr ref android.R.styleable#Animation_fillAfter
- */
- public boolean getFillAfter() {
- return mFillAfter;
- }
-
- /**
- * Returns the Z ordering mode to use while running the animation as
- * previously set by {@link #setZAdjustment}.
- *
- * @return Returns one of {@link #ZORDER_NORMAL},
- * {@link #ZORDER_TOP}, or {@link #ZORDER_BOTTOM}.
- * @attr ref android.R.styleable#Animation_zAdjustment
- */
- public int getZAdjustment() {
- return mZAdjustment;
- }
-
- /**
- * <p>Indicates whether or not this animation will affect the transformation
- * matrix. For instance, a fade animation will not affect the matrix whereas
- * a scale animation will.</p>
- *
- * @return true if this animation will change the transformation matrix
- */
- public boolean willChangeTransformationMatrix() {
- // assume we will change the matrix
- return true;
- }
-
- /**
- * <p>Indicates whether or not this animation will affect the bounds of the
- * animated view. For instance, a fade animation will not affect the bounds
- * whereas a 200% scale animation will.</p>
- *
- * @return true if this animation will change the view's bounds
- */
- public boolean willChangeBounds() {
- // assume we will change the bounds
- return true;
- }
-
- /**
- * <p>Binds an animation listener to this animation. The animation listener
- * is notified of animation events such as the end of the animation or the
- * repetition of the animation.</p>
- *
- * @param listener the animation listener to be notified
- */
- public void setAnimationListener(AnimationListener listener) {
- mListener = listener;
- }
-
- /**
- * Gurantees that this animation has an interpolator. Will use
- * a AccelerateDecelerateInterpolator is nothing else was specified.
- */
- protected void ensureInterpolator() {
- if (mInterpolator == null) {
- mInterpolator = new AccelerateDecelerateInterpolator();
- }
- }
-
- /**
- * Compute a hint at how long the entire animation may last, in milliseconds.
- * Animations can be written to cause themselves to run for a different
- * duration than what is computed here, but generally this should be
- * accurate.
- */
- public long computeDurationHint() {
- return (getStartOffset() + getDuration()) * (getRepeatCount() + 1);
- }
-
- /**
- * Gets the transformation to apply at a specified point in time. Implementations of this
- * method should always replace the specified Transformation or document they are doing
- * otherwise.
- *
- * @param currentTime Where we are in the animation. This is wall clock time.
- * @param outTransformation A tranformation object that is provided by the
- * caller and will be filled in by the animation.
- * @return True if the animation is still running
- */
- public boolean getTransformation(long currentTime, Transformation outTransformation) {
- if (mStartTime == -1) {
- mStartTime = currentTime;
- }
-
- final long startOffset = getStartOffset();
- final long duration = mDuration;
- float normalizedTime;
- if (duration != 0) {
- normalizedTime = ((float) (currentTime - (mStartTime + startOffset))) /
- (float) duration;
- } else {
- // time is a step-change with a zero duration
- normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f;
- }
-
- final boolean expired = normalizedTime >= 1.0f;
- mMore = !expired;
-
- if (!mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);
-
- if ((normalizedTime >= 0.0f || mFillBefore) && (normalizedTime <= 1.0f || mFillAfter)) {
- if (!mStarted) {
- if (mListener != null) {
- mListener.onAnimationStart(this);
- }
- mStarted = true;
- }
-
- if (mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);
-
- if (mCycleFlip) {
- normalizedTime = 1.0f - normalizedTime;
- }
-
- final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);
- applyTransformation(interpolatedTime, outTransformation);
- }
-
- if (expired) {
- if (mRepeatCount == mRepeated) {
- if (!mEnded) {
- if (mListener != null) {
- mListener.onAnimationEnd(this);
- }
- mEnded = true;
- }
- } else {
- if (mRepeatCount > 0) {
- mRepeated++;
- }
-
- if (mRepeatMode == REVERSE) {
- mCycleFlip = !mCycleFlip;
- }
-
- mStartTime = -1;
- mMore = true;
-
- if (mListener != null) {
- mListener.onAnimationRepeat(this);
- }
- }
- }
-
- if (!mMore && mOneMoreTime) {
- mOneMoreTime = false;
- return true;
- }
-
- return mMore;
- }
-
- /**
- * <p>Indicates whether this animation has started or not.</p>
- *
- * @return true if the animation has started, false otherwise
- */
- public boolean hasStarted() {
- return mStarted;
- }
-
- /**
- * <p>Indicates whether this animation has ended or not.</p>
- *
- * @return true if the animation has ended, false otherwise
- */
- public boolean hasEnded() {
- return mEnded;
- }
-
- /**
- * Helper for getTransformation. Subclasses should implement this to apply
- * their transforms given an interpolation value. Implementations of this
- * method should always replace the specified Transformation or document
- * they are doing otherwise.
- *
- * @param interpolatedTime The value of the normalized time (0.0 to 1.0)
- * after it has been run through the interpolation function.
- * @param t The Transofrmation object to fill in with the current
- * transforms.
- */
- protected void applyTransformation(float interpolatedTime, Transformation t) {
- }
-
- /**
- * Convert the information in the description of a size to an actual
- * dimension
- *
- * @param type One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
- * Animation.RELATIVE_TO_PARENT.
- * @param value The dimension associated with the type parameter
- * @param size The size of the object being animated
- * @param parentSize The size of the parent of the object being animated
- * @return The dimension to use for the animation
- */
- protected float resolveSize(int type, float value, int size, int parentSize) {
- switch (type) {
- case ABSOLUTE:
- return value;
- case RELATIVE_TO_SELF:
- return size * value;
- case RELATIVE_TO_PARENT:
- return parentSize * value;
- default:
- return value;
- }
- }
-
- /**
- * @param left
- * @param top
- * @param right
- * @param bottom
- * @param invalidate
- * @param transformation
- *
- * @hide
- */
- public void getInvalidateRegion(int left, int top, int right, int bottom,
- RectF invalidate, Transformation transformation) {
-
- final RectF tempRegion = mRegion;
- final RectF previousRegion = mPreviousRegion;
-
- invalidate.set(left, top, right, bottom);
- transformation.getMatrix().mapRect(invalidate);
- tempRegion.set(invalidate);
- invalidate.union(previousRegion);
-
- previousRegion.set(tempRegion);
-
- final Transformation tempTransformation = mTransformation;
- final Transformation previousTransformation = mPreviousTransformation;
-
- tempTransformation.set(transformation);
- transformation.set(previousTransformation);
- previousTransformation.set(tempTransformation);
- }
-
- /**
- * @param left
- * @param top
- * @param right
- * @param bottom
- *
- * @hide
- */
- public void initializeInvalidateRegion(int left, int top, int right, int bottom) {
- final RectF region = mPreviousRegion;
- region.set(left, top, right, bottom);
- if (mFillBefore) {
- final Transformation previousTransformation = mPreviousTransformation;
- applyTransformation(0.0f, previousTransformation);
- }
- }
-
- /**
- * Utility class to parse a string description of a size.
- */
- protected static class Description {
- /**
- * One of Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
- * Animation.RELATIVE_TO_PARENT.
- */
- public int type;
-
- /**
- * The absolute or relative dimension for this Description.
- */
- public float value;
-
- /**
- * Size descriptions can appear inthree forms:
- * <ol>
- * <li>An absolute size. This is represented by a number.</li>
- * <li>A size relative to the size of the object being animated. This
- * is represented by a number followed by "%".</li> *
- * <li>A size relative to the size of the parent of object being
- * animated. This is represented by a number followed by "%p".</li>
- * </ol>
- * @param value The typed value to parse
- * @return The parsed version of the description
- */
- static Description parseValue(TypedValue value) {
- Description d = new Description();
- if (value == null) {
- d.type = ABSOLUTE;
- d.value = 0;
- } else {
- if (value.type == TypedValue.TYPE_FRACTION) {
- d.type = (value.data & TypedValue.COMPLEX_UNIT_MASK) ==
- TypedValue.COMPLEX_UNIT_FRACTION_PARENT ?
- RELATIVE_TO_PARENT : RELATIVE_TO_SELF;
- d.value = TypedValue.complexToFloat(value.data);
- return d;
- } else if (value.type == TypedValue.TYPE_FLOAT) {
- d.type = ABSOLUTE;
- d.value = value.getFloat();
- return d;
- } else if (value.type >= TypedValue.TYPE_FIRST_INT &&
- value.type <= TypedValue.TYPE_LAST_INT) {
- d.type = ABSOLUTE;
- d.value = value.data;
- return d;
- }
- }
-
- d.type = ABSOLUTE;
- d.value = 0.0f;
-
- return d;
- }
- }
-
- /**
- * <p>An animation listener receives notifications from an animation.
- * Notifications indicate animation related events, such as the end or the
- * repetition of the animation.</p>
- */
- public static interface AnimationListener {
- /**
- * <p>Notifies the start of the animation.</p>
- *
- * @param animation The started animation.
- */
- void onAnimationStart(Animation animation);
-
- /**
- * <p>Notifies the end of the animation. This callback is not invoked
- * for animations with repeat count set to INFINITE.</p>
- *
- * @param animation The animation which reached its end.
- */
- void onAnimationEnd(Animation animation);
-
- /**
- * <p>Notifies the repetition of the animation.</p>
- *
- * @param animation The animation which was repeated.
- */
- void onAnimationRepeat(Animation animation);
- }
-}
diff --git a/core/java/android/view/animation/AnimationSet.java b/core/java/android/view/animation/AnimationSet.java
deleted file mode 100644
index 7b56f00..0000000
--- a/core/java/android/view/animation/AnimationSet.java
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.graphics.RectF;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Represents a group of Animations that should be played together.
- * The transformation of each individual animation are composed
- * together into a single transform.
- * If AnimationSet sets any properties that its children also set
- * (for example, duration or fillBefore), the values of AnimationSet
- * override the child values.
- */
-public class AnimationSet extends Animation {
- private static final int PROPERTY_FILL_AFTER_MASK = 0x1;
- private static final int PROPERTY_FILL_BEFORE_MASK = 0x2;
- private static final int PROPERTY_REPEAT_MODE_MASK = 0x4;
- private static final int PROPERTY_START_OFFSET_MASK = 0x8;
- private static final int PROPERTY_SHARE_INTERPOLATOR_MASK = 0x10;
- private static final int PROPERTY_DURATION_MASK = 0x20;
- private static final int PROPERTY_MORPH_MATRIX_MASK = 0x40;
- private static final int PROPERTY_CHANGE_BOUNDS_MASK = 0x80;
-
- private int mFlags = 0;
-
- private ArrayList<Animation> mAnimations = new ArrayList<Animation>();
-
- private Transformation mTempTransformation = new Transformation();
-
- private long mLastEnd;
-
- private long[] mStoredOffsets;
-
- /**
- * Constructor used whan an AnimationSet is loaded from a resource.
- *
- * @param context Application context to use
- * @param attrs Attribute set from which to read values
- */
- public AnimationSet(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a =
- context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AnimationSet);
-
- setFlag(PROPERTY_SHARE_INTERPOLATOR_MASK,
- a.getBoolean(com.android.internal.R.styleable.AnimationSet_shareInterpolator, true));
- init();
-
- a.recycle();
- }
-
-
- /**
- * Constructor to use when building an AnimationSet from code
- *
- * @param shareInterpolator Pass true if all of the animations in this set
- * should use the interpolator assocciated with this AnimationSet.
- * Pass false if each animation should use its own interpolator.
- */
- public AnimationSet(boolean shareInterpolator) {
- setFlag(PROPERTY_SHARE_INTERPOLATOR_MASK, shareInterpolator);
- init();
- }
-
- @Override
- protected AnimationSet clone() throws CloneNotSupportedException {
- final AnimationSet animation = (AnimationSet) super.clone();
- animation.mTempTransformation = new Transformation();
- animation.mAnimations = new ArrayList<Animation>();
-
- final int count = mAnimations.size();
- final ArrayList<Animation> animations = mAnimations;
-
- for (int i = 0; i < count; i++) {
- animation.mAnimations.add(animations.get(i).clone());
- }
-
- return animation;
- }
-
- private void setFlag(int mask, boolean value) {
- if (value) {
- mFlags |= mask;
- } else {
- mFlags &= ~mask;
- }
- }
-
- private void init() {
- mStartTime = 0;
- mDuration = 0;
- }
-
- @Override
- public void setFillAfter(boolean fillAfter) {
- mFlags |= PROPERTY_FILL_AFTER_MASK;
- super.setFillAfter(fillAfter);
- }
-
- @Override
- public void setFillBefore(boolean fillBefore) {
- mFlags |= PROPERTY_FILL_BEFORE_MASK;
- super.setFillBefore(fillBefore);
- }
-
- @Override
- public void setRepeatMode(int repeatMode) {
- mFlags |= PROPERTY_REPEAT_MODE_MASK;
- super.setRepeatMode(repeatMode);
- }
-
- @Override
- public void setStartOffset(long startOffset) {
- mFlags |= PROPERTY_START_OFFSET_MASK;
- super.setStartOffset(startOffset);
- }
-
- /**
- * <p>Sets the duration of every child animation.</p>
- *
- * @param durationMillis the duration of the animation, in milliseconds, for
- * every child in this set
- */
- @Override
- public void setDuration(long durationMillis) {
- mFlags |= PROPERTY_DURATION_MASK;
- super.setDuration(durationMillis);
- }
-
- /**
- * Add a child animation to this animation set.
- * The transforms of the child animations are applied in the order
- * that they were added
- * @param a Animation to add.
- */
- public void addAnimation(Animation a) {
- mAnimations.add(a);
-
- boolean noMatrix = (mFlags & PROPERTY_MORPH_MATRIX_MASK) == 0;
- if (noMatrix && a.willChangeTransformationMatrix()) {
- mFlags |= PROPERTY_MORPH_MATRIX_MASK;
- }
-
- boolean changeBounds = (mFlags & PROPERTY_CHANGE_BOUNDS_MASK) == 0;
- if (changeBounds && a.willChangeTransformationMatrix()) {
- mFlags |= PROPERTY_CHANGE_BOUNDS_MASK;
- }
-
- if (mAnimations.size() == 1) {
- mDuration = a.getStartOffset() + a.getDuration();
- mLastEnd = mStartOffset + mDuration;
- } else {
- mLastEnd = Math.max(mLastEnd, a.getStartOffset() + a.getDuration());
- mDuration = mLastEnd - mStartOffset;
- }
- }
-
- /**
- * Sets the start time of this animation and all child animations
- *
- * @see android.view.animation.Animation#setStartTime(long)
- */
- @Override
- public void setStartTime(long startTimeMillis) {
- super.setStartTime(startTimeMillis);
-
- final int count = mAnimations.size();
- final ArrayList<Animation> animations = mAnimations;
-
- for (int i = 0; i < count; i++) {
- Animation a = animations.get(i);
- a.setStartTime(startTimeMillis);
- }
- }
-
- @Override
- public long getStartTime() {
- long startTime = Long.MAX_VALUE;
-
- final int count = mAnimations.size();
- final ArrayList<Animation> animations = mAnimations;
-
- for (int i = 0; i < count; i++) {
- Animation a = animations.get(i);
- startTime = Math.min(startTime, a.getStartTime());
- }
-
- return startTime;
- }
-
- @Override
- public void restrictDuration(long durationMillis) {
- super.restrictDuration(durationMillis);
-
- final ArrayList<Animation> animations = mAnimations;
- int count = animations.size();
-
- for (int i = 0; i < count; i++) {
- animations.get(i).restrictDuration(durationMillis);
- }
- }
-
- /**
- * The duration of an AnimationSet is defined to be the
- * duration of the longest child animation.
- *
- * @see android.view.animation.Animation#getDuration()
- */
- @Override
- public long getDuration() {
- final ArrayList<Animation> animations = mAnimations;
- final int count = animations.size();
- long duration = 0;
-
- boolean durationSet = (mFlags & PROPERTY_DURATION_MASK) == PROPERTY_DURATION_MASK;
- if (durationSet) {
- duration = mDuration;
- } else {
- for (int i = 0; i < count; i++) {
- duration = Math.max(duration, animations.get(i).getDuration());
- }
- }
-
- return duration;
- }
-
- /**
- * The duration hint of an animation set is the maximum of the duration
- * hints of all of its component animations.
- *
- * @see android.view.animation.Animation#computeDurationHint
- */
- public long computeDurationHint() {
- long duration = 0;
- final int count = mAnimations.size();
- final ArrayList<Animation> animations = mAnimations;
- for (int i = count - 1; i >= 0; --i) {
- final long d = animations.get(i).computeDurationHint();
- if (d > duration) duration = d;
- }
- return duration;
- }
-
- /**
- * @hide
- */
- public void getInvalidateRegion(int left, int top, int right, int bottom,
- RectF invalidate, Transformation transformation) {
-
- final RectF previousRegion = mPreviousRegion;
-
- invalidate.set(left, top, right, bottom);
- transformation.getMatrix().mapRect(invalidate);
- invalidate.union(previousRegion);
-
- previousRegion.set(left, top, right, bottom);
- transformation.getMatrix().mapRect(previousRegion);
-
- final Transformation tempTransformation = mTransformation;
- final Transformation previousTransformation = mPreviousTransformation;
-
- tempTransformation.set(transformation);
- transformation.set(previousTransformation);
- previousTransformation.set(tempTransformation);
- }
-
- /**
- * @hide
- */
- public void initializeInvalidateRegion(int left, int top, int right, int bottom) {
- final RectF region = mPreviousRegion;
- region.set(left, top, right, bottom);
-
- if (mFillBefore) {
- final int count = mAnimations.size();
- final ArrayList<Animation> animations = mAnimations;
- final Transformation temp = mTempTransformation;
-
- final Transformation previousTransformation = mPreviousTransformation;
-
- for (int i = count - 1; i >= 0; --i) {
- final Animation a = animations.get(i);
-
- temp.clear();
- a.applyTransformation(0.0f, temp);
- previousTransformation.compose(temp);
- }
- }
- }
-
- /**
- * The transformation of an animation set is the concatenation of all of its
- * component animations.
- *
- * @see android.view.animation.Animation#getTransformation
- */
- @Override
- public boolean getTransformation(long currentTime, Transformation t) {
- final int count = mAnimations.size();
- final ArrayList<Animation> animations = mAnimations;
- final Transformation temp = mTempTransformation;
-
- boolean more = false;
- boolean started = false;
- boolean ended = true;
-
- t.clear();
-
- for (int i = count - 1; i >= 0; --i) {
- final Animation a = animations.get(i);
-
- temp.clear();
- more = a.getTransformation(currentTime, temp) || more;
- t.compose(temp);
-
- started = started || a.hasStarted();
- ended = a.hasEnded() && ended;
- }
-
- if (started && !mStarted) {
- if (mListener != null) {
- mListener.onAnimationStart(this);
- }
- mStarted = true;
- }
-
- if (ended != mEnded) {
- if (mListener != null) {
- mListener.onAnimationEnd(this);
- }
- mEnded = ended;
- }
-
- return more;
- }
-
- /**
- * @see android.view.animation.Animation#scaleCurrentDuration(float)
- */
- @Override
- public void scaleCurrentDuration(float scale) {
- final ArrayList<Animation> animations = mAnimations;
- int count = animations.size();
- for (int i = 0; i < count; i++) {
- animations.get(i).scaleCurrentDuration(scale);
- }
- }
-
- /**
- * @see android.view.animation.Animation#initialize(int, int, int, int)
- */
- @Override
- public void initialize(int width, int height, int parentWidth, int parentHeight) {
- super.initialize(width, height, parentWidth, parentHeight);
-
- boolean durationSet = (mFlags & PROPERTY_DURATION_MASK) == PROPERTY_DURATION_MASK;
- boolean fillAfterSet = (mFlags & PROPERTY_FILL_AFTER_MASK) == PROPERTY_FILL_AFTER_MASK;
- boolean fillBeforeSet = (mFlags & PROPERTY_FILL_BEFORE_MASK) == PROPERTY_FILL_BEFORE_MASK;
- boolean repeatModeSet = (mFlags & PROPERTY_REPEAT_MODE_MASK) == PROPERTY_REPEAT_MODE_MASK;
- boolean shareInterpolator = (mFlags & PROPERTY_SHARE_INTERPOLATOR_MASK)
- == PROPERTY_SHARE_INTERPOLATOR_MASK;
- boolean startOffsetSet = (mFlags & PROPERTY_START_OFFSET_MASK)
- == PROPERTY_START_OFFSET_MASK;
-
- if (shareInterpolator) {
- ensureInterpolator();
- }
-
- final ArrayList<Animation> children = mAnimations;
- final int count = children.size();
-
- final long duration = mDuration;
- final boolean fillAfter = mFillAfter;
- final boolean fillBefore = mFillBefore;
- final int repeatMode = mRepeatMode;
- final Interpolator interpolator = mInterpolator;
- final long startOffset = mStartOffset;
-
-
- long[] storedOffsets = mStoredOffsets;
- if (storedOffsets == null || storedOffsets.length != count) {
- storedOffsets = mStoredOffsets = new long[count];
- }
-
- for (int i = 0; i < count; i++) {
- Animation a = children.get(i);
- if (durationSet) {
- a.setDuration(duration);
- }
- if (fillAfterSet) {
- a.setFillAfter(fillAfter);
- }
- if (fillBeforeSet) {
- a.setFillBefore(fillBefore);
- }
- if (repeatModeSet) {
- a.setRepeatMode(repeatMode);
- }
- if (shareInterpolator) {
- a.setInterpolator(interpolator);
- }
- if (startOffsetSet) {
- long offset = a.getStartOffset();
- a.setStartOffset(offset + startOffset);
- storedOffsets[i] = offset;
- }
- a.initialize(width, height, parentWidth, parentHeight);
- }
- }
-
- @Override
- public void reset() {
- super.reset();
- restoreChildrenStartOffset();
- }
-
- /**
- * @hide
- */
- void restoreChildrenStartOffset() {
- final long[] offsets = mStoredOffsets;
- if (offsets == null) return;
-
- final ArrayList<Animation> children = mAnimations;
- final int count = children.size();
-
-
- for (int i = 0; i < count; i++) {
- children.get(i).setStartOffset(offsets[i]);
- }
- }
-
- /**
- * @return All the child animations in this AnimationSet. Note that
- * this may include other AnimationSets, which are not expanded.
- */
- public List<Animation> getAnimations() {
- return mAnimations;
- }
-
- @Override
- public boolean willChangeTransformationMatrix() {
- return (mFlags & PROPERTY_MORPH_MATRIX_MASK) == PROPERTY_MORPH_MATRIX_MASK;
- }
-
- @Override
- public boolean willChangeBounds() {
- return (mFlags & PROPERTY_CHANGE_BOUNDS_MASK) == PROPERTY_CHANGE_BOUNDS_MASK;
- }
-}
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
deleted file mode 100644
index ce3cdc5..0000000
--- a/core/java/android/view/animation/AnimationUtils.java
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-import android.content.res.XmlResourceParser;
-import android.content.res.Resources.NotFoundException;
-import android.util.AttributeSet;
-import android.util.Xml;
-import android.os.SystemClock;
-
-import java.io.IOException;
-
-/**
- * Defines common utilities for working with animations.
- *
- */
-public class AnimationUtils {
- /**
- * Returns the current animation time in milliseconds. This time should be used when invoking
- * {@link Animation#setStartTime(long)}. Refer to {@link android.os.SystemClock} for more
- * information about the different available clocks. The clock used by this method is
- * <em>not</em> the "wall" clock (it is not {@link System#currentTimeMillis}).
- *
- * @return the current animation time in milliseconds
- *
- * @see android.os.SystemClock
- */
- public static long currentAnimationTimeMillis() {
- return SystemClock.uptimeMillis();
- }
-
- /**
- * Loads an {@link Animation} object from a resource
- *
- * @param context Application context used to access resources
- * @param id The resource id of the animation to load
- * @return The animation object reference by the specified id
- * @throws NotFoundException when the animation cannot be loaded
- */
- public static Animation loadAnimation(Context context, int id)
- throws NotFoundException {
-
- XmlResourceParser parser = null;
- try {
- parser = context.getResources().getAnimation(id);
- return createAnimationFromXml(context, parser);
- } catch (XmlPullParserException ex) {
- NotFoundException rnf = new NotFoundException(
- "Can't load animation resource ID #0x"
- + Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
- } catch (IOException ex) {
- NotFoundException rnf = new NotFoundException(
- "Can't load animation resource ID #0x"
- + Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
- } finally {
- if (parser != null) parser.close();
- }
- }
-
- private static Animation createAnimationFromXml(Context c, XmlPullParser parser)
- throws XmlPullParserException, IOException {
- return createAnimationFromXml(c, parser, null, Xml.asAttributeSet(parser));
- }
-
- private static Animation createAnimationFromXml(Context c, XmlPullParser parser, AnimationSet parent, AttributeSet attrs)
- throws XmlPullParserException, IOException {
-
- Animation anim = null;
-
- // Make sure we are on a start tag.
- int type = parser.getEventType();
- int depth = parser.getDepth();
-
- while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
- && type != XmlPullParser.END_DOCUMENT) {
-
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
-
- String name = parser.getName();
-
- if (name.equals("set")) {
- anim = new AnimationSet(c, attrs);
- createAnimationFromXml(c, parser, (AnimationSet)anim, attrs);
- } else if (name.equals("alpha")) {
- anim = new AlphaAnimation(c, attrs);
- } else if (name.equals("scale")) {
- anim = new ScaleAnimation(c, attrs);
- } else if (name.equals("rotate")) {
- anim = new RotateAnimation(c, attrs);
- } else if (name.equals("translate")) {
- anim = new TranslateAnimation(c, attrs);
- } else {
- throw new RuntimeException("Unknown animation name: " + parser.getName());
- }
-
- if (parent != null) {
- parent.addAnimation(anim);
- }
- }
-
- return anim;
-
- }
-
- public static LayoutAnimationController loadLayoutAnimation(
- Context context, int id) throws NotFoundException {
-
- XmlResourceParser parser = null;
- try {
- parser = context.getResources().getAnimation(id);
- return createLayoutAnimationFromXml(context, parser);
- } catch (XmlPullParserException ex) {
- NotFoundException rnf = new NotFoundException(
- "Can't load animation resource ID #0x" +
- Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
- } catch (IOException ex) {
- NotFoundException rnf = new NotFoundException(
- "Can't load animation resource ID #0x" +
- Integer .toHexString(id));
- rnf.initCause(ex);
- throw rnf;
- } finally {
- if (parser != null) parser.close();
- }
- }
-
- private static LayoutAnimationController createLayoutAnimationFromXml(
- Context c, XmlPullParser parser)
- throws XmlPullParserException, IOException {
- return createLayoutAnimationFromXml(c, parser,
- Xml.asAttributeSet(parser));
- }
-
- private static LayoutAnimationController createLayoutAnimationFromXml(
- Context c, XmlPullParser parser, AttributeSet attrs)
- throws XmlPullParserException, IOException {
-
- LayoutAnimationController controller = null;
-
- int type;
- int depth = parser.getDepth();
-
- while (((type = parser.next()) != XmlPullParser.END_TAG
- || parser.getDepth() > depth)
- && type != XmlPullParser.END_DOCUMENT) {
-
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
-
- String name = parser.getName();
-
- if ("layoutAnimation".equals(name)) {
- controller = new LayoutAnimationController(c, attrs);
- } else if ("gridLayoutAnimation".equals(name)) {
- controller = new GridLayoutAnimationController(c, attrs);
- } else {
- throw new RuntimeException("Unknown layout animation name: " +
- name);
- }
- }
-
- return controller;
- }
-
- /**
- * Make an animation for objects becoming visible. Uses a slide and fade
- * effect.
- *
- * @param c Context for loading resources
- * @param fromLeft is the object to be animated coming from the left
- * @return The new animation
- */
- public static Animation makeInAnimation(Context c, boolean fromLeft)
- {
-
- Animation a;
- if (fromLeft) {
- a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_left);
- } else {
- a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_right);
- }
-
- a.setInterpolator(new DecelerateInterpolator());
- a.setStartTime(currentAnimationTimeMillis());
- return a;
- }
-
- /**
- * Make an animation for objects becoming invisible. Uses a slide and fade
- * effect.
- *
- * @param c Context for loading resources
- * @param toRight is the object to be animated exiting to the right
- * @return The new animation
- */
- public static Animation makeOutAnimation(Context c, boolean toRight)
- {
-
- Animation a;
- if (toRight) {
- a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_out_right);
- } else {
- a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_out_left);
- }
-
- a.setInterpolator(new AccelerateInterpolator());
- a.setStartTime(currentAnimationTimeMillis());
- return a;
- }
-
-
- /**
- * Make an animation for objects becoming visible. Uses a slide up and fade
- * effect.
- *
- * @param c Context for loading resources
- * @return The new animation
- */
- public static Animation makeInChildBottomAnimation(Context c)
- {
-
- Animation a;
- a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_child_bottom);
- a.setInterpolator(new AccelerateInterpolator());
- a.setStartTime(currentAnimationTimeMillis());
- return a;
- }
-
- /**
- * Loads an {@link Interpolator} object from a resource
- *
- * @param context Application context used to access resources
- * @param id The resource id of the animation to load
- * @return The animation object reference by the specified id
- * @throws NotFoundException
- */
- public static Interpolator loadInterpolator(Context context, int id)
- throws NotFoundException {
-
- XmlResourceParser parser = null;
- try {
- parser = context.getResources().getAnimation(id);
- return createInterpolatorFromXml(context, parser);
- } catch (XmlPullParserException ex) {
- NotFoundException rnf = new NotFoundException(
- "Can't load animation resource ID #0x"
- + Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
- } catch (IOException ex) {
- NotFoundException rnf = new NotFoundException(
- "Can't load animation resource ID #0x"
- + Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
- } finally {
- if (parser != null) parser.close();
- }
-
- }
-
- private static Interpolator createInterpolatorFromXml(Context c, XmlPullParser parser)
- throws XmlPullParserException, IOException {
-
- Interpolator interpolator = null;
-
- // Make sure we are on a start tag.
- int type = parser.getEventType();
- int depth = parser.getDepth();
-
- while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
- && type != XmlPullParser.END_DOCUMENT) {
-
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
-
- AttributeSet attrs = Xml.asAttributeSet(parser);
-
- String name = parser.getName();
-
-
- if (name.equals("linearInterpolator")) {
- interpolator = new LinearInterpolator(c, attrs);
- } else if (name.equals("accelerateInterpolator")) {
- interpolator = new AccelerateInterpolator(c, attrs);
- } else if (name.equals("decelerateInterpolator")) {
- interpolator = new DecelerateInterpolator(c, attrs);
- } else if (name.equals("accelerateDecelerateInterpolator")) {
- interpolator = new AccelerateDecelerateInterpolator(c, attrs);
- } else if (name.equals("cycleInterpolator")) {
- interpolator = new CycleInterpolator(c, attrs);
- } else {
- throw new RuntimeException("Unknown interpolator name: " + parser.getName());
- }
-
- }
-
- return interpolator;
-
- }
-}
diff --git a/core/java/android/view/animation/CycleInterpolator.java b/core/java/android/view/animation/CycleInterpolator.java
deleted file mode 100644
index d355c23..0000000
--- a/core/java/android/view/animation/CycleInterpolator.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-
-/**
- * Repeats the animation for a specified number of cycles. The
- * rate of change follows a sinusoidal pattern.
- *
- */
-public class CycleInterpolator implements Interpolator {
- public CycleInterpolator(float cycles) {
- mCycles = cycles;
- }
-
- public CycleInterpolator(Context context, AttributeSet attrs) {
- TypedArray a =
- context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.CycleInterpolator);
-
- mCycles = a.getFloat(com.android.internal.R.styleable.CycleInterpolator_cycles, 1.0f);
-
- a.recycle();
- }
-
- public float getInterpolation(float input) {
- return (float)(Math.sin(2 * mCycles * Math.PI * input));
- }
-
- private float mCycles;
-}
diff --git a/core/java/android/view/animation/DecelerateInterpolator.java b/core/java/android/view/animation/DecelerateInterpolator.java
deleted file mode 100644
index 176169e..0000000
--- a/core/java/android/view/animation/DecelerateInterpolator.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-
-/**
- * An interpolator where the rate of change starts out quickly and
- * and then decelerates.
- *
- */
-public class DecelerateInterpolator implements Interpolator {
- public DecelerateInterpolator() {
- }
-
- /**
- * Constructor
- *
- * @param factor Degree to which the animation should be eased. Seting factor to 1.0f produces
- * an upside-down y=x^2 parabola. Increasing factor above 1.0f makes exaggerates the
- * ease-out effect (i.e., it starts even faster and ends evens slower)
- */
- public DecelerateInterpolator(float factor) {
- mFactor = factor;
- }
-
- public DecelerateInterpolator(Context context, AttributeSet attrs) {
- TypedArray a =
- context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.DecelerateInterpolator);
-
- mFactor = a.getFloat(com.android.internal.R.styleable.DecelerateInterpolator_factor, 1.0f);
-
- a.recycle();
- }
-
- public float getInterpolation(float input) {
- if (mFactor == 1.0f) {
- return (float)(1.0f - (1.0f - input) * (1.0f - input));
- } else {
- return (float)(1.0f - Math.pow((1.0f - input), 2 * mFactor));
- }
- }
-
- private float mFactor = 1.0f;
-}
diff --git a/core/java/android/view/animation/GridLayoutAnimationController.java b/core/java/android/view/animation/GridLayoutAnimationController.java
deleted file mode 100644
index 9161d8b..0000000
--- a/core/java/android/view/animation/GridLayoutAnimationController.java
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import android.view.View;
-import android.view.ViewGroup;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-
-import java.util.Random;
-
-/**
- * A layout animation controller is used to animated a grid layout's children.
- *
- * While {@link LayoutAnimationController} relies only on the index of the child
- * in the view group to compute the animation delay, this class uses both the
- * X and Y coordinates of the child within a grid.
- *
- * In addition, the animation direction can be controlled. The default direction
- * is <code>DIRECTION_LEFT_TO_RIGHT | DIRECTION_TOP_TO_BOTTOM</code>. You can
- * also set the animation priority to columns or rows. The default priority is
- * none.
- *
- * Information used to compute the animation delay of each child are stored
- * in an instance of
- * {@link android.view.animation.GridLayoutAnimationController.AnimationParameters},
- * itself stored in the {@link android.view.ViewGroup.LayoutParams} of the view.
- *
- * @see LayoutAnimationController
- * @see android.widget.GridView
- *
- * @attr ref android.R.styleable#GridLayoutAnimation_columnDelay
- * @attr ref android.R.styleable#GridLayoutAnimation_rowDelay
- * @attr ref android.R.styleable#GridLayoutAnimation_direction
- * @attr ref android.R.styleable#GridLayoutAnimation_directionPriority
- */
-public class GridLayoutAnimationController extends LayoutAnimationController {
- /**
- * Animates the children starting from the left of the grid to the right.
- */
- public static final int DIRECTION_LEFT_TO_RIGHT = 0x0;
-
- /**
- * Animates the children starting from the right of the grid to the left.
- */
- public static final int DIRECTION_RIGHT_TO_LEFT = 0x1;
-
- /**
- * Animates the children starting from the top of the grid to the bottom.
- */
- public static final int DIRECTION_TOP_TO_BOTTOM = 0x0;
-
- /**
- * Animates the children starting from the bottom of the grid to the top.
- */
- public static final int DIRECTION_BOTTOM_TO_TOP = 0x2;
-
- /**
- * Bitmask used to retrieve the horizontal component of the direction.
- */
- public static final int DIRECTION_HORIZONTAL_MASK = 0x1;
-
- /**
- * Bitmask used to retrieve the vertical component of the direction.
- */
- public static final int DIRECTION_VERTICAL_MASK = 0x2;
-
- /**
- * Rows and columns are animated at the same time.
- */
- public static final int PRIORITY_NONE = 0;
-
- /**
- * Columns are animated first.
- */
- public static final int PRIORITY_COLUMN = 1;
-
- /**
- * Rows are animated first.
- */
- public static final int PRIORITY_ROW = 2;
-
- private float mColumnDelay;
- private float mRowDelay;
-
- private int mDirection;
- private int mDirectionPriority;
-
- /**
- * Creates a new grid layout animation controller from external resources.
- *
- * @param context the Context the view group is running in, through which
- * it can access the resources
- * @param attrs the attributes of the XML tag that is inflating the
- * layout animation controller
- */
- public GridLayoutAnimationController(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.GridLayoutAnimation);
-
- Animation.Description d = Animation.Description.parseValue(
- a.peekValue(com.android.internal.R.styleable.GridLayoutAnimation_columnDelay));
- mColumnDelay = d.value;
- d = Animation.Description.parseValue(
- a.peekValue(com.android.internal.R.styleable.GridLayoutAnimation_rowDelay));
- mRowDelay = d.value;
- //noinspection PointlessBitwiseExpression
- mDirection = a.getInt(com.android.internal.R.styleable.GridLayoutAnimation_direction,
- DIRECTION_LEFT_TO_RIGHT | DIRECTION_TOP_TO_BOTTOM);
- mDirectionPriority = a.getInt(com.android.internal.R.styleable.GridLayoutAnimation_directionPriority,
- PRIORITY_NONE);
-
- a.recycle();
- }
-
- /**
- * Creates a new layout animation controller with a delay of 50%
- * for both rows and columns and the specified animation.
- *
- * @param animation the animation to use on each child of the view group
- */
- public GridLayoutAnimationController(Animation animation) {
- this(animation, 0.5f, 0.5f);
- }
-
- /**
- * Creates a new layout animation controller with the specified delays
- * and the specified animation.
- *
- * @param animation the animation to use on each child of the view group
- * @param columnDelay the delay by which each column animation must be offset
- * @param rowDelay the delay by which each row animation must be offset
- */
- public GridLayoutAnimationController(Animation animation, float columnDelay, float rowDelay) {
- super(animation);
- mColumnDelay = columnDelay;
- mRowDelay = rowDelay;
- }
-
- /**
- * Returns the delay by which the children's animation are offset from one
- * column to the other. The delay is expressed as a fraction of the
- * animation duration.
- *
- * @return a fraction of the animation duration
- *
- * @see #setColumnDelay(float)
- * @see #getRowDelay()
- * @see #setRowDelay(float)
- */
- public float getColumnDelay() {
- return mColumnDelay;
- }
-
- /**
- * Sets the delay, as a fraction of the animation duration, by which the
- * children's animations are offset from one column to the other.
- *
- * @param columnDelay a fraction of the animation duration
- *
- * @see #getColumnDelay()
- * @see #getRowDelay()
- * @see #setRowDelay(float)
- */
- public void setColumnDelay(float columnDelay) {
- mColumnDelay = columnDelay;
- }
-
- /**
- * Returns the delay by which the children's animation are offset from one
- * row to the other. The delay is expressed as a fraction of the
- * animation duration.
- *
- * @return a fraction of the animation duration
- *
- * @see #setRowDelay(float)
- * @see #getColumnDelay()
- * @see #setColumnDelay(float)
- */
- public float getRowDelay() {
- return mRowDelay;
- }
-
- /**
- * Sets the delay, as a fraction of the animation duration, by which the
- * children's animations are offset from one row to the other.
- *
- * @param rowDelay a fraction of the animation duration
- *
- * @see #getRowDelay()
- * @see #getColumnDelay()
- * @see #setColumnDelay(float)
- */
- public void setRowDelay(float rowDelay) {
- mRowDelay = rowDelay;
- }
-
- /**
- * Returns the direction of the animation. {@link #DIRECTION_HORIZONTAL_MASK}
- * and {@link #DIRECTION_VERTICAL_MASK} can be used to retrieve the
- * horizontal and vertical components of the direction.
- *
- * @return the direction of the animation
- *
- * @see #setDirection(int)
- * @see #DIRECTION_BOTTOM_TO_TOP
- * @see #DIRECTION_TOP_TO_BOTTOM
- * @see #DIRECTION_LEFT_TO_RIGHT
- * @see #DIRECTION_RIGHT_TO_LEFT
- * @see #DIRECTION_HORIZONTAL_MASK
- * @see #DIRECTION_VERTICAL_MASK
- */
- public int getDirection() {
- return mDirection;
- }
-
- /**
- * Sets the direction of the animation. The direction is expressed as an
- * integer containing a horizontal and vertical component. For instance,
- * <code>DIRECTION_BOTTOM_TO_TOP | DIRECTION_RIGHT_TO_LEFT</code>.
- *
- * @param direction the direction of the animation
- *
- * @see #getDirection()
- * @see #DIRECTION_BOTTOM_TO_TOP
- * @see #DIRECTION_TOP_TO_BOTTOM
- * @see #DIRECTION_LEFT_TO_RIGHT
- * @see #DIRECTION_RIGHT_TO_LEFT
- * @see #DIRECTION_HORIZONTAL_MASK
- * @see #DIRECTION_VERTICAL_MASK
- */
- public void setDirection(int direction) {
- mDirection = direction;
- }
-
- /**
- * Returns the direction priority for the animation. The priority can
- * be either {@link #PRIORITY_NONE}, {@link #PRIORITY_COLUMN} or
- * {@link #PRIORITY_ROW}.
- *
- * @return the priority of the animation direction
- *
- * @see #setDirectionPriority(int)
- * @see #PRIORITY_COLUMN
- * @see #PRIORITY_NONE
- * @see #PRIORITY_ROW
- */
- public int getDirectionPriority() {
- return mDirectionPriority;
- }
-
- /**
- * Specifies the direction priority of the animation. For instance,
- * {@link #PRIORITY_COLUMN} will give priority to columns: the animation
- * will first play on the column, then on the rows.Z
- *
- * @param directionPriority the direction priority of the animation
- *
- * @see #getDirectionPriority()
- * @see #PRIORITY_COLUMN
- * @see #PRIORITY_NONE
- * @see #PRIORITY_ROW
- */
- public void setDirectionPriority(int directionPriority) {
- mDirectionPriority = directionPriority;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean willOverlap() {
- return mColumnDelay < 1.0f || mRowDelay < 1.0f;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected long getDelayForView(View view) {
- ViewGroup.LayoutParams lp = view.getLayoutParams();
- AnimationParameters params = (AnimationParameters) lp.layoutAnimationParameters;
-
- if (params == null) {
- return 0;
- }
-
- final int column = getTransformedColumnIndex(params);
- final int row = getTransformedRowIndex(params);
-
- final int rowsCount = params.rowsCount;
- final int columnsCount = params.columnsCount;
-
- final long duration = mAnimation.getDuration();
- final float columnDelay = mColumnDelay * duration;
- final float rowDelay = mRowDelay * duration;
-
- float totalDelay;
- long viewDelay;
-
- if (mInterpolator == null) {
- mInterpolator = new LinearInterpolator();
- }
-
- switch (mDirectionPriority) {
- case PRIORITY_COLUMN:
- viewDelay = (long) (row * rowDelay + column * rowsCount * rowDelay);
- totalDelay = rowsCount * rowDelay + columnsCount * rowsCount * rowDelay;
- break;
- case PRIORITY_ROW:
- viewDelay = (long) (column * columnDelay + row * columnsCount * columnDelay);
- totalDelay = columnsCount * columnDelay + rowsCount * columnsCount * columnDelay;
- break;
- case PRIORITY_NONE:
- default:
- viewDelay = (long) (column * columnDelay + row * rowDelay);
- totalDelay = columnsCount * columnDelay + rowsCount * rowDelay;
- break;
- }
-
- float normalizedDelay = viewDelay / totalDelay;
- normalizedDelay = mInterpolator.getInterpolation(normalizedDelay);
-
- return (long) (normalizedDelay * totalDelay);
- }
-
- private int getTransformedColumnIndex(AnimationParameters params) {
- int index;
- switch (getOrder()) {
- case ORDER_REVERSE:
- index = params.columnsCount - 1 - params.column;
- break;
- case ORDER_RANDOM:
- if (mRandomizer == null) {
- mRandomizer = new Random();
- }
- index = (int) (params.columnsCount * mRandomizer.nextFloat());
- break;
- case ORDER_NORMAL:
- default:
- index = params.column;
- break;
- }
-
- int direction = mDirection & DIRECTION_HORIZONTAL_MASK;
- if (direction == DIRECTION_RIGHT_TO_LEFT) {
- index = params.columnsCount - 1 - index;
- }
-
- return index;
- }
-
- private int getTransformedRowIndex(AnimationParameters params) {
- int index;
- switch (getOrder()) {
- case ORDER_REVERSE:
- index = params.rowsCount - 1 - params.row;
- break;
- case ORDER_RANDOM:
- if (mRandomizer == null) {
- mRandomizer = new Random();
- }
- index = (int) (params.rowsCount * mRandomizer.nextFloat());
- break;
- case ORDER_NORMAL:
- default:
- index = params.row;
- break;
- }
-
- int direction = mDirection & DIRECTION_VERTICAL_MASK;
- if (direction == DIRECTION_BOTTOM_TO_TOP) {
- index = params.rowsCount - 1 - index;
- }
-
- return index;
- }
-
- /**
- * The set of parameters that has to be attached to each view contained in
- * the view group animated by the grid layout animation controller. These
- * parameters are used to compute the start time of each individual view's
- * animation.
- */
- public static class AnimationParameters extends
- LayoutAnimationController.AnimationParameters {
- /**
- * The view group's column to which the view belongs.
- */
- public int column;
-
- /**
- * The view group's row to which the view belongs.
- */
- public int row;
-
- /**
- * The number of columns in the view's enclosing grid layout.
- */
- public int columnsCount;
-
- /**
- * The number of rows in the view's enclosing grid layout.
- */
- public int rowsCount;
- }
-}
diff --git a/core/java/android/view/animation/Interpolator.java b/core/java/android/view/animation/Interpolator.java
deleted file mode 100644
index d14c3e3..0000000
--- a/core/java/android/view/animation/Interpolator.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-/**
- * An interpolator defines the rate of change of an animation. This allows
- * the basic animation effects (alpha, scale, translate, rotate) to be
- * accelerated, decelerated, repeated, etc.
- */
-public interface Interpolator {
-
- /**
- * Maps a point on the timeline to a multiplier to be applied to the
- * transformations of an animation.
- *
- * @param input A value between 0 and 1.0 indicating our current point
- * in the animation where 0 represents the start and 1.0 represents
- * the end
- * @return The interpolation value. This value can be more than 1.0 for
- * Interpolators which overshoot their targets, or less than 0 for
- * Interpolators that undershoot their targets.
- */
- float getInterpolation(float input);
-
-}
diff --git a/core/java/android/view/animation/LayoutAnimationController.java b/core/java/android/view/animation/LayoutAnimationController.java
deleted file mode 100644
index 882e738..0000000
--- a/core/java/android/view/animation/LayoutAnimationController.java
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-
-import java.util.Random;
-
-/**
- * A layout animation controller is used to animated a layout's, or a view
- * group's, children. Each child uses the same animation but for every one of
- * them, the animation starts at a different time. A layout animation controller
- * is used by {@link android.view.ViewGroup} to compute the delay by which each
- * child's animation start must be offset. The delay is computed by using
- * characteristics of each child, like its index in the view group.
- *
- * This standard implementation computes the delay by multiplying a fixed
- * amount of miliseconds by the index of the child in its parent view group.
- * Subclasses are supposed to override
- * {@link #getDelayForView(android.view.View)} to implement a different way
- * of computing the delay. For instance, a
- * {@link android.view.animation.GridLayoutAnimationController} will compute the
- * delay based on the column and row indices of the child in its parent view
- * group.
- *
- * Information used to compute the animation delay of each child are stored
- * in an instance of
- * {@link android.view.animation.LayoutAnimationController.AnimationParameters},
- * itself stored in the {@link android.view.ViewGroup.LayoutParams} of the view.
- *
- * @attr ref android.R.styleable#LayoutAnimation_delay
- * @attr ref android.R.styleable#LayoutAnimation_animationOrder
- * @attr ref android.R.styleable#LayoutAnimation_interpolator
- * @attr ref android.R.styleable#LayoutAnimation_animation
- */
-public class LayoutAnimationController {
- /**
- * Distributes the animation delays in the order in which view were added
- * to their view group.
- */
- public static final int ORDER_NORMAL = 0;
-
- /**
- * Distributes the animation delays in the reverse order in which view were
- * added to their view group.
- */
- public static final int ORDER_REVERSE = 1;
-
- /**
- * Randomly distributes the animation delays.
- */
- public static final int ORDER_RANDOM = 2;
-
- /**
- * The animation applied on each child of the view group on which this
- * layout animation controller is set.
- */
- protected Animation mAnimation;
-
- /**
- * The randomizer used when the order is set to random. Subclasses should
- * use this object to avoid creating their own.
- */
- protected Random mRandomizer;
-
- /**
- * The interpolator used to interpolate the delays.
- */
- protected Interpolator mInterpolator;
-
- private float mDelay;
- private int mOrder;
-
- private long mDuration;
- private long mMaxDelay;
-
- /**
- * Creates a new layout animation controller from external resources.
- *
- * @param context the Context the view group is running in, through which
- * it can access the resources
- * @param attrs the attributes of the XML tag that is inflating the
- * layout animation controller
- */
- public LayoutAnimationController(Context context, AttributeSet attrs) {
- TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.LayoutAnimation);
-
- Animation.Description d = Animation.Description.parseValue(
- a.peekValue(com.android.internal.R.styleable.LayoutAnimation_delay));
- mDelay = d.value;
-
- mOrder = a.getInt(com.android.internal.R.styleable.LayoutAnimation_animationOrder, ORDER_NORMAL);
-
- int resource = a.getResourceId(com.android.internal.R.styleable.LayoutAnimation_animation, 0);
- if (resource > 0) {
- setAnimation(context, resource);
- }
-
- resource = a.getResourceId(com.android.internal.R.styleable.LayoutAnimation_interpolator, 0);
- if (resource > 0) {
- setInterpolator(context, resource);
- }
-
- a.recycle();
- }
-
- /**
- * Creates a new layout animation controller with a delay of 50%
- * and the specified animation.
- *
- * @param animation the animation to use on each child of the view group
- */
- public LayoutAnimationController(Animation animation) {
- this(animation, 0.5f);
- }
-
- /**
- * Creates a new layout animation controller with the specified delay
- * and the specified animation.
- *
- * @param animation the animation to use on each child of the view group
- * @param delay the delay by which each child's animation must be offset
- */
- public LayoutAnimationController(Animation animation, float delay) {
- mDelay = delay;
- setAnimation(animation);
- }
-
- /**
- * Returns the order used to compute the delay of each child's animation.
- *
- * @return one of {@link #ORDER_NORMAL}, {@link #ORDER_REVERSE} or
- * {@link #ORDER_RANDOM)
- *
- * @attr ref android.R.styleable#LayoutAnimation_animationOrder
- */
- public int getOrder() {
- return mOrder;
- }
-
- /**
- * Sets the order used to compute the delay of each child's animation.
- *
- * @param order one of {@link #ORDER_NORMAL}, {@link #ORDER_REVERSE} or
- * {@link #ORDER_RANDOM}
- *
- * @attr ref android.R.styleable#LayoutAnimation_animationOrder
- */
- public void setOrder(int order) {
- mOrder = order;
- }
-
- /**
- * Sets the animation to be run on each child of the view group on which
- * this layout animation controller is .
- *
- * @param context the context from which the animation must be inflated
- * @param resourceID the resource identifier of the animation
- *
- * @see #setAnimation(Animation)
- * @see #getAnimation()
- *
- * @attr ref android.R.styleable#LayoutAnimation_animation
- */
- public void setAnimation(Context context, int resourceID) {
- setAnimation(AnimationUtils.loadAnimation(context, resourceID));
- }
-
- /**
- * Sets the animation to be run on each child of the view group on which
- * this layout animation controller is .
- *
- * @param animation the animation to run on each child of the view group
-
- * @see #setAnimation(android.content.Context, int)
- * @see #getAnimation()
- *
- * @attr ref android.R.styleable#LayoutAnimation_animation
- */
- public void setAnimation(Animation animation) {
- mAnimation = animation;
- mAnimation.setFillBefore(true);
- }
-
- /**
- * Returns the animation applied to each child of the view group on which
- * this controller is set.
- *
- * @return an {@link android.view.animation.Animation} instance
- *
- * @see #setAnimation(android.content.Context, int)
- * @see #setAnimation(Animation)
- */
- public Animation getAnimation() {
- return mAnimation;
- }
-
- /**
- * Sets the interpolator used to interpolate the delays between the
- * children.
- *
- * @param context the context from which the interpolator must be inflated
- * @param resourceID the resource identifier of the interpolator
- *
- * @see #getInterpolator()
- * @see #setInterpolator(Interpolator)
- *
- * @attr ref android.R.styleable#LayoutAnimation_interpolator
- */
- public void setInterpolator(Context context, int resourceID) {
- setInterpolator(AnimationUtils.loadInterpolator(context, resourceID));
- }
-
- /**
- * Sets the interpolator used to interpolate the delays between the
- * children.
- *
- * @param interpolator the interpolator
- *
- * @see #getInterpolator()
- * @see #setInterpolator(Interpolator)
- *
- * @attr ref android.R.styleable#LayoutAnimation_interpolator
- */
- public void setInterpolator(Interpolator interpolator) {
- mInterpolator = interpolator;
- }
-
- /**
- * Returns the interpolator used to interpolate the delays between the
- * children.
- *
- * @return an {@link android.view.animation.Interpolator}
- */
- public Interpolator getInterpolator() {
- return mInterpolator;
- }
-
- /**
- * Returns the delay by which the children's animation are offset. The
- * delay is expressed as a fraction of the animation duration.
- *
- * @return a fraction of the animation duration
- *
- * @see #setDelay(float)
- */
- public float getDelay() {
- return mDelay;
- }
-
- /**
- * Sets the delay, as a fraction of the animation duration, by which the
- * children's animations are offset. The general formula is:
- *
- * <pre>
- * child animation delay = child index * delay * animation duration
- * </pre>
- *
- * @param delay a fraction of the animation duration
- *
- * @see #getDelay()
- */
- public void setDelay(float delay) {
- mDelay = delay;
- }
-
- /**
- * Indicates whether two children's animations will overlap. Animations
- * overlap when the delay is lower than 100% (or 1.0).
- *
- * @return true if animations will overlap, false otherwise
- */
- public boolean willOverlap() {
- return mDelay < 1.0f;
- }
-
- /**
- * Starts the animation.
- */
- public void start() {
- mDuration = mAnimation.getDuration();
- mMaxDelay = Long.MIN_VALUE;
- mAnimation.setStartTime(-1);
- }
-
- /**
- * Returns the animation to be applied to the specified view. The returned
- * animation is delayed by an offset computed according to the information
- * provided by
- * {@link android.view.animation.LayoutAnimationController.AnimationParameters}.
- * This method is called by view groups to obtain the animation to set on
- * a specific child.
- *
- * @param view the view to animate
- * @return an animation delayed by the number of milliseconds returned by
- * {@link #getDelayForView(android.view.View)}
- *
- * @see #getDelay()
- * @see #setDelay(float)
- * @see #getDelayForView(android.view.View)
- */
- public final Animation getAnimationForView(View view) {
- final long delay = getDelayForView(view) + mAnimation.getStartOffset();
- mMaxDelay = Math.max(mMaxDelay, delay);
-
- try {
- final Animation animation = mAnimation.clone();
- animation.setStartOffset(delay);
- return animation;
- } catch (CloneNotSupportedException e) {
- return null;
- }
- }
-
- /**
- * Indicates whether the layout animation is over or not. A layout animation
- * is considered done when the animation with the longest delay is done.
- *
- * @return true if all of the children's animations are over, false otherwise
- */
- public boolean isDone() {
- return AnimationUtils.currentAnimationTimeMillis() >
- mAnimation.getStartTime() + mMaxDelay + mDuration;
- }
-
- /**
- * Returns the amount of milliseconds by which the specified view's
- * animation must be delayed or offset. Subclasses should override this
- * method to return a suitable value.
- *
- * This implementation returns <code>child animation delay</code>
- * milliseconds where:
- *
- * <pre>
- * child animation delay = child index * delay
- * </pre>
- *
- * The index is retrieved from the
- * {@link android.view.animation.LayoutAnimationController.AnimationParameters}
- * found in the view's {@link android.view.ViewGroup.LayoutParams}.
- *
- * @param view the view for which to obtain the animation's delay
- * @return a delay in milliseconds
- *
- * @see #getAnimationForView(android.view.View)
- * @see #getDelay()
- * @see #getTransformedIndex(android.view.animation.LayoutAnimationController.AnimationParameters)
- * @see android.view.ViewGroup.LayoutParams
- */
- protected long getDelayForView(View view) {
- ViewGroup.LayoutParams lp = view.getLayoutParams();
- AnimationParameters params = lp.layoutAnimationParameters;
-
- if (params == null) {
- return 0;
- }
-
- final float delay = mDelay * mAnimation.getDuration();
- final long viewDelay = (long) (getTransformedIndex(params) * delay);
- final float totalDelay = delay * params.count;
-
- if (mInterpolator == null) {
- mInterpolator = new LinearInterpolator();
- }
-
- float normalizedDelay = viewDelay / totalDelay;
- normalizedDelay = mInterpolator.getInterpolation(normalizedDelay);
-
- return (long) (normalizedDelay * totalDelay);
- }
-
- /**
- * Transforms the index stored in
- * {@link android.view.animation.LayoutAnimationController.AnimationParameters}
- * by the order returned by {@link #getOrder()}. Subclasses should override
- * this method to provide additional support for other types of ordering.
- * This method should be invoked by
- * {@link #getDelayForView(android.view.View)} prior to any computation.
- *
- * @param params the animation parameters containing the index
- * @return a transformed index
- */
- protected int getTransformedIndex(AnimationParameters params) {
- switch (getOrder()) {
- case ORDER_REVERSE:
- return params.count - 1 - params.index;
- case ORDER_RANDOM:
- if (mRandomizer == null) {
- mRandomizer = new Random();
- }
- return (int) (params.count * mRandomizer.nextFloat());
- case ORDER_NORMAL:
- default:
- return params.index;
- }
- }
-
- /**
- * The set of parameters that has to be attached to each view contained in
- * the view group animated by the layout animation controller. These
- * parameters are used to compute the start time of each individual view's
- * animation.
- */
- public static class AnimationParameters {
- /**
- * The number of children in the view group containing the view to which
- * these parameters are attached.
- */
- public int count;
-
- /**
- * The index of the view to which these parameters are attached in its
- * containing view group.
- */
- public int index;
- }
-}
diff --git a/core/java/android/view/animation/LinearInterpolator.java b/core/java/android/view/animation/LinearInterpolator.java
deleted file mode 100644
index 96a039f..0000000
--- a/core/java/android/view/animation/LinearInterpolator.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-/**
- * An interpolator where the rate of change is constant
- *
- */
-public class LinearInterpolator implements Interpolator {
-
- public LinearInterpolator() {
- }
-
- public LinearInterpolator(Context context, AttributeSet attrs) {
- }
-
- public float getInterpolation(float input) {
- return input;
- }
-}
diff --git a/core/java/android/view/animation/RotateAnimation.java b/core/java/android/view/animation/RotateAnimation.java
deleted file mode 100644
index 2f51b91..0000000
--- a/core/java/android/view/animation/RotateAnimation.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-
-/**
- * An animation that controls the rotation of an object. This rotation takes
- * place int the X-Y plane. You can specify the point to use for the center of
- * the rotation, where (0,0) is the top left point. If not specified, (0,0) is
- * the default rotation point.
- *
- */
-public class RotateAnimation extends Animation {
- private float mFromDegrees;
- private float mToDegrees;
-
- private int mPivotXType = ABSOLUTE;
- private int mPivotYType = ABSOLUTE;
- private float mPivotXValue = 0.0f;
- private float mPivotYValue = 0.0f;
-
- private float mPivotX;
- private float mPivotY;
-
- /**
- * Constructor used whan an RotateAnimation is loaded from a resource.
- *
- * @param context Application context to use
- * @param attrs Attribute set from which to read values
- */
- public RotateAnimation(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.RotateAnimation);
-
- mFromDegrees = a.getFloat(
- com.android.internal.R.styleable.RotateAnimation_fromDegrees, 0.0f);
- mToDegrees = a.getFloat(com.android.internal.R.styleable.RotateAnimation_toDegrees, 0.0f);
-
- Description d = Description.parseValue(a.peekValue(
- com.android.internal.R.styleable.RotateAnimation_pivotX));
- mPivotXType = d.type;
- mPivotXValue = d.value;
-
- d = Description.parseValue(a.peekValue(
- com.android.internal.R.styleable.RotateAnimation_pivotY));
- mPivotYType = d.type;
- mPivotYValue = d.value;
-
- a.recycle();
- }
-
- /**
- * Constructor to use when building a RotateAnimation from code.
- * Default pivotX/pivotY point is (0,0).
- *
- * @param fromDegrees Rotation offset to apply at the start of the
- * animation.
- *
- * @param toDegrees Rotation offset to apply at the end of the animation.
- */
- public RotateAnimation(float fromDegrees, float toDegrees) {
- mFromDegrees = fromDegrees;
- mToDegrees = toDegrees;
- mPivotX = 0.0f;
- mPivotY = 0.0f;
- }
-
- /**
- * Constructor to use when building a RotateAnimation from code
- *
- * @param fromDegrees Rotation offset to apply at the start of the
- * animation.
- *
- * @param toDegrees Rotation offset to apply at the end of the animation.
- *
- * @param pivotX The X coordinate of the point about which the object is
- * being rotated, specified as an absolute number where 0 is the left
- * edge.
- * @param pivotY The Y coordinate of the point about which the object is
- * being rotated, specified as an absolute number where 0 is the top
- * edge.
- */
- public RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY) {
- mFromDegrees = fromDegrees;
- mToDegrees = toDegrees;
-
- mPivotXType = ABSOLUTE;
- mPivotYType = ABSOLUTE;
- mPivotXValue = pivotX;
- mPivotYValue = pivotY;
- }
-
- /**
- * Constructor to use when building a RotateAnimation from code
- *
- * @param fromDegrees Rotation offset to apply at the start of the
- * animation.
- *
- * @param toDegrees Rotation offset to apply at the end of the animation.
- *
- * @param pivotXType Specifies how pivotXValue should be interpreted. One of
- * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
- * Animation.RELATIVE_TO_PARENT.
- * @param pivotXValue The X coordinate of the point about which the object
- * is being rotated, specified as an absolute number where 0 is the
- * left edge. This value can either be an absolute number if
- * pivotXType is ABSOLUTE, or a percentage (where 1.0 is 100%)
- * otherwise.
- * @param pivotYType Specifies how pivotYValue should be interpreted. One of
- * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
- * Animation.RELATIVE_TO_PARENT.
- * @param pivotYValue The Y coordinate of the point about which the object
- * is being rotated, specified as an absolute number where 0 is the
- * top edge. This value can either be an absolute number if
- * pivotYType is ABSOLUTE, or a percentage (where 1.0 is 100%)
- * otherwise.
- */
- public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,
- int pivotYType, float pivotYValue) {
- mFromDegrees = fromDegrees;
- mToDegrees = toDegrees;
-
- mPivotXValue = pivotXValue;
- mPivotXType = pivotXType;
- mPivotYValue = pivotYValue;
- mPivotYType = pivotYType;
- }
-
- @Override
- protected void applyTransformation(float interpolatedTime, Transformation t) {
- float degrees = mFromDegrees + ((mToDegrees - mFromDegrees) * interpolatedTime);
-
- if (mPivotX == 0.0f && mPivotY == 0.0f) {
- t.getMatrix().setRotate(degrees);
- } else {
- t.getMatrix().setRotate(degrees, mPivotX, mPivotY);
- }
- }
-
- @Override
- public void initialize(int width, int height, int parentWidth, int parentHeight) {
- super.initialize(width, height, parentWidth, parentHeight);
- mPivotX = resolveSize(mPivotXType, mPivotXValue, width, parentWidth);
- mPivotY = resolveSize(mPivotYType, mPivotYValue, height, parentHeight);
- }
-}
diff --git a/core/java/android/view/animation/ScaleAnimation.java b/core/java/android/view/animation/ScaleAnimation.java
deleted file mode 100644
index 122ed6d..0000000
--- a/core/java/android/view/animation/ScaleAnimation.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-
-/**
- * An animation that controls the scale of an object. You can specify the point
- * to use for the center of scaling.
- *
- */
-public class ScaleAnimation extends Animation {
- private float mFromX;
- private float mToX;
- private float mFromY;
- private float mToY;
-
- private int mPivotXType = ABSOLUTE;
- private int mPivotYType = ABSOLUTE;
- private float mPivotXValue = 0.0f;
- private float mPivotYValue = 0.0f;
-
- private float mPivotX;
- private float mPivotY;
-
- /**
- * Constructor used whan an ScaleAnimation is loaded from a resource.
- *
- * @param context Application context to use
- * @param attrs Attribute set from which to read values
- */
- public ScaleAnimation(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.ScaleAnimation);
-
- mFromX = a.getFloat(com.android.internal.R.styleable.ScaleAnimation_fromXScale, 0.0f);
- mToX = a.getFloat(com.android.internal.R.styleable.ScaleAnimation_toXScale, 0.0f);
-
- mFromY = a.getFloat(com.android.internal.R.styleable.ScaleAnimation_fromYScale, 0.0f);
- mToY = a.getFloat(com.android.internal.R.styleable.ScaleAnimation_toYScale, 0.0f);
-
- Description d = Description.parseValue(a.peekValue(
- com.android.internal.R.styleable.ScaleAnimation_pivotX));
- mPivotXType = d.type;
- mPivotXValue = d.value;
-
- d = Description.parseValue(a.peekValue(
- com.android.internal.R.styleable.ScaleAnimation_pivotY));
- mPivotYType = d.type;
- mPivotYValue = d.value;
-
- a.recycle();
- }
-
- /**
- * Constructor to use when building a ScaleAnimation from code
- *
- * @param fromX Horizontal scaling factor to apply at the start of the
- * animation
- * @param toX Horizontal scaling factor to apply at the end of the animation
- * @param fromY Vertical scaling factor to apply at the start of the
- * animation
- * @param toY Vertical scaling factor to apply at the end of the animation
- */
- public ScaleAnimation(float fromX, float toX, float fromY, float toY) {
- mFromX = fromX;
- mToX = toX;
- mFromY = fromY;
- mToY = toY;
- mPivotX = 0;
- mPivotY = 0;
- }
-
- /**
- * Constructor to use when building a ScaleAnimation from code
- *
- * @param fromX Horizontal scaling factor to apply at the start of the
- * animation
- * @param toX Horizontal scaling factor to apply at the end of the animation
- * @param fromY Vertical scaling factor to apply at the start of the
- * animation
- * @param toY Vertical scaling factor to apply at the end of the animation
- * @param pivotX The X coordinate of the point about which the object is
- * being scaled, specified as an absolute number where 0 is the left
- * edge. (This point remains fixed while the object changes size.)
- * @param pivotY The Y coordinate of the point about which the object is
- * being scaled, specified as an absolute number where 0 is the top
- * edge. (This point remains fixed while the object changes size.)
- */
- public ScaleAnimation(float fromX, float toX, float fromY, float toY,
- float pivotX, float pivotY) {
- mFromX = fromX;
- mToX = toX;
- mFromY = fromY;
- mToY = toY;
-
- mPivotXType = ABSOLUTE;
- mPivotYType = ABSOLUTE;
- mPivotXValue = pivotX;
- mPivotYValue = pivotY;
- }
-
- /**
- * Constructor to use when building a ScaleAnimation from code
- *
- * @param fromX Horizontal scaling factor to apply at the start of the
- * animation
- * @param toX Horizontal scaling factor to apply at the end of the animation
- * @param fromY Vertical scaling factor to apply at the start of the
- * animation
- * @param toY Vertical scaling factor to apply at the end of the animation
- * @param pivotXType Specifies how pivotXValue should be interpreted. One of
- * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
- * Animation.RELATIVE_TO_PARENT.
- * @param pivotXValue The X coordinate of the point about which the object
- * is being scaled, specified as an absolute number where 0 is the
- * left edge. (This point remains fixed while the object changes
- * size.) This value can either be an absolute number if pivotXType
- * is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
- * @param pivotYType Specifies how pivotYValue should be interpreted. One of
- * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
- * Animation.RELATIVE_TO_PARENT.
- * @param pivotYValue The Y coordinate of the point about which the object
- * is being scaled, specified as an absolute number where 0 is the
- * top edge. (This point remains fixed while the object changes
- * size.) This value can either be an absolute number if pivotYType
- * is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
- */
- public ScaleAnimation(float fromX, float toX, float fromY, float toY,
- int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {
- mFromX = fromX;
- mToX = toX;
- mFromY = fromY;
- mToY = toY;
-
- mPivotXValue = pivotXValue;
- mPivotXType = pivotXType;
- mPivotYValue = pivotYValue;
- mPivotYType = pivotYType;
- }
-
- @Override
- protected void applyTransformation(float interpolatedTime, Transformation t) {
- float sx = 1.0f;
- float sy = 1.0f;
-
- if (mFromX != 1.0f || mToX != 1.0f) {
- sx = mFromX + ((mToX - mFromX) * interpolatedTime);
- }
- if (mFromY != 1.0f || mToY != 1.0f) {
- sy = mFromY + ((mToY - mFromY) * interpolatedTime);
- }
-
- if (mPivotX == 0 && mPivotY == 0) {
- t.getMatrix().setScale(sx, sy);
- } else {
- t.getMatrix().setScale(sx, sy, mPivotX, mPivotY);
- }
- }
-
- @Override
- public void initialize(int width, int height, int parentWidth, int parentHeight) {
- super.initialize(width, height, parentWidth, parentHeight);
-
- mPivotX = resolveSize(mPivotXType, mPivotXValue, width, parentWidth);
- mPivotY = resolveSize(mPivotYType, mPivotYValue, height, parentHeight);
- }
-}
diff --git a/core/java/android/view/animation/Transformation.java b/core/java/android/view/animation/Transformation.java
deleted file mode 100644
index f9e85bf..0000000
--- a/core/java/android/view/animation/Transformation.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import android.graphics.Matrix;
-
-/**
- * Defines the transformation to be applied at
- * one point in time of an Animation.
- *
- */
-public class Transformation {
- /**
- * Indicates a transformation that has no effect (alpha = 1 and identity matrix.)
- */
- public static int TYPE_IDENTITY = 0x0;
- /**
- * Indicates a transformation that applies an alpha only (uses an identity matrix.)
- */
- public static int TYPE_ALPHA = 0x1;
- /**
- * Indicates a transformation that applies a matrix only (alpha = 1.)
- */
- public static int TYPE_MATRIX = 0x2;
- /**
- * Indicates a transformation that applies an alpha and a matrix.
- */
- public static int TYPE_BOTH = TYPE_ALPHA | TYPE_MATRIX;
-
- protected Matrix mMatrix;
- protected float mAlpha;
- protected int mTransformationType;
-
- /**
- * Creates a new transformation with alpha = 1 and the identity matrix.
- */
- public Transformation() {
- clear();
- }
-
- /**
- * Reset the transformation to a state that leaves the object
- * being animated in an unmodified state. The transformation type is
- * {@link #TYPE_BOTH} by default.
- */
- public void clear() {
- if (mMatrix == null) {
- mMatrix = new Matrix();
- } else {
- mMatrix.reset();
- }
- mAlpha = 1.0f;
- mTransformationType = TYPE_BOTH;
- }
-
- /**
- * Indicates the nature of this transformation.
- *
- * @return {@link #TYPE_ALPHA}, {@link #TYPE_MATRIX},
- * {@link #TYPE_BOTH} or {@link #TYPE_IDENTITY}.
- */
- public int getTransformationType() {
- return mTransformationType;
- }
-
- /**
- * Sets the transformation type.
- *
- * @param transformationType One of {@link #TYPE_ALPHA},
- * {@link #TYPE_MATRIX}, {@link #TYPE_BOTH} or
- * {@link #TYPE_IDENTITY}.
- */
- public void setTransformationType(int transformationType) {
- mTransformationType = transformationType;
- }
-
- /**
- * Clones the specified transformation.
- *
- * @param t The transformation to clone.
- */
- public void set(Transformation t) {
- mAlpha = t.getAlpha();
- mMatrix.set(t.getMatrix());
- mTransformationType = t.getTransformationType();
- }
-
- /**
- * Apply this Transformation to an existing Transformation, e.g. apply
- * a scale effect to something that has already been rotated.
- * @param t
- */
- public void compose(Transformation t) {
- mAlpha *= t.getAlpha();
- mMatrix.preConcat(t.getMatrix());
- }
-
- /**
- * @return The 3x3 Matrix representing the trnasformation to apply to the
- * coordinates of the object being animated
- */
- public Matrix getMatrix() {
- return mMatrix;
- }
-
- /**
- * Sets the degree of transparency
- * @param alpha 1.0 means fully opaqe and 0.0 means fully transparent
- */
- public void setAlpha(float alpha) {
- mAlpha = alpha;
- }
-
- /**
- * @return The degree of transparency
- */
- public float getAlpha() {
- return mAlpha;
- }
-
- @Override
- public String toString() {
- return "Transformation{alpha=" + mAlpha + " matrix="
- + mMatrix.toShortString() + "}";
- }
-
- /**
- * Return a string representation of the transformation in a compact form.
- */
- public String toShortString() {
- return "{alpha=" + mAlpha + " matrix=" + mMatrix.toShortString() + "}";
- }
-}
diff --git a/core/java/android/view/animation/TranslateAnimation.java b/core/java/android/view/animation/TranslateAnimation.java
deleted file mode 100644
index ae21768..0000000
--- a/core/java/android/view/animation/TranslateAnimation.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.animation;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-
-/**
- * An animation that controls the position of an object. See the
- * {@link android.view.animation full package} description for details and
- * sample code.
- *
- */
-public class TranslateAnimation extends Animation {
- private int mFromXType = ABSOLUTE;
- private int mToXType = ABSOLUTE;
-
- private int mFromYType = ABSOLUTE;
- private int mToYType = ABSOLUTE;
-
- private float mFromXValue = 0.0f;
- private float mToXValue = 0.0f;
-
- private float mFromYValue = 0.0f;
- private float mToYValue = 0.0f;
-
- private float mFromXDelta;
- private float mToXDelta;
- private float mFromYDelta;
- private float mToYDelta;
-
- /**
- * Constructor used whan an ScaleAnimation is loaded from a resource.
- *
- * @param context Application context to use
- * @param attrs Attribute set from which to read values
- */
- public TranslateAnimation(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.TranslateAnimation);
-
- Description d = Description.parseValue(a.peekValue(
- com.android.internal.R.styleable.TranslateAnimation_fromXDelta));
- mFromXType = d.type;
- mFromXValue = d.value;
-
- d = Description.parseValue(a.peekValue(
- com.android.internal.R.styleable.TranslateAnimation_toXDelta));
- mToXType = d.type;
- mToXValue = d.value;
-
- d = Description.parseValue(a.peekValue(
- com.android.internal.R.styleable.TranslateAnimation_fromYDelta));
- mFromYType = d.type;
- mFromYValue = d.value;
-
- d = Description.parseValue(a.peekValue(
- com.android.internal.R.styleable.TranslateAnimation_toYDelta));
- mToYType = d.type;
- mToYValue = d.value;
-
- a.recycle();
- }
-
- /**
- * Constructor to use when building a ScaleAnimation from code
- *
- * @param fromXDelta Change in X coordinate to apply at the start of the
- * animation
- * @param toXDelta Change in X coordinate to apply at the end of the
- * animation
- * @param fromYDelta Change in Y coordinate to apply at the start of the
- * animation
- * @param toYDelta Change in Y coordinate to apply at the end of the
- * animation
- */
- public TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) {
- mFromXValue = fromXDelta;
- mToXValue = toXDelta;
- mFromYValue = fromYDelta;
- mToYValue = toYDelta;
-
- mFromXType = ABSOLUTE;
- mToXType = ABSOLUTE;
- mFromYType = ABSOLUTE;
- mToYType = ABSOLUTE;
- }
-
- /**
- * Constructor to use when building a ScaleAnimation from code
- *
- * @param fromXType Specifies how fromXValue should be interpreted. One of
- * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
- * Animation.RELATIVE_TO_PARENT.
- * @param fromXValue Change in X coordinate to apply at the start of the
- * animation. This value can either be an absolute number if fromXType
- * is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
- * @param toXType Specifies how toXValue should be interpreted. One of
- * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
- * Animation.RELATIVE_TO_PARENT.
- * @param toXValue Change in X coordinate to apply at the end of the
- * animation. This value can either be an absolute number if toXType
- * is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
- * @param fromYType Specifies how fromYValue should be interpreted. One of
- * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
- * Animation.RELATIVE_TO_PARENT.
- * @param fromYValue Change in Y coordinate to apply at the start of the
- * animation. This value can either be an absolute number if fromYType
- * is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
- * @param toYType Specifies how toYValue should be interpreted. One of
- * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
- * Animation.RELATIVE_TO_PARENT.
- * @param toYValue Change in Y coordinate to apply at the end of the
- * animation. This value can either be an absolute number if toYType
- * is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
- */
- public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,
- int fromYType, float fromYValue, int toYType, float toYValue) {
-
- mFromXValue = fromXValue;
- mToXValue = toXValue;
- mFromYValue = fromYValue;
- mToYValue = toYValue;
-
- mFromXType = fromXType;
- mToXType = toXType;
- mFromYType = fromYType;
- mToYType = toYType;
- }
-
-
- @Override
- protected void applyTransformation(float interpolatedTime, Transformation t) {
- float dx = mFromXDelta;
- float dy = mFromYDelta;
- if (mFromXDelta != mToXDelta) {
- dx = mFromXDelta + ((mToXDelta - mFromXDelta) * interpolatedTime);
- }
- if (mFromYDelta != mToYDelta) {
- dy = mFromYDelta + ((mToYDelta - mFromYDelta) * interpolatedTime);
- }
-
- t.getMatrix().setTranslate(dx, dy);
- }
-
- @Override
- public void initialize(int width, int height, int parentWidth, int parentHeight) {
- super.initialize(width, height, parentWidth, parentHeight);
- mFromXDelta = resolveSize(mFromXType, mFromXValue, width, parentWidth);
- mToXDelta = resolveSize(mToXType, mToXValue, width, parentWidth);
- mFromYDelta = resolveSize(mFromYType, mFromYValue, height, parentHeight);
- mToYDelta = resolveSize(mToYType, mToYValue, height, parentHeight);
- }
-}
diff --git a/core/java/android/view/animation/package.html b/core/java/android/view/animation/package.html
deleted file mode 100755
index 87c99bb..0000000
--- a/core/java/android/view/animation/package.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<html>
-<body>
-<p>Provides classes that handle tweened animations.</p>
-<p>Android provides two mechanisms
- that you can use to create simple animations: <strong>tweened
- animation</strong>, in which you tell Android to perform a series of simple
- transformations (position, size, rotation, and so on) to the content of a
- View; and <strong>frame-by-frame animation</strong>, which loads a series of Drawable resources
- one after the other. Both animation types can be used in any View object
- to provide simple rotating timers, activity icons, and other useful UI elements.
- Tweened animation is handled by this package (android.view.animation); frame-by-frame animation is
- handled by the {@link android.graphics.drawable.AnimationDrawable} class.
- </p>
-
-<p>For more information on creating tweened or frame-by-frame animations, read the discussion in the
-<a href="{@docRoot}guide/topics/graphics/2d-graphics.html#tween-animation">2D Graphics</a>
-Dev Guide.</p>
-
-</body>
-</html>
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
deleted file mode 100644
index 6fbc174..0000000
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.view.inputmethod;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.SystemClock;
-import android.text.Editable;
-import android.text.NoCopySpan;
-import android.text.Selection;
-import android.text.Spannable;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-import android.text.TextUtils;
-import android.text.method.MetaKeyKeyListener;
-import android.util.Log;
-import android.util.LogPrinter;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewRoot;
-
-class ComposingText implements NoCopySpan {
-}
-
-/**
- * Base class for implementors of the InputConnection interface, taking care
- * of most of the common behavior for providing a connection to an Editable.
- * Implementors of this class will want to be sure to implement
- * {@link #getEditable} to provide access to their own editable object.
- */
-public class BaseInputConnection implements InputConnection {
- private static final boolean DEBUG = false;
- private static final String TAG = "BaseInputConnection";
- static final Object COMPOSING = new ComposingText();
-
- final InputMethodManager mIMM;
- final Handler mH;
- final View mTargetView;
- final boolean mDummyMode;
-
- private Object[] mDefaultComposingSpans;
-
- Editable mEditable;
- KeyCharacterMap mKeyCharacterMap;
-
- BaseInputConnection(InputMethodManager mgr, boolean dummyMode) {
- mIMM = mgr;
- mTargetView = null;
- mH = null;
- mDummyMode = dummyMode;
- }
-
- public BaseInputConnection(View targetView, boolean dummyMode) {
- mIMM = (InputMethodManager)targetView.getContext().getSystemService(
- Context.INPUT_METHOD_SERVICE);
- mH = targetView.getHandler();
- mTargetView = targetView;
- mDummyMode = dummyMode;
- }
-
- public static final void removeComposingSpans(Spannable text) {
- text.removeSpan(COMPOSING);
- Object[] sps = text.getSpans(0, text.length(), Object.class);
- if (sps != null) {
- for (int i=sps.length-1; i>=0; i--) {
- Object o = sps[i];
- if ((text.getSpanFlags(o)&Spanned.SPAN_COMPOSING) != 0) {
- text.removeSpan(o);
- }
- }
- }
- }
-
- public static void setComposingSpans(Spannable text) {
- final Object[] sps = text.getSpans(0, text.length(), Object.class);
- if (sps != null) {
- for (int i=sps.length-1; i>=0; i--) {
- final Object o = sps[i];
- if (o == COMPOSING) {
- text.removeSpan(o);
- continue;
- }
- final int fl = text.getSpanFlags(o);
- if ((fl&(Spanned.SPAN_COMPOSING|Spanned.SPAN_POINT_MARK_MASK))
- != (Spanned.SPAN_COMPOSING|Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)) {
- text.setSpan(o, text.getSpanStart(o), text.getSpanEnd(o),
- (fl&Spanned.SPAN_POINT_MARK_MASK)
- | Spanned.SPAN_COMPOSING
- | Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- }
-
- text.setSpan(COMPOSING, 0, text.length(),
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING);
- }
-
- public static int getComposingSpanStart(Spannable text) {
- return text.getSpanStart(COMPOSING);
- }
-
- public static int getComposingSpanEnd(Spannable text) {
- return text.getSpanEnd(COMPOSING);
- }
-
- /**
- * Return the target of edit operations. The default implementation
- * returns its own fake editable that is just used for composing text;
- * subclasses that are real text editors should override this and
- * supply their own.
- */
- public Editable getEditable() {
- if (mEditable == null) {
- mEditable = Editable.Factory.getInstance().newEditable("");
- Selection.setSelection(mEditable, 0);
- }
- return mEditable;
- }
-
- /**
- * Default implementation does nothing.
- */
- public boolean beginBatchEdit() {
- return false;
- }
-
- /**
- * Default implementation does nothing.
- */
- public boolean endBatchEdit() {
- return false;
- }
-
- /**
- * Default implementation uses
- * {@link MetaKeyKeyListener#clearMetaKeyState(long, int)
- * MetaKeyKeyListener.clearMetaKeyState(long, int)} to clear the state.
- */
- public boolean clearMetaKeyStates(int states) {
- final Editable content = getEditable();
- if (content == null) return false;
- MetaKeyKeyListener.clearMetaKeyState(content, states);
- return true;
- }
-
- /**
- * Default implementation does nothing.
- */
- public boolean commitCompletion(CompletionInfo text) {
- return false;
- }
-
- /**
- * Default implementation replaces any existing composing text with
- * the given text. In addition, only if dummy mode, a key event is
- * sent for the new text and the current editable buffer cleared.
- */
- public boolean commitText(CharSequence text, int newCursorPosition) {
- if (DEBUG) Log.v(TAG, "commitText " + text);
- replaceText(text, newCursorPosition, false);
- sendCurrentText();
- return true;
- }
-
- /**
- * The default implementation performs the deletion around the current
- * selection position of the editable text.
- */
- public boolean deleteSurroundingText(int leftLength, int rightLength) {
- if (DEBUG) Log.v(TAG, "deleteSurroundingText " + leftLength
- + " / " + rightLength);
- final Editable content = getEditable();
- if (content == null) return false;
-
- beginBatchEdit();
-
- int a = Selection.getSelectionStart(content);
- int b = Selection.getSelectionEnd(content);
-
- if (a > b) {
- int tmp = a;
- a = b;
- b = tmp;
- }
-
- // ignore the composing text.
- int ca = getComposingSpanStart(content);
- int cb = getComposingSpanEnd(content);
- if (cb < ca) {
- int tmp = ca;
- ca = cb;
- cb = tmp;
- }
- if (ca != -1 && cb != -1) {
- if (ca < a) a = ca;
- if (cb > b) b = cb;
- }
-
- int deleted = 0;
-
- if (leftLength > 0) {
- int start = a - leftLength;
- if (start < 0) start = 0;
- content.delete(start, a);
- deleted = a - start;
- }
-
- if (rightLength > 0) {
- b = b - deleted;
-
- int end = b + rightLength;
- if (end > content.length()) end = content.length();
-
- content.delete(b, end);
- }
-
- endBatchEdit();
-
- return true;
- }
-
- /**
- * The default implementation removes the composing state from the
- * current editable text. In addition, only if dummy mode, a key event is
- * sent for the new text and the current editable buffer cleared.
- */
- public boolean finishComposingText() {
- if (DEBUG) Log.v(TAG, "finishComposingText");
- final Editable content = getEditable();
- if (content != null) {
- beginBatchEdit();
- removeComposingSpans(content);
- endBatchEdit();
- sendCurrentText();
- }
- return true;
- }
-
- /**
- * The default implementation uses TextUtils.getCapsMode to get the
- * cursor caps mode for the current selection position in the editable
- * text, unless in dummy mode in which case 0 is always returned.
- */
- public int getCursorCapsMode(int reqModes) {
- if (mDummyMode) return 0;
-
- final Editable content = getEditable();
- if (content == null) return 0;
-
- int a = Selection.getSelectionStart(content);
- int b = Selection.getSelectionEnd(content);
-
- if (a > b) {
- int tmp = a;
- a = b;
- b = tmp;
- }
-
- return TextUtils.getCapsMode(content, a, reqModes);
- }
-
- /**
- * The default implementation always returns null.
- */
- public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
- return null;
- }
-
- /**
- * The default implementation returns the given amount of text from the
- * current cursor position in the buffer.
- */
- public CharSequence getTextBeforeCursor(int length, int flags) {
- final Editable content = getEditable();
- if (content == null) return null;
-
- int a = Selection.getSelectionStart(content);
- int b = Selection.getSelectionEnd(content);
-
- if (a > b) {
- int tmp = a;
- a = b;
- b = tmp;
- }
-
- if (length > a) {
- length = a;
- }
-
- if ((flags&GET_TEXT_WITH_STYLES) != 0) {
- return content.subSequence(a - length, a);
- }
- return TextUtils.substring(content, a - length, a);
- }
-
- /**
- * The default implementation returns the given amount of text from the
- * current cursor position in the buffer.
- */
- public CharSequence getTextAfterCursor(int length, int flags) {
- final Editable content = getEditable();
- if (content == null) return null;
-
- int a = Selection.getSelectionStart(content);
- int b = Selection.getSelectionEnd(content);
-
- if (a > b) {
- int tmp = a;
- a = b;
- b = tmp;
- }
-
- if (b + length > content.length()) {
- length = content.length() - b;
- }
-
-
- if ((flags&GET_TEXT_WITH_STYLES) != 0) {
- return content.subSequence(b, b + length);
- }
- return TextUtils.substring(content, b, b + length);
- }
-
- /**
- * The default implementation does nothing.
- */
- public boolean performContextMenuAction(int id) {
- return false;
- }
-
- /**
- * The default implementation does nothing.
- */
- public boolean performPrivateCommand(String action, Bundle data) {
- return false;
- }
-
- /**
- * The default implementation places the given text into the editable,
- * replacing any existing composing text. The new text is marked as
- * in a composing state with the composing style.
- */
- public boolean setComposingText(CharSequence text, int newCursorPosition) {
- if (DEBUG) Log.v(TAG, "setComposingText " + text);
- replaceText(text, newCursorPosition, true);
- return true;
- }
-
- /**
- * The default implementation changes the selection position in the
- * current editable text.
- */
- public boolean setSelection(int start, int end) {
- if (DEBUG) Log.v(TAG, "setSelection " + start + ", " + end);
- final Editable content = getEditable();
- if (content == null) return false;
- int len = content.length();
- if (start > len || end > len) {
- // If the given selection is out of bounds, just ignore it.
- // Most likely the text was changed out from under the IME,
- // the the IME is going to have to update all of its state
- // anyway.
- return true;
- }
- Selection.setSelection(content, start, end);
- return true;
- }
-
- /**
- * Provides standard implementation for sending a key event to the window
- * attached to the input connection's view.
- */
- public boolean sendKeyEvent(KeyEvent event) {
- synchronized (mIMM.mH) {
- Handler h = mH;
- if (h == null) {
- if (mIMM.mServedView != null) {
- h = mIMM.mServedView.getHandler();
- }
- }
- if (h != null) {
- h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME,
- event));
- }
- }
- return false;
- }
-
- /**
- * Updates InputMethodManager with the current fullscreen mode.
- */
- public boolean reportFullscreenMode(boolean enabled) {
- mIMM.setFullscreenMode(enabled);
- return true;
- }
-
- private void sendCurrentText() {
- if (!mDummyMode) {
- return;
- }
-
- Editable content = getEditable();
- if (content != null) {
- final int N = content.length();
- if (N == 0) {
- return;
- }
- if (N == 1) {
- // If it's 1 character, we have a chance of being
- // able to generate normal key events...
- if (mKeyCharacterMap == null) {
- mKeyCharacterMap = KeyCharacterMap.load(
- KeyCharacterMap.BUILT_IN_KEYBOARD);
- }
- char[] chars = new char[1];
- content.getChars(0, 1, chars, 0);
- KeyEvent[] events = mKeyCharacterMap.getEvents(chars);
- if (events != null) {
- for (int i=0; i<events.length; i++) {
- if (DEBUG) Log.v(TAG, "Sending: " + events[i]);
- sendKeyEvent(events[i]);
- }
- content.clear();
- return;
- }
- }
-
- // Otherwise, revert to the special key event containing
- // the actual characters.
- KeyEvent event = new KeyEvent(SystemClock.uptimeMillis(),
- content.toString(), KeyCharacterMap.BUILT_IN_KEYBOARD, 0);
- sendKeyEvent(event);
- content.clear();
- }
- }
-
- private void replaceText(CharSequence text, int newCursorPosition,
- boolean composing) {
- final Editable content = getEditable();
- if (content == null) {
- return;
- }
-
- beginBatchEdit();
-
- // delete composing text set previously.
- int a = getComposingSpanStart(content);
- int b = getComposingSpanEnd(content);
-
- if (DEBUG) Log.v(TAG, "Composing span: " + a + " to " + b);
-
- if (b < a) {
- int tmp = a;
- a = b;
- b = tmp;
- }
-
- if (a != -1 && b != -1) {
- removeComposingSpans(content);
- } else {
- a = Selection.getSelectionStart(content);
- b = Selection.getSelectionEnd(content);
- if (a >=0 && b>= 0 && a != b) {
- if (b < a) {
- int tmp = a;
- a = b;
- b = tmp;
- }
- }
- }
-
- if (composing) {
- Spannable sp = null;
- if (!(text instanceof Spannable)) {
- sp = new SpannableStringBuilder(text);
- text = sp;
- if (mDefaultComposingSpans == null) {
- Context context;
- if (mTargetView != null) {
- context = mTargetView.getContext();
- } else if (mIMM.mServedView != null) {
- context = mIMM.mServedView.getContext();
- } else {
- context = null;
- }
- if (context != null) {
- TypedArray ta = context.getTheme()
- .obtainStyledAttributes(new int[] {
- com.android.internal.R.attr.candidatesTextStyleSpans
- });
- CharSequence style = ta.getText(0);
- ta.recycle();
- if (style != null && style instanceof Spanned) {
- mDefaultComposingSpans = ((Spanned)style).getSpans(
- 0, style.length(), Object.class);
- }
- }
- }
- if (mDefaultComposingSpans != null) {
- for (int i = 0; i < mDefaultComposingSpans.length; ++i) {
- sp.setSpan(mDefaultComposingSpans[i], 0, sp.length(),
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- } else {
- sp = (Spannable)text;
- }
- setComposingSpans(sp);
- }
-
- if (DEBUG) Log.v(TAG, "Replacing from " + a + " to " + b + " with \""
- + text + "\", composing=" + composing
- + ", type=" + text.getClass().getCanonicalName());
-
- if (DEBUG) {
- LogPrinter lp = new LogPrinter(Log.VERBOSE, TAG);
- lp.println("Current text:");
- TextUtils.dumpSpans(content, lp, " ");
- lp.println("Composing text:");
- TextUtils.dumpSpans(text, lp, " ");
- }
-
- // Position the cursor appropriately, so that after replacing the
- // desired range of text it will be located in the correct spot.
- // This allows us to deal with filters performing edits on the text
- // we are providing here.
- if (newCursorPosition > 0) {
- newCursorPosition += b - 1;
- } else {
- newCursorPosition += a;
- }
- if (newCursorPosition < 0) newCursorPosition = 0;
- if (newCursorPosition > content.length())
- newCursorPosition = content.length();
- Selection.setSelection(content, newCursorPosition);
-
- content.replace(a, b, text);
-
- if (DEBUG) {
- LogPrinter lp = new LogPrinter(Log.VERBOSE, TAG);
- lp.println("Final text:");
- TextUtils.dumpSpans(content, lp, " ");
- }
-
- endBatchEdit();
- }
-}
diff --git a/core/java/android/view/inputmethod/CompletionInfo.aidl b/core/java/android/view/inputmethod/CompletionInfo.aidl
deleted file mode 100644
index e601054..0000000
--- a/core/java/android/view/inputmethod/CompletionInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.inputmethod;
-
-parcelable CompletionInfo;
diff --git a/core/java/android/view/inputmethod/CompletionInfo.java b/core/java/android/view/inputmethod/CompletionInfo.java
deleted file mode 100644
index 3a8fe72..0000000
--- a/core/java/android/view/inputmethod/CompletionInfo.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.view.inputmethod;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-/**
- * Information about a single text completion that an editor has reported to
- * an input method.
- */
-public final class CompletionInfo implements Parcelable {
- static final String TAG = "CompletionInfo";
-
- final long mId;
- final int mPosition;
- final CharSequence mText;
- final CharSequence mLabel;
-
- /**
- * Create a simple completion with just text, no label.
- */
- public CompletionInfo(long id, int index, CharSequence text) {
- mId = id;
- mPosition = index;
- mText = text;
- mLabel = null;
- }
-
- /**
- * Create a full completion with both text and label.
- */
- public CompletionInfo(long id, int index, CharSequence text, CharSequence label) {
- mId = id;
- mPosition = index;
- mText = text;
- mLabel = label;
- }
-
- CompletionInfo(Parcel source) {
- mId = source.readLong();
- mPosition = source.readInt();
- mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- }
-
- /**
- * Return the abstract identifier for this completion, typically
- * corresponding to the id associated with it in the original adapter.
- */
- public long getId() {
- return mId;
- }
-
- /**
- * Return the original position of this completion, typically
- * corresponding to its position in the original adapter.
- */
- public int getPosition() {
- return mPosition;
- }
-
- /**
- * Return the actual text associated with this completion. This is the
- * real text that will be inserted into the editor if the user selects it.
- */
- public CharSequence getText() {
- return mText;
- }
-
- /**
- * Return the user-visible label for the completion, or null if the plain
- * text should be shown. If non-null, this will be what the user sees as
- * the completion option instead of the actual text.
- */
- public CharSequence getLabel() {
- return mLabel;
- }
-
- @Override
- public String toString() {
- return "CompletionInfo{#" + mPosition + " \"" + mText
- + "\" id=" + mId + " label=" + mLabel + "}";
- }
-
- /**
- * Used to package this object into a {@link Parcel}.
- *
- * @param dest The {@link Parcel} to be written.
- * @param flags The flags used for parceling.
- */
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(mId);
- dest.writeInt(mPosition);
- TextUtils.writeToParcel(mText, dest, flags);
- TextUtils.writeToParcel(mLabel, dest, flags);
- }
-
- /**
- * Used to make this class parcelable.
- */
- public static final Parcelable.Creator<CompletionInfo> CREATOR
- = new Parcelable.Creator<CompletionInfo>() {
- public CompletionInfo createFromParcel(Parcel source) {
- return new CompletionInfo(source);
- }
-
- public CompletionInfo[] newArray(int size) {
- return new CompletionInfo[size];
- }
- };
-
- public int describeContents() {
- return 0;
- }
-}
diff --git a/core/java/android/view/inputmethod/EditorInfo.aidl b/core/java/android/view/inputmethod/EditorInfo.aidl
deleted file mode 100644
index 48068f0..0000000
--- a/core/java/android/view/inputmethod/EditorInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.inputmethod;
-
-parcelable EditorInfo;
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
deleted file mode 100644
index b2f26d7..0000000
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ /dev/null
@@ -1,171 +0,0 @@
-package android.view.inputmethod;
-
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.InputType;
-import android.text.TextUtils;
-import android.util.Printer;
-
-/**
- * An EditorInfo describes several attributes of a text editing object
- * that an input method is communicating with (typically an EditText), most
- * importantly the type of text content it contains.
- */
-public class EditorInfo implements InputType, Parcelable {
- /**
- * The content type of the text box, whose bits are defined by
- * {@link InputType}.
- *
- * @see InputType
- * @see #TYPE_MASK_CLASS
- * @see #TYPE_MASK_VARIATION
- * @see #TYPE_MASK_FLAGS
- */
- public int inputType = TYPE_NULL;
-
- /**
- * A string supplying additional information about the content type that
- * is private to a particular IME implementation. The string must be
- * scoped to a package owned by the implementation, to ensure there are
- * no conflicts between implementations, but other than that you can put
- * whatever you want in it to communicate with the IME. For example,
- * you could have a string that supplies an argument like
- * <code>"com.example.myapp.SpecialMode=3"</code>. This field is can be
- * filled in from the {@link android.R.attr#editorPrivateContentType}
- * attribute of a TextView.
- */
- public String privateContentType = null;
-
- /**
- * The text offset of the start of the selection at the time editing
- * began; -1 if not known.
- */
- public int initialSelStart = -1;
-
- /**
- * The text offset of the end of the selection at the time editing
- * began; -1 if not known.
- */
- public int initialSelEnd = -1;
-
- /**
- * The capitalization mode of the first character being edited in the
- * text. Values may be any combination of
- * {@link TextUtils#CAP_MODE_CHARACTERS TextUtils.CAP_MODE_CHARACTERS},
- * {@link TextUtils#CAP_MODE_WORDS TextUtils.CAP_MODE_WORDS}, and
- * {@link TextUtils#CAP_MODE_SENTENCES TextUtils.CAP_MODE_SENTENCES}, though
- * you should generally just take a non-zero value to mean start out in
- * caps mode.
- */
- public int initialCapsMode = 0;
-
- /**
- * The "hint" text of the text view, typically shown in-line when the
- * text is empty to tell the user what to enter.
- */
- public CharSequence hintText;
-
- /**
- * A label to show to the user describing the text they are writing.
- */
- public CharSequence label;
-
- /**
- * Name of the package that owns this editor.
- */
- public String packageName;
-
- /**
- * Identifier for the editor's field. This is optional, and may be
- * 0. By default it is filled in with the result of
- * {@link android.view.View#getId() View.getId()} on the View that
- * is being edited.
- */
- public int fieldId;
-
- /**
- * Additional name for the editor's field. This can supply additional
- * name information for the field. By default it is null. The actual
- * contents have no meaning.
- */
- public String fieldName;
-
- /**
- * Any extra data to supply to the input method. This is for extended
- * communication with specific input methods; the name fields in the
- * bundle should be scoped (such as "com.mydomain.im.SOME_FIELD") so
- * that they don't conflict with others. This field is can be
- * filled in from the {@link android.R.attr#editorExtras}
- * attribute of a TextView.
- */
- public Bundle extras;
-
- /**
- * Write debug output of this object.
- */
- public void dump(Printer pw, String prefix) {
- pw.println(prefix + "inputType=0x" + Integer.toHexString(inputType)
- + " privateContentType=" + privateContentType);
- pw.println(prefix + "initialSelStart=" + initialSelStart
- + " initialSelEnd=" + initialSelEnd
- + " initialCapsMode=0x"
- + Integer.toHexString(initialCapsMode));
- pw.println(prefix + "hintText=" + hintText
- + " label=" + label);
- pw.println(prefix + "packageName=" + packageName
- + " fieldId=" + fieldId
- + " fieldName=" + fieldName);
- pw.println(prefix + "extras=" + extras);
- }
-
- /**
- * Used to package this object into a {@link Parcel}.
- *
- * @param dest The {@link Parcel} to be written.
- * @param flags The flags used for parceling.
- */
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(inputType);
- dest.writeString(privateContentType);
- dest.writeInt(initialSelStart);
- dest.writeInt(initialSelEnd);
- dest.writeInt(initialCapsMode);
- TextUtils.writeToParcel(hintText, dest, flags);
- TextUtils.writeToParcel(label, dest, flags);
- dest.writeString(packageName);
- dest.writeInt(fieldId);
- dest.writeString(fieldName);
- dest.writeBundle(extras);
- }
-
- /**
- * Used to make this class parcelable.
- */
- public static final Parcelable.Creator<EditorInfo> CREATOR = new Parcelable.Creator<EditorInfo>() {
- public EditorInfo createFromParcel(Parcel source) {
- EditorInfo res = new EditorInfo();
- res.inputType = source.readInt();
- res.privateContentType = source.readString();
- res.initialSelStart = source.readInt();
- res.initialSelEnd = source.readInt();
- res.initialCapsMode = source.readInt();
- res.hintText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- res.label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- res.packageName = source.readString();
- res.fieldId = source.readInt();
- res.fieldName = source.readString();
- res.extras = source.readBundle();
- return res;
- }
-
- public EditorInfo[] newArray(int size) {
- return new EditorInfo[size];
- }
- };
-
- public int describeContents() {
- return 0;
- }
-
-}
diff --git a/core/java/android/view/inputmethod/ExtractedText.aidl b/core/java/android/view/inputmethod/ExtractedText.aidl
deleted file mode 100644
index 95e56d7..0000000
--- a/core/java/android/view/inputmethod/ExtractedText.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.inputmethod;
-
-parcelable ExtractedText;
diff --git a/core/java/android/view/inputmethod/ExtractedText.java b/core/java/android/view/inputmethod/ExtractedText.java
deleted file mode 100644
index e5d3cae..0000000
--- a/core/java/android/view/inputmethod/ExtractedText.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package android.view.inputmethod;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-/**
- * Information about text that has been extracted for use by an input method.
- */
-public class ExtractedText implements Parcelable {
- /**
- * The text that has been extracted.
- */
- public CharSequence text;
-
- /**
- * The offset in the overall text at which the extracted text starts.
- */
- public int startOffset;
-
- /**
- * If the content is a report of a partial text change, this is the
- * offset where the change starts and it runs until
- * {@link #partialEndOffset}. If the content is the full text, this
- * field is -1.
- */
- public int partialStartOffset;
-
- /**
- * If the content is a report of a partial text change, this is the offset
- * where the change ends. Note that the actual text may be larger or
- * smaller than the difference between this and {@link #partialEndOffset},
- * meaning a reduction or increase, respectively, in the total text.
- */
- public int partialEndOffset;
-
- /**
- * The offset where the selection currently starts within the extracted
- * text. The real selection start position is at
- * <var>startOffset</var>+<var>selectionStart</var>.
- */
- public int selectionStart;
-
- /**
- * The offset where the selection currently ends within the extracted
- * text. The real selection end position is at
- * <var>startOffset</var>+<var>selectionEnd</var>.
- */
- public int selectionEnd;
-
- /**
- * Bit for {@link #flags}: set if the text being edited can only be on
- * a single line.
- */
- public static final int FLAG_SINGLE_LINE = 0x0001;
-
- /**
- * Additional bit flags of information about the edited text.
- */
- public int flags;
-
- /**
- * Used to package this object into a {@link Parcel}.
- *
- * @param dest The {@link Parcel} to be written.
- * @param flags The flags used for parceling.
- */
- public void writeToParcel(Parcel dest, int flags) {
- TextUtils.writeToParcel(text, dest, flags);
- dest.writeInt(startOffset);
- dest.writeInt(partialStartOffset);
- dest.writeInt(partialEndOffset);
- dest.writeInt(selectionStart);
- dest.writeInt(selectionEnd);
- dest.writeInt(flags);
- }
-
- /**
- * Used to make this class parcelable.
- */
- public static final Parcelable.Creator<ExtractedText> CREATOR = new Parcelable.Creator<ExtractedText>() {
- public ExtractedText createFromParcel(Parcel source) {
- ExtractedText res = new ExtractedText();
- res.text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- res.startOffset = source.readInt();
- res.partialStartOffset = source.readInt();
- res.partialEndOffset = source.readInt();
- res.selectionStart = source.readInt();
- res.selectionEnd = source.readInt();
- res.flags = source.readInt();
- return res;
- }
-
- public ExtractedText[] newArray(int size) {
- return new ExtractedText[size];
- }
- };
-
- public int describeContents() {
- return 0;
- }
-}
diff --git a/core/java/android/view/inputmethod/ExtractedTextRequest.aidl b/core/java/android/view/inputmethod/ExtractedTextRequest.aidl
deleted file mode 100644
index c69acc7..0000000
--- a/core/java/android/view/inputmethod/ExtractedTextRequest.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.inputmethod;
-
-parcelable ExtractedTextRequest;
diff --git a/core/java/android/view/inputmethod/ExtractedTextRequest.java b/core/java/android/view/inputmethod/ExtractedTextRequest.java
deleted file mode 100644
index e84b094..0000000
--- a/core/java/android/view/inputmethod/ExtractedTextRequest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package android.view.inputmethod;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-/**
- * Description of what an input method would like from an application when
- * extract text from its input editor.
- */
-public class ExtractedTextRequest implements Parcelable {
- /**
- * Arbitrary integer that can be supplied in the request, which will be
- * delivered back when reporting updates.
- */
- public int token;
-
- /**
- * Additional request flags, having the same possible values as the
- * flags parameter of {@link InputConnection#getTextBeforeCursor
- * InputConnection.getTextBeforeCursor()}.
- */
- public int flags;
-
- /**
- * Hint for the maximum number of lines to return.
- */
- public int hintMaxLines;
-
- /**
- * Hint for the maximum number of characters to return.
- */
- public int hintMaxChars;
-
- /**
- * Used to package this object into a {@link Parcel}.
- *
- * @param dest The {@link Parcel} to be written.
- * @param flags The flags used for parceling.
- */
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(token);
- dest.writeInt(this.flags);
- dest.writeInt(hintMaxLines);
- dest.writeInt(hintMaxChars);
- }
-
- /**
- * Used to make this class parcelable.
- */
- public static final Parcelable.Creator<ExtractedTextRequest> CREATOR
- = new Parcelable.Creator<ExtractedTextRequest>() {
- public ExtractedTextRequest createFromParcel(Parcel source) {
- ExtractedTextRequest res = new ExtractedTextRequest();
- res.token = source.readInt();
- res.flags = source.readInt();
- res.hintMaxLines = source.readInt();
- res.hintMaxChars = source.readInt();
- return res;
- }
-
- public ExtractedTextRequest[] newArray(int size) {
- return new ExtractedTextRequest[size];
- }
- };
-
- public int describeContents() {
- return 0;
- }
-}
diff --git a/core/java/android/view/inputmethod/InputBinding.aidl b/core/java/android/view/inputmethod/InputBinding.aidl
deleted file mode 100644
index ea09d8b..0000000
--- a/core/java/android/view/inputmethod/InputBinding.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.inputmethod;
-
-parcelable InputBinding;
diff --git a/core/java/android/view/inputmethod/InputBinding.java b/core/java/android/view/inputmethod/InputBinding.java
deleted file mode 100644
index f4209ef..0000000
--- a/core/java/android/view/inputmethod/InputBinding.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.view.inputmethod;
-
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-/**
- * Information given to an {@link InputMethod} about a client connecting
- * to it.
- */
-public final class InputBinding implements Parcelable {
- static final String TAG = "InputBinding";
-
- /**
- * The connection back to the client.
- */
- final InputConnection mConnection;
-
- /**
- * A remotable token for the connection back to the client.
- */
- final IBinder mConnectionToken;
-
- /**
- * The UID where this binding came from.
- */
- final int mUid;
-
- /**
- * The PID where this binding came from.
- */
- final int mPid;
-
- /**
- * Constructor.
- *
- * @param conn The interface for communicating back with the application.
- * @param connToken A remoteable token for communicating across processes.
- * @param uid The user id of the client of this binding.
- * @param pid The process id of where the binding came from.
- */
- public InputBinding(InputConnection conn, IBinder connToken,
- int uid, int pid) {
- mConnection = conn;
- mConnectionToken = connToken;
- mUid = uid;
- mPid = pid;
- }
-
- /**
- * Constructor from an existing InputBinding taking a new local input
- * connection interface.
- *
- * @param conn The new connection interface.
- * @param binding Existing binding to copy.
- */
- public InputBinding(InputConnection conn, InputBinding binding) {
- mConnection = conn;
- mConnectionToken = binding.getConnectionToken();
- mUid = binding.getUid();
- mPid = binding.getPid();
- }
-
- InputBinding(Parcel source) {
- mConnection = null;
- mConnectionToken = source.readStrongBinder();
- mUid = source.readInt();
- mPid = source.readInt();
- }
-
- /**
- * Return the connection for interacting back with the application.
- */
- public InputConnection getConnection() {
- return mConnection;
- }
-
- /**
- * Return the token for the connection back to the application. You can
- * not use this directly, it must be converted to a {@link InputConnection}
- * for you.
- */
- public IBinder getConnectionToken() {
- return mConnectionToken;
- }
-
- /**
- * Return the user id of the client associated with this binding.
- */
- public int getUid() {
- return mUid;
- }
-
- /**
- * Return the process id where this binding came from.
- */
- public int getPid() {
- return mPid;
- }
-
- @Override
- public String toString() {
- return "InputBinding{" + mConnectionToken
- + " / uid " + mUid + " / pid " + mPid + "}";
- }
-
- /**
- * Used to package this object into a {@link Parcel}.
- *
- * @param dest The {@link Parcel} to be written.
- * @param flags The flags used for parceling.
- */
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeStrongBinder(mConnectionToken);
- dest.writeInt(mUid);
- dest.writeInt(mPid);
- }
-
- /**
- * Used to make this class parcelable.
- */
- public static final Parcelable.Creator<InputBinding> CREATOR = new Parcelable.Creator<InputBinding>() {
- public InputBinding createFromParcel(Parcel source) {
- return new InputBinding(source);
- }
-
- public InputBinding[] newArray(int size) {
- return new InputBinding[size];
- }
- };
-
- public int describeContents() {
- return 0;
- }
-}
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
deleted file mode 100644
index 530127d..0000000
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.view.inputmethod;
-
-import android.os.Bundle;
-import android.text.Spanned;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-
-/**
- * The InputConnection interface is the communication channel from an
- * {@link InputMethod} back to the application that is receiving its input. It
- * is used to perform such things as reading text around the cursor,
- * committing text to the text box, and sending raw key events to the application.
- *
- * <p>Implementations of this interface should generally be done by
- * subclassing {@link BaseInputConnection}.
- */
-public interface InputConnection {
- /**
- * Flag for use with {@link #getTextAfterCursor} and
- * {@link #getTextBeforeCursor} to have style information returned along
- * with the text. If not set, you will receive only the raw text. If
- * set, you may receive a complex CharSequence of both text and style
- * spans.
- */
- static final int GET_TEXT_WITH_STYLES = 0x0001;
-
- /**
- * Flag for use with {@link #getExtractedText} to indicate you would
- * like to receive updates when the extracted text changes.
- */
- public static final int GET_EXTRACTED_TEXT_MONITOR = 0x0001;
-
- /**
- * Get <var>n</var> characters of text before the current cursor position.
- *
- * <p>This method may fail either if the input connection has become invalid
- * (such as its process crashing) or the client is taking too long to
- * respond with the text (it is given a couple seconds to return).
- * In either case, a null is returned.
- *
- * @param n The expected length of the text.
- * @param flags Supplies additional options controlling how the text is
- * returned. May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
- *
- * @return Returns the text before the cursor position; the length of the
- * returned text might be less than <var>n</var>.
- */
- public CharSequence getTextBeforeCursor(int n, int flags);
-
- /**
- * Get <var>n</var> characters of text after the current cursor position.
- *
- * <p>This method may fail either if the input connection has become invalid
- * (such as its process crashing) or the client is taking too long to
- * respond with the text (it is given a couple seconds to return).
- * In either case, a null is returned.
- *
- * @param n The expected length of the text.
- * @param flags Supplies additional options controlling how the text is
- * returned. May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
- *
- * @return Returns the text after the cursor position; the length of the
- * returned text might be less than <var>n</var>.
- */
- public CharSequence getTextAfterCursor(int n, int flags);
-
- /**
- * Retrieve the current capitalization mode in effect at the current
- * cursor position in the text. See
- * {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode} for
- * more information.
- *
- * <p>This method may fail either if the input connection has become invalid
- * (such as its process crashing) or the client is taking too long to
- * respond with the text (it is given a couple seconds to return).
- * In either case, a 0 is returned.
- *
- * @param reqModes The desired modes to retrieve, as defined by
- * {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode}. These
- * constants are defined so that you can simply pass the current
- * {@link EditorInfo#inputType TextBoxAttribute.contentType} value
- * directly in to here.
- *
- * @return Returns the caps mode flags that are in effect.
- */
- public int getCursorCapsMode(int reqModes);
-
- /**
- * Retrieve the current text in the input connection's editor, and monitor
- * for any changes to it. This function returns with the current text,
- * and optionally the input connection can send updates to the
- * input method when its text changes.
- *
- * <p>This method may fail either if the input connection has become invalid
- * (such as its process crashing) or the client is taking too long to
- * respond with the text (it is given a couple seconds to return).
- * In either case, a null is returned.
- *
- * @param request Description of how the text should be returned.
- * @param flags Additional options to control the client, either 0 or
- * {@link #GET_EXTRACTED_TEXT_MONITOR}.
- *
- * @return Returns an ExtractedText object describing the state of the
- * text view and containing the extracted text itself.
- */
- public ExtractedText getExtractedText(ExtractedTextRequest request,
- int flags);
-
- /**
- * Delete <var>leftLength</var> characters of text before the current cursor
- * position, and delete <var>rightLength</var> characters of text after the
- * current cursor position, excluding composing text.
- *
- * @param leftLength The number of characters to be deleted before the
- * current cursor position.
- * @param rightLength The number of characters to be deleted after the
- * current cursor position.
- *
- * @return Returns true on success, false if the input connection is no longer
- * valid.
- */
- boolean deleteSurroundingText(int leftLength, int rightLength);
-
- /**
- * Set composing text around the current cursor position with the given text,
- * and set the new cursor position. Any composing text set previously will
- * be removed automatically.
- *
- * @param text The composing text with styles if necessary. If no style
- * object attached to the text, the default style for composing text
- * is used. See {#link android.text.Spanned} for how to attach style
- * object to the text. {#link android.text.SpannableString} and
- * {#link android.text.SpannableStringBuilder} are two
- * implementations of the interface {#link android.text.Spanned}.
- * @param newCursorPosition The new cursor position around the text. If
- * > 0, this is relative to the end of the text - 1; if <= 0, this
- * is relative to the start of the text. So a value of 1 will
- * always advance you to the position after the full text being
- * inserted. Note that this means you can't position the cursor
- * within the text, because the editor can make modifications to
- * the text you are providing so it is not possible to correctly
- * specify locations there.
- *
- * @return Returns true on success, false if the input connection is no longer
- * valid.
- */
- public boolean setComposingText(CharSequence text, int newCursorPosition);
-
- /**
- * Have the text editor finish whatever composing text is currently
- * active. This simply leaves the text as-is, removing any special
- * composing styling or other state that was around it. The cursor
- * position remains unchanged.
- */
- public boolean finishComposingText();
-
- /**
- * Commit text to the text box and set the new cursor position.
- * Any composing text set previously will be removed
- * automatically.
- *
- * @param text The committed text.
- * @param newCursorPosition The new cursor position around the text. If
- * > 0, this is relative to the end of the text - 1; if <= 0, this
- * is relative to the start of the text. So a value of 1 will
- * always advance you to the position after the full text being
- * inserted. Note that this means you can't position the cursor
- * within the text, because the editor can make modifications to
- * the text you are providing so it is not possible to correctly
- * specify locations there.
- *
- *
- * @return Returns true on success, false if the input connection is no longer
- * valid.
- */
- public boolean commitText(CharSequence text, int newCursorPosition);
-
- /**
- * Commit a completion the user has selected from the possible ones
- * previously reported to {@link InputMethodSession#displayCompletions
- * InputMethodSession.displayCompletions()}. This will result in the
- * same behavior as if the user had selected the completion from the
- * actual UI.
- *
- * @param text The committed completion.
- *
- * @return Returns true on success, false if the input connection is no longer
- * valid.
- */
- public boolean commitCompletion(CompletionInfo text);
-
- /**
- * Set the selection of the text editor. To set the cursor position,
- * start and end should have the same value.
- */
- public boolean setSelection(int start, int end);
-
- /**
- * Perform a context menu action on the field. The given id may be one of:
- * {@link android.R.id#selectAll},
- * {@link android.R.id#startSelectingText}, {@link android.R.id#stopSelectingText},
- * {@link android.R.id#cut}, {@link android.R.id#copy},
- * {@link android.R.id#paste}, {@link android.R.id#copyUrl},
- * or {@link android.R.id#switchInputMethod}
- */
- public boolean performContextMenuAction(int id);
-
- /**
- * Tell the editor that you are starting a batch of editor operations.
- * The editor will try to avoid sending you updates about its state
- * until {@link #endBatchEdit} is called.
- */
- public boolean beginBatchEdit();
-
- /**
- * Tell the editor that you are done with a batch edit previously
- * initiated with {@link #endBatchEdit}.
- */
- public boolean endBatchEdit();
-
- /**
- * Send a key event to the process that is currently attached through
- * this input connection. The event will be dispatched like a normal
- * key event, to the currently focused; this generally is the view that
- * is providing this InputConnection, but due to the asynchronous nature
- * of this protocol that can not be guaranteed and the focus may have
- * changed by the time the event is received.
- *
- * <p>
- * This method can be used to send key events to the application. For
- * example, an on-screen keyboard may use this method to simulate a hardware
- * keyboard. There are three types of standard keyboards, numeric (12-key),
- * predictive (20-key) and ALPHA (QWERTY). You can specify the keyboard type
- * by specify the device id of the key event.
- *
- * <p>
- * You will usually want to set the flag
- * {@link KeyEvent#FLAG_SOFT_KEYBOARD KeyEvent.FLAG_SOFT_KEYBOARD} on all
- * key event objects you give to this API; the flag will not be set
- * for you.
- *
- * @param event The key event.
- *
- * @return Returns true on success, false if the input connection is no longer
- * valid.
- *
- * @see KeyEvent
- * @see KeyCharacterMap#NUMERIC
- * @see KeyCharacterMap#PREDICTIVE
- * @see KeyCharacterMap#ALPHA
- */
- public boolean sendKeyEvent(KeyEvent event);
-
- /**
- * Clear the given meta key pressed states in the given input connection.
- *
- * @param states The states to be cleared, may be one or more bits as
- * per {@link KeyEvent#getMetaState() KeyEvent.getMetaState()}.
- *
- * @return Returns true on success, false if the input connection is no longer
- * valid.
- */
- public boolean clearMetaKeyStates(int states);
-
- /**
- * Called by the IME to tell the client when it switches between fullscreen
- * and normal modes. This will normally be called for you by the standard
- * implementation of {@link android.inputmethodservice.InputMethodService}.
- */
- public boolean reportFullscreenMode(boolean enabled);
-
- /**
- * API to send private commands from an input method to its connected
- * editor. This can be used to provide domain-specific features that are
- * only known between certain input methods and their clients. Note that
- * because the InputConnection protocol is asynchronous, you have no way
- * to get a result back or know if the client understood the command; you
- * can use the information in {@link EditorInfo} to determine if
- * a client supports a particular command.
- *
- * @param action Name of the command to be performed. This <em>must</em>
- * be a scoped name, i.e. prefixed with a package name you own, so that
- * different developers will not create conflicting commands.
- * @param data Any data to include with the command.
- * @return Returns true if the command was sent (whether or not the
- * associated editor understood it), false if the input connection is no longer
- * valid.
- */
- public boolean performPrivateCommand(String action, Bundle data);
-}
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
deleted file mode 100644
index 740dca8..0000000
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.view.inputmethod;
-
-import android.inputmethodservice.InputMethodService;
-import android.os.IBinder;
-
-/**
- * The InputMethod interface represents an input method which can generate key
- * events and text, such as digital, email addresses, CJK characters, other
- * language characters, and etc., while handling various input events, and send
- * the text back to the application that requests text input. See
- * {@link InputMethodManager} for more general information about the
- * architecture.
- *
- * <p>Applications will not normally use this interface themselves, instead
- * relying on the standard interaction provided by
- * {@link android.widget.TextView} and {@link android.widget.EditText}.
- *
- * <p>Those implementing input methods should normally do so by deriving from
- * {@link InputMethodService} or one of its subclasses. When implementing
- * an input method, the service component containing it must also supply
- * a {@link #SERVICE_META_DATA} meta-data field, referencing an XML resource
- * providing details about the input method. All input methods also must
- * require that clients hold the
- * {@link android.Manifest.permission#BIND_INPUT_METHOD} in order to interact
- * with the service; if this is not required, the system will not use that
- * input method, because it can not trust that it is not compromised.
- *
- * <p>The InputMethod interface is actually split into two parts: the interface
- * here is the top-level interface to the input method, providing all
- * access to it, which only the system can access (due to the BIND_INPUT_METHOD
- * permission requirement). In addition its method
- * {@link #createSession(android.view.inputmethod.InputMethod.SessionCallback)}
- * can be called to instantate a secondary {@link InputMethodSession} interface
- * which is what clients use to communicate with the input method.
- */
-public interface InputMethod {
- /**
- * This is the interface name that a service implementing an input
- * method should say that it supports -- that is, this is the action it
- * uses for its intent filter. (Note: this name is used because this
- * interface should be moved to the view package.)
- */
- public static final String SERVICE_INTERFACE = "android.view.InputMethod";
-
- /**
- * Name under which an InputMethod service component publishes information
- * about itself. This meta-data must reference an XML resource containing
- * an
- * <code>&lt;{@link android.R.styleable#InputMethod input-method}&gt;</code>
- * tag.
- */
- public static final String SERVICE_META_DATA = "android.view.im";
-
- public interface SessionCallback {
- public void sessionCreated(InputMethodSession session);
- }
-
- /**
- * Called first thing after an input method is created, this supplies a
- * unique token for the session it has with the system service. It is
- * needed to identify itself with the service to validate its operations.
- * This token <strong>must not</strong> be passed to applications, since
- * it grants special priviledges that should not be given to applications.
- *
- * <p>Note: to protect yourself from malicious clients, you should only
- * accept the first token given to you. Any after that may come from the
- * client.
- */
- public void attachToken(IBinder token);
-
- /**
- * Bind a new application environment in to the input method, so that it
- * can later start and stop input processing.
- * Typically this method is called when this input method is enabled in an
- * application for the first time.
- *
- * @param binding Information about the application window that is binding
- * to the input method.
- *
- * @see InputBinding
- * @see #unbindInput()
- */
- public void bindInput(InputBinding binding);
-
- /**
- * Unbind an application environment, called when the information previously
- * set by {@link #bindInput} is no longer valid for this input method.
- *
- * <p>
- * Typically this method is called when the application changes to be
- * non-foreground.
- */
- public void unbindInput();
-
- /**
- * This method is called when the application starts to receive text and it
- * is ready for this input method to process received events and send result
- * text back to the application.
- *
- * @param inputConnection Optional specific input connection for
- * communicating with the text box; if null, you should use the generic
- * bound input connection.
- * @param info Information about the text box (typically, an EditText)
- * that requests input.
- *
- * @see EditorInfo
- */
- public void startInput(InputConnection inputConnection, EditorInfo info);
-
- /**
- * This method is called when the state of this input method needs to be
- * reset.
- *
- * <p>
- * Typically, this method is called when the input focus is moved from one
- * text box to another.
- *
- * @param inputConnection Optional specific input connection for
- * communicating with the text box; if null, you should use the generic
- * bound input connection.
- * @param attribute The attribute of the text box (typically, a EditText)
- * that requests input.
- *
- * @see EditorInfo
- */
- public void restartInput(InputConnection inputConnection, EditorInfo attribute);
-
- /**
- * Create a new {@link InputMethodSession} that can be handed to client
- * applications for interacting with the input method. You can later
- * use {@link #revokeSession(InputMethodSession)} to destroy the session
- * so that it can no longer be used by any clients.
- *
- * @param callback Interface that is called with the newly created session.
- */
- public void createSession(SessionCallback callback);
-
- /**
- * Control whether a particular input method session is active.
- *
- * @param session The {@link InputMethodSession} previously provided through
- * SessionCallback.sessionCreated() that is to be changed.
- */
- public void setSessionEnabled(InputMethodSession session, boolean enabled);
-
- /**
- * Disable and destroy a session that was previously created with
- * {@link #createSession(android.view.inputmethod.InputMethod.SessionCallback)}.
- * After this call, the given session interface is no longer active and
- * calls on it will fail.
- *
- * @param session The {@link InputMethodSession} previously provided through
- * SessionCallback.sessionCreated() that is to be revoked.
- */
- public void revokeSession(InputMethodSession session);
-
- /**
- * Flag for {@link #showSoftInput(int)}: this show has been explicitly
- * requested by the user. If not set, the system has decided it may be
- * a good idea to show the input method based on a navigation operation
- * in the UI.
- */
- public static final int SHOW_EXPLICIT = 0x00001;
-
- /**
- * Flag for {@link #showSoftInput(int)}: this show has been forced to
- * happen by the user. If set, the input method should remain visible
- * until deliberated dismissed by the user in its UI.
- */
- public static final int SHOW_FORCED = 0x00002;
-
- /**
- * Request that any soft input part of the input method be shown to the user.
- *
- * @param flags Provide additional information about the show request.
- * Currently may be 0 or have the bit {@link #SHOW_EXPLICIT} set.
- */
- public void showSoftInput(int flags);
-
- /**
- * Request that any soft input part of the input method be hidden from the user.
- */
- public void hideSoftInput();
-}
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.aidl b/core/java/android/view/inputmethod/InputMethodInfo.aidl
deleted file mode 100644
index 5f4d6b6..0000000
--- a/core/java/android/view/inputmethod/InputMethodInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.inputmethod;
-
-parcelable InputMethodInfo;
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
deleted file mode 100644
index e8f4b54..0000000
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.view.inputmethod;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.graphics.drawable.Drawable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.util.Printer;
-import android.util.Xml;
-
-import java.io.IOException;
-
-/**
- * This class is used to specify meta information of an input method.
- */
-public final class InputMethodInfo implements Parcelable {
- static final String TAG = "InputMethodMetaInfo";
-
- /**
- * The Service that implements this input method component.
- */
- final ResolveInfo mService;
-
- /**
- * The unique string Id to identify the input method. This is generated
- * from the input method component.
- */
- final String mId;
-
- /**
- * The input method setting activity's name, used by the system settings to
- * launch the setting activity of this input method.
- */
- final String mSettingsActivityName;
-
- /**
- * The resource in the input method's .apk that holds a boolean indicating
- * whether it should be considered the default input method for this
- * system. This is a resource ID instead of the final value so that it
- * can change based on the configuration (in particular locale).
- */
- final int mIsDefaultResId;
-
- /**
- * Constructor.
- *
- * @param context The Context in which we are parsing the input method.
- * @param service The ResolveInfo returned from the package manager about
- * this input method's component.
- */
- public InputMethodInfo(Context context, ResolveInfo service)
- throws XmlPullParserException, IOException {
- mService = service;
- ServiceInfo si = service.serviceInfo;
- mId = new ComponentName(si.packageName, si.name).flattenToShortString();
-
- PackageManager pm = context.getPackageManager();
- String settingsActivityComponent = null;
- int isDefaultResId = 0;
-
- XmlResourceParser parser = null;
- try {
- parser = si.loadXmlMetaData(pm, InputMethod.SERVICE_META_DATA);
- if (parser == null) {
- throw new XmlPullParserException("No "
- + InputMethod.SERVICE_META_DATA + " meta-data");
- }
-
- AttributeSet attrs = Xml.asAttributeSet(parser);
-
- int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && type != XmlPullParser.START_TAG) {
- }
-
- String nodeName = parser.getName();
- if (!"input-method".equals(nodeName)) {
- throw new XmlPullParserException(
- "Meta-data does not start with input-method tag");
- }
-
- TypedArray sa = context.getResources().obtainAttributes(attrs,
- com.android.internal.R.styleable.InputMethod);
- settingsActivityComponent = sa.getString(
- com.android.internal.R.styleable.InputMethod_settingsActivity);
- isDefaultResId = sa.getResourceId(
- com.android.internal.R.styleable.InputMethod_isDefault, 0);
- sa.recycle();
- } finally {
- if (parser != null) parser.close();
- }
-
- mSettingsActivityName = settingsActivityComponent;
- mIsDefaultResId = isDefaultResId;
- }
-
- InputMethodInfo(Parcel source) {
- mId = source.readString();
- mSettingsActivityName = source.readString();
- mIsDefaultResId = source.readInt();
- mService = ResolveInfo.CREATOR.createFromParcel(source);
- }
-
- /**
- * Temporary API for creating a built-in input method.
- */
- public InputMethodInfo(String packageName, String className,
- CharSequence label, String settingsActivity) {
- ResolveInfo ri = new ResolveInfo();
- ServiceInfo si = new ServiceInfo();
- ApplicationInfo ai = new ApplicationInfo();
- ai.packageName = packageName;
- ai.enabled = true;
- si.applicationInfo = ai;
- si.enabled = true;
- si.packageName = packageName;
- si.name = className;
- si.exported = true;
- si.nonLocalizedLabel = label;
- ri.serviceInfo = si;
- mService = ri;
- mId = new ComponentName(si.packageName, si.name).flattenToShortString();
- mSettingsActivityName = settingsActivity;
- mIsDefaultResId = 0;
- }
-
- /**
- * Return a unique ID for this input method. The ID is generated from
- * the package and class name implementing the method.
- */
- public String getId() {
- return mId;
- }
-
- /**
- * Return the .apk package that implements this input method.
- */
- public String getPackageName() {
- return mService.serviceInfo.packageName;
- }
-
- /**
- * Return the class name of the service component that implements
- * this input method.
- */
- public String getServiceName() {
- return mService.serviceInfo.name;
- }
-
- /**
- * Return the component of the service that implements this input
- * method.
- */
- public ComponentName getComponent() {
- return new ComponentName(mService.serviceInfo.packageName,
- mService.serviceInfo.name);
- }
-
- /**
- * Load the user-displayed label for this input method.
- *
- * @param pm Supply a PackageManager used to load the input method's
- * resources.
- */
- public CharSequence loadLabel(PackageManager pm) {
- return mService.loadLabel(pm);
- }
-
- /**
- * Load the user-displayed icon for this input method.
- *
- * @param pm Supply a PackageManager used to load the input method's
- * resources.
- */
- public Drawable loadIcon(PackageManager pm) {
- return mService.loadIcon(pm);
- }
-
- /**
- * Return the class name of an activity that provides a settings UI for
- * the input method. You can launch this activity be starting it with
- * an {@link android.content.Intent} whose action is MAIN and with an
- * explicit {@link android.content.ComponentName}
- * composed of {@link #getPackageName} and the class name returned here.
- *
- * <p>A null will be returned if there is no settings activity associated
- * with the input method.
- */
- public String getSettingsActivity() {
- return mSettingsActivityName;
- }
-
- /**
- * Return the resource identifier of a resource inside of this input
- * method's .apk that determines whether it should be considered a
- * default input method for the system.
- */
- public int getIsDefaultResourceId() {
- return mIsDefaultResId;
- }
-
- /**
- * Returns true if this input method is one of the components that is
- * built in to the system.
- */
- public boolean isBuiltin() {
- return mService.serviceInfo.packageName.equals(
- InputMethodManager.BUILDIN_INPUTMETHOD_PACKAGE);
- }
-
- public void dump(Printer pw, String prefix) {
- pw.println(prefix + "mId=" + mId
- + " mSettingsActivityName=" + mSettingsActivityName);
- pw.println(prefix + "mIsDefaultResId=0x"
- + Integer.toHexString(mIsDefaultResId));
- pw.println(prefix + "Service:");
- mService.dump(pw, prefix + " ");
- }
-
- @Override
- public String toString() {
- return "InputMethodMetaInfo{" + mId
- + ", settings: "
- + mSettingsActivityName + "}";
- }
-
- /**
- * Used to test whether the given parameter object is an
- * {@link InputMethodInfo} and its Id is the same to this one.
- *
- * @return true if the given parameter object is an
- * {@link InputMethodInfo} and its Id is the same to this one.
- */
- @Override
- public boolean equals(Object o) {
- if (o == this) return true;
- if (o == null) return false;
-
- if (!(o instanceof InputMethodInfo)) return false;
-
- InputMethodInfo obj = (InputMethodInfo) o;
- return mId.equals(obj.mId);
- }
-
- /**
- * Used to package this object into a {@link Parcel}.
- *
- * @param dest The {@link Parcel} to be written.
- * @param flags The flags used for parceling.
- */
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mId);
- dest.writeString(mSettingsActivityName);
- dest.writeInt(mIsDefaultResId);
- mService.writeToParcel(dest, flags);
- }
-
- /**
- * Used to make this class parcelable.
- */
- public static final Parcelable.Creator<InputMethodInfo> CREATOR = new Parcelable.Creator<InputMethodInfo>() {
- public InputMethodInfo createFromParcel(Parcel source) {
- return new InputMethodInfo(source);
- }
-
- public InputMethodInfo[] newArray(int size) {
- return new InputMethodInfo[size];
- }
- };
-
- public int describeContents() {
- return 0;
- }
-}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
deleted file mode 100644
index 91fa211..0000000
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ /dev/null
@@ -1,1185 +0,0 @@
-/*
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.view.inputmethod;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.Log;
-import android.util.PrintWriterPrinter;
-import android.util.Printer;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewRoot;
-
-import com.android.internal.os.HandlerCaller;
-import com.android.internal.view.IInputConnectionWrapper;
-import com.android.internal.view.IInputContext;
-import com.android.internal.view.IInputMethodCallback;
-import com.android.internal.view.IInputMethodClient;
-import com.android.internal.view.IInputMethodManager;
-import com.android.internal.view.IInputMethodSession;
-import com.android.internal.view.InputBindResult;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Central system API to the overall input method framework (IMF) architecture,
- * which arbitrates interaction between applications and the current input method.
- * You can retrieve an instance of this interface with
- * {@link Context#getSystemService(String) Context.getSystemService()}.
- *
- * <p>Topics covered here:
- * <ol>
- * <li><a href="#ArchitectureOverview">Architecture Overview</a>
- * </ol>
- *
- * <a name="ArchitectureOverview"></a>
- * <h3>Architecture Overview</h3>
- *
- * <p>There are three primary parties involved in the input method
- * framework (IMF) architecture:</p>
- *
- * <ul>
- * <li> The <strong>input method manager</strong> as expressed by this class
- * is the central point of the system that manages interaction between all
- * other parts. It is expressed as the client-side API here which exists
- * in each application context and communicates with a global system service
- * that manages the interaction across all processes.
- * <li> An <strong>input method (IME)</strong> implements a particular
- * interaction model allowing the user to generate text. The system binds
- * to the current input method that is use, causing it to be created and run,
- * and tells it when to hide and show its UI. Only one IME is running at a time.
- * <li> Multiple <strong>client applications</strong> arbitrate with the input
- * method manager for input focus and control over the state of the IME. Only
- * one such client is ever active (working with the IME) at a time.
- * </ul>
- *
- *
- * <a name="Applications"></a>
- * <h3>Applications</h3>
- *
- * <p>In most cases, applications that are using the standard
- * {@link android.widget.TextView} or its subclasses will have little they need
- * to do to work well with soft input methods. The main things you need to
- * be aware of are:</p>
- *
- * <ul>
- * <li> Properly set the {@link android.R.attr#inputType} if your editable
- * text views, so that the input method will have enough context to help the
- * user in entering text into them.
- * <li> Deal well with losing screen space when the input method is
- * displayed. Ideally an application should handle its window being resized
- * smaller, but it can rely on the system performing panning of the window
- * if needed. You should set the {@link android.R.attr#windowSoftInputMode}
- * attribute on your activity or the corresponding values on windows you
- * create to help the system determine whether to pan or resize (it will
- * try to determine this automatically but may get it wrong).
- * <li> You can also control the preferred soft input state (open, closed, etc)
- * for your window using the same {@link android.R.attr#windowSoftInputMode}
- * attribute.
- * </ul>
- *
- * <p>More finer-grained control is available through the APIs here to directly
- * interact with the IMF and its IME -- either showing or hiding the input
- * area, letting the user pick an input method, etc.</p>
- *
- * <p>For the rare people amongst us writing their own text editors, you
- * will need to implement {@link android.view.View#onCreateInputConnection}
- * to return a new instance of your own {@link InputConnection} interface
- * allowing the IME to interact with your editor.</p>
- *
- *
- * <a name="InputMethods"></a>
- * <h3>Input Methods</h3>
- *
- * <p>An input method (IME) is implemented
- * as a {@link android.app.Service}, typically deriving from
- * {@link android.inputmethodservice.InputMethodService}. It must provide
- * the core {@link InputMethod} interface, though this is normally handled by
- * {@link android.inputmethodservice.InputMethodService} and implementors will
- * only need to deal with the higher-level API there.</p>
- *
- * See the {@link android.inputmethodservice.InputMethodService} class for
- * more information on implementing IMEs.
- *
- *
- * <a name="Security"></a>
- * <h3>Security</h3>
- *
- * <p>There are a lot of security issues associated with input methods,
- * since they essentially have freedom to completely drive the UI and monitor
- * everything the user enters. The Android input method framework also allows
- * arbitrary third party IMEs, so care must be taken to restrict their
- * selection and interactions.</p>
- *
- * <p>Here are some key points about the security architecture behind the
- * IMF:</p>
- *
- * <ul>
- * <li> <p>Only the system is allowed to directly access an IME's
- * {@link InputMethod} interface, via the
- * {@link android.Manifest.permission#BIND_INPUT_METHOD} permission. This is
- * enforced in the system by not binding to an input method service that does
- * not require this permission, so the system can guarantee no other untrusted
- * clients are accessing the current input method outside of its control.</p>
- *
- * <li> <p>There may be many client processes of the IMF, but only one may
- * be active at a time. The inactive clients can not interact with key
- * parts of the IMF through the mechanisms described below.</p>
- *
- * <li> <p>Clients of an input method are only given access to its
- * {@link InputMethodSession} interface. One instance of this interface is
- * created for each client, and only calls from the session associated with
- * the active client will be processed by the current IME. This is enforced
- * by {@link android.inputmethodservice.AbstractInputMethodService} for normal
- * IMEs, but must be explicitly handled by an IME that is customizing the
- * raw {@link InputMethodSession} implementation.</p>
- *
- * <li> <p>Only the active client's {@link InputConnection} will accept
- * operations. The IMF tells each client process whether it is active, and
- * the framework enforces that in inactive processes calls on to the current
- * InputConnection will be ignored. This ensures that the current IME can
- * only deliver events and text edits to the UI that the user sees as
- * being in focus.</p>
- *
- * <li> <p>An IME can never interact with an {@link InputConnection} while
- * the screen is off. This is enforced by making all clients inactive while
- * the screen is off, and prevents bad IMEs from driving the UI when the user
- * can not be aware of its behavior.</p>
- *
- * <li> <p>A client application can ask that the system let the user pick a
- * new IME, but can not programmatically switch to one itself. This avoids
- * malicious applications from switching the user to their own IME, which
- * remains running when the user navigates away to another application. An
- * IME, on the other hand, <em>is</em> allowed to programmatically switch
- * the system to another IME, since it already has full control of user
- * input.</p>
- *
- * <li> <p>The user must explicitly enable a new IME in settings before
- * they can switch to it, to confirm with the system that they know about it
- * and want to make it available for use.</p>
- * </ul>
- */
-public final class InputMethodManager {
- static final boolean DEBUG = false;
- static final String TAG = "InputMethodManager";
-
- /**
- * The package name of the build-in input method.
- * {@hide}
- */
- public static final String BUILDIN_INPUTMETHOD_PACKAGE = "android.text.inputmethod";
-
- static final Object mInstanceSync = new Object();
- static InputMethodManager mInstance;
-
- final IInputMethodManager mService;
- final Looper mMainLooper;
-
- // For scheduling work on the main thread. This also serves as our
- // global lock.
- final H mH;
-
- // Our generic input connection if the current target does not have its own.
- final IInputContext mIInputContext;
-
- /**
- * True if this input method client is active, initially false.
- */
- boolean mActive = false;
-
- /**
- * As reported by IME through InputConnection.
- */
- boolean mFullscreenMode;
-
- // -----------------------------------------------------------
-
- /**
- * This is the view that should currently be served by an input method,
- * regardless of the state of setting that up.
- */
- View mServedView;
- /*
- * Keep track of the view that was set when our window gained focus.
- */
- View mWindowFocusedView;
- /**
- * For evaluating the state after a focus change, this is the view that
- * had focus.
- */
- View mLastServedView;
- /**
- * This is set when we are in the process of connecting, to determine
- * when we have actually finished.
- */
- boolean mServedConnecting;
- /**
- * This is non-null when we have connected the served view; it holds
- * the attributes that were last retrieved from the served view and given
- * to the input connection.
- */
- EditorInfo mCurrentTextBoxAttribute;
- /**
- * The InputConnection that was last retrieved from the served view.
- */
- InputConnection mServedInputConnection;
- /**
- * The completions that were last provided by the served view.
- */
- CompletionInfo[] mCompletions;
-
- // Cursor position on the screen.
- Rect mTmpCursorRect = new Rect();
- Rect mCursorRect = new Rect();
- int mCursorSelStart;
- int mCursorSelEnd;
- int mCursorCandStart;
- int mCursorCandEnd;
-
- // -----------------------------------------------------------
-
- /**
- * Sequence number of this binding, as returned by the server.
- */
- int mBindSequence = -1;
- /**
- * ID of the method we are bound to.
- */
- String mCurId;
- /**
- * The actual instance of the method to make calls on it.
- */
- IInputMethodSession mCurMethod;
-
- // -----------------------------------------------------------
-
- static final int MSG_DUMP = 1;
-
- class H extends Handler {
- H(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_DUMP: {
- HandlerCaller.SomeArgs args = (HandlerCaller.SomeArgs)msg.obj;
- try {
- doDump((FileDescriptor)args.arg1,
- (PrintWriter)args.arg2, (String[])args.arg3);
- } catch (RuntimeException e) {
- ((PrintWriter)args.arg2).println("Exception: " + e);
- }
- synchronized (args.arg4) {
- ((CountDownLatch)args.arg4).countDown();
- }
- return;
- }
- }
- }
- }
-
- class ControlledInputConnectionWrapper extends IInputConnectionWrapper {
- public ControlledInputConnectionWrapper(Looper mainLooper, InputConnection conn) {
- super(mainLooper, conn);
- }
-
- public boolean isActive() {
- return mActive;
- }
- }
-
- final IInputMethodClient.Stub mClient = new IInputMethodClient.Stub() {
- @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
- // No need to check for dump permission, since we only give this
- // interface to the system.
-
- CountDownLatch latch = new CountDownLatch(1);
- HandlerCaller.SomeArgs sargs = new HandlerCaller.SomeArgs();
- sargs.arg1 = fd;
- sargs.arg2 = fout;
- sargs.arg3 = args;
- sargs.arg4 = latch;
- mH.sendMessage(mH.obtainMessage(MSG_DUMP, sargs));
- try {
- if (!latch.await(5, TimeUnit.SECONDS)) {
- fout.println("Timeout waiting for dump");
- }
- } catch (InterruptedException e) {
- fout.println("Interrupted waiting for dump");
- }
- }
-
- public void setUsingInputMethod(boolean state) {
- }
-
- public void onBindMethod(InputBindResult res) {
- synchronized (mH) {
- if (mBindSequence < 0 || mBindSequence != res.sequence) {
- Log.w(TAG, "Ignoring onBind: cur seq=" + mBindSequence
- + ", given seq=" + res.sequence);
- return;
- }
-
- mCurMethod = res.method;
- mCurId = res.id;
- mBindSequence = res.sequence;
- }
- startInputInner();
- }
-
- public void onUnbindMethod(int sequence) {
- synchronized (mH) {
- if (mBindSequence == sequence) {
- if (false) {
- // XXX the server has already unbound!
- if (mCurMethod != null && mCurrentTextBoxAttribute != null) {
- try {
- mCurMethod.finishInput();
- } catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- }
- }
- }
- clearBindingLocked();
-
- // If we were actively using the last input method, then
- // we would like to re-connect to the next input method.
- if (mServedView != null && mServedView.isFocused()) {
- mServedConnecting = true;
- }
- }
- startInputInner();
- }
- }
-
- public void setActive(boolean active) {
- mActive = active;
- mFullscreenMode = false;
- }
- };
-
- final InputConnection mDummyInputConnection = new BaseInputConnection(this, true);
-
- InputMethodManager(IInputMethodManager service, Looper looper) {
- mService = service;
- mMainLooper = looper;
- mH = new H(looper);
- mIInputContext = new ControlledInputConnectionWrapper(looper,
- mDummyInputConnection);
-
- if (mInstance == null) {
- mInstance = this;
- }
- }
-
- /**
- * Retrieve the global InputMethodManager instance, creating it if it
- * doesn't already exist.
- * @hide
- */
- static public InputMethodManager getInstance(Context context) {
- synchronized (mInstanceSync) {
- if (mInstance != null) {
- return mInstance;
- }
- IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
- IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
- mInstance = new InputMethodManager(service, context.getMainLooper());
- }
- return mInstance;
- }
-
- /**
- * Private optimization: retrieve the global InputMethodManager instance,
- * if it exists.
- * @hide
- */
- static public InputMethodManager peekInstance() {
- return mInstance;
- }
-
- /** @hide */
- public IInputMethodClient getClient() {
- return mClient;
- }
-
- /** @hide */
- public IInputContext getInputContext() {
- return mIInputContext;
- }
-
- public List<InputMethodInfo> getInputMethodList() {
- try {
- return mService.getInputMethodList();
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- public List<InputMethodInfo> getEnabledInputMethodList() {
- try {
- return mService.getEnabledInputMethodList();
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- public void showStatusIcon(IBinder imeToken, String packageName, int iconId) {
- try {
- mService.updateStatusIcon(imeToken, packageName, iconId);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- public void hideStatusIcon(IBinder imeToken) {
- try {
- mService.updateStatusIcon(imeToken, null, 0);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** @hide */
- public void setFullscreenMode(boolean fullScreen) {
- mFullscreenMode = fullScreen;
- }
-
- /**
- * Allows you to discover whether the attached input method is running
- * in fullscreen mode. Return true if it is fullscreen, entirely covering
- * your UI, else returns false.
- */
- public boolean isFullscreenMode() {
- return mFullscreenMode;
- }
-
- /**
- * Return true if the given view is the currently active view for the
- * input method.
- */
- public boolean isActive(View view) {
- synchronized (mH) {
- return mServedView == view && mCurrentTextBoxAttribute != null;
- }
- }
-
- /**
- * Return true if any view is currently active in the input method.
- */
- public boolean isActive() {
- synchronized (mH) {
- return mServedView != null && mCurrentTextBoxAttribute != null;
- }
- }
-
- /**
- * Return true if the currently served view is accepting full text edits.
- * If false, it has no input connection, so can only handle raw key events.
- */
- public boolean isAcceptingText() {
- return mServedInputConnection != null;
- }
-
- /**
- * Reset all of the state associated with being bound to an input method.
- */
- void clearBindingLocked() {
- clearConnectionLocked();
- mBindSequence = -1;
- mCurId = null;
- mCurMethod = null;
- }
-
- /**
- * Reset all of the state associated with a served view being connected
- * to an input method
- */
- void clearConnectionLocked() {
- mCurrentTextBoxAttribute = null;
- mServedInputConnection = null;
- }
-
- /**
- * Disconnect any existing input connection, clearing the served view.
- */
- void finishInputLocked() {
- if (mServedView != null) {
- if (DEBUG) Log.v(TAG, "FINISH INPUT: " + mServedView);
-
- if (mCurrentTextBoxAttribute != null) {
- try {
- mService.finishInput(mClient);
- } catch (RemoteException e) {
- }
- }
-
- if (mServedInputConnection != null) {
- // We need to tell the previously served view that it is no
- // longer the input target, so it can reset its state. Schedule
- // this call on its window's Handler so it will be on the correct
- // thread and outside of our lock.
- Handler vh = mServedView.getHandler();
- if (vh != null) {
- // This will result in a call to reportFinishInputConnection()
- // below.
- vh.sendMessage(vh.obtainMessage(ViewRoot.FINISH_INPUT_CONNECTION,
- mServedInputConnection));
- }
- }
-
- mServedView = null;
- mCompletions = null;
- mServedConnecting = false;
- clearConnectionLocked();
- }
- }
-
- /**
- * Called from the FINISH_INPUT_CONNECTION message above.
- * @hide
- */
- public void reportFinishInputConnection(InputConnection ic) {
- if (mServedInputConnection != ic) {
- ic.finishComposingText();
- }
- }
-
- public void displayCompletions(View view, CompletionInfo[] completions) {
- synchronized (mH) {
- if (mServedView != view) {
- return;
- }
-
- mCompletions = completions;
- if (mCurMethod != null) {
- try {
- mCurMethod.displayCompletions(mCompletions);
- } catch (RemoteException e) {
- }
- }
- }
- }
-
- public void updateExtractedText(View view, int token, ExtractedText text) {
- synchronized (mH) {
- if (mServedView != view) {
- return;
- }
-
- if (mCurMethod != null) {
- try {
- mCurMethod.updateExtractedText(token, text);
- } catch (RemoteException e) {
- }
- }
- }
- }
-
- /**
- * Flag for {@link #showSoftInput} to indicate that this is an implicit
- * request to show the input window, not as the result of a direct request
- * by the user. The window may not be shown in this case.
- */
- public static final int SHOW_IMPLICIT = 0x0001;
-
- /**
- * Flag for {@link #showSoftInput} to indicate that the user has forced
- * the input method open (such as by long-pressing menu) so it should
- * not be closed until they explicitly do so.
- */
- public static final int SHOW_FORCED = 0x0002;
-
- /**
- * Explicitly request that the current input method's soft input area be
- * shown to the user, if needed. Call this if the user interacts with
- * your view in such a way that they have expressed they would like to
- * start performing input into it.
- *
- * @param view The currently focused view, which would like to receive
- * soft keyboard input.
- * @param flags Provides additional operating flags. Currently may be
- * 0 or have the {@link #SHOW_IMPLICIT} bit set.
- */
- public void showSoftInput(View view, int flags) {
- synchronized (mH) {
- if (mServedView != view) {
- return;
- }
-
- try {
- mService.showSoftInput(mClient, flags);
- } catch (RemoteException e) {
- }
- }
- }
-
- /** @hide */
- public void showSoftInputUnchecked(int flags) {
- try {
- mService.showSoftInput(mClient, flags);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Flag for {@link #hideSoftInputFromWindow} to indicate that the soft
- * input window should only be hidden if it was not explicitly shown
- * by the user.
- */
- public static final int HIDE_IMPLICIT_ONLY = 0x0001;
-
- /**
- * Flag for {@link #hideSoftInputFromWindow} to indicate that the soft
- * input window should normally be hidden, unless it was originally
- * shown with {@link #SHOW_FORCED}.
- */
- public static final int HIDE_NOT_ALWAYS = 0x0002;
-
- /**
- * Request to hide the soft input window from the context of the window
- * that is currently accepting input. This should be called as a result
- * of the user doing some actually than fairly explicitly requests to
- * have the input window hidden.
- *
- * @param windowToken The token of the window that is making the request,
- * as returned by {@link View#getWindowToken() View.getWindowToken()}.
- * @param flags Provides additional operating flags. Currently may be
- * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
- */
- public void hideSoftInputFromWindow(IBinder windowToken, int flags) {
- synchronized (mH) {
- if (mServedView == null || mServedView.getWindowToken() != windowToken) {
- return;
- }
-
- try {
- mService.hideSoftInput(mClient, flags);
- } catch (RemoteException e) {
- }
- }
- }
-
- /**
- * If the input method is currently connected to the given view,
- * restart it with its new contents. You should call this when the text
- * within your view changes outside of the normal input method or key
- * input flow, such as when an application calls TextView.setText().
- *
- * @param view The view whose text has changed.
- */
- public void restartInput(View view) {
- synchronized (mH) {
- if (mServedView != view) {
- return;
- }
-
- mServedConnecting = true;
- }
-
- startInputInner();
- }
-
- void startInputInner() {
- final View view;
- synchronized (mH) {
- view = mServedView;
-
- // Make sure we have a window token for the served view.
- if (DEBUG) Log.v(TAG, "Starting input: view=" + view);
- if (view == null) {
- if (DEBUG) Log.v(TAG, "ABORT input: no served view!");
- return;
- }
- }
-
- // Now we need to get an input connection from the served view.
- // This is complicated in a couple ways: we can't be holding our lock
- // when calling out to the view, and we need to make sure we call into
- // the view on the same thread that is driving its view hierarchy.
- Handler vh = view.getHandler();
- if (vh == null) {
- // If the view doesn't have a handler, something has changed out
- // from under us, so just bail.
- if (DEBUG) Log.v(TAG, "ABORT input: no handler for view!");
- return;
- }
- if (vh.getLooper() != Looper.myLooper()) {
- // The view is running on a different thread than our own, so
- // we need to reschedule our work for over there.
- if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread");
- vh.post(new Runnable() {
- public void run() {
- startInputInner();
- }
- });
- }
-
- // Okay we are now ready to call into the served view and have it
- // do its stuff.
- // Life is good: let's hook everything up!
- EditorInfo tba = new EditorInfo();
- tba.packageName = view.getContext().getPackageName();
- tba.fieldId = view.getId();
- InputConnection ic = view.onCreateInputConnection(tba);
- if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);
-
- synchronized (mH) {
- // Now that we are locked again, validate that our state hasn't
- // changed.
- if (mServedView != view || !mServedConnecting) {
- // Something else happened, so abort.
- if (DEBUG) Log.v(TAG,
- "Starting input: finished by someone else (view="
- + mServedView + " conn=" + mServedConnecting + ")");
- return;
- }
-
- // If we already have a text box, then this view is already
- // connected so we want to restart it.
- final boolean initial = mCurrentTextBoxAttribute == null;
-
- // Hook 'em up and let 'er rip.
- mCurrentTextBoxAttribute = tba;
- mServedConnecting = false;
- mServedInputConnection = ic;
- IInputContext servedContext;
- if (ic != null) {
- mCursorSelStart = tba.initialSelStart;
- mCursorSelEnd = tba.initialSelEnd;
- mCursorCandStart = -1;
- mCursorCandEnd = -1;
- mCursorRect.setEmpty();
- servedContext = new ControlledInputConnectionWrapper(vh.getLooper(), ic);
- } else {
- servedContext = null;
- }
-
- try {
- if (DEBUG) Log.v(TAG, "START INPUT: " + view + " ic="
- + ic + " tba=" + tba + " initial=" + initial);
- InputBindResult res = mService.startInput(mClient,
- servedContext, tba, initial, mCurMethod == null);
- if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
- if (res != null) {
- if (res.id != null) {
- mBindSequence = res.sequence;
- mCurMethod = res.method;
- } else {
- // This means there is no input method available.
- if (DEBUG) Log.v(TAG, "ABORT input: no input method!");
- return;
- }
- }
- if (mCurMethod != null && mCompletions != null) {
- try {
- mCurMethod.displayCompletions(mCompletions);
- } catch (RemoteException e) {
- }
- }
- } catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- }
- }
- }
-
- /**
- * When the focused window is dismissed, this method is called to finish the
- * input method started before.
- * @hide
- */
- public void windowDismissed(IBinder appWindowToken) {
- synchronized (mH) {
- if (mServedView != null &&
- mServedView.getWindowToken() == appWindowToken) {
- finishInputLocked();
- }
- }
- }
-
- /**
- * Call this when a view receives focus.
- * @hide
- */
- public void focusIn(View view) {
- synchronized (mH) {
- focusInLocked(view);
- }
-
- startInputInner();
- }
-
- void focusInLocked(View view) {
- if (DEBUG) Log.v(TAG, "focusIn: " + view);
- // Okay we have a new view that is being served.
- if (mServedView != view) {
- mCurrentTextBoxAttribute = null;
- }
- mServedView = view;
- mCompletions = null;
- mServedConnecting = true;
- }
-
- /**
- * Call this when a view loses focus.
- * @hide
- */
- public void focusOut(View view) {
- InputConnection ic = null;
- synchronized (mH) {
- if (DEBUG) Log.v(TAG, "focusOut: " + view
- + " mServedView=" + mServedView
- + " winFocus=" + view.hasWindowFocus());
- if (mServedView == view) {
- ic = mServedInputConnection;
- // The following code would auto-hide the IME if we end up
- // with no more views with focus. This can happen, however,
- // whenever we go into touch mode, so it ends up hiding
- // at times when we don't really want it to. For now it
- // seems better to just turn it all off.
- if (false && view.hasWindowFocus()) {
- mLastServedView = view;
- Handler vh = view.getHandler();
- if (vh != null) {
- // This will result in a call to checkFocus() below.
- vh.removeMessages(ViewRoot.CHECK_FOCUS);
- vh.sendMessage(vh.obtainMessage(ViewRoot.CHECK_FOCUS,
- view));
- }
- }
- }
- }
-
- if (ic != null) {
- ic.finishComposingText();
- }
- }
-
- /**
- * @hide
- */
- public void checkFocus(View view) {
- synchronized (mH) {
- if (view != mLastServedView) {
- return;
- }
- if (DEBUG) Log.v(TAG, "checkFocus: view=" + mServedView
- + " last=" + mLastServedView);
- if (mServedView == mLastServedView) {
- finishInputLocked();
- // In this case, we used to have a focused view on the window,
- // but no longer do. We should make sure the input method is
- // no longer shown, since it serves no purpose.
- closeCurrentInput();
- }
- mLastServedView = null;
- }
- }
-
- void closeCurrentInput() {
- try {
- mService.hideSoftInput(mClient, HIDE_NOT_ALWAYS);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Called by ViewRoot the first time it gets window focus.
- * @hide
- */
- public void onWindowFocus(View rootView, View focusedView, int softInputMode,
- boolean first, int windowFlags) {
- boolean needStartInput = false;
- synchronized (mH) {
- if (DEBUG) Log.v(TAG, "onWindowFocus: " + focusedView
- + " softInputMode=" + softInputMode
- + " first=" + first + " flags=#"
- + Integer.toHexString(windowFlags));
- if (mWindowFocusedView == null) {
- focusInLocked(focusedView != null ? focusedView : rootView);
- needStartInput = true;
- }
- }
-
- if (needStartInput) {
- startInputInner();
- }
-
- synchronized (mH) {
- try {
- final boolean isTextEditor = focusedView != null &&
- focusedView.onCheckIsTextEditor();
- mService.windowGainedFocus(mClient, focusedView != null,
- isTextEditor, softInputMode, first, windowFlags);
- } catch (RemoteException e) {
- }
- }
- }
-
- /** @hide */
- public void startGettingWindowFocus() {
- synchronized (mH) {
- mWindowFocusedView = null;
- }
- }
-
- /**
- * Report the current selection range.
- */
- public void updateSelection(View view, int selStart, int selEnd,
- int candidatesStart, int candidatesEnd) {
- synchronized (mH) {
- if (mServedView != view || mCurrentTextBoxAttribute == null
- || mCurMethod == null) {
- return;
- }
-
- if (mCursorSelStart != selStart || mCursorSelEnd != selEnd
- || mCursorCandStart != candidatesStart
- || mCursorCandEnd != candidatesEnd) {
- if (DEBUG) Log.d(TAG, "updateSelection");
-
- try {
- if (DEBUG) Log.v(TAG, "SELECTION CHANGE: " + mCurMethod);
- mCurMethod.updateSelection(mCursorSelStart, mCursorSelEnd,
- selStart, selEnd, candidatesStart, candidatesEnd);
- mCursorSelStart = selStart;
- mCursorSelEnd = selEnd;
- mCursorCandStart = candidatesStart;
- mCursorCandEnd = candidatesEnd;
- } catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- }
- }
- }
- }
-
- /**
- * Returns true if the current input method wants to watch the location
- * of the input editor's cursor in its window.
- */
- public boolean isWatchingCursor(View view) {
- return false;
- }
-
- /**
- * Report the current cursor location in its window.
- */
- public void updateCursor(View view, int left, int top, int right, int bottom) {
- synchronized (mH) {
- if (mServedView != view || mCurrentTextBoxAttribute == null
- || mCurMethod == null) {
- return;
- }
-
- mTmpCursorRect.set(left, top, right, bottom);
- if (!mCursorRect.equals(mTmpCursorRect)) {
- if (DEBUG) Log.d(TAG, "updateCursor");
-
- try {
- if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod);
- mCurMethod.updateCursor(mTmpCursorRect);
- mCursorRect.set(mTmpCursorRect);
- } catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- }
- }
- }
- }
-
- /**
- * Call {@link InputMethodSession#appPrivateCommand(String, Bundle)
- * InputMethodSession.appPrivateCommand()} on the current Input Method.
- * @param view Optional View that is sending the command, or null if
- * you want to send the command regardless of the view that is attached
- * to the input method.
- * @param action Name of the command to be performed. This <em>must</em>
- * be a scoped name, i.e. prefixed with a package name you own, so that
- * different developers will not create conflicting commands.
- * @param data Any data to include with the command.
- */
- public void sendAppPrivateCommand(View view, String action, Bundle data) {
- synchronized (mH) {
- if ((view != null && mServedView != view)
- || mCurrentTextBoxAttribute == null || mCurMethod == null) {
- return;
- }
- try {
- if (DEBUG) Log.v(TAG, "APP PRIVATE COMMAND " + action + ": " + data);
- mCurMethod.appPrivateCommand(action, data);
- } catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- }
- }
- }
-
- /**
- * Force switch to a new input method component. This can only be called
- * from the currently active input method, as validated by the given token.
- * @param token Supplies the identifying token given to an input method
- * when it was started, which allows it to perform this operation on
- * itself.
- * @param id The unique identifier for the new input method to be switched to.
- */
- public void setInputMethod(IBinder token, String id) {
- try {
- mService.setInputMethod(token, id);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Close/hide the input method's soft input area, so the user no longer
- * sees it or can interact with it. This can only be called
- * from the currently active input method, as validated by the given token.
- *
- * @param token Supplies the identifying token given to an input method
- * when it was started, which allows it to perform this operation on
- * itself.
- * @param flags Provides additional operating flags. Currently may be
- * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
- */
- public void hideSoftInputFromInputMethod(IBinder token, int flags) {
- try {
- mService.hideMySoftInput(token, flags);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * @hide
- */
- public void dispatchKeyEvent(Context context, int seq, KeyEvent key,
- IInputMethodCallback callback) {
- synchronized (mH) {
- if (DEBUG) Log.d(TAG, "dispatchKeyEvent");
-
- if (mCurMethod == null) {
- try {
- callback.finishedEvent(seq, false);
- } catch (RemoteException e) {
- }
- return;
- }
-
- if (key.getAction() == KeyEvent.ACTION_DOWN
- && key.getKeyCode() == KeyEvent.KEYCODE_SYM) {
- showInputMethodPicker();
- try {
- callback.finishedEvent(seq, true);
- } catch (RemoteException e) {
- }
- return;
- }
- try {
- if (DEBUG) Log.v(TAG, "DISPATCH KEY: " + mCurMethod);
- mCurMethod.dispatchKeyEvent(seq, key, callback);
- } catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId + " dropping: " + key, e);
- try {
- callback.finishedEvent(seq, false);
- } catch (RemoteException ex) {
- }
- }
- }
- }
-
- /**
- * @hide
- */
- void dispatchTrackballEvent(Context context, int seq, MotionEvent motion,
- IInputMethodCallback callback) {
- synchronized (mH) {
- if (DEBUG) Log.d(TAG, "dispatchTrackballEvent");
-
- if (mCurMethod == null || mCurrentTextBoxAttribute == null) {
- try {
- callback.finishedEvent(seq, false);
- } catch (RemoteException e) {
- }
- return;
- }
-
- try {
- if (DEBUG) Log.v(TAG, "DISPATCH TRACKBALL: " + mCurMethod);
- mCurMethod.dispatchTrackballEvent(seq, motion, callback);
- } catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId + " dropping trackball: " + motion, e);
- try {
- callback.finishedEvent(seq, false);
- } catch (RemoteException ex) {
- }
- }
- }
- }
-
- public void showInputMethodPicker() {
- synchronized (mH) {
- try {
- mService.showInputMethodPickerFromClient(mClient);
- } catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- }
- }
- }
-
- void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
- final Printer p = new PrintWriterPrinter(fout);
- p.println("Input method client state for " + this + ":");
-
- p.println(" mService=" + mService);
- p.println(" mMainLooper=" + mMainLooper);
- p.println(" mIInputContext=" + mIInputContext);
- p.println(" mActive=" + mActive
- + " mBindSequence=" + mBindSequence
- + " mCurId=" + mCurId);
- p.println(" mCurMethod=" + mCurMethod);
- p.println(" mServedView=" + mServedView);
- p.println(" mLastServedView=" + mLastServedView);
- p.println(" mServedConnecting=" + mServedConnecting);
- if (mCurrentTextBoxAttribute != null) {
- p.println(" mCurrentTextBoxAttribute:");
- mCurrentTextBoxAttribute.dump(p, " ");
- } else {
- p.println(" mCurrentTextBoxAttribute: null");
- }
- p.println(" mServedInputConnection=" + mServedInputConnection);
- p.println(" mCompletions=" + mCompletions);
- p.println(" mCursorRect=" + mCursorRect);
- p.println(" mCursorSelStart=" + mCursorSelStart
- + " mCursorSelEnd=" + mCursorSelEnd
- + " mCursorCandStart=" + mCursorCandStart
- + " mCursorCandEnd=" + mCursorCandEnd);
- }
-}
diff --git a/core/java/android/view/inputmethod/InputMethodSession.java b/core/java/android/view/inputmethod/InputMethodSession.java
deleted file mode 100644
index b5bbaff..0000000
--- a/core/java/android/view/inputmethod/InputMethodSession.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.view.inputmethod;
-
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-
-/**
- * The InputMethodSession interface provides the per-client functionality
- * of {@link InputMethod} that is safe to expose to applications.
- *
- * <p>Applications will not normally use this interface themselves, instead
- * relying on the standard interaction provided by
- * {@link android.widget.TextView} and {@link android.widget.EditText}.
- */
-public interface InputMethodSession {
-
- public interface EventCallback {
- void finishedEvent(int seq, boolean handled);
- }
-
- /**
- * This method is called when the application would like to stop
- * receiving text input.
- */
- public void finishInput();
-
- /**
- * This method is called when the selection or cursor in the current
- * target input field has changed.
- *
- * @param oldSelStart The previous text offset of the cursor selection
- * start position.
- * @param oldSelEnd The previous text offset of the cursor selection
- * end position.
- * @param newSelStart The new text offset of the cursor selection
- * start position.
- * @param newSelEnd The new text offset of the cursor selection
- * end position.
- * @param candidatesStart The text offset of the current candidate
- * text start position.
- * @param candidatesEnd The text offset of the current candidate
- * text end position.
- */
- public void updateSelection(int oldSelStart, int oldSelEnd,
- int newSelStart, int newSelEnd,
- int candidatesStart, int candidatesEnd);
-
- /**
- * This method is called when cursor location of the target input field
- * has changed within its window. This is not normally called, but will
- * only be reported if requested by the input method.
- *
- * @param newCursor The rectangle of the cursor currently being shown in
- * the input field's window coordinates.
- */
- public void updateCursor(Rect newCursor);
-
- /**
- * Called by a text editor that performs auto completion, to tell the
- * input method about the completions it has available. This can be used
- * by the input method to display them to the user to select the text to
- * be inserted.
- *
- * @param completions Array of text completions that are available, starting with
- * the best. If this array is null, any existing completions will be
- * removed.
- */
- public void displayCompletions(CompletionInfo[] completions);
-
- /**
- * Called by a text editor to report its new extracted text when its
- * contents change. This will only be called if the input method
- * calls {@link InputConnection#getExtractedText(ExtractedTextRequest, int)
- * InputConnection.getExtractedText()} with the option to report updates.
- *
- * @param token The input method supplied token for identifying its request.
- * @param text The new extracted text.
- */
- public void updateExtractedText(int token, ExtractedText text);
-
- /**
- * This method is called when a key is pressed. When done with the event,
- * the implementation must call back on <var>callback</var> with its
- * result.
- *
- * <p>
- * If the input method wants to handle this event, return true, otherwise
- * return false and the caller (i.e. the application) will handle the event.
- *
- * @param event The key event.
- *
- * @return Whether the input method wants to handle this event.
- *
- * @see #dispatchKeyUp
- * @see android.view.KeyEvent
- */
- public void dispatchKeyEvent(int seq, KeyEvent event, EventCallback callback);
-
- /**
- * This method is called when there is a track ball event.
- *
- * <p>
- * If the input method wants to handle this event, return true, otherwise
- * return false and the caller (i.e. the application) will handle the event.
- *
- * @param event The motion event.
- *
- * @return Whether the input method wants to handle this event.
- *
- * @see android.view.MotionEvent
- */
- public void dispatchTrackballEvent(int seq, MotionEvent event, EventCallback callback);
-
- /**
- * Process a private command sent from the application to the input method.
- * This can be used to provide domain-specific features that are
- * only known between certain input methods and their clients.
- *
- * @param action Name of the command to be performed. This <em>must</em>
- * be a scoped name, i.e. prefixed with a package name you own, so that
- * different developers will not create conflicting commands.
- * @param data Any data to include with the command.
- */
- public void appPrivateCommand(String action, Bundle data);
-}
diff --git a/core/java/android/view/inputmethod/package.html b/core/java/android/view/inputmethod/package.html
deleted file mode 100644
index 328c7b3..0000000
--- a/core/java/android/view/inputmethod/package.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<html>
-<body>
-Framework classes for interaction between views and input methods (such
-as soft keyboards). See {@link android.view.inputmethod.InputMethodManager} for
-an overview. In most cases the main classes here are not needed for
-most applications, since they are dealt with for you by
-{@link android.widget.TextView}. When implementing a custom text editor,
-however, you will need to implement the
-{@link android.view.inputmethod.InputConnection} class to allow the current
-input method to interact with your view.
-</body>
-</html>
diff --git a/core/java/android/view/package.html b/core/java/android/view/package.html
deleted file mode 100644
index 1c58765..0000000
--- a/core/java/android/view/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<HTML>
-<BODY>
-Provides classes that expose basic user interface classes that handle
-screen layout and interaction with the user.
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
deleted file mode 100644
index 451af6d..0000000
--- a/core/java/android/webkit/BrowserFrame.java
+++ /dev/null
@@ -1,786 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.content.Context;
-import android.content.res.AssetManager;
-import android.graphics.Bitmap;
-import android.net.ParseException;
-import android.net.WebAddress;
-import android.net.http.SslCertificate;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Config;
-import android.util.Log;
-import android.util.TypedValue;
-
-import junit.framework.Assert;
-
-import java.net.URLEncoder;
-import java.util.HashMap;
-import java.util.Iterator;
-
-class BrowserFrame extends Handler {
-
- private static final String LOGTAG = "webkit";
-
- /**
- * Cap the number of LoadListeners that will be instantiated, so
- * we don't blow the GREF count. Attempting to queue more than
- * this many requests will prompt an error() callback on the
- * request's LoadListener
- */
- private final static int MAX_OUTSTANDING_REQUESTS = 300;
-
- private final CallbackProxy mCallbackProxy;
- private final WebSettings mSettings;
- private final Context mContext;
- private final WebViewDatabase mDatabase;
- private final WebViewCore mWebViewCore;
- /* package */ boolean mLoadInitFromJava;
- private int mLoadType;
- private boolean mFirstLayoutDone = true;
- private boolean mCommitted = true;
-
- // Is this frame the main frame?
- private boolean mIsMainFrame;
-
- // Attached Javascript interfaces
- private HashMap mJSInterfaceMap;
-
- // message ids
- // a message posted when a frame loading is completed
- static final int FRAME_COMPLETED = 1001;
- // a message posted when the user decides the policy
- static final int POLICY_FUNCTION = 1003;
-
- // Note: need to keep these in sync with FrameLoaderTypes.h in native
- static final int FRAME_LOADTYPE_STANDARD = 0;
- static final int FRAME_LOADTYPE_BACK = 1;
- static final int FRAME_LOADTYPE_FORWARD = 2;
- static final int FRAME_LOADTYPE_INDEXEDBACKFORWARD = 3;
- static final int FRAME_LOADTYPE_RELOAD = 4;
- static final int FRAME_LOADTYPE_RELOADALLOWINGSTALEDATA = 5;
- static final int FRAME_LOADTYPE_SAME = 6;
- static final int FRAME_LOADTYPE_REDIRECT = 7;
- static final int FRAME_LOADTYPE_REPLACE = 8;
-
- // A progress threshold to switch from history Picture to live Picture
- private static final int TRANSITION_SWITCH_THRESHOLD = 75;
-
- // This is a field accessed by native code as well as package classes.
- /*package*/ int mNativeFrame;
-
- // Static instance of a JWebCoreJavaBridge to handle timer and cookie
- // requests from WebCore.
- static JWebCoreJavaBridge sJavaBridge;
-
- /**
- * Create a new BrowserFrame to be used in an application.
- * @param context An application context to use when retrieving assets.
- * @param w A WebViewCore used as the view for this frame.
- * @param proxy A CallbackProxy for posting messages to the UI thread and
- * querying a client for information.
- * @param settings A WebSettings object that holds all settings.
- * XXX: Called by WebCore thread.
- */
- public BrowserFrame(Context context, WebViewCore w, CallbackProxy proxy,
- WebSettings settings) {
- // Create a global JWebCoreJavaBridge to handle timers and
- // cookies in the WebCore thread.
- if (sJavaBridge == null) {
- sJavaBridge = new JWebCoreJavaBridge();
- // set WebCore native cache size
- sJavaBridge.setCacheSize(4 * 1024 * 1024);
- // initialize CacheManager
- CacheManager.init(context);
- // create CookieSyncManager with current Context
- CookieSyncManager.createInstance(context);
- }
- AssetManager am = context.getAssets();
- nativeCreateFrame(w, am, proxy.getBackForwardList());
-
- mSettings = settings;
- mContext = context;
- mCallbackProxy = proxy;
- mDatabase = WebViewDatabase.getInstance(context);
- mWebViewCore = w;
-
- if (Config.LOGV) {
- Log.v(LOGTAG, "BrowserFrame constructor: this=" + this);
- }
- }
-
- /**
- * Load a url from the network or the filesystem into the main frame.
- * Following the same behaviour as Safari, javascript: URLs are not
- * passed to the main frame, instead they are evaluated immediately.
- * @param url The url to load.
- */
- public void loadUrl(String url) {
- mLoadInitFromJava = true;
- if (URLUtil.isJavaScriptUrl(url)) {
- // strip off the scheme and evaluate the string
- stringByEvaluatingJavaScriptFromString(
- url.substring("javascript:".length()));
- } else {
- nativeLoadUrl(url);
- }
- mLoadInitFromJava = false;
- }
-
- /**
- * Load the content as if it was loaded by the provided base URL. The
- * failUrl is used as the history entry for the load data. If null or
- * an empty string is passed for the failUrl, then no history entry is
- * created.
- *
- * @param baseUrl Base URL used to resolve relative paths in the content
- * @param data Content to render in the browser
- * @param mimeType Mimetype of the data being passed in
- * @param encoding Character set encoding of the provided data.
- * @param failUrl URL to use if the content fails to load or null.
- */
- public void loadData(String baseUrl, String data, String mimeType,
- String encoding, String failUrl) {
- mLoadInitFromJava = true;
- if (failUrl == null) {
- failUrl = "";
- }
- if (data == null) {
- data = "";
- }
-
- // Setup defaults for missing values. These defaults where taken from
- // WebKit's WebFrame.mm
- if (baseUrl == null || baseUrl.length() == 0) {
- baseUrl = "about:blank";
- }
- if (mimeType == null || mimeType.length() == 0) {
- mimeType = "text/html";
- }
- nativeLoadData(baseUrl, data, mimeType, encoding, failUrl);
- mLoadInitFromJava = false;
- }
-
- /**
- * Go back or forward the number of steps given.
- * @param steps A negative or positive number indicating the direction
- * and number of steps to move.
- */
- public void goBackOrForward(int steps) {
- mLoadInitFromJava = true;
- nativeGoBackOrForward(steps);
- mLoadInitFromJava = false;
- }
-
- /**
- * native callback
- * Report an error to an activity.
- * @param errorCode The HTTP error code.
- * @param description A String description.
- * TODO: Report all errors including resource errors but include some kind
- * of domain identifier. Change errorCode to an enum for a cleaner
- * interface.
- */
- private void reportError(final int errorCode, final String description,
- final String failingUrl) {
- // As this is called for the main resource and loading will be stopped
- // after, reset the state variables.
- mCommitted = true;
- mWebViewCore.mEndScaleZoom = mFirstLayoutDone == false;
- mFirstLayoutDone = true;
- mCallbackProxy.onReceivedError(errorCode, description, failingUrl);
- }
-
- /* package */boolean committed() {
- return mCommitted;
- }
-
- /* package */boolean firstLayoutDone() {
- return mFirstLayoutDone;
- }
-
- /* package */int loadType() {
- return mLoadType;
- }
-
- /* package */void didFirstLayout() {
- if (!mFirstLayoutDone) {
- mFirstLayoutDone = true;
- // ensure {@link WebViewCore#webkitDraw} is called as we were
- // blocking the update in {@link #loadStarted}
- mWebViewCore.contentDraw();
- }
- mWebViewCore.mEndScaleZoom = true;
- }
-
- /**
- * native callback
- * Indicates the beginning of a new load.
- * This method will be called once for the main frame.
- */
- private void loadStarted(String url, Bitmap favicon, int loadType,
- boolean isMainFrame) {
- mIsMainFrame = isMainFrame;
-
- if (isMainFrame || loadType == FRAME_LOADTYPE_STANDARD) {
- mLoadType = loadType;
-
- if (isMainFrame) {
- // Call onPageStarted for main frames.
- mCallbackProxy.onPageStarted(url, favicon);
- // as didFirstLayout() is only called for the main frame, reset
- // mFirstLayoutDone only for the main frames
- mFirstLayoutDone = false;
- mCommitted = false;
- // remove pending draw to block update until mFirstLayoutDone is
- // set to true in didFirstLayout()
- mWebViewCore.removeMessages(WebViewCore.EventHub.WEBKIT_DRAW);
- }
-
- // Note: only saves committed form data in standard load
- if (loadType == FRAME_LOADTYPE_STANDARD
- && mSettings.getSaveFormData()) {
- final WebHistoryItem h = mCallbackProxy.getBackForwardList()
- .getCurrentItem();
- if (h != null) {
- String currentUrl = h.getUrl();
- if (currentUrl != null) {
- mDatabase.setFormData(currentUrl, getFormTextData());
- }
- }
- }
- }
- }
-
- /**
- * native callback
- * Indicates the WebKit has committed to the new load
- */
- private void transitionToCommitted(int loadType, boolean isMainFrame) {
- // loadType is not used yet
- if (isMainFrame) {
- mCommitted = true;
- }
- }
-
- /**
- * native callback
- * <p>
- * Indicates the end of a new load.
- * This method will be called once for the main frame.
- */
- private void loadFinished(String url, int loadType, boolean isMainFrame) {
- // mIsMainFrame and isMainFrame are better be equal!!!
-
- if (isMainFrame || loadType == FRAME_LOADTYPE_STANDARD) {
- if (isMainFrame) {
- mCallbackProxy.switchOutDrawHistory();
- mCallbackProxy.onPageFinished(url);
- }
- }
- }
-
- /**
- * We have received an SSL certificate for the main top-level page.
- *
- * !!!Called from the network thread!!!
- */
- void certificate(SslCertificate certificate) {
- if (mIsMainFrame) {
- // we want to make this call even if the certificate is null
- // (ie, the site is not secure)
- mCallbackProxy.onReceivedCertificate(certificate);
- }
- }
-
- /**
- * Destroy all native components of the BrowserFrame.
- */
- public void destroy() {
- nativeDestroyFrame();
- removeCallbacksAndMessages(null);
- }
-
- /**
- * Handle messages posted to us.
- * @param msg The message to handle.
- */
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case FRAME_COMPLETED: {
- if (mSettings.getSavePassword() && hasPasswordField()) {
- if (Config.DEBUG) {
- Assert.assertNotNull(mCallbackProxy.getBackForwardList()
- .getCurrentItem());
- }
- WebAddress uri = new WebAddress(
- mCallbackProxy.getBackForwardList().getCurrentItem()
- .getUrl());
- String schemePlusHost = uri.mScheme + uri.mHost;
- String[] up = mDatabase.getUsernamePassword(schemePlusHost);
- if (up != null && up[0] != null) {
- setUsernamePassword(up[0], up[1]);
- }
- }
- CacheManager.trimCacheIfNeeded();
- break;
- }
-
- case POLICY_FUNCTION: {
- nativeCallPolicyFunction(msg.arg1, msg.arg2);
- break;
- }
-
- default:
- break;
- }
- }
-
- /**
- * Punch-through for WebCore to set the document
- * title. Inform the Activity of the new title.
- * @param title The new title of the document.
- */
- private void setTitle(String title) {
- // FIXME: The activity must call getTitle (a native method) to get the
- // title. We should try and cache the title if we can also keep it in
- // sync with the document.
- mCallbackProxy.onReceivedTitle(title);
- }
-
- /**
- * Retrieves the render tree of this frame and puts it as the object for
- * the message and sends the message.
- * @param callback the message to use to send the render tree
- */
- public void externalRepresentation(Message callback) {
- callback.obj = externalRepresentation();;
- callback.sendToTarget();
- }
-
- /**
- * Return the render tree as a string
- */
- private native String externalRepresentation();
-
- /**
- * Retrieves the visual text of the current frame, puts it as the object for
- * the message and sends the message.
- * @param callback the message to use to send the visual text
- */
- public void documentAsText(Message callback) {
- callback.obj = documentAsText();;
- callback.sendToTarget();
- }
-
- /**
- * Return the text drawn on the screen as a string
- */
- private native String documentAsText();
-
- /*
- * This method is called by WebCore to inform the frame that
- * the Javascript window object has been cleared.
- * We should re-attach any attached js interfaces.
- */
- private void windowObjectCleared(int nativeFramePointer) {
- if (mJSInterfaceMap != null) {
- Iterator iter = mJSInterfaceMap.keySet().iterator();
- while (iter.hasNext()) {
- String interfaceName = (String) iter.next();
- nativeAddJavascriptInterface(nativeFramePointer,
- mJSInterfaceMap.get(interfaceName), interfaceName);
- }
- }
- }
-
- /**
- * This method is called by WebCore to check whether application
- * wants to hijack url loading
- */
- public boolean handleUrl(String url) {
- if (mLoadInitFromJava == true) {
- return false;
- }
- if (mCallbackProxy.shouldOverrideUrlLoading(url)) {
- // if the url is hijacked, reset the state of the BrowserFrame
- didFirstLayout();
- return true;
- } else {
- return false;
- }
- }
-
- public void addJavascriptInterface(Object obj, String interfaceName) {
- if (mJSInterfaceMap == null) {
- mJSInterfaceMap = new HashMap<String, Object>();
- }
- if (mJSInterfaceMap.containsKey(interfaceName)) {
- mJSInterfaceMap.remove(interfaceName);
- }
- mJSInterfaceMap.put(interfaceName, obj);
- }
-
- /**
- * Start loading a resource.
- * @param loaderHandle The native ResourceLoader that is the target of the
- * data.
- * @param url The url to load.
- * @param method The http method.
- * @param headers The http headers.
- * @param postData If the method is "POST" postData is sent as the request
- * body. Is null when empty.
- * @param cacheMode The cache mode to use when loading this resource.
- * @param isHighPriority True if this resource needs to be put at the front
- * of the network queue.
- * @param synchronous True if the load is synchronous.
- * @return A newly created LoadListener object.
- */
- private LoadListener startLoadingResource(int loaderHandle,
- String url,
- String method,
- HashMap headers,
- byte[] postData,
- int cacheMode,
- boolean isHighPriority,
- boolean synchronous) {
- PerfChecker checker = new PerfChecker();
-
- if (mSettings.getCacheMode() != WebSettings.LOAD_DEFAULT) {
- cacheMode = mSettings.getCacheMode();
- }
-
- if (method.equals("POST")) {
- // Don't use the cache on POSTs when issuing a normal POST
- // request.
- if (cacheMode == WebSettings.LOAD_NORMAL) {
- cacheMode = WebSettings.LOAD_NO_CACHE;
- }
- if (mSettings.getSavePassword() && hasPasswordField()) {
- try {
- if (Config.DEBUG) {
- Assert.assertNotNull(mCallbackProxy.getBackForwardList()
- .getCurrentItem());
- }
- WebAddress uri = new WebAddress(mCallbackProxy
- .getBackForwardList().getCurrentItem().getUrl());
- String schemePlusHost = uri.mScheme + uri.mHost;
- String[] ret = getUsernamePassword();
- // Has the user entered a username/password pair and is
- // there some POST data
- if (ret != null && postData != null &&
- ret[0].length() > 0 && ret[1].length() > 0) {
- // Check to see if the username & password appear in
- // the post data (there could be another form on the
- // page and that was posted instead.
- String postString = new String(postData);
- if (postString.contains(URLEncoder.encode(ret[0])) &&
- postString.contains(URLEncoder.encode(ret[1]))) {
- String[] saved = mDatabase.getUsernamePassword(
- schemePlusHost);
- if (saved != null) {
- // null username implies that user has chosen not to
- // save password
- if (saved[0] != null) {
- // non-null username implies that user has
- // chosen to save password, so update the
- // recorded password
- mDatabase.setUsernamePassword(
- schemePlusHost, ret[0], ret[1]);
- }
- } else {
- // CallbackProxy will handle creating the resume
- // message
- mCallbackProxy.onSavePassword(schemePlusHost, ret[0],
- ret[1], null);
- }
- }
- }
- } catch (ParseException ex) {
- // if it is bad uri, don't save its password
- }
-
- }
- }
-
- // is this resource the main-frame top-level page?
- boolean isMainFramePage = mIsMainFrame;
-
- if (Config.LOGV) {
- Log.v(LOGTAG, "startLoadingResource: url=" + url + ", method="
- + method + ", postData=" + postData + ", isHighPriority="
- + isHighPriority + ", isMainFramePage=" + isMainFramePage);
- }
-
- // Create a LoadListener
- LoadListener loadListener = LoadListener.getLoadListener(mContext, this, url,
- loaderHandle, synchronous, isMainFramePage);
-
- mCallbackProxy.onLoadResource(url);
-
- if (LoadListener.getNativeLoaderCount() > MAX_OUTSTANDING_REQUESTS) {
- loadListener.error(
- android.net.http.EventHandler.ERROR, mContext.getString(
- com.android.internal.R.string.httpErrorTooManyRequests));
- loadListener.notifyError();
- loadListener.tearDown();
- return null;
- }
-
- // during synchronous load, the WebViewCore thread is blocked, so we
- // need to endCacheTransaction first so that http thread won't be
- // blocked in setupFile() when createCacheFile.
- if (synchronous) {
- CacheManager.endCacheTransaction();
- }
-
- FrameLoader loader = new FrameLoader(loadListener, mSettings,
- method, isHighPriority);
- loader.setHeaders(headers);
- loader.setPostData(postData);
- loader.setCacheMode(cacheMode); // Set the load mode to the mode used
- // for the current page.
- // Set referrer to current URL?
- if (!loader.executeLoad()) {
- checker.responseAlert("startLoadingResource fail");
- }
- checker.responseAlert("startLoadingResource succeed");
-
- if (synchronous) {
- CacheManager.startCacheTransaction();
- }
-
- return !synchronous ? loadListener : null;
- }
-
- /**
- * Set the progress for the browser activity. Called by native code.
- * Uses a delay so it does not happen too often.
- * @param newProgress An int between zero and one hundred representing
- * the current progress percentage of loading the page.
- */
- private void setProgress(int newProgress) {
- mCallbackProxy.onProgressChanged(newProgress);
- if (newProgress == 100) {
- sendMessageDelayed(obtainMessage(FRAME_COMPLETED), 100);
- }
- // FIXME: Need to figure out a better way to switch out of the history
- // drawing mode. Maybe we can somehow compare the history picture with
- // the current picture, and switch when it contains more content.
- if (mFirstLayoutDone && newProgress > TRANSITION_SWITCH_THRESHOLD) {
- mCallbackProxy.switchOutDrawHistory();
- }
- }
-
- /**
- * Send the icon to the activity for display.
- * @param icon A Bitmap representing a page's favicon.
- */
- private void didReceiveIcon(Bitmap icon) {
- mCallbackProxy.onReceivedIcon(icon);
- }
-
- /**
- * Request a new window from the client.
- * @return The BrowserFrame object stored in the new WebView.
- */
- private BrowserFrame createWindow(boolean dialog, boolean userGesture) {
- WebView w = mCallbackProxy.createWindow(dialog, userGesture);
- if (w != null) {
- return w.getWebViewCore().getBrowserFrame();
- }
- return null;
- }
-
- /**
- * Try to focus this WebView.
- */
- private void requestFocus() {
- mCallbackProxy.onRequestFocus();
- }
-
- /**
- * Close this frame and window.
- */
- private void closeWindow(WebViewCore w) {
- mCallbackProxy.onCloseWindow(w.getWebView());
- }
-
- // XXX: Must match PolicyAction in FrameLoaderTypes.h in webcore
- static final int POLICY_USE = 0;
- static final int POLICY_IGNORE = 2;
-
- private void decidePolicyForFormResubmission(int policyFunction) {
- Message dontResend = obtainMessage(POLICY_FUNCTION, policyFunction,
- POLICY_IGNORE);
- Message resend = obtainMessage(POLICY_FUNCTION, policyFunction,
- POLICY_USE);
- mCallbackProxy.onFormResubmission(dontResend, resend);
- }
-
- /**
- * Tell the activity to update its global history.
- */
- private void updateVisitedHistory(String url, boolean isReload) {
- mCallbackProxy.doUpdateVisitedHistory(url, isReload);
- }
-
- /**
- * Get the CallbackProxy for sending messages to the UI thread.
- */
- /* package */ CallbackProxy getCallbackProxy() {
- return mCallbackProxy;
- }
-
- /**
- * Returns the User Agent used by this frame
- */
- String getUserAgentString() {
- return mSettings.getUserAgentString();
- }
-
- // these ids need to be in sync with enum RAW_RES_ID in WebFrame
- private static final int NODOMAIN = 1;
- private static final int LOADERROR = 2;
-
- String getRawResFilename(int id) {
- int resid;
- switch (id) {
- case NODOMAIN:
- resid = com.android.internal.R.raw.nodomain;
- break;
-
- case LOADERROR:
- resid = com.android.internal.R.raw.loaderror;
- break;
-
- default:
- Log.e(LOGTAG, "getRawResFilename got incompatible resource ID");
- return new String();
- }
- TypedValue value = new TypedValue();
- mContext.getResources().getValue(resid, value, true);
- return value.string.toString();
- }
-
- //==========================================================================
- // native functions
- //==========================================================================
-
- /**
- * Create a new native frame for a given WebView
- * @param w A WebView that the frame draws into.
- * @param am AssetManager to use to get assets.
- * @param list The native side will add and remove items from this list as
- * the native list changes.
- */
- private native void nativeCreateFrame(WebViewCore w, AssetManager am,
- WebBackForwardList list);
-
- /**
- * Destroy the native frame.
- */
- public native void nativeDestroyFrame();
-
- private native void nativeCallPolicyFunction(int policyFunction,
- int decision);
-
- /**
- * Reload the current main frame.
- */
- public native void reload(boolean allowStale);
-
- /**
- * Go back or forward the number of steps given.
- * @param steps A negative or positive number indicating the direction
- * and number of steps to move.
- */
- private native void nativeGoBackOrForward(int steps);
-
- /**
- * stringByEvaluatingJavaScriptFromString will execute the
- * JS passed in in the context of this browser frame.
- * @param script A javascript string to execute
- *
- * @return string result of execution or null
- */
- public native String stringByEvaluatingJavaScriptFromString(String script);
-
- /**
- * Add a javascript interface to the main frame.
- */
- private native void nativeAddJavascriptInterface(int nativeFramePointer,
- Object obj, String interfaceName);
-
- /**
- * Enable or disable the native cache.
- */
- /* FIXME: The native cache is always on for now until we have a better
- * solution for our 2 caches. */
- private native void setCacheDisabled(boolean disabled);
-
- public native boolean cacheDisabled();
-
- public native void clearCache();
-
- /**
- * Returns false if the url is bad.
- */
- private native void nativeLoadUrl(String url);
-
- private native void nativeLoadData(String baseUrl, String data,
- String mimeType, String encoding, String failUrl);
-
- /**
- * Stop loading the current page.
- */
- public native void stopLoading();
-
- /**
- * Return true if the document has images.
- */
- public native boolean documentHasImages();
-
- /**
- * @return TRUE if there is a password field in the current frame
- */
- private native boolean hasPasswordField();
-
- /**
- * Get username and password in the current frame. If found, String[0] is
- * username and String[1] is password. Otherwise return NULL.
- * @return String[]
- */
- private native String[] getUsernamePassword();
-
- /**
- * Set username and password to the proper fields in the current frame
- * @param username
- * @param password
- */
- private native void setUsernamePassword(String username, String password);
-
- /**
- * Get form's "text" type data associated with the current frame.
- * @return HashMap If succeed, returns a list of name/value pair. Otherwise
- * returns null.
- */
- private native HashMap getFormTextData();
-}
diff --git a/core/java/android/webkit/ByteArrayBuilder.java b/core/java/android/webkit/ByteArrayBuilder.java
deleted file mode 100644
index 806b458..0000000
--- a/core/java/android/webkit/ByteArrayBuilder.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import java.util.LinkedList;
-
-/** Utility class optimized for accumulating bytes, and then spitting
- them back out. It does not optimize for returning the result in a
- single array, though this is supported in the API. It is fastest
- if the retrieval can be done via iterating through chunks.
-
- Things to add:
- - consider dynamically increasing our min_capacity,
- as we see mTotalSize increase
-*/
-class ByteArrayBuilder {
-
- private static final int DEFAULT_CAPACITY = 8192;
-
- private LinkedList<Chunk> mChunks;
-
- /** free pool */
- private LinkedList<Chunk> mPool;
-
- private int mMinCapacity;
-
- public ByteArrayBuilder() {
- init(0);
- }
-
- public ByteArrayBuilder(int minCapacity) {
- init(minCapacity);
- }
-
- private void init(int minCapacity) {
- mChunks = new LinkedList<Chunk>();
- mPool = new LinkedList<Chunk>();
-
- if (minCapacity <= 0) {
- minCapacity = DEFAULT_CAPACITY;
- }
- mMinCapacity = minCapacity;
- }
-
- public void append(byte[] array) {
- append(array, 0, array.length);
- }
-
- public synchronized void append(byte[] array, int offset, int length) {
- while (length > 0) {
- Chunk c = appendChunk(length);
- int amount = Math.min(length, c.mArray.length - c.mLength);
- System.arraycopy(array, offset, c.mArray, c.mLength, amount);
- c.mLength += amount;
- length -= amount;
- offset += amount;
- }
- }
-
- /**
- * The fastest way to retrieve the data is to iterate through the
- * chunks. This returns the first chunk. Note: this pulls the
- * chunk out of the queue. The caller must call releaseChunk() to
- * dispose of it.
- */
- public synchronized Chunk getFirstChunk() {
- if (mChunks.isEmpty()) return null;
- return mChunks.removeFirst();
- }
-
- /**
- * recycles chunk
- */
- public synchronized void releaseChunk(Chunk c) {
- c.mLength = 0;
- mPool.addLast(c);
- }
-
- public boolean isEmpty() {
- return mChunks.isEmpty();
- }
-
- public synchronized void clear() {
- Chunk c = getFirstChunk();
- while (c != null) {
- releaseChunk(c);
- c = getFirstChunk();
- }
- }
-
- private Chunk appendChunk(int length) {
- if (length < mMinCapacity) {
- length = mMinCapacity;
- }
-
- Chunk c;
- if (mChunks.isEmpty()) {
- c = obtainChunk(length);
- } else {
- c = mChunks.getLast();
- if (c.mLength == c.mArray.length) {
- c = obtainChunk(length);
- }
- }
- return c;
- }
-
- private Chunk obtainChunk(int length) {
- Chunk c;
- if (mPool.isEmpty()) {
- c = new Chunk(length);
- } else {
- c = mPool.removeFirst();
- }
- mChunks.addLast(c);
- return c;
- }
-
- public static class Chunk {
- public byte[] mArray;
- public int mLength;
-
- public Chunk(int length) {
- mArray = new byte[length];
- mLength = 0;
- }
- }
-}
diff --git a/core/java/android/webkit/CacheLoader.java b/core/java/android/webkit/CacheLoader.java
deleted file mode 100644
index 3e1b602..0000000
--- a/core/java/android/webkit/CacheLoader.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.net.http.Headers;
-
-/**
- * This class is a concrete implementation of StreamLoader that uses a
- * CacheResult as the source for the stream. The CacheResult stored mimetype
- * and encoding is added to the HTTP response headers.
- */
-class CacheLoader extends StreamLoader {
-
- CacheManager.CacheResult mCacheResult; // Content source
-
- /**
- * Constructs a CacheLoader for use when loading content from the cache.
- *
- * @param loadListener LoadListener to pass the content to
- * @param result CacheResult used as the source for the content.
- */
- CacheLoader(LoadListener loadListener, CacheManager.CacheResult result) {
- super(loadListener);
- mCacheResult = result;
- }
-
- @Override
- protected boolean setupStreamAndSendStatus() {
- mDataStream = mCacheResult.inStream;
- mContentLength = mCacheResult.contentLength;
- mHandler.status(1, 1, mCacheResult.httpStatusCode, "OK");
- return true;
- }
-
- @Override
- protected void buildHeaders(Headers headers) {
- StringBuilder sb = new StringBuilder(mCacheResult.mimeType);
- if (mCacheResult.encoding != null &&
- mCacheResult.encoding.length() > 0) {
- sb.append(';');
- sb.append(mCacheResult.encoding);
- }
- headers.setContentType(sb.toString());
-
- if (mCacheResult.location != null &&
- mCacheResult.location.length() > 0) {
- headers.setLocation(mCacheResult.location);
- }
- }
-
-}
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
deleted file mode 100644
index d12940d..0000000
--- a/core/java/android/webkit/CacheManager.java
+++ /dev/null
@@ -1,703 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.content.Context;
-import android.net.http.Headers;
-import android.os.FileUtils;
-import android.util.Config;
-import android.util.Log;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Map;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-
-/**
- * The class CacheManager provides the persistent cache of content that is
- * received over the network. The component handles parsing of HTTP headers and
- * utilizes the relevant cache headers to determine if the content should be
- * stored and if so, how long it is valid for. Network requests are provided to
- * this component and if they can not be resolved by the cache, the HTTP headers
- * are attached, as appropriate, to the request for revalidation of content. The
- * class also manages the cache size.
- */
-public final class CacheManager {
-
- private static final String LOGTAG = "cache";
-
- static final String HEADER_KEY_IFMODIFIEDSINCE = "if-modified-since";
- static final String HEADER_KEY_IFNONEMATCH = "if-none-match";
-
- private static final String NO_STORE = "no-store";
- private static final String NO_CACHE = "no-cache";
- private static final String MAX_AGE = "max-age";
-
- private static long CACHE_THRESHOLD = 6 * 1024 * 1024;
- private static long CACHE_TRIM_AMOUNT = 2 * 1024 * 1024;
-
- private static boolean mDisabled;
-
- // Reference count the enable/disable transaction
- private static int mRefCount;
-
- // trimCacheIfNeeded() is called when a page is fully loaded. But JavaScript
- // can load the content, e.g. in a slideshow, continuously, so we need to
- // trim the cache on a timer base too. endCacheTransaction() is called on a
- // timer base. We share the same timer with less frequent update.
- private static int mTrimCacheCount = 0;
- private static final int TRIM_CACHE_INTERVAL = 5;
-
- private static WebViewDatabase mDataBase;
- private static File mBaseDir;
-
- // Flag to clear the cache when the CacheManager is initialized
- private static boolean mClearCacheOnInit = false;
-
- public static class CacheResult {
- // these fields are saved to the database
- int httpStatusCode;
- long contentLength;
- long expires;
- String localPath;
- String lastModified;
- String etag;
- String mimeType;
- String location;
- String encoding;
-
- // these fields are NOT saved to the database
- InputStream inStream;
- OutputStream outStream;
- File outFile;
-
- public int getHttpStatusCode() {
- return httpStatusCode;
- }
-
- public long getContentLength() {
- return contentLength;
- }
-
- public String getLocalPath() {
- return localPath;
- }
-
- public long getExpires() {
- return expires;
- }
-
- public String getLastModified() {
- return lastModified;
- }
-
- public String getETag() {
- return etag;
- }
-
- public String getMimeType() {
- return mimeType;
- }
-
- public String getLocation() {
- return location;
- }
-
- public String getEncoding() {
- return encoding;
- }
-
- // For out-of-package access to the underlying streams.
- public InputStream getInputStream() {
- return inStream;
- }
-
- public OutputStream getOutputStream() {
- return outStream;
- }
-
- // These fields can be set manually.
- public void setInputStream(InputStream stream) {
- this.inStream = stream;
- }
-
- public void setEncoding(String encoding) {
- this.encoding = encoding;
- }
- }
-
- /**
- * initialize the CacheManager. WebView should handle this for each process.
- *
- * @param context The application context.
- */
- static void init(Context context) {
- mDataBase = WebViewDatabase.getInstance(context);
- mBaseDir = new File(context.getCacheDir(), "webviewCache");
- if (createCacheDirectory() && mClearCacheOnInit) {
- removeAllCacheFiles();
- mClearCacheOnInit = false;
- }
- }
-
- /**
- * Create the cache directory if it does not already exist.
- *
- * @return true if the cache directory didn't exist and was created.
- */
- static private boolean createCacheDirectory() {
- if (!mBaseDir.exists()) {
- if(!mBaseDir.mkdirs()) {
- Log.w(LOGTAG, "Unable to create webviewCache directory");
- return false;
- }
- FileUtils.setPermissions(
- mBaseDir.toString(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
- -1, -1);
- // If we did create the directory, we need to flush
- // the cache database. The directory could be recreated
- // because the system flushed all the data/cache directories
- // to free up disk space.
- WebViewCore.endCacheTransaction();
- mDataBase.clearCache();
- WebViewCore.startCacheTransaction();
- return true;
- }
- return false;
- }
-
- /**
- * get the base directory of the cache. With localPath of the CacheResult,
- * it identifies the cache file.
- *
- * @return File The base directory of the cache.
- */
- public static File getCacheFileBaseDir() {
- return mBaseDir;
- }
-
- /**
- * set the flag to control whether cache is enabled or disabled
- *
- * @param disabled true to disable the cache
- */
- // only called from WebCore thread
- static void setCacheDisabled(boolean disabled) {
- if (disabled == mDisabled) {
- return;
- }
- mDisabled = disabled;
- if (mDisabled) {
- removeAllCacheFiles();
- }
- }
-
- /**
- * get the state of the current cache, enabled or disabled
- *
- * @return return if it is disabled
- */
- public static boolean cacheDisabled() {
- return mDisabled;
- }
-
- // only called from WebCore thread
- // make sure to call enableTransaction/disableTransaction in pair
- static boolean enableTransaction() {
- if (++mRefCount == 1) {
- mDataBase.startCacheTransaction();
- return true;
- }
- return false;
- }
-
- // only called from WebCore thread
- // make sure to call enableTransaction/disableTransaction in pair
- static boolean disableTransaction() {
- if (mRefCount == 0) {
- Log.e(LOGTAG, "disableTransaction is out of sync");
- }
- if (--mRefCount == 0) {
- mDataBase.endCacheTransaction();
- return true;
- }
- return false;
- }
-
- // only called from WebCore thread
- // make sure to call startCacheTransaction/endCacheTransaction in pair
- public static boolean startCacheTransaction() {
- return mDataBase.startCacheTransaction();
- }
-
- // only called from WebCore thread
- // make sure to call startCacheTransaction/endCacheTransaction in pair
- public static boolean endCacheTransaction() {
- boolean ret = mDataBase.endCacheTransaction();
- if (++mTrimCacheCount >= TRIM_CACHE_INTERVAL) {
- mTrimCacheCount = 0;
- trimCacheIfNeeded();
- }
- return ret;
- }
-
- /**
- * Given a url, returns the CacheResult if exists. Otherwise returns null.
- * If headers are provided and a cache needs validation,
- * HEADER_KEY_IFNONEMATCH or HEADER_KEY_IFMODIFIEDSINCE will be set in the
- * cached headers.
- *
- * @return the CacheResult for a given url
- */
- // only called from WebCore thread
- public static CacheResult getCacheFile(String url,
- Map<String, String> headers) {
- if (mDisabled) {
- return null;
- }
-
- CacheResult result = mDataBase.getCache(url);
- if (result != null) {
- if (result.contentLength == 0) {
- if (result.httpStatusCode != 301
- && result.httpStatusCode != 302
- && result.httpStatusCode != 307) {
- // this should not happen. If it does, remove it.
- mDataBase.removeCache(url);
- return null;
- }
- } else {
- File src = new File(mBaseDir, result.localPath);
- try {
- // open here so that even the file is deleted, the content
- // is still readable by the caller until close() is called
- result.inStream = new FileInputStream(src);
- } catch (FileNotFoundException e) {
- // the files in the cache directory can be removed by the
- // system. If it is gone, clean up the database
- mDataBase.removeCache(url);
- return null;
- }
- }
- } else {
- return null;
- }
-
- // null headers request coming from CACHE_MODE_CACHE_ONLY
- // which implies that it needs cache even it is expired.
- // negative expires means time in the far future.
- if (headers != null && result.expires >= 0
- && result.expires <= System.currentTimeMillis()) {
- if (result.lastModified == null && result.etag == null) {
- return null;
- }
- // return HEADER_KEY_IFNONEMATCH or HEADER_KEY_IFMODIFIEDSINCE
- // for requesting validation
- if (result.etag != null) {
- headers.put(HEADER_KEY_IFNONEMATCH, result.etag);
- }
- if (result.lastModified != null) {
- headers.put(HEADER_KEY_IFMODIFIEDSINCE, result.lastModified);
- }
- }
-
- if (Config.LOGV) {
- Log.v(LOGTAG, "getCacheFile for url " + url);
- }
-
- return result;
- }
-
- /**
- * Given a url and its full headers, returns CacheResult if a local cache
- * can be stored. Otherwise returns null. The mimetype is passed in so that
- * the function can use the mimetype that will be passed to WebCore which
- * could be different from the mimetype defined in the headers.
- * forceCache is for out-of-package callers to force creation of a
- * CacheResult, and is used to supply surrogate responses for URL
- * interception.
- * @return CacheResult for a given url
- * @hide - hide createCacheFile since it has a parameter of type headers, which is
- * in a hidden package.
- */
- // can be called from any thread
- public static CacheResult createCacheFile(String url, int statusCode,
- Headers headers, String mimeType, boolean forceCache) {
- if (!forceCache && mDisabled) {
- return null;
- }
-
- CacheResult ret = parseHeaders(statusCode, headers, mimeType);
- if (ret != null) {
- setupFiles(url, ret);
- try {
- ret.outStream = new FileOutputStream(ret.outFile);
- } catch (FileNotFoundException e) {
- // This can happen with the system did a purge and our
- // subdirectory has gone, so lets try to create it again
- if (createCacheDirectory()) {
- try {
- ret.outStream = new FileOutputStream(ret.outFile);
- } catch (FileNotFoundException e2) {
- // We failed to create the file again, so there
- // is something else wrong. Return null.
- return null;
- }
- } else {
- // Failed to create cache directory
- return null;
- }
- }
- ret.mimeType = mimeType;
- }
-
- return ret;
- }
-
- /**
- * Save the info of a cache file for a given url to the CacheMap so that it
- * can be reused later
- */
- // only called from WebCore thread
- public static void saveCacheFile(String url, CacheResult cacheRet) {
- try {
- cacheRet.outStream.close();
- } catch (IOException e) {
- return;
- }
-
- if (!cacheRet.outFile.exists()) {
- // the file in the cache directory can be removed by the system
- return;
- }
-
- cacheRet.contentLength = cacheRet.outFile.length();
- if (cacheRet.httpStatusCode == 301
- || cacheRet.httpStatusCode == 302
- || cacheRet.httpStatusCode == 307) {
- // location is in database, no need to keep the file
- cacheRet.contentLength = 0;
- cacheRet.localPath = new String();
- cacheRet.outFile.delete();
- } else if (cacheRet.contentLength == 0) {
- cacheRet.outFile.delete();
- return;
- }
-
- mDataBase.addCache(url, cacheRet);
-
- if (Config.LOGV) {
- Log.v(LOGTAG, "saveCacheFile for url " + url);
- }
- }
-
- /**
- * remove all cache files
- *
- * @return true if it succeeds
- */
- // only called from WebCore thread
- static boolean removeAllCacheFiles() {
- // Note, this is called before init() when the database is
- // created or upgraded.
- if (mBaseDir == null) {
- // Init() has not been called yet, so just flag that
- // we need to clear the cache when init() is called.
- mClearCacheOnInit = true;
- return true;
- }
- // delete cache in a separate thread to not block UI.
- final Runnable clearCache = new Runnable() {
- public void run() {
- // delete all cache files
- try {
- String[] files = mBaseDir.list();
- // if mBaseDir doesn't exist, files can be null.
- if (files != null) {
- for (int i = 0; i < files.length; i++) {
- new File(mBaseDir, files[i]).delete();
- }
- }
- } catch (SecurityException e) {
- // Ignore SecurityExceptions.
- }
- // delete database
- mDataBase.clearCache();
- }
- };
- new Thread(clearCache).start();
- return true;
- }
-
- /**
- * Return true if the cache is empty.
- */
- // only called from WebCore thread
- static boolean cacheEmpty() {
- return mDataBase.hasCache();
- }
-
- // only called from WebCore thread
- static void trimCacheIfNeeded() {
- if (mDataBase.getCacheTotalSize() > CACHE_THRESHOLD) {
- ArrayList<String> pathList = mDataBase.trimCache(CACHE_TRIM_AMOUNT);
- int size = pathList.size();
- for (int i = 0; i < size; i++) {
- new File(mBaseDir, pathList.get(i)).delete();
- }
- }
- }
-
- @SuppressWarnings("deprecation")
- private static void setupFiles(String url, CacheResult cacheRet) {
- if (true) {
- // Note: SHA1 is much stronger hash. But the cost of setupFiles() is
- // 3.2% cpu time for a fresh load of nytimes.com. While a simple
- // String.hashCode() is only 0.6%. If adding the collision resolving
- // to String.hashCode(), it makes the cpu time to be 1.6% for a
- // fresh load, but 5.3% for the worst case where all the files
- // already exist in the file system, but database is gone. So it
- // needs to resolve collision for every file at least once.
- int hashCode = url.hashCode();
- StringBuffer ret = new StringBuffer(8);
- appendAsHex(hashCode, ret);
- String path = ret.toString();
- File file = new File(mBaseDir, path);
- if (true) {
- boolean checkOldPath = true;
- // Check hash collision. If the hash file doesn't exist, just
- // continue. There is a chance that the old cache file is not
- // same as the hash file. As mDataBase.getCache() is more
- // expansive than "leak" a file until clear cache, don't bother.
- // If the hash file exists, make sure that it is same as the
- // cache file. If it is not, resolve the collision.
- while (file.exists()) {
- if (checkOldPath) {
- // as this is called from http thread through
- // createCacheFile, we need endCacheTransaction before
- // database access.
- WebViewCore.endCacheTransaction();
- CacheResult oldResult = mDataBase.getCache(url);
- WebViewCore.startCacheTransaction();
- if (oldResult != null && oldResult.contentLength > 0) {
- if (path.equals(oldResult.localPath)) {
- path = oldResult.localPath;
- } else {
- path = oldResult.localPath;
- file = new File(mBaseDir, path);
- }
- break;
- }
- checkOldPath = false;
- }
- ret = new StringBuffer(8);
- appendAsHex(++hashCode, ret);
- path = ret.toString();
- file = new File(mBaseDir, path);
- }
- }
- cacheRet.localPath = path;
- cacheRet.outFile = file;
- } else {
- // get hash in byte[]
- Digest digest = new SHA1Digest();
- int digestLen = digest.getDigestSize();
- byte[] hash = new byte[digestLen];
- int urlLen = url.length();
- byte[] data = new byte[urlLen];
- url.getBytes(0, urlLen, data, 0);
- digest.update(data, 0, urlLen);
- digest.doFinal(hash, 0);
- // convert byte[] to hex String
- StringBuffer result = new StringBuffer(2 * digestLen);
- for (int i = 0; i < digestLen; i = i + 4) {
- int h = (0x00ff & hash[i]) << 24 | (0x00ff & hash[i + 1]) << 16
- | (0x00ff & hash[i + 2]) << 8 | (0x00ff & hash[i + 3]);
- appendAsHex(h, result);
- }
- cacheRet.localPath = result.toString();
- cacheRet.outFile = new File(mBaseDir, cacheRet.localPath);
- }
- }
-
- private static void appendAsHex(int i, StringBuffer ret) {
- String hex = Integer.toHexString(i);
- switch (hex.length()) {
- case 1:
- ret.append("0000000");
- break;
- case 2:
- ret.append("000000");
- break;
- case 3:
- ret.append("00000");
- break;
- case 4:
- ret.append("0000");
- break;
- case 5:
- ret.append("000");
- break;
- case 6:
- ret.append("00");
- break;
- case 7:
- ret.append("0");
- break;
- }
- ret.append(hex);
- }
-
- private static CacheResult parseHeaders(int statusCode, Headers headers,
- String mimeType) {
- // TODO: if authenticated or secure, return null
- CacheResult ret = new CacheResult();
- ret.httpStatusCode = statusCode;
-
- String location = headers.getLocation();
- if (location != null) ret.location = location;
-
- ret.expires = -1;
- String expires = headers.getExpires();
- if (expires != null) {
- try {
- ret.expires = HttpDateTime.parse(expires);
- } catch (IllegalArgumentException ex) {
- // Take care of the special "-1" and "0" cases
- if ("-1".equals(expires) || "0".equals(expires)) {
- // make it expired, but can be used for history navigation
- ret.expires = 0;
- } else {
- Log.e(LOGTAG, "illegal expires: " + expires);
- }
- }
- }
-
- String lastModified = headers.getLastModified();
- if (lastModified != null) ret.lastModified = lastModified;
-
- String etag = headers.getEtag();
- if (etag != null) ret.etag = etag;
-
- String cacheControl = headers.getCacheControl();
- if (cacheControl != null) {
- String[] controls = cacheControl.toLowerCase().split("[ ,;]");
- for (int i = 0; i < controls.length; i++) {
- if (NO_STORE.equals(controls[i])) {
- return null;
- }
- // According to the spec, 'no-cache' means that the content
- // must be re-validated on every load. It does not mean that
- // the content can not be cached. set to expire 0 means it
- // can only be used in CACHE_MODE_CACHE_ONLY case
- if (NO_CACHE.equals(controls[i])) {
- ret.expires = 0;
- } else if (controls[i].startsWith(MAX_AGE)) {
- int separator = controls[i].indexOf('=');
- if (separator < 0) {
- separator = controls[i].indexOf(':');
- }
- if (separator > 0) {
- String s = controls[i].substring(separator + 1);
- try {
- long sec = Long.parseLong(s);
- if (sec >= 0) {
- ret.expires = System.currentTimeMillis() + 1000
- * sec;
- }
- } catch (NumberFormatException ex) {
- if ("1d".equals(s)) {
- // Take care of the special "1d" case
- ret.expires = System.currentTimeMillis() + 86400000; // 24*60*60*1000
- } else {
- Log.e(LOGTAG, "exception in parseHeaders for "
- + "max-age:"
- + controls[i].substring(separator + 1));
- ret.expires = 0;
- }
- }
- }
- }
- }
- }
-
- // According to RFC 2616 section 14.32:
- // HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the
- // client had sent "Cache-Control: no-cache"
- if (NO_CACHE.equals(headers.getPragma())) {
- ret.expires = 0;
- }
-
- // According to RFC 2616 section 13.2.4, if an expiration has not been
- // explicitly defined a heuristic to set an expiration may be used.
- if (ret.expires == -1) {
- if (ret.httpStatusCode == 301) {
- // If it is a permanent redirect, and it did not have an
- // explicit cache directive, then it never expires
- ret.expires = Long.MAX_VALUE;
- } else if (ret.httpStatusCode == 302 || ret.httpStatusCode == 307) {
- // If it is temporary redirect, expires
- ret.expires = 0;
- } else if (ret.lastModified == null) {
- // When we have no last-modified, then expire the content with
- // in 24hrs as, according to the RFC, longer time requires a
- // warning 113 to be added to the response.
-
- // Only add the default expiration for non-html markup. Some
- // sites like news.google.com have no cache directives.
- if (!mimeType.startsWith("text/html")) {
- ret.expires = System.currentTimeMillis() + 86400000; // 24*60*60*1000
- } else {
- // Setting a expires as zero will cache the result for
- // forward/back nav.
- ret.expires = 0;
- }
- } else {
- // If we have a last-modified value, we could use it to set the
- // expiration. Suggestion from RFC is 10% of time since
- // last-modified. As we are on mobile, loads are expensive,
- // increasing this to 20%.
-
- // 24 * 60 * 60 * 1000
- long lastmod = System.currentTimeMillis() + 86400000;
- try {
- lastmod = HttpDateTime.parse(ret.lastModified);
- } catch (IllegalArgumentException ex) {
- Log.e(LOGTAG, "illegal lastModified: " + ret.lastModified);
- }
- long difference = System.currentTimeMillis() - lastmod;
- if (difference > 0) {
- ret.expires = System.currentTimeMillis() + difference / 5;
- } else {
- // last modified is in the future, expire the content
- // on the last modified
- ret.expires = lastmod;
- }
- }
- }
-
- return ret;
- }
-}
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
deleted file mode 100644
index 4f8e5e4..0000000
--- a/core/java/android/webkit/CallbackProxy.java
+++ /dev/null
@@ -1,1018 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.app.AlertDialog;
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.net.http.SslCertificate;
-import android.net.http.SslError;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemClock;
-import android.util.Config;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.EditText;
-import android.widget.TextView;
-import com.android.internal.R;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.HashMap;
-
-/**
- * This class is a proxy class for handling WebCore -> UI thread messaging. All
- * the callback functions are called from the WebCore thread and messages are
- * posted to the UI thread for the actual client callback.
- */
-/*
- * This class is created in the UI thread so its handler and any private classes
- * that extend Handler will operate in the UI thread.
- */
-class CallbackProxy extends Handler {
- // Logging tag
- private static final String LOGTAG = "CallbackProxy";
- // Instance of WebViewClient that is the client callback.
- private volatile WebViewClient mWebViewClient;
- // Instance of WebChromeClient for handling all chrome functions.
- private volatile WebChromeClient mWebChromeClient;
- // Instance of WebView for handling UI requests.
- private final WebView mWebView;
- // Client registered callback listener for download events
- private volatile DownloadListener mDownloadListener;
- // Keep track of multiple progress updates.
- private boolean mProgressUpdatePending;
- // Keep track of the last progress amount.
- private volatile int mLatestProgress;
- // Back/Forward list
- private final WebBackForwardList mBackForwardList;
- // Used to call startActivity during url override.
- private final Context mContext;
-
- // Message Ids
- private static final int PAGE_STARTED = 100;
- private static final int RECEIVED_ICON = 101;
- private static final int RECEIVED_TITLE = 102;
- private static final int OVERRIDE_URL = 103;
- private static final int AUTH_REQUEST = 104;
- private static final int SSL_ERROR = 105;
- private static final int PROGRESS = 106;
- private static final int UPDATE_VISITED = 107;
- private static final int LOAD_RESOURCE = 108;
- private static final int CREATE_WINDOW = 109;
- private static final int CLOSE_WINDOW = 110;
- private static final int SAVE_PASSWORD = 111;
- private static final int JS_ALERT = 112;
- private static final int JS_CONFIRM = 113;
- private static final int JS_PROMPT = 114;
- private static final int JS_UNLOAD = 115;
- private static final int ASYNC_KEYEVENTS = 116;
- private static final int TOO_MANY_REDIRECTS = 117;
- private static final int DOWNLOAD_FILE = 118;
- private static final int REPORT_ERROR = 119;
- private static final int RESEND_POST_DATA = 120;
- private static final int PAGE_FINISHED = 121;
- private static final int REQUEST_FOCUS = 122;
- private static final int SCALE_CHANGED = 123;
- private static final int RECEIVED_CERTIFICATE = 124;
- private static final int SWITCH_OUT_HISTORY = 125;
-
- // Message triggered by the client to resume execution
- private static final int NOTIFY = 200;
-
- // Result transportation object for returning results across thread
- // boundaries.
- private class ResultTransport<E> {
- // Private result object
- private E mResult;
-
- public synchronized void setResult(E result) {
- mResult = result;
- }
-
- public synchronized E getResult() {
- return mResult;
- }
- }
-
- /**
- * Construct a new CallbackProxy.
- */
- public CallbackProxy(Context context, WebView w) {
- // Used to start a default activity.
- mContext = context;
- mWebView = w;
- mBackForwardList = new WebBackForwardList();
- }
-
- /**
- * Set the WebViewClient.
- * @param client An implementation of WebViewClient.
- */
- public void setWebViewClient(WebViewClient client) {
- mWebViewClient = client;
- }
-
- /**
- * Set the WebChromeClient.
- * @param client An implementation of WebChromeClient.
- */
- public void setWebChromeClient(WebChromeClient client) {
- mWebChromeClient = client;
- }
-
- /**
- * Set the client DownloadListener.
- * @param client An implementation of DownloadListener.
- */
- public void setDownloadListener(DownloadListener client) {
- mDownloadListener = client;
- }
-
- /**
- * Get the Back/Forward list to return to the user or to update the cached
- * history list.
- */
- public WebBackForwardList getBackForwardList() {
- return mBackForwardList;
- }
-
- /**
- * Called by the UI side. Calling overrideUrlLoading from the WebCore
- * side will post a message to call this method.
- */
- public boolean uiOverrideUrlLoading(String overrideUrl) {
- if (overrideUrl == null || overrideUrl.length() == 0) {
- return false;
- }
- boolean override = false;
- if (mWebViewClient != null) {
- override = mWebViewClient.shouldOverrideUrlLoading(mWebView,
- overrideUrl);
- } else {
- Intent intent = new Intent(Intent.ACTION_VIEW,
- Uri.parse(overrideUrl));
- intent.addCategory(Intent.CATEGORY_BROWSABLE);
- try {
- mContext.startActivity(intent);
- override = true;
- } catch (ActivityNotFoundException ex) {
- // If no application can handle the URL, assume that the
- // browser can handle it.
- }
- }
- return override;
- }
-
- /**
- * Called by UI side.
- */
- public boolean uiOverrideKeyEvent(KeyEvent event) {
- if (mWebViewClient != null) {
- return mWebViewClient.shouldOverrideKeyEvent(mWebView, event);
- }
- return false;
- }
-
- @Override
- public void handleMessage(Message msg) {
- // We don't have to do synchronization because this function operates
- // in the UI thread. The WebViewClient and WebChromeClient functions
- // that check for a non-null callback are ok because java ensures atomic
- // 32-bit reads and writes.
- switch (msg.what) {
- case PAGE_STARTED:
- if (mWebViewClient != null) {
- mWebViewClient.onPageStarted(mWebView,
- msg.getData().getString("url"),
- (Bitmap) msg.obj);
- }
- break;
-
- case PAGE_FINISHED:
- if (mWebViewClient != null) {
- mWebViewClient.onPageFinished(mWebView, (String) msg.obj);
- }
- break;
-
- case RECEIVED_ICON:
- if (mWebChromeClient != null) {
- mWebChromeClient.onReceivedIcon(mWebView, (Bitmap) msg.obj);
- }
- break;
-
- case RECEIVED_TITLE:
- if (mWebChromeClient != null) {
- mWebChromeClient.onReceivedTitle(mWebView,
- (String) msg.obj);
- }
- break;
-
- case TOO_MANY_REDIRECTS:
- Message cancelMsg =
- (Message) msg.getData().getParcelable("cancelMsg");
- Message continueMsg =
- (Message) msg.getData().getParcelable("continueMsg");
- if (mWebViewClient != null) {
- mWebViewClient.onTooManyRedirects(mWebView, cancelMsg,
- continueMsg);
- } else {
- cancelMsg.sendToTarget();
- }
- break;
-
- case REPORT_ERROR:
- if (mWebViewClient != null) {
- int reasonCode = msg.arg1;
- final String description = msg.getData().getString("description");
- final String failUrl = msg.getData().getString("failingUrl");
- mWebViewClient.onReceivedError(mWebView, reasonCode,
- description, failUrl);
- }
- break;
-
- case RESEND_POST_DATA:
- Message resend =
- (Message) msg.getData().getParcelable("resend");
- Message dontResend =
- (Message) msg.getData().getParcelable("dontResend");
- if (mWebViewClient != null) {
- mWebViewClient.onFormResubmission(mWebView, dontResend,
- resend);
- } else {
- dontResend.sendToTarget();
- }
- break;
-
- case OVERRIDE_URL:
- String overrideUrl = msg.getData().getString("url");
- boolean override = uiOverrideUrlLoading(overrideUrl);
- ResultTransport<Boolean> result =
- (ResultTransport<Boolean>) msg.obj;
- synchronized (this) {
- result.setResult(override);
- notify();
- }
- break;
-
- case AUTH_REQUEST:
- if (mWebViewClient != null) {
- HttpAuthHandler handler = (HttpAuthHandler) msg.obj;
- String host = msg.getData().getString("host");
- String realm = msg.getData().getString("realm");
- mWebViewClient.onReceivedHttpAuthRequest(mWebView, handler,
- host, realm);
- }
- break;
-
- case SSL_ERROR:
- if (mWebViewClient != null) {
- HashMap<String, Object> map =
- (HashMap<String, Object>) msg.obj;
- mWebViewClient.onReceivedSslError(mWebView,
- (SslErrorHandler) map.get("handler"),
- (SslError) map.get("error"));
- }
- break;
-
- case PROGRESS:
- // Synchronize to ensure mLatestProgress is not modified after
- // setProgress is called and before mProgressUpdatePending is
- // changed.
- synchronized (this) {
- if (mWebChromeClient != null) {
- mWebChromeClient.onProgressChanged(mWebView,
- mLatestProgress);
- }
- mProgressUpdatePending = false;
- }
- break;
-
- case UPDATE_VISITED:
- if (mWebViewClient != null) {
- mWebViewClient.doUpdateVisitedHistory(mWebView,
- (String) msg.obj, msg.arg1 != 0);
- }
- break;
-
- case LOAD_RESOURCE:
- if (mWebViewClient != null) {
- mWebViewClient.onLoadResource(mWebView, (String) msg.obj);
- }
- break;
-
- case DOWNLOAD_FILE:
- if (mDownloadListener != null) {
- String url = msg.getData().getString("url");
- String userAgent = msg.getData().getString("userAgent");
- String contentDisposition =
- msg.getData().getString("contentDisposition");
- String mimetype = msg.getData().getString("mimetype");
- Long contentLength = msg.getData().getLong("contentLength");
-
- mDownloadListener.onDownloadStart(url, userAgent,
- contentDisposition, mimetype, contentLength);
- }
- break;
-
- case CREATE_WINDOW:
- if (mWebChromeClient != null) {
- if (!mWebChromeClient.onCreateWindow(mWebView,
- msg.arg1 == 1, msg.arg2 == 1,
- (Message) msg.obj)) {
- synchronized (this) {
- notify();
- }
- }
- }
- break;
-
- case REQUEST_FOCUS:
- if (mWebChromeClient != null) {
- mWebChromeClient.onRequestFocus(mWebView);
- }
- break;
-
- case CLOSE_WINDOW:
- if (mWebChromeClient != null) {
- mWebChromeClient.onCloseWindow((WebView) msg.obj);
- }
- break;
-
- case SAVE_PASSWORD:
- Bundle bundle = msg.getData();
- String schemePlusHost = bundle.getString("host");
- String username = bundle.getString("username");
- String password = bundle.getString("password");
- // If the client returned false it means that the notify message
- // will not be sent and we should notify WebCore ourselves.
- if (!mWebView.onSavePassword(schemePlusHost, username, password,
- (Message) msg.obj)) {
- synchronized (this) {
- notify();
- }
- }
- break;
-
- case ASYNC_KEYEVENTS:
- if (mWebViewClient != null) {
- mWebViewClient.onUnhandledKeyEvent(mWebView,
- (KeyEvent) msg.obj);
- }
- break;
-
- case JS_ALERT:
- if (mWebChromeClient != null) {
- final JsResult res = (JsResult) msg.obj;
- String message = msg.getData().getString("message");
- String url = msg.getData().getString("url");
- if (!mWebChromeClient.onJsAlert(mWebView, url, message,
- res)) {
- new AlertDialog.Builder(mContext)
- .setTitle(getJsDialogTitle(url))
- .setMessage(message)
- .setPositiveButton(R.string.ok,
- new AlertDialog.OnClickListener() {
- public void onClick(
- DialogInterface dialog,
- int which) {
- res.confirm();
- }
- })
- .setCancelable(false)
- .show();
- }
- res.setReady();
- }
- break;
-
- case JS_CONFIRM:
- if (mWebChromeClient != null) {
- final JsResult res = (JsResult) msg.obj;
- String message = msg.getData().getString("message");
- String url = msg.getData().getString("url");
- if (!mWebChromeClient.onJsConfirm(mWebView, url, message,
- res)) {
- new AlertDialog.Builder(mContext)
- .setTitle(getJsDialogTitle(url))
- .setMessage(message)
- .setPositiveButton(R.string.ok,
- new DialogInterface.OnClickListener() {
- public void onClick(
- DialogInterface dialog,
- int which) {
- res.confirm();
- }})
- .setNegativeButton(R.string.cancel,
- new DialogInterface.OnClickListener() {
- public void onClick(
- DialogInterface dialog,
- int which) {
- res.cancel();
- }})
- .show();
- }
- // Tell the JsResult that it is ready for client
- // interaction.
- res.setReady();
- }
- break;
-
- case JS_PROMPT:
- if (mWebChromeClient != null) {
- final JsPromptResult res = (JsPromptResult) msg.obj;
- String message = msg.getData().getString("message");
- String defaultVal = msg.getData().getString("default");
- String url = msg.getData().getString("url");
- if (!mWebChromeClient.onJsPrompt(mWebView, url, message,
- defaultVal, res)) {
- final LayoutInflater factory = LayoutInflater
- .from(mContext);
- final View view = factory.inflate(R.layout.js_prompt,
- null);
- final EditText v = (EditText) view
- .findViewById(R.id.value);
- v.setText(defaultVal);
- ((TextView) view.findViewById(R.id.message))
- .setText(message);
- new AlertDialog.Builder(mContext)
- .setTitle(getJsDialogTitle(url))
- .setView(view)
- .setPositiveButton(R.string.ok,
- new DialogInterface.OnClickListener() {
- public void onClick(
- DialogInterface dialog,
- int whichButton) {
- res.confirm(v.getText()
- .toString());
- }
- })
- .setNegativeButton(R.string.cancel,
- new DialogInterface.OnClickListener() {
- public void onClick(
- DialogInterface dialog,
- int whichButton) {
- res.cancel();
- }
- })
- .setOnCancelListener(
- new DialogInterface.OnCancelListener() {
- public void onCancel(
- DialogInterface dialog) {
- res.cancel();
- }
- })
- .show();
- }
- // Tell the JsResult that it is ready for client
- // interaction.
- res.setReady();
- }
- break;
-
- case JS_UNLOAD:
- if (mWebChromeClient != null) {
- final JsResult res = (JsResult) msg.obj;
- String message = msg.getData().getString("message");
- String url = msg.getData().getString("url");
- if (!mWebChromeClient.onJsBeforeUnload(mWebView, url,
- message, res)) {
- final String m = mContext.getString(
- R.string.js_dialog_before_unload, message);
- new AlertDialog.Builder(mContext)
- .setMessage(m)
- .setPositiveButton(R.string.ok,
- new DialogInterface.OnClickListener() {
- public void onClick(
- DialogInterface dialog,
- int which) {
- res.confirm();
- }
- })
- .setNegativeButton(R.string.cancel,
- new DialogInterface.OnClickListener() {
- public void onClick(
- DialogInterface dialog,
- int which) {
- res.cancel();
- }
- })
- .show();
- }
- res.setReady();
- }
- break;
-
- case RECEIVED_CERTIFICATE:
- mWebView.setCertificate((SslCertificate) msg.obj);
- break;
-
- case NOTIFY:
- synchronized (this) {
- notify();
- }
- break;
-
- case SCALE_CHANGED:
- if (mWebViewClient != null) {
- mWebViewClient.onScaleChanged(mWebView, msg.getData()
- .getFloat("old"), msg.getData().getFloat("new"));
- }
- break;
-
- case SWITCH_OUT_HISTORY:
- mWebView.switchOutDrawHistory();
- break;
- }
- }
-
- /**
- * Return the latest progress.
- */
- public int getProgress() {
- return mLatestProgress;
- }
-
- /**
- * Called by WebCore side to switch out of history Picture drawing mode
- */
- void switchOutDrawHistory() {
- sendMessage(obtainMessage(SWITCH_OUT_HISTORY));
- }
-
- private String getJsDialogTitle(String url) {
- String title = url;
- if (URLUtil.isDataUrl(url)) {
- // For data: urls, we just display 'JavaScript' similar to Safari.
- title = mContext.getString(R.string.js_dialog_title_default);
- } else {
- try {
- URL aUrl = new URL(url);
- // For example: "The page at 'http://www.mit.edu' says:"
- title = mContext.getString(R.string.js_dialog_title,
- aUrl.getProtocol() + "://" + aUrl.getHost());
- } catch (MalformedURLException ex) {
- // do nothing. just use the url as the title
- }
- }
- return title;
- }
-
- //--------------------------------------------------------------------------
- // WebViewClient functions.
- // NOTE: shouldOverrideKeyEvent is never called from the WebCore thread so
- // it is not necessary to include it here.
- //--------------------------------------------------------------------------
-
- // Performance probe
- private long mWebCoreThreadTime;
-
- public void onPageStarted(String url, Bitmap favicon) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebViewClient == null) {
- return;
- }
- // Performance probe
- if (false) {
- mWebCoreThreadTime = SystemClock.currentThreadTimeMillis();
- Network.getInstance(mContext).startTiming();
- }
- Message msg = obtainMessage(PAGE_STARTED);
- msg.obj = favicon;
- msg.getData().putString("url", url);
- sendMessage(msg);
- }
-
- public void onPageFinished(String url) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebViewClient == null) {
- return;
- }
- // Performance probe
- if (false) {
- Log.d("WebCore", "WebCore thread used " +
- (SystemClock.currentThreadTimeMillis() - mWebCoreThreadTime)
- + " ms");
- Network.getInstance(mContext).stopTiming();
- }
- Message msg = obtainMessage(PAGE_FINISHED, url);
- sendMessage(msg);
- }
-
- public void onTooManyRedirects(Message cancelMsg, Message continueMsg) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebViewClient == null) {
- cancelMsg.sendToTarget();
- return;
- }
-
- Message msg = obtainMessage(TOO_MANY_REDIRECTS);
- Bundle bundle = msg.getData();
- bundle.putParcelable("cancelMsg", cancelMsg);
- bundle.putParcelable("continueMsg", continueMsg);
- sendMessage(msg);
- }
-
- public void onReceivedError(int errorCode, String description,
- String failingUrl) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebViewClient == null) {
- return;
- }
-
- Message msg = obtainMessage(REPORT_ERROR);
- msg.arg1 = errorCode;
- msg.getData().putString("description", description);
- msg.getData().putString("failingUrl", failingUrl);
- sendMessage(msg);
- }
-
- public void onFormResubmission(Message dontResend,
- Message resend) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebViewClient == null) {
- dontResend.sendToTarget();
- return;
- }
-
- Message msg = obtainMessage(RESEND_POST_DATA);
- Bundle bundle = msg.getData();
- bundle.putParcelable("resend", resend);
- bundle.putParcelable("dontResend", dontResend);
- sendMessage(msg);
- }
-
- /**
- * Called by the WebCore side
- */
- public boolean shouldOverrideUrlLoading(String url) {
- // We have a default behavior if no client exists so always send the
- // message.
- ResultTransport<Boolean> res = new ResultTransport<Boolean>();
- Message msg = obtainMessage(OVERRIDE_URL);
- msg.getData().putString("url", url);
- msg.obj = res;
- synchronized (this) {
- sendMessage(msg);
- try {
- wait();
- } catch (InterruptedException e) {
- Log.e(LOGTAG, "Caught exception while waiting for overrideUrl");
- Log.e(LOGTAG, Log.getStackTraceString(e));
- }
- }
- return res.getResult().booleanValue();
- }
-
- public void onReceivedHttpAuthRequest(HttpAuthHandler handler,
- String hostName, String realmName) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebViewClient == null) {
- handler.cancel();
- return;
- }
- Message msg = obtainMessage(AUTH_REQUEST, handler);
- msg.getData().putString("host", hostName);
- msg.getData().putString("realm", realmName);
- sendMessage(msg);
- }
- /**
- * @hide - hide this because it contains a parameter of type SslError.
- * SslError is located in a hidden package.
- */
- public void onReceivedSslError(SslErrorHandler handler, SslError error) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebViewClient == null) {
- handler.cancel();
- return;
- }
- Message msg = obtainMessage(SSL_ERROR);
- //, handler);
- HashMap<String, Object> map = new HashMap();
- map.put("handler", handler);
- map.put("error", error);
- msg.obj = map;
- sendMessage(msg);
- }
- /**
- * @hide - hide this because it contains a parameter of type SslCertificate,
- * which is located in a hidden package.
- */
-
- public void onReceivedCertificate(SslCertificate certificate) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebViewClient == null) {
- return;
- }
- // here, certificate can be null (if the site is not secure)
- sendMessage(obtainMessage(RECEIVED_CERTIFICATE, certificate));
- }
-
- public void doUpdateVisitedHistory(String url, boolean isReload) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebViewClient == null) {
- return;
- }
- sendMessage(obtainMessage(UPDATE_VISITED, isReload ? 1 : 0, 0, url));
- }
-
- public void onLoadResource(String url) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebViewClient == null) {
- return;
- }
- sendMessage(obtainMessage(LOAD_RESOURCE, url));
- }
-
- public void onUnhandledKeyEvent(KeyEvent event) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebViewClient == null) {
- return;
- }
- sendMessage(obtainMessage(ASYNC_KEYEVENTS, event));
- }
-
- public void onScaleChanged(float oldScale, float newScale) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebViewClient == null) {
- return;
- }
- Message msg = obtainMessage(SCALE_CHANGED);
- Bundle bundle = msg.getData();
- bundle.putFloat("old", oldScale);
- bundle.putFloat("new", newScale);
- sendMessage(msg);
- }
-
- //--------------------------------------------------------------------------
- // DownloadListener functions.
- //--------------------------------------------------------------------------
-
- /**
- * Starts a download if a download listener has been registered, otherwise
- * return false.
- */
- public boolean onDownloadStart(String url, String userAgent,
- String contentDisposition, String mimetype, long contentLength) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mDownloadListener == null) {
- // Cancel the download if there is no browser client.
- return false;
- }
-
- Message msg = obtainMessage(DOWNLOAD_FILE);
- Bundle bundle = msg.getData();
- bundle.putString("url", url);
- bundle.putString("userAgent", userAgent);
- bundle.putString("mimetype", mimetype);
- bundle.putLong("contentLength", contentLength);
- bundle.putString("contentDisposition", contentDisposition);
- sendMessage(msg);
- return true;
- }
-
-
- //--------------------------------------------------------------------------
- // WebView specific functions that do not interact with a client. These
- // functions just need to operate within the UI thread.
- //--------------------------------------------------------------------------
-
- public boolean onSavePassword(String schemePlusHost, String username,
- String password, Message resumeMsg) {
- // resumeMsg should be null at this point because we want to create it
- // within the CallbackProxy.
- if (Config.DEBUG) {
- junit.framework.Assert.assertNull(resumeMsg);
- }
- resumeMsg = obtainMessage(NOTIFY);
-
- Message msg = obtainMessage(SAVE_PASSWORD, resumeMsg);
- Bundle bundle = msg.getData();
- bundle.putString("host", schemePlusHost);
- bundle.putString("username", username);
- bundle.putString("password", password);
- synchronized (this) {
- sendMessage(msg);
- try {
- wait();
- } catch (InterruptedException e) {
- Log.e(LOGTAG,
- "Caught exception while waiting for onSavePassword");
- Log.e(LOGTAG, Log.getStackTraceString(e));
- }
- }
- // Doesn't matter here
- return false;
- }
-
- //--------------------------------------------------------------------------
- // WebChromeClient methods
- //--------------------------------------------------------------------------
-
- public void onProgressChanged(int newProgress) {
- // Synchronize so that mLatestProgress is up-to-date.
- synchronized (this) {
- mLatestProgress = newProgress;
- if (mWebChromeClient == null) {
- return;
- }
- if (!mProgressUpdatePending) {
- sendEmptyMessage(PROGRESS);
- mProgressUpdatePending = true;
- }
- }
- }
-
- public WebView createWindow(boolean dialog, boolean userGesture) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebChromeClient == null) {
- return null;
- }
-
- WebView.WebViewTransport transport = mWebView.new WebViewTransport();
- final Message msg = obtainMessage(NOTIFY);
- msg.obj = transport;
- synchronized (this) {
- sendMessage(obtainMessage(CREATE_WINDOW, dialog ? 1 : 0,
- userGesture ? 1 : 0, msg));
- try {
- wait();
- } catch (InterruptedException e) {
- Log.e(LOGTAG,
- "Caught exception while waiting for createWindow");
- Log.e(LOGTAG, Log.getStackTraceString(e));
- }
- }
-
- WebView w = transport.getWebView();
- if (w != null) {
- w.getWebViewCore().initializeSubwindow();
- }
- return w;
- }
-
- public void onRequestFocus() {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebChromeClient == null) {
- return;
- }
-
- sendEmptyMessage(REQUEST_FOCUS);
- }
-
- public void onCloseWindow(WebView window) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebChromeClient == null) {
- return;
- }
- sendMessage(obtainMessage(CLOSE_WINDOW, window));
- }
-
- public void onReceivedIcon(Bitmap icon) {
- if (Config.DEBUG && mBackForwardList.getCurrentItem() == null) {
- throw new AssertionError();
- }
- mBackForwardList.getCurrentItem().setFavicon(icon);
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebChromeClient == null) {
- return;
- }
- sendMessage(obtainMessage(RECEIVED_ICON, icon));
- }
-
- public void onReceivedTitle(String title) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebChromeClient == null) {
- return;
- }
- sendMessage(obtainMessage(RECEIVED_TITLE, title));
- }
-
- public void onJsAlert(String url, String message) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebChromeClient == null) {
- return;
- }
- JsResult result = new JsResult(this, false);
- Message alert = obtainMessage(JS_ALERT, result);
- alert.getData().putString("message", message);
- alert.getData().putString("url", url);
- synchronized (this) {
- sendMessage(alert);
- try {
- wait();
- } catch (InterruptedException e) {
- Log.e(LOGTAG, "Caught exception while waiting for jsAlert");
- Log.e(LOGTAG, Log.getStackTraceString(e));
- }
- }
- }
-
- public boolean onJsConfirm(String url, String message) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebChromeClient == null) {
- return false;
- }
- JsResult result = new JsResult(this, false);
- Message confirm = obtainMessage(JS_CONFIRM, result);
- confirm.getData().putString("message", message);
- confirm.getData().putString("url", url);
- synchronized (this) {
- sendMessage(confirm);
- try {
- wait();
- } catch (InterruptedException e) {
- Log.e(LOGTAG, "Caught exception while waiting for jsConfirm");
- Log.e(LOGTAG, Log.getStackTraceString(e));
- }
- }
- return result.getResult();
- }
-
- public String onJsPrompt(String url, String message, String defaultValue) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebChromeClient == null) {
- return null;
- }
- JsPromptResult result = new JsPromptResult(this);
- Message prompt = obtainMessage(JS_PROMPT, result);
- prompt.getData().putString("message", message);
- prompt.getData().putString("default", defaultValue);
- prompt.getData().putString("url", url);
- synchronized (this) {
- sendMessage(prompt);
- try {
- wait();
- } catch (InterruptedException e) {
- Log.e(LOGTAG, "Caught exception while waiting for jsPrompt");
- Log.e(LOGTAG, Log.getStackTraceString(e));
- }
- }
- return result.getStringResult();
- }
-
- public boolean onJsBeforeUnload(String url, String message) {
- // Do an unsynchronized quick check to avoid posting if no callback has
- // been set.
- if (mWebChromeClient == null) {
- return true;
- }
- JsResult result = new JsResult(this, true);
- Message confirm = obtainMessage(JS_UNLOAD, result);
- confirm.getData().putString("message", message);
- confirm.getData().putString("url", url);
- synchronized (this) {
- sendMessage(confirm);
- try {
- wait();
- } catch (InterruptedException e) {
- Log.e(LOGTAG, "Caught exception while waiting for jsUnload");
- Log.e(LOGTAG, Log.getStackTraceString(e));
- }
- }
- return result.getResult();
- }
-}
diff --git a/core/java/android/webkit/ContentLoader.java b/core/java/android/webkit/ContentLoader.java
deleted file mode 100644
index fb01c8c..0000000
--- a/core/java/android/webkit/ContentLoader.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.content.Context;
-import android.net.http.EventHandler;
-import android.net.http.Headers;
-import android.net.Uri;
-
-import java.io.File;
-import java.io.FileInputStream;
-
-/**
- * This class is a concrete implementation of StreamLoader that loads
- * "content:" URIs
- */
-class ContentLoader extends StreamLoader {
-
- private String mUrl;
- private Context mContext;
- private String mContentType;
-
- /**
- * Construct a ContentLoader with the specified content URI
- *
- * @param rawUrl "content:" url pointing to content to be loaded. This url
- * is the same url passed in to the WebView.
- * @param loadListener LoadListener to pass the content to
- * @param context Context to use to access the asset.
- */
- ContentLoader(String rawUrl, LoadListener loadListener, Context context) {
- super(loadListener);
- mContext = context;
-
- /* strip off mimetype */
- int mimeIndex = rawUrl.lastIndexOf('?');
- if (mimeIndex != -1) {
- mUrl = rawUrl.substring(0, mimeIndex);
- mContentType = rawUrl.substring(mimeIndex + 1);
- } else {
- mUrl = rawUrl;
- }
-
- }
-
- @Override
- protected boolean setupStreamAndSendStatus() {
- Uri uri = Uri.parse(mUrl);
- if (uri == null) {
- mHandler.error(
- EventHandler.FILE_NOT_FOUND_ERROR,
- mContext.getString(
- com.android.internal.R.string.httpErrorBadUrl) +
- " " + mUrl);
- return false;
- }
-
- try {
- mDataStream = mContext.getContentResolver().openInputStream(uri);
- mHandler.status(1, 1, 0, "OK");
- } catch (java.io.FileNotFoundException ex) {
- mHandler.error(
- EventHandler.FILE_NOT_FOUND_ERROR,
- mContext.getString(
- com.android.internal.R.string.httpErrorFileNotFound) +
- " " + ex.getMessage());
- return false;
-
- } catch (java.io.IOException ex) {
- mHandler.error(
- EventHandler.FILE_ERROR,
- mContext.getString(
- com.android.internal.R.string.httpErrorFileNotFound) +
- " " + ex.getMessage());
- return false;
- } catch (RuntimeException ex) {
- // readExceptionWithFileNotFoundExceptionFromParcel in DatabaseUtils
- // can throw a serial of RuntimeException. Catch them all here.
- mHandler.error(
- EventHandler.FILE_ERROR,
- mContext.getString(
- com.android.internal.R.string.httpErrorFileNotFound) +
- " " + ex.getMessage());
- return false;
- }
- return true;
- }
-
- @Override
- protected void buildHeaders(Headers headers) {
- if (mContentType != null) {
- headers.setContentType("text/html");
- }
- }
-
- /**
- * Construct a ContentLoader and instruct it to start loading.
- *
- * @param url "content:" url pointing to content to be loaded
- * @param loadListener LoadListener to pass the content to
- * @param context Context to use to access the asset.
- */
- public static void requestUrl(String url, LoadListener loadListener,
- Context context) {
- ContentLoader loader = new ContentLoader(url, loadListener, context);
- loader.load();
- }
-
-}
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
deleted file mode 100644
index 07c1a5d..0000000
--- a/core/java/android/webkit/CookieManager.java
+++ /dev/null
@@ -1,934 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.net.ParseException;
-import android.net.WebAddress;
-import android.util.Config;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/**
- * CookieManager manages cookies according to RFC2109 spec.
- */
-public final class CookieManager {
-
- private static CookieManager sRef;
-
- private static final String LOGTAG = "webkit";
-
- private static final String DOMAIN = "domain";
-
- private static final String PATH = "path";
-
- private static final String EXPIRES = "expires";
-
- private static final String SECURE = "secure";
-
- private static final String MAX_AGE = "max-age";
-
- private static final String HTTP_ONLY = "httponly";
-
- private static final String HTTPS = "https";
-
- private static final char PERIOD = '.';
-
- private static final char COMMA = ',';
-
- private static final char SEMICOLON = ';';
-
- private static final char EQUAL = '=';
-
- private static final char PATH_DELIM = '/';
-
- private static final char QUESTION_MARK = '?';
-
- private static final char WHITE_SPACE = ' ';
-
- private static final char QUOTATION = '\"';
-
- private static final int SECURE_LENGTH = SECURE.length();
-
- private static final int HTTP_ONLY_LENGTH = HTTP_ONLY.length();
-
- // RFC2109 defines 4k as maximum size of a cookie
- private static final int MAX_COOKIE_LENGTH = 4 * 1024;
-
- // RFC2109 defines 20 as max cookie count per domain. As we track with base
- // domain, we allow 50 per base domain
- private static final int MAX_COOKIE_COUNT_PER_BASE_DOMAIN = 50;
-
- // RFC2109 defines 300 as max count of domains. As we track with base
- // domain, we set 200 as max base domain count
- private static final int MAX_DOMAIN_COUNT = 200;
-
- // max cookie count to limit RAM cookie takes less than 100k, it is based on
- // average cookie entry size is less than 100 bytes
- private static final int MAX_RAM_COOKIES_COUNT = 1000;
-
- // max domain count to limit RAM cookie takes less than 100k,
- private static final int MAX_RAM_DOMAIN_COUNT = 15;
-
- private Map<String, ArrayList<Cookie>> mCookieMap = new LinkedHashMap
- <String, ArrayList<Cookie>>(MAX_DOMAIN_COUNT, 0.75f, true);
-
- private boolean mAcceptCookie = true;
-
- /**
- * This contains a list of 2nd-level domains that aren't allowed to have
- * wildcards when combined with country-codes. For example: [.co.uk].
- */
- private final static String[] BAD_COUNTRY_2LDS =
- { "ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info",
- "lg", "ne", "net", "or", "org" };
-
- static {
- Arrays.sort(BAD_COUNTRY_2LDS);
- }
-
- /**
- * Package level class to be accessed by cookie sync manager
- */
- static class Cookie {
- static final byte MODE_NEW = 0;
-
- static final byte MODE_NORMAL = 1;
-
- static final byte MODE_DELETED = 2;
-
- static final byte MODE_REPLACED = 3;
-
- String domain;
-
- String path;
-
- String name;
-
- String value;
-
- long expires;
-
- long lastAcessTime;
-
- long lastUpdateTime;
-
- boolean secure;
-
- byte mode;
-
- Cookie() {
- }
-
- Cookie(String defaultDomain, String defaultPath) {
- domain = defaultDomain;
- path = defaultPath;
- expires = -1;
- }
-
- boolean exactMatch(Cookie in) {
- return domain.equals(in.domain) && path.equals(in.path) &&
- name.equals(in.name);
- }
-
- boolean domainMatch(String urlHost) {
- if (domain.startsWith(".")) {
- if (urlHost.endsWith(domain.substring(1))) {
- int len = domain.length();
- int urlLen = urlHost.length();
- if (urlLen > len - 1) {
- // make sure bar.com doesn't match .ar.com
- return urlHost.charAt(urlLen - len) == PERIOD;
- }
- return true;
- }
- return false;
- } else {
- // exact match if domain is not leading w/ dot
- return urlHost.equals(domain);
- }
- }
-
- boolean pathMatch(String urlPath) {
- if (urlPath.startsWith(path)) {
- int len = path.length();
- if (len == 0) {
- Log.w(LOGTAG, "Empty cookie path");
- return false;
- }
- int urlLen = urlPath.length();
- if (path.charAt(len-1) != PATH_DELIM && urlLen > len) {
- // make sure /wee doesn't match /we
- return urlPath.charAt(len) == PATH_DELIM;
- }
- return true;
- }
- return false;
- }
-
- public String toString() {
- return "domain: " + domain + "; path: " + path + "; name: " + name
- + "; value: " + value;
- }
- }
-
- private CookieManager() {
- }
-
- protected Object clone() throws CloneNotSupportedException {
- throw new CloneNotSupportedException("doesn't implement Cloneable");
- }
-
- /**
- * Get a singleton CookieManager. If this is called before any
- * {@link WebView} is created or outside of {@link WebView} context, the
- * caller needs to call {@link CookieSyncManager#createInstance(Context)}
- * first.
- *
- * @return CookieManager
-= */
- public static synchronized CookieManager getInstance() {
- if (sRef == null) {
- sRef = new CookieManager();
- }
- return sRef;
- }
-
- /**
- * Control whether cookie is enabled or disabled
- * @param accept TRUE if accept cookie
- */
- public synchronized void setAcceptCookie(boolean accept) {
- mAcceptCookie = accept;
- }
-
- /**
- * Return whether cookie is enabled
- * @return TRUE if accept cookie
- */
- public synchronized boolean acceptCookie() {
- return mAcceptCookie;
- }
-
- /**
- * Set cookie for a given url. The old cookie with same host/path/name will
- * be removed. The new cookie will be added if it is not expired or it does
- * not have expiration which implies it is session cookie.
- * @param url The url which cookie is set for
- * @param value The value for set-cookie: in http response header
- */
- public void setCookie(String url, String value) {
- WebAddress uri;
- try {
- uri = new WebAddress(url);
- } catch (ParseException ex) {
- Log.e(LOGTAG, "Bad address: " + url);
- return;
- }
- setCookie(uri, value);
- }
-
- /**
- * Set cookie for a given uri. The old cookie with same host/path/name will
- * be removed. The new cookie will be added if it is not expired or it does
- * not have expiration which implies it is session cookie.
- * @param uri The uri which cookie is set for
- * @param value The value for set-cookie: in http response header
- * @hide - hide this because it takes in a parameter of type WebAddress,
- * a system private class.
- */
- public synchronized void setCookie(WebAddress uri, String value) {
- if (value != null && value.length() > MAX_COOKIE_LENGTH) {
- return;
- }
- if (!mAcceptCookie || uri == null) {
- return;
- }
- if (Config.LOGV) {
- Log.v(LOGTAG, "setCookie: uri: " + uri + " value: " + value);
- }
-
- String[] hostAndPath = getHostAndPath(uri);
- if (hostAndPath == null) {
- return;
- }
-
- // For default path, when setting a cookie, the spec says:
- //Path: Defaults to the path of the request URL that generated the
- // Set-Cookie response, up to, but not including, the
- // right-most /.
- if (hostAndPath[1].length() > 1) {
- int index = hostAndPath[1].lastIndexOf(PATH_DELIM);
- hostAndPath[1] = hostAndPath[1].substring(0,
- index > 0 ? index : index + 1);
- }
-
- ArrayList<Cookie> cookies = null;
- try {
- cookies = parseCookie(hostAndPath[0], hostAndPath[1], value);
- } catch (RuntimeException ex) {
- Log.e(LOGTAG, "parse cookie failed for: " + value);
- }
-
- if (cookies == null || cookies.size() == 0) {
- return;
- }
-
- String baseDomain = getBaseDomain(hostAndPath[0]);
- ArrayList<Cookie> cookieList = mCookieMap.get(baseDomain);
- if (cookieList == null) {
- cookieList = CookieSyncManager.getInstance()
- .getCookiesForDomain(baseDomain);
- mCookieMap.put(baseDomain, cookieList);
- }
-
- long now = System.currentTimeMillis();
- int size = cookies.size();
- for (int i = 0; i < size; i++) {
- Cookie cookie = cookies.get(i);
-
- boolean done = false;
- Iterator<Cookie> iter = cookieList.iterator();
- while (iter.hasNext()) {
- Cookie cookieEntry = iter.next();
- if (cookie.exactMatch(cookieEntry)) {
- // expires == -1 means no expires defined. Otherwise
- // negative means far future
- if (cookie.expires < 0 || cookie.expires > now) {
- // secure cookies can't be overwritten by non-HTTPS url
- if (!cookieEntry.secure || HTTPS.equals(uri.mScheme)) {
- cookieEntry.value = cookie.value;
- cookieEntry.expires = cookie.expires;
- cookieEntry.secure = cookie.secure;
- cookieEntry.lastAcessTime = now;
- cookieEntry.lastUpdateTime = now;
- cookieEntry.mode = Cookie.MODE_REPLACED;
- }
- } else {
- cookieEntry.lastUpdateTime = now;
- cookieEntry.mode = Cookie.MODE_DELETED;
- }
- done = true;
- break;
- }
- }
-
- // expires == -1 means no expires defined. Otherwise negative means
- // far future
- if (!done && (cookie.expires < 0 || cookie.expires > now)) {
- cookie.lastAcessTime = now;
- cookie.lastUpdateTime = now;
- cookie.mode = Cookie.MODE_NEW;
- if (cookieList.size() > MAX_COOKIE_COUNT_PER_BASE_DOMAIN) {
- Cookie toDelete = new Cookie();
- toDelete.lastAcessTime = now;
- Iterator<Cookie> iter2 = cookieList.iterator();
- while (iter2.hasNext()) {
- Cookie cookieEntry2 = iter2.next();
- if ((cookieEntry2.lastAcessTime < toDelete.lastAcessTime)
- && cookieEntry2.mode != Cookie.MODE_DELETED) {
- toDelete = cookieEntry2;
- }
- }
- toDelete.mode = Cookie.MODE_DELETED;
- }
- cookieList.add(cookie);
- }
- }
- }
-
- /**
- * Get cookie(s) for a given url so that it can be set to "cookie:" in http
- * request header.
- * @param url The url needs cookie
- * @return The cookies in the format of NAME=VALUE [; NAME=VALUE]
- */
- public String getCookie(String url) {
- WebAddress uri;
- try {
- uri = new WebAddress(url);
- } catch (ParseException ex) {
- Log.e(LOGTAG, "Bad address: " + url);
- return null;
- }
- return getCookie(uri);
- }
-
- /**
- * Get cookie(s) for a given uri so that it can be set to "cookie:" in http
- * request header.
- * @param uri The uri needs cookie
- * @return The cookies in the format of NAME=VALUE [; NAME=VALUE]
- * @hide - hide this because it has a parameter of type WebAddress, which
- * is a system private class.
- */
- public synchronized String getCookie(WebAddress uri) {
- if (!mAcceptCookie || uri == null) {
- return null;
- }
-
- String[] hostAndPath = getHostAndPath(uri);
- if (hostAndPath == null) {
- return null;
- }
-
- String baseDomain = getBaseDomain(hostAndPath[0]);
- ArrayList<Cookie> cookieList = mCookieMap.get(baseDomain);
- if (cookieList == null) {
- cookieList = CookieSyncManager.getInstance()
- .getCookiesForDomain(baseDomain);
- mCookieMap.put(baseDomain, cookieList);
- }
-
- long now = System.currentTimeMillis();
- boolean secure = HTTPS.equals(uri.mScheme);
- Iterator<Cookie> iter = cookieList.iterator();
- StringBuilder ret = new StringBuilder(256);
-
- while (iter.hasNext()) {
- Cookie cookie = iter.next();
- if (cookie.domainMatch(hostAndPath[0]) &&
- cookie.pathMatch(hostAndPath[1])
- // expires == -1 means no expires defined. Otherwise
- // negative means far future
- && (cookie.expires < 0 || cookie.expires > now)
- && (!cookie.secure || secure)
- && cookie.mode != Cookie.MODE_DELETED) {
- cookie.lastAcessTime = now;
-
- if (ret.length() > 0) {
- ret.append(SEMICOLON);
- // according to RC2109, SEMICOLON is office separator,
- // but when log in yahoo.com, it needs WHITE_SPACE too.
- ret.append(WHITE_SPACE);
- }
-
- ret.append(cookie.name);
- ret.append(EQUAL);
- ret.append(cookie.value);
- }
- }
- if (ret.length() > 0) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "getCookie: uri: " + uri + " value: " + ret);
- }
- return ret.toString();
- } else {
- if (Config.LOGV) {
- Log.v(LOGTAG, "getCookie: uri: " + uri
- + " But can't find cookie.");
- }
- return null;
- }
- }
-
- /**
- * Remove all session cookies, which are cookies without expiration date
- */
- public void removeSessionCookie() {
- final Runnable clearCache = new Runnable() {
- public void run() {
- synchronized(CookieManager.this) {
- Collection<ArrayList<Cookie>> cookieList = mCookieMap.values();
- Iterator<ArrayList<Cookie>> listIter = cookieList.iterator();
- while (listIter.hasNext()) {
- ArrayList<Cookie> list = listIter.next();
- Iterator<Cookie> iter = list.iterator();
- while (iter.hasNext()) {
- Cookie cookie = iter.next();
- if (cookie.expires == -1) {
- iter.remove();
- }
- }
- }
- CookieSyncManager.getInstance().clearSessionCookies();
- }
- }
- };
- new Thread(clearCache).start();
- }
-
- /**
- * Remove all cookies
- */
- public void removeAllCookie() {
- final Runnable clearCache = new Runnable() {
- public void run() {
- synchronized(CookieManager.this) {
- mCookieMap = new LinkedHashMap<String, ArrayList<Cookie>>(
- MAX_DOMAIN_COUNT, 0.75f, true);
- CookieSyncManager.getInstance().clearAllCookies();
- }
- }
- };
- new Thread(clearCache).start();
- }
-
- /**
- * Return true if there are stored cookies.
- */
- public synchronized boolean hasCookies() {
- return CookieSyncManager.getInstance().hasCookies();
- }
-
- /**
- * Remove all expired cookies
- */
- public void removeExpiredCookie() {
- final Runnable clearCache = new Runnable() {
- public void run() {
- synchronized(CookieManager.this) {
- long now = System.currentTimeMillis();
- Collection<ArrayList<Cookie>> cookieList = mCookieMap.values();
- Iterator<ArrayList<Cookie>> listIter = cookieList.iterator();
- while (listIter.hasNext()) {
- ArrayList<Cookie> list = listIter.next();
- Iterator<Cookie> iter = list.iterator();
- while (iter.hasNext()) {
- Cookie cookie = iter.next();
- // expires == -1 means no expires defined. Otherwise
- // negative means far future
- if (cookie.expires > 0 && cookie.expires < now) {
- iter.remove();
- }
- }
- }
- CookieSyncManager.getInstance().clearExpiredCookies(now);
- }
- }
- };
- new Thread(clearCache).start();
- }
-
- /**
- * Package level api, called from CookieSyncManager
- *
- * Get a list of cookies which are updated since a given time.
- * @param last The given time in millisec
- * @return A list of cookies
- */
- synchronized ArrayList<Cookie> getUpdatedCookiesSince(long last) {
- ArrayList<Cookie> cookies = new ArrayList<Cookie>();
- Collection<ArrayList<Cookie>> cookieList = mCookieMap.values();
- Iterator<ArrayList<Cookie>> listIter = cookieList.iterator();
- while (listIter.hasNext()) {
- ArrayList<Cookie> list = listIter.next();
- Iterator<Cookie> iter = list.iterator();
- while (iter.hasNext()) {
- Cookie cookie = iter.next();
- if (cookie.lastUpdateTime > last) {
- cookies.add(cookie);
- }
- }
- }
- return cookies;
- }
-
- /**
- * Package level api, called from CookieSyncManager
- *
- * Delete a Cookie in the RAM
- * @param cookie Cookie to be deleted
- */
- synchronized void deleteACookie(Cookie cookie) {
- if (cookie.mode == Cookie.MODE_DELETED) {
- String baseDomain = getBaseDomain(cookie.domain);
- ArrayList<Cookie> cookieList = mCookieMap.get(baseDomain);
- if (cookieList != null) {
- cookieList.remove(cookie);
- if (cookieList.isEmpty()) {
- mCookieMap.remove(baseDomain);
- }
- }
- }
- }
-
- /**
- * Package level api, called from CookieSyncManager
- *
- * Called after a cookie is synced to FLASH
- * @param cookie Cookie to be synced
- */
- synchronized void syncedACookie(Cookie cookie) {
- cookie.mode = Cookie.MODE_NORMAL;
- }
-
- /**
- * Package level api, called from CookieSyncManager
- *
- * Delete the least recent used domains if the total cookie count in RAM
- * exceeds the limit
- * @return A list of cookies which are removed from RAM
- */
- synchronized ArrayList<Cookie> deleteLRUDomain() {
- int count = 0;
- int byteCount = 0;
- int mapSize = mCookieMap.size();
-
- if (mapSize < MAX_RAM_DOMAIN_COUNT) {
- Collection<ArrayList<Cookie>> cookieLists = mCookieMap.values();
- Iterator<ArrayList<Cookie>> listIter = cookieLists.iterator();
- while (listIter.hasNext() && count < MAX_RAM_COOKIES_COUNT) {
- ArrayList<Cookie> list = listIter.next();
- if (Config.DEBUG) {
- Iterator<Cookie> iter = list.iterator();
- while (iter.hasNext() && count < MAX_RAM_COOKIES_COUNT) {
- Cookie cookie = iter.next();
- // 14 is 3 * sizeof(long) + sizeof(boolean)
- // + sizeof(byte)
- byteCount += cookie.domain.length()
- + cookie.path.length()
- + cookie.name.length()
- + cookie.value.length() + 14;
- count++;
- }
- } else {
- count += list.size();
- }
- }
- }
-
- ArrayList<Cookie> retlist = new ArrayList<Cookie>();
- if (mapSize >= MAX_RAM_DOMAIN_COUNT || count >= MAX_RAM_COOKIES_COUNT) {
- if (Config.DEBUG) {
- Log.v(LOGTAG, count + " cookies used " + byteCount
- + " bytes with " + mapSize + " domains");
- }
- Object[] domains = mCookieMap.keySet().toArray();
- int toGo = mapSize / 10 + 1;
- while (toGo-- > 0){
- String domain = domains[toGo].toString();
- if (Config.LOGV) {
- Log.v(LOGTAG, "delete domain: " + domain
- + " from RAM cache");
- }
- retlist.addAll(mCookieMap.get(domain));
- mCookieMap.remove(domain);
- }
- }
- return retlist;
- }
-
- /**
- * Extract the host and path out of a uri
- * @param uri The given WebAddress
- * @return The host and path in the format of String[], String[0] is host
- * which has at least two periods, String[1] is path which always
- * ended with "/"
- */
- private String[] getHostAndPath(WebAddress uri) {
- if (uri.mHost != null && uri.mPath != null) {
- String[] ret = new String[2];
- ret[0] = uri.mHost;
- ret[1] = uri.mPath;
-
- int index = ret[0].indexOf(PERIOD);
- if (index == -1) {
- if (uri.mScheme.equalsIgnoreCase("file")) {
- // There is a potential bug where a local file path matches
- // another file in the local web server directory. Still
- // "localhost" is the best pseudo domain name.
- ret[0] = "localhost";
- } else if (!ret[0].equals("localhost")) {
- return null;
- }
- } else if (index == ret[0].lastIndexOf(PERIOD)) {
- // cookie host must have at least two periods
- ret[0] = PERIOD + ret[0];
- }
-
- if (ret[1].charAt(0) != PATH_DELIM) {
- return null;
- }
-
- /*
- * find cookie path, e.g. for http://www.google.com, the path is "/"
- * for http://www.google.com/lab/, the path is "/lab"
- * for http://www.google.com/lab/foo, the path is "/lab/foo"
- * for http://www.google.com/lab?hl=en, the path is "/lab"
- * for http://www.google.com/lab.asp?hl=en, the path is "/lab.asp"
- * Note: the path from URI has at least one "/"
- * See:
- * http://www.unix.com.ua/rfc/rfc2109.html
- */
- index = ret[1].indexOf(QUESTION_MARK);
- if (index != -1) {
- ret[1] = ret[1].substring(0, index);
- }
- return ret;
- } else
- return null;
- }
-
- /**
- * Get the base domain for a give host. E.g. mail.google.com will return
- * google.com
- * @param host The give host
- * @return the base domain
- */
- private String getBaseDomain(String host) {
- int startIndex = 0;
- int nextIndex = host.indexOf(PERIOD);
- int lastIndex = host.lastIndexOf(PERIOD);
- while (nextIndex < lastIndex) {
- startIndex = nextIndex + 1;
- nextIndex = host.indexOf(PERIOD, startIndex);
- }
- if (startIndex > 0) {
- return host.substring(startIndex);
- } else {
- return host;
- }
- }
-
- /**
- * parseCookie() parses the cookieString which is a comma-separated list of
- * one or more cookies in the format of "NAME=VALUE; expires=DATE;
- * path=PATH; domain=DOMAIN_NAME; secure httponly" to a list of Cookies.
- * Here is a sample: IGDND=1, IGPC=ET=UB8TSNwtDmQ:AF=0; expires=Sun,
- * 17-Jan-2038 19:14:07 GMT; path=/ig; domain=.google.com, =,
- * PREF=ID=408909b1b304593d:TM=1156459854:LM=1156459854:S=V-vCAU6Sh-gobCfO;
- * expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com which
- * contains 3 cookies IGDND, IGPC, PREF and an empty cookie
- * @param host The default host
- * @param path The default path
- * @param cookieString The string coming from "Set-Cookie:"
- * @return A list of Cookies
- */
- private ArrayList<Cookie> parseCookie(String host, String path,
- String cookieString) {
- ArrayList<Cookie> ret = new ArrayList<Cookie>();
-
- int index = 0;
- int length = cookieString.length();
- while (true) {
- Cookie cookie = null;
-
- // done
- if (index < 0 || index >= length) {
- break;
- }
-
- // skip white space
- if (cookieString.charAt(index) == WHITE_SPACE) {
- index++;
- continue;
- }
-
- /*
- * get NAME=VALUE; pair. detecting the end of a pair is tricky, it
- * can be the end of a string, like "foo=bluh", it can be semicolon
- * like "foo=bluh;path=/"; or it can be enclosed by \", like
- * "foo=\"bluh bluh\";path=/"
- *
- * Note: in the case of "foo=bluh, bar=bluh;path=/", we interpret
- * it as one cookie instead of two cookies.
- */
- int equalIndex = cookieString.indexOf(EQUAL, index);
- if (equalIndex == -1) {
- // bad format, force return
- break;
- }
- cookie = new Cookie(host, path);
- cookie.name = cookieString.substring(index, equalIndex);
- if (cookieString.charAt(equalIndex + 1) == QUOTATION) {
- index = cookieString.indexOf(QUOTATION, equalIndex + 2);
- if (index == -1) {
- // bad format, force return
- break;
- }
- }
- int semicolonIndex = cookieString.indexOf(SEMICOLON, index);
- if (semicolonIndex == -1) {
- semicolonIndex = length;
- }
- if (semicolonIndex - equalIndex > MAX_COOKIE_LENGTH) {
- // cookie is too big, trim it
- cookie.value = cookieString.substring(equalIndex + 1,
- equalIndex + MAX_COOKIE_LENGTH);
- } else if (equalIndex + 1 == semicolonIndex
- || semicolonIndex < equalIndex) {
- // these are unusual case like foo=; and foo; path=/
- cookie.value = "";
- } else {
- cookie.value = cookieString.substring(equalIndex + 1,
- semicolonIndex);
- }
- // get attributes
- index = semicolonIndex;
- while (true) {
- // done
- if (index < 0 || index >= length) {
- break;
- }
-
- // skip white space and semicolon
- if (cookieString.charAt(index) == WHITE_SPACE
- || cookieString.charAt(index) == SEMICOLON) {
- index++;
- continue;
- }
-
- // comma means next cookie
- if (cookieString.charAt(index) == COMMA) {
- index++;
- break;
- }
-
- // "secure" is a known attribute doesn't use "=";
- // while sites like live.com uses "secure="
- if (length - index > SECURE_LENGTH
- && cookieString.substring(index, index + SECURE_LENGTH).
- equalsIgnoreCase(SECURE)) {
- index += SECURE_LENGTH;
- cookie.secure = true;
- if (cookieString.charAt(index) == EQUAL) index++;
- continue;
- }
-
- // "httponly" is a known attribute doesn't use "=";
- // while sites like live.com uses "httponly="
- if (length - index > HTTP_ONLY_LENGTH
- && cookieString.substring(index,
- index + HTTP_ONLY_LENGTH).
- equalsIgnoreCase(HTTP_ONLY)) {
- index += HTTP_ONLY_LENGTH;
- if (cookieString.charAt(index) == EQUAL) index++;
- // FIXME: currently only parse the attribute
- continue;
- }
- equalIndex = cookieString.indexOf(EQUAL, index);
- if (equalIndex > 0) {
- String name = cookieString.substring(index, equalIndex)
- .toLowerCase();
- if (name.equals(EXPIRES)) {
- int comaIndex = cookieString.indexOf(COMMA, equalIndex);
-
- // skip ',' in (Wdy, DD-Mon-YYYY HH:MM:SS GMT) or
- // (Weekday, DD-Mon-YY HH:MM:SS GMT) if it applies.
- // "Wednesday" is the longest Weekday which has length 9
- if ((comaIndex != -1) &&
- (comaIndex - equalIndex <= 10)) {
- index = comaIndex + 1;
- }
- }
- semicolonIndex = cookieString.indexOf(SEMICOLON, index);
- int commaIndex = cookieString.indexOf(COMMA, index);
- if (semicolonIndex == -1 && commaIndex == -1) {
- index = length;
- } else if (semicolonIndex == -1) {
- index = commaIndex;
- } else if (commaIndex == -1) {
- index = semicolonIndex;
- } else {
- index = Math.min(semicolonIndex, commaIndex);
- }
- String value =
- cookieString.substring(equalIndex + 1, index);
-
- // Strip quotes if they exist
- if (value.length() > 2 && value.charAt(0) == QUOTATION) {
- int endQuote = value.indexOf(QUOTATION, 1);
- if (endQuote > 0) {
- value = value.substring(1, endQuote);
- }
- }
- if (name.equals(EXPIRES)) {
- try {
- cookie.expires = HttpDateTime.parse(value);
- } catch (IllegalArgumentException ex) {
- Log.e(LOGTAG,
- "illegal format for expires: " + value);
- }
- } else if (name.equals(MAX_AGE)) {
- try {
- cookie.expires = System.currentTimeMillis() + 1000
- * Long.parseLong(value);
- } catch (NumberFormatException ex) {
- Log.e(LOGTAG,
- "illegal format for max-age: " + value);
- }
- } else if (name.equals(PATH)) {
- // only allow non-empty path value
- if (value.length() > 0) {
- cookie.path = value;
- }
- } else if (name.equals(DOMAIN)) {
- int lastPeriod = value.lastIndexOf(PERIOD);
- if (lastPeriod == 0) {
- // disallow cookies set for TLDs like [.com]
- cookie.domain = null;
- continue;
- }
- try {
- Integer.parseInt(value.substring(lastPeriod + 1));
- // no wildcard for ip address match
- if (!value.equals(host)) {
- // no cross-site cookie
- cookie.domain = null;
- }
- continue;
- } catch (NumberFormatException ex) {
- // ignore the exception, value is a host name
- }
- value = value.toLowerCase();
- if (value.charAt(0) != PERIOD) {
- // pre-pended dot to make it as a domain cookie
- value = PERIOD + value;
- lastPeriod++;
- }
- if (host.endsWith(value.substring(1))) {
- int len = value.length();
- int hostLen = host.length();
- if (hostLen > (len - 1)
- && host.charAt(hostLen - len) != PERIOD) {
- // make sure the bar.com doesn't match .ar.com
- cookie.domain = null;
- continue;
- }
- // disallow cookies set on ccTLDs like [.co.uk]
- if ((len == lastPeriod + 3)
- && (len >= 6 && len <= 8)) {
- String s = value.substring(1, lastPeriod);
- if (Arrays.binarySearch(BAD_COUNTRY_2LDS, s) >= 0) {
- cookie.domain = null;
- continue;
- }
- }
- cookie.domain = value;
- } else {
- // no cross-site or more specific sub-domain cookie
- cookie.domain = null;
- }
- }
- } else {
- // bad format, force return
- index = length;
- }
- }
- if (cookie != null && cookie.domain != null) {
- ret.add(cookie);
- }
- }
- return ret;
- }
-}
diff --git a/core/java/android/webkit/CookieSyncManager.java b/core/java/android/webkit/CookieSyncManager.java
deleted file mode 100644
index f2511d8..0000000
--- a/core/java/android/webkit/CookieSyncManager.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.content.Context;
-import android.util.Config;
-import android.util.Log;
-import android.webkit.CookieManager.Cookie;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * The class CookieSyncManager is used to synchronize the browser cookies
- * between RAM and FLASH. To get the best performance, browser cookie is saved
- * in RAM. We use a separate thread to sync the cookies between RAM and FLASH on
- * a timer base.
- * <p>
- * To use the CookieSyncManager, the host application has to call the following
- * when the application starts.
- * <p>
- * CookieSyncManager.createInstance(context)
- * <p>
- * To set up for sync, the host application has to call
- * <p>
- * CookieSyncManager.getInstance().startSync()
- * <p>
- * in its Activity.onResume(), and call
- * <p>
- * CookieSyncManager.getInstance().stopSync()
- * <p>
- * in its Activity.onStop().
- * <p>
- * To get instant sync instead of waiting for the timer to trigger, the host can
- * call
- * <p>
- * CookieSyncManager.getInstance().sync()
- */
-public final class CookieSyncManager extends WebSyncManager {
-
- private static CookieSyncManager sRef;
-
- // time when last update happened
- private long mLastUpdate;
-
- private CookieSyncManager(Context context) {
- super(context, "CookieSyncManager");
- }
-
- /**
- * Singleton access to a {@link CookieSyncManager}. An
- * IllegalStateException will be thrown if
- * {@link CookieSyncManager#createInstance(Context)} is not called before.
- *
- * @return CookieSyncManager
- */
- public static synchronized CookieSyncManager getInstance() {
- if (sRef == null) {
- throw new IllegalStateException(
- "CookieSyncManager::createInstance() needs to be called "
- + "before CookieSyncManager::getInstance()");
- }
- return sRef;
- }
-
- /**
- * Create a singleton CookieSyncManager within a context
- * @param context
- * @return CookieSyncManager
- */
- public static synchronized CookieSyncManager createInstance(
- Context context) {
- if (sRef == null) {
- sRef = new CookieSyncManager(context);
- }
- return sRef;
- }
-
- /**
- * Package level api, called from CookieManager Get all the cookies which
- * matches a given base domain.
- * @param domain
- * @return A list of Cookie
- */
- ArrayList<Cookie> getCookiesForDomain(String domain) {
- // null mDataBase implies that the host application doesn't support
- // persistent cookie. No sync needed.
- if (mDataBase == null) {
- return new ArrayList<Cookie>();
- }
-
- return mDataBase.getCookiesForDomain(domain);
- }
-
- /**
- * Package level api, called from CookieManager Clear all cookies in the
- * database
- */
- void clearAllCookies() {
- // null mDataBase implies that the host application doesn't support
- // persistent cookie.
- if (mDataBase == null) {
- return;
- }
-
- mDataBase.clearCookies();
- }
-
- /**
- * Returns true if there are any saved cookies.
- */
- boolean hasCookies() {
- // null mDataBase implies that the host application doesn't support
- // persistent cookie.
- if (mDataBase == null) {
- return false;
- }
-
- return mDataBase.hasCookies();
- }
-
- /**
- * Package level api, called from CookieManager Clear all session cookies in
- * the database
- */
- void clearSessionCookies() {
- // null mDataBase implies that the host application doesn't support
- // persistent cookie.
- if (mDataBase == null) {
- return;
- }
-
- mDataBase.clearSessionCookies();
- }
-
- /**
- * Package level api, called from CookieManager Clear all expired cookies in
- * the database
- */
- void clearExpiredCookies(long now) {
- // null mDataBase implies that the host application doesn't support
- // persistent cookie.
- if (mDataBase == null) {
- return;
- }
-
- mDataBase.clearExpiredCookies(now);
- }
-
- protected void syncFromRamToFlash() {
- if (Config.LOGV) {
- Log.v(LOGTAG, "CookieSyncManager::syncFromRamToFlash STARTS");
- }
-
- if (!CookieManager.getInstance().acceptCookie()) {
- return;
- }
-
- ArrayList<Cookie> cookieList = CookieManager.getInstance()
- .getUpdatedCookiesSince(mLastUpdate);
- mLastUpdate = System.currentTimeMillis();
- syncFromRamToFlash(cookieList);
-
- ArrayList<Cookie> lruList =
- CookieManager.getInstance().deleteLRUDomain();
- syncFromRamToFlash(lruList);
-
- if (Config.LOGV) {
- Log.v(LOGTAG, "CookieSyncManager::syncFromRamToFlash DONE");
- }
- }
-
- private void syncFromRamToFlash(ArrayList<Cookie> list) {
- Iterator<Cookie> iter = list.iterator();
- while (iter.hasNext()) {
- Cookie cookie = iter.next();
- if (cookie.mode != Cookie.MODE_NORMAL) {
- if (cookie.mode != Cookie.MODE_NEW) {
- mDataBase.deleteCookies(cookie.domain, cookie.path,
- cookie.name);
- }
- if (cookie.mode != Cookie.MODE_DELETED) {
- mDataBase.addCookie(cookie);
- CookieManager.getInstance().syncedACookie(cookie);
- } else {
- CookieManager.getInstance().deleteACookie(cookie);
- }
- }
- }
- }
-}
diff --git a/core/java/android/webkit/DataLoader.java b/core/java/android/webkit/DataLoader.java
deleted file mode 100644
index dcdc949..0000000
--- a/core/java/android/webkit/DataLoader.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import org.apache.http.protocol.HTTP;
-
-import android.net.http.Headers;
-
-import java.io.ByteArrayInputStream;
-
-/**
- * This class is a concrete implementation of StreamLoader that uses the
- * content supplied as a URL as the source for the stream. The mimetype
- * optionally provided in the URL is extracted and inserted into the HTTP
- * response headers.
- */
-class DataLoader extends StreamLoader {
-
- private String mContentType; // Content mimetype, if supplied in URL
-
- /**
- * Constructor uses the dataURL as the source for an InputStream
- * @param dataUrl data: URL string optionally containing a mimetype
- * @param loadListener LoadListener to pass the content to
- */
- DataLoader(String dataUrl, LoadListener loadListener) {
- super(loadListener);
-
- String url = dataUrl.substring("data:".length());
- String content;
- int commaIndex = url.indexOf(',');
- if (commaIndex != -1) {
- mContentType = url.substring(0, commaIndex);
- content = url.substring(commaIndex + 1);
- } else {
- content = url;
- }
- mDataStream = new ByteArrayInputStream(content.getBytes());
- mContentLength = content.length();
- }
-
- @Override
- protected boolean setupStreamAndSendStatus() {
- mHandler.status(1, 1, 0, "OK");
- return true;
- }
-
- @Override
- protected void buildHeaders(Headers headers) {
- if (mContentType != null) {
- headers.setContentType(mContentType);
- }
- }
-
- /**
- * Construct a DataLoader and instruct it to start loading.
- *
- * @param url data: URL string optionally containing a mimetype
- * @param loadListener LoadListener to pass the content to
- */
- public static void requestUrl(String url, LoadListener loadListener) {
- DataLoader loader = new DataLoader(url, loadListener);
- loader.load();
- }
-
-}
diff --git a/core/java/android/webkit/DateSorter.java b/core/java/android/webkit/DateSorter.java
deleted file mode 100644
index 750403b..0000000
--- a/core/java/android/webkit/DateSorter.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.content.Context;
-import android.content.res.Resources;
-
-import java.util.Calendar;
-import java.util.Date;
-
-/**
- * Sorts dates into the following groups:
- * Today
- * Yesterday
- * five days ago
- * one month ago
- * older than a month ago
- */
-
-public class DateSorter {
-
- private static final String LOGTAG = "webkit";
-
- /** must be >= 3 */
- public static final int DAY_COUNT = 5;
-
- private long [] mBins = new long[DAY_COUNT];
- private String [] mLabels = new String[DAY_COUNT];
-
- private static final int NUM_DAYS_AGO = 5;
-
- Date mDate = new Date();
- Calendar mCal = Calendar.getInstance();
-
- /**
- * @param context Application context
- */
- public DateSorter(Context context) {
- Resources resources = context.getResources();
-
- Calendar c = Calendar.getInstance();
- beginningOfDay(c);
-
- // Create the bins
- mBins[0] = c.getTimeInMillis(); // Today
- c.roll(Calendar.DAY_OF_YEAR, -1);
- mBins[1] = c.getTimeInMillis(); // Yesterday
- c.roll(Calendar.DAY_OF_YEAR, -(NUM_DAYS_AGO - 1));
- mBins[2] = c.getTimeInMillis(); // Five days ago
- c.roll(Calendar.DAY_OF_YEAR, NUM_DAYS_AGO); // move back to today
- c.roll(Calendar.MONTH, -1);
- mBins[3] = c.getTimeInMillis(); // One month ago
- c.roll(Calendar.MONTH, -1);
- mBins[4] = c.getTimeInMillis(); // Over one month ago
-
- // build labels
- mLabels[0] = context.getText(com.android.internal.R.string.today).toString();
- mLabels[1] = context.getText(com.android.internal.R.string.yesterday).toString();
-
- int resId = com.android.internal.R.plurals.num_days_ago;
- String format = resources.getQuantityString(resId, NUM_DAYS_AGO);
- mLabels[2] = String.format(format, NUM_DAYS_AGO);
-
- mLabels[3] = context.getText(com.android.internal.R.string.oneMonthDurationPast).toString();
- mLabels[4] = context.getText(com.android.internal.R.string.beforeOneMonthDurationPast)
- .toString();
- }
-
- /**
- * @param time time since the Epoch in milliseconds, such as that
- * returned by Calendar.getTimeInMillis()
- * @return an index from 0 to (DAY_COUNT - 1) that identifies which
- * date bin this date belongs to
- */
- public int getIndex(long time) {
- // Lame linear search
- for (int i = 0; i < DAY_COUNT; i++) {
- if (time > mBins[i]) return i;
- }
- return DAY_COUNT - 1;
- }
-
- /**
- * @param index date bin index as returned by getIndex()
- * @return string label suitable for display to user
- */
- public String getLabel(int index) {
- return mLabels[index];
- }
-
-
- /**
- * @param index date bin index as returned by getIndex()
- * @return date boundary at given index
- */
- public long getBoundary(int index) {
- return mBins[index];
- }
-
- /**
- * Calcuate 12:00am by zeroing out hour, minute, second, millisecond
- */
- private Calendar beginningOfDay(Calendar c) {
- c.set(Calendar.HOUR_OF_DAY, 0);
- c.set(Calendar.MINUTE, 0);
- c.set(Calendar.SECOND, 0);
- c.set(Calendar.MILLISECOND, 0);
- return c;
- }
-}
diff --git a/core/java/android/webkit/DownloadListener.java b/core/java/android/webkit/DownloadListener.java
deleted file mode 100644
index dfaa1b9..0000000
--- a/core/java/android/webkit/DownloadListener.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-public interface DownloadListener {
-
- /**
- * Notify the host application that a file should be downloaded
- * @param url The full url to the content that should be downloaded
- * @param userAgent the user agent to be used for the download.
- * @param contentDisposition Content-disposition http header, if
- * present.
- * @param mimetype The mimetype of the content reported by the server
- * @param contentLength The file size reported by the server
- */
- public void onDownloadStart(String url, String userAgent,
- String contentDisposition, String mimetype, long contentLength);
-
-}
diff --git a/core/java/android/webkit/FileLoader.java b/core/java/android/webkit/FileLoader.java
deleted file mode 100644
index 54a4c1d..0000000
--- a/core/java/android/webkit/FileLoader.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import com.android.internal.R;
-
-import android.content.Context;
-import android.content.res.AssetManager;
-import android.net.http.EventHandler;
-import android.net.http.Headers;
-import android.os.Environment;
-
-import java.io.File;
-import java.io.FileInputStream;
-
-/**
- * This class is a concrete implementation of StreamLoader that uses a
- * file or asset as the source for the stream.
- *
- */
-class FileLoader extends StreamLoader {
-
- private String mPath; // Full path to the file to load
- private Context mContext; // Application context, used for asset loads
- private boolean mIsAsset; // Indicates if the load is an asset or not
- private boolean mAllowFileAccess; // Allow/block file system access
-
- /**
- * Construct a FileLoader with the file URL specified as the content
- * source.
- *
- * @param url Full file url pointing to content to be loaded
- * @param loadListener LoadListener to pass the content to
- * @param context Context to use to access the asset.
- * @param asset true if url points to an asset.
- * @param allowFileAccess true if this WebView is allowed to access files
- * on the file system.
- */
- FileLoader(String url, LoadListener loadListener, Context context,
- boolean asset, boolean allowFileAccess) {
- super(loadListener);
- mIsAsset = asset;
- mContext = context;
- mAllowFileAccess = allowFileAccess;
-
- // clean the Url
- int index = url.indexOf('?');
- if (mIsAsset) {
- mPath = index > 0 ? URLUtil.stripAnchor(
- url.substring(URLUtil.ASSET_BASE.length(), index)) :
- URLUtil.stripAnchor(url.substring(
- URLUtil.ASSET_BASE.length()));
- } else {
- mPath = index > 0 ? URLUtil.stripAnchor(
- url.substring(URLUtil.FILE_BASE.length(), index)) :
- URLUtil.stripAnchor(url.substring(
- URLUtil.FILE_BASE.length()));
- }
- }
-
- @Override
- protected boolean setupStreamAndSendStatus() {
- try {
- if (mIsAsset) {
- try {
- mDataStream = mContext.getAssets().open(mPath);
- } catch (java.io.FileNotFoundException ex) {
- // try the rest files included in the package
- mDataStream = mContext.getAssets().openNonAsset(mPath);
- }
- } else {
- if (!mAllowFileAccess) {
- mHandler.error(EventHandler.FILE_ERROR,
- mContext.getString(R.string.httpErrorFileNotFound));
- return false;
- }
-
- mDataStream = new FileInputStream(mPath);
- mContentLength = (new File(mPath)).length();
- }
- mHandler.status(1, 1, 0, "OK");
-
- } catch (java.io.FileNotFoundException ex) {
- mHandler.error(
- EventHandler.FILE_NOT_FOUND_ERROR,
- mContext.getString(R.string.httpErrorFileNotFound) +
- " " + ex.getMessage());
- return false;
-
- } catch (java.io.IOException ex) {
- mHandler.error(EventHandler.FILE_ERROR,
- mContext.getString(R.string.httpErrorFileNotFound) +
- " " + ex.getMessage());
- return false;
- }
- return true;
- }
-
- @Override
- protected void buildHeaders(Headers headers) {
- // do nothing.
- }
-
-
- /**
- * Construct a FileLoader and instruct it to start loading.
- *
- * @param url Full file url pointing to content to be loaded
- * @param loadListener LoadListener to pass the content to
- * @param context Context to use to access the asset.
- * @param asset true if url points to an asset.
- * @param allowFileAccess true if this FileLoader can load files from the
- * file system.
- */
- public static void requestUrl(String url, LoadListener loadListener,
- Context context, boolean asset, boolean allowFileAccess) {
- FileLoader loader = new FileLoader(url, loadListener, context, asset,
- allowFileAccess);
- loader.load();
- }
-
-}
diff --git a/core/java/android/webkit/FrameLoader.java b/core/java/android/webkit/FrameLoader.java
deleted file mode 100644
index 5e323eb..0000000
--- a/core/java/android/webkit/FrameLoader.java
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.net.http.EventHandler;
-import android.net.http.RequestHandle;
-import android.util.Config;
-import android.util.Log;
-import android.webkit.CacheManager.CacheResult;
-import android.webkit.UrlInterceptRegistry;
-
-import java.util.HashMap;
-import java.util.Map;
-
-class FrameLoader {
-
- private final LoadListener mListener;
- private final String mMethod;
- private final boolean mIsHighPriority;
- private final WebSettings mSettings;
- private Map<String, String> mHeaders;
- private byte[] mPostData;
- private Network mNetwork;
- private int mCacheMode;
- private String mReferrer;
- private String mContentType;
-
- private static final int URI_PROTOCOL = 0x100;
-
- private static final String CONTENT_TYPE = "content-type";
-
- // Contents of an about:blank page
- private static final String mAboutBlank =
- "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EB\">" +
- "<html><head><title>about:blank</title></head><body></body></html>";
-
- static final String HEADER_STR = "text/xml, text/html, " +
- "application/xhtml+xml, image/png, text/plain, */*;q=0.8";
-
- private static final String LOGTAG = "webkit";
-
- FrameLoader(LoadListener listener, WebSettings settings,
- String method, boolean highPriority) {
- mListener = listener;
- mHeaders = null;
- mMethod = method;
- mIsHighPriority = highPriority;
- mCacheMode = WebSettings.LOAD_NORMAL;
- mSettings = settings;
- }
-
- public void setReferrer(String ref) {
- // only set referrer for http or https
- if (URLUtil.isNetworkUrl(ref)) mReferrer = ref;
- }
-
- public void setPostData(byte[] postData) {
- mPostData = postData;
- }
-
- public void setContentTypeForPost(String postContentType) {
- mContentType = postContentType;
- }
-
- public void setCacheMode(int cacheMode) {
- mCacheMode = cacheMode;
- }
-
- public void setHeaders(HashMap headers) {
- mHeaders = headers;
- }
-
- public LoadListener getLoadListener() {
- return mListener;
- }
-
- /**
- * Issues the load request.
- *
- * Return value does not indicate if the load was successful or not. It
- * simply indicates that the load request is reasonable.
- *
- * @return true if the load is reasonable.
- */
- public boolean executeLoad() {
- String url = mListener.url();
-
- // Attempt to decode the percent-encoded url.
- try {
- url = new String(URLUtil.decode(url.getBytes()));
- } catch (IllegalArgumentException e) {
- // Fail with a bad url error if the decode fails.
- mListener.error(EventHandler.ERROR_BAD_URL,
- mListener.getContext().getString(
- com.android.internal.R.string.httpErrorBadUrl));
- return false;
- }
-
- if (URLUtil.isNetworkUrl(url)){
- if (mSettings.getBlockNetworkLoads()) {
- mListener.error(EventHandler.ERROR_BAD_URL,
- mListener.getContext().getString(
- com.android.internal.R.string.httpErrorBadUrl));
- return false;
- }
- mNetwork = Network.getInstance(mListener.getContext());
- return handleHTTPLoad();
- } else if (handleLocalFile(url, mListener, mSettings)) {
- return true;
- }
- if (Config.LOGV) {
- Log.v(LOGTAG, "FrameLoader.executeLoad: url protocol not supported:"
- + mListener.url());
- }
- mListener.error(EventHandler.ERROR_UNSUPPORTED_SCHEME,
- mListener.getContext().getText(
- com.android.internal.R.string.httpErrorUnsupportedScheme).toString());
- return false;
-
- }
-
- /* package */
- static boolean handleLocalFile(String url, LoadListener loadListener,
- WebSettings settings) {
- if (URLUtil.isAssetUrl(url)) {
- FileLoader.requestUrl(url, loadListener, loadListener.getContext(),
- true, settings.getAllowFileAccess());
- return true;
- } else if (URLUtil.isFileUrl(url)) {
- FileLoader.requestUrl(url, loadListener, loadListener.getContext(),
- false, settings.getAllowFileAccess());
- return true;
- } else if (URLUtil.isContentUrl(url)) {
- // Send the raw url to the ContentLoader because it will do a
- // permission check and the url has to match..
- ContentLoader.requestUrl(loadListener.url(), loadListener,
- loadListener.getContext());
- return true;
- } else if (URLUtil.isDataUrl(url)) {
- DataLoader.requestUrl(url, loadListener);
- return true;
- } else if (URLUtil.isAboutUrl(url)) {
- loadListener.data(mAboutBlank.getBytes(), mAboutBlank.length());
- loadListener.endData();
- return true;
- }
- return false;
- }
-
- private boolean handleHTTPLoad() {
- if (mHeaders == null) {
- mHeaders = new HashMap<String, String>();
- }
- populateStaticHeaders();
- populateHeaders();
-
- // response was handled by UrlIntercept, don't issue HTTP request
- if (handleUrlIntercept()) return true;
-
- // response was handled by Cache, don't issue HTTP request
- if (handleCache()) {
- // push the request data down to the LoadListener
- // as response from the cache could be a redirect
- // and we may need to initiate a network request if the cache
- // can't satisfy redirect URL
- mListener.setRequestData(mMethod, mHeaders, mPostData,
- mIsHighPriority);
- return true;
- }
-
- if (Config.LOGV) {
- Log.v(LOGTAG, "FrameLoader: http " + mMethod + " load for: "
- + mListener.url());
- }
-
- boolean ret = false;
- int error = EventHandler.ERROR_UNSUPPORTED_SCHEME;
-
- try {
- ret = mNetwork.requestURL(mMethod, mHeaders,
- mPostData, mListener, mIsHighPriority);
- } catch (android.net.ParseException ex) {
- error = EventHandler.ERROR_BAD_URL;
- } catch (java.lang.RuntimeException ex) {
- /* probably an empty header set by javascript. We want
- the same result as bad URL */
- error = EventHandler.ERROR_BAD_URL;
- }
- if (!ret) {
- mListener.error(error, mListener.getContext().getText(
- EventHandler.errorStringResources[Math.abs(error)]).toString());
- return false;
- }
- return true;
- }
-
- /*
- * This function is used by handleUrlInterecpt and handleCache to
- * setup a load from the byte stream in a CacheResult.
- */
- private void startCacheLoad(CacheResult result) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "FrameLoader: loading from cache: "
- + mListener.url());
- }
- // Tell the Listener respond with the cache file
- CacheLoader cacheLoader =
- new CacheLoader(mListener, result);
- mListener.setCacheLoader(cacheLoader);
- cacheLoader.load();
- }
-
- /*
- * This function is used by handleHTTPLoad to allow URL
- * interception. This can be used to provide alternative load
- * methods such as locally stored versions or for debugging.
- *
- * Returns true if the response was handled by UrlIntercept.
- */
- private boolean handleUrlIntercept() {
- // Check if the URL can be served from UrlIntercept. If
- // successful, return the data just like a cache hit.
- CacheResult result = UrlInterceptRegistry.getSurrogate(
- mListener.url(), mHeaders);
- if(result != null) {
- // Intercepted. The data is stored in result.stream. Setup
- // a load from the CacheResult.
- startCacheLoad(result);
- return true;
- }
- // Not intercepted. Carry on as normal.
- return false;
- }
-
- /*
- * This function is used by the handleHTTPLoad to setup the cache headers
- * correctly.
- * Returns true if the response was handled from the cache
- */
- private boolean handleCache() {
- switch (mCacheMode) {
- // This mode is normally used for a reload, it instructs the http
- // loader to not use the cached content.
- case WebSettings.LOAD_NO_CACHE:
- break;
-
-
- // This mode is used when the content should only be loaded from
- // the cache. If it is not there, then fail the load. This is used
- // to load POST content in a history navigation.
- case WebSettings.LOAD_CACHE_ONLY: {
- CacheResult result = CacheManager.getCacheFile(mListener.url(),
- null);
- if (result != null) {
- startCacheLoad(result);
- } else {
- // This happens if WebCore was first told that the POST
- // response was in the cache, then when we try to use it
- // it has gone.
- // Generate a file not found error
- int err = EventHandler.FILE_NOT_FOUND_ERROR;
- mListener.error(err, mListener.getContext().getText(
- EventHandler.errorStringResources[Math.abs(err)])
- .toString());
- }
- return true;
- }
-
- // This mode is for when the user is doing a history navigation
- // in the browser and should returned cached content regardless
- // of it's state. If it is not in the cache, then go to the
- // network.
- case WebSettings.LOAD_CACHE_ELSE_NETWORK: {
- if (Config.LOGV) {
- Log.v(LOGTAG, "FrameLoader: checking cache: "
- + mListener.url());
- }
- // Get the cache file name for the current URL, passing null for
- // the validation headers causes no validation to occur
- CacheResult result = CacheManager.getCacheFile(mListener.url(),
- null);
- if (result != null) {
- startCacheLoad(result);
- return true;
- }
- break;
- }
-
- // This is the default case, which is to check to see if the
- // content in the cache can be used. If it can be used, then
- // use it. If it needs revalidation then the relevant headers
- // are added to the request.
- default:
- case WebSettings.LOAD_NORMAL:
- return mListener.checkCache(mHeaders);
- }// end of switch
-
- return false;
- }
-
- /**
- * Add the static headers that don't change with each request.
- */
- private void populateStaticHeaders() {
- // Accept header should already be there as they are built by WebCore,
- // but in the case they are missing, add some.
- String accept = mHeaders.get("Accept");
- if (accept == null || accept.length() == 0) {
- mHeaders.put("Accept", HEADER_STR);
- }
- mHeaders.put("Accept-Charset", "utf-8, iso-8859-1, utf-16, *;q=0.7");
-
- String acceptLanguage = mSettings.getAcceptLanguage();
- if (acceptLanguage.length() > 0) {
- mHeaders.put("Accept-Language", acceptLanguage);
- }
-
- mHeaders.put("User-Agent", mSettings.getUserAgentString());
- }
-
- /**
- * Add the content related headers. These headers contain user private data
- * and is not used when we are proxying an untrusted request.
- */
- private void populateHeaders() {
-
- if (mReferrer != null) mHeaders.put("Referer", mReferrer);
- if (mContentType != null) mHeaders.put(CONTENT_TYPE, mContentType);
-
- // if we have an active proxy and have proxy credentials, do pre-emptive
- // authentication to avoid an extra round-trip:
- if (mNetwork.isValidProxySet()) {
- String username;
- String password;
- /* The proxy credentials can be set in the Network thread */
- synchronized (mNetwork) {
- username = mNetwork.getProxyUsername();
- password = mNetwork.getProxyPassword();
- }
- if (username != null && password != null) {
- // we collect credentials ONLY if the proxy scheme is BASIC!!!
- String proxyHeader = RequestHandle.authorizationHeader(true);
- mHeaders.put(proxyHeader,
- "Basic " + RequestHandle.computeBasicAuthResponse(
- username, password));
- }
- }
-
- // Set cookie header
- String cookie = CookieManager.getInstance().getCookie(
- mListener.getWebAddress());
- if (cookie != null && cookie.length() > 0) {
- mHeaders.put("cookie", cookie);
- }
- }
-}
diff --git a/core/java/android/webkit/HttpAuthHandler.java b/core/java/android/webkit/HttpAuthHandler.java
deleted file mode 100644
index 48b9eec..0000000
--- a/core/java/android/webkit/HttpAuthHandler.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-
-import java.util.ListIterator;
-import java.util.LinkedList;
-
-/**
- * HTTP authentication handler: local handler that takes care
- * of HTTP authentication requests. This class is passed as a
- * parameter to BrowserCallback.displayHttpAuthDialog and is
- * meant to receive the user's response.
- */
-public class HttpAuthHandler extends Handler {
- /* It is important that the handler is in Network, because
- * we want to share it accross multiple loaders and windows
- * (like our subwindow and the main window).
- */
-
- private static final String LOGTAG = "network";
-
- /**
- * Network.
- */
- private Network mNetwork;
-
- /**
- * Loader queue.
- */
- private LinkedList<LoadListener> mLoaderQueue;
-
-
- // Message id for handling the user response
- private final int AUTH_PROCEED = 100;
- private final int AUTH_CANCEL = 200;
-
- /**
- * Creates a new HTTP authentication handler with an empty
- * loader queue
- *
- * @param network The parent network object
- */
- /* package */ HttpAuthHandler(Network network) {
- mNetwork = network;
- mLoaderQueue = new LinkedList<LoadListener>();
- }
-
-
- @Override
- public void handleMessage(Message msg) {
- LoadListener loader = null;
- synchronized (mLoaderQueue) {
- loader = mLoaderQueue.poll();
- }
-
- switch (msg.what) {
- case AUTH_PROCEED:
- String username = msg.getData().getString("username");
- String password = msg.getData().getString("password");
-
- loader.handleAuthResponse(username, password);
- break;
-
- case AUTH_CANCEL:
-
- mNetwork.resetHandlersAndStopLoading(loader.getFrame());
- break;
- }
-
- processNextLoader();
- }
-
-
- /**
- * Proceed with the authorization with the given credentials
- *
- * @param username The username to use for authentication
- * @param password The password to use for authentication
- */
- public void proceed(String username, String password) {
- Message msg = obtainMessage(AUTH_PROCEED);
- msg.getData().putString("username", username);
- msg.getData().putString("password", password);
- sendMessage(msg);
- }
-
- /**
- * Cancel the authorization request
- */
- public void cancel() {
- sendMessage(obtainMessage(AUTH_CANCEL));
- }
-
- /**
- * @return True if we can use user credentials on record
- * (ie, if we did not fail trying to use them last time)
- */
- public boolean useHttpAuthUsernamePassword() {
- LoadListener loader = null;
- synchronized (mLoaderQueue) {
- loader = mLoaderQueue.peek();
- }
- if (loader != null) {
- return !loader.authCredentialsInvalid();
- }
-
- return false;
- }
-
- /**
- * Resets the HTTP-authentication request handler, removes
- * all loaders that share the same BrowserFrame
- *
- * @param frame The browser frame
- */
- /* package */ void reset(BrowserFrame frame) {
- synchronized (mLoaderQueue) {
- ListIterator<LoadListener> i = mLoaderQueue.listIterator(0);
- while (i.hasNext()) {
- LoadListener loader = i.next();
- if (frame == loader.getFrame()) {
- i.remove();
- }
- }
- }
- }
-
- /**
- * Enqueues the loader, if the loader is the only element
- * in the queue, starts processing the loader
- *
- * @param loader The loader that resulted in this http
- * authentication request
- */
- /* package */ void handleAuthRequest(LoadListener loader) {
- boolean processNext = false;
-
- synchronized (mLoaderQueue) {
- mLoaderQueue.offer(loader);
- processNext =
- (mLoaderQueue.size() == 1);
- }
-
- if (processNext) {
- processNextLoader();
- }
- }
-
- /**
- * Process the next loader in the queue (helper method)
- */
- private void processNextLoader() {
- LoadListener loader = null;
- synchronized (mLoaderQueue) {
- loader = mLoaderQueue.peek();
- }
- if (loader != null) {
- CallbackProxy proxy = loader.getFrame().getCallbackProxy();
-
- String hostname = loader.proxyAuthenticate() ?
- mNetwork.getProxyHostname() : loader.host();
-
- String realm = loader.realm();
-
- proxy.onReceivedHttpAuthRequest(this, hostname, realm);
- }
- }
-}
diff --git a/core/java/android/webkit/HttpDateTime.java b/core/java/android/webkit/HttpDateTime.java
deleted file mode 100644
index c6ec2d2..0000000
--- a/core/java/android/webkit/HttpDateTime.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.text.format.Time;
-
-import java.util.Calendar;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-
-class HttpDateTime {
-
- /*
- * Regular expression for parsing HTTP-date.
- *
- * Wdy, DD Mon YYYY HH:MM:SS GMT
- * RFC 822, updated by RFC 1123
- *
- * Weekday, DD-Mon-YY HH:MM:SS GMT
- * RFC 850, obsoleted by RFC 1036
- *
- * Wdy Mon DD HH:MM:SS YYYY
- * ANSI C's asctime() format
- *
- * with following variations
- *
- * Wdy, DD-Mon-YYYY HH:MM:SS GMT
- * Wdy, (SP)D Mon YYYY HH:MM:SS GMT
- * Wdy,DD Mon YYYY HH:MM:SS GMT
- * Wdy, DD-Mon-YY HH:MM:SS GMT
- * Wdy, DD Mon YYYY HH:MM:SS -HHMM
- * Wdy, DD Mon YYYY HH:MM:SS
- * Wdy Mon (SP)D HH:MM:SS YYYY
- * Wdy Mon DD HH:MM:SS YYYY GMT
- */
- private static final String HTTP_DATE_RFC_REGEXP =
- "([0-9]{1,2})[- ]([A-Za-z]{3,3})[- ]([0-9]{2,4})[ ]"
- + "([0-9][0-9]:[0-9][0-9]:[0-9][0-9])";
-
- private static final String HTTP_DATE_ANSIC_REGEXP =
- "[ ]([A-Za-z]{3,3})[ ]+([0-9]{1,2})[ ]"
- + "([0-9][0-9]:[0-9][0-9]:[0-9][0-9])[ ]([0-9]{2,4})";
-
- /**
- * The compiled version of the HTTP-date regular expressions.
- */
- private static final Pattern HTTP_DATE_RFC_PATTERN =
- Pattern.compile(HTTP_DATE_RFC_REGEXP);
- private static final Pattern HTTP_DATE_ANSIC_PATTERN =
- Pattern.compile(HTTP_DATE_ANSIC_REGEXP);
-
- private static class TimeOfDay {
- int hour;
- int minute;
- int second;
- }
-
- public static Long parse(String timeString)
- throws IllegalArgumentException {
-
- int date = 1;
- int month = Calendar.JANUARY;
- int year = 1970;
- TimeOfDay timeOfDay = new TimeOfDay();
-
- Matcher rfcMatcher = HTTP_DATE_RFC_PATTERN.matcher(timeString);
- if (rfcMatcher.find()) {
- date = getDate(rfcMatcher.group(1));
- month = getMonth(rfcMatcher.group(2));
- year = getYear(rfcMatcher.group(3));
- timeOfDay = getTime(rfcMatcher.group(4));
- } else {
- Matcher ansicMatcher = HTTP_DATE_ANSIC_PATTERN.matcher(timeString);
- if (ansicMatcher.find()) {
- month = getMonth(ansicMatcher.group(1));
- date = getDate(ansicMatcher.group(2));
- timeOfDay = getTime(ansicMatcher.group(3));
- year = getYear(ansicMatcher.group(4));
- } else {
- throw new IllegalArgumentException();
- }
- }
-
- // FIXME: Y2038 BUG!
- if (year >= 2038) {
- year = 2038;
- month = Calendar.JANUARY;
- date = 1;
- }
-
- Time time = new Time(Time.TIMEZONE_UTC);
- time.set(timeOfDay.second, timeOfDay.minute, timeOfDay.hour, date,
- month, year);
- return time.toMillis(false /* use isDst */);
- }
-
- private static int getDate(String dateString) {
- if (dateString.length() == 2) {
- return (dateString.charAt(0) - '0') * 10
- + (dateString.charAt(1) - '0');
- } else {
- return (dateString.charAt(0) - '0');
- }
- }
-
- /*
- * jan = 9 + 0 + 13 = 22
- * feb = 5 + 4 + 1 = 10
- * mar = 12 + 0 + 17 = 29
- * apr = 0 + 15 + 17 = 32
- * may = 12 + 0 + 24 = 36
- * jun = 9 + 20 + 13 = 42
- * jul = 9 + 20 + 11 = 40
- * aug = 0 + 20 + 6 = 26
- * sep = 18 + 4 + 15 = 37
- * oct = 14 + 2 + 19 = 35
- * nov = 13 + 14 + 21 = 48
- * dec = 3 + 4 + 2 = 9
- */
- private static int getMonth(String monthString) {
- int hash = Character.toLowerCase(monthString.charAt(0)) +
- Character.toLowerCase(monthString.charAt(1)) +
- Character.toLowerCase(monthString.charAt(2)) - 3 * 'a';
- switch (hash) {
- case 22:
- return Calendar.JANUARY;
- case 10:
- return Calendar.FEBRUARY;
- case 29:
- return Calendar.MARCH;
- case 32:
- return Calendar.APRIL;
- case 36:
- return Calendar.MAY;
- case 42:
- return Calendar.JUNE;
- case 40:
- return Calendar.JULY;
- case 26:
- return Calendar.AUGUST;
- case 37:
- return Calendar.SEPTEMBER;
- case 35:
- return Calendar.OCTOBER;
- case 48:
- return Calendar.NOVEMBER;
- case 9:
- return Calendar.DECEMBER;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- private static int getYear(String yearString) {
- if (yearString.length() == 2) {
- int year = (yearString.charAt(0) - '0') * 10
- + (yearString.charAt(1) - '0');
- if (year >= 70) {
- return year + 1900;
- } else {
- return year + 2000;
- }
- } else
- return (yearString.charAt(0) - '0') * 1000
- + (yearString.charAt(1) - '0') * 100
- + (yearString.charAt(2) - '0') * 10
- + (yearString.charAt(3) - '0');
- }
-
- private static TimeOfDay getTime(String timeString) {
- TimeOfDay time = new TimeOfDay();
- time.hour = (timeString.charAt(0) - '0') * 10
- + (timeString.charAt(1) - '0');
- time.minute = (timeString.charAt(3) - '0') * 10
- + (timeString.charAt(4) - '0');
- time.second = (timeString.charAt(6) - '0') * 10
- + (timeString.charAt(7) - '0');
- return time;
- }
-}
diff --git a/core/java/android/webkit/JWebCoreJavaBridge.java b/core/java/android/webkit/JWebCoreJavaBridge.java
deleted file mode 100644
index a0049ac..0000000
--- a/core/java/android/webkit/JWebCoreJavaBridge.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.os.Handler;
-import android.os.Message;
-import android.util.Config;
-import android.util.Log;
-
-final class JWebCoreJavaBridge extends Handler {
- // Identifier for the timer message.
- private static final int TIMER_MESSAGE = 1;
- // ID for servicing functionptr queue
- private static final int FUNCPTR_MESSAGE = 2;
- // Log system identifier.
- private static final String LOGTAG = "webkit-timers";
-
- // Native object pointer for interacting in native code.
- private int mNativeBridge;
- // Instant timer is used to implement a timer that needs to fire almost
- // immediately.
- private boolean mHasInstantTimer;
- // Reference count the pause/resume of timers
- private int mPauseTimerRefCount;
-
- /**
- * Construct a new JWebCoreJavaBridge to interface with
- * WebCore timers and cookies.
- */
- public JWebCoreJavaBridge() {
- nativeConstructor();
- }
-
- @Override
- protected void finalize() {
- nativeFinalize();
- }
-
- /**
- * handleMessage
- * @param msg The dispatched message.
- *
- * The only accepted message currently is TIMER_MESSAGE
- */
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case TIMER_MESSAGE: {
- PerfChecker checker = new PerfChecker();
- // clear the flag so that sharedTimerFired() can set a new timer
- mHasInstantTimer = false;
- sharedTimerFired();
- checker.responseAlert("sharedTimer");
- break;
- }
- case FUNCPTR_MESSAGE:
- nativeServiceFuncPtrQueue();
- break;
- }
- }
-
- // called from JNI side
- private void signalServiceFuncPtrQueue() {
- Message msg = obtainMessage(FUNCPTR_MESSAGE);
- sendMessage(msg);
- }
-
- private native void nativeServiceFuncPtrQueue();
-
- /**
- * Pause all timers.
- */
- public void pause() {
- if (--mPauseTimerRefCount == 0) {
- setDeferringTimers(true);
- }
- }
-
- /**
- * Resume all timers.
- */
- public void resume() {
- if (++mPauseTimerRefCount == 1) {
- setDeferringTimers(false);
- }
- }
-
- /**
- * Set WebCore cache size.
- * @param bytes The cache size in bytes.
- */
- public native void setCacheSize(int bytes);
-
- /**
- * Store a cookie string associated with a url.
- * @param url The url to be used as a key for the cookie.
- * @param docUrl The policy base url used by WebCore.
- * @param value The cookie string to be stored.
- */
- private void setCookies(String url, String docUrl, String value) {
- if (value.contains("\r") || value.contains("\n")) {
- // for security reason, filter out '\r' and '\n' from the cookie
- int size = value.length();
- StringBuilder buffer = new StringBuilder(size);
- int i = 0;
- while (i != -1 && i < size) {
- int ir = value.indexOf('\r', i);
- int in = value.indexOf('\n', i);
- int newi = (ir == -1) ? in : (in == -1 ? ir : (ir < in ? ir
- : in));
- if (newi > i) {
- buffer.append(value.subSequence(i, newi));
- } else if (newi == -1) {
- buffer.append(value.subSequence(i, size));
- break;
- }
- i = newi + 1;
- }
- value = buffer.toString();
- }
- CookieManager.getInstance().setCookie(url, value);
- }
-
- /**
- * Retrieve the cookie string for the given url.
- * @param url The resource's url.
- * @return A String representing the cookies for the given resource url.
- */
- private String cookies(String url) {
- return CookieManager.getInstance().getCookie(url);
- }
-
- /**
- * Returns whether cookies are enabled or not.
- */
- private boolean cookiesEnabled() {
- return CookieManager.getInstance().acceptCookie();
- }
-
- /**
- * setSharedTimer
- * @param timemillis The relative time when the timer should fire
- */
- private void setSharedTimer(long timemillis) {
- if (Config.LOGV) Log.v(LOGTAG, "setSharedTimer " + timemillis);
-
- if (timemillis <= 0) {
- // we don't accumulate the sharedTimer unless it is a delayed
- // request. This way we won't flood the message queue with
- // WebKit messages. This should improve the browser's
- // responsiveness to key events.
- if (mHasInstantTimer) {
- return;
- } else {
- mHasInstantTimer = true;
- Message msg = obtainMessage(TIMER_MESSAGE);
- sendMessageDelayed(msg, timemillis);
- }
- } else {
- Message msg = obtainMessage(TIMER_MESSAGE);
- sendMessageDelayed(msg, timemillis);
- }
- }
-
- /**
- * Stop the shared timer.
- */
- private void stopSharedTimer() {
- if (Config.LOGV) {
- Log.v(LOGTAG, "stopSharedTimer removing all timers");
- }
- removeMessages(TIMER_MESSAGE);
- mHasInstantTimer = false;
- }
-
- private native void nativeConstructor();
- private native void nativeFinalize();
- private native void sharedTimerFired();
- private native void setDeferringTimers(boolean defer);
- public native void setNetworkOnLine(boolean online);
-}
diff --git a/core/java/android/webkit/JsPromptResult.java b/core/java/android/webkit/JsPromptResult.java
deleted file mode 100644
index 9fcd1bc..0000000
--- a/core/java/android/webkit/JsPromptResult.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-
-/**
- * Public class for handling javascript prompt requests. A
- * JsDialogHandlerInterface implentation will receive a jsPrompt call with a
- * JsPromptResult parameter. This parameter is used to return a result to
- * WebView. The client can call cancel() to cancel the dialog or confirm() with
- * the user's input to confirm the dialog.
- */
-public class JsPromptResult extends JsResult {
- // String result of the prompt
- private String mStringResult;
-
- /**
- * Handle a confirmation response from the user.
- */
- public void confirm(String result) {
- mStringResult = result;
- confirm();
- }
-
- /*package*/ JsPromptResult(CallbackProxy proxy) {
- super(proxy, /* unused */ false);
- }
-
- /*package*/ String getStringResult() {
- return mStringResult;
- }
-
- @Override
- /*package*/ void handleDefault() {
- mStringResult = null;
- super.handleDefault();
- }
-}
diff --git a/core/java/android/webkit/JsResult.java b/core/java/android/webkit/JsResult.java
deleted file mode 100644
index 0c86e0a..0000000
--- a/core/java/android/webkit/JsResult.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-
-public class JsResult {
- // This prevents a user from interacting with the result before WebCore is
- // ready to handle it.
- private boolean mReady;
- // Tells us if the user tried to confirm or cancel the result before WebCore
- // is ready.
- private boolean mTriedToNotifyBeforeReady;
- // This is a basic result of a confirm or prompt dialog.
- protected boolean mResult;
- // This is the caller of the prompt and is the object that is waiting.
- protected final CallbackProxy mProxy;
- // This is the default value of the result.
- private final boolean mDefaultValue;
-
- /**
- * Handle the result if the user cancelled the dialog.
- */
- public final void cancel() {
- mResult = false;
- wakeUp();
- }
-
- /**
- * Handle a confirmation response from the user.
- */
- public final void confirm() {
- mResult = true;
- wakeUp();
- }
-
- /*package*/ JsResult(CallbackProxy proxy, boolean defaultVal) {
- mProxy = proxy;
- mDefaultValue = defaultVal;
- }
-
- /*package*/ final boolean getResult() {
- return mResult;
- }
-
- /*package*/ final void setReady() {
- mReady = true;
- if (mTriedToNotifyBeforeReady) {
- wakeUp();
- }
- }
-
- /*package*/ void handleDefault() {
- setReady();
- mResult = mDefaultValue;
- wakeUp();
- }
-
- /* Wake up the WebCore thread. */
- protected final void wakeUp() {
- if (mReady) {
- synchronized (mProxy) {
- mProxy.notify();
- }
- } else {
- mTriedToNotifyBeforeReady = true;
- }
- }
-}
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
deleted file mode 100644
index dfae17d..0000000
--- a/core/java/android/webkit/LoadListener.java
+++ /dev/null
@@ -1,1499 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.content.Context;
-import android.net.WebAddress;
-import android.net.ParseException;
-import android.net.http.EventHandler;
-import android.net.http.Headers;
-import android.net.http.HttpAuthHeader;
-import android.net.http.RequestHandle;
-import android.net.http.SslCertificate;
-import android.net.http.SslError;
-import android.net.http.SslCertificate;
-
-import android.os.Handler;
-import android.os.Message;
-import android.util.Config;
-import android.util.Log;
-import android.webkit.CacheManager.CacheResult;
-
-import com.android.internal.R;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Vector;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
-
-import org.apache.commons.codec.binary.Base64;
-
-class LoadListener extends Handler implements EventHandler {
-
- private static final String LOGTAG = "webkit";
-
- // Messages used internally to communicate state between the
- // Network thread and the WebCore thread.
- private static final int MSG_CONTENT_HEADERS = 100;
- private static final int MSG_CONTENT_DATA = 110;
- private static final int MSG_CONTENT_FINISHED = 120;
- private static final int MSG_CONTENT_ERROR = 130;
- private static final int MSG_LOCATION_CHANGED = 140;
- private static final int MSG_LOCATION_CHANGED_REQUEST = 150;
- private static final int MSG_STATUS = 160;
- private static final int MSG_SSL_CERTIFICATE = 170;
- private static final int MSG_SSL_ERROR = 180;
-
- // Standard HTTP status codes in a more representative format
- private static final int HTTP_OK = 200;
- private static final int HTTP_MOVED_PERMANENTLY = 301;
- private static final int HTTP_FOUND = 302;
- private static final int HTTP_SEE_OTHER = 303;
- private static final int HTTP_NOT_MODIFIED = 304;
- private static final int HTTP_TEMPORARY_REDIRECT = 307;
- private static final int HTTP_AUTH = 401;
- private static final int HTTP_NOT_FOUND = 404;
- private static final int HTTP_PROXY_AUTH = 407;
-
- private static int sNativeLoaderCount;
-
- private final ByteArrayBuilder mDataBuilder = new ByteArrayBuilder(8192);
-
- private String mUrl;
- private WebAddress mUri;
- private boolean mPermanent;
- private String mOriginalUrl;
- private Context mContext;
- private BrowserFrame mBrowserFrame;
- private int mNativeLoader;
- private String mMimeType;
- private String mEncoding;
- private String mTransferEncoding;
- private int mStatusCode;
- private String mStatusText;
- public long mContentLength; // Content length of the incoming data
- private boolean mCancelled; // The request has been cancelled.
- private boolean mAuthFailed; // indicates that the prev. auth failed
- private CacheLoader mCacheLoader;
- private CacheManager.CacheResult mCacheResult;
- private HttpAuthHeader mAuthHeader;
- private int mErrorID = OK;
- private String mErrorDescription;
- private SslError mSslError;
- private RequestHandle mRequestHandle;
-
- // Request data. It is only valid when we are doing a load from the
- // cache. It is needed if the cache returns a redirect
- private String mMethod;
- private Map<String, String> mRequestHeaders;
- private byte[] mPostData;
- private boolean mIsHighPriority;
- // Flag to indicate that this load is synchronous.
- private boolean mSynchronous;
- private Vector<Message> mMessageQueue;
-
- // Does this loader correspond to the main-frame top-level page?
- private boolean mIsMainPageLoader;
-
- private Headers mHeaders;
-
- // =========================================================================
- // Public functions
- // =========================================================================
-
- public static LoadListener getLoadListener(
- Context context, BrowserFrame frame, String url,
- int nativeLoader, boolean synchronous, boolean isMainPageLoader) {
-
- sNativeLoaderCount += 1;
- return new LoadListener(
- context, frame, url, nativeLoader, synchronous, isMainPageLoader);
- }
-
- public static int getNativeLoaderCount() {
- return sNativeLoaderCount;
- }
-
- LoadListener(Context context, BrowserFrame frame, String url,
- int nativeLoader, boolean synchronous, boolean isMainPageLoader) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "LoadListener constructor url=" + url);
- }
- mContext = context;
- mBrowserFrame = frame;
- setUrl(url);
- mNativeLoader = nativeLoader;
- mMimeType = "";
- mEncoding = "";
- mSynchronous = synchronous;
- if (synchronous) {
- mMessageQueue = new Vector<Message>();
- }
- mIsMainPageLoader = isMainPageLoader;
- }
-
- /**
- * We keep a count of refs to the nativeLoader so we do not create
- * so many LoadListeners that the GREFs blow up
- */
- private void clearNativeLoader() {
- sNativeLoaderCount -= 1;
- mNativeLoader = 0;
- }
-
- /*
- * This message handler is to facilitate communication between the network
- * thread and the browser thread.
- */
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_CONTENT_HEADERS:
- /*
- * This message is sent when the LoadListener has headers
- * available. The headers are sent onto WebCore to see what we
- * should do with them.
- */
- handleHeaders((Headers) msg.obj);
- break;
-
- case MSG_CONTENT_DATA:
- /*
- * This message is sent when the LoadListener has data available
- * in it's data buffer. This data buffer could be filled from a
- * file (this thread) or from http (Network thread).
- */
- if (mNativeLoader != 0 && !ignoreCallbacks()) {
- commitLoad();
- }
- break;
-
- case MSG_CONTENT_FINISHED:
- /*
- * This message is sent when the LoadListener knows that the
- * load is finished. This message is not sent in the case of an
- * error.
- *
- */
- handleEndData();
- break;
-
- case MSG_CONTENT_ERROR:
- /*
- * This message is sent when a load error has occured. The
- * LoadListener will clean itself up.
- */
- handleError(msg.arg1, (String) msg.obj);
- break;
-
- case MSG_LOCATION_CHANGED:
- /*
- * This message is sent from LoadListener.endData to inform the
- * browser activity that the location of the top level page
- * changed.
- */
- doRedirect();
- break;
-
- case MSG_LOCATION_CHANGED_REQUEST:
- /*
- * This message is sent from endData on receipt of a 307
- * Temporary Redirect in response to a POST -- the user must
- * confirm whether to continue loading. If the user says Yes,
- * we simply call MSG_LOCATION_CHANGED. If the user says No,
- * we call MSG_CONTENT_FINISHED.
- */
- Message contMsg = obtainMessage(MSG_LOCATION_CHANGED);
- Message stopMsg = obtainMessage(MSG_CONTENT_FINISHED);
- mBrowserFrame.getCallbackProxy().onFormResubmission(
- stopMsg, contMsg);
- break;
-
- case MSG_STATUS:
- /*
- * This message is sent from the network thread when the http
- * stack has received the status response from the server.
- */
- HashMap status = (HashMap) msg.obj;
- handleStatus(((Integer) status.get("major")).intValue(),
- ((Integer) status.get("minor")).intValue(),
- ((Integer) status.get("code")).intValue(),
- (String) status.get("reason"));
- break;
-
- case MSG_SSL_CERTIFICATE:
- /*
- * This message is sent when the network thread receives a ssl
- * certificate.
- */
- handleCertificate((SslCertificate) msg.obj);
- break;
-
- case MSG_SSL_ERROR:
- /*
- * This message is sent when the network thread encounters a
- * ssl error.
- */
- handleSslError((SslError) msg.obj);
- break;
- }
- }
-
- /**
- * @return The loader's BrowserFrame.
- */
- BrowserFrame getFrame() {
- return mBrowserFrame;
- }
-
- Context getContext() {
- return mContext;
- }
-
- /* package */ boolean isSynchronous() {
- return mSynchronous;
- }
-
- /**
- * @return True iff the load has been cancelled
- */
- public boolean cancelled() {
- return mCancelled;
- }
-
- /**
- * Parse the headers sent from the server.
- * @param headers gives up the HeaderGroup
- * IMPORTANT: as this is called from network thread, can't call native
- * directly
- */
- public void headers(Headers headers) {
- if (Config.LOGV) Log.v(LOGTAG, "LoadListener.headers");
- sendMessageInternal(obtainMessage(MSG_CONTENT_HEADERS, headers));
- }
-
- // Does the header parsing work on the WebCore thread.
- private void handleHeaders(Headers headers) {
- if (mCancelled) return;
- mHeaders = headers;
- mMimeType = "";
- mEncoding = "";
-
- ArrayList<String> cookies = headers.getSetCookie();
- for (int i = 0; i < cookies.size(); ++i) {
- CookieManager.getInstance().setCookie(mUri, cookies.get(i));
- }
-
- long contentLength = headers.getContentLength();
- if (contentLength != Headers.NO_CONTENT_LENGTH) {
- mContentLength = contentLength;
- } else {
- mContentLength = 0;
- }
-
- String contentType = headers.getContentType();
- if (contentType != null) {
- parseContentTypeHeader(contentType);
-
- // If we have one of "generic" MIME types, try to deduce
- // the right MIME type from the file extension (if any):
- if (mMimeType.equalsIgnoreCase("text/plain") ||
- mMimeType.equalsIgnoreCase("application/octet-stream")) {
-
- String newMimeType = guessMimeTypeFromExtension();
- if (newMimeType != null) {
- mMimeType = newMimeType;
- }
- } else if (mMimeType.equalsIgnoreCase("text/vnd.wap.wml")) {
- // As we don't support wml, render it as plain text
- mMimeType = "text/plain";
- } else {
- // XXX: Until the servers send us either correct xhtml or
- // text/html, treat application/xhtml+xml as text/html.
- // It seems that xhtml+xml and vnd.wap.xhtml+xml mime
- // subtypes are used interchangeably. So treat them the same.
- if (mMimeType.equalsIgnoreCase("application/xhtml+xml") ||
- mMimeType.equals("application/vnd.wap.xhtml+xml")) {
- mMimeType = "text/html";
- }
- }
- } else {
- /* Often when servers respond with 304 Not Modified or a
- Redirect, then they don't specify a MIMEType. When this
- occurs, the function below is called. In the case of
- 304 Not Modified, the cached headers are used rather
- than the headers that are returned from the server. */
- guessMimeType();
- }
-
- // is it an authentication request?
- boolean mustAuthenticate = (mStatusCode == HTTP_AUTH ||
- mStatusCode == HTTP_PROXY_AUTH);
- // is it a proxy authentication request?
- boolean isProxyAuthRequest = (mStatusCode == HTTP_PROXY_AUTH);
- // is this authentication request due to a failed attempt to
- // authenticate ealier?
- mAuthFailed = false;
-
- // if we tried to authenticate ourselves last time
- if (mAuthHeader != null) {
- // we failed, if we must to authenticate again now and
- // we have a proxy-ness match
- mAuthFailed = (mustAuthenticate &&
- isProxyAuthRequest == mAuthHeader.isProxy());
-
- // if we did NOT fail and last authentication request was a
- // proxy-authentication request
- if (!mAuthFailed && mAuthHeader.isProxy()) {
- Network network = Network.getInstance(mContext);
- // if we have a valid proxy set
- if (network.isValidProxySet()) {
- /* The proxy credentials can be read in the WebCore thread
- */
- synchronized (network) {
- // save authentication credentials for pre-emptive proxy
- // authentication
- network.setProxyUsername(mAuthHeader.getUsername());
- network.setProxyPassword(mAuthHeader.getPassword());
- }
- }
- }
- }
- // it is only here that we can reset the last mAuthHeader object
- // (if existed) and start a new one!!!
- mAuthHeader = null;
- if (mustAuthenticate) {
- if (mStatusCode == HTTP_AUTH) {
- mAuthHeader = parseAuthHeader(
- headers.getWwwAuthenticate());
- } else {
- mAuthHeader = parseAuthHeader(
- headers.getProxyAuthenticate());
- // if successfully parsed the header
- if (mAuthHeader != null) {
- // mark the auth-header object as a proxy
- mAuthHeader.setProxy();
- }
- }
- }
-
- // Only create a cache file if the server has responded positively.
- if ((mStatusCode == HTTP_OK ||
- mStatusCode == HTTP_FOUND ||
- mStatusCode == HTTP_MOVED_PERMANENTLY ||
- mStatusCode == HTTP_TEMPORARY_REDIRECT) &&
- mNativeLoader != 0) {
- // Content arriving from a StreamLoader (eg File, Cache or Data)
- // will not be cached as they have the header:
- // cache-control: no-store
- mCacheResult = CacheManager.createCacheFile(mUrl, mStatusCode,
- headers, mMimeType, false);
- if (mCacheResult != null) {
- mCacheResult.encoding = mEncoding;
- }
- }
- commitHeadersCheckRedirect();
- }
-
- /**
- * @return True iff this loader is in the proxy-authenticate state.
- */
- boolean proxyAuthenticate() {
- if (mAuthHeader != null) {
- return mAuthHeader.isProxy();
- }
-
- return false;
- }
-
- /**
- * Report the status of the response.
- * TODO: Comments about each parameter.
- * IMPORTANT: as this is called from network thread, can't call native
- * directly
- */
- public void status(int majorVersion, int minorVersion,
- int code, /* Status-Code value */ String reasonPhrase) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "LoadListener: from: " + mUrl
- + " major: " + majorVersion
- + " minor: " + minorVersion
- + " code: " + code
- + " reason: " + reasonPhrase);
- }
- HashMap status = new HashMap();
- status.put("major", majorVersion);
- status.put("minor", minorVersion);
- status.put("code", code);
- status.put("reason", reasonPhrase);
- sendMessageInternal(obtainMessage(MSG_STATUS, status));
- }
-
- // Handle the status callback on the WebCore thread.
- private void handleStatus(int major, int minor, int code, String reason) {
- if (mCancelled) return;
-
- mStatusCode = code;
- mStatusText = reason;
- mPermanent = false;
- }
-
- /**
- * Implementation of certificate handler for EventHandler.
- * Called every time a resource is loaded via a secure
- * connection. In this context, can be called multiple
- * times if we have redirects
- * @param certificate The SSL certifcate
- * IMPORTANT: as this is called from network thread, can't call native
- * directly
- */
- public void certificate(SslCertificate certificate) {
- sendMessageInternal(obtainMessage(MSG_SSL_CERTIFICATE, certificate));
- }
-
- // Handle the certificate on the WebCore thread.
- private void handleCertificate(SslCertificate certificate) {
- // if this is the top-most main-frame page loader
- if (mIsMainPageLoader) {
- // update the browser frame (ie, the main frame)
- mBrowserFrame.certificate(certificate);
- }
- }
-
- /**
- * Implementation of error handler for EventHandler.
- * Subclasses should call this method to have error fields set.
- * @param id The error id described by EventHandler.
- * @param description A string description of the error.
- * IMPORTANT: as this is called from network thread, can't call native
- * directly
- */
- public void error(int id, String description) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "LoadListener.error url:" +
- url() + " id:" + id + " description:" + description);
- }
- sendMessageInternal(obtainMessage(MSG_CONTENT_ERROR, id, 0, description));
- }
-
- // Handle the error on the WebCore thread.
- private void handleError(int id, String description) {
- mErrorID = id;
- mErrorDescription = description;
- detachRequestHandle();
- notifyError();
- tearDown();
- }
-
- /**
- * Add data to the internal collection of data. This function is used by
- * the data: scheme, about: scheme and http/https schemes.
- * @param data A byte array containing the content.
- * @param length The length of data.
- * IMPORTANT: as this is called from network thread, can't call native
- * directly
- * XXX: Unlike the other network thread methods, this method can do the
- * work of decoding the data and appending it to the data builder because
- * mDataBuilder is a thread-safe structure.
- */
- public void data(byte[] data, int length) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "LoadListener.data(): url: " + url());
- }
-
- // Decode base64 data
- // Note: It's fine that we only decode base64 here and not in the other
- // data call because the only caller of the stream version is not
- // base64 encoded.
- if ("base64".equalsIgnoreCase(mTransferEncoding)) {
- if (length < data.length) {
- byte[] trimmedData = new byte[length];
- System.arraycopy(data, 0, trimmedData, 0, length);
- data = trimmedData;
- }
- data = Base64.decodeBase64(data);
- length = data.length;
- }
- // Synchronize on mData because commitLoad may write mData to WebCore
- // and we don't want to replace mData or mDataLength at the same time
- // as a write.
- boolean sendMessage = false;
- synchronized (mDataBuilder) {
- sendMessage = mDataBuilder.isEmpty();
- mDataBuilder.append(data, 0, length);
- }
- if (sendMessage) {
- // Send a message whenever data comes in after a write to WebCore
- sendMessageInternal(obtainMessage(MSG_CONTENT_DATA));
- }
- }
-
- /**
- * Event handler's endData call. Send a message to the handler notifying
- * them that the data has finished.
- * IMPORTANT: as this is called from network thread, can't call native
- * directly
- */
- public void endData() {
- if (Config.LOGV) {
- Log.v(LOGTAG, "LoadListener.endData(): url: " + url());
- }
- sendMessageInternal(obtainMessage(MSG_CONTENT_FINISHED));
- }
-
- // Handle the end of data.
- private void handleEndData() {
- if (mCancelled) return;
-
- switch (mStatusCode) {
- case HTTP_MOVED_PERMANENTLY:
- // 301 - permanent redirect
- mPermanent = true;
- case HTTP_FOUND:
- case HTTP_SEE_OTHER:
- case HTTP_TEMPORARY_REDIRECT:
- // 301, 302, 303, and 307 - redirect
- if (mStatusCode == HTTP_TEMPORARY_REDIRECT) {
- if (mRequestHandle != null &&
- mRequestHandle.getMethod().equals("POST")) {
- sendMessageInternal(obtainMessage(
- MSG_LOCATION_CHANGED_REQUEST));
- } else if (mMethod != null && mMethod.equals("POST")) {
- sendMessageInternal(obtainMessage(
- MSG_LOCATION_CHANGED_REQUEST));
- } else {
- sendMessageInternal(obtainMessage(MSG_LOCATION_CHANGED));
- }
- } else {
- sendMessageInternal(obtainMessage(MSG_LOCATION_CHANGED));
- }
- return;
-
- case HTTP_AUTH:
- case HTTP_PROXY_AUTH:
- // According to rfc2616, the response for HTTP_AUTH must include
- // WWW-Authenticate header field and the response for
- // HTTP_PROXY_AUTH must include Proxy-Authenticate header field.
- if (mAuthHeader != null &&
- (Network.getInstance(mContext).isValidProxySet() ||
- !mAuthHeader.isProxy())) {
- Network.getInstance(mContext).handleAuthRequest(this);
- return;
- }
- break; // use default
-
- case HTTP_NOT_MODIFIED:
- // Server could send back NOT_MODIFIED even if we didn't
- // ask for it, so make sure we have a valid CacheLoader
- // before calling it.
- if (mCacheLoader != null) {
- detachRequestHandle();
- mCacheLoader.load();
- if (Config.LOGV) {
- Log.v(LOGTAG, "LoadListener cache load url=" + url());
- }
- return;
- }
- break; // use default
-
- case HTTP_NOT_FOUND:
- // Not an error, the server can send back content.
- default:
- break;
- }
- detachRequestHandle();
- tearDown();
- }
-
- /* This method is called from CacheLoader when the initial request is
- * serviced by the Cache. */
- /* package */ void setCacheLoader(CacheLoader c) {
- mCacheLoader = c;
- }
-
- /**
- * Check the cache for the current URL, and load it if it is valid.
- *
- * @param headers for the request
- * @return true if cached response is used.
- */
- boolean checkCache(Map<String, String> headers) {
- // Get the cache file name for the current URL
- CacheResult result = CacheManager.getCacheFile(url(),
- headers);
-
- // Go ahead and set the cache loader to null in case the result is
- // null.
- mCacheLoader = null;
-
- if (result != null) {
- // The contents of the cache may need to be revalidated so just
- // remember the cache loader in the case that the server responds
- // positively to the cached content. This is also used to detect if
- // a redirect came from the cache.
- mCacheLoader = new CacheLoader(this, result);
-
- // If I got a cachedUrl and the revalidation header was not
- // added, then the cached content valid, we should use it.
- if (!headers.containsKey(
- CacheManager.HEADER_KEY_IFNONEMATCH) &&
- !headers.containsKey(
- CacheManager.HEADER_KEY_IFMODIFIEDSINCE)) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "FrameLoader: HTTP URL in cache " +
- "and usable: " + url());
- }
- // Load the cached file
- mCacheLoader.load();
- return true;
- }
- }
- return false;
- }
-
- /**
- * SSL certificate error callback. Handles SSL error(s) on the way up
- * to the user.
- * IMPORTANT: as this is called from network thread, can't call native
- * directly
- */
- public void handleSslErrorRequest(SslError error) {
- if (Config.LOGV) {
- Log.v(LOGTAG,
- "LoadListener.handleSslErrorRequest(): url:" + url() +
- " primary error: " + error.getPrimaryError() +
- " certificate: " + error.getCertificate());
- }
- sendMessageInternal(obtainMessage(MSG_SSL_ERROR, error));
- }
-
- // Handle the ssl error on the WebCore thread.
- private void handleSslError(SslError error) {
- if (!mCancelled) {
- mSslError = error;
- Network.getInstance(mContext).handleSslErrorRequest(this);
- }
- }
-
- /**
- * @return HTTP authentication realm or null if none.
- */
- String realm() {
- if (mAuthHeader == null) {
- return null;
- } else {
- return mAuthHeader.getRealm();
- }
- }
-
- /**
- * Returns true iff an HTTP authentication problem has
- * occured (credentials invalid).
- */
- boolean authCredentialsInvalid() {
- // if it is digest and the nonce is stale, we just
- // resubmit with a new nonce
- return (mAuthFailed &&
- !(mAuthHeader.isDigest() && mAuthHeader.getStale()));
- }
-
- /**
- * @return The last SSL error or null if there is none
- */
- SslError sslError() {
- return mSslError;
- }
-
- /**
- * Handles SSL error(s) on the way down from the user
- * (the user has already provided their feedback).
- */
- void handleSslErrorResponse(boolean proceed) {
- if (mRequestHandle != null) {
- mRequestHandle.handleSslErrorResponse(proceed);
- }
- }
-
- /**
- * Uses user-supplied credentials to restar a request.
- */
- void handleAuthResponse(String username, String password) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "LoadListener.handleAuthResponse: url: " + mUrl
- + " username: " + username
- + " password: " + password);
- }
-
- // create and queue an authentication-response
- if (username != null && password != null) {
- if (mAuthHeader != null && mRequestHandle != null) {
- mAuthHeader.setUsername(username);
- mAuthHeader.setPassword(password);
-
- int scheme = mAuthHeader.getScheme();
- if (scheme == HttpAuthHeader.BASIC) {
- // create a basic response
- boolean isProxy = mAuthHeader.isProxy();
-
- mRequestHandle.setupBasicAuthResponse(isProxy,
- username, password);
- } else {
- if (scheme == HttpAuthHeader.DIGEST) {
- // create a digest response
- boolean isProxy = mAuthHeader.isProxy();
-
- String realm = mAuthHeader.getRealm();
- String nonce = mAuthHeader.getNonce();
- String qop = mAuthHeader.getQop();
- String algorithm = mAuthHeader.getAlgorithm();
- String opaque = mAuthHeader.getOpaque();
-
- mRequestHandle.setupDigestAuthResponse
- (isProxy, username, password, realm,
- nonce, qop, algorithm, opaque);
- }
- }
- }
- }
- }
-
- /**
- * This is called when a request can be satisfied by the cache, however,
- * the cache result could be a redirect. In this case we need to issue
- * the network request.
- * @param method
- * @param headers
- * @param postData
- * @param isHighPriority
- */
- void setRequestData(String method, Map<String, String> headers,
- byte[] postData, boolean isHighPriority) {
- mMethod = method;
- mRequestHeaders = headers;
- mPostData = postData;
- mIsHighPriority = isHighPriority;
- }
-
- /**
- * @return The current URL associated with this load.
- */
- String url() {
- return mUrl;
- }
-
- /**
- * @return The current WebAddress associated with this load.
- */
- WebAddress getWebAddress() {
- return mUri;
- }
-
- /**
- * @return URL hostname (current URL).
- */
- String host() {
- if (mUri != null) {
- return mUri.mHost;
- }
-
- return null;
- }
-
- /**
- * @return The original URL associated with this load.
- */
- String originalUrl() {
- if (mOriginalUrl != null) {
- return mOriginalUrl;
- } else {
- return mUrl;
- }
- }
-
- void attachRequestHandle(RequestHandle requestHandle) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "LoadListener.attachRequestHandle(): " +
- "requestHandle: " + requestHandle);
- }
- mRequestHandle = requestHandle;
- }
-
- void detachRequestHandle() {
- if (Config.LOGV) {
- Log.v(LOGTAG, "LoadListener.detachRequestHandle(): " +
- "requestHandle: " + mRequestHandle);
- }
- mRequestHandle = null;
- }
-
- /*
- * This function is called from native WebCore code to
- * notify this LoadListener that the content it is currently
- * downloading should be saved to a file and not sent to
- * WebCore.
- */
- void downloadFile() {
- // Setting the Cache Result to null ensures that this
- // content is not added to the cache
- mCacheResult = null;
-
- // Inform the client that they should download a file
- mBrowserFrame.getCallbackProxy().onDownloadStart(url(),
- mBrowserFrame.getUserAgentString(),
- mHeaders.getContentDisposition(),
- mMimeType, mContentLength);
-
- // Cancel the download. We need to stop the http load.
- // The native loader object will get cleared by the call to
- // cancel() but will also be cleared on the WebCore side
- // when this function returns.
- cancel();
- }
-
- /*
- * This function is called from native WebCore code to
- * find out if the given URL is in the cache, and if it can
- * be used. This is just for forward/back navigation to a POST
- * URL.
- */
- static boolean willLoadFromCache(String url) {
- boolean inCache = CacheManager.getCacheFile(url, null) != null;
- if (Config.LOGV) {
- Log.v(LOGTAG, "willLoadFromCache: " + url + " in cache: " +
- inCache);
- }
- return inCache;
- }
-
- /*
- * Reset the cancel flag. This is used when we are resuming a stopped
- * download. To suspend a download, we cancel it. It can also be cancelled
- * when it has run out of disk space. In this situation, the download
- * can be resumed.
- */
- void resetCancel() {
- mCancelled = false;
- }
-
- String mimeType() {
- return mMimeType;
- }
-
- /*
- * Return the size of the content being downloaded. This represents the
- * full content size, even under the situation where the download has been
- * resumed after interruption.
- *
- * @ return full content size
- */
- long contentLength() {
- return mContentLength;
- }
-
- // Commit the headers if the status code is not a redirect.
- private void commitHeadersCheckRedirect() {
- if (mCancelled) return;
-
- // do not call webcore if it is redirect. According to the code in
- // InspectorController::willSendRequest(), the response is only updated
- // when it is not redirect.
- if ((mStatusCode >= 301 && mStatusCode <= 303) || mStatusCode == 307) {
- return;
- }
-
- commitHeaders();
- }
-
- // This commits the headers without checking the response status code.
- private void commitHeaders() {
- // Commit the headers to WebCore
- int nativeResponse = createNativeResponse();
- // The native code deletes the native response object.
- nativeReceivedResponse(nativeResponse);
- }
-
- /**
- * Create a WebCore response object so that it can be used by
- * nativeReceivedResponse or nativeRedirectedToUrl
- * @return native response pointer
- */
- private int createNativeResponse() {
- // The reason we change HTTP_NOT_MODIFIED to HTTP_OK is because we know
- // that WebCore never sends the if-modified-since header. Our
- // CacheManager does it for us. If the server responds with a 304, then
- // we treat it like it was a 200 code and proceed with loading the file
- // from the cache.
- int statusCode = mStatusCode == HTTP_NOT_MODIFIED
- ? HTTP_OK : mStatusCode;
- // pass content-type content-length and content-encoding
- final int nativeResponse = nativeCreateResponse(
- mUrl, statusCode, mStatusText,
- mMimeType, mContentLength, mEncoding,
- mCacheResult == null ? 0 : mCacheResult.expires / 1000);
- if (mHeaders != null) {
- mHeaders.getHeaders(new Headers.HeaderCallback() {
- public void header(String name, String value) {
- nativeSetResponseHeader(nativeResponse, name, value);
- }
- });
- }
- return nativeResponse;
- }
-
- /**
- * Commit the load. It should be ok to call repeatedly but only before
- * tearDown is called.
- */
- private void commitLoad() {
- if (mCancelled) return;
-
- // Give the data to WebKit now
- PerfChecker checker = new PerfChecker();
- ByteArrayBuilder.Chunk c;
- while (true) {
- c = mDataBuilder.getFirstChunk();
- if (c == null) break;
-
- if (c.mLength != 0) {
- if (mCacheResult != null) {
- try {
- mCacheResult.outStream.write(c.mArray, 0, c.mLength);
- } catch (IOException e) {
- mCacheResult = null;
- }
- }
- nativeAddData(c.mArray, c.mLength);
- }
- mDataBuilder.releaseChunk(c);
- checker.responseAlert("res nativeAddData");
- }
- }
-
- /**
- * Tear down the load. Subclasses should clean up any mess because of
- * cancellation or errors during the load.
- */
- void tearDown() {
- if (mCacheResult != null) {
- if (getErrorID() == OK) {
- CacheManager.saveCacheFile(mUrl, mCacheResult);
- }
-
- // we need to reset mCacheResult to be null
- // resource loader's tearDown will call into WebCore's
- // nativeFinish, which in turn calls loader.cancel().
- // If we don't reset mCacheFile, the file will be deleted.
- mCacheResult = null;
- }
- if (mNativeLoader != 0) {
- PerfChecker checker = new PerfChecker();
- nativeFinished();
- checker.responseAlert("res nativeFinished");
- clearNativeLoader();
- }
- }
-
- /**
- * Helper for getting the error ID.
- * @return errorID.
- */
- private int getErrorID() {
- return mErrorID;
- }
-
- /**
- * Return the error description.
- * @return errorDescription.
- */
- private String getErrorDescription() {
- return mErrorDescription;
- }
-
- /**
- * Notify the loader we encountered an error.
- */
- void notifyError() {
- if (mNativeLoader != 0) {
- String description = getErrorDescription();
- if (description == null) description = "";
- nativeError(getErrorID(), description, url());
- clearNativeLoader();
- }
- }
-
- /**
- * Cancel a request.
- * FIXME: This will only work if the request has yet to be handled. This
- * is in no way guarenteed if requests are served in a separate thread.
- * It also causes major problems if cancel is called during an
- * EventHandler's method call.
- */
- public void cancel() {
- if (Config.LOGV) {
- if (mRequestHandle == null) {
- Log.v(LOGTAG, "LoadListener.cancel(): no requestHandle");
- } else {
- Log.v(LOGTAG, "LoadListener.cancel()");
- }
- }
- if (mRequestHandle != null) {
- mRequestHandle.cancel();
- mRequestHandle = null;
- }
-
- mCacheResult = null;
- mCancelled = true;
-
- clearNativeLoader();
- }
-
- // This count is transferred from RequestHandle to LoadListener when
- // loading from the cache so that we can detect redirect loops that switch
- // between the network and the cache.
- private int mCacheRedirectCount;
-
- /*
- * Perform the actual redirection. This involves setting up the new URL,
- * informing WebCore and then telling the Network to start loading again.
- */
- private void doRedirect() {
- // as cancel() can cancel the load before doRedirect() is
- // called through handleMessage, needs to check to see if we
- // are canceled before proceed
- if (mCancelled) {
- return;
- }
-
- // Do the same check for a redirect loop that
- // RequestHandle.setupRedirect does.
- if (mCacheRedirectCount >= RequestHandle.MAX_REDIRECT_COUNT) {
- handleError(EventHandler.ERROR_REDIRECT_LOOP, mContext.getString(
- R.string.httpErrorRedirectLoop));
- return;
- }
-
- String redirectTo = mHeaders.getLocation();
- if (redirectTo != null) {
- int nativeResponse = createNativeResponse();
- redirectTo =
- nativeRedirectedToUrl(mUrl, redirectTo, nativeResponse);
- // nativeRedirectedToUrl() may call cancel(), e.g. when redirect
- // from a https site to a http site, check mCancelled again
- if (mCancelled) {
- return;
- }
- if (redirectTo == null) {
- Log.d(LOGTAG, "Redirection failed for "
- + mHeaders.getLocation());
- cancel();
- return;
- } else if (!URLUtil.isNetworkUrl(redirectTo)) {
- final String text = mContext
- .getString(R.string.open_permission_deny)
- + "\n" + redirectTo;
- nativeAddData(text.getBytes(), text.length());
- nativeFinished();
- clearNativeLoader();
- return;
- }
-
- if (mOriginalUrl == null) {
- mOriginalUrl = mUrl;
- }
-
- // Cache the redirect response
- if (mCacheResult != null) {
- if (getErrorID() == OK) {
- CacheManager.saveCacheFile(mUrl, mCacheResult);
- }
- mCacheResult = null;
- }
-
- setUrl(redirectTo);
-
- // Redirect may be in the cache
- if (mRequestHeaders == null) {
- mRequestHeaders = new HashMap<String, String>();
- }
- boolean fromCache = false;
- if (mCacheLoader != null) {
- // This is a redirect from the cache loader. Increment the
- // redirect count to avoid redirect loops.
- mCacheRedirectCount++;
- fromCache = true;
- }
- if (!checkCache(mRequestHeaders)) {
- // mRequestHandle can be null when the request was satisfied
- // by the cache, and the cache returned a redirect
- if (mRequestHandle != null) {
- mRequestHandle.setupRedirect(redirectTo, mStatusCode,
- mRequestHeaders);
- } else {
- // If the original request came from the cache, there is no
- // RequestHandle, we have to create a new one through
- // Network.requestURL.
- Network network = Network.getInstance(getContext());
- if (!network.requestURL(mMethod, mRequestHeaders,
- mPostData, this, mIsHighPriority)) {
- // Signal a bad url error if we could not load the
- // redirection.
- handleError(EventHandler.ERROR_BAD_URL,
- mContext.getString(R.string.httpErrorBadUrl));
- return;
- }
- }
- if (fromCache) {
- // If we are coming from a cache load, we need to transfer
- // the redirect count to the new (or old) RequestHandle to
- // keep the redirect count in sync.
- mRequestHandle.setRedirectCount(mCacheRedirectCount);
- }
- } else if (!fromCache) {
- // Switching from network to cache means we need to grab the
- // redirect count from the RequestHandle to keep the count in
- // sync. Add 1 to account for the current redirect.
- mCacheRedirectCount = mRequestHandle.getRedirectCount() + 1;
- }
- // Clear the buffered data since the redirect is valid.
- mDataBuilder.clear();
- } else {
- commitHeaders();
- commitLoad();
- tearDown();
- }
-
- if (Config.LOGV) {
- Log.v(LOGTAG, "LoadListener.onRedirect(): redirect to: " +
- redirectTo);
- }
- }
-
- /**
- * Parses the content-type header.
- */
- private static final Pattern CONTENT_TYPE_PATTERN =
- Pattern.compile("^([a-zA-Z\\*]+/[\\w\\+\\*-]+[\\.[\\w\\+-]+]*)$");
-
- private void parseContentTypeHeader(String contentType) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "LoadListener.parseContentTypeHeader: " +
- "contentType: " + contentType);
- }
-
- if (contentType != null) {
- int i = contentType.indexOf(';');
- if (i >= 0) {
- mMimeType = contentType.substring(0, i);
-
- int j = contentType.indexOf('=', i);
- if (j > 0) {
- i = contentType.indexOf(';', j);
- if (i < j) {
- i = contentType.length();
- }
- mEncoding = contentType.substring(j + 1, i);
- } else {
- mEncoding = contentType.substring(i + 1);
- }
- // Trim excess whitespace.
- mEncoding = mEncoding.trim();
-
- if (i < contentType.length() - 1) {
- // for data: uri the mimeType and encoding have
- // the form image/jpeg;base64 or text/plain;charset=utf-8
- // or text/html;charset=utf-8;base64
- mTransferEncoding = contentType.substring(i + 1).trim();
- }
- } else {
- mMimeType = contentType;
- }
-
- // Trim leading and trailing whitespace
- mMimeType = mMimeType.trim();
-
- try {
- Matcher m = CONTENT_TYPE_PATTERN.matcher(mMimeType);
- if (m.find()) {
- mMimeType = m.group(1);
- } else {
- guessMimeType();
- }
- } catch (IllegalStateException ex) {
- guessMimeType();
- }
- }
- }
-
- /**
- * @return The HTTP-authentication object or null if there
- * is no supported scheme in the header.
- * If there are several valid schemes present, we pick the
- * strongest one. If there are several schemes of the same
- * strength, we pick the one that comes first.
- */
- private HttpAuthHeader parseAuthHeader(String header) {
- if (header != null) {
- int posMax = 256;
- int posLen = 0;
- int[] pos = new int [posMax];
-
- int headerLen = header.length();
- if (headerLen > 0) {
- // first, we find all unquoted instances of 'Basic' and 'Digest'
- boolean quoted = false;
- for (int i = 0; i < headerLen && posLen < posMax; ++i) {
- if (header.charAt(i) == '\"') {
- quoted = !quoted;
- } else {
- if (!quoted) {
- if (header.regionMatches(true, i,
- HttpAuthHeader.BASIC_TOKEN, 0,
- HttpAuthHeader.BASIC_TOKEN.length())) {
- pos[posLen++] = i;
- continue;
- }
-
- if (header.regionMatches(true, i,
- HttpAuthHeader.DIGEST_TOKEN, 0,
- HttpAuthHeader.DIGEST_TOKEN.length())) {
- pos[posLen++] = i;
- continue;
- }
- }
- }
- }
- }
-
- if (posLen > 0) {
- // consider all digest schemes first (if any)
- for (int i = 0; i < posLen; i++) {
- if (header.regionMatches(true, pos[i],
- HttpAuthHeader.DIGEST_TOKEN, 0,
- HttpAuthHeader.DIGEST_TOKEN.length())) {
- String sub = header.substring(pos[i],
- (i + 1 < posLen ? pos[i + 1] : headerLen));
-
- HttpAuthHeader rval = new HttpAuthHeader(sub);
- if (rval.isSupportedScheme()) {
- // take the first match
- return rval;
- }
- }
- }
-
- // ...then consider all basic schemes (if any)
- for (int i = 0; i < posLen; i++) {
- if (header.regionMatches(true, pos[i],
- HttpAuthHeader.BASIC_TOKEN, 0,
- HttpAuthHeader.BASIC_TOKEN.length())) {
- String sub = header.substring(pos[i],
- (i + 1 < posLen ? pos[i + 1] : headerLen));
-
- HttpAuthHeader rval = new HttpAuthHeader(sub);
- if (rval.isSupportedScheme()) {
- // take the first match
- return rval;
- }
- }
- }
- }
- }
-
- return null;
- }
-
- /**
- * If the content is a redirect or not modified we should not send
- * any data into WebCore as that will cause it create a document with
- * the data, then when we try to provide the real content, it will assert.
- *
- * @return True iff the callback should be ignored.
- */
- private boolean ignoreCallbacks() {
- return (mCancelled || mAuthHeader != null ||
- (mStatusCode > 300 && mStatusCode < 400));
- }
-
- /**
- * Sets the current URL associated with this load.
- */
- void setUrl(String url) {
- if (url != null) {
- if (URLUtil.isDataUrl(url)) {
- // Don't strip anchor as that is a valid part of the URL
- mUrl = url;
- } else {
- mUrl = URLUtil.stripAnchor(url);
- }
- mUri = null;
- if (URLUtil.isNetworkUrl(mUrl)) {
- try {
- mUri = new WebAddress(mUrl);
- } catch (ParseException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- /**
- * Guesses MIME type if one was not specified. Defaults to 'text/html'. In
- * addition, tries to guess the MIME type based on the extension.
- *
- */
- private void guessMimeType() {
- // Data urls must have a valid mime type or a blank string for the mime
- // type (implying text/plain).
- if (URLUtil.isDataUrl(mUrl) && mMimeType.length() != 0) {
- cancel();
- final String text = mContext.getString(R.string.httpErrorBadUrl);
- handleError(EventHandler.ERROR_BAD_URL, text);
- } else {
- // Note: This is ok because this is used only for the main content
- // of frames. If no content-type was specified, it is fine to
- // default to text/html.
- mMimeType = "text/html";
- String newMimeType = guessMimeTypeFromExtension();
- if (newMimeType != null) {
- mMimeType = newMimeType;
- }
- }
- }
-
- /**
- * guess MIME type based on the file extension.
- */
- private String guessMimeTypeFromExtension() {
- // PENDING: need to normalize url
- if (Config.LOGV) {
- Log.v(LOGTAG, "guessMimeTypeFromExtension: mURL = " + mUrl);
- }
-
- String mimeType =
- MimeTypeMap.getSingleton().getMimeTypeFromExtension(
- MimeTypeMap.getFileExtensionFromUrl(mUrl));
-
- if (mimeType != null) {
- // XXX: Until the servers send us either correct xhtml or
- // text/html, treat application/xhtml+xml as text/html.
- if (mimeType.equals("application/xhtml+xml")) {
- mimeType = "text/html";
- }
- }
-
- return mimeType;
- }
-
- /**
- * Either send a message to ourselves or queue the message if this is a
- * synchronous load.
- */
- private void sendMessageInternal(Message msg) {
- if (mSynchronous) {
- mMessageQueue.add(msg);
- } else {
- sendMessage(msg);
- }
- }
-
- /**
- * Cycle through our messages for synchronous loads.
- */
- /* package */ void loadSynchronousMessages() {
- if (Config.DEBUG && !mSynchronous) {
- throw new AssertionError();
- }
- // Note: this can be called twice if it is a synchronous network load,
- // and there is a cache, but it needs to go to network to validate. If
- // validation succeed, the CacheLoader is used so this is first called
- // from http thread. Then it is called again from WebViewCore thread
- // after the load is completed. So make sure the queue is cleared but
- // don't set it to null.
- for (int size = mMessageQueue.size(); size > 0; size--) {
- handleMessage(mMessageQueue.remove(0));
- }
- }
-
- //=========================================================================
- // native functions
- //=========================================================================
-
- /**
- * Create a new native response object.
- * @param url The url of the resource.
- * @param statusCode The HTTP status code.
- * @param statusText The HTTP status text.
- * @param mimeType HTTP content-type.
- * @param expectedLength An estimate of the content length or the length
- * given by the server.
- * @param encoding HTTP encoding.
- * @param expireTime HTTP expires converted to seconds since the epoch.
- * @return The native response pointer.
- */
- private native int nativeCreateResponse(String url, int statusCode,
- String statusText, String mimeType, long expectedLength,
- String encoding, long expireTime);
-
- /**
- * Add a response header to the native object.
- * @param nativeResponse The native pointer.
- * @param key String key.
- * @param val String value.
- */
- private native void nativeSetResponseHeader(int nativeResponse, String key,
- String val);
-
- /**
- * Dispatch the response.
- * @param nativeResponse The native pointer.
- */
- private native void nativeReceivedResponse(int nativeResponse);
-
- /**
- * Add data to the loader.
- * @param data Byte array of data.
- * @param length Number of objects in data.
- */
- private native void nativeAddData(byte[] data, int length);
-
- /**
- * Tell the loader it has finished.
- */
- private native void nativeFinished();
-
- /**
- * tell the loader to redirect
- * @param baseUrl The base url.
- * @param redirectTo The url to redirect to.
- * @param nativeResponse The native pointer.
- * @return The new url that the resource redirected to.
- */
- private native String nativeRedirectedToUrl(String baseUrl,
- String redirectTo, int nativeResponse);
-
- /**
- * Tell the loader there is error
- * @param id
- * @param desc
- * @param failingUrl The url that failed.
- */
- private native void nativeError(int id, String desc, String failingUrl);
-
-}
diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java
deleted file mode 100644
index c9cc208..0000000
--- a/core/java/android/webkit/MimeTypeMap.java
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import java.util.HashMap;
-import java.util.regex.Pattern;
-
-/**
- * Two-way map that maps MIME-types to file extensions and vice versa.
- */
-public /* package */ class MimeTypeMap {
-
- /**
- * Singleton MIME-type map instance:
- */
- private static MimeTypeMap sMimeTypeMap;
-
- /**
- * MIME-type to file extension mapping:
- */
- private HashMap<String, String> mMimeTypeToExtensionMap;
-
- /**
- * File extension to MIME type mapping:
- */
- private HashMap<String, String> mExtensionToMimeTypeMap;
-
-
- /**
- * Creates a new MIME-type map.
- */
- private MimeTypeMap() {
- mMimeTypeToExtensionMap = new HashMap<String, String>();
- mExtensionToMimeTypeMap = new HashMap<String, String>();
- }
-
- /**
- * Returns the file extension or an empty string iff there is no
- * extension.
- */
- public static String getFileExtensionFromUrl(String url) {
- if (url != null && url.length() > 0) {
- int query = url.lastIndexOf('?');
- if (query > 0) {
- url = url.substring(0, query);
- }
- int filenamePos = url.lastIndexOf('/');
- String filename =
- 0 <= filenamePos ? url.substring(filenamePos + 1) : url;
-
- // if the filename contains special characters, we don't
- // consider it valid for our matching purposes:
- if (filename.length() > 0 &&
- Pattern.matches("[a-zA-Z_0-9\\.\\-\\(\\)]+", filename)) {
- int dotPos = filename.lastIndexOf('.');
- if (0 <= dotPos) {
- return filename.substring(dotPos + 1);
- }
- }
- }
-
- return "";
- }
-
- /**
- * Load an entry into the map. This does not check if the item already
- * exists, it trusts the caller!
- */
- private void loadEntry(String mimeType, String extension,
- boolean textType) {
- //
- // if we have an existing x --> y mapping, we do not want to
- // override it with another mapping x --> ?
- // this is mostly because of the way the mime-type map below
- // is constructed (if a mime type maps to several extensions
- // the first extension is considered the most popular and is
- // added first; we do not want to overwrite it later).
- //
- if (!mMimeTypeToExtensionMap.containsKey(mimeType)) {
- mMimeTypeToExtensionMap.put(mimeType, extension);
- }
-
- //
- // here, we don't want to map extensions to text MIME types;
- // otherwise, we will start replacing generic text/plain and
- // text/html with text MIME types that our platform does not
- // understand.
- //
- if (!textType) {
- mExtensionToMimeTypeMap.put(extension, mimeType);
- }
- }
-
- /**
- * @return True iff there is a mimeType entry in the map.
- */
- public boolean hasMimeType(String mimeType) {
- if (mimeType != null && mimeType.length() > 0) {
- return mMimeTypeToExtensionMap.containsKey(mimeType);
- }
-
- return false;
- }
-
- /**
- * @return The extension for the MIME type or null iff there is none.
- */
- public String getMimeTypeFromExtension(String extension) {
- if (extension != null && extension.length() > 0) {
- return mExtensionToMimeTypeMap.get(extension);
- }
-
- return null;
- }
-
- /**
- * @return True iff there is an extension entry in the map.
- */
- public boolean hasExtension(String extension) {
- if (extension != null && extension.length() > 0) {
- return mExtensionToMimeTypeMap.containsKey(extension);
- }
-
- return false;
- }
-
- /**
- * @return The MIME type for the extension or null iff there is none.
- */
- public String getExtensionFromMimeType(String mimeType) {
- if (mimeType != null && mimeType.length() > 0) {
- return mMimeTypeToExtensionMap.get(mimeType);
- }
-
- return null;
- }
-
- /**
- * @return The singleton instance of the MIME-type map.
- */
- public static MimeTypeMap getSingleton() {
- if (sMimeTypeMap == null) {
- sMimeTypeMap = new MimeTypeMap();
-
- // The following table is based on /etc/mime.types data minus
- // chemical/* MIME types and MIME types that don't map to any
- // file extensions. We also exclude top-level domain names to
- // deal with cases like:
- //
- // mail.google.com/a/google.com
- //
- // and "active" MIME types (due to potential security issues).
- //
- // Also, notice that not all data from this table is actually
- // added (see loadEntry method for more details).
-
- sMimeTypeMap.loadEntry("application/andrew-inset", "ez", false);
- sMimeTypeMap.loadEntry("application/dsptype", "tsp", false);
- sMimeTypeMap.loadEntry("application/futuresplash", "spl", false);
- sMimeTypeMap.loadEntry("application/hta", "hta", false);
- sMimeTypeMap.loadEntry("application/mac-binhex40", "hqx", false);
- sMimeTypeMap.loadEntry("application/mac-compactpro", "cpt", false);
- sMimeTypeMap.loadEntry("application/mathematica", "nb", false);
- sMimeTypeMap.loadEntry("application/msaccess", "mdb", false);
- sMimeTypeMap.loadEntry("application/oda", "oda", false);
- sMimeTypeMap.loadEntry("application/ogg", "ogg", false);
- sMimeTypeMap.loadEntry("application/pdf", "pdf", false);
- sMimeTypeMap.loadEntry("application/pgp-keys", "key", false);
- sMimeTypeMap.loadEntry("application/pgp-signature", "pgp", false);
- sMimeTypeMap.loadEntry("application/pics-rules", "prf", false);
- sMimeTypeMap.loadEntry("application/rar", "rar", false);
- sMimeTypeMap.loadEntry("application/rdf+xml", "rdf", false);
- sMimeTypeMap.loadEntry("application/rss+xml", "rss", false);
- sMimeTypeMap.loadEntry("application/zip", "zip", false);
- sMimeTypeMap.loadEntry("application/vnd.android.package-archive",
- "apk", false);
- sMimeTypeMap.loadEntry("application/vnd.cinderella", "cdy", false);
- sMimeTypeMap.loadEntry("application/vnd.ms-pki.stl", "stl", false);
- sMimeTypeMap.loadEntry(
- "application/vnd.oasis.opendocument.database", "odb",
- false);
- sMimeTypeMap.loadEntry(
- "application/vnd.oasis.opendocument.formula", "odf",
- false);
- sMimeTypeMap.loadEntry(
- "application/vnd.oasis.opendocument.graphics", "odg",
- false);
- sMimeTypeMap.loadEntry(
- "application/vnd.oasis.opendocument.graphics-template",
- "otg", false);
- sMimeTypeMap.loadEntry(
- "application/vnd.oasis.opendocument.image", "odi", false);
- sMimeTypeMap.loadEntry(
- "application/vnd.oasis.opendocument.spreadsheet", "ods",
- false);
- sMimeTypeMap.loadEntry(
- "application/vnd.oasis.opendocument.spreadsheet-template",
- "ots", false);
- sMimeTypeMap.loadEntry(
- "application/vnd.oasis.opendocument.text", "odt", false);
- sMimeTypeMap.loadEntry(
- "application/vnd.oasis.opendocument.text-master", "odm",
- false);
- sMimeTypeMap.loadEntry(
- "application/vnd.oasis.opendocument.text-template", "ott",
- false);
- sMimeTypeMap.loadEntry(
- "application/vnd.oasis.opendocument.text-web", "oth",
- false);
- sMimeTypeMap.loadEntry("application/vnd.rim.cod", "cod", false);
- sMimeTypeMap.loadEntry("application/vnd.smaf", "mmf", false);
- sMimeTypeMap.loadEntry("application/vnd.stardivision.calc", "sdc",
- false);
- sMimeTypeMap.loadEntry("application/vnd.stardivision.draw", "sda",
- false);
- sMimeTypeMap.loadEntry(
- "application/vnd.stardivision.impress", "sdd", false);
- sMimeTypeMap.loadEntry(
- "application/vnd.stardivision.impress", "sdp", false);
- sMimeTypeMap.loadEntry("application/vnd.stardivision.math", "smf",
- false);
- sMimeTypeMap.loadEntry("application/vnd.stardivision.writer", "sdw",
- false);
- sMimeTypeMap.loadEntry("application/vnd.stardivision.writer", "vor",
- false);
- sMimeTypeMap.loadEntry(
- "application/vnd.stardivision.writer-global", "sgl", false);
- sMimeTypeMap.loadEntry("application/vnd.sun.xml.calc", "sxc",
- false);
- sMimeTypeMap.loadEntry(
- "application/vnd.sun.xml.calc.template", "stc", false);
- sMimeTypeMap.loadEntry("application/vnd.sun.xml.draw", "sxd",
- false);
- sMimeTypeMap.loadEntry(
- "application/vnd.sun.xml.draw.template", "std", false);
- sMimeTypeMap.loadEntry("application/vnd.sun.xml.impress", "sxi",
- false);
- sMimeTypeMap.loadEntry(
- "application/vnd.sun.xml.impress.template", "sti", false);
- sMimeTypeMap.loadEntry("application/vnd.sun.xml.math", "sxm",
- false);
- sMimeTypeMap.loadEntry("application/vnd.sun.xml.writer", "sxw",
- false);
- sMimeTypeMap.loadEntry(
- "application/vnd.sun.xml.writer.global", "sxg", false);
- sMimeTypeMap.loadEntry(
- "application/vnd.sun.xml.writer.template", "stw", false);
- sMimeTypeMap.loadEntry("application/vnd.visio", "vsd", false);
- sMimeTypeMap.loadEntry("application/x-abiword", "abw", false);
- sMimeTypeMap.loadEntry("application/x-apple-diskimage", "dmg",
- false);
- sMimeTypeMap.loadEntry("application/x-bcpio", "bcpio", false);
- sMimeTypeMap.loadEntry("application/x-bittorrent", "torrent",
- false);
- sMimeTypeMap.loadEntry("application/x-cdf", "cdf", false);
- sMimeTypeMap.loadEntry("application/x-cdlink", "vcd", false);
- sMimeTypeMap.loadEntry("application/x-chess-pgn", "pgn", false);
- sMimeTypeMap.loadEntry("application/x-cpio", "cpio", false);
- sMimeTypeMap.loadEntry("application/x-debian-package", "deb",
- false);
- sMimeTypeMap.loadEntry("application/x-debian-package", "udeb",
- false);
- sMimeTypeMap.loadEntry("application/x-director", "dcr", false);
- sMimeTypeMap.loadEntry("application/x-director", "dir", false);
- sMimeTypeMap.loadEntry("application/x-director", "dxr", false);
- sMimeTypeMap.loadEntry("application/x-dms", "dms", false);
- sMimeTypeMap.loadEntry("application/x-doom", "wad", false);
- sMimeTypeMap.loadEntry("application/x-dvi", "dvi", false);
- sMimeTypeMap.loadEntry("application/x-flac", "flac", false);
- sMimeTypeMap.loadEntry("application/x-font", "pfa", false);
- sMimeTypeMap.loadEntry("application/x-font", "pfb", false);
- sMimeTypeMap.loadEntry("application/x-font", "gsf", false);
- sMimeTypeMap.loadEntry("application/x-font", "pcf", false);
- sMimeTypeMap.loadEntry("application/x-font", "pcf.Z", false);
- sMimeTypeMap.loadEntry("application/x-freemind", "mm", false);
- sMimeTypeMap.loadEntry("application/x-futuresplash", "spl", false);
- sMimeTypeMap.loadEntry("application/x-gnumeric", "gnumeric", false);
- sMimeTypeMap.loadEntry("application/x-go-sgf", "sgf", false);
- sMimeTypeMap.loadEntry("application/x-graphing-calculator", "gcf",
- false);
- sMimeTypeMap.loadEntry("application/x-gtar", "gtar", false);
- sMimeTypeMap.loadEntry("application/x-gtar", "tgz", false);
- sMimeTypeMap.loadEntry("application/x-gtar", "taz", false);
- sMimeTypeMap.loadEntry("application/x-hdf", "hdf", false);
- sMimeTypeMap.loadEntry("application/x-ica", "ica", false);
- sMimeTypeMap.loadEntry("application/x-internet-signup", "ins",
- false);
- sMimeTypeMap.loadEntry("application/x-internet-signup", "isp",
- false);
- sMimeTypeMap.loadEntry("application/x-iphone", "iii", false);
- sMimeTypeMap.loadEntry("application/x-iso9660-image", "iso", false);
- sMimeTypeMap.loadEntry("application/x-jmol", "jmz", false);
- sMimeTypeMap.loadEntry("application/x-kchart", "chrt", false);
- sMimeTypeMap.loadEntry("application/x-killustrator", "kil", false);
- sMimeTypeMap.loadEntry("application/x-koan", "skp", false);
- sMimeTypeMap.loadEntry("application/x-koan", "skd", false);
- sMimeTypeMap.loadEntry("application/x-koan", "skt", false);
- sMimeTypeMap.loadEntry("application/x-koan", "skm", false);
- sMimeTypeMap.loadEntry("application/x-kpresenter", "kpr", false);
- sMimeTypeMap.loadEntry("application/x-kpresenter", "kpt", false);
- sMimeTypeMap.loadEntry("application/x-kspread", "ksp", false);
- sMimeTypeMap.loadEntry("application/x-kword", "kwd", false);
- sMimeTypeMap.loadEntry("application/x-kword", "kwt", false);
- sMimeTypeMap.loadEntry("application/x-latex", "latex", false);
- sMimeTypeMap.loadEntry("application/x-lha", "lha", false);
- sMimeTypeMap.loadEntry("application/x-lzh", "lzh", false);
- sMimeTypeMap.loadEntry("application/x-lzx", "lzx", false);
- sMimeTypeMap.loadEntry("application/x-maker", "frm", false);
- sMimeTypeMap.loadEntry("application/x-maker", "maker", false);
- sMimeTypeMap.loadEntry("application/x-maker", "frame", false);
- sMimeTypeMap.loadEntry("application/x-maker", "fb", false);
- sMimeTypeMap.loadEntry("application/x-maker", "book", false);
- sMimeTypeMap.loadEntry("application/x-maker", "fbdoc", false);
- sMimeTypeMap.loadEntry("application/x-mif", "mif", false);
- sMimeTypeMap.loadEntry("application/x-ms-wmd", "wmd", false);
- sMimeTypeMap.loadEntry("application/x-ms-wmz", "wmz", false);
- sMimeTypeMap.loadEntry("application/x-msi", "msi", false);
- sMimeTypeMap.loadEntry("application/x-ns-proxy-autoconfig", "pac",
- false);
- sMimeTypeMap.loadEntry("application/x-nwc", "nwc", false);
- sMimeTypeMap.loadEntry("application/x-object", "o", false);
- sMimeTypeMap.loadEntry("application/x-oz-application", "oza",
- false);
- sMimeTypeMap.loadEntry("application/x-pkcs7-certreqresp", "p7r",
- false);
- sMimeTypeMap.loadEntry("application/x-pkcs7-crl", "crl", false);
- sMimeTypeMap.loadEntry("application/x-quicktimeplayer", "qtl",
- false);
- sMimeTypeMap.loadEntry("application/x-shar", "shar", false);
- sMimeTypeMap.loadEntry("application/x-stuffit", "sit", false);
- sMimeTypeMap.loadEntry("application/x-sv4cpio", "sv4cpio", false);
- sMimeTypeMap.loadEntry("application/x-sv4crc", "sv4crc", false);
- sMimeTypeMap.loadEntry("application/x-tar", "tar", false);
- sMimeTypeMap.loadEntry("application/x-texinfo", "texinfo", false);
- sMimeTypeMap.loadEntry("application/x-texinfo", "texi", false);
- sMimeTypeMap.loadEntry("application/x-troff", "t", false);
- sMimeTypeMap.loadEntry("application/x-troff", "roff", false);
- sMimeTypeMap.loadEntry("application/x-troff-man", "man", false);
- sMimeTypeMap.loadEntry("application/x-ustar", "ustar", false);
- sMimeTypeMap.loadEntry("application/x-wais-source", "src", false);
- sMimeTypeMap.loadEntry("application/x-wingz", "wz", false);
- sMimeTypeMap.loadEntry(
- "application/x-webarchive", "webarchive", false); // added
- sMimeTypeMap.loadEntry("application/x-x509-ca-cert", "crt", false);
- sMimeTypeMap.loadEntry("application/x-xcf", "xcf", false);
- sMimeTypeMap.loadEntry("application/x-xfig", "fig", false);
- sMimeTypeMap.loadEntry("audio/basic", "snd", false);
- sMimeTypeMap.loadEntry("audio/midi", "mid", false);
- sMimeTypeMap.loadEntry("audio/midi", "midi", false);
- sMimeTypeMap.loadEntry("audio/midi", "kar", false);
- sMimeTypeMap.loadEntry("audio/mpeg", "mpga", false);
- sMimeTypeMap.loadEntry("audio/mpeg", "mpega", false);
- sMimeTypeMap.loadEntry("audio/mpeg", "mp2", false);
- sMimeTypeMap.loadEntry("audio/mpeg", "mp3", false);
- sMimeTypeMap.loadEntry("audio/mpeg", "m4a", false);
- sMimeTypeMap.loadEntry("audio/mpegurl", "m3u", false);
- sMimeTypeMap.loadEntry("audio/prs.sid", "sid", false);
- sMimeTypeMap.loadEntry("audio/x-aiff", "aif", false);
- sMimeTypeMap.loadEntry("audio/x-aiff", "aiff", false);
- sMimeTypeMap.loadEntry("audio/x-aiff", "aifc", false);
- sMimeTypeMap.loadEntry("audio/x-gsm", "gsm", false);
- sMimeTypeMap.loadEntry("audio/x-mpegurl", "m3u", false);
- sMimeTypeMap.loadEntry("audio/x-ms-wma", "wma", false);
- sMimeTypeMap.loadEntry("audio/x-ms-wax", "wax", false);
- sMimeTypeMap.loadEntry("audio/x-pn-realaudio", "ra", false);
- sMimeTypeMap.loadEntry("audio/x-pn-realaudio", "rm", false);
- sMimeTypeMap.loadEntry("audio/x-pn-realaudio", "ram", false);
- sMimeTypeMap.loadEntry("audio/x-realaudio", "ra", false);
- sMimeTypeMap.loadEntry("audio/x-scpls", "pls", false);
- sMimeTypeMap.loadEntry("audio/x-sd2", "sd2", false);
- sMimeTypeMap.loadEntry("audio/x-wav", "wav", false);
- sMimeTypeMap.loadEntry("image/bmp", "bmp", false); // added
- sMimeTypeMap.loadEntry("image/gif", "gif", false);
- sMimeTypeMap.loadEntry("image/ico", "cur", false); // added
- sMimeTypeMap.loadEntry("image/ico", "ico", false); // added
- sMimeTypeMap.loadEntry("image/ief", "ief", false);
- sMimeTypeMap.loadEntry("image/jpeg", "jpeg", false);
- sMimeTypeMap.loadEntry("image/jpeg", "jpg", false);
- sMimeTypeMap.loadEntry("image/jpeg", "jpe", false);
- sMimeTypeMap.loadEntry("image/pcx", "pcx", false);
- sMimeTypeMap.loadEntry("image/png", "png", false);
- sMimeTypeMap.loadEntry("image/svg+xml", "svg", false);
- sMimeTypeMap.loadEntry("image/svg+xml", "svgz", false);
- sMimeTypeMap.loadEntry("image/tiff", "tiff", false);
- sMimeTypeMap.loadEntry("image/tiff", "tif", false);
- sMimeTypeMap.loadEntry("image/vnd.djvu", "djvu", false);
- sMimeTypeMap.loadEntry("image/vnd.djvu", "djv", false);
- sMimeTypeMap.loadEntry("image/vnd.wap.wbmp", "wbmp", false);
- sMimeTypeMap.loadEntry("image/x-cmu-raster", "ras", false);
- sMimeTypeMap.loadEntry("image/x-coreldraw", "cdr", false);
- sMimeTypeMap.loadEntry("image/x-coreldrawpattern", "pat", false);
- sMimeTypeMap.loadEntry("image/x-coreldrawtemplate", "cdt", false);
- sMimeTypeMap.loadEntry("image/x-corelphotopaint", "cpt", false);
- sMimeTypeMap.loadEntry("image/x-icon", "ico", false);
- sMimeTypeMap.loadEntry("image/x-jg", "art", false);
- sMimeTypeMap.loadEntry("image/x-jng", "jng", false);
- sMimeTypeMap.loadEntry("image/x-ms-bmp", "bmp", false);
- sMimeTypeMap.loadEntry("image/x-photoshop", "psd", false);
- sMimeTypeMap.loadEntry("image/x-portable-anymap", "pnm", false);
- sMimeTypeMap.loadEntry("image/x-portable-bitmap", "pbm", false);
- sMimeTypeMap.loadEntry("image/x-portable-graymap", "pgm", false);
- sMimeTypeMap.loadEntry("image/x-portable-pixmap", "ppm", false);
- sMimeTypeMap.loadEntry("image/x-rgb", "rgb", false);
- sMimeTypeMap.loadEntry("image/x-xbitmap", "xbm", false);
- sMimeTypeMap.loadEntry("image/x-xpixmap", "xpm", false);
- sMimeTypeMap.loadEntry("image/x-xwindowdump", "xwd", false);
- sMimeTypeMap.loadEntry("model/iges", "igs", false);
- sMimeTypeMap.loadEntry("model/iges", "iges", false);
- sMimeTypeMap.loadEntry("model/mesh", "msh", false);
- sMimeTypeMap.loadEntry("model/mesh", "mesh", false);
- sMimeTypeMap.loadEntry("model/mesh", "silo", false);
- sMimeTypeMap.loadEntry("text/calendar", "ics", true);
- sMimeTypeMap.loadEntry("text/calendar", "icz", true);
- sMimeTypeMap.loadEntry("text/comma-separated-values", "csv", true);
- sMimeTypeMap.loadEntry("text/css", "css", true);
- sMimeTypeMap.loadEntry("text/h323", "323", true);
- sMimeTypeMap.loadEntry("text/iuls", "uls", true);
- sMimeTypeMap.loadEntry("text/mathml", "mml", true);
- // add it first so it will be the default for ExtensionFromMimeType
- sMimeTypeMap.loadEntry("text/plain", "txt", true);
- sMimeTypeMap.loadEntry("text/plain", "asc", true);
- sMimeTypeMap.loadEntry("text/plain", "text", true);
- sMimeTypeMap.loadEntry("text/plain", "diff", true);
- sMimeTypeMap.loadEntry("text/plain", "pot", true);
- sMimeTypeMap.loadEntry("text/richtext", "rtx", true);
- sMimeTypeMap.loadEntry("text/rtf", "rtf", true);
- sMimeTypeMap.loadEntry("text/texmacs", "ts", true);
- sMimeTypeMap.loadEntry("text/text", "phps", true);
- sMimeTypeMap.loadEntry("text/tab-separated-values", "tsv", true);
- sMimeTypeMap.loadEntry("text/x-bibtex", "bib", true);
- sMimeTypeMap.loadEntry("text/x-boo", "boo", true);
- sMimeTypeMap.loadEntry("text/x-c++hdr", "h++", true);
- sMimeTypeMap.loadEntry("text/x-c++hdr", "hpp", true);
- sMimeTypeMap.loadEntry("text/x-c++hdr", "hxx", true);
- sMimeTypeMap.loadEntry("text/x-c++hdr", "hh", true);
- sMimeTypeMap.loadEntry("text/x-c++src", "c++", true);
- sMimeTypeMap.loadEntry("text/x-c++src", "cpp", true);
- sMimeTypeMap.loadEntry("text/x-c++src", "cxx", true);
- sMimeTypeMap.loadEntry("text/x-chdr", "h", true);
- sMimeTypeMap.loadEntry("text/x-component", "htc", true);
- sMimeTypeMap.loadEntry("text/x-csh", "csh", true);
- sMimeTypeMap.loadEntry("text/x-csrc", "c", true);
- sMimeTypeMap.loadEntry("text/x-dsrc", "d", true);
- sMimeTypeMap.loadEntry("text/x-haskell", "hs", true);
- sMimeTypeMap.loadEntry("text/x-java", "java", true);
- sMimeTypeMap.loadEntry("text/x-literate-haskell", "lhs", true);
- sMimeTypeMap.loadEntry("text/x-moc", "moc", true);
- sMimeTypeMap.loadEntry("text/x-pascal", "p", true);
- sMimeTypeMap.loadEntry("text/x-pascal", "pas", true);
- sMimeTypeMap.loadEntry("text/x-pcs-gcd", "gcd", true);
- sMimeTypeMap.loadEntry("text/x-setext", "etx", true);
- sMimeTypeMap.loadEntry("text/x-tcl", "tcl", true);
- sMimeTypeMap.loadEntry("text/x-tex", "tex", true);
- sMimeTypeMap.loadEntry("text/x-tex", "ltx", true);
- sMimeTypeMap.loadEntry("text/x-tex", "sty", true);
- sMimeTypeMap.loadEntry("text/x-tex", "cls", true);
- sMimeTypeMap.loadEntry("text/x-vcalendar", "vcs", true);
- sMimeTypeMap.loadEntry("text/x-vcard", "vcf", true);
- sMimeTypeMap.loadEntry("video/3gpp", "3gp", false);
- sMimeTypeMap.loadEntry("video/3gpp", "3g2", false);
- sMimeTypeMap.loadEntry("video/dl", "dl", false);
- sMimeTypeMap.loadEntry("video/dv", "dif", false);
- sMimeTypeMap.loadEntry("video/dv", "dv", false);
- sMimeTypeMap.loadEntry("video/fli", "fli", false);
- sMimeTypeMap.loadEntry("video/mpeg", "mpeg", false);
- sMimeTypeMap.loadEntry("video/mpeg", "mpg", false);
- sMimeTypeMap.loadEntry("video/mpeg", "mpe", false);
- sMimeTypeMap.loadEntry("video/mp4", "mp4", false);
- sMimeTypeMap.loadEntry("video/mpeg", "VOB", false);
- sMimeTypeMap.loadEntry("video/quicktime", "qt", false);
- sMimeTypeMap.loadEntry("video/quicktime", "mov", false);
- sMimeTypeMap.loadEntry("video/vnd.mpegurl", "mxu", false);
- sMimeTypeMap.loadEntry("video/x-la-asf", "lsf", false);
- sMimeTypeMap.loadEntry("video/x-la-asf", "lsx", false);
- sMimeTypeMap.loadEntry("video/x-mng", "mng", false);
- sMimeTypeMap.loadEntry("video/x-ms-asf", "asf", false);
- sMimeTypeMap.loadEntry("video/x-ms-asf", "asx", false);
- sMimeTypeMap.loadEntry("video/x-ms-wm", "wm", false);
- sMimeTypeMap.loadEntry("video/x-ms-wmv", "wmv", false);
- sMimeTypeMap.loadEntry("video/x-ms-wmx", "wmx", false);
- sMimeTypeMap.loadEntry("video/x-ms-wvx", "wvx", false);
- sMimeTypeMap.loadEntry("video/x-msvideo", "avi", false);
- sMimeTypeMap.loadEntry("video/x-sgi-movie", "movie", false);
- sMimeTypeMap.loadEntry("x-conference/x-cooltalk", "ice", false);
- }
-
- return sMimeTypeMap;
- }
-}
diff --git a/core/java/android/webkit/Network.java b/core/java/android/webkit/Network.java
deleted file mode 100644
index 74622b3..0000000
--- a/core/java/android/webkit/Network.java
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.content.Context;
-import android.net.http.*;
-import android.os.*;
-import android.util.Log;
-import android.util.Config;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.util.Map;
-
-import junit.framework.Assert;
-
-class Network {
-
- private static final String LOGTAG = "network";
-
- /**
- * Static instance of a Network object.
- */
- private static Network sNetwork;
-
- /**
- * Flag to store the state of platform notifications, for the case
- * when the Network object has not been constructed yet
- */
- private static boolean sPlatformNotifications;
-
- /**
- * Reference count for platform notifications as the network class is a
- * static and can exist over multiple activities, thus over multiple
- * onPause/onResume pairs.
- */
- private static int sPlatformNotificationEnableRefCount;
-
- /**
- * Proxy username if known (used for pre-emptive proxy authentication).
- */
- private String mProxyUsername;
-
- /**
- * Proxy password if known (used for pre-emptive proxy authentication).
- */
- private String mProxyPassword;
-
- /**
- * Network request queue (requests are added from the browser thread).
- */
- private RequestQueue mRequestQueue;
-
- /**
- * SSL error handler: takes care of synchronization of multiple async
- * loaders with SSL-related problems.
- */
- private SslErrorHandler mSslErrorHandler;
-
- /**
- * HTTP authentication handler: takes care of synchronization of HTTP
- * authentication requests.
- */
- private HttpAuthHandler mHttpAuthHandler;
-
- /**
- * @return The singleton instance of the network.
- */
- public static synchronized Network getInstance(Context context) {
- if (sNetwork == null) {
- // Note Context of the Application is used here, rather than
- // the what is passed in (usually a Context derived from an
- // Activity) so the intent receivers belong to the application
- // rather than an activity - this fixes the issue where
- // Activities are created and destroyed during the lifetime of
- // an Application
- sNetwork = new Network(context.getApplicationContext());
- if (sPlatformNotifications) {
- // Adjust the ref count before calling enable as it is already
- // taken into account when the static function was called
- // directly
- --sPlatformNotificationEnableRefCount;
- enablePlatformNotifications();
- }
- }
- return sNetwork;
- }
-
-
- /**
- * Enables data state and proxy tracking
- */
- public static void enablePlatformNotifications() {
- if (++sPlatformNotificationEnableRefCount == 1) {
- if (sNetwork != null) {
- sNetwork.mRequestQueue.enablePlatformNotifications();
- } else {
- sPlatformNotifications = true;
- }
- }
- }
-
- /**
- * If platform notifications are enabled, this should be called
- * from onPause() or onStop()
- */
- public static void disablePlatformNotifications() {
- if (--sPlatformNotificationEnableRefCount == 0) {
- if (sNetwork != null) {
- sNetwork.mRequestQueue.disablePlatformNotifications();
- } else {
- sPlatformNotifications = false;
- }
- }
- }
-
- /**
- * Creates a new Network object.
- * XXX: Must be created in the same thread as WebCore!!!!!
- */
- private Network(Context context) {
- if (Config.DEBUG) {
- Assert.assertTrue(Thread.currentThread().
- getName().equals(WebViewCore.THREAD_NAME));
- }
- mSslErrorHandler = new SslErrorHandler(this);
- mHttpAuthHandler = new HttpAuthHandler(this);
-
- mRequestQueue = new RequestQueue(context);
- }
-
- /**
- * Request a url from either the network or the file system.
- * @param url The url to load.
- * @param method The http method.
- * @param headers The http headers.
- * @param postData The body of the request.
- * @param loader A LoadListener for receiving the results of the request.
- * @param isHighPriority True if this is high priority request.
- * @return True if the request was successfully queued.
- */
- public boolean requestURL(String method,
- Map<String, String> headers,
- byte [] postData,
- LoadListener loader,
- boolean isHighPriority) {
-
- String url = loader.url();
-
- // Not a valid url, return false because we won't service the request!
- if (!URLUtil.isValidUrl(url)) {
- return false;
- }
-
- // asset, file system or data stream are handled in the other code path.
- // This only handles network request.
- if (URLUtil.isAssetUrl(url) || URLUtil.isFileUrl(url) ||
- URLUtil.isDataUrl(url)) {
- return false;
- }
-
- /* FIXME: this is lame. Pass an InputStream in, rather than
- making this lame one here */
- InputStream bodyProvider = null;
- int bodyLength = 0;
- if (postData != null) {
- bodyLength = postData.length;
- bodyProvider = new ByteArrayInputStream(postData);
- }
-
- RequestQueue q = mRequestQueue;
- if (loader.isSynchronous()) {
- q = new RequestQueue(loader.getContext(), 1);
- }
-
- RequestHandle handle = q.queueRequest(
- url, loader.getWebAddress(), method, headers, loader,
- bodyProvider, bodyLength, isHighPriority);
- loader.attachRequestHandle(handle);
-
- if (loader.isSynchronous()) {
- handle.waitUntilComplete();
- loader.loadSynchronousMessages();
- q.shutdown();
- }
- return true;
- }
-
- /**
- * @return True iff there is a valid proxy set.
- */
- public boolean isValidProxySet() {
- // The proxy host and port can be set within a different thread during
- // an Intent broadcast.
- synchronized (mRequestQueue) {
- return mRequestQueue.getProxyHost() != null;
- }
- }
-
- /**
- * Get the proxy hostname.
- * @return The proxy hostname obtained from the network queue and proxy
- * settings.
- */
- public String getProxyHostname() {
- return mRequestQueue.getProxyHost().getHostName();
- }
-
- /**
- * @return The proxy username or null if none.
- */
- public synchronized String getProxyUsername() {
- return mProxyUsername;
- }
-
- /**
- * Sets the proxy username.
- * @param proxyUsername Username to use when
- * connecting through the proxy.
- */
- public synchronized void setProxyUsername(String proxyUsername) {
- if (Config.DEBUG) {
- Assert.assertTrue(isValidProxySet());
- }
-
- mProxyUsername = proxyUsername;
- }
-
- /**
- * @return The proxy password or null if none.
- */
- public synchronized String getProxyPassword() {
- return mProxyPassword;
- }
-
- /**
- * Sets the proxy password.
- * @param proxyPassword Password to use when
- * connecting through the proxy.
- */
- public synchronized void setProxyPassword(String proxyPassword) {
- if (Config.DEBUG) {
- Assert.assertTrue(isValidProxySet());
- }
-
- mProxyPassword = proxyPassword;
- }
-
- /**
- * If we need to stop loading done in a handler (here, browser frame), we
- * send a message to the handler to stop loading, and remove all loaders
- * that share the same CallbackProxy in question from all local
- * handlers (such as ssl-error and http-authentication handler).
- * @param proxy The CallbackProxy responsible for cancelling the current
- * load.
- */
- public void resetHandlersAndStopLoading(BrowserFrame frame) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "Network.resetHandlersAndStopLoading()");
- }
-
- frame.stopLoading();
- mSslErrorHandler.reset(frame);
- mHttpAuthHandler.reset(frame);
- }
-
- /**
- * Saves the state of network handlers (user SSL and HTTP-authentication
- * preferences).
- * @param outState The out-state to save (write) to.
- * @return True iff succeeds.
- */
- public boolean saveState(Bundle outState) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "Network.saveState()");
- }
-
- return mSslErrorHandler.saveState(outState);
- }
-
- /**
- * Restores the state of network handlers (user SSL and HTTP-authentication
- * preferences).
- * @param inState The in-state to load (read) from.
- * @return True iff succeeds.
- */
- public boolean restoreState(Bundle inState) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "Network.restoreState()");
- }
-
- return mSslErrorHandler.restoreState(inState);
- }
-
- /**
- * Clears user SSL-error preference table.
- */
- public void clearUserSslPrefTable() {
- mSslErrorHandler.clear();
- }
-
- /**
- * Handles SSL error(s) on the way up to the user: the user must decide
- * whether errors should be ignored or not.
- * @param loader The loader that resulted in SSL errors.
- */
- public void handleSslErrorRequest(LoadListener loader) {
- if (Config.DEBUG) Assert.assertNotNull(loader);
- if (loader != null) {
- mSslErrorHandler.handleSslErrorRequest(loader);
- }
- }
-
- /**
- * Handles authentication requests on their way up to the user (the user
- * must provide credentials).
- * @param loader The loader that resulted in an HTTP
- * authentication request.
- */
- public void handleAuthRequest(LoadListener loader) {
- if (Config.DEBUG) Assert.assertNotNull(loader);
- if (loader != null) {
- mHttpAuthHandler.handleAuthRequest(loader);
- }
- }
-
- // Performance probe
- public void startTiming() {
- mRequestQueue.startTiming();
- }
-
- public void stopTiming() {
- mRequestQueue.stopTiming();
- }
-}
diff --git a/core/java/android/webkit/PerfChecker.java b/core/java/android/webkit/PerfChecker.java
deleted file mode 100644
index 8c5f86e..0000000
--- a/core/java/android/webkit/PerfChecker.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.os.SystemClock;
-import android.util.Log;
-
-class PerfChecker {
-
- private long mTime;
- private static final long mResponseThreshold = 2000; // 2s
-
- public PerfChecker() {
- if (false) {
- mTime = SystemClock.uptimeMillis();
- }
- }
-
- /**
- * @param what log string
- * Logs given string if mResponseThreshold time passed between either
- * instantiation or previous responseAlert call
- */
- public void responseAlert(String what) {
- if (false) {
- long upTime = SystemClock.uptimeMillis();
- long time = upTime - mTime;
- if (time > mResponseThreshold) {
- Log.w("webkit", what + " used " + time + " ms");
- }
- // Reset mTime, to permit reuse
- mTime = upTime;
- }
- }
-}
diff --git a/core/java/android/webkit/Plugin.java b/core/java/android/webkit/Plugin.java
deleted file mode 100644
index f83da99..0000000
--- a/core/java/android/webkit/Plugin.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import com.android.internal.R;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.webkit.WebView;
-
-/**
- * Represents a plugin (Java equivalent of the PluginPackageAndroid
- * C++ class in libs/WebKitLib/WebKit/WebCore/plugins/android/)
- */
-public class Plugin {
- public interface PreferencesClickHandler {
- public void handleClickEvent(Context context);
- }
-
- private String mName;
- private String mPath;
- private String mFileName;
- private String mDescription;
- private PreferencesClickHandler mHandler;
-
- public Plugin(String name,
- String path,
- String fileName,
- String description) {
- mName = name;
- mPath = path;
- mFileName = fileName;
- mDescription = description;
- mHandler = new DefaultClickHandler();
- }
-
- public String toString() {
- return mName;
- }
-
- public String getName() {
- return mName;
- }
-
- public String getPath() {
- return mPath;
- }
-
- public String getFileName() {
- return mFileName;
- }
-
- public String getDescription() {
- return mDescription;
- }
-
- public void setName(String name) {
- mName = name;
- }
-
- public void setPath(String path) {
- mPath = path;
- }
-
- public void setFileName(String fileName) {
- mFileName = fileName;
- }
-
- public void setDescription(String description) {
- mDescription = description;
- }
-
- public void setClickHandler(PreferencesClickHandler handler) {
- mHandler = handler;
- }
-
- /**
- * Invokes the click handler for this plugin.
- */
- public void dispatchClickEvent(Context context) {
- if (mHandler != null) {
- mHandler.handleClickEvent(context);
- }
- }
-
- /**
- * Default click handler. The plugins should implement their own.
- */
- private class DefaultClickHandler implements PreferencesClickHandler,
- DialogInterface.OnClickListener {
- private AlertDialog mDialog;
-
- public void handleClickEvent(Context context) {
- // Show a simple popup dialog containing the description
- // string of the plugin.
- if (mDialog == null) {
- mDialog = new AlertDialog.Builder(context)
- .setTitle(mName)
- .setMessage(mDescription)
- .setPositiveButton(R.string.ok, this)
- .setCancelable(false)
- .show();
- }
- }
-
- public void onClick(DialogInterface dialog, int which) {
- mDialog.dismiss();
- mDialog = null;
- }
- }
-}
diff --git a/core/java/android/webkit/PluginList.java b/core/java/android/webkit/PluginList.java
deleted file mode 100644
index a9d3d8c..0000000
--- a/core/java/android/webkit/PluginList.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.content.Context;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A simple list of initialized plugins. This list gets
- * populated when the plugins are initialized (at
- * browser startup, at the moment).
- */
-public class PluginList {
- private ArrayList<Plugin> mPlugins;
-
- /**
- * Public constructor. Initializes the list of plugins.
- */
- public PluginList() {
- mPlugins = new ArrayList<Plugin>();
- }
-
- /**
- * Returns the list of plugins as a java.util.List.
- */
- public synchronized List getList() {
- return mPlugins;
- }
-
- /**
- * Adds a plugin to the list.
- */
- public synchronized void addPlugin(Plugin plugin) {
- if (!mPlugins.contains(plugin)) {
- mPlugins.add(plugin);
- }
- }
-
- /**
- * Removes a plugin from the list.
- */
- public synchronized void removePlugin(Plugin plugin) {
- int location = mPlugins.indexOf(plugin);
- if (location != -1) {
- mPlugins.remove(location);
- }
- }
-
- /**
- * Clears the plugin list.
- */
- public synchronized void clear() {
- mPlugins.clear();
- }
-
- /**
- * Dispatches the click event to the appropriate plugin.
- */
- public synchronized void pluginClicked(Context context, int position) {
- try {
- Plugin plugin = mPlugins.get(position);
- plugin.dispatchClickEvent(context);
- } catch (IndexOutOfBoundsException e) {
- // This can happen if the list of plugins
- // gets changed while the pref menu is up.
- }
- }
-}
diff --git a/core/java/android/webkit/SslErrorHandler.java b/core/java/android/webkit/SslErrorHandler.java
deleted file mode 100644
index 115434a..0000000
--- a/core/java/android/webkit/SslErrorHandler.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import junit.framework.Assert;
-
-import android.net.http.SslError;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Config;
-import android.util.Log;
-
-import java.util.LinkedList;
-import java.util.ListIterator;
-
-/**
- * SslErrorHandler: class responsible for handling SSL errors. This class is
- * passed as a parameter to BrowserCallback.displaySslErrorDialog and is meant
- * to receive the user's response.
- */
-public class SslErrorHandler extends Handler {
- /* One problem here is that there may potentially be multiple SSL errors
- * coming from mutiple loaders. Therefore, we keep a queue of loaders
- * that have SSL-related problems and process errors one by one in the
- * order they were received.
- */
-
- private static final String LOGTAG = "network";
-
- /**
- * Network.
- */
- private Network mNetwork;
-
- /**
- * Queue of loaders that experience SSL-related problems.
- */
- private LinkedList<LoadListener> mLoaderQueue;
-
- /**
- * SSL error preference table.
- */
- private Bundle mSslPrefTable;
-
- // Message id for handling the response
- private final int HANDLE_RESPONSE = 100;
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case HANDLE_RESPONSE:
- handleSslErrorResponse(msg.arg1 == 1);
- fastProcessQueuedSslErrors();
- break;
- }
- }
-
- /**
- * Creates a new error handler with an empty loader queue.
- */
- /* package */ SslErrorHandler(Network network) {
- mNetwork = network;
-
- mLoaderQueue = new LinkedList<LoadListener>();
- mSslPrefTable = new Bundle();
- }
-
- /**
- * Saves this handler's state into a map.
- * @return True iff succeeds.
- */
- /* package */ boolean saveState(Bundle outState) {
- boolean success = (outState != null);
- if (success) {
- // TODO?
- outState.putBundle("ssl-error-handler", mSslPrefTable);
- }
-
- return success;
- }
-
- /**
- * Restores this handler's state from a map.
- * @return True iff succeeds.
- */
- /* package */ boolean restoreState(Bundle inState) {
- boolean success = (inState != null);
- if (success) {
- success = inState.containsKey("ssl-error-handler");
- if (success) {
- mSslPrefTable = inState.getBundle("ssl-error-handler");
- }
- }
-
- return success;
- }
-
- /**
- * Clears SSL error preference table.
- */
- /* package */ synchronized void clear() {
- mSslPrefTable.clear();
- }
-
- /**
- * Resets the SSL error handler, removes all loaders that
- * share the same BrowserFrame.
- */
- /* package */ synchronized void reset(BrowserFrame frame) {
- ListIterator<LoadListener> i = mLoaderQueue.listIterator(0);
- while (i.hasNext()) {
- LoadListener loader = i.next();
- if (frame == loader.getFrame()) {
- i.remove();
- }
- }
- }
-
- /**
- * Handles SSL error(s) on the way up to the user.
- */
- /* package */ synchronized void handleSslErrorRequest(LoadListener loader) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "SslErrorHandler.handleSslErrorRequest(): " +
- "url=" + loader.url());
- }
-
- if (!loader.cancelled()) {
- mLoaderQueue.offer(loader);
- if (loader == mLoaderQueue.peek()) {
- fastProcessQueuedSslErrors();
- }
- }
- }
-
- /**
- * Processes queued SSL-error confirmation requests in
- * a tight loop while there is no need to ask the user.
- */
- /* package */void fastProcessQueuedSslErrors() {
- while (processNextLoader());
- }
-
- /**
- * Processes the next loader in the queue.
- * @return True iff should proceed to processing the
- * following loader in the queue
- */
- private synchronized boolean processNextLoader() {
- LoadListener loader = mLoaderQueue.peek();
- if (loader != null) {
- // if this loader has been cancelled
- if (loader.cancelled()) {
- // go to the following loader in the queue
- return true;
- }
-
- SslError error = loader.sslError();
-
- if (Config.DEBUG) {
- Assert.assertNotNull(error);
- }
-
- int primary = error.getPrimaryError();
- String host = loader.host();
-
- if (Config.DEBUG) {
- Assert.assertTrue(host != null && primary != 0);
- }
-
- if (mSslPrefTable.containsKey(host)) {
- if (primary <= mSslPrefTable.getInt(host)) {
- handleSslErrorResponse(true);
- return true;
- }
- }
-
- // if we do not have information on record, ask
- // the user (display a dialog)
- CallbackProxy proxy = loader.getFrame().getCallbackProxy();
- proxy.onReceivedSslError(this, error);
- }
-
- // the queue must be empty, stop
- return false;
- }
-
- /**
- * Proceed with the SSL certificate.
- */
- public void proceed() {
- sendMessage(obtainMessage(HANDLE_RESPONSE, 1, 0));
- }
-
- /**
- * Cancel this request and all pending requests for the WebView that had
- * the error.
- */
- public void cancel() {
- sendMessage(obtainMessage(HANDLE_RESPONSE, 0, 0));
- }
-
- /**
- * Handles SSL error(s) on the way down from the user.
- */
- /* package */ synchronized void handleSslErrorResponse(boolean proceed) {
- LoadListener loader = mLoaderQueue.poll();
- if (Config.DEBUG) {
- Assert.assertNotNull(loader);
- }
-
- if (Config.LOGV) {
- Log.v(LOGTAG, "SslErrorHandler.handleSslErrorResponse():"
- + " proceed: " + proceed
- + " url:" + loader.url());
- }
-
- if (!loader.cancelled()) {
- if (proceed) {
- // update the user's SSL error preference table
- int primary = loader.sslError().getPrimaryError();
- String host = loader.host();
-
- if (Config.DEBUG) {
- Assert.assertTrue(host != null && primary != 0);
- }
- boolean hasKey = mSslPrefTable.containsKey(host);
- if (!hasKey ||
- primary > mSslPrefTable.getInt(host)) {
- mSslPrefTable.putInt(host, new Integer(primary));
- }
-
- loader.handleSslErrorResponse(proceed);
- } else {
- loader.handleSslErrorResponse(proceed);
- mNetwork.resetHandlersAndStopLoading(loader.getFrame());
- }
- }
- }
-}
diff --git a/core/java/android/webkit/StreamLoader.java b/core/java/android/webkit/StreamLoader.java
deleted file mode 100644
index 9098307..0000000
--- a/core/java/android/webkit/StreamLoader.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.net.http.EventHandler;
-import android.net.http.Headers;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Config;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-
-/**
- * This abstract class is used for all content loaders that rely on streaming
- * content into the rendering engine loading framework.
- *
- * The class implements a state machine to load the content into the frame in
- * a similar manor to the way content arrives from the network. The class uses
- * messages to move from one state to the next, which enables async. loading of
- * the streamed content.
- *
- * Classes that inherit from this class must implement two methods, the first
- * method is used to setup the InputStream and notify the loading framework if
- * it can load it's content. The other method allows the derived class to add
- * additional HTTP headers to the response.
- *
- * By default, content loaded with a StreamLoader is marked with a HTTP header
- * that indicates the content should not be cached.
- *
- */
-abstract class StreamLoader extends Handler {
-
- public static final String NO_STORE = "no-store";
-
- private static final int MSG_STATUS = 100; // Send status to loader
- private static final int MSG_HEADERS = 101; // Send headers to loader
- private static final int MSG_DATA = 102; // Send data to loader
- private static final int MSG_END = 103; // Send endData to loader
-
- protected LoadListener mHandler; // loader class
- protected InputStream mDataStream; // stream to read data from
- protected long mContentLength; // content length of data
- private byte [] mData; // buffer to pass data to loader with.
-
- /**
- * Constructor. Although this class calls the LoadListener, it only calls
- * the EventHandler Interface methods. LoadListener concrete class is used
- * to avoid the penality of calling an interface.
- *
- * @param loadlistener The LoadListener to call with the data.
- */
- StreamLoader(LoadListener loadlistener) {
- mHandler = loadlistener;
- }
-
- /**
- * This method is called when the derived class should setup mDataStream,
- * and call mHandler.status() to indicate that the load can occur. If it
- * fails to setup, it should still call status() with the error code.
- *
- * @return true if stream was successfully setup
- */
- protected abstract boolean setupStreamAndSendStatus();
-
- /**
- * This method is called when the headers are about to be sent to the
- * load framework. The derived class has the opportunity to add addition
- * headers.
- *
- * @param headers Map of HTTP headers that will be sent to the loader.
- */
- abstract protected void buildHeaders(Headers headers);
-
-
- /**
- * Calling this method starts the load of the content for this StreamLoader.
- * This method simply posts a message to send the status and returns
- * immediately.
- */
- public void load() {
- if (!mHandler.isSynchronous()) {
- sendMessage(obtainMessage(MSG_STATUS));
- } else {
- // Load the stream synchronously.
- if (setupStreamAndSendStatus()) {
- // We were able to open the stream, create the array
- // to pass data to the loader
- mData = new byte[8192];
- sendHeaders();
- while (!sendData());
- closeStreamAndSendEndData();
- mHandler.loadSynchronousMessages();
- }
- }
- }
-
- /* (non-Javadoc)
- * @see android.os.Handler#handleMessage(android.os.Message)
- */
- public void handleMessage(Message msg) {
- if (Config.DEBUG && mHandler.isSynchronous()) {
- throw new AssertionError();
- }
- switch(msg.what) {
- case MSG_STATUS:
- if (setupStreamAndSendStatus()) {
- // We were able to open the stream, create the array
- // to pass data to the loader
- mData = new byte[8192];
- sendMessage(obtainMessage(MSG_HEADERS));
- }
- break;
- case MSG_HEADERS:
- sendHeaders();
- sendMessage(obtainMessage(MSG_DATA));
- break;
- case MSG_DATA:
- if (sendData()) {
- sendMessage(obtainMessage(MSG_END));
- } else {
- sendMessage(obtainMessage(MSG_DATA));
- }
- break;
- case MSG_END:
- closeStreamAndSendEndData();
- break;
- default:
- super.handleMessage(msg);
- break;
- }
- }
-
- /**
- * Construct the headers and pass them to the EventHandler.
- */
- private void sendHeaders() {
- Headers headers = new Headers();
- if (mContentLength > 0) {
- headers.setContentLength(mContentLength);
- }
- headers.setCacheControl(NO_STORE);
- buildHeaders(headers);
- mHandler.headers(headers);
- }
-
- /**
- * Read data from the stream and pass it to the EventHandler.
- * If an error occurs reading the stream, then an error is sent to the
- * EventHandler, and moves onto the next state - end of data.
- * @return True if all the data has been read. False if sendData should be
- * called again.
- */
- private boolean sendData() {
- if (mDataStream != null) {
- try {
- int amount = mDataStream.read(mData);
- if (amount > 0) {
- mHandler.data(mData, amount);
- return false;
- }
- } catch (IOException ex) {
- mHandler.error(EventHandler.FILE_ERROR,
- ex.getMessage());
- }
- }
- return true;
- }
-
- /**
- * Close the stream and inform the EventHandler that load is complete.
- */
- private void closeStreamAndSendEndData() {
- if (mDataStream != null) {
- try {
- mDataStream.close();
- } catch (IOException ex) {
- // ignore.
- }
- }
- mHandler.endData();
- }
-
-}
diff --git a/core/java/android/webkit/TextDialog.java b/core/java/android/webkit/TextDialog.java
deleted file mode 100644
index c2620a5..0000000
--- a/core/java/android/webkit/TextDialog.java
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.shapes.RectShape;
-import android.os.Handler;
-import android.os.Message;
-import android.text.Editable;
-import android.text.InputFilter;
-import android.text.Selection;
-import android.text.Spannable;
-import android.text.TextPaint;
-import android.text.TextUtils;
-import android.text.method.MovementMethod;
-import android.text.method.PasswordTransformationMethod;
-import android.text.method.TextKeyListener;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewConfiguration;
-import android.widget.AbsoluteLayout.LayoutParams;
-import android.widget.ArrayAdapter;
-import android.widget.AutoCompleteTextView;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-
-/**
- * TextDialog is a specialized version of EditText used by WebView
- * to overlay html textfields (and textareas) to use our standard
- * text editing.
- */
-/* package */ class TextDialog extends AutoCompleteTextView {
-
- private WebView mWebView;
- private boolean mSingle;
- private int mWidthSpec;
- private int mHeightSpec;
- private int mNodePointer;
- // FIXME: This is a hack for blocking unmatched key ups, in particular
- // on the enter key. The method for blocking unmatched key ups prevents
- // the shift key from working properly.
- private boolean mGotEnterDown;
- // mScrollToAccommodateCursor being set to false prevents us from scrolling
- // the cursor on screen when using the trackball to select a textfield.
- private boolean mScrollToAccommodateCursor;
- private int mMaxLength;
- // Keep track of the text before the change so we know whether we actually
- // need to send down the DOM events.
- private String mPreChange;
- // Array to store the final character added in onTextChanged, so that its
- // KeyEvents may be determined.
- private char[] mCharacter = new char[1];
- // This is used to reset the length filter when on a textfield
- // with no max length.
- // FIXME: This can be replaced with TextView.NO_FILTERS if that
- // is made public/protected.
- private static final InputFilter[] NO_FILTERS = new InputFilter[0];
- // The time of the last enter down, so we know whether to perform a long
- // press.
- private long mDownTime;
-
- private boolean mTrackballDown = false;
- private static int LONGPRESS = 1;
- private Handler mHandler = new Handler() {
- public void handleMessage(Message msg) {
- if (msg.what == LONGPRESS) {
- if (mTrackballDown) {
- performLongClick();
- mTrackballDown = false;
- }
- }
- }
- };
-
- /**
- * Create a new TextDialog.
- * @param context The Context for this TextDialog.
- * @param webView The WebView that created this.
- */
- /* package */ TextDialog(Context context, WebView webView) {
- super(context);
- mWebView = webView;
- ShapeDrawable background = new ShapeDrawable(new RectShape());
- Paint shapePaint = background.getPaint();
- shapePaint.setStyle(Paint.Style.STROKE);
- ColorDrawable color = new ColorDrawable(Color.WHITE);
- Drawable[] array = new Drawable[2];
- array[0] = color;
- array[1] = background;
- LayerDrawable layers = new LayerDrawable(array);
- // Hide WebCore's text behind this and allow the WebView
- // to draw its own focusring.
- setBackgroundDrawable(layers);
- // Align the text better with the text behind it, so moving
- // off of the textfield will not appear to move the text.
- setPadding(3, 2, 0, 0);
- mMaxLength = -1;
- // Turn on subpixel text, and turn off kerning, so it better matches
- // the text in webkit.
- TextPaint paint = getPaint();
- int flags = paint.getFlags() | Paint.SUBPIXEL_TEXT_FLAG |
- Paint.ANTI_ALIAS_FLAG & ~Paint.DEV_KERN_TEXT_FLAG;
- paint.setFlags(flags);
- // Set the text color to black, regardless of the theme. This ensures
- // that other applications that use embedded WebViews will properly
- // display the text in textfields.
- setTextColor(Color.BLACK);
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- if (event.isSystem()) {
- return super.dispatchKeyEvent(event);
- }
- // Treat ACTION_DOWN and ACTION MULTIPLE the same
- boolean down = event.getAction() != KeyEvent.ACTION_UP;
- int keyCode = event.getKeyCode();
- Spannable text = (Spannable) getText();
- int oldLength = text.length();
- // Normally the delete key's dom events are sent via onTextChanged.
- // However, if the length is zero, the text did not change, so we
- // go ahead and pass the key down immediately.
- if (KeyEvent.KEYCODE_DEL == keyCode && 0 == oldLength) {
- sendDomEvent(event);
- return true;
- }
-
- // For single-line textfields, return key should not be handled
- // here. Instead, the WebView is passed the key up, so it may fire a
- // submit/onClick.
- // Center key should always be passed to a potential onClick
- if ((mSingle && KeyEvent.KEYCODE_ENTER == keyCode)
- || KeyEvent.KEYCODE_DPAD_CENTER == keyCode) {
- if (isPopupShowing()) {
- super.dispatchKeyEvent(event);
- return true;
- }
- if (down) {
- if (event.getRepeatCount() == 0) {
- mGotEnterDown = true;
- mDownTime = event.getEventTime();
- // Send the keydown when the up comes, so that we have
- // a chance to handle a long press.
- } else if (mGotEnterDown && event.getEventTime() - mDownTime >
- ViewConfiguration.getLongPressTimeout()) {
- performLongClick();
- mGotEnterDown = false;
- }
- } else if (mGotEnterDown) {
- mGotEnterDown = false;
- if (KeyEvent.KEYCODE_DPAD_CENTER == keyCode) {
- mWebView.shortPressOnTextField();
- return true;
- }
- // If we reached here, then this is a single line textfield, and
- // the user pressed ENTER. In this case, we want to hide the
- // soft input method.
- InputMethodManager.getInstance(mContext)
- .hideSoftInputFromWindow(getWindowToken(), 0);
- sendDomEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
- sendDomEvent(event);
- }
- return true;
- }
- // Ensure there is a layout so arrow keys are handled properly.
- if (getLayout() == null) {
- measure(mWidthSpec, mHeightSpec);
- }
- int oldStart = Selection.getSelectionStart(text);
- int oldEnd = Selection.getSelectionEnd(text);
-
- boolean maxedOut = mMaxLength != -1 && oldLength == mMaxLength;
- // If we are at max length, and there is a selection rather than a
- // cursor, we need to store the text to compare later, since the key
- // may have changed the string.
- String oldText;
- if (maxedOut && oldEnd != oldStart) {
- oldText = text.toString();
- } else {
- oldText = "";
- }
- if (super.dispatchKeyEvent(event)) {
- // If the TextDialog handled the key it was either an alphanumeric
- // key, a delete, or a movement within the text. All of those are
- // ok to pass to javascript.
-
- // UNLESS there is a max length determined by the html. In that
- // case, if the string was already at the max length, an
- // alphanumeric key will be erased by the LengthFilter,
- // so do not pass down to javascript, and instead
- // return true. If it is an arrow key or a delete key, we can go
- // ahead and pass it down.
- boolean isArrowKey;
- switch(keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- isArrowKey = true;
- break;
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_ENTER:
- // For multi-line text boxes, newlines and dpad center will
- // trigger onTextChanged for key down (which will send both
- // key up and key down) but not key up.
- mGotEnterDown = true;
- default:
- isArrowKey = false;
- break;
- }
- if (maxedOut && !isArrowKey && keyCode != KeyEvent.KEYCODE_DEL) {
- if (oldEnd == oldStart) {
- // Return true so the key gets dropped.
- mScrollToAccommodateCursor = true;
- return true;
- } else if (!oldText.equals(getText().toString())) {
- // FIXME: This makes the text work properly, but it
- // does not pass down the key event, so it may not
- // work for a textfield that has the type of
- // behavior of GoogleSuggest. That said, it is
- // unlikely that a site would combine the two in
- // one textfield.
- Spannable span = (Spannable) getText();
- int newStart = Selection.getSelectionStart(span);
- int newEnd = Selection.getSelectionEnd(span);
- mWebView.replaceTextfieldText(0, oldLength, span.toString(),
- newStart, newEnd);
- mScrollToAccommodateCursor = true;
- return true;
- }
- }
- if (isArrowKey) {
- // Arrow key does not change the text, but we still want to send
- // the DOM events.
- sendDomEvent(event);
- }
- mScrollToAccommodateCursor = true;
- return true;
- }
- // FIXME: TextViews return false for up and down key events even though
- // they change the selection. Since we don't want the get out of sync
- // with WebCore's notion of the current selection, reset the selection
- // to what it was before the key event.
- Selection.setSelection(text, oldStart, oldEnd);
- // Ignore the key up event for newlines or dpad center. This prevents
- // multiple newlines in the native textarea.
- if (mGotEnterDown && !down) {
- return true;
- }
- // if it is a navigation key, pass it to WebView
- if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT
- || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT
- || keyCode == KeyEvent.KEYCODE_DPAD_UP
- || keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
- // WebView check the trackballtime in onKeyDown to avoid calling
- // native from both trackball and key handling. As this is called
- // from TextDialog, we always want WebView to check with native.
- // Reset trackballtime to ensure it.
- mWebView.resetTrackballTime();
- return down ? mWebView.onKeyDown(keyCode, event) : mWebView
- .onKeyUp(keyCode, event);
- }
- return false;
- }
-
- /**
- * Create a fake touch up event at (x,y) with respect to this TextDialog.
- * This is used by WebView to act as though a touch event which happened
- * before we placed the TextDialog actually hit it, so that it can place
- * the cursor accordingly.
- */
- /* package */ void fakeTouchEvent(float x, float y) {
- // We need to ensure that there is a Layout, since the Layout is used
- // in determining where to place the cursor.
- if (getLayout() == null) {
- measure(mWidthSpec, mHeightSpec);
- }
- // Create a fake touch up, which is used to place the cursor.
- MotionEvent ev = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP,
- x, y, 0);
- onTouchEvent(ev);
- ev.recycle();
- }
-
- /**
- * Determine whether this TextDialog currently represents the node
- * represented by ptr.
- * @param ptr Pointer to a node to compare to.
- * @return boolean Whether this TextDialog already represents the node
- * pointed to by ptr.
- */
- /* package */ boolean isSameTextField(int ptr) {
- return ptr == mNodePointer;
- }
-
- @Override
- public boolean onPreDraw() {
- if (getLayout() == null) {
- measure(mWidthSpec, mHeightSpec);
- }
- return super.onPreDraw();
- }
-
- @Override
- protected void onTextChanged(CharSequence s,int start,int before,int count){
- super.onTextChanged(s, start, before, count);
- String postChange = s.toString();
- // Prevent calls to setText from invoking onTextChanged (since this will
- // mean we are on a different textfield). Also prevent the change when
- // going from a textfield with a string of text to one with a smaller
- // limit on text length from registering the onTextChanged event.
- if (mPreChange == null || mPreChange.equals(postChange) ||
- (mMaxLength > -1 && mPreChange.length() > mMaxLength &&
- mPreChange.substring(0, mMaxLength).equals(postChange))) {
- return;
- }
- mPreChange = postChange;
- // This was simply a delete or a cut, so just delete the
- // selection.
- if (before > 0 && 0 == count) {
- mWebView.deleteSelection(start, start + before);
- // For this and all changes to the text, update our cache
- updateCachedTextfield();
- return;
- }
- // Find the last character being replaced. If it can be represented by
- // events, we will pass them to native (after replacing the beginning
- // of the changed text), so we can see javascript events.
- // Otherwise, replace the text being changed (including the last
- // character) in the textfield.
- TextUtils.getChars(s, start + count - 1, start + count, mCharacter, 0);
- KeyCharacterMap kmap =
- KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD);
- KeyEvent[] events = kmap.getEvents(mCharacter);
- boolean cannotUseKeyEvents = null == events;
- int charactersFromKeyEvents = cannotUseKeyEvents ? 0 : 1;
- if (count > 1 || cannotUseKeyEvents) {
- String replace = s.subSequence(start,
- start + count - charactersFromKeyEvents).toString();
- mWebView.replaceTextfieldText(start, start + before, replace,
- start + count - charactersFromKeyEvents,
- start + count - charactersFromKeyEvents);
- } else {
- // This corrects the selection which may have been affected by the
- // trackball or auto-correct.
- mWebView.setSelection(start, start + before);
- }
- updateCachedTextfield();
- if (cannotUseKeyEvents) {
- return;
- }
- int length = events.length;
- for (int i = 0; i < length; i++) {
- // We never send modifier keys to native code so don't send them
- // here either.
- if (!KeyEvent.isModifierKey(events[i].getKeyCode())) {
- sendDomEvent(events[i]);
- }
- }
- }
-
- @Override
- public boolean onTrackballEvent(MotionEvent event) {
- if (isPopupShowing()) {
- return super.onTrackballEvent(event);
- }
- int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- if (!mTrackballDown) {
- mTrackballDown = true;
- mHandler.sendEmptyMessageDelayed(LONGPRESS,
- ViewConfiguration.getLongPressTimeout());
- }
- return true;
- case MotionEvent.ACTION_UP:
- if (mTrackballDown) {
- mWebView.shortPressOnTextField();
- mTrackballDown = false;
- mHandler.removeMessages(LONGPRESS);
- }
- return true;
- case MotionEvent.ACTION_CANCEL:
- mTrackballDown = false;
- return true;
- case MotionEvent.ACTION_MOVE:
- // fall through
- }
- Spannable text = (Spannable) getText();
- MovementMethod move = getMovementMethod();
- if (move != null && getLayout() != null &&
- move.onTrackballEvent(this, text, event)) {
- // Need to pass down the selection, which has changed.
- // FIXME: This should work, but does not, so we set the selection
- // in onTextChanged.
- //int start = Selection.getSelectionStart(text);
- //int end = Selection.getSelectionEnd(text);
- //mWebView.setSelection(start, end);
- return true;
- }
- // If the user is in a textfield, and the movement method is not
- // handling the trackball events, it means they are at the end of the
- // field and continuing to move the trackball. In this case, we should
- // not scroll the cursor on screen bc the user may be attempting to
- // scroll the page, possibly in the opposite direction of the cursor.
- mScrollToAccommodateCursor = false;
- return false;
- }
-
- /**
- * Remove this TextDialog from its host WebView, and return
- * focus to the host.
- */
- /* package */ void remove() {
- // hide the soft keyboard when the edit text is out of focus
- InputMethodManager.getInstance(mContext).hideSoftInputFromWindow(
- getWindowToken(), 0);
- mHandler.removeMessages(LONGPRESS);
- mWebView.removeView(this);
- mWebView.requestFocus();
- mScrollToAccommodateCursor = false;
- }
-
- /* package */ void enableScrollOnScreen(boolean enable) {
- mScrollToAccommodateCursor = enable;
- }
-
- /* package */ void bringIntoView() {
- if (getLayout() != null) {
- bringPointIntoView(Selection.getSelectionEnd(getText()));
- }
- }
-
- @Override
- public boolean requestRectangleOnScreen(Rect rectangle) {
- if (mScrollToAccommodateCursor) {
- return super.requestRectangleOnScreen(rectangle);
- }
- return false;
- }
-
- /**
- * Send the DOM events for the specified event.
- * @param event KeyEvent to be translated into a DOM event.
- */
- private void sendDomEvent(KeyEvent event) {
- mWebView.passToJavaScript(getText().toString(), event);
- }
-
- /**
- * Always use this instead of setAdapter, as this has features specific to
- * the TextDialog.
- */
- public void setAdapterCustom(AutoCompleteAdapter adapter) {
- if (adapter != null) {
- setInputType(EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE);
- adapter.setTextView(this);
- }
- super.setAdapter(adapter);
- }
-
- /**
- * This is a special version of ArrayAdapter which changes its text size
- * to match the text size of its host TextView.
- */
- public static class AutoCompleteAdapter extends ArrayAdapter<String> {
- private TextView mTextView;
-
- public AutoCompleteAdapter(Context context, ArrayList<String> entries) {
- super(context, com.android.internal.R.layout
- .search_dropdown_item_1line, entries);
- }
-
- /**
- * {@inheritDoc}
- */
- public View getView(int position, View convertView, ViewGroup parent) {
- TextView tv =
- (TextView) super.getView(position, convertView, parent);
- if (tv != null && mTextView != null) {
- tv.setTextSize(mTextView.getTextSize());
- }
- return tv;
- }
-
- /**
- * Set the TextView so we can match its text size.
- */
- private void setTextView(TextView tv) {
- mTextView = tv;
- }
- }
-
- /**
- * Determine whether to use the system-wide password disguising method,
- * or to use none.
- * @param inPassword True if the textfield is a password field.
- */
- /* package */ void setInPassword(boolean inPassword) {
- PasswordTransformationMethod method;
- if (inPassword) {
- method = PasswordTransformationMethod.getInstance();
- setInputType(EditorInfo.TYPE_CLASS_TEXT|EditorInfo.
- TYPE_TEXT_VARIATION_PASSWORD);
- } else {
- method = null;
- }
- setTransformationMethod(method);
- }
-
- /* package */ void setMaxLength(int maxLength) {
- mMaxLength = maxLength;
- if (-1 == maxLength) {
- setFilters(NO_FILTERS);
- } else {
- setFilters(new InputFilter[] {
- new InputFilter.LengthFilter(maxLength) });
- }
- }
-
- /**
- * Set the pointer for this node so it can be determined which node this
- * TextDialog represents.
- * @param ptr Integer representing the pointer to the node which this
- * TextDialog represents.
- */
- /* package */ void setNodePointer(int ptr) {
- mNodePointer = ptr;
- }
-
- /**
- * Determine the position and size of TextDialog, and add it to the
- * WebView's view heirarchy. All parameters are presumed to be in
- * view coordinates. Also requests Focus and sets the cursor to not
- * request to be in view.
- * @param x x-position of the textfield.
- * @param y y-position of the textfield.
- * @param width width of the textfield.
- * @param height height of the textfield.
- */
- /* package */ void setRect(int x, int y, int width, int height) {
- LayoutParams lp = (LayoutParams) getLayoutParams();
- if (null == lp) {
- lp = new LayoutParams(width, height, x, y);
- } else {
- lp.x = x;
- lp.y = y;
- lp.width = width;
- lp.height = height;
- }
- if (getParent() == null) {
- mWebView.addView(this, lp);
- } else {
- setLayoutParams(lp);
- }
- // Set up a measure spec so a layout can always be recreated.
- mWidthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
- mHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
- requestFocus();
- }
-
- /**
- * Set whether this is a single-line textfield or a multi-line textarea.
- * Textfields scroll horizontally, and do not handle the enter key.
- * Textareas behave oppositely.
- * Do NOT call this after calling setInPassword(true). This will result in
- * removing the password input type.
- */
- public void setSingleLine(boolean single) {
- if (mSingle != single) {
- TextKeyListener.Capitalize cap;
- int inputType = EditorInfo.TYPE_CLASS_TEXT;
- if (single) {
- cap = TextKeyListener.Capitalize.NONE;
- } else {
- cap = TextKeyListener.Capitalize.SENTENCES;
- inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
- }
- setKeyListener(TextKeyListener.getInstance(!single, cap));
- mSingle = single;
- setHorizontallyScrolling(single);
- setInputType(inputType);
- }
- }
-
- /**
- * Set the text for this TextDialog, and set the selection to (start, end)
- * @param text Text to go into this TextDialog.
- * @param start Beginning of the selection.
- * @param end End of the selection.
- */
- /* package */ void setText(CharSequence text, int start, int end) {
- mPreChange = text.toString();
- setText(text);
- Spannable span = (Spannable) getText();
- int length = span.length();
- if (end > length) {
- end = length;
- }
- if (start < 0) {
- start = 0;
- } else if (start > length) {
- start = length;
- }
- Selection.setSelection(span, start, end);
- }
-
- /**
- * Set the text to the new string, but use the old selection, making sure
- * to keep it within the new string.
- * @param text The new text to place in the textfield.
- */
- /* package */ void setTextAndKeepSelection(String text) {
- mPreChange = text.toString();
- Editable edit = (Editable) getText();
- edit.replace(0, edit.length(), text);
- updateCachedTextfield();
- }
-
- /**
- * Update the cache to reflect the current text.
- */
- /* package */ void updateCachedTextfield() {
- mWebView.updateCachedTextfield(getText().toString());
- }
-}
diff --git a/core/java/android/webkit/URLUtil.java b/core/java/android/webkit/URLUtil.java
deleted file mode 100644
index 0e8144e..0000000
--- a/core/java/android/webkit/URLUtil.java
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import java.io.UnsupportedEncodingException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import android.net.Uri;
-import android.net.ParseException;
-import android.net.WebAddress;
-import android.util.Config;
-import android.util.Log;
-
-public final class URLUtil {
-
- private static final String LOGTAG = "webkit";
-
- static final String ASSET_BASE = "file:///android_asset/";
- static final String FILE_BASE = "file://";
- static final String PROXY_BASE = "file:///cookieless_proxy/";
-
- /**
- * Cleans up (if possible) user-entered web addresses
- */
- public static String guessUrl(String inUrl) {
-
- String retVal = inUrl;
- WebAddress webAddress;
-
- Log.v(LOGTAG, "guessURL before queueRequest: " + inUrl);
-
- if (inUrl.length() == 0) return inUrl;
- if (inUrl.startsWith("about:")) return inUrl;
- // Do not try to interpret data scheme URLs
- if (inUrl.startsWith("data:")) return inUrl;
- // Do not try to interpret file scheme URLs
- if (inUrl.startsWith("file:")) return inUrl;
- // Do not try to interpret javascript scheme URLs
- if (inUrl.startsWith("javascript:")) return inUrl;
-
- // bug 762454: strip period off end of url
- if (inUrl.endsWith(".") == true) {
- inUrl = inUrl.substring(0, inUrl.length() - 1);
- }
-
- try {
- webAddress = new WebAddress(inUrl);
- } catch (ParseException ex) {
-
- if (Config.LOGV) {
- Log.v(LOGTAG, "smartUrlFilter: failed to parse url = " + inUrl);
- }
- return retVal;
- }
-
- // Check host
- if (webAddress.mHost.indexOf('.') == -1) {
- // no dot: user probably entered a bare domain. try .com
- webAddress.mHost = "www." + webAddress.mHost + ".com";
- }
- return webAddress.toString();
- }
-
- public static String composeSearchUrl(String inQuery, String template,
- String queryPlaceHolder) {
- int placeHolderIndex = template.indexOf(queryPlaceHolder);
- if (placeHolderIndex < 0) {
- return null;
- }
-
- String query;
- StringBuilder buffer = new StringBuilder();
- buffer.append(template.substring(0, placeHolderIndex));
-
- try {
- query = java.net.URLEncoder.encode(inQuery, "utf-8");
- buffer.append(query);
- } catch (UnsupportedEncodingException ex) {
- return null;
- }
-
- buffer.append(template.substring(
- placeHolderIndex + queryPlaceHolder.length()));
-
- return buffer.toString();
- }
-
- public static byte[] decode(byte[] url) throws IllegalArgumentException {
- if (url.length == 0) {
- return new byte[0];
- }
-
- // Create a new byte array with the same length to ensure capacity
- byte[] tempData = new byte[url.length];
-
- int tempCount = 0;
- for (int i = 0; i < url.length; i++) {
- byte b = url[i];
- if (b == '%') {
- if (url.length - i > 2) {
- b = (byte) (parseHex(url[i + 1]) * 16
- + parseHex(url[i + 2]));
- i += 2;
- } else {
- throw new IllegalArgumentException("Invalid format");
- }
- }
- tempData[tempCount++] = b;
- }
- byte[] retData = new byte[tempCount];
- System.arraycopy(tempData, 0, retData, 0, tempCount);
- return retData;
- }
-
- private static int parseHex(byte b) {
- if (b >= '0' && b <= '9') return (b - '0');
- if (b >= 'A' && b <= 'F') return (b - 'A' + 10);
- if (b >= 'a' && b <= 'f') return (b - 'a' + 10);
-
- throw new IllegalArgumentException("Invalid hex char '" + b + "'");
- }
-
- /**
- * @return True iff the url is an asset file.
- */
- public static boolean isAssetUrl(String url) {
- return (null != url) && url.startsWith(ASSET_BASE);
- }
-
- /**
- * @return True iff the url is an proxy url to allow cookieless network
- * requests from a file url.
- * @deprecated Cookieless proxy is no longer supported.
- */
- public static boolean isCookielessProxyUrl(String url) {
- return (null != url) && url.startsWith(PROXY_BASE);
- }
-
- /**
- * @return True iff the url is a local file.
- */
- public static boolean isFileUrl(String url) {
- return (null != url) && (url.startsWith(FILE_BASE) &&
- !url.startsWith(ASSET_BASE) &&
- !url.startsWith(PROXY_BASE));
- }
-
- /**
- * @return True iff the url is an about: url.
- */
- public static boolean isAboutUrl(String url) {
- return (null != url) && url.startsWith("about:");
- }
-
- /**
- * @return True iff the url is a data: url.
- */
- public static boolean isDataUrl(String url) {
- return (null != url) && url.startsWith("data:");
- }
-
- /**
- * @return True iff the url is a javascript: url.
- */
- public static boolean isJavaScriptUrl(String url) {
- return (null != url) && url.startsWith("javascript:");
- }
-
- /**
- * @return True iff the url is an http: url.
- */
- public static boolean isHttpUrl(String url) {
- return (null != url) &&
- (url.length() > 6) &&
- url.substring(0, 7).equalsIgnoreCase("http://");
- }
-
- /**
- * @return True iff the url is an https: url.
- */
- public static boolean isHttpsUrl(String url) {
- return (null != url) &&
- (url.length() > 7) &&
- url.substring(0, 8).equalsIgnoreCase("https://");
- }
-
- /**
- * @return True iff the url is a network url.
- */
- public static boolean isNetworkUrl(String url) {
- if (url == null || url.length() == 0) {
- return false;
- }
- return isHttpUrl(url) || isHttpsUrl(url);
- }
-
- /**
- * @return True iff the url is a content: url.
- */
- public static boolean isContentUrl(String url) {
- return (null != url) && url.startsWith("content:");
- }
-
- /**
- * @return True iff the url is valid.
- */
- public static boolean isValidUrl(String url) {
- if (url == null || url.length() == 0) {
- return false;
- }
-
- return (isAssetUrl(url) ||
- isFileUrl(url) ||
- isAboutUrl(url) ||
- isHttpUrl(url) ||
- isHttpsUrl(url) ||
- isJavaScriptUrl(url) ||
- isContentUrl(url));
- }
-
- /**
- * Strips the url of the anchor.
- */
- public static String stripAnchor(String url) {
- int anchorIndex = url.indexOf('#');
- if (anchorIndex != -1) {
- return url.substring(0, anchorIndex);
- }
- return url;
- }
-
- /**
- * Guesses canonical filename that a download would have, using
- * the URL and contentDisposition. File extension, if not defined,
- * is added based on the mimetype
- * @param url Url to the content
- * @param contentDisposition Content-Disposition HTTP header or null
- * @param mimeType Mime-type of the content or null
- *
- * @return suggested filename
- */
- public static final String guessFileName(
- String url,
- String contentDisposition,
- String mimeType) {
- String filename = null;
- String extension = null;
-
- // If we couldn't do anything with the hint, move toward the content disposition
- if (filename == null && contentDisposition != null) {
- filename = parseContentDisposition(contentDisposition);
- if (filename != null) {
- int index = filename.lastIndexOf('/') + 1;
- if (index > 0) {
- filename = filename.substring(index);
- }
- }
- }
-
- // If all the other http-related approaches failed, use the plain uri
- if (filename == null) {
- String decodedUrl = Uri.decode(url);
- if (decodedUrl != null) {
- int queryIndex = decodedUrl.indexOf('?');
- // If there is a query string strip it, same as desktop browsers
- if (queryIndex > 0) {
- decodedUrl = decodedUrl.substring(0, queryIndex);
- }
- if (!decodedUrl.endsWith("/")) {
- int index = decodedUrl.lastIndexOf('/') + 1;
- if (index > 0) {
- filename = decodedUrl.substring(index);
- }
- }
- }
- }
-
- // Finally, if couldn't get filename from URI, get a generic filename
- if (filename == null) {
- filename = "downloadfile";
- }
-
- // Split filename between base and extension
- // Add an extension if filename does not have one
- int dotIndex = filename.indexOf('.');
- if (dotIndex < 0) {
- if (mimeType != null) {
- extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);
- if (extension != null) {
- extension = "." + extension;
- }
- }
- if (extension == null) {
- if (mimeType != null && mimeType.toLowerCase().startsWith("text/")) {
- if (mimeType.equalsIgnoreCase("text/html")) {
- extension = ".html";
- } else {
- extension = ".txt";
- }
- } else {
- extension = ".bin";
- }
- }
- } else {
- if (mimeType != null) {
- // Compare the last segment of the extension against the mime type.
- // If there's a mismatch, discard the entire extension.
- int lastDotIndex = filename.lastIndexOf('.');
- String typeFromExt = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
- filename.substring(lastDotIndex + 1));
- if (typeFromExt != null && !typeFromExt.equalsIgnoreCase(mimeType)) {
- extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);
- if (extension != null) {
- extension = "." + extension;
- }
- }
- }
- if (extension == null) {
- extension = filename.substring(dotIndex);
- }
- filename = filename.substring(0, dotIndex);
- }
-
- return filename + extension;
- }
-
- /** Regex used to parse content-disposition headers */
- private static final Pattern CONTENT_DISPOSITION_PATTERN =
- Pattern.compile("attachment;\\s*filename\\s*=\\s*\"([^\"]*)\"");
-
- /*
- * Parse the Content-Disposition HTTP Header. The format of the header
- * is defined here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html
- * This header provides a filename for content that is going to be
- * downloaded to the file system. We only support the attachment type.
- */
- private static String parseContentDisposition(String contentDisposition) {
- try {
- Matcher m = CONTENT_DISPOSITION_PATTERN.matcher(contentDisposition);
- if (m.find()) {
- return m.group(1);
- }
- } catch (IllegalStateException ex) {
- // This function is defined as returning null when it can't parse the header
- }
- return null;
- }
-}
diff --git a/core/java/android/webkit/UrlInterceptHandler.java b/core/java/android/webkit/UrlInterceptHandler.java
deleted file mode 100644
index e1c9d61..0000000
--- a/core/java/android/webkit/UrlInterceptHandler.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.webkit.CacheManager.CacheResult;
-import java.util.Map;
-
-public interface UrlInterceptHandler {
-
- /**
- * Given an URL, returns the CacheResult which contains the
- * surrogate response for the request, or null if the handler is
- * not interested.
- *
- * @param url URL string.
- * @param headers The headers associated with the request. May be null.
- * @return The CacheResult containing the surrogate response.
- */
- public CacheResult service(String url, Map<String, String> headers);
-}
diff --git a/core/java/android/webkit/UrlInterceptRegistry.java b/core/java/android/webkit/UrlInterceptRegistry.java
deleted file mode 100644
index a218191..0000000
--- a/core/java/android/webkit/UrlInterceptRegistry.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.webkit.CacheManager.CacheResult;
-import android.webkit.UrlInterceptHandler;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.Map;
-
-public final class UrlInterceptRegistry {
-
- private final static String LOGTAG = "intercept";
-
- private static boolean mDisabled = false;
-
- private static LinkedList mHandlerList;
-
- private static synchronized LinkedList getHandlers() {
- if(mHandlerList == null)
- mHandlerList = new LinkedList<UrlInterceptHandler>();
- return mHandlerList;
- }
-
- /**
- * set the flag to control whether url intercept is enabled or disabled
- *
- * @param disabled true to disable the cache
- */
- public static synchronized void setUrlInterceptDisabled(boolean disabled) {
- mDisabled = disabled;
- }
-
- /**
- * get the state of the url intercept, enabled or disabled
- *
- * @return return if it is disabled
- */
- public static synchronized boolean urlInterceptDisabled() {
- return mDisabled;
- }
-
- /**
- * Register a new UrlInterceptHandler. This handler will be called
- * before any that were previously registered.
- *
- * @param handler The new UrlInterceptHandler object
- * @return true if the handler was not previously registered.
- */
- public static synchronized boolean registerHandler(
- UrlInterceptHandler handler) {
- if (!getHandlers().contains(handler)) {
- getHandlers().addFirst(handler);
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Unregister a previously registered UrlInterceptHandler.
- *
- * @param handler A previously registered UrlInterceptHandler.
- * @return true if the handler was found and removed from the list.
- */
- public static synchronized boolean unregisterHandler(
- UrlInterceptHandler handler) {
- return getHandlers().remove(handler);
- }
-
- /**
- * Given an url, returns the CacheResult of the first
- * UrlInterceptHandler interested, or null if none are.
- *
- * @return A CacheResult containing surrogate content.
- */
- public static synchronized CacheResult getSurrogate(
- String url, Map<String, String> headers) {
- if (urlInterceptDisabled())
- return null;
- Iterator iter = getHandlers().listIterator();
- while (iter.hasNext()) {
- UrlInterceptHandler handler = (UrlInterceptHandler) iter.next();
- CacheResult result = handler.service(url, headers);
- if (result != null) {
- return result;
- }
- }
- return null;
- }
-}
diff --git a/core/java/android/webkit/WebBackForwardList.java b/core/java/android/webkit/WebBackForwardList.java
deleted file mode 100644
index 9dea5ec..0000000
--- a/core/java/android/webkit/WebBackForwardList.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.util.Config;
-import java.io.Serializable;
-import java.util.ArrayList;
-
-/**
- * This class contains the back/forward list for a WebView.
- * WebView.copyBackForwardList() will return a copy of this class used to
- * inspect the entries in the list.
- */
-public class WebBackForwardList implements Cloneable, Serializable {
- // Current position in the list.
- private int mCurrentIndex;
- // ArrayList of WebHistoryItems for maintaining our copy.
- private ArrayList<WebHistoryItem> mArray;
- // Flag to indicate that the list is invalid
- private boolean mClearPending;
-
- /**
- * Construct a back/forward list used by clients of WebView.
- */
- /*package*/ WebBackForwardList() {
- mCurrentIndex = -1;
- mArray = new ArrayList<WebHistoryItem>();
- }
-
- /**
- * Return the current history item. This method returns null if the list is
- * empty.
- * @return The current history item.
- */
- public synchronized WebHistoryItem getCurrentItem() {
- return getItemAtIndex(mCurrentIndex);
- }
-
- /**
- * Get the index of the current history item. This index can be used to
- * directly index into the array list.
- * @return The current index from 0...n or -1 if the list is empty.
- */
- public synchronized int getCurrentIndex() {
- return mCurrentIndex;
- }
-
- /**
- * Get the history item at the given index. The index range is from 0...n
- * where 0 is the first item and n is the last item.
- * @param index The index to retrieve.
- */
- public synchronized WebHistoryItem getItemAtIndex(int index) {
- if (index < 0 || index >= getSize()) {
- return null;
- }
- return mArray.get(index);
- }
-
- /**
- * Get the total size of the back/forward list.
- * @return The size of the list.
- */
- public synchronized int getSize() {
- return mArray.size();
- }
-
- /**
- * Mark the back/forward list as having a pending clear. This is used on the
- * UI side to mark the list as being invalid during the clearHistory method.
- */
- /*package*/ synchronized void setClearPending() {
- mClearPending = true;
- }
-
- /**
- * Return the status of the clear flag. This is used on the UI side to
- * determine if the list is valid for checking things like canGoBack.
- */
- /*package*/ synchronized boolean getClearPending() {
- return mClearPending;
- }
-
- /**
- * Add a new history item to the list. This will remove all items after the
- * current item and append the new item to the end of the list. Called from
- * the WebCore thread only. Synchronized because the UI thread may be
- * reading the array or the current index.
- * @param item A new history item.
- */
- /*package*/ synchronized void addHistoryItem(WebHistoryItem item) {
- // Update the current position because we are going to add the new item
- // in that slot.
- ++mCurrentIndex;
- // If the current position is not at the end, remove all history items
- // after the current item.
- final int size = mArray.size();
- final int newPos = mCurrentIndex;
- if (newPos != size) {
- for (int i = size - 1; i >= newPos; i--) {
- final WebHistoryItem h = mArray.remove(i);
- }
- }
- // Add the item to the list.
- mArray.add(item);
- }
-
- /**
- * Clear the back/forward list. Called from the WebCore thread.
- */
- /*package*/ synchronized void close(int nativeFrame) {
- // Clear the array first because nativeClose will call addHistoryItem
- // with the current item.
- mArray.clear();
- mCurrentIndex = -1;
- nativeClose(nativeFrame);
- // Reset the clear flag
- mClearPending = false;
- }
-
- /* Remove the item at the given index. Called by JNI only. */
- private synchronized void removeHistoryItem(int index) {
- // XXX: This is a special case. Since the callback is only triggered
- // when removing the first item, we can assert that the index is 0.
- // This lets us change the current index without having to query the
- // native BackForwardList.
- if (Config.DEBUG && (index != 0)) {
- throw new AssertionError();
- }
- final WebHistoryItem h = mArray.remove(index);
- // XXX: If we ever add another callback for removing history items at
- // any index, this will no longer be valid.
- mCurrentIndex--;
- }
-
- /**
- * Clone the entire object to be used in the UI thread by clients of
- * WebView. This creates a copy that should never be modified by any of the
- * webkit package classes.
- */
- protected synchronized WebBackForwardList clone() {
- WebBackForwardList l = new WebBackForwardList();
- if (mClearPending) {
- // If a clear is pending, return a copy with only the current item.
- l.addHistoryItem(getCurrentItem());
- return l;
- }
- l.mCurrentIndex = mCurrentIndex;
- int size = getSize();
- l.mArray = new ArrayList<WebHistoryItem>(size);
- for (int i = 0; i < size; i++) {
- // Add a copy of each WebHistoryItem
- l.mArray.add(mArray.get(i).clone());
- }
- return l;
- }
-
- /**
- * Set the new history index.
- * @param newIndex The new history index.
- */
- /*package*/ synchronized void setCurrentIndex(int newIndex) {
- mCurrentIndex = newIndex;
- }
-
- /**
- * Restore the history index.
- */
- /*package*/ static native synchronized void restoreIndex(int nativeFrame,
- int index);
-
- /* Close the native list. */
- private static native void nativeClose(int nativeFrame);
-}
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
deleted file mode 100644
index f940006..0000000
--- a/core/java/android/webkit/WebChromeClient.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.graphics.Bitmap;
-import android.os.Message;
-
-public class WebChromeClient {
-
- /**
- * Tell the host application the current progress of loading a page.
- * @param view The WebView that initiated the callback.
- * @param newProgress Current page loading progress, represented by
- * an integer between 0 and 100.
- */
- public void onProgressChanged(WebView view, int newProgress) {}
-
- /**
- * Notify the host application of a change in the document title.
- * @param view The WebView that initiated the callback.
- * @param title A String containing the new title of the document.
- */
- public void onReceivedTitle(WebView view, String title) {}
-
- /**
- * Notify the host application of a new favicon for the current page.
- * @param view The WebView that initiated the callback.
- * @param icon A Bitmap containing the favicon for the current page.
- */
- public void onReceivedIcon(WebView view, Bitmap icon) {}
-
- /**
- * Request the host application to create a new Webview. The host
- * application should handle placement of the new WebView in the view
- * system. The default behavior returns null.
- * @param view The WebView that initiated the callback.
- * @param dialog True if the new window is meant to be a small dialog
- * window.
- * @param userGesture True if the request was initiated by a user gesture
- * such as clicking a link.
- * @param resultMsg The message to send when done creating a new WebView.
- * Set the new WebView through resultMsg.obj which is
- * WebView.WebViewTransport() and then call
- * resultMsg.sendToTarget();
- * @return Similar to javscript dialogs, this method should return true if
- * the client is going to handle creating a new WebView. Note that
- * the WebView will halt processing if this method returns true so
- * make sure to call resultMsg.sendToTarget(). It is undefined
- * behavior to call resultMsg.sendToTarget() after returning false
- * from this method.
- */
- public boolean onCreateWindow(WebView view, boolean dialog,
- boolean userGesture, Message resultMsg) {
- return false;
- }
-
- /**
- * Request display and focus for this WebView. This may happen due to
- * another WebView opening a link in this WebView and requesting that this
- * WebView be displayed.
- * @param view The WebView that needs to be focused.
- */
- public void onRequestFocus(WebView view) {}
-
- /**
- * Notify the host application to close the given WebView and remove it
- * from the view system if necessary. At this point, WebCore has stopped
- * any loading in this window and has removed any cross-scripting ability
- * in javascript.
- * @param window The WebView that needs to be closed.
- */
- public void onCloseWindow(WebView window) {}
-
- /**
- * Tell the client to display a javascript alert dialog. If the client
- * returns true, WebView will assume that the client will handle the
- * dialog. If the client returns false, it will continue execution.
- * @param view The WebView that initiated the callback.
- * @param url The url of the page requesting the dialog.
- * @param message Message to be displayed in the window.
- * @param result A JsResult to confirm that the user hit enter.
- * @return boolean Whether the client will handle the alert dialog.
- */
- public boolean onJsAlert(WebView view, String url, String message,
- JsResult result) {
- return false;
- }
-
- /**
- * Tell the client to display a confirm dialog to the user. If the client
- * returns true, WebView will assume that the client will handle the
- * confirm dialog and call the appropriate JsResult method. If the
- * client returns false, a default value of false will be returned to
- * javascript. The default behavior is to return false.
- * @param view The WebView that initiated the callback.
- * @param url The url of the page requesting the dialog.
- * @param message Message to be displayed in the window.
- * @param result A JsResult used to send the user's response to
- * javascript.
- * @return boolean Whether the client will handle the confirm dialog.
- */
- public boolean onJsConfirm(WebView view, String url, String message,
- JsResult result) {
- return false;
- }
-
- /**
- * Tell the client to display a prompt dialog to the user. If the client
- * returns true, WebView will assume that the client will handle the
- * prompt dialog and call the appropriate JsPromptResult method. If the
- * client returns false, a default value of false will be returned to to
- * javascript. The default behavior is to return false.
- * @param view The WebView that initiated the callback.
- * @param url The url of the page requesting the dialog.
- * @param message Message to be displayed in the window.
- * @param defaultValue The default value displayed in the prompt dialog.
- * @param result A JsPromptResult used to send the user's reponse to
- * javascript.
- * @return boolean Whether the client will handle the prompt dialog.
- */
- public boolean onJsPrompt(WebView view, String url, String message,
- String defaultValue, JsPromptResult result) {
- return false;
- }
-
- /**
- * Tell the client to display a dialog to confirm navigation away from the
- * current page. This is the result of the onbeforeunload javascript event.
- * If the client returns true, WebView will assume that the client will
- * handle the confirm dialog and call the appropriate JsResult method. If
- * the client returns false, a default value of true will be returned to
- * javascript to accept navigation away from the current page. The default
- * behavior is to return false. Setting the JsResult to true will navigate
- * away from the current page, false will cancel the navigation.
- * @param view The WebView that initiated the callback.
- * @param url The url of the page requesting the dialog.
- * @param message Message to be displayed in the window.
- * @param result A JsResult used to send the user's response to
- * javascript.
- * @return boolean Whether the client will handle the confirm dialog.
- */
- public boolean onJsBeforeUnload(WebView view, String url, String message,
- JsResult result) {
- return false;
- }
-}
diff --git a/core/java/android/webkit/WebHistoryItem.java b/core/java/android/webkit/WebHistoryItem.java
deleted file mode 100644
index a408e06..0000000
--- a/core/java/android/webkit/WebHistoryItem.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.graphics.Bitmap;
-
-/**
- * A convenience class for accessing fields in an entry in the back/forward list
- * of a WebView. Each WebHistoryItem is a snapshot of the requested history
- * item. Each history item may be updated during the load of a page.
- * @see WebBackForwardList
- */
-public class WebHistoryItem implements Cloneable {
- // Global identifier count.
- private static int sNextId = 0;
- // Unique identifier.
- private final int mId;
- // The title of this item's document.
- private String mTitle;
- // The base url of this item.
- private String mUrl;
- // The original requested url of this item.
- private String mOriginalUrl;
- // The favicon for this item.
- private Bitmap mFavicon;
- // The pre-flattened data used for saving the state.
- private byte[] mFlattenedData;
-
- /**
- * Basic constructor that assigns a unique id to the item. Called by JNI
- * only.
- */
- private WebHistoryItem() {
- synchronized (WebHistoryItem.class) {
- mId = sNextId++;
- }
- }
-
- /**
- * Construct a new WebHistoryItem with initial flattened data.
- * @param data The pre-flattened data coming from restoreState.
- */
- /*package*/ WebHistoryItem(byte[] data) {
- mUrl = null; // This will be updated natively
- mFlattenedData = data;
- synchronized (WebHistoryItem.class) {
- mId = sNextId++;
- }
- }
-
- /**
- * Construct a clone of a WebHistoryItem from the given item.
- * @param item The history item to clone.
- */
- private WebHistoryItem(WebHistoryItem item) {
- mUrl = item.mUrl;
- mTitle = item.mTitle;
- mFlattenedData = item.mFlattenedData;
- mFavicon = item.mFavicon;
- mId = item.mId;
-}
-
- /**
- * Return an identifier for this history item. If an item is a copy of
- * another item, the identifiers will be the same even if they are not the
- * same object.
- * @return The id for this item.
- */
- public int getId() {
- return mId;
- }
-
- /**
- * Return the url of this history item. The url is the base url of this
- * history item. See getTargetUrl() for the url that is the actual target of
- * this history item.
- * @return The base url of this history item.
- * Note: The VM ensures 32-bit atomic read/write operations so we don't have
- * to synchronize this method.
- */
- public String getUrl() {
- return mUrl;
- }
-
- /**
- * Return the original url of this history item. This was the requested
- * url, the final url may be different as there might have been
- * redirects while loading the site.
- * @return The original url of this history item.
- *
- * @hide pending API Council approval
- */
- public String getOriginalUrl() {
- return mOriginalUrl;
- }
-
- /**
- * Return the document title of this history item.
- * @return The document title of this history item.
- * Note: The VM ensures 32-bit atomic read/write operations so we don't have
- * to synchronize this method.
- */
- public String getTitle() {
- return mTitle;
- }
-
- /**
- * Return the favicon of this history item or null if no favicon was found.
- * @return A Bitmap containing the favicon for this history item or null.
- * Note: The VM ensures 32-bit atomic read/write operations so we don't have
- * to synchronize this method.
- */
- public Bitmap getFavicon() {
- return mFavicon;
- }
-
- /**
- * Set the favicon.
- * @param icon A Bitmap containing the favicon for this history item.
- * Note: The VM ensures 32-bit atomic read/write operations so we don't have
- * to synchronize this method.
- */
- /*package*/ void setFavicon(Bitmap icon) {
- mFavicon = icon;
- }
-
- /**
- * Get the pre-flattened data.
- * Note: The VM ensures 32-bit atomic read/write operations so we don't have
- * to synchronize this method.
- */
- /*package*/ byte[] getFlattenedData() {
- return mFlattenedData;
- }
-
- /**
- * Inflate this item.
- * Note: The VM ensures 32-bit atomic read/write operations so we don't have
- * to synchronize this method.
- */
- /*package*/ void inflate(int nativeFrame) {
- inflate(nativeFrame, mFlattenedData);
- }
-
- /**
- * Clone the history item for use by clients of WebView.
- */
- protected synchronized WebHistoryItem clone() {
- return new WebHistoryItem(this);
- }
-
- /* Natively inflate this item, this method is called in the WebCore thread.
- */
- private native void inflate(int nativeFrame, byte[] data);
-
- /* Called by jni when the item is updated */
- private void update(String url, String originalUrl, String title,
- Bitmap favicon, byte[] data) {
- mUrl = url;
- mOriginalUrl = originalUrl;
- mTitle = title;
- mFavicon = favicon;
- mFlattenedData = data;
- }
-}
diff --git a/core/java/android/webkit/WebIconDatabase.java b/core/java/android/webkit/WebIconDatabase.java
deleted file mode 100644
index d284f5e..0000000
--- a/core/java/android/webkit/WebIconDatabase.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.os.Handler;
-import android.os.Message;
-import android.graphics.Bitmap;
-
-import java.util.Vector;
-
-/**
- * Functions for manipulating the icon database used by WebView.
- * These functions require that a WebView be constructed before being invoked
- * and WebView.getIconDatabase() will return a WebIconDatabase object. This
- * WebIconDatabase object is a single instance and all methods operate on that
- * single object.
- */
-public final class WebIconDatabase {
- // Global instance of a WebIconDatabase
- private static WebIconDatabase sIconDatabase;
- // EventHandler for handling messages before and after the WebCore thread is
- // ready.
- private final EventHandler mEventHandler = new EventHandler();
-
- // Class to handle messages before WebCore is ready
- private class EventHandler extends Handler {
- // Message ids
- static final int OPEN = 0;
- static final int CLOSE = 1;
- static final int REMOVE_ALL = 2;
- static final int REQUEST_ICON = 3;
- static final int RETAIN_ICON = 4;
- static final int RELEASE_ICON = 5;
- // Message for dispatching icon request results
- private static final int ICON_RESULT = 10;
- // Actual handler that runs in WebCore thread
- private Handler mHandler;
- // Vector of messages before the WebCore thread is ready
- private Vector<Message> mMessages = new Vector<Message>();
- // Class to handle a result dispatch
- private class IconResult {
- private final String mUrl;
- private final Bitmap mIcon;
- private final IconListener mListener;
- IconResult(String url, Bitmap icon, IconListener l) {
- mUrl = url;
- mIcon = icon;
- mListener = l;
- }
- void dispatch() {
- mListener.onReceivedIcon(mUrl, mIcon);
- }
- }
-
- @Override
- public void handleMessage(Message msg) {
- // Note: This is the message handler for the UI thread.
- switch (msg.what) {
- case ICON_RESULT:
- ((IconResult) msg.obj).dispatch();
- break;
- }
- }
-
- // Called by WebCore thread to create the actual handler
- private synchronized void createHandler() {
- if (mHandler == null) {
- mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- // Note: This is the message handler for the WebCore
- // thread.
- switch (msg.what) {
- case OPEN:
- nativeOpen((String) msg.obj);
- break;
-
- case CLOSE:
- nativeClose();
- break;
-
- case REMOVE_ALL:
- nativeRemoveAllIcons();
- break;
-
- case REQUEST_ICON:
- IconListener l = (IconListener) msg.obj;
- String url = msg.getData().getString("url");
- Bitmap icon = nativeIconForPageUrl(url);
- if (icon != null) {
- EventHandler.this.sendMessage(
- Message.obtain(null, ICON_RESULT,
- new IconResult(url, icon, l)));
- }
- break;
-
- case RETAIN_ICON:
- nativeRetainIconForPageUrl((String) msg.obj);
- break;
-
- case RELEASE_ICON:
- nativeReleaseIconForPageUrl((String) msg.obj);
- break;
- }
- }
- };
- // Transfer all pending messages
- for (int size = mMessages.size(); size > 0; size--) {
- mHandler.sendMessage(mMessages.remove(0));
- }
- mMessages = null;
- }
- }
-
- private synchronized void postMessage(Message msg) {
- if (mMessages != null) {
- mMessages.add(msg);
- } else {
- mHandler.sendMessage(msg);
- }
- }
- }
-
- /**
- * Interface for receiving icons from the database.
- */
- public interface IconListener {
- /**
- * Called when the icon has been retrieved from the database and the
- * result is non-null.
- * @param url The url passed in the request.
- * @param icon The favicon for the given url.
- */
- public void onReceivedIcon(String url, Bitmap icon);
- }
-
- /**
- * Open a the icon database and store the icons in the given path.
- * @param path The directory path where the icon database will be stored.
- * @return True if the database was successfully opened or created in
- * the given path.
- */
- public void open(String path) {
- if (path != null) {
- mEventHandler.postMessage(
- Message.obtain(null, EventHandler.OPEN, path));
- }
- }
-
- /**
- * Close the shared instance of the icon database.
- */
- public void close() {
- mEventHandler.postMessage(
- Message.obtain(null, EventHandler.CLOSE));
- }
-
- /**
- * Removes all the icons in the database.
- */
- public void removeAllIcons() {
- mEventHandler.postMessage(
- Message.obtain(null, EventHandler.REMOVE_ALL));
- }
-
- /**
- * Request the Bitmap representing the icon for the given page
- * url. If the icon exists, the listener will be called with the result.
- * @param url The page's url.
- * @param listener An implementation on IconListener to receive the result.
- */
- public void requestIconForPageUrl(String url, IconListener listener) {
- if (listener == null || url == null) {
- return;
- }
- Message msg = Message.obtain(null, EventHandler.REQUEST_ICON, listener);
- msg.getData().putString("url", url);
- mEventHandler.postMessage(msg);
- }
-
- /**
- * Retain the icon for the given page url.
- * @param url The page's url.
- */
- public void retainIconForPageUrl(String url) {
- if (url != null) {
- mEventHandler.postMessage(
- Message.obtain(null, EventHandler.RETAIN_ICON, url));
- }
- }
-
- /**
- * Release the icon for the given page url.
- * @param url The page's url.
- */
- public void releaseIconForPageUrl(String url) {
- if (url != null) {
- mEventHandler.postMessage(
- Message.obtain(null, EventHandler.RELEASE_ICON, url));
- }
- }
-
- /**
- * Get the global instance of WebIconDatabase.
- * @return A single instance of WebIconDatabase. It will be the same
- * instance for the current process each time this method is
- * called.
- */
- public static WebIconDatabase getInstance() {
- // XXX: Must be created in the UI thread.
- if (sIconDatabase == null) {
- sIconDatabase = new WebIconDatabase();
- }
- return sIconDatabase;
- }
-
- /**
- * Create the internal handler and transfer all pending messages.
- * XXX: Called by WebCore thread only!
- */
- /*package*/ void createHandler() {
- mEventHandler.createHandler();
- }
-
- /**
- * Private constructor to avoid anyone else creating an instance.
- */
- private WebIconDatabase() {}
-
- // Native functions
- private static native void nativeOpen(String path);
- private static native void nativeClose();
- private static native void nativeRemoveAllIcons();
- private static native Bitmap nativeIconForPageUrl(String url);
- private static native void nativeRetainIconForPageUrl(String url);
- private static native void nativeReleaseIconForPageUrl(String url);
-}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
deleted file mode 100644
index 4e2b2ab..0000000
--- a/core/java/android/webkit/WebSettings.java
+++ /dev/null
@@ -1,1112 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.content.Context;
-import android.os.Build;
-import android.os.Handler;
-import android.os.Message;
-import android.provider.Checkin;
-
-import java.lang.SecurityException;
-import android.content.pm.PackageManager;
-
-import java.util.Locale;
-
-/**
- * Manages settings state for a WebView. When a WebView is first created, it
- * obtains a set of default settings. These default settings will be returned
- * from any getter call. A WebSettings object obtained from
- * WebView.getSettings() is tied to the life of the WebView. If a WebView has
- * been destroyed, any method call on WebSettings will throw an
- * IllegalStateException.
- */
-public class WebSettings {
- /**
- * Enum for controlling the layout of html.
- * NORMAL means no rendering changes.
- * SINGLE_COLUMN moves all content into one column that is the width of the
- * view.
- * NARROW_COLUMNS makes all columns no wider than the screen if possible.
- */
- // XXX: These must match LayoutAlgorithm in Settings.h in WebCore.
- public enum LayoutAlgorithm {
- NORMAL,
- SINGLE_COLUMN,
- NARROW_COLUMNS
- }
-
- /**
- * Enum for specifying the text size.
- * SMALLEST is 50%
- * SMALLER is 75%
- * NORMAL is 100%
- * LARGER is 150%
- * LARGEST is 200%
- */
- public enum TextSize {
- SMALLEST(50),
- SMALLER(75),
- NORMAL(100),
- LARGER(150),
- LARGEST(200);
- TextSize(int size) {
- value = size;
- }
- int value;
- }
-
- /**
- * Default cache usage pattern Use with {@link #setCacheMode}.
- */
- public static final int LOAD_DEFAULT = -1;
-
- /**
- * Normal cache usage pattern Use with {@link #setCacheMode}.
- */
- public static final int LOAD_NORMAL = 0;
-
- /**
- * Use cache if content is there, even if expired (eg, history nav)
- * If it is not in the cache, load from network.
- * Use with {@link #setCacheMode}.
- */
- public static final int LOAD_CACHE_ELSE_NETWORK = 1;
-
- /**
- * Don't use the cache, load from network
- * Use with {@link #setCacheMode}.
- */
- public static final int LOAD_NO_CACHE = 2;
-
- /**
- * Don't use the network, load from cache only.
- * Use with {@link #setCacheMode}.
- */
- public static final int LOAD_CACHE_ONLY = 3;
-
- public enum RenderPriority {
- NORMAL,
- HIGH,
- LOW
- }
-
- // BrowserFrame used to access the native frame pointer.
- private BrowserFrame mBrowserFrame;
- // Flag to prevent multiple SYNC messages at one time.
- private boolean mSyncPending = false;
- // Custom handler that queues messages until the WebCore thread is active.
- private final EventHandler mEventHandler;
- // Private settings so we don't have to go into native code to
- // retrieve the values. After setXXX, postSync() needs to be called.
- // XXX: The default values need to match those in WebSettings.cpp
- private LayoutAlgorithm mLayoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS;
- private Context mContext;
- private TextSize mTextSize = TextSize.NORMAL;
- private String mStandardFontFamily = "sans-serif";
- private String mFixedFontFamily = "monospace";
- private String mSansSerifFontFamily = "sans-serif";
- private String mSerifFontFamily = "serif";
- private String mCursiveFontFamily = "cursive";
- private String mFantasyFontFamily = "fantasy";
- private String mDefaultTextEncoding = "Latin-1";
- private String mUserAgent;
- private boolean mUseDefaultUserAgent;
- private String mAcceptLanguage;
- private String mPluginsPath = "";
- private int mMinimumFontSize = 8;
- private int mMinimumLogicalFontSize = 8;
- private int mDefaultFontSize = 16;
- private int mDefaultFixedFontSize = 13;
- private boolean mLoadsImagesAutomatically = true;
- private boolean mBlockNetworkImage = false;
- private boolean mBlockNetworkLoads = false;
- private boolean mJavaScriptEnabled = false;
- private boolean mPluginsEnabled = false;
- private boolean mJavaScriptCanOpenWindowsAutomatically = false;
- private boolean mUseDoubleTree = false;
- private boolean mUseWideViewport = false;
- private boolean mSupportMultipleWindows = false;
- private boolean mShrinksStandaloneImagesToFit = false;
- // Don't need to synchronize the get/set methods as they
- // are basic types, also none of these values are used in
- // native WebCore code.
- private RenderPriority mRenderPriority = RenderPriority.NORMAL;
- private int mOverrideCacheMode = LOAD_DEFAULT;
- private boolean mSaveFormData = true;
- private boolean mSavePassword = true;
- private boolean mLightTouchEnabled = false;
- private boolean mNeedInitialFocus = true;
- private boolean mNavDump = false;
- private boolean mSupportZoom = true;
- private boolean mAllowFileAccess = true;
-
- // Class to handle messages before WebCore is ready.
- private class EventHandler {
- // Message id for syncing
- static final int SYNC = 0;
- // Message id for setting priority
- static final int PRIORITY = 1;
- // Actual WebCore thread handler
- private Handler mHandler;
-
- private synchronized void createHandler() {
- // as mRenderPriority can be set before thread is running, sync up
- setRenderPriority();
-
- // create a new handler
- mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case SYNC:
- synchronized (WebSettings.this) {
- if (mBrowserFrame.mNativeFrame != 0) {
- nativeSync(mBrowserFrame.mNativeFrame);
- }
- mSyncPending = false;
- }
- break;
-
- case PRIORITY: {
- setRenderPriority();
- break;
- }
- }
- }
- };
- }
-
- private void setRenderPriority() {
- synchronized (WebSettings.this) {
- if (mRenderPriority == RenderPriority.NORMAL) {
- android.os.Process.setThreadPriority(
- android.os.Process.THREAD_PRIORITY_DEFAULT);
- } else if (mRenderPriority == RenderPriority.HIGH) {
- android.os.Process.setThreadPriority(
- android.os.Process.THREAD_PRIORITY_FOREGROUND +
- android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE);
- } else if (mRenderPriority == RenderPriority.LOW) {
- android.os.Process.setThreadPriority(
- android.os.Process.THREAD_PRIORITY_BACKGROUND);
- }
- }
- }
-
- /**
- * Send a message to the private queue or handler.
- */
- private synchronized boolean sendMessage(Message msg) {
- if (mHandler != null) {
- mHandler.sendMessage(msg);
- return true;
- } else {
- return false;
- }
- }
- }
-
- // User agent strings.
- private static final String DESKTOP_USERAGENT =
- "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en)"
- + " AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2"
- + " Safari/525.20.1";
- private static final String IPHONE_USERAGENT =
- "Mozilla/5.0 (iPhone; U; CPU iPhone 2_1 like Mac OS X; en)"
- + " AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2"
- + " Mobile/5F136 Safari/525.20.1";
- private static Locale sLocale;
- private static Object sLockForLocaleSettings;
-
- /**
- * Package constructor to prevent clients from creating a new settings
- * instance.
- */
- WebSettings(Context context) {
- mEventHandler = new EventHandler();
- mContext = context;
-
- if (sLockForLocaleSettings == null) {
- sLockForLocaleSettings = new Object();
- sLocale = Locale.getDefault();
- }
- mAcceptLanguage = getCurrentAcceptLanguage();
- mUserAgent = getCurrentUserAgent();
- mUseDefaultUserAgent = true;
-
- verifyNetworkAccess();
- }
-
- /**
- * Looks at sLocale and returns current AcceptLanguage String.
- * @return Current AcceptLanguage String.
- */
- private String getCurrentAcceptLanguage() {
- Locale locale;
- synchronized(sLockForLocaleSettings) {
- locale = sLocale;
- }
- StringBuffer buffer = new StringBuffer();
- final String language = locale.getLanguage();
- if (language != null) {
- buffer.append(language);
- final String country = locale.getCountry();
- if (country != null) {
- buffer.append("-");
- buffer.append(country);
- }
- }
- if (!locale.equals(Locale.US)) {
- buffer.append(", ");
- java.util.Locale us = Locale.US;
- if (us.getLanguage() != null) {
- buffer.append(us.getLanguage());
- final String country = us.getCountry();
- if (country != null) {
- buffer.append("-");
- buffer.append(country);
- }
- }
- }
-
- return buffer.toString();
- }
-
- /**
- * Looks at sLocale and mContext and returns current UserAgent String.
- * @return Current UserAgent String.
- */
- private synchronized String getCurrentUserAgent() {
- Locale locale;
- synchronized(sLockForLocaleSettings) {
- locale = sLocale;
- }
- StringBuffer buffer = new StringBuffer();
- // Add version
- final String version = Build.VERSION.RELEASE;
- if (version.length() > 0) {
- buffer.append(version);
- } else {
- // default to "1.0"
- buffer.append("1.0");
- }
- buffer.append("; ");
- final String language = locale.getLanguage();
- if (language != null) {
- buffer.append(language.toLowerCase());
- final String country = locale.getCountry();
- if (country != null) {
- buffer.append("-");
- buffer.append(country.toLowerCase());
- }
- } else {
- // default to "en"
- buffer.append("en");
- }
-
- final String model = Build.MODEL;
- if (model.length() > 0) {
- buffer.append("; ");
- buffer.append(model);
- }
- final String id = Build.ID;
- if (id.length() > 0) {
- buffer.append(" Build/");
- buffer.append(id);
- }
- final String base = mContext.getResources().getText(
- com.android.internal.R.string.web_user_agent).toString();
- return String.format(base, buffer);
- }
-
- /**
- * Enables dumping the pages navigation cache to a text file.
- */
- public void setNavDump(boolean enabled) {
- mNavDump = enabled;
- }
-
- /**
- * Returns true if dumping the navigation cache is enabled.
- */
- public boolean getNavDump() {
- return mNavDump;
- }
-
- /**
- * Set whether the WebView supports zoom
- */
- public void setSupportZoom(boolean support) {
- mSupportZoom = support;
- }
-
- /**
- * Returns whether the WebView supports zoom
- */
- public boolean supportZoom() {
- return mSupportZoom;
- }
-
- /**
- * Enable or disable file access within WebView. File access is enabled by
- * default.
- */
- public void setAllowFileAccess(boolean allow) {
- mAllowFileAccess = allow;
- }
-
- /**
- * Returns true if this WebView supports file access.
- */
- public boolean getAllowFileAccess() {
- return mAllowFileAccess;
- }
-
- /**
- * Store whether the WebView is saving form data.
- */
- public void setSaveFormData(boolean save) {
- mSaveFormData = save;
- }
-
- /**
- * Return whether the WebView is saving form data.
- */
- public boolean getSaveFormData() {
- return mSaveFormData;
- }
-
- /**
- * Store whether the WebView is saving password.
- */
- public void setSavePassword(boolean save) {
- mSavePassword = save;
- }
-
- /**
- * Return whether the WebView is saving password.
- */
- public boolean getSavePassword() {
- return mSavePassword;
- }
-
- /**
- * Set the text size of the page.
- * @param t A TextSize value for increasing or decreasing the text.
- * @see WebSettings.TextSize
- */
- public synchronized void setTextSize(TextSize t) {
- if (WebView.mLogEvent && mTextSize != t ) {
- Checkin.updateStats(mContext.getContentResolver(),
- Checkin.Stats.Tag.BROWSER_TEXT_SIZE_CHANGE, 1, 0.0);
- }
- mTextSize = t;
- postSync();
- }
-
- /**
- * Get the text size of the page.
- * @return A TextSize enum value describing the text size.
- * @see WebSettings.TextSize
- */
- public synchronized TextSize getTextSize() {
- return mTextSize;
- }
-
- /**
- * Enables using light touches to make a selection and activate mouseovers.
- */
- public void setLightTouchEnabled(boolean enabled) {
- mLightTouchEnabled = enabled;
- }
-
- /**
- * Returns true if light touches are enabled.
- */
- public boolean getLightTouchEnabled() {
- return mLightTouchEnabled;
- }
-
- /**
- * Tell the WebView to use the double tree rendering algorithm.
- * @param use True if the WebView is to use double tree rendering, false
- * otherwise.
- */
- public synchronized void setUseDoubleTree(boolean use) {
- if (mUseDoubleTree != use) {
- mUseDoubleTree = use;
- postSync();
- }
- }
-
- /**
- * Return true if the WebView is using the double tree rendering algorithm.
- * @return True if the WebView is using the double tree rendering
- * algorithm.
- */
- public synchronized boolean getUseDoubleTree() {
- return mUseDoubleTree;
- }
-
- /**
- * Tell the WebView about user-agent string.
- * @param ua 0 if the WebView should use an Android user-agent string,
- * 1 if the WebView should use a desktop user-agent string.
- *
- * @deprecated Please use setUserAgentString instead.
- */
- @Deprecated
- public synchronized void setUserAgent(int ua) {
- String uaString = null;
- if (ua == 1) {
- if (DESKTOP_USERAGENT.equals(mUserAgent)) {
- return; // do nothing
- } else {
- uaString = DESKTOP_USERAGENT;
- }
- } else if (ua == 2) {
- if (IPHONE_USERAGENT.equals(mUserAgent)) {
- return; // do nothing
- } else {
- uaString = IPHONE_USERAGENT;
- }
- } else if (ua != 0) {
- return; // do nothing
- }
- setUserAgentString(uaString);
- }
-
- /**
- * Return user-agent as int
- * @return int 0 if the WebView is using an Android user-agent string.
- * 1 if the WebView is using a desktop user-agent string.
- * -1 if the WebView is using user defined user-agent string.
- *
- * @deprecated Please use getUserAgentString instead.
- */
- @Deprecated
- public synchronized int getUserAgent() {
- if (DESKTOP_USERAGENT.equals(mUserAgent)) {
- return 1;
- } else if (IPHONE_USERAGENT.equals(mUserAgent)) {
- return 2;
- } else if (mUseDefaultUserAgent) {
- return 0;
- }
- return -1;
- }
-
- /**
- * Tell the WebView to use the wide viewport
- */
- public synchronized void setUseWideViewPort(boolean use) {
- if (mUseWideViewport != use) {
- mUseWideViewport = use;
- postSync();
- }
- }
-
- /**
- * @return True if the WebView is using a wide viewport
- */
- public synchronized boolean getUseWideViewPort() {
- return mUseWideViewport;
- }
-
- /**
- * Tell the WebView whether it supports multiple windows. TRUE means
- * that {@link WebChromeClient#onCreateWindow(WebView, boolean,
- * boolean, Message)} is implemented by the host application.
- */
- public synchronized void setSupportMultipleWindows(boolean support) {
- if (mSupportMultipleWindows != support) {
- mSupportMultipleWindows = support;
- postSync();
- }
- }
-
- /**
- * @return True if the WebView is supporting multiple windows. This means
- * that {@link WebChromeClient#onCreateWindow(WebView, boolean,
- * boolean, Message)} is implemented by the host application.
- */
- public synchronized boolean supportMultipleWindows() {
- return mSupportMultipleWindows;
- }
-
- /**
- * Set the underlying layout algorithm. This will cause a relayout of the
- * WebView.
- * @param l A LayoutAlgorithm enum specifying the algorithm to use.
- * @see WebSettings.LayoutAlgorithm
- */
- public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) {
- // XXX: This will only be affective if libwebcore was built with
- // ANDROID_LAYOUT defined.
- if (mLayoutAlgorithm != l) {
- mLayoutAlgorithm = l;
- postSync();
- }
- }
-
- /**
- * Return the current layout algorithm.
- * @return LayoutAlgorithm enum value describing the layout algorithm
- * being used.
- * @see WebSettings.LayoutAlgorithm
- */
- public synchronized LayoutAlgorithm getLayoutAlgorithm() {
- return mLayoutAlgorithm;
- }
-
- /**
- * Set the standard font family name.
- * @param font A font family name.
- */
- public synchronized void setStandardFontFamily(String font) {
- if (font != null && !font.equals(mStandardFontFamily)) {
- mStandardFontFamily = font;
- postSync();
- }
- }
-
- /**
- * Get the standard font family name.
- * @return The standard font family name as a string.
- */
- public synchronized String getStandardFontFamily() {
- return mStandardFontFamily;
- }
-
- /**
- * Set the fixed font family name.
- * @param font A font family name.
- */
- public synchronized void setFixedFontFamily(String font) {
- if (font != null && !font.equals(mFixedFontFamily)) {
- mFixedFontFamily = font;
- postSync();
- }
- }
-
- /**
- * Get the fixed font family name.
- * @return The fixed font family name as a string.
- */
- public synchronized String getFixedFontFamily() {
- return mFixedFontFamily;
- }
-
- /**
- * Set the sans-serif font family name.
- * @param font A font family name.
- */
- public synchronized void setSansSerifFontFamily(String font) {
- if (font != null && !font.equals(mSansSerifFontFamily)) {
- mSansSerifFontFamily = font;
- postSync();
- }
- }
-
- /**
- * Get the sans-serif font family name.
- * @return The sans-serif font family name as a string.
- */
- public synchronized String getSansSerifFontFamily() {
- return mSansSerifFontFamily;
- }
-
- /**
- * Set the serif font family name.
- * @param font A font family name.
- */
- public synchronized void setSerifFontFamily(String font) {
- if (font != null && !font.equals(mSerifFontFamily)) {
- mSerifFontFamily = font;
- postSync();
- }
- }
-
- /**
- * Get the serif font family name.
- * @return The serif font family name as a string.
- */
- public synchronized String getSerifFontFamily() {
- return mSerifFontFamily;
- }
-
- /**
- * Set the cursive font family name.
- * @param font A font family name.
- */
- public synchronized void setCursiveFontFamily(String font) {
- if (font != null && !font.equals(mCursiveFontFamily)) {
- mCursiveFontFamily = font;
- postSync();
- }
- }
-
- /**
- * Get the cursive font family name.
- * @return The cursive font family name as a string.
- */
- public synchronized String getCursiveFontFamily() {
- return mCursiveFontFamily;
- }
-
- /**
- * Set the fantasy font family name.
- * @param font A font family name.
- */
- public synchronized void setFantasyFontFamily(String font) {
- if (font != null && !font.equals(mFantasyFontFamily)) {
- mFantasyFontFamily = font;
- postSync();
- }
- }
-
- /**
- * Get the fantasy font family name.
- * @return The fantasy font family name as a string.
- */
- public synchronized String getFantasyFontFamily() {
- return mFantasyFontFamily;
- }
-
- /**
- * Set the minimum font size.
- * @param size A non-negative integer between 1 and 72.
- * Any number outside the specified range will be pinned.
- */
- public synchronized void setMinimumFontSize(int size) {
- size = pin(size);
- if (mMinimumFontSize != size) {
- mMinimumFontSize = size;
- postSync();
- }
- }
-
- /**
- * Get the minimum font size.
- * @return A non-negative integer between 1 and 72.
- */
- public synchronized int getMinimumFontSize() {
- return mMinimumFontSize;
- }
-
- /**
- * Set the minimum logical font size.
- * @param size A non-negative integer between 1 and 72.
- * Any number outside the specified range will be pinned.
- */
- public synchronized void setMinimumLogicalFontSize(int size) {
- size = pin(size);
- if (mMinimumLogicalFontSize != size) {
- mMinimumLogicalFontSize = size;
- postSync();
- }
- }
-
- /**
- * Get the minimum logical font size.
- * @return A non-negative integer between 1 and 72.
- */
- public synchronized int getMinimumLogicalFontSize() {
- return mMinimumLogicalFontSize;
- }
-
- /**
- * Set the default font size.
- * @param size A non-negative integer between 1 and 72.
- * Any number outside the specified range will be pinned.
- */
- public synchronized void setDefaultFontSize(int size) {
- size = pin(size);
- if (mDefaultFontSize != size) {
- mDefaultFontSize = size;
- postSync();
- }
- }
-
- /**
- * Get the default font size.
- * @return A non-negative integer between 1 and 72.
- */
- public synchronized int getDefaultFontSize() {
- return mDefaultFontSize;
- }
-
- /**
- * Set the default fixed font size.
- * @param size A non-negative integer between 1 and 72.
- * Any number outside the specified range will be pinned.
- */
- public synchronized void setDefaultFixedFontSize(int size) {
- size = pin(size);
- if (mDefaultFixedFontSize != size) {
- mDefaultFixedFontSize = size;
- postSync();
- }
- }
-
- /**
- * Get the default fixed font size.
- * @return A non-negative integer between 1 and 72.
- */
- public synchronized int getDefaultFixedFontSize() {
- return mDefaultFixedFontSize;
- }
-
- /**
- * Tell the WebView to load image resources automatically.
- * @param flag True if the WebView should load images automatically.
- */
- public synchronized void setLoadsImagesAutomatically(boolean flag) {
- if (mLoadsImagesAutomatically != flag) {
- mLoadsImagesAutomatically = flag;
- postSync();
- }
- }
-
- /**
- * Return true if the WebView will load image resources automatically.
- * @return True if the WebView loads images automatically.
- */
- public synchronized boolean getLoadsImagesAutomatically() {
- return mLoadsImagesAutomatically;
- }
-
- /**
- * Tell the WebView to block network image. This is only checked when
- * getLoadsImagesAutomatically() is true.
- * @param flag True if the WebView should block network image
- */
- public synchronized void setBlockNetworkImage(boolean flag) {
- if (mBlockNetworkImage != flag) {
- mBlockNetworkImage = flag;
- postSync();
- }
- }
-
- /**
- * Return true if the WebView will block network image.
- * @return True if the WebView blocks network image.
- */
- public synchronized boolean getBlockNetworkImage() {
- return mBlockNetworkImage;
- }
-
- /**
- * @hide
- * Tell the WebView to block all network load requests.
- * @param flag True if the WebView should block all network loads
- */
- public synchronized void setBlockNetworkLoads(boolean flag) {
- if (mBlockNetworkLoads != flag) {
- mBlockNetworkLoads = flag;
- verifyNetworkAccess();
- }
- }
-
- /**
- * @hide
- * Return true if the WebView will block all network loads.
- * @return True if the WebView blocks all network loads.
- */
- public synchronized boolean getBlockNetworkLoads() {
- return mBlockNetworkLoads;
- }
-
-
- private void verifyNetworkAccess() {
- if (!mBlockNetworkLoads) {
- if (mContext.checkPermission("android.permission.INTERNET",
- android.os.Process.myPid(), 0) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException
- ("Permission denied - " +
- "application missing INTERNET permission");
- }
- }
- }
-
- /**
- * Tell the WebView to enable javascript execution.
- * @param flag True if the WebView should execute javascript.
- */
- public synchronized void setJavaScriptEnabled(boolean flag) {
- if (mJavaScriptEnabled != flag) {
- mJavaScriptEnabled = flag;
- postSync();
- }
- }
-
- /**
- * Tell the WebView to enable plugins.
- * @param flag True if the WebView should load plugins.
- */
- public synchronized void setPluginsEnabled(boolean flag) {
- if (mPluginsEnabled != flag) {
- mPluginsEnabled = flag;
- postSync();
- }
- }
-
- /**
- * Set a custom path to plugins used by the WebView. The client
- * must ensure it exists before this call.
- * @param pluginsPath String path to the directory containing plugins.
- */
- public synchronized void setPluginsPath(String pluginsPath) {
- if (pluginsPath != null && !pluginsPath.equals(mPluginsPath)) {
- mPluginsPath = pluginsPath;
- postSync();
- }
- }
-
- /**
- * Return true if javascript is enabled.
- * @return True if javascript is enabled.
- */
- public synchronized boolean getJavaScriptEnabled() {
- return mJavaScriptEnabled;
- }
-
- /**
- * Return true if plugins are enabled.
- * @return True if plugins are enabled.
- */
- public synchronized boolean getPluginsEnabled() {
- return mPluginsEnabled;
- }
-
- /**
- * Return the current path used for plugins in the WebView.
- * @return The string path to the WebView plugins.
- */
- public synchronized String getPluginsPath() {
- return mPluginsPath;
- }
-
- /**
- * Tell javascript to open windows automatically. This applies to the
- * javascript function window.open().
- * @param flag True if javascript can open windows automatically.
- */
- public synchronized void setJavaScriptCanOpenWindowsAutomatically(
- boolean flag) {
- if (mJavaScriptCanOpenWindowsAutomatically != flag) {
- mJavaScriptCanOpenWindowsAutomatically = flag;
- postSync();
- }
- }
-
- /**
- * Return true if javascript can open windows automatically.
- * @return True if javascript can open windows automatically during
- * window.open().
- */
- public synchronized boolean getJavaScriptCanOpenWindowsAutomatically() {
- return mJavaScriptCanOpenWindowsAutomatically;
- }
-
- /**
- * Set the default text encoding name to use when decoding html pages.
- * @param encoding The text encoding name.
- */
- public synchronized void setDefaultTextEncodingName(String encoding) {
- if (encoding != null && !encoding.equals(mDefaultTextEncoding)) {
- mDefaultTextEncoding = encoding;
- postSync();
- }
- }
-
- /**
- * Get the default text encoding name.
- * @return The default text encoding name as a string.
- */
- public synchronized String getDefaultTextEncodingName() {
- return mDefaultTextEncoding;
- }
-
- /**
- * Set the WebView's user-agent string. If the string "ua" is null or empty,
- * it will use the system default user-agent string.
- */
- public synchronized void setUserAgentString(String ua) {
- if (ua == null || ua.length() == 0) {
- synchronized(sLockForLocaleSettings) {
- Locale currentLocale = Locale.getDefault();
- if (!sLocale.equals(currentLocale)) {
- sLocale = currentLocale;
- mAcceptLanguage = getCurrentAcceptLanguage();
- }
- }
- ua = getCurrentUserAgent();
- mUseDefaultUserAgent = true;
- } else {
- mUseDefaultUserAgent = false;
- }
-
- if (!ua.equals(mUserAgent)) {
- mUserAgent = ua;
- postSync();
- }
- }
-
- /**
- * Return the WebView's user-agent string.
- */
- public synchronized String getUserAgentString() {
- if (DESKTOP_USERAGENT.equals(mUserAgent) ||
- IPHONE_USERAGENT.equals(mUserAgent) ||
- !mUseDefaultUserAgent) {
- return mUserAgent;
- }
-
- boolean doPostSync = false;
- synchronized(sLockForLocaleSettings) {
- Locale currentLocale = Locale.getDefault();
- if (!sLocale.equals(currentLocale)) {
- sLocale = currentLocale;
- mUserAgent = getCurrentUserAgent();
- mAcceptLanguage = getCurrentAcceptLanguage();
- doPostSync = true;
- }
- }
- if (doPostSync) {
- postSync();
- }
- return mUserAgent;
- }
-
- /* package api to grab the Accept Language string. */
- /*package*/ synchronized String getAcceptLanguage() {
- synchronized(sLockForLocaleSettings) {
- Locale currentLocale = Locale.getDefault();
- if (!sLocale.equals(currentLocale)) {
- sLocale = currentLocale;
- mAcceptLanguage = getCurrentAcceptLanguage();
- }
- }
- return mAcceptLanguage;
- }
-
- /**
- * Tell the WebView whether it needs to set a node to have focus when
- * {@link WebView#requestFocus(int, android.graphics.Rect)} is called.
- *
- * @param flag
- */
- public void setNeedInitialFocus(boolean flag) {
- if (mNeedInitialFocus != flag) {
- mNeedInitialFocus = flag;
- }
- }
-
- /* Package api to get the choice whether it needs to set initial focus. */
- /* package */ boolean getNeedInitialFocus() {
- return mNeedInitialFocus;
- }
-
- /**
- * Set the priority of the Render thread. Unlike the other settings, this
- * one only needs to be called once per process.
- *
- * @param priority RenderPriority, can be normal, high or low.
- */
- public synchronized void setRenderPriority(RenderPriority priority) {
- if (mRenderPriority != priority) {
- mRenderPriority = priority;
- mEventHandler.sendMessage(Message.obtain(null,
- EventHandler.PRIORITY));
- }
- }
-
- /**
- * Override the way the cache is used. The way the cache is used is based
- * on the navigation option. For a normal page load, the cache is checked
- * and content is re-validated as needed. When navigating back, content is
- * not revalidated, instead the content is just pulled from the cache.
- * This function allows the client to override this behavior.
- * @param mode One of the LOAD_ values.
- */
- public void setCacheMode(int mode) {
- if (mode != mOverrideCacheMode) {
- mOverrideCacheMode = mode;
- }
- }
-
- /**
- * Return the current setting for overriding the cache mode. For a full
- * description, see the {@link #setCacheMode(int)} function.
- */
- public int getCacheMode() {
- return mOverrideCacheMode;
- }
-
- /**
- * If set, webkit alternately shrinks and expands images viewed outside
- * of an HTML page to fit the screen. This conflicts with attempts by
- * the UI to zoom in and out of an image, so it is set false by default.
- * @param shrink Set true to let webkit shrink the standalone image to fit.
- * {@hide}
- */
- public void setShrinksStandaloneImagesToFit(boolean shrink) {
- if (mShrinksStandaloneImagesToFit != shrink) {
- mShrinksStandaloneImagesToFit = shrink;
- postSync();
- }
- }
-
- /**
- * Transfer messages from the queue to the new WebCoreThread. Called from
- * WebCore thread.
- */
- /*package*/
- synchronized void syncSettingsAndCreateHandler(BrowserFrame frame) {
- mBrowserFrame = frame;
- if (android.util.Config.DEBUG) {
- junit.framework.Assert.assertTrue(frame.mNativeFrame != 0);
- }
- nativeSync(frame.mNativeFrame);
- mSyncPending = false;
- mEventHandler.createHandler();
- }
-
- private int pin(int size) {
- // FIXME: 72 is just an arbitrary max text size value.
- if (size < 1) {
- return 1;
- } else if (size > 72) {
- return 72;
- }
- return size;
- }
-
- /* Post a SYNC message to handle syncing the native settings. */
- private synchronized void postSync() {
- // Only post if a sync is not pending
- if (!mSyncPending) {
- mSyncPending = mEventHandler.sendMessage(
- Message.obtain(null, EventHandler.SYNC));
- }
- }
-
- // Synchronize the native and java settings.
- private native void nativeSync(int nativeFrame);
-}
diff --git a/core/java/android/webkit/WebSyncManager.java b/core/java/android/webkit/WebSyncManager.java
deleted file mode 100644
index e6e9994..0000000
--- a/core/java/android/webkit/WebSyncManager.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Process;
-import android.util.Config;
-import android.util.Log;
-
-abstract class WebSyncManager implements Runnable {
- // message code for sync message
- private static final int SYNC_MESSAGE = 101;
- // time delay in millisec for a sync (now) message
- private static int SYNC_NOW_INTERVAL = 100; // 100 millisec
- // time delay in millisec for a sync (later) message
- private static int SYNC_LATER_INTERVAL = 5 * 60 * 1000; // 5 minutes
- // thread for syncing
- private Thread mSyncThread;
- // Name of thread
- private String mThreadName;
- // handler of the sync thread
- protected Handler mHandler;
- // database for the persistent storage
- protected WebViewDatabase mDataBase;
- // Ref count for calls to start/stop sync
- private int mStartSyncRefCount;
- // log tag
- protected static final String LOGTAG = "websync";
-
- private class SyncHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == SYNC_MESSAGE) {
- if (Config.LOGV) {
- Log.v(LOGTAG, "*** WebSyncManager sync ***");
- }
- syncFromRamToFlash();
-
- // send a delayed message to request sync later
- Message newmsg = obtainMessage(SYNC_MESSAGE);
- sendMessageDelayed(newmsg, SYNC_LATER_INTERVAL);
- }
- }
- }
-
- protected WebSyncManager(Context context, String name) {
- mThreadName = name;
- if (context != null) {
- mDataBase = WebViewDatabase.getInstance(context);
- mSyncThread = new Thread(this);
- mSyncThread.setName(mThreadName);
- mSyncThread.start();
- } else {
- throw new IllegalStateException(
- "WebSyncManager can't be created without context");
- }
- }
-
- protected Object clone() throws CloneNotSupportedException {
- throw new CloneNotSupportedException("doesn't implement Cloneable");
- }
-
- public void run() {
- // prepare Looper for sync handler
- Looper.prepare();
- mHandler = new SyncHandler();
- onSyncInit();
- // lower the priority after onSyncInit() is done
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-
- Message msg = mHandler.obtainMessage(SYNC_MESSAGE);
- mHandler.sendMessageDelayed(msg, SYNC_LATER_INTERVAL);
-
- Looper.loop();
- }
-
- /**
- * sync() forces sync manager to sync now
- */
- public void sync() {
- if (Config.LOGV) {
- Log.v(LOGTAG, "*** WebSyncManager sync ***");
- }
- if (mHandler == null) {
- return;
- }
- mHandler.removeMessages(SYNC_MESSAGE);
- Message msg = mHandler.obtainMessage(SYNC_MESSAGE);
- mHandler.sendMessageDelayed(msg, SYNC_NOW_INTERVAL);
- }
-
- /**
- * resetSync() resets sync manager's timer
- */
- public void resetSync() {
- if (Config.LOGV) {
- Log.v(LOGTAG, "*** WebSyncManager resetSync ***");
- }
- if (mHandler == null) {
- return;
- }
- mHandler.removeMessages(SYNC_MESSAGE);
- Message msg = mHandler.obtainMessage(SYNC_MESSAGE);
- mHandler.sendMessageDelayed(msg, SYNC_LATER_INTERVAL);
- }
-
- /**
- * startSync() requests sync manager to start sync
- */
- public void startSync() {
- if (Config.LOGV) {
- Log.v(LOGTAG, "*** WebSyncManager startSync ***, Ref count:" +
- mStartSyncRefCount);
- }
- if (mHandler == null) {
- return;
- }
- if (++mStartSyncRefCount == 1) {
- Message msg = mHandler.obtainMessage(SYNC_MESSAGE);
- mHandler.sendMessageDelayed(msg, SYNC_LATER_INTERVAL);
- }
- }
-
- /**
- * stopSync() requests sync manager to stop sync. remove any SYNC_MESSAGE in
- * the queue to break the sync loop
- */
- public void stopSync() {
- if (Config.LOGV) {
- Log.v(LOGTAG, "*** WebSyncManager stopSync ***, Ref count:" +
- mStartSyncRefCount);
- }
- if (mHandler == null) {
- return;
- }
- if (--mStartSyncRefCount == 0) {
- mHandler.removeMessages(SYNC_MESSAGE);
- }
- }
-
- protected void onSyncInit() {
- }
-
- abstract void syncFromRamToFlash();
-}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
deleted file mode 100644
index 417b657..0000000
--- a/core/java/android/webkit/WebView.java
+++ /dev/null
@@ -1,5338 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Picture;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.net.http.SslCertificate;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.provider.Checkin;
-import android.text.IClipboard;
-import android.text.Selection;
-import android.text.Spannable;
-import android.util.AttributeSet;
-import android.util.Config;
-import android.util.EventLog;
-import android.util.Log;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.SoundEffectConstants;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.view.ViewTreeObserver;
-import android.view.inputmethod.InputMethodManager;
-import android.webkit.TextDialog.AutoCompleteAdapter;
-import android.webkit.WebViewCore.EventHub;
-import android.widget.AbsoluteLayout;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.RelativeLayout;
-import android.widget.Scroller;
-import android.widget.Toast;
-import android.widget.ZoomControls;
-import android.widget.ZoomRingController;
-import android.widget.FrameLayout;
-import android.widget.AdapterView.OnItemClickListener;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * <p>A View that displays web pages. This class is the basis upon which you
- * can roll your own web browser or simply display some online content within your Activity.
- * It uses the WebKit rendering engine to display
- * web pages and includes methods to navigate forward and backward
- * through a history, zoom in and out, perform text searches and more.</p>
- * <p>Note that, in order for your Activity to access the Internet and load web pages
- * in a WebView, you must add the <var>INTERNET</var> permissions to your
- * Android Manifest file:</p>
- * <pre>&lt;uses-permission android:name="android.permission.INTERNET" /></pre>
- * <p>This must be a child of the <code>&lt;manifest></code> element.</p>
- */
-public class WebView extends AbsoluteLayout
- implements ViewTreeObserver.OnGlobalFocusChangeListener,
- ViewGroup.OnHierarchyChangeListener {
-
- // if AUTO_REDRAW_HACK is true, then the CALL key will toggle redrawing
- // the screen all-the-time. Good for profiling our drawing code
- static private final boolean AUTO_REDRAW_HACK = false;
- // true means redraw the screen all-the-time. Only with AUTO_REDRAW_HACK
- private boolean mAutoRedraw;
-
- // keep debugging parameters near the top of the file
- static final String LOGTAG = "webview";
- static final boolean DEBUG = false;
- static final boolean LOGV_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
-
- private class ExtendedZoomControls extends FrameLayout {
- public ExtendedZoomControls(Context context, AttributeSet attrs) {
- super(context, attrs);
- LayoutInflater inflater = (LayoutInflater)
- context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(com.android.internal.R.layout.zoom_magnify, this, true);
- mZoomControls = (ZoomControls) findViewById(com.android.internal.R.id.zoomControls);
- mZoomMagnify = (ImageView) findViewById(com.android.internal.R.id.zoomMagnify);
- }
-
- public void show(boolean showZoom, boolean canZoomOut) {
- mZoomControls.setVisibility(showZoom ? View.VISIBLE : View.GONE);
- mZoomMagnify.setVisibility(canZoomOut ? View.VISIBLE : View.GONE);
- fade(View.VISIBLE, 0.0f, 1.0f);
- }
-
- public void hide() {
- fade(View.GONE, 1.0f, 0.0f);
- }
-
- private void fade(int visibility, float startAlpha, float endAlpha) {
- AlphaAnimation anim = new AlphaAnimation(startAlpha, endAlpha);
- anim.setDuration(500);
- startAnimation(anim);
- setVisibility(visibility);
- }
-
- public void setIsZoomMagnifyEnabled(boolean isEnabled) {
- mZoomMagnify.setEnabled(isEnabled);
- }
-
- public boolean hasFocus() {
- return mZoomControls.hasFocus() || mZoomMagnify.hasFocus();
- }
-
- public void setOnZoomInClickListener(OnClickListener listener) {
- mZoomControls.setOnZoomInClickListener(listener);
- }
-
- public void setOnZoomOutClickListener(OnClickListener listener) {
- mZoomControls.setOnZoomOutClickListener(listener);
- }
-
- public void setOnZoomMagnifyClickListener(OnClickListener listener) {
- mZoomMagnify.setOnClickListener(listener);
- }
-
- ZoomControls mZoomControls;
- ImageView mZoomMagnify;
- }
-
- /**
- * Transportation object for returning WebView across thread boundaries.
- */
- public class WebViewTransport {
- private WebView mWebview;
-
- /**
- * Set the WebView to the transportation object.
- * @param webview The WebView to transport.
- */
- public synchronized void setWebView(WebView webview) {
- mWebview = webview;
- }
-
- /**
- * Return the WebView object.
- * @return WebView The transported WebView object.
- */
- public synchronized WebView getWebView() {
- return mWebview;
- }
- }
-
- // A final CallbackProxy shared by WebViewCore and BrowserFrame.
- private final CallbackProxy mCallbackProxy;
-
- private final WebViewDatabase mDatabase;
-
- // SSL certificate for the main top-level page (if secure)
- private SslCertificate mCertificate;
-
- // Native WebView pointer that is 0 until the native object has been
- // created.
- private int mNativeClass;
- // This would be final but it needs to be set to null when the WebView is
- // destroyed.
- private WebViewCore mWebViewCore;
- // Handler for dispatching UI messages.
- /* package */ final Handler mPrivateHandler = new PrivateHandler();
- private TextDialog mTextEntry;
- // Used to ignore changes to webkit text that arrives to the UI side after
- // more key events.
- private int mTextGeneration;
-
- // The list of loaded plugins.
- private static PluginList sPluginList;
-
- /**
- * Position of the last touch event.
- */
- private float mLastTouchX;
- private float mLastTouchY;
-
- /**
- * Time of the last touch event.
- */
- private long mLastTouchTime;
-
- /**
- * Time of the last time sending touch event to WebViewCore
- */
- private long mLastSentTouchTime;
-
- /**
- * The minimum elapsed time before sending another ACTION_MOVE event to
- * WebViewCore
- */
- private static final int TOUCH_SENT_INTERVAL = 100;
-
- /**
- * Helper class to get velocity for fling
- */
- VelocityTracker mVelocityTracker;
-
- private static boolean mShowZoomRingTutorial = true;
- private static final int ZOOM_RING_TUTORIAL_DURATION = 3000;
-
- /**
- * Touch mode
- */
- private int mTouchMode = TOUCH_DONE_MODE;
- private static final int TOUCH_INIT_MODE = 1;
- private static final int TOUCH_DRAG_START_MODE = 2;
- private static final int TOUCH_DRAG_MODE = 3;
- private static final int TOUCH_SHORTPRESS_START_MODE = 4;
- private static final int TOUCH_SHORTPRESS_MODE = 5;
- private static final int TOUCH_DOUBLECLICK_MODE = 6;
- private static final int TOUCH_DONE_MODE = 7;
- private static final int TOUCH_SELECT_MODE = 8;
- // touch mode values specific to scale+scroll
- private static final int FIRST_SCROLL_ZOOM = 9;
- private static final int SCROLL_ZOOM_ANIMATION_IN = 9;
- private static final int SCROLL_ZOOM_ANIMATION_OUT = 10;
- private static final int SCROLL_ZOOM_OUT = 11;
- private static final int LAST_SCROLL_ZOOM = 11;
- // end of touch mode values specific to scale+scroll
-
- // Whether to forward the touch events to WebCore
- private boolean mForwardTouchEvents = false;
-
- // Whether we are in the drag tap mode, which exists starting at the second
- // tap's down, through its move, and includes its up. These events should be
- // given to the method on the zoom controller.
- private boolean mInZoomTapDragMode = false;
-
- // Whether to prevent drag during touch. The initial value depends on
- // mForwardTouchEvents. If WebCore wants touch events, we assume it will
- // take control of touch events unless it says no for touch down event.
- private boolean mPreventDrag;
-
- // If updateTextEntry gets called while we are out of focus, use this
- // variable to remember to do it next time we gain focus.
- private boolean mNeedsUpdateTextEntry = false;
-
- // Whether or not to draw the focus ring.
- private boolean mDrawFocusRing = true;
-
- /**
- * Customizable constant
- */
- // pre-computed square of ViewConfiguration.getTouchSlop()
- private int mTouchSlopSquare;
- // This should be ViewConfiguration.getTapTimeout()
- // But system time out is 100ms, which is too short for the browser.
- // In the browser, if it switches out of tap too soon, jump tap won't work.
- private static final int TAP_TIMEOUT = 200;
- // The duration in milliseconds we will wait to see if it is a double tap.
- private static final int DOUBLE_TAP_TIMEOUT = 250;
- // This should be ViewConfiguration.getLongPressTimeout()
- // But system time out is 500ms, which is too short for the browser.
- // With a short timeout, it's difficult to treat trigger a short press.
- private static final int LONG_PRESS_TIMEOUT = 1000;
- // needed to avoid flinging after a pause of no movement
- private static final int MIN_FLING_TIME = 250;
- // The time that the Zoom Controls are visible before fading away
- private static final long ZOOM_CONTROLS_TIMEOUT =
- ViewConfiguration.getZoomControlsTimeout();
- // The amount of content to overlap between two screens when going through
- // pages with the space bar, in pixels.
- private static final int PAGE_SCROLL_OVERLAP = 24;
-
- /**
- * These prevent calling requestLayout if either dimension is fixed. This
- * depends on the layout parameters and the measure specs.
- */
- boolean mWidthCanMeasure;
- boolean mHeightCanMeasure;
-
- // Remember the last dimensions we sent to the native side so we can avoid
- // sending the same dimensions more than once.
- int mLastWidthSent;
- int mLastHeightSent;
-
- private int mContentWidth; // cache of value from WebViewCore
- private int mContentHeight; // cache of value from WebViewCore
-
- static int MAX_FLOAT_CONTENT_WIDTH = 480;
- private int mMinContentWidth;
-
- // Need to have the separate control for horizontal and vertical scrollbar
- // style than the View's single scrollbar style
- private boolean mOverlayHorizontalScrollbar = true;
- private boolean mOverlayVerticalScrollbar = false;
-
- // our standard speed. this way small distances will be traversed in less
- // time than large distances, but we cap the duration, so that very large
- // distances won't take too long to get there.
- private static final int STD_SPEED = 480; // pixels per second
- // time for the longest scroll animation
- private static final int MAX_DURATION = 750; // milliseconds
- private Scroller mScroller;
-
- private boolean mWrapContent;
-
- // The View containing the zoom controls
- private ExtendedZoomControls mZoomControls;
- private Runnable mZoomControlRunnable;
-
- // true if we should call webcore to draw the content, false means we have
- // requested something but it isn't ready to draw yet.
- private WebViewCore.FocusData mFocusData;
- /**
- * Private message ids
- */
- private static final int REMEMBER_PASSWORD = 1;
- private static final int NEVER_REMEMBER_PASSWORD = 2;
- private static final int SWITCH_TO_SHORTPRESS = 3;
- private static final int SWITCH_TO_LONGPRESS = 4;
- private static final int RELEASE_SINGLE_TAP = 5;
- private static final int UPDATE_TEXT_ENTRY_ADAPTER = 6;
- private static final int SWITCH_TO_ENTER = 7;
- private static final int RESUME_WEBCORE_UPDATE = 8;
- private static final int DISMISS_ZOOM_RING_TUTORIAL = 9;
-
- //! arg1=x, arg2=y
- static final int SCROLL_TO_MSG_ID = 10;
- static final int SCROLL_BY_MSG_ID = 11;
- //! arg1=x, arg2=y
- static final int SPAWN_SCROLL_TO_MSG_ID = 12;
- //! arg1=x, arg2=y
- static final int SYNC_SCROLL_TO_MSG_ID = 13;
- static final int NEW_PICTURE_MSG_ID = 14;
- static final int UPDATE_TEXT_ENTRY_MSG_ID = 15;
- static final int WEBCORE_INITIALIZED_MSG_ID = 16;
- static final int UPDATE_TEXTFIELD_TEXT_MSG_ID = 17;
- static final int DID_FIRST_LAYOUT_MSG_ID = 18;
- static final int RECOMPUTE_FOCUS_MSG_ID = 19;
- static final int NOTIFY_FOCUS_SET_MSG_ID = 20;
- static final int MARK_NODE_INVALID_ID = 21;
- static final int UPDATE_CLIPBOARD = 22;
- static final int LONG_PRESS_ENTER = 23;
- static final int PREVENT_TOUCH_ID = 24;
- static final int WEBCORE_NEED_TOUCH_EVENTS = 25;
- // obj=Rect in doc coordinates
- static final int INVAL_RECT_MSG_ID = 26;
-
- static final String[] HandlerDebugString = {
- "REMEMBER_PASSWORD", // = 1;
- "NEVER_REMEMBER_PASSWORD", // = 2;
- "SWITCH_TO_SHORTPRESS", // = 3;
- "SWITCH_TO_LONGPRESS", // = 4;
- "RELEASE_SINGLE_TAP", // = 5;
- "UPDATE_TEXT_ENTRY_ADAPTER", // = 6;
- "SWITCH_TO_ENTER", // = 7;
- "RESUME_WEBCORE_UPDATE", // = 8;
- "9",
- "SCROLL_TO_MSG_ID", // = 10;
- "SCROLL_BY_MSG_ID", // = 11;
- "SPAWN_SCROLL_TO_MSG_ID", // = 12;
- "SYNC_SCROLL_TO_MSG_ID", // = 13;
- "NEW_PICTURE_MSG_ID", // = 14;
- "UPDATE_TEXT_ENTRY_MSG_ID", // = 15;
- "WEBCORE_INITIALIZED_MSG_ID", // = 16;
- "UPDATE_TEXTFIELD_TEXT_MSG_ID", // = 17;
- "DID_FIRST_LAYOUT_MSG_ID", // = 18;
- "RECOMPUTE_FOCUS_MSG_ID", // = 19;
- "NOTIFY_FOCUS_SET_MSG_ID", // = 20;
- "MARK_NODE_INVALID_ID", // = 21;
- "UPDATE_CLIPBOARD", // = 22;
- "LONG_PRESS_ENTER", // = 23;
- "PREVENT_TOUCH_ID", // = 24;
- "WEBCORE_NEED_TOUCH_EVENTS", // = 25;
- "INVAL_RECT_MSG_ID" // = 26;
- };
-
- // width which view is considered to be fully zoomed out
- static final int ZOOM_OUT_WIDTH = 1024;
-
- private static final float MAX_ZOOM_RING_ANGLE = (float) (Math.PI * 2 / 3);
- private static final int ZOOM_RING_STEPS = 4;
- private static final float ZOOM_RING_ANGLE_UNIT = MAX_ZOOM_RING_ANGLE
- / ZOOM_RING_STEPS;
-
- private static final float DEFAULT_MAX_ZOOM_SCALE = 2;
- private static final float DEFAULT_MIN_ZOOM_SCALE = (float) 1/3;
- // scale limit, which can be set through viewport meta tag in the web page
- private float mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
- private float mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
-
- // initial scale in percent. 0 means using default.
- private int mInitialScale = 0;
-
- // set to true temporarily while the zoom control is being dragged
- private boolean mPreviewZoomOnly = false;
-
- // computed scale and inverse, from mZoomWidth.
- private float mActualScale = 1;
- private float mInvActualScale = 1;
- // if this is non-zero, it is used on drawing rather than mActualScale
- private float mZoomScale;
- private float mInvInitialZoomScale;
- private float mInvFinalZoomScale;
- private long mZoomStart;
- private static final int ZOOM_ANIMATION_LENGTH = 500;
-
- private boolean mUserScroll = false;
-
- private int mSnapScrollMode = SNAP_NONE;
- private static final int SNAP_NONE = 1;
- private static final int SNAP_X = 2;
- private static final int SNAP_Y = 3;
- private static final int SNAP_X_LOCK = 4;
- private static final int SNAP_Y_LOCK = 5;
- private boolean mSnapPositive;
-
- // Used to match key downs and key ups
- private boolean mGotKeyDown;
-
- /* package */ static boolean mLogEvent = true;
- private static final int EVENT_LOG_ZOOM_LEVEL_CHANGE = 70101;
- private static final int EVENT_LOG_DOUBLE_TAP_DURATION = 70102;
-
- // for event log
- private long mLastTouchUpTime = 0;
-
- /**
- * URI scheme for telephone number
- */
- public static final String SCHEME_TEL = "tel:";
- /**
- * URI scheme for email address
- */
- public static final String SCHEME_MAILTO = "mailto:";
- /**
- * URI scheme for map address
- */
- public static final String SCHEME_GEO = "geo:0,0?q=";
-
- private int mBackgroundColor = Color.WHITE;
-
- // Used to notify listeners of a new picture.
- private PictureListener mPictureListener;
- /**
- * Interface to listen for new pictures as they change.
- */
- public interface PictureListener {
- /**
- * Notify the listener that the picture has changed.
- * @param view The WebView that owns the picture.
- * @param picture The new picture.
- */
- public void onNewPicture(WebView view, Picture picture);
- }
-
- public class HitTestResult {
- /**
- * Default HitTestResult, where the target is unknown
- */
- public static final int UNKNOWN_TYPE = 0;
- /**
- * HitTestResult for hitting a HTML::a tag
- */
- public static final int ANCHOR_TYPE = 1;
- /**
- * HitTestResult for hitting a phone number
- */
- public static final int PHONE_TYPE = 2;
- /**
- * HitTestResult for hitting a map address
- */
- public static final int GEO_TYPE = 3;
- /**
- * HitTestResult for hitting an email address
- */
- public static final int EMAIL_TYPE = 4;
- /**
- * HitTestResult for hitting an HTML::img tag
- */
- public static final int IMAGE_TYPE = 5;
- /**
- * HitTestResult for hitting a HTML::a tag which contains HTML::img
- */
- public static final int IMAGE_ANCHOR_TYPE = 6;
- /**
- * HitTestResult for hitting a HTML::a tag with src=http
- */
- public static final int SRC_ANCHOR_TYPE = 7;
- /**
- * HitTestResult for hitting a HTML::a tag with src=http + HTML::img
- */
- public static final int SRC_IMAGE_ANCHOR_TYPE = 8;
- /**
- * HitTestResult for hitting an edit text area
- */
- public static final int EDIT_TEXT_TYPE = 9;
-
- private int mType;
- private String mExtra;
-
- HitTestResult() {
- mType = UNKNOWN_TYPE;
- }
-
- private void setType(int type) {
- mType = type;
- }
-
- private void setExtra(String extra) {
- mExtra = extra;
- }
-
- public int getType() {
- return mType;
- }
-
- public String getExtra() {
- return mExtra;
- }
- }
-
- private ZoomRingController mZoomRingController;
- private ImageView mZoomRingOverview;
- private Animation mZoomRingOverviewExitAnimation;
-
- // These keep track of the center point of the zoom ring. They are used to
- // determine the point around which we should zoom.
- private float mZoomCenterX;
- private float mZoomCenterY;
-
- private ZoomRingController.OnZoomListener mZoomListener =
- new ZoomRingController.OnZoomListener() {
-
- private float mClockwiseBound;
- private float mCounterClockwiseBound;
- private float mStartScale;
-
- public void onCenter(int x, int y) {
- // Don't translate when the control is invoked, hence we do nothing
- // in this callback
- }
-
- public void onBeginPan() {
- setZoomOverviewVisible(false);
- if (mLogEvent) {
- Checkin.updateStats(mContext.getContentResolver(),
- Checkin.Stats.Tag.BROWSER_ZOOM_RING_DRAG, 1, 0.0);
- }
- }
-
- public boolean onPan(int deltaX, int deltaY) {
- return pinScrollBy(deltaX, deltaY, false, 0);
- }
-
- public void onEndPan() {
- }
-
- public void onVisibilityChanged(boolean visible) {
- if (visible) {
- switchOutDrawHistory();
- if (mMaxZoomScale - 1 > ZOOM_RING_STEPS * 0.01f) {
- mClockwiseBound = (float) (2 * Math.PI - MAX_ZOOM_RING_ANGLE);
- } else {
- mClockwiseBound = (float) (2 * Math.PI);
- }
- mZoomRingController.setThumbClockwiseBound(mClockwiseBound);
- if (1 - mMinZoomScale > ZOOM_RING_STEPS * 0.01f) {
- mCounterClockwiseBound = MAX_ZOOM_RING_ANGLE;
- } else {
- mCounterClockwiseBound = 0;
- }
- mZoomRingController
- .setThumbCounterclockwiseBound(mCounterClockwiseBound);
- float angle = 0f;
- if (mActualScale > 1 && mClockwiseBound < (float) (2 * Math.PI)) {
- angle = -(float) Math.round(ZOOM_RING_STEPS
- * (mActualScale - 1) / (mMaxZoomScale - 1))
- / ZOOM_RING_STEPS;
- } else if (mActualScale < 1 && mCounterClockwiseBound > 0) {
- angle = (float) Math.round(ZOOM_RING_STEPS
- * (1 - mActualScale) / (1 - mMinZoomScale))
- / ZOOM_RING_STEPS;
- }
- mZoomRingController.setThumbAngle(angle * MAX_ZOOM_RING_ANGLE);
-
- // Show the zoom overview tab on the ring
- setZoomOverviewVisible(true);
- if (mLogEvent) {
- Checkin.updateStats(mContext.getContentResolver(),
- Checkin.Stats.Tag.BROWSER_ZOOM_RING, 1, 0.0);
- }
- }
- }
-
- public void onBeginDrag() {
- mPreviewZoomOnly = true;
- mStartScale = mActualScale;
- setZoomOverviewVisible(false);
- }
-
- public void onEndDrag() {
- mPreviewZoomOnly = false;
- if (mLogEvent) {
- EventLog.writeEvent(EVENT_LOG_ZOOM_LEVEL_CHANGE,
- (int) mStartScale * 100, (int) mActualScale * 100,
- System.currentTimeMillis());
- }
- setNewZoomScale(mActualScale, true);
- }
-
- public boolean onDragZoom(int deltaZoomLevel, int centerX,
- int centerY, float startAngle, float curAngle) {
- if (deltaZoomLevel < 0
- && Math.abs(mActualScale - mMinZoomScale) < 0.01f
- || deltaZoomLevel > 0
- && Math.abs(mActualScale - mMaxZoomScale) < 0.01f
- || deltaZoomLevel == 0) {
- return false;
- }
- mZoomCenterX = (float) centerX;
- mZoomCenterY = (float) centerY;
-
- float scale = 1.0f;
- // curAngle is [0, 2 * Math.PI)
- if (curAngle < (float) Math.PI) {
- if (curAngle >= mCounterClockwiseBound) {
- scale = mMinZoomScale;
- } else {
- scale = 1 - (float) Math.round(curAngle
- / ZOOM_RING_ANGLE_UNIT) / ZOOM_RING_STEPS
- * (1 - mMinZoomScale);
- }
- } else {
- if (curAngle <= mClockwiseBound) {
- scale = mMaxZoomScale;
- } else {
- scale = 1 + (float) Math.round(
- ((float) 2 * Math.PI - curAngle)
- / ZOOM_RING_ANGLE_UNIT) / ZOOM_RING_STEPS
- * (mMaxZoomScale - 1);
- }
- }
- zoomWithPreview(scale);
- return true;
- }
-
- public void onSimpleZoom(boolean zoomIn) {
- if (zoomIn) {
- zoomIn();
- } else {
- zoomOut();
- }
- }
-
- };
-
- /**
- * Construct a new WebView with a Context object.
- * @param context A Context object used to access application assets.
- */
- public WebView(Context context) {
- this(context, null);
- }
-
- /**
- * Construct a new WebView with layout parameters.
- * @param context A Context object used to access application assets.
- * @param attrs An AttributeSet passed to our parent.
- */
- public WebView(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.webViewStyle);
- }
-
- /**
- * Construct a new WebView with layout parameters and a default style.
- * @param context A Context object used to access application assets.
- * @param attrs An AttributeSet passed to our parent.
- * @param defStyle The default style resource ID.
- */
- public WebView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init();
-
- mCallbackProxy = new CallbackProxy(context, this);
- mWebViewCore = new WebViewCore(context, this, mCallbackProxy);
- mDatabase = WebViewDatabase.getInstance(context);
- mFocusData = new WebViewCore.FocusData();
- mFocusData.mFrame = 0;
- mFocusData.mNode = 0;
- mFocusData.mX = 0;
- mFocusData.mY = 0;
- mScroller = new Scroller(context);
- mZoomRingController = new ZoomRingController(context, this);
- mZoomRingController.setResetThumbAutomatically(false);
- mZoomRingController.setCallback(mZoomListener);
- mZoomRingController.setZoomRingTrack(
- com.android.internal.R.drawable.zoom_ring_track_absolute);
- mZoomRingController.setPannerAcceleration(160);
- mZoomRingController.setPannerStartAcceleratingDuration(700);
- createZoomRingOverviewTab();
- }
-
- private void init() {
- setWillNotDraw(false);
- setFocusable(true);
- setFocusableInTouchMode(true);
- setClickable(true);
- setLongClickable(true);
-
- final int slop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- mTouchSlopSquare = slop * slop;
- mMinLockSnapReverseDistance = slop;
- }
-
- private void createZoomRingOverviewTab() {
- Context context = getContext();
-
- mZoomRingOverviewExitAnimation = AnimationUtils.loadAnimation(context,
- com.android.internal.R.anim.fade_out);
-
- mZoomRingOverview = new ImageView(context);
- mZoomRingOverview.setBackgroundResource(
- com.android.internal.R.drawable.zoom_ring_overview_tab);
- mZoomRingOverview.setImageResource(com.android.internal.R.drawable.btn_zoom_page);
-
- FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
- FrameLayout.LayoutParams.WRAP_CONTENT,
- FrameLayout.LayoutParams.WRAP_CONTENT,
- Gravity.CENTER);
- // TODO: magic constant that's based on the zoom ring radius + some offset
- lp.topMargin = 208;
- mZoomRingOverview.setLayoutParams(lp);
- mZoomRingOverview.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- // Hide the zoom ring
- mZoomRingController.setVisible(false);
- if (mLogEvent) {
- Checkin.updateStats(mContext.getContentResolver(),
- Checkin.Stats.Tag.BROWSER_ZOOM_OVERVIEW, 1, 0.0);
- }
- zoomScrollOut();
- }});
-
- // Measure the overview View to figure out its height
- mZoomRingOverview.forceLayout();
- mZoomRingOverview.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
-
- ViewGroup container = mZoomRingController.getContainer();
- // Find the index of the zoom ring in the container
- View zoomRing = container.findViewById(mZoomRingController.getZoomRingId());
- int zoomRingIndex;
- for (zoomRingIndex = container.getChildCount() - 1; zoomRingIndex >= 0; zoomRingIndex--) {
- if (container.getChildAt(zoomRingIndex) == zoomRing) break;
- }
- // Add the overview tab below the zoom ring (so we don't steal its events)
- container.addView(mZoomRingOverview, zoomRingIndex);
- // Since we use margins to adjust the vertical placement of the tab, the widget
- // ends up getting clipped off. Ensure the container is big enough for
- // us.
- int myHeight = mZoomRingOverview.getMeasuredHeight() + lp.topMargin / 2;
- // Multiplied by 2 b/c the zoom ring needs to be centered on the screen
- container.setMinimumHeight(myHeight * 2);
- }
-
- private void setZoomOverviewVisible(boolean visible) {
- int newVisibility = visible ? View.VISIBLE : View.INVISIBLE;
- if (mZoomRingOverview.getVisibility() == newVisibility) return;
-
- if (!visible) {
- mZoomRingOverview.startAnimation(mZoomRingOverviewExitAnimation);
- }
- mZoomRingOverview.setVisibility(newVisibility);
- }
-
- /* package */ boolean onSavePassword(String schemePlusHost, String username,
- String password, final Message resumeMsg) {
- boolean rVal = false;
- if (resumeMsg == null) {
- // null resumeMsg implies saving password silently
- mDatabase.setUsernamePassword(schemePlusHost, username, password);
- } else {
- final Message remember = mPrivateHandler.obtainMessage(
- REMEMBER_PASSWORD);
- remember.getData().putString("host", schemePlusHost);
- remember.getData().putString("username", username);
- remember.getData().putString("password", password);
- remember.obj = resumeMsg;
-
- final Message neverRemember = mPrivateHandler.obtainMessage(
- NEVER_REMEMBER_PASSWORD);
- neverRemember.getData().putString("host", schemePlusHost);
- neverRemember.getData().putString("username", username);
- neverRemember.getData().putString("password", password);
- neverRemember.obj = resumeMsg;
-
- new AlertDialog.Builder(getContext())
- .setTitle(com.android.internal.R.string.save_password_label)
- .setMessage(com.android.internal.R.string.save_password_message)
- .setPositiveButton(com.android.internal.R.string.save_password_notnow,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- resumeMsg.sendToTarget();
- }
- })
- .setNeutralButton(com.android.internal.R.string.save_password_remember,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- remember.sendToTarget();
- }
- })
- .setNegativeButton(com.android.internal.R.string.save_password_never,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- neverRemember.sendToTarget();
- }
- })
- .setOnCancelListener(new OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- resumeMsg.sendToTarget();
- }
- }).show();
- // Return true so that WebViewCore will pause while the dialog is
- // up.
- rVal = true;
- }
- return rVal;
- }
-
- @Override
- public void setScrollBarStyle(int style) {
- if (style == View.SCROLLBARS_INSIDE_INSET
- || style == View.SCROLLBARS_OUTSIDE_INSET) {
- mOverlayHorizontalScrollbar = mOverlayVerticalScrollbar = false;
- } else {
- mOverlayHorizontalScrollbar = mOverlayVerticalScrollbar = true;
- }
- super.setScrollBarStyle(style);
- }
-
- /**
- * Specify whether the horizontal scrollbar has overlay style.
- * @param overlay TRUE if horizontal scrollbar should have overlay style.
- */
- public void setHorizontalScrollbarOverlay(boolean overlay) {
- mOverlayHorizontalScrollbar = overlay;
- }
-
- /**
- * Specify whether the vertical scrollbar has overlay style.
- * @param overlay TRUE if vertical scrollbar should have overlay style.
- */
- public void setVerticalScrollbarOverlay(boolean overlay) {
- mOverlayVerticalScrollbar = overlay;
- }
-
- /**
- * Return whether horizontal scrollbar has overlay style
- * @return TRUE if horizontal scrollbar has overlay style.
- */
- public boolean overlayHorizontalScrollbar() {
- return mOverlayHorizontalScrollbar;
- }
-
- /**
- * Return whether vertical scrollbar has overlay style
- * @return TRUE if vertical scrollbar has overlay style.
- */
- public boolean overlayVerticalScrollbar() {
- return mOverlayVerticalScrollbar;
- }
-
- /*
- * Return the width of the view where the content of WebView should render
- * to.
- */
- private int getViewWidth() {
- if (!isVerticalScrollBarEnabled() || mOverlayVerticalScrollbar) {
- return getWidth();
- } else {
- return getWidth() - getVerticalScrollbarWidth();
- }
- }
-
- /*
- * Return the height of the view where the content of WebView should render
- * to.
- */
- private int getViewHeight() {
- if (!isHorizontalScrollBarEnabled() || mOverlayHorizontalScrollbar) {
- return getHeight();
- } else {
- return getHeight() - getHorizontalScrollbarHeight();
- }
- }
-
- /**
- * @return The SSL certificate for the main top-level page or null if
- * there is no certificate (the site is not secure).
- */
- public SslCertificate getCertificate() {
- return mCertificate;
- }
-
- /**
- * Sets the SSL certificate for the main top-level page.
- */
- public void setCertificate(SslCertificate certificate) {
- // here, the certificate can be null (if the site is not secure)
- mCertificate = certificate;
- }
-
- //-------------------------------------------------------------------------
- // Methods called by activity
- //-------------------------------------------------------------------------
-
- /**
- * Save the username and password for a particular host in the WebView's
- * internal database.
- * @param host The host that required the credentials.
- * @param username The username for the given host.
- * @param password The password for the given host.
- */
- public void savePassword(String host, String username, String password) {
- mDatabase.setUsernamePassword(host, username, password);
- }
-
- /**
- * Set the HTTP authentication credentials for a given host and realm.
- *
- * @param host The host for the credentials.
- * @param realm The realm for the credentials.
- * @param username The username for the password. If it is null, it means
- * password can't be saved.
- * @param password The password
- */
- public void setHttpAuthUsernamePassword(String host, String realm,
- String username, String password) {
- mDatabase.setHttpAuthUsernamePassword(host, realm, username, password);
- }
-
- /**
- * Retrieve the HTTP authentication username and password for a given
- * host & realm pair
- *
- * @param host The host for which the credentials apply.
- * @param realm The realm for which the credentials apply.
- * @return String[] if found, String[0] is username, which can be null and
- * String[1] is password. Return null if it can't find anything.
- */
- public String[] getHttpAuthUsernamePassword(String host, String realm) {
- return mDatabase.getHttpAuthUsernamePassword(host, realm);
- }
-
- /**
- * Destroy the internal state of the WebView. This method should be called
- * after the WebView has been removed from the view system. No other
- * methods may be called on a WebView after destroy.
- */
- public void destroy() {
- clearTextEntry();
- if (mWebViewCore != null) {
- // Set the handlers to null before destroying WebViewCore so no
- // more messages will be posted.
- mCallbackProxy.setWebViewClient(null);
- mCallbackProxy.setWebChromeClient(null);
- // Tell WebViewCore to destroy itself
- WebViewCore webViewCore = mWebViewCore;
- mWebViewCore = null; // prevent using partial webViewCore
- webViewCore.destroy();
- // Remove any pending messages that might not be serviced yet.
- mPrivateHandler.removeCallbacksAndMessages(null);
- mCallbackProxy.removeCallbacksAndMessages(null);
- // Wake up the WebCore thread just in case it is waiting for a
- // javascript dialog.
- synchronized (mCallbackProxy) {
- mCallbackProxy.notify();
- }
- }
- if (mNativeClass != 0) {
- nativeDestroy();
- mNativeClass = 0;
- }
- }
-
- /**
- * Enables platform notifications of data state and proxy changes.
- */
- public static void enablePlatformNotifications() {
- Network.enablePlatformNotifications();
- }
-
- /**
- * If platform notifications are enabled, this should be called
- * from onPause() or onStop().
- */
- public static void disablePlatformNotifications() {
- Network.disablePlatformNotifications();
- }
-
- /**
- * Inform WebView of the network state. This is used to set
- * the javascript property window.navigator.isOnline and
- * generates the online/offline event as specified in HTML5, sec. 5.7.7
- * @param networkUp boolean indicating if network is available
- *
- * @hide pending API Council approval
- */
- public void setNetworkAvailable(boolean networkUp) {
- BrowserFrame.sJavaBridge.setNetworkOnLine(networkUp);
- }
-
- /**
- * Save the state of this WebView used in
- * {@link android.app.Activity#onSaveInstanceState}. Please note that this
- * method no longer stores the display data for this WebView. The previous
- * behavior could potentially leak files if {@link #restoreState} was never
- * called. See {@link #savePicture} and {@link #restorePicture} for saving
- * and restoring the display data.
- * @param outState The Bundle to store the WebView state.
- * @return The same copy of the back/forward list used to save the state. If
- * saveState fails, the returned list will be null.
- * @see #savePicture
- * @see #restorePicture
- */
- public WebBackForwardList saveState(Bundle outState) {
- if (outState == null) {
- return null;
- }
- // We grab a copy of the back/forward list because a client of WebView
- // may have invalidated the history list by calling clearHistory.
- WebBackForwardList list = copyBackForwardList();
- final int currentIndex = list.getCurrentIndex();
- final int size = list.getSize();
- // We should fail saving the state if the list is empty or the index is
- // not in a valid range.
- if (currentIndex < 0 || currentIndex >= size || size == 0) {
- return null;
- }
- outState.putInt("index", currentIndex);
- // FIXME: This should just be a byte[][] instead of ArrayList but
- // Parcel.java does not have the code to handle multi-dimensional
- // arrays.
- ArrayList<byte[]> history = new ArrayList<byte[]>(size);
- for (int i = 0; i < size; i++) {
- WebHistoryItem item = list.getItemAtIndex(i);
- byte[] data = item.getFlattenedData();
- if (data == null) {
- // It would be very odd to not have any data for a given history
- // item. And we will fail to rebuild the history list without
- // flattened data.
- return null;
- }
- history.add(data);
- }
- outState.putSerializable("history", history);
- if (mCertificate != null) {
- outState.putBundle("certificate",
- SslCertificate.saveState(mCertificate));
- }
- return list;
- }
-
- /**
- * Save the current display data to the Bundle given. Used in conjunction
- * with {@link #saveState}.
- * @param b A Bundle to store the display data.
- * @param dest The file to store the serialized picture data. Will be
- * overwritten with this WebView's picture data.
- * @return True if the picture was successfully saved.
- */
- public boolean savePicture(Bundle b, File dest) {
- if (dest == null || b == null) {
- return false;
- }
- final Picture p = capturePicture();
- try {
- final FileOutputStream out = new FileOutputStream(dest);
- p.writeToStream(out);
- out.close();
- } catch (FileNotFoundException e){
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (RuntimeException e) {
- e.printStackTrace();
- }
- if (dest.length() > 0) {
- b.putInt("scrollX", mScrollX);
- b.putInt("scrollY", mScrollY);
- b.putFloat("scale", mActualScale);
- return true;
- }
- return false;
- }
-
- /**
- * Restore the display data that was save in {@link #savePicture}. Used in
- * conjunction with {@link #restoreState}.
- * @param b A Bundle containing the saved display data.
- * @param src The file where the picture data was stored.
- * @return True if the picture was successfully restored.
- */
- public boolean restorePicture(Bundle b, File src) {
- if (src == null || b == null) {
- return false;
- }
- if (src.exists()) {
- Picture p = null;
- try {
- final FileInputStream in = new FileInputStream(src);
- p = Picture.createFromStream(in);
- in.close();
- } catch (FileNotFoundException e){
- e.printStackTrace();
- } catch (RuntimeException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- if (p != null) {
- int sx = b.getInt("scrollX", 0);
- int sy = b.getInt("scrollY", 0);
- float scale = b.getFloat("scale", 1.0f);
- mDrawHistory = true;
- mHistoryPicture = p;
- mScrollX = sx;
- mScrollY = sy;
- mHistoryWidth = Math.round(p.getWidth() * scale);
- mHistoryHeight = Math.round(p.getHeight() * scale);
- // as getWidth() / getHeight() of the view are not
- // available yet, set up mActualScale, so that when
- // onSizeChanged() is called, the rest will be set
- // correctly
- mActualScale = scale;
- invalidate();
- return true;
- }
- }
- return false;
- }
-
- /**
- * Restore the state of this WebView from the given map used in
- * {@link android.app.Activity#onRestoreInstanceState}. This method should
- * be called to restore the state of the WebView before using the object. If
- * it is called after the WebView has had a chance to build state (load
- * pages, create a back/forward list, etc.) there may be undesirable
- * side-effects. Please note that this method no longer restores the
- * display data for this WebView. See {@link #savePicture} and {@link
- * #restorePicture} for saving and restoring the display data.
- * @param inState The incoming Bundle of state.
- * @return The restored back/forward list or null if restoreState failed.
- * @see #savePicture
- * @see #restorePicture
- */
- public WebBackForwardList restoreState(Bundle inState) {
- WebBackForwardList returnList = null;
- if (inState == null) {
- return returnList;
- }
- if (inState.containsKey("index") && inState.containsKey("history")) {
- mCertificate = SslCertificate.restoreState(
- inState.getBundle("certificate"));
-
- final WebBackForwardList list = mCallbackProxy.getBackForwardList();
- final int index = inState.getInt("index");
- // We can't use a clone of the list because we need to modify the
- // shared copy, so synchronize instead to prevent concurrent
- // modifications.
- synchronized (list) {
- final List<byte[]> history =
- (List<byte[]>) inState.getSerializable("history");
- final int size = history.size();
- // Check the index bounds so we don't crash in native code while
- // restoring the history index.
- if (index < 0 || index >= size) {
- return null;
- }
- for (int i = 0; i < size; i++) {
- byte[] data = history.remove(0);
- if (data == null) {
- // If we somehow have null data, we cannot reconstruct
- // the item and thus our history list cannot be rebuilt.
- return null;
- }
- WebHistoryItem item = new WebHistoryItem(data);
- list.addHistoryItem(item);
- }
- // Grab the most recent copy to return to the caller.
- returnList = copyBackForwardList();
- // Update the copy to have the correct index.
- returnList.setCurrentIndex(index);
- }
- // Remove all pending messages because we are restoring previous
- // state.
- mWebViewCore.removeMessages();
- // Send a restore state message.
- mWebViewCore.sendMessage(EventHub.RESTORE_STATE, index);
- }
- return returnList;
- }
-
- /**
- * Load the given url.
- * @param url The url of the resource to load.
- */
- public void loadUrl(String url) {
- switchOutDrawHistory();
- mWebViewCore.sendMessage(EventHub.LOAD_URL, url);
- clearTextEntry();
- }
-
- /**
- * Load the given data into the WebView. This will load the data into
- * WebView using the data: scheme. Content loaded through this mechanism
- * does not have the ability to load content from the network.
- * @param data A String of data in the given encoding.
- * @param mimeType The MIMEType of the data. i.e. text/html, image/jpeg
- * @param encoding The encoding of the data. i.e. utf-8, base64
- */
- public void loadData(String data, String mimeType, String encoding) {
- loadUrl("data:" + mimeType + ";" + encoding + "," + data);
- }
-
- /**
- * Load the given data into the WebView, use the provided URL as the base
- * URL for the content. The base URL is the URL that represents the page
- * that is loaded through this interface. As such, it is used for the
- * history entry and to resolve any relative URLs. The failUrl is used if
- * browser fails to load the data provided. If it is empty or null, and the
- * load fails, then no history entry is created.
- * <p>
- * Note for post 1.0. Due to the change in the WebKit, the access to asset
- * files through "file:///android_asset/" for the sub resources is more
- * restricted. If you provide null or empty string as baseUrl, you won't be
- * able to access asset files. If the baseUrl is anything other than
- * http(s)/ftp(s)/about/javascript as scheme, you can access asset files for
- * sub resources.
- *
- * @param baseUrl Url to resolve relative paths with, if null defaults to
- * "about:blank"
- * @param data A String of data in the given encoding.
- * @param mimeType The MIMEType of the data. i.e. text/html. If null,
- * defaults to "text/html"
- * @param encoding The encoding of the data. i.e. utf-8, us-ascii
- * @param failUrl URL to use if the content fails to load or null.
- */
- public void loadDataWithBaseURL(String baseUrl, String data,
- String mimeType, String encoding, String failUrl) {
-
- if (baseUrl != null && baseUrl.toLowerCase().startsWith("data:")) {
- loadData(data, mimeType, encoding);
- return;
- }
- switchOutDrawHistory();
- HashMap arg = new HashMap();
- arg.put("baseUrl", baseUrl);
- arg.put("data", data);
- arg.put("mimeType", mimeType);
- arg.put("encoding", encoding);
- arg.put("failUrl", failUrl);
- mWebViewCore.sendMessage(EventHub.LOAD_DATA, arg);
- clearTextEntry();
- }
-
- /**
- * Stop the current load.
- */
- public void stopLoading() {
- // TODO: should we clear all the messages in the queue before sending
- // STOP_LOADING?
- switchOutDrawHistory();
- mWebViewCore.sendMessage(EventHub.STOP_LOADING);
- }
-
- /**
- * Reload the current url.
- */
- public void reload() {
- switchOutDrawHistory();
- mWebViewCore.sendMessage(EventHub.RELOAD);
- }
-
- /**
- * Return true if this WebView has a back history item.
- * @return True iff this WebView has a back history item.
- */
- public boolean canGoBack() {
- WebBackForwardList l = mCallbackProxy.getBackForwardList();
- synchronized (l) {
- if (l.getClearPending()) {
- return false;
- } else {
- return l.getCurrentIndex() > 0;
- }
- }
- }
-
- /**
- * Go back in the history of this WebView.
- */
- public void goBack() {
- goBackOrForward(-1);
- }
-
- /**
- * Return true if this WebView has a forward history item.
- * @return True iff this Webview has a forward history item.
- */
- public boolean canGoForward() {
- WebBackForwardList l = mCallbackProxy.getBackForwardList();
- synchronized (l) {
- if (l.getClearPending()) {
- return false;
- } else {
- return l.getCurrentIndex() < l.getSize() - 1;
- }
- }
- }
-
- /**
- * Go forward in the history of this WebView.
- */
- public void goForward() {
- goBackOrForward(1);
- }
-
- /**
- * Return true if the page can go back or forward the given
- * number of steps.
- * @param steps The negative or positive number of steps to move the
- * history.
- */
- public boolean canGoBackOrForward(int steps) {
- WebBackForwardList l = mCallbackProxy.getBackForwardList();
- synchronized (l) {
- if (l.getClearPending()) {
- return false;
- } else {
- int newIndex = l.getCurrentIndex() + steps;
- return newIndex >= 0 && newIndex < l.getSize();
- }
- }
- }
-
- /**
- * Go to the history item that is the number of steps away from
- * the current item. Steps is negative if backward and positive
- * if forward.
- * @param steps The number of steps to take back or forward in the back
- * forward list.
- */
- public void goBackOrForward(int steps) {
- goBackOrForward(steps, false);
- }
-
- private void goBackOrForward(int steps, boolean ignoreSnapshot) {
- // every time we go back or forward, we want to reset the
- // WebView certificate:
- // if the new site is secure, we will reload it and get a
- // new certificate set;
- // if the new site is not secure, the certificate must be
- // null, and that will be the case
- mCertificate = null;
- if (steps != 0) {
- clearTextEntry();
- mWebViewCore.sendMessage(EventHub.GO_BACK_FORWARD, steps,
- ignoreSnapshot ? 1 : 0);
- }
- }
-
- private boolean extendScroll(int y) {
- int finalY = mScroller.getFinalY();
- int newY = pinLocY(finalY + y);
- if (newY == finalY) return false;
- mScroller.setFinalY(newY);
- mScroller.extendDuration(computeDuration(0, y));
- return true;
- }
-
- /**
- * Scroll the contents of the view up by half the view size
- * @param top true to jump to the top of the page
- * @return true if the page was scrolled
- */
- public boolean pageUp(boolean top) {
- if (mNativeClass == 0) {
- return false;
- }
- nativeClearFocus(-1, -1);
- if (top) {
- // go to the top of the document
- return pinScrollTo(mScrollX, 0, true, 0);
- }
- // Page up
- int h = getHeight();
- int y;
- if (h > 2 * PAGE_SCROLL_OVERLAP) {
- y = -h + PAGE_SCROLL_OVERLAP;
- } else {
- y = -h / 2;
- }
- mUserScroll = true;
- return mScroller.isFinished() ? pinScrollBy(0, y, true, 0)
- : extendScroll(y);
- }
-
- /**
- * Scroll the contents of the view down by half the page size
- * @param bottom true to jump to bottom of page
- * @return true if the page was scrolled
- */
- public boolean pageDown(boolean bottom) {
- if (mNativeClass == 0) {
- return false;
- }
- nativeClearFocus(-1, -1);
- if (bottom) {
- return pinScrollTo(mScrollX, mContentHeight, true, 0);
- }
- // Page down.
- int h = getHeight();
- int y;
- if (h > 2 * PAGE_SCROLL_OVERLAP) {
- y = h - PAGE_SCROLL_OVERLAP;
- } else {
- y = h / 2;
- }
- mUserScroll = true;
- return mScroller.isFinished() ? pinScrollBy(0, y, true, 0)
- : extendScroll(y);
- }
-
- /**
- * Clear the view so that onDraw() will draw nothing but white background,
- * and onMeasure() will return 0 if MeasureSpec is not MeasureSpec.EXACTLY
- */
- public void clearView() {
- mContentWidth = 0;
- mContentHeight = 0;
- mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
- }
-
- /**
- * Return a new picture that captures the current display of the webview.
- * This is a copy of the display, and will be unaffected if the webview
- * later loads a different URL.
- *
- * @return a picture containing the current contents of the view. Note this
- * picture is of the entire document, and is not restricted to the
- * bounds of the view.
- */
- public Picture capturePicture() {
- if (null == mWebViewCore) return null; // check for out of memory tab
- return mWebViewCore.copyContentPicture();
- }
-
- /**
- * Return true if the browser is displaying a TextView for text input.
- */
- private boolean inEditingMode() {
- return mTextEntry != null && mTextEntry.getParent() != null
- && mTextEntry.hasFocus();
- }
-
- private void clearTextEntry() {
- if (inEditingMode()) {
- mTextEntry.remove();
- }
- }
-
- /**
- * Return the current scale of the WebView
- * @return The current scale.
- */
- public float getScale() {
- return mActualScale;
- }
-
- /**
- * Set the initial scale for the WebView. 0 means default. If
- * {@link WebSettings#getUseWideViewPort()} is true, it zooms out all the
- * way. Otherwise it starts with 100%. If initial scale is greater than 0,
- * WebView starts will this value as initial scale.
- *
- * @param scaleInPercent The initial scale in percent.
- */
- public void setInitialScale(int scaleInPercent) {
- mInitialScale = scaleInPercent;
- }
-
- /**
- * Invoke the graphical zoom picker widget for this WebView. This will
- * result in the zoom widget appearing on the screen to control the zoom
- * level of this WebView.
- */
- public void invokeZoomPicker() {
- if (!getSettings().supportZoom()) {
- Log.w(LOGTAG, "This WebView doesn't support zoom.");
- return;
- }
- clearTextEntry();
- ExtendedZoomControls zoomControls = (ExtendedZoomControls)
- getZoomControls();
- zoomControls.show(true, canZoomScrollOut());
- zoomControls.requestFocus();
- mPrivateHandler.removeCallbacks(mZoomControlRunnable);
- mPrivateHandler.postDelayed(mZoomControlRunnable,
- ZOOM_CONTROLS_TIMEOUT);
- }
-
- /**
- * Return a HitTestResult based on the current focus node. If a HTML::a tag
- * is found and the anchor has a non-javascript url, the HitTestResult type
- * is set to SRC_ANCHOR_TYPE and the url is set in the "extra" field. If the
- * anchor does not have a url or if it is a javascript url, the type will
- * be UNKNOWN_TYPE and the url has to be retrieved through
- * {@link #requestFocusNodeHref} asynchronously. If a HTML::img tag is
- * found, the HitTestResult type is set to IMAGE_TYPE and the url is set in
- * the "extra" field. A type of
- * SRC_IMAGE_ANCHOR_TYPE indicates an anchor with a url that has an image as
- * a child node. If a phone number is found, the HitTestResult type is set
- * to PHONE_TYPE and the phone number is set in the "extra" field of
- * HitTestResult. If a map address is found, the HitTestResult type is set
- * to GEO_TYPE and the address is set in the "extra" field of HitTestResult.
- * If an email address is found, the HitTestResult type is set to EMAIL_TYPE
- * and the email is set in the "extra" field of HitTestResult. Otherwise,
- * HitTestResult type is set to UNKNOWN_TYPE.
- */
- public HitTestResult getHitTestResult() {
- if (mNativeClass == 0) {
- return null;
- }
-
- HitTestResult result = new HitTestResult();
-
- if (nativeUpdateFocusNode()) {
- FocusNode node = mFocusNode;
- if (node.mIsTextField || node.mIsTextArea) {
- result.setType(HitTestResult.EDIT_TEXT_TYPE);
- } else if (node.mText != null) {
- String text = node.mText;
- if (text.startsWith(SCHEME_TEL)) {
- result.setType(HitTestResult.PHONE_TYPE);
- result.setExtra(text.substring(SCHEME_TEL.length()));
- } else if (text.startsWith(SCHEME_MAILTO)) {
- result.setType(HitTestResult.EMAIL_TYPE);
- result.setExtra(text.substring(SCHEME_MAILTO.length()));
- } else if (text.startsWith(SCHEME_GEO)) {
- result.setType(HitTestResult.GEO_TYPE);
- result.setExtra(URLDecoder.decode(text
- .substring(SCHEME_GEO.length())));
- } else if (node.mIsAnchor) {
- result.setType(HitTestResult.SRC_ANCHOR_TYPE);
- result.setExtra(text);
- }
- }
- }
- int type = result.getType();
- if (type == HitTestResult.UNKNOWN_TYPE
- || type == HitTestResult.SRC_ANCHOR_TYPE) {
- // Now check to see if it is an image.
- int contentX = viewToContent((int) mLastTouchX + mScrollX);
- int contentY = viewToContent((int) mLastTouchY + mScrollY);
- String text = nativeImageURI(contentX, contentY);
- if (text != null) {
- result.setType(type == HitTestResult.UNKNOWN_TYPE ?
- HitTestResult.IMAGE_TYPE :
- HitTestResult.SRC_IMAGE_ANCHOR_TYPE);
- result.setExtra(text);
- }
- }
- return result;
- }
-
- /**
- * Request the href of an anchor element due to getFocusNodePath returning
- * "href." If hrefMsg is null, this method returns immediately and does not
- * dispatch hrefMsg to its target.
- *
- * @param hrefMsg This message will be dispatched with the result of the
- * request as the data member with "url" as key. The result can
- * be null.
- */
- public void requestFocusNodeHref(Message hrefMsg) {
- if (hrefMsg == null || mNativeClass == 0) {
- return;
- }
- if (nativeUpdateFocusNode()) {
- FocusNode node = mFocusNode;
- if (node.mIsAnchor) {
- // NOTE: We may already have the url of the anchor stored in
- // node.mText but it may be out of date or the caller may want
- // to know about javascript urls.
- mWebViewCore.sendMessage(EventHub.REQUEST_FOCUS_HREF,
- node.mFramePointer, node.mNodePointer, hrefMsg);
- }
- }
- }
-
- /**
- * Request the url of the image last touched by the user. msg will be sent
- * to its target with a String representing the url as its object.
- *
- * @param msg This message will be dispatched with the result of the request
- * as the data member with "url" as key. The result can be null.
- */
- public void requestImageRef(Message msg) {
- int contentX = viewToContent((int) mLastTouchX + mScrollX);
- int contentY = viewToContent((int) mLastTouchY + mScrollY);
- String ref = nativeImageURI(contentX, contentY);
- Bundle data = msg.getData();
- data.putString("url", ref);
- msg.setData(data);
- msg.sendToTarget();
- }
-
- private static int pinLoc(int x, int viewMax, int docMax) {
-// Log.d(LOGTAG, "-- pinLoc " + x + " " + viewMax + " " + docMax);
- if (docMax < viewMax) { // the doc has room on the sides for "blank"
- x = -(viewMax - docMax) >> 1;
-// Log.d(LOGTAG, "--- center " + x);
- } else if (x < 0) {
- x = 0;
-// Log.d(LOGTAG, "--- zero");
- } else if (x + viewMax > docMax) {
- x = docMax - viewMax;
-// Log.d(LOGTAG, "--- pin " + x);
- }
- return x;
- }
-
- // Expects x in view coordinates
- private int pinLocX(int x) {
- return pinLoc(x, getViewWidth(), computeHorizontalScrollRange());
- }
-
- // Expects y in view coordinates
- private int pinLocY(int y) {
- return pinLoc(y, getViewHeight(), computeVerticalScrollRange());
- }
-
- /*package*/ int viewToContent(int x) {
- return Math.round(x * mInvActualScale);
- }
-
- private int contentToView(int x) {
- return Math.round(x * mActualScale);
- }
-
- // Called by JNI to invalidate the View, given rectangle coordinates in
- // content space
- private void viewInvalidate(int l, int t, int r, int b) {
- invalidate(contentToView(l), contentToView(t), contentToView(r),
- contentToView(b));
- }
-
- // Called by JNI to invalidate the View after a delay, given rectangle
- // coordinates in content space
- private void viewInvalidateDelayed(long delay, int l, int t, int r, int b) {
- postInvalidateDelayed(delay, contentToView(l), contentToView(t),
- contentToView(r), contentToView(b));
- }
-
- private Rect contentToView(Rect x) {
- return new Rect(contentToView(x.left), contentToView(x.top)
- , contentToView(x.right), contentToView(x.bottom));
- }
-
- /* call from webcoreview.draw(), so we're still executing in the UI thread
- */
- private void recordNewContentSize(int w, int h, boolean updateLayout) {
-
- // premature data from webkit, ignore
- if ((w | h) == 0) {
- return;
- }
-
- // don't abort a scroll animation if we didn't change anything
- if (mContentWidth != w || mContentHeight != h) {
- // record new dimensions
- mContentWidth = w;
- mContentHeight = h;
- // If history Picture is drawn, don't update scroll. They will be
- // updated when we get out of that mode.
- if (!mDrawHistory) {
- // repin our scroll, taking into account the new content size
- int oldX = mScrollX;
- int oldY = mScrollY;
- mScrollX = pinLocX(mScrollX);
- mScrollY = pinLocY(mScrollY);
- // android.util.Log.d("skia", "recordNewContentSize -
- // abortAnimation");
- mScroller.abortAnimation(); // just in case
- if (oldX != mScrollX || oldY != mScrollY) {
- sendOurVisibleRect();
- }
- }
- }
- contentSizeChanged(updateLayout);
- }
-
- private void setNewZoomScale(float scale, boolean force) {
- if (scale < mMinZoomScale) {
- scale = mMinZoomScale;
- } else if (scale > mMaxZoomScale) {
- scale = mMaxZoomScale;
- }
- if (scale != mActualScale || force) {
- if (mDrawHistory) {
- // If history Picture is drawn, don't update scroll. They will
- // be updated when we get out of that mode.
- if (scale != mActualScale && !mPreviewZoomOnly) {
- mCallbackProxy.onScaleChanged(mActualScale, scale);
- }
- mActualScale = scale;
- mInvActualScale = 1 / scale;
- if (!mPreviewZoomOnly) {
- sendViewSizeZoom();
- }
- } else {
- // update our scroll so we don't appear to jump
- // i.e. keep the center of the doc in the center of the view
-
- int oldX = mScrollX;
- int oldY = mScrollY;
- float ratio = scale * mInvActualScale; // old inverse
- float sx = ratio * oldX + (ratio - 1) * mZoomCenterX;
- float sy = ratio * oldY + (ratio - 1) * mZoomCenterY;
-
- // now update our new scale and inverse
- if (scale != mActualScale && !mPreviewZoomOnly) {
- mCallbackProxy.onScaleChanged(mActualScale, scale);
- }
- mActualScale = scale;
- mInvActualScale = 1 / scale;
-
- // as we don't have animation for scaling, don't do animation
- // for scrolling, as it causes weird intermediate state
- // pinScrollTo(Math.round(sx), Math.round(sy));
- mScrollX = pinLocX(Math.round(sx));
- mScrollY = pinLocY(Math.round(sy));
-
- if (!mPreviewZoomOnly) {
- sendViewSizeZoom();
- sendOurVisibleRect();
- }
- }
- }
- }
-
- // Used to avoid sending many visible rect messages.
- private Rect mLastVisibleRectSent;
- private Rect mLastGlobalRect;
-
- private Rect sendOurVisibleRect() {
- Rect rect = new Rect();
- calcOurContentVisibleRect(rect);
- if (mFindIsUp) {
- rect.bottom -= viewToContent(FIND_HEIGHT);
- }
- // Rect.equals() checks for null input.
- if (!rect.equals(mLastVisibleRectSent)) {
- mWebViewCore.sendMessage(EventHub.SET_SCROLL_OFFSET,
- rect.left, rect.top);
- mLastVisibleRectSent = rect;
- }
- Rect globalRect = new Rect();
- if (getGlobalVisibleRect(globalRect)
- && !globalRect.equals(mLastGlobalRect)) {
- // TODO: the global offset is only used by windowRect()
- // in ChromeClientAndroid ; other clients such as touch
- // and mouse events could return view + screen relative points.
- mWebViewCore.sendMessage(EventHub.SET_GLOBAL_BOUNDS, globalRect);
- mLastGlobalRect = globalRect;
- }
- return rect;
- }
-
- // Sets r to be the visible rectangle of our webview in view coordinates
- private void calcOurVisibleRect(Rect r) {
- Point p = new Point();
- getGlobalVisibleRect(r, p);
- r.offset(-p.x, -p.y);
- }
-
- // Sets r to be our visible rectangle in content coordinates
- private void calcOurContentVisibleRect(Rect r) {
- calcOurVisibleRect(r);
- r.left = viewToContent(r.left);
- r.top = viewToContent(r.top);
- r.right = viewToContent(r.right);
- r.bottom = viewToContent(r.bottom);
- }
-
- /**
- * Compute unzoomed width and height, and if they differ from the last
- * values we sent, send them to webkit (to be used has new viewport)
- *
- * @return true if new values were sent
- */
- private boolean sendViewSizeZoom() {
- int viewWidth = getViewWidth();
- int newWidth = Math.round(viewWidth * mInvActualScale);
- int newHeight = Math.round(getViewHeight() * mInvActualScale);
- /*
- * Because the native side may have already done a layout before the
- * View system was able to measure us, we have to send a height of 0 to
- * remove excess whitespace when we grow our width. This will trigger a
- * layout and a change in content size. This content size change will
- * mean that contentSizeChanged will either call this method directly or
- * indirectly from onSizeChanged.
- */
- if (newWidth > mLastWidthSent && mWrapContent) {
- newHeight = 0;
- }
- // Avoid sending another message if the dimensions have not changed.
- if (newWidth != mLastWidthSent || newHeight != mLastHeightSent) {
- mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED,
- newWidth, newHeight, new Integer(viewWidth));
- mLastWidthSent = newWidth;
- mLastHeightSent = newHeight;
- return true;
- }
- return false;
- }
-
- @Override
- protected int computeHorizontalScrollRange() {
- if (mDrawHistory) {
- return mHistoryWidth;
- } else {
- return contentToView(mContentWidth);
- }
- }
-
- // Make sure this stays in sync with the actual height of the FindDialog.
- private static final int FIND_HEIGHT = 79;
-
- @Override
- protected int computeVerticalScrollRange() {
- if (mDrawHistory) {
- return mHistoryHeight;
- } else {
- int height = contentToView(mContentHeight);
- if (mFindIsUp) {
- height += FIND_HEIGHT;
- }
- return height;
- }
- }
-
- /**
- * Get the url for the current page. This is not always the same as the url
- * passed to WebViewClient.onPageStarted because although the load for
- * that url has begun, the current page may not have changed.
- * @return The url for the current page.
- */
- public String getUrl() {
- WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
- return h != null ? h.getUrl() : null;
- }
-
- /**
- * Get the original url for the current page. This is not always the same
- * as the url passed to WebViewClient.onPageStarted because although the
- * load for that url has begun, the current page may not have changed.
- * Also, there may have been redirects resulting in a different url to that
- * originally requested.
- * @return The url that was originally requested for the current page.
- *
- * @hide pending API Council approval
- */
- public String getOriginalUrl() {
- WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
- return h != null ? h.getOriginalUrl() : null;
- }
-
- /**
- * Get the title for the current page. This is the title of the current page
- * until WebViewClient.onReceivedTitle is called.
- * @return The title for the current page.
- */
- public String getTitle() {
- WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
- return h != null ? h.getTitle() : null;
- }
-
- /**
- * Get the favicon for the current page. This is the favicon of the current
- * page until WebViewClient.onReceivedIcon is called.
- * @return The favicon for the current page.
- */
- public Bitmap getFavicon() {
- WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
- return h != null ? h.getFavicon() : null;
- }
-
- /**
- * Get the progress for the current page.
- * @return The progress for the current page between 0 and 100.
- */
- public int getProgress() {
- return mCallbackProxy.getProgress();
- }
-
- /**
- * @return the height of the HTML content.
- */
- public int getContentHeight() {
- return mContentHeight;
- }
-
- /**
- * Pause all layout, parsing, and javascript timers. This can be useful if
- * the WebView is not visible or the application has been paused.
- */
- public void pauseTimers() {
- mWebViewCore.sendMessage(EventHub.PAUSE_TIMERS);
- }
-
- /**
- * Resume all layout, parsing, and javascript timers. This will resume
- * dispatching all timers.
- */
- public void resumeTimers() {
- mWebViewCore.sendMessage(EventHub.RESUME_TIMERS);
- }
-
- /**
- * Clear the resource cache. This will cause resources to be re-downloaded
- * if accessed again.
- * <p>
- * Note: this really needs to be a static method as it clears cache for all
- * WebView. But we need mWebViewCore to send message to WebCore thread, so
- * we can't make this static.
- */
- public void clearCache(boolean includeDiskFiles) {
- mWebViewCore.sendMessage(EventHub.CLEAR_CACHE,
- includeDiskFiles ? 1 : 0, 0);
- }
-
- /**
- * Make sure that clearing the form data removes the adapter from the
- * currently focused textfield if there is one.
- */
- public void clearFormData() {
- if (inEditingMode()) {
- AutoCompleteAdapter adapter = null;
- mTextEntry.setAdapterCustom(adapter);
- }
- }
-
- /**
- * Tell the WebView to clear its internal back/forward list.
- */
- public void clearHistory() {
- mCallbackProxy.getBackForwardList().setClearPending();
- mWebViewCore.sendMessage(EventHub.CLEAR_HISTORY);
- }
-
- /**
- * Clear the SSL preferences table stored in response to proceeding with SSL
- * certificate errors.
- */
- public void clearSslPreferences() {
- mWebViewCore.sendMessage(EventHub.CLEAR_SSL_PREF_TABLE);
- }
-
- /**
- * Return the WebBackForwardList for this WebView. This contains the
- * back/forward list for use in querying each item in the history stack.
- * This is a copy of the private WebBackForwardList so it contains only a
- * snapshot of the current state. Multiple calls to this method may return
- * different objects. The object returned from this method will not be
- * updated to reflect any new state.
- */
- public WebBackForwardList copyBackForwardList() {
- return mCallbackProxy.getBackForwardList().clone();
- }
-
- /*
- * Highlight and scroll to the next occurance of String in findAll.
- * Wraps the page infinitely, and scrolls. Must be called after
- * calling findAll.
- *
- * @param forward Direction to search.
- */
- public void findNext(boolean forward) {
- nativeFindNext(forward);
- }
-
- /*
- * Find all instances of find on the page and highlight them.
- * @param find String to find.
- * @return int The number of occurances of the String "find"
- * that were found.
- */
- public int findAll(String find) {
- mFindIsUp = true;
- int result = nativeFindAll(find.toLowerCase(), find.toUpperCase());
- invalidate();
- return result;
- }
-
- // Used to know whether the find dialog is open. Affects whether
- // or not we draw the highlights for matches.
- private boolean mFindIsUp;
-
- private native int nativeFindAll(String findLower, String findUpper);
- private native void nativeFindNext(boolean forward);
-
- /**
- * Return the first substring consisting of the address of a physical
- * location. Currently, only addresses in the United States are detected,
- * and consist of:
- * - a house number
- * - a street name
- * - a street type (Road, Circle, etc), either spelled out or abbreviated
- * - a city name
- * - a state or territory, either spelled out or two-letter abbr.
- * - an optional 5 digit or 9 digit zip code.
- *
- * All names must be correctly capitalized, and the zip code, if present,
- * must be valid for the state. The street type must be a standard USPS
- * spelling or abbreviation. The state or territory must also be spelled
- * or abbreviated using USPS standards. The house number may not exceed
- * five digits.
- * @param addr The string to search for addresses.
- *
- * @return the address, or if no address is found, return null.
- */
- public static String findAddress(String addr) {
- return WebViewCore.nativeFindAddress(addr);
- }
-
- /*
- * Clear the highlighting surrounding text matches created by findAll.
- */
- public void clearMatches() {
- mFindIsUp = false;
- nativeSetFindIsDown();
- // Now that the dialog has been removed, ensure that we scroll to a
- // location that is not beyond the end of the page.
- pinScrollTo(mScrollX, mScrollY, false, 0);
- invalidate();
- }
-
- /**
- * Query the document to see if it contains any image references. The
- * message object will be dispatched with arg1 being set to 1 if images
- * were found and 0 if the document does not reference any images.
- * @param response The message that will be dispatched with the result.
- */
- public void documentHasImages(Message response) {
- if (response == null) {
- return;
- }
- mWebViewCore.sendMessage(EventHub.DOC_HAS_IMAGES, response);
- }
-
- @Override
- public void computeScroll() {
- if (mScroller.computeScrollOffset()) {
- int oldX = mScrollX;
- int oldY = mScrollY;
- mScrollX = mScroller.getCurrX();
- mScrollY = mScroller.getCurrY();
- postInvalidate(); // So we draw again
- if (oldX != mScrollX || oldY != mScrollY) {
- // as onScrollChanged() is not called, sendOurVisibleRect()
- // needs to be call explicitly
- sendOurVisibleRect();
- }
- } else {
- super.computeScroll();
- }
- }
-
- private static int computeDuration(int dx, int dy) {
- int distance = Math.max(Math.abs(dx), Math.abs(dy));
- int duration = distance * 1000 / STD_SPEED;
- return Math.min(duration, MAX_DURATION);
- }
-
- // helper to pin the scrollBy parameters (already in view coordinates)
- // returns true if the scroll was changed
- private boolean pinScrollBy(int dx, int dy, boolean animate, int animationDuration) {
- return pinScrollTo(mScrollX + dx, mScrollY + dy, animate, animationDuration);
- }
-
- // helper to pin the scrollTo parameters (already in view coordinates)
- // returns true if the scroll was changed
- private boolean pinScrollTo(int x, int y, boolean animate, int animationDuration) {
- x = pinLocX(x);
- y = pinLocY(y);
- int dx = x - mScrollX;
- int dy = y - mScrollY;
-
- if ((dx | dy) == 0) {
- return false;
- }
-
- if (true && animate) {
- // Log.d(LOGTAG, "startScroll: " + dx + " " + dy);
-
- mScroller.startScroll(mScrollX, mScrollY, dx, dy,
- animationDuration > 0 ? animationDuration : computeDuration(dx, dy));
- invalidate();
- } else {
- mScroller.abortAnimation(); // just in case
- scrollTo(x, y);
- }
- return true;
- }
-
- // Scale from content to view coordinates, and pin.
- // Also called by jni webview.cpp
- private void setContentScrollBy(int cx, int cy, boolean animate) {
- if (mDrawHistory) {
- // disallow WebView to change the scroll position as History Picture
- // is used in the view system.
- // TODO: as we switchOutDrawHistory when trackball or navigation
- // keys are hit, this should be safe. Right?
- return;
- }
- cx = contentToView(cx);
- cy = contentToView(cy);
- if (mHeightCanMeasure) {
- // move our visible rect according to scroll request
- if (cy != 0) {
- Rect tempRect = new Rect();
- calcOurVisibleRect(tempRect);
- tempRect.offset(cx, cy);
- requestRectangleOnScreen(tempRect);
- }
- // FIXME: We scroll horizontally no matter what because currently
- // ScrollView and ListView will not scroll horizontally.
- // FIXME: Why do we only scroll horizontally if there is no
- // vertical scroll?
-// Log.d(LOGTAG, "setContentScrollBy cy=" + cy);
- if (cy == 0 && cx != 0) {
- pinScrollBy(cx, 0, animate, 0);
- }
- } else {
- pinScrollBy(cx, cy, animate, 0);
- }
- }
-
- // scale from content to view coordinates, and pin
- // return true if pin caused the final x/y different than the request cx/cy;
- // return false if the view scroll to the exact position as it is requested.
- private boolean setContentScrollTo(int cx, int cy) {
- if (mDrawHistory) {
- // disallow WebView to change the scroll position as History Picture
- // is used in the view system.
- // One known case where this is called is that WebCore tries to
- // restore the scroll position. As history Picture already uses the
- // saved scroll position, it is ok to skip this.
- return false;
- }
- int vx = contentToView(cx);
- int vy = contentToView(cy);
-// Log.d(LOGTAG, "content scrollTo [" + cx + " " + cy + "] view=[" +
-// vx + " " + vy + "]");
- pinScrollTo(vx, vy, false, 0);
- if (mScrollX != vx || mScrollY != vy) {
- return true;
- } else {
- return false;
- }
- }
-
- // scale from content to view coordinates, and pin
- private void spawnContentScrollTo(int cx, int cy) {
- if (mDrawHistory) {
- // disallow WebView to change the scroll position as History Picture
- // is used in the view system.
- return;
- }
- int vx = contentToView(cx);
- int vy = contentToView(cy);
- pinScrollTo(vx, vy, true, 0);
- }
-
- /**
- * These are from webkit, and are in content coordinate system (unzoomed)
- */
- private void contentSizeChanged(boolean updateLayout) {
- // suppress 0,0 since we usually see real dimensions soon after
- // this avoids drawing the prev content in a funny place. If we find a
- // way to consolidate these notifications, this check may become
- // obsolete
- if ((mContentWidth | mContentHeight) == 0) {
- return;
- }
-
- if (mHeightCanMeasure) {
- if (getMeasuredHeight() != contentToView(mContentHeight)
- && updateLayout) {
- requestLayout();
- }
- } else if (mWidthCanMeasure) {
- if (getMeasuredWidth() != contentToView(mContentWidth)
- && updateLayout) {
- requestLayout();
- }
- } else {
- // If we don't request a layout, try to send our view size to the
- // native side to ensure that WebCore has the correct dimensions.
- sendViewSizeZoom();
- }
- }
-
- /**
- * Set the WebViewClient that will receive various notifications and
- * requests. This will replace the current handler.
- * @param client An implementation of WebViewClient.
- */
- public void setWebViewClient(WebViewClient client) {
- mCallbackProxy.setWebViewClient(client);
- }
-
- /**
- * Register the interface to be used when content can not be handled by
- * the rendering engine, and should be downloaded instead. This will replace
- * the current handler.
- * @param listener An implementation of DownloadListener.
- */
- public void setDownloadListener(DownloadListener listener) {
- mCallbackProxy.setDownloadListener(listener);
- }
-
- /**
- * Set the chrome handler. This is an implementation of WebChromeClient for
- * use in handling Javascript dialogs, favicons, titles, and the progress.
- * This will replace the current handler.
- * @param client An implementation of WebChromeClient.
- */
- public void setWebChromeClient(WebChromeClient client) {
- mCallbackProxy.setWebChromeClient(client);
- }
-
- /**
- * Set the Picture listener. This is an interface used to receive
- * notifications of a new Picture.
- * @param listener An implementation of WebView.PictureListener.
- */
- public void setPictureListener(PictureListener listener) {
- mPictureListener = listener;
- }
-
- /**
- * {@hide}
- */
- /* FIXME: Debug only! Remove for SDK! */
- public void externalRepresentation(Message callback) {
- mWebViewCore.sendMessage(EventHub.REQUEST_EXT_REPRESENTATION, callback);
- }
-
- /**
- * {@hide}
- */
- /* FIXME: Debug only! Remove for SDK! */
- public void documentAsText(Message callback) {
- mWebViewCore.sendMessage(EventHub.REQUEST_DOC_AS_TEXT, callback);
- }
-
- /**
- * Use this function to bind an object to Javascript so that the
- * methods can be accessed from Javascript.
- * IMPORTANT, the object that is bound runs in another thread and
- * not in the thread that it was constructed in.
- * @param obj The class instance to bind to Javascript
- * @param interfaceName The name to used to expose the class in Javascript
- */
- public void addJavascriptInterface(Object obj, String interfaceName) {
- // Use Hashmap rather than Bundle as Bundles can't cope with Objects
- HashMap arg = new HashMap();
- arg.put("object", obj);
- arg.put("interfaceName", interfaceName);
- mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg);
- }
-
- /**
- * Return the WebSettings object used to control the settings for this
- * WebView.
- * @return A WebSettings object that can be used to control this WebView's
- * settings.
- */
- public WebSettings getSettings() {
- return mWebViewCore.getSettings();
- }
-
- /**
- * Return the list of currently loaded plugins.
- * @return The list of currently loaded plugins.
- */
- public static synchronized PluginList getPluginList() {
- if (sPluginList == null) {
- sPluginList = new PluginList();
- }
- return sPluginList;
- }
-
- /**
- * Signal the WebCore thread to refresh its list of plugins. Use
- * this if the directory contents of one of the plugin directories
- * has been modified and needs its changes reflecting. May cause
- * plugin load and/or unload.
- * @param reloadOpenPages Set to true to reload all open pages.
- */
- public void refreshPlugins(boolean reloadOpenPages) {
- if (mWebViewCore != null) {
- mWebViewCore.sendMessage(EventHub.REFRESH_PLUGINS, reloadOpenPages);
- }
- }
-
- //-------------------------------------------------------------------------
- // Override View methods
- //-------------------------------------------------------------------------
-
- @Override
- protected void finalize() throws Throwable {
- destroy();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- // if mNativeClass is 0, the WebView has been destroyed. Do nothing.
- if (mNativeClass == 0) {
- return;
- }
- if (mWebViewCore.mEndScaleZoom) {
- mWebViewCore.mEndScaleZoom = false;
- if (mTouchMode >= FIRST_SCROLL_ZOOM
- && mTouchMode <= LAST_SCROLL_ZOOM) {
- setHorizontalScrollBarEnabled(true);
- setVerticalScrollBarEnabled(true);
- mTouchMode = TOUCH_DONE_MODE;
- }
- }
- int sc = canvas.save();
- if (mTouchMode >= FIRST_SCROLL_ZOOM && mTouchMode <= LAST_SCROLL_ZOOM) {
- scrollZoomDraw(canvas);
- } else {
- nativeRecomputeFocus();
- // Update the buttons in the picture, so when we draw the picture
- // to the screen, they are in the correct state.
- // Tell the native side if user is a) touching the screen,
- // b) pressing the trackball down, or c) pressing the enter key
- // If the focus is a button, we need to draw it in the pressed
- // state.
- // If mNativeClass is 0, we should not reach here, so we do not
- // need to check it again.
- nativeRecordButtons(hasFocus() && hasWindowFocus(),
- mTouchMode == TOUCH_SHORTPRESS_START_MODE
- || mTrackballDown || mGotEnterDown, false);
- drawCoreAndFocusRing(canvas, mBackgroundColor, mDrawFocusRing);
- }
- canvas.restoreToCount(sc);
-
- if (AUTO_REDRAW_HACK && mAutoRedraw) {
- invalidate();
- }
- }
-
- @Override
- public void setLayoutParams(ViewGroup.LayoutParams params) {
- if (params.height == LayoutParams.WRAP_CONTENT) {
- mWrapContent = true;
- }
- super.setLayoutParams(params);
- }
-
- @Override
- public boolean performLongClick() {
- if (inEditingMode()) {
- return mTextEntry.performLongClick();
- } else {
- return super.performLongClick();
- }
- }
-
- private void drawCoreAndFocusRing(Canvas canvas, int color,
- boolean drawFocus) {
- if (mDrawHistory) {
- canvas.scale(mActualScale, mActualScale);
- canvas.drawPicture(mHistoryPicture);
- return;
- }
-
- boolean animateZoom = mZoomScale != 0;
- boolean animateScroll = !mScroller.isFinished()
- || mVelocityTracker != null;
- if (animateZoom) {
- float zoomScale;
- int interval = (int) (SystemClock.uptimeMillis() - mZoomStart);
- if (interval < ZOOM_ANIMATION_LENGTH) {
- float ratio = (float) interval / ZOOM_ANIMATION_LENGTH;
- zoomScale = 1.0f / (mInvInitialZoomScale
- + (mInvFinalZoomScale - mInvInitialZoomScale) * ratio);
- invalidate();
- } else {
- zoomScale = mZoomScale;
- // set mZoomScale to be 0 as we have done animation
- mZoomScale = 0;
- }
- float scale = (mActualScale - zoomScale) * mInvActualScale;
- float tx = scale * (mZoomCenterX + mScrollX);
- float ty = scale * (mZoomCenterY + mScrollY);
-
- // this block pins the translate to "legal" bounds. This makes the
- // animation a bit non-obvious, but it means we won't pop when the
- // "real" zoom takes effect
- if (true) {
- // canvas.translate(mScrollX, mScrollY);
- tx -= mScrollX;
- ty -= mScrollY;
- tx = -pinLoc(-Math.round(tx), getViewWidth(), Math
- .round(mContentWidth * zoomScale));
- ty = -pinLoc(-Math.round(ty), getViewHeight(), Math
- .round(mContentHeight * zoomScale));
- tx += mScrollX;
- ty += mScrollY;
- }
- canvas.translate(tx, ty);
- canvas.scale(zoomScale, zoomScale);
- } else {
- canvas.scale(mActualScale, mActualScale);
- }
-
- mWebViewCore.drawContentPicture(canvas, color, animateZoom,
- animateScroll);
-
- if (mNativeClass == 0) return;
- if (mShiftIsPressed) {
- if (mTouchSelection) {
- nativeDrawSelectionRegion(canvas);
- } else {
- nativeDrawSelection(canvas, mSelectX, mSelectY,
- mExtendSelection);
- }
- } else if (drawFocus) {
- if (mTouchMode == TOUCH_SHORTPRESS_START_MODE) {
- mTouchMode = TOUCH_SHORTPRESS_MODE;
- HitTestResult hitTest = getHitTestResult();
- if (hitTest != null &&
- hitTest.mType != HitTestResult.UNKNOWN_TYPE) {
- mPrivateHandler.sendMessageDelayed(mPrivateHandler
- .obtainMessage(SWITCH_TO_LONGPRESS),
- LONG_PRESS_TIMEOUT);
- }
- }
- nativeDrawFocusRing(canvas);
- }
- // When the FindDialog is up, only draw the matches if we are not in
- // the process of scrolling them into view.
- if (mFindIsUp && !animateScroll) {
- nativeDrawMatches(canvas);
- }
- }
-
- private native void nativeDrawMatches(Canvas canvas);
-
- private float scrollZoomGridScale(float invScale) {
- float griddedInvScale = (int) (invScale * SCROLL_ZOOM_GRID)
- / (float) SCROLL_ZOOM_GRID;
- return 1.0f / griddedInvScale;
- }
-
- private float scrollZoomX(float scale) {
- int width = getViewWidth();
- float maxScrollZoomX = mContentWidth * scale - width;
- int maxX = mContentWidth - width;
- return -(maxScrollZoomX > 0 ? mZoomScrollX * maxScrollZoomX / maxX
- : maxScrollZoomX / 2);
- }
-
- private float scrollZoomY(float scale) {
- int height = getViewHeight();
- float maxScrollZoomY = mContentHeight * scale - height;
- int maxY = mContentHeight - height;
- return -(maxScrollZoomY > 0 ? mZoomScrollY * maxScrollZoomY / maxY
- : maxScrollZoomY / 2);
- }
-
- private void drawMagnifyFrame(Canvas canvas, Rect frame, Paint paint) {
- final float ADORNMENT_LEN = 16.0f;
- float width = frame.width();
- float height = frame.height();
- Path path = new Path();
- path.moveTo(-ADORNMENT_LEN, -ADORNMENT_LEN);
- path.lineTo(0, 0);
- path.lineTo(width, 0);
- path.lineTo(width + ADORNMENT_LEN, -ADORNMENT_LEN);
- path.moveTo(-ADORNMENT_LEN, height + ADORNMENT_LEN);
- path.lineTo(0, height);
- path.lineTo(width, height);
- path.lineTo(width + ADORNMENT_LEN, height + ADORNMENT_LEN);
- path.moveTo(0, 0);
- path.lineTo(0, height);
- path.moveTo(width, 0);
- path.lineTo(width, height);
- path.offset(frame.left, frame.top);
- canvas.drawPath(path, paint);
- }
-
- // Returns frame surrounding magified portion of screen while
- // scroll-zoom is enabled. The frame is also used to center the
- // zoom-in zoom-out points at the start and end of the animation.
- private Rect scrollZoomFrame(int width, int height, float halfScale) {
- Rect scrollFrame = new Rect();
- scrollFrame.set(mZoomScrollX, mZoomScrollY,
- mZoomScrollX + width, mZoomScrollY + height);
- if (mContentWidth * mZoomScrollLimit < width) {
- float scale = zoomFrameScaleX(width, halfScale, 1.0f);
- float offsetX = (width * scale - width) * 0.5f;
- scrollFrame.left -= offsetX;
- scrollFrame.right += offsetX;
- }
- if (mContentHeight * mZoomScrollLimit < height) {
- float scale = zoomFrameScaleY(height, halfScale, 1.0f);
- float offsetY = (height * scale - height) * 0.5f;
- scrollFrame.top -= offsetY;
- scrollFrame.bottom += offsetY;
- }
- return scrollFrame;
- }
-
- private float zoomFrameScaleX(int width, float halfScale, float noScale) {
- // mContentWidth > width > mContentWidth * mZoomScrollLimit
- if (mContentWidth <= width) {
- return halfScale;
- }
- float part = (width - mContentWidth * mZoomScrollLimit)
- / (width * (1 - mZoomScrollLimit));
- return halfScale * part + noScale * (1.0f - part);
- }
-
- private float zoomFrameScaleY(int height, float halfScale, float noScale) {
- if (mContentHeight <= height) {
- return halfScale;
- }
- float part = (height - mContentHeight * mZoomScrollLimit)
- / (height * (1 - mZoomScrollLimit));
- return halfScale * part + noScale * (1.0f - part);
- }
-
- private float scrollZoomMagScale(float invScale) {
- return (invScale * 2 + mInvActualScale) / 3;
- }
-
- private void scrollZoomDraw(Canvas canvas) {
- float invScale = mZoomScrollInvLimit;
- int elapsed = 0;
- if (mTouchMode != SCROLL_ZOOM_OUT) {
- elapsed = (int) Math.min(System.currentTimeMillis()
- - mZoomScrollStart, SCROLL_ZOOM_DURATION);
- float transitionScale = (mZoomScrollInvLimit - mInvActualScale)
- * elapsed / SCROLL_ZOOM_DURATION;
- if (mTouchMode == SCROLL_ZOOM_ANIMATION_OUT) {
- invScale = mInvActualScale + transitionScale;
- } else { /* if (mTouchMode == SCROLL_ZOOM_ANIMATION_IN) */
- invScale = mZoomScrollInvLimit - transitionScale;
- }
- }
- float scale = scrollZoomGridScale(invScale);
- invScale = 1.0f / scale;
- int width = getViewWidth();
- int height = getViewHeight();
- float halfScale = scrollZoomMagScale(invScale);
- Rect scrollFrame = scrollZoomFrame(width, height, halfScale);
- if (elapsed == SCROLL_ZOOM_DURATION) {
- if (mTouchMode == SCROLL_ZOOM_ANIMATION_IN) {
- setHorizontalScrollBarEnabled(true);
- setVerticalScrollBarEnabled(true);
- updateTextEntry();
- scrollTo((int) (scrollFrame.centerX() * mActualScale)
- - (width >> 1), (int) (scrollFrame.centerY()
- * mActualScale) - (height >> 1));
- mTouchMode = TOUCH_DONE_MODE;
- } else {
- mTouchMode = SCROLL_ZOOM_OUT;
- }
- }
- float newX = scrollZoomX(scale);
- float newY = scrollZoomY(scale);
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "scrollZoomDraw scale=" + scale + " + (" + newX
- + ", " + newY + ") mZoomScroll=(" + mZoomScrollX + ", "
- + mZoomScrollY + ")" + " invScale=" + invScale + " scale="
- + scale);
- }
- canvas.translate(newX, newY);
- canvas.scale(scale, scale);
- boolean animating = mTouchMode != SCROLL_ZOOM_OUT;
- if (mDrawHistory) {
- int sc = canvas.save(Canvas.CLIP_SAVE_FLAG);
- Rect clip = new Rect(0, 0, mHistoryPicture.getWidth(),
- mHistoryPicture.getHeight());
- canvas.clipRect(clip, Region.Op.DIFFERENCE);
- canvas.drawColor(mBackgroundColor);
- canvas.restoreToCount(sc);
- canvas.drawPicture(mHistoryPicture);
- } else {
- mWebViewCore.drawContentPicture(canvas, mBackgroundColor,
- animating, true);
- }
- if (mTouchMode == TOUCH_DONE_MODE) {
- return;
- }
- Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeWidth(30.0f);
- paint.setARGB(0x50, 0, 0, 0);
- int maxX = mContentWidth - width;
- int maxY = mContentHeight - height;
- if (true) { // experiment: draw hint to place finger off magnify area
- drawMagnifyFrame(canvas, scrollFrame, paint);
- } else {
- canvas.drawRect(scrollFrame, paint);
- }
- int sc = canvas.save();
- canvas.clipRect(scrollFrame);
- float halfX = (float) mZoomScrollX / maxX;
- if (mContentWidth * mZoomScrollLimit < width) {
- halfX = zoomFrameScaleX(width, 0.5f, halfX);
- }
- float halfY = (float) mZoomScrollY / maxY;
- if (mContentHeight * mZoomScrollLimit < height) {
- halfY = zoomFrameScaleY(height, 0.5f, halfY);
- }
- canvas.scale(halfScale, halfScale, mZoomScrollX + width * halfX
- , mZoomScrollY + height * halfY);
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "scrollZoomDraw halfScale=" + halfScale + " w/h=("
- + width + ", " + height + ") half=(" + halfX + ", "
- + halfY + ")");
- }
- if (mDrawHistory) {
- canvas.drawPicture(mHistoryPicture);
- } else {
- mWebViewCore.drawContentPicture(canvas, mBackgroundColor,
- animating, false);
- }
- canvas.restoreToCount(sc);
- if (mTouchMode != SCROLL_ZOOM_OUT) {
- invalidate();
- }
- }
-
- private void zoomScrollTap(float x, float y) {
- float scale = scrollZoomGridScale(mZoomScrollInvLimit);
- float left = scrollZoomX(scale);
- float top = scrollZoomY(scale);
- int width = getViewWidth();
- int height = getViewHeight();
- x -= width * scale / 2;
- y -= height * scale / 2;
- mZoomScrollX = Math.min(mContentWidth - width
- , Math.max(0, (int) ((x - left) / scale)));
- mZoomScrollY = Math.min(mContentHeight - height
- , Math.max(0, (int) ((y - top) / scale)));
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "zoomScrollTap scale=" + scale + " + (" + left
- + ", " + top + ") mZoomScroll=(" + mZoomScrollX + ", "
- + mZoomScrollY + ")" + " x=" + x + " y=" + y);
- }
- }
-
- private boolean canZoomScrollOut() {
- if (mContentWidth == 0 || mContentHeight == 0) {
- return false;
- }
- int width = getViewWidth();
- int height = getViewHeight();
- float x = (float) width / (float) mContentWidth;
- float y = (float) height / (float) mContentHeight;
- mZoomScrollLimit = Math.max(DEFAULT_MIN_ZOOM_SCALE, Math.min(x, y));
- mZoomScrollInvLimit = 1.0f / mZoomScrollLimit;
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "canZoomScrollOut"
- + " mInvActualScale=" + mInvActualScale
- + " mZoomScrollLimit=" + mZoomScrollLimit
- + " mZoomScrollInvLimit=" + mZoomScrollInvLimit
- + " mContentWidth=" + mContentWidth
- + " mContentHeight=" + mContentHeight
- );
- }
- // don't zoom out unless magnify area is at least half as wide
- // or tall as content
- float limit = mZoomScrollLimit * 2;
- return mContentWidth >= width * limit
- || mContentHeight >= height * limit;
- }
-
- private void startZoomScrollOut() {
- setHorizontalScrollBarEnabled(false);
- setVerticalScrollBarEnabled(false);
- if (mZoomControlRunnable != null) {
- mPrivateHandler.removeCallbacks(mZoomControlRunnable);
- }
- if (mZoomControls != null) {
- mZoomControls.hide();
- }
- int width = getViewWidth();
- int height = getViewHeight();
- int halfW = width >> 1;
- mLastTouchX = halfW;
- int halfH = height >> 1;
- mLastTouchY = halfH;
- mScroller.abortAnimation();
- mZoomScrollStart = System.currentTimeMillis();
- Rect zoomFrame = scrollZoomFrame(width, height
- , scrollZoomMagScale(mZoomScrollInvLimit));
- mZoomScrollX = Math.max(0, (int) ((mScrollX + halfW) * mInvActualScale)
- - (zoomFrame.width() >> 1));
- mZoomScrollY = Math.max(0, (int) ((mScrollY + halfH) * mInvActualScale)
- - (zoomFrame.height() >> 1));
- scrollTo(0, 0); // triggers inval, starts animation
- clearTextEntry();
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "startZoomScrollOut mZoomScroll=("
- + mZoomScrollX + ", " + mZoomScrollY +")");
- }
- }
-
- private void zoomScrollOut() {
- if (canZoomScrollOut() == false) {
- mTouchMode = TOUCH_DONE_MODE;
- return;
- }
- startZoomScrollOut();
- mTouchMode = SCROLL_ZOOM_ANIMATION_OUT;
- invalidate();
- }
-
- private void moveZoomScrollWindow(float x, float y) {
- if (Math.abs(x - mLastZoomScrollRawX) < 1.5f
- && Math.abs(y - mLastZoomScrollRawY) < 1.5f) {
- return;
- }
- mLastZoomScrollRawX = x;
- mLastZoomScrollRawY = y;
- int oldX = mZoomScrollX;
- int oldY = mZoomScrollY;
- int width = getViewWidth();
- int height = getViewHeight();
- int maxZoomX = mContentWidth - width;
- if (maxZoomX > 0) {
- int maxScreenX = width - (int) Math.ceil(width
- * mZoomScrollLimit) - SCROLL_ZOOM_FINGER_BUFFER;
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "moveZoomScrollWindow-X"
- + " maxScreenX=" + maxScreenX + " width=" + width
- + " mZoomScrollLimit=" + mZoomScrollLimit + " x=" + x);
- }
- x += maxScreenX * mLastScrollX / maxZoomX - mLastTouchX;
- x *= Math.max(maxZoomX / maxScreenX, mZoomScrollInvLimit);
- mZoomScrollX = Math.max(0, Math.min(maxZoomX, (int) x));
- }
- int maxZoomY = mContentHeight - height;
- if (maxZoomY > 0) {
- int maxScreenY = height - (int) Math.ceil(height
- * mZoomScrollLimit) - SCROLL_ZOOM_FINGER_BUFFER;
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "moveZoomScrollWindow-Y"
- + " maxScreenY=" + maxScreenY + " height=" + height
- + " mZoomScrollLimit=" + mZoomScrollLimit + " y=" + y);
- }
- y += maxScreenY * mLastScrollY / maxZoomY - mLastTouchY;
- y *= Math.max(maxZoomY / maxScreenY, mZoomScrollInvLimit);
- mZoomScrollY = Math.max(0, Math.min(maxZoomY, (int) y));
- }
- if (oldX != mZoomScrollX || oldY != mZoomScrollY) {
- invalidate();
- }
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "moveZoomScrollWindow"
- + " scrollTo=(" + mZoomScrollX + ", " + mZoomScrollY + ")"
- + " mLastTouch=(" + mLastTouchX + ", " + mLastTouchY + ")"
- + " maxZoom=(" + maxZoomX + ", " + maxZoomY + ")"
- + " last=("+mLastScrollX+", "+mLastScrollY+")"
- + " x=" + x + " y=" + y);
- }
- }
-
- private void setZoomScrollIn() {
- mZoomScrollStart = System.currentTimeMillis();
- }
-
- private float mZoomScrollLimit;
- private float mZoomScrollInvLimit;
- private int mLastScrollX;
- private int mLastScrollY;
- private long mZoomScrollStart;
- private int mZoomScrollX;
- private int mZoomScrollY;
- private float mLastZoomScrollRawX = -1000.0f;
- private float mLastZoomScrollRawY = -1000.0f;
- // The zoomed scale varies from 1.0 to DEFAULT_MIN_ZOOM_SCALE == 0.25.
- // The zoom animation duration SCROLL_ZOOM_DURATION == 0.5.
- // Two pressures compete for gridding; a high frame rate (e.g. 20 fps)
- // and minimizing font cache allocations (fewer frames is better).
- // A SCROLL_ZOOM_GRID of 6 permits about 20 zoom levels over 0.5 seconds:
- // the inverse of: 1.0, 1.16, 1.33, 1.5, 1.67, 1.84, 2.0, etc. to 4.0
- private static final int SCROLL_ZOOM_GRID = 6;
- private static final int SCROLL_ZOOM_DURATION = 500;
- // Make it easier to get to the bottom of a document by reserving a 32
- // pixel buffer, for when the starting drag is a bit below the bottom of
- // the magnify frame.
- private static final int SCROLL_ZOOM_FINGER_BUFFER = 32;
-
- // draw history
- private boolean mDrawHistory = false;
- private Picture mHistoryPicture = null;
- private int mHistoryWidth = 0;
- private int mHistoryHeight = 0;
-
- // Only check the flag, can be called from WebCore thread
- boolean drawHistory() {
- return mDrawHistory;
- }
-
- // Should only be called in UI thread
- void switchOutDrawHistory() {
- if (null == mWebViewCore) return; // CallbackProxy may trigger this
- if (mDrawHistory) {
- mDrawHistory = false;
- invalidate();
- int oldScrollX = mScrollX;
- int oldScrollY = mScrollY;
- mScrollX = pinLocX(mScrollX);
- mScrollY = pinLocY(mScrollY);
- if (oldScrollX != mScrollX || oldScrollY != mScrollY) {
- mUserScroll = false;
- mWebViewCore.sendMessage(EventHub.SYNC_SCROLL, oldScrollX,
- oldScrollY);
- }
- sendOurVisibleRect();
- }
- }
-
- /**
- * Class representing the node which is focused.
- */
- private class FocusNode {
- public FocusNode() {
- mBounds = new Rect();
- }
- // Only to be called by JNI
- private void setAll(boolean isTextField, boolean isTextArea, boolean
- isPassword, boolean isAnchor, boolean isRtlText, int maxLength,
- int textSize, int boundsX, int boundsY, int boundsRight, int
- boundsBottom, int nodePointer, int framePointer, String text,
- String name, int rootTextGeneration) {
- mIsTextField = isTextField;
- mIsTextArea = isTextArea;
- mIsPassword = isPassword;
- mIsAnchor = isAnchor;
- mIsRtlText = isRtlText;
-
- mMaxLength = maxLength;
- mTextSize = textSize;
-
- mBounds.set(boundsX, boundsY, boundsRight, boundsBottom);
-
-
- mNodePointer = nodePointer;
- mFramePointer = framePointer;
- mText = text;
- mName = name;
- mRootTextGeneration = rootTextGeneration;
- }
- public boolean mIsTextField;
- public boolean mIsTextArea;
- public boolean mIsPassword;
- public boolean mIsAnchor;
- public boolean mIsRtlText;
-
- public int mSelectionStart;
- public int mSelectionEnd;
- public int mMaxLength;
- public int mTextSize;
-
- public Rect mBounds;
-
- public int mNodePointer;
- public int mFramePointer;
- public String mText;
- public String mName;
- public int mRootTextGeneration;
- }
-
- // Warning: ONLY use mFocusNode AFTER calling nativeUpdateFocusNode(),
- // and ONLY if it returns true;
- private FocusNode mFocusNode = new FocusNode();
-
- /**
- * Delete text from start to end in the focused textfield. If there is no
- * focus, or if start == end, silently fail. If start and end are out of
- * order, swap them.
- * @param start Beginning of selection to delete.
- * @param end End of selection to delete.
- */
- /* package */ void deleteSelection(int start, int end) {
- mWebViewCore.sendMessage(EventHub.DELETE_SELECTION, start, end,
- new WebViewCore.FocusData(mFocusData));
- }
-
- /**
- * Set the selection to (start, end) in the focused textfield. If start and
- * end are out of order, swap them.
- * @param start Beginning of selection.
- * @param end End of selection.
- */
- /* package */ void setSelection(int start, int end) {
- mWebViewCore.sendMessage(EventHub.SET_SELECTION, start, end,
- new WebViewCore.FocusData(mFocusData));
- }
-
- // Called by JNI when a touch event puts a textfield into focus.
- private void displaySoftKeyboard() {
- InputMethodManager imm = (InputMethodManager)
- getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(mTextEntry, 0);
- mTextEntry.enableScrollOnScreen(true);
- // Now we need to fake a touch event to place the cursor where the
- // user touched.
- AbsoluteLayout.LayoutParams lp = (AbsoluteLayout.LayoutParams)
- mTextEntry.getLayoutParams();
- if (lp != null) {
- // Take the last touch and adjust for the location of the
- // TextDialog.
- float x = mLastTouchX - lp.x;
- float y = mLastTouchY - lp.y;
- mTextEntry.fakeTouchEvent(x, y);
- }
- }
-
- private void updateTextEntry() {
- if (mTextEntry == null) {
- mTextEntry = new TextDialog(mContext, WebView.this);
- // Initialize our generation number.
- mTextGeneration = 0;
- }
- // If we do not have focus, do nothing until we gain focus.
- if (!hasFocus() && !mTextEntry.hasFocus()
- || (mTouchMode >= FIRST_SCROLL_ZOOM
- && mTouchMode <= LAST_SCROLL_ZOOM)) {
- mNeedsUpdateTextEntry = true;
- return;
- }
- boolean alreadyThere = inEditingMode();
- if (0 == mNativeClass || !nativeUpdateFocusNode()) {
- if (alreadyThere) {
- mTextEntry.remove();
- }
- return;
- }
- FocusNode node = mFocusNode;
- if (!node.mIsTextField && !node.mIsTextArea) {
- if (alreadyThere) {
- mTextEntry.remove();
- }
- return;
- }
- mTextEntry.setTextSize(contentToView(node.mTextSize));
- Rect visibleRect = sendOurVisibleRect();
- // Note that sendOurVisibleRect calls viewToContent, so the coordinates
- // should be in content coordinates.
- if (!Rect.intersects(node.mBounds, visibleRect)) {
- // Node is not on screen, so do not bother.
- return;
- }
- int x = node.mBounds.left;
- int y = node.mBounds.top;
- int width = node.mBounds.width();
- int height = node.mBounds.height();
- if (alreadyThere && mTextEntry.isSameTextField(node.mNodePointer)) {
- // It is possible that we have the same textfield, but it has moved,
- // i.e. In the case of opening/closing the screen.
- // In that case, we need to set the dimensions, but not the other
- // aspects.
- // We also need to restore the selection, which gets wrecked by
- // calling setTextEntryRect.
- Spannable spannable = (Spannable) mTextEntry.getText();
- int start = Selection.getSelectionStart(spannable);
- int end = Selection.getSelectionEnd(spannable);
- setTextEntryRect(x, y, width, height);
- // If the text has been changed by webkit, update it. However, if
- // there has been more UI text input, ignore it. We will receive
- // another update when that text is recognized.
- if (node.mText != null && !node.mText.equals(spannable.toString())
- && node.mRootTextGeneration == mTextGeneration) {
- mTextEntry.setTextAndKeepSelection(node.mText);
- } else {
- Selection.setSelection(spannable, start, end);
- }
- } else {
- String text = node.mText;
- setTextEntryRect(x, y, width, height);
- mTextEntry.setGravity(node.mIsRtlText ? Gravity.RIGHT :
- Gravity.NO_GRAVITY);
- // this needs to be called before update adapter thread starts to
- // ensure the mTextEntry has the same node pointer
- mTextEntry.setNodePointer(node.mNodePointer);
- int maxLength = -1;
- if (node.mIsTextField) {
- maxLength = node.mMaxLength;
- if (mWebViewCore.getSettings().getSaveFormData()
- && node.mName != null) {
- HashMap data = new HashMap();
- data.put("text", node.mText);
- Message update = mPrivateHandler.obtainMessage(
- UPDATE_TEXT_ENTRY_ADAPTER, node.mNodePointer, 0,
- data);
- UpdateTextEntryAdapter updater = new UpdateTextEntryAdapter(
- node.mName, getUrl(), update);
- Thread t = new Thread(updater);
- t.start();
- }
- }
- mTextEntry.setMaxLength(maxLength);
- AutoCompleteAdapter adapter = null;
- mTextEntry.setAdapterCustom(adapter);
- mTextEntry.setSingleLine(node.mIsTextField);
- mTextEntry.setInPassword(node.mIsPassword);
- if (null == text) {
- mTextEntry.setText("", 0, 0);
- } else {
- // Change to true to enable the old style behavior, where
- // entering a textfield/textarea always set the selection to the
- // whole field. This was desirable for the case where the user
- // intends to scroll past the field using the trackball.
- // However, it causes a problem when replying to emails - the
- // user expects the cursor to be at the beginning of the
- // textarea. Testing out a new behavior, where textfields set
- // selection at the end, and textareas at the beginning.
- if (false) {
- mTextEntry.setText(text, 0, text.length());
- } else if (node.mIsTextField) {
- int length = text.length();
- mTextEntry.setText(text, length, length);
- } else {
- mTextEntry.setText(text, 0, 0);
- }
- }
- mTextEntry.requestFocus();
- }
- }
-
- private class UpdateTextEntryAdapter implements Runnable {
- private String mName;
- private String mUrl;
- private Message mUpdateMessage;
-
- public UpdateTextEntryAdapter(String name, String url, Message msg) {
- mName = name;
- mUrl = url;
- mUpdateMessage = msg;
- }
-
- public void run() {
- ArrayList<String> pastEntries = mDatabase.getFormData(mUrl, mName);
- if (pastEntries.size() > 0) {
- AutoCompleteAdapter adapter = new
- AutoCompleteAdapter(mContext, pastEntries);
- ((HashMap) mUpdateMessage.obj).put("adapter", adapter);
- mUpdateMessage.sendToTarget();
- }
- }
- }
-
- private void setTextEntryRect(int x, int y, int width, int height) {
- x = contentToView(x);
- y = contentToView(y);
- width = contentToView(width);
- height = contentToView(height);
- mTextEntry.setRect(x, y, width, height);
- }
-
- // This is used to determine long press with the enter key, or
- // a center key. Does not affect long press with the trackball/touch.
- private boolean mGotEnterDown = false;
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "keyDown at " + System.currentTimeMillis()
- + ", " + event);
- }
-
- if (mNativeClass == 0) {
- return false;
- }
-
- // do this hack up front, so it always works, regardless of touch-mode
- if (AUTO_REDRAW_HACK && (keyCode == KeyEvent.KEYCODE_CALL)) {
- mAutoRedraw = !mAutoRedraw;
- if (mAutoRedraw) {
- invalidate();
- }
- return true;
- }
-
- // Bubble up the key event if
- // 1. it is a system key; or
- // 2. the host application wants to handle it; or
- // 3. webview is in scroll-zoom state;
- if (event.isSystem()
- || mCallbackProxy.uiOverrideKeyEvent(event)
- || (mTouchMode >= FIRST_SCROLL_ZOOM && mTouchMode <= LAST_SCROLL_ZOOM)) {
- return false;
- }
-
- if (mShiftIsPressed == false && nativeFocusNodeWantsKeyEvents() == false
- && (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
- || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT)) {
- mExtendSelection = false;
- mShiftIsPressed = true;
- if (nativeUpdateFocusNode()) {
- FocusNode node = mFocusNode;
- mSelectX = contentToView(node.mBounds.left);
- mSelectY = contentToView(node.mBounds.top);
- } else {
- mSelectX = mScrollX + (int) mLastTouchX;
- mSelectY = mScrollY + (int) mLastTouchY;
- }
- }
-
- if (keyCode >= KeyEvent.KEYCODE_DPAD_UP
- && keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT) {
- // always handle the navigation keys in the UI thread
- switchOutDrawHistory();
- if (navHandledKey(keyCode, 1, false, event.getEventTime())) {
- playSoundEffect(keyCodeToSoundsEffect(keyCode));
- return true;
- }
- // Bubble up the key event as WebView doesn't handle it
- return false;
- }
-
- if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER
- || keyCode == KeyEvent.KEYCODE_ENTER) {
- switchOutDrawHistory();
- if (event.getRepeatCount() == 0) {
- mGotEnterDown = true;
- mPrivateHandler.sendMessageDelayed(mPrivateHandler
- .obtainMessage(LONG_PRESS_ENTER), LONG_PRESS_TIMEOUT);
- // Already checked mNativeClass, so we do not need to check it
- // again.
- nativeRecordButtons(hasFocus() && hasWindowFocus(), true, true);
- return true;
- }
- // Bubble up the key event as WebView doesn't handle it
- return false;
- }
-
- if (getSettings().getNavDump()) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_4:
- // "/data/data/com.android.browser/displayTree.txt"
- nativeDumpDisplayTree(getUrl());
- break;
- case KeyEvent.KEYCODE_5:
- case KeyEvent.KEYCODE_6:
- // 5: dump the dom tree to the file
- // "/data/data/com.android.browser/domTree.txt"
- // 6: dump the dom tree to the adb log
- mWebViewCore.sendMessage(EventHub.DUMP_DOMTREE,
- (keyCode == KeyEvent.KEYCODE_5) ? 1 : 0, 0);
- break;
- case KeyEvent.KEYCODE_7:
- case KeyEvent.KEYCODE_8:
- // 7: dump the render tree to the file
- // "/data/data/com.android.browser/renderTree.txt"
- // 8: dump the render tree to the adb log
- mWebViewCore.sendMessage(EventHub.DUMP_RENDERTREE,
- (keyCode == KeyEvent.KEYCODE_7) ? 1 : 0, 0);
- break;
- case KeyEvent.KEYCODE_9:
- nativeInstrumentReport();
- return true;
- }
- }
-
- // TODO: should we pass all the keys to DOM or check the meta tag
- if (nativeFocusNodeWantsKeyEvents() || true) {
- // pass the key to DOM
- mWebViewCore.sendMessage(EventHub.KEY_DOWN, event);
- // return true as DOM handles the key
- return true;
- }
-
- // Bubble up the key event as WebView doesn't handle it
- return false;
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "keyUp at " + System.currentTimeMillis()
- + ", " + event);
- }
-
- if (mNativeClass == 0) {
- return false;
- }
-
- // special CALL handling when focus node's href is "tel:XXX"
- if (keyCode == KeyEvent.KEYCODE_CALL && nativeUpdateFocusNode()) {
- FocusNode node = mFocusNode;
- String text = node.mText;
- if (!node.mIsTextField && !node.mIsTextArea && text != null
- && text.startsWith(SCHEME_TEL)) {
- Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(text));
- getContext().startActivity(intent);
- return true;
- }
- }
-
- // Bubble up the key event if
- // 1. it is a system key; or
- // 2. the host application wants to handle it;
- if (event.isSystem() || mCallbackProxy.uiOverrideKeyEvent(event)) {
- return false;
- }
-
- // special handling in scroll_zoom state
- if (mTouchMode >= FIRST_SCROLL_ZOOM && mTouchMode <= LAST_SCROLL_ZOOM) {
- if (KeyEvent.KEYCODE_DPAD_CENTER == keyCode
- && mTouchMode != SCROLL_ZOOM_ANIMATION_IN) {
- setZoomScrollIn();
- mTouchMode = SCROLL_ZOOM_ANIMATION_IN;
- invalidate();
- return true;
- }
- return false;
- }
-
- if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
- || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
- if (commitCopy()) {
- return true;
- }
- }
-
- if (keyCode >= KeyEvent.KEYCODE_DPAD_UP
- && keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT) {
- // always handle the navigation keys in the UI thread
- // Bubble up the key event as WebView doesn't handle it
- return false;
- }
-
- if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER
- || keyCode == KeyEvent.KEYCODE_ENTER) {
- // remove the long press message first
- mPrivateHandler.removeMessages(LONG_PRESS_ENTER);
- mGotEnterDown = false;
-
- if (KeyEvent.KEYCODE_DPAD_CENTER == keyCode) {
- if (mShiftIsPressed) {
- return false;
- }
- if (getSettings().supportZoom()) {
- if (mTouchMode == TOUCH_DOUBLECLICK_MODE) {
- zoomScrollOut();
- } else {
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "TOUCH_DOUBLECLICK_MODE");
- }
- mPrivateHandler.sendMessageDelayed(mPrivateHandler
- .obtainMessage(SWITCH_TO_ENTER), TAP_TIMEOUT);
- mTouchMode = TOUCH_DOUBLECLICK_MODE;
- }
- return true;
- }
- }
-
- Rect visibleRect = sendOurVisibleRect();
- // Note that sendOurVisibleRect calls viewToContent, so the
- // coordinates should be in content coordinates.
- if (nativeUpdateFocusNode()) {
- if (Rect.intersects(mFocusNode.mBounds, visibleRect)) {
- nativeSetFollowedLink(true);
- mWebViewCore.sendMessage(EventHub.SET_FINAL_FOCUS,
- EventHub.BLOCK_FOCUS_CHANGE_UNTIL_KEY_UP, 0,
- new WebViewCore.FocusData(mFocusData));
- playSoundEffect(SoundEffectConstants.CLICK);
- if (!mCallbackProxy.uiOverrideUrlLoading(mFocusNode.mText)) {
- // use CLICK instead of KEY_DOWN/KEY_UP so that we can
- // trigger mouse click events
- mWebViewCore.sendMessage(EventHub.CLICK);
- }
- }
- return true;
- }
- // Bubble up the key event as WebView doesn't handle it
- return false;
- }
-
- // TODO: should we pass all the keys to DOM or check the meta tag
- if (nativeFocusNodeWantsKeyEvents() || true) {
- // pass the key to DOM
- mWebViewCore.sendMessage(EventHub.KEY_UP, event);
- // return true as DOM handles the key
- return true;
- }
-
- // Bubble up the key event as WebView doesn't handle it
- return false;
- }
-
- /**
- * @hide
- */
- public void emulateShiftHeld() {
- mExtendSelection = false;
- mShiftIsPressed = true;
- }
-
- private boolean commitCopy() {
- boolean copiedSomething = false;
- if (mExtendSelection) {
- // copy region so core operates on copy without touching orig.
- Region selection = new Region(nativeGetSelection());
- if (selection.isEmpty() == false) {
- Toast.makeText(mContext
- , com.android.internal.R.string.text_copied
- , Toast.LENGTH_SHORT).show();
- mWebViewCore.sendMessage(EventHub.GET_SELECTION, selection);
- copiedSomething = true;
- }
- mExtendSelection = false;
- }
- mShiftIsPressed = false;
- if (mTouchMode == TOUCH_SELECT_MODE) {
- mTouchMode = TOUCH_INIT_MODE;
- }
- return copiedSomething;
- }
-
- // Set this as a hierarchy change listener so we can know when this view
- // is removed and still have access to our parent.
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- ViewParent parent = getParent();
- if (parent instanceof ViewGroup) {
- ViewGroup p = (ViewGroup) parent;
- p.setOnHierarchyChangeListener(this);
- }
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- ViewParent parent = getParent();
- if (parent instanceof ViewGroup) {
- ViewGroup p = (ViewGroup) parent;
- p.setOnHierarchyChangeListener(null);
- }
-
- // Clean up the zoom ring
- mZoomRingController.setVisible(false);
- }
-
- // Implementation for OnHierarchyChangeListener
- public void onChildViewAdded(View parent, View child) {}
-
- public void onChildViewRemoved(View p, View child) {
- if (child == this) {
- if (inEditingMode()) {
- clearTextEntry();
- mNeedsUpdateTextEntry = true;
- }
- }
- }
-
- /**
- * @deprecated WebView should not have implemented
- * ViewTreeObserver.OnGlobalFocusChangeListener. This method
- * does nothing now.
- */
- @Deprecated
- public void onGlobalFocusChanged(View oldFocus, View newFocus) {
- }
-
- // To avoid drawing the focus ring, and remove the TextView when our window
- // loses focus.
- @Override
- public void onWindowFocusChanged(boolean hasWindowFocus) {
- if (hasWindowFocus) {
- if (hasFocus()) {
- // If our window regained focus, and we have focus, then begin
- // drawing the focus ring, and restore the TextView if
- // necessary.
- mDrawFocusRing = true;
- if (mNeedsUpdateTextEntry) {
- updateTextEntry();
- }
- if (mNativeClass != 0) {
- nativeRecordButtons(true, false, true);
- }
- } else {
- // If our window gained focus, but we do not have it, do not
- // draw the focus ring.
- mDrawFocusRing = false;
- // We do not call nativeRecordButtons here because we assume
- // that when we lost focus, or window focus, it got called with
- // false for the first parameter
- }
- } else {
- // If our window has lost focus, stop drawing the focus ring
- mDrawFocusRing = false;
- mGotKeyDown = false;
- mShiftIsPressed = false;
- if (mNativeClass != 0) {
- nativeRecordButtons(false, false, true);
- }
- }
- invalidate();
- super.onWindowFocusChanged(hasWindowFocus);
- }
-
- @Override
- protected void onFocusChanged(boolean focused, int direction,
- Rect previouslyFocusedRect) {
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "MT focusChanged " + focused + ", " + direction);
- }
- if (focused) {
- // When we regain focus, if we have window focus, resume drawing
- // the focus ring, and add the TextView if necessary.
- if (hasWindowFocus()) {
- mDrawFocusRing = true;
- if (mNeedsUpdateTextEntry) {
- updateTextEntry();
- mNeedsUpdateTextEntry = false;
- }
- if (mNativeClass != 0) {
- nativeRecordButtons(true, false, true);
- }
- //} else {
- // The WebView has gained focus while we do not have
- // windowfocus. When our window lost focus, we should have
- // called nativeRecordButtons(false...)
- }
- } else {
- // When we lost focus, unless focus went to the TextView (which is
- // true if we are in editing mode), stop drawing the focus ring.
- if (!inEditingMode()) {
- mDrawFocusRing = false;
- if (mNativeClass != 0) {
- nativeRecordButtons(false, false, true);
- }
- }
- mGotKeyDown = false;
- }
-
- super.onFocusChanged(focused, direction, previouslyFocusedRect);
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int ow, int oh) {
- super.onSizeChanged(w, h, ow, oh);
- // Center zooming to the center of the screen. This is appropriate for
- // this case of zooming, and it also sets us up properly if we remove
- // the new zoom ring controller
- mZoomCenterX = getViewWidth() * .5f;
- mZoomCenterY = getViewHeight() * .5f;
-
- // update mMinZoomScale
- if (mMinContentWidth > MAX_FLOAT_CONTENT_WIDTH) {
- boolean atMin = Math.abs(mActualScale - mMinZoomScale) < 0.01f;
- mMinZoomScale = (float) getViewWidth() / mContentWidth;
- if (atMin) {
- // if the WebView was at the minimum zoom scale, keep it. e,g.,
- // the WebView was at the minimum zoom scale at the portrait
- // mode, rotate it to the landscape modifying the scale to the
- // new minimum zoom scale, when rotating back, we would like to
- // keep the minimum zoom scale instead of keeping the same scale
- // as normally we do.
- mActualScale = mMinZoomScale;
- }
- }
-
- // we always force, in case our height changed, in which case we still
- // want to send the notification over to webkit
- setNewZoomScale(mActualScale, true);
- }
-
- @Override
- protected void onScrollChanged(int l, int t, int oldl, int oldt) {
- super.onScrollChanged(l, t, oldl, oldt);
- sendOurVisibleRect();
- }
-
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- boolean dispatch = true;
-
- if (!inEditingMode()) {
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- mGotKeyDown = true;
- } else {
- if (!mGotKeyDown) {
- /*
- * We got a key up for which we were not the recipient of
- * the original key down. Don't give it to the view.
- */
- dispatch = false;
- }
- mGotKeyDown = false;
- }
- }
-
- if (dispatch) {
- return super.dispatchKeyEvent(event);
- } else {
- // We didn't dispatch, so let something else handle the key
- return false;
- }
- }
-
- // Here are the snap align logic:
- // 1. If it starts nearly horizontally or vertically, snap align;
- // 2. If there is a dramitic direction change, let it go;
- // 3. If there is a same direction back and forth, lock it.
-
- // adjustable parameters
- private int mMinLockSnapReverseDistance;
- private static final float MAX_SLOPE_FOR_DIAG = 1.5f;
- private static final int MIN_BREAK_SNAP_CROSS_DISTANCE = 80;
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- if (mNativeClass == 0 || !isClickable() || !isLongClickable()) {
- return false;
- }
-
- if (mShowZoomRingTutorial && getSettings().supportZoom()
- && (mMaxZoomScale - mMinZoomScale) > ZOOM_RING_STEPS * 0.01f) {
- ZoomRingController.showZoomTutorialOnce(mContext);
- mShowZoomRingTutorial = false;
- mPrivateHandler.sendMessageDelayed(mPrivateHandler
- .obtainMessage(DISMISS_ZOOM_RING_TUTORIAL),
- ZOOM_RING_TUTORIAL_DURATION);
- }
-
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, ev + " at " + ev.getEventTime() + " mTouchMode="
- + mTouchMode);
- }
-
- if (mZoomRingController.isVisible() && mInZoomTapDragMode) {
- if (ev.getAction() == MotionEvent.ACTION_UP) {
- // Just released the second tap, no longer in tap-drag mode
- mInZoomTapDragMode = false;
- }
- return mZoomRingController.handleDoubleTapEvent(ev);
- }
-
- int action = ev.getAction();
- float x = ev.getX();
- float y = ev.getY();
- long eventTime = ev.getEventTime();
-
- // Due to the touch screen edge effect, a touch closer to the edge
- // always snapped to the edge. As getViewWidth() can be different from
- // getWidth() due to the scrollbar, adjusting the point to match
- // getViewWidth(). Same applied to the height.
- if (x > getViewWidth() - 1) {
- x = getViewWidth() - 1;
- }
- if (y > getViewHeight() - 1) {
- y = getViewHeight() - 1;
- }
-
- // pass the touch events from UI thread to WebCore thread
- if (mForwardTouchEvents && mTouchMode != SCROLL_ZOOM_OUT
- && mTouchMode != SCROLL_ZOOM_ANIMATION_IN
- && mTouchMode != SCROLL_ZOOM_ANIMATION_OUT
- && (action != MotionEvent.ACTION_MOVE ||
- eventTime - mLastSentTouchTime > TOUCH_SENT_INTERVAL)) {
- WebViewCore.TouchEventData ted = new WebViewCore.TouchEventData();
- ted.mAction = action;
- ted.mX = viewToContent((int) x + mScrollX);
- ted.mY = viewToContent((int) y + mScrollY);;
- mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
- mLastSentTouchTime = eventTime;
- }
-
- switch (action) {
- case MotionEvent.ACTION_DOWN: {
- if (mTouchMode == SCROLL_ZOOM_ANIMATION_IN
- || mTouchMode == SCROLL_ZOOM_ANIMATION_OUT) {
- // no interaction while animation is in progress
- break;
- } else if (mTouchMode == SCROLL_ZOOM_OUT) {
- mLastScrollX = mZoomScrollX;
- mLastScrollY = mZoomScrollY;
- // If two taps are close, ignore the first tap
- } else if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
- mTouchMode = TOUCH_DRAG_START_MODE;
- mPrivateHandler.removeMessages(RESUME_WEBCORE_UPDATE);
- } else if (mShiftIsPressed) {
- mSelectX = mScrollX + (int) x;
- mSelectY = mScrollY + (int) y;
- mTouchMode = TOUCH_SELECT_MODE;
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "select=" + mSelectX + "," + mSelectY);
- }
- nativeMoveSelection(viewToContent(mSelectX)
- , viewToContent(mSelectY), false);
- mTouchSelection = mExtendSelection = true;
- } else if (!ZoomRingController.useOldZoom(mContext) &&
- mPrivateHandler.hasMessages(RELEASE_SINGLE_TAP)) {
- // Found doubletap, invoke the zoom controller
- mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP);
- mZoomRingController.setVisible(true);
- mInZoomTapDragMode = true;
- if (mLogEvent) {
- EventLog.writeEvent(EVENT_LOG_DOUBLE_TAP_DURATION,
- (eventTime - mLastTouchUpTime), eventTime);
- }
- return mZoomRingController.handleDoubleTapEvent(ev);
- } else {
- mTouchMode = TOUCH_INIT_MODE;
- mPreventDrag = mForwardTouchEvents;
- if (mLogEvent && eventTime - mLastTouchUpTime < 1000) {
- EventLog.writeEvent(EVENT_LOG_DOUBLE_TAP_DURATION,
- (eventTime - mLastTouchUpTime), eventTime);
- }
- }
- // don't trigger the link if zoom ring is visible
- if (mTouchMode == TOUCH_INIT_MODE
- && !mZoomRingController.isVisible()) {
- mPrivateHandler.sendMessageDelayed(mPrivateHandler
- .obtainMessage(SWITCH_TO_SHORTPRESS), TAP_TIMEOUT);
- }
- // Remember where the motion event started
- mLastTouchX = x;
- mLastTouchY = y;
- mLastTouchTime = eventTime;
- mVelocityTracker = VelocityTracker.obtain();
- mSnapScrollMode = SNAP_NONE;
- break;
- }
- case MotionEvent.ACTION_MOVE: {
- if (mTouchMode == TOUCH_DONE_MODE
- || mTouchMode == SCROLL_ZOOM_ANIMATION_IN
- || mTouchMode == SCROLL_ZOOM_ANIMATION_OUT) {
- // no dragging during scroll zoom animation
- break;
- }
- if (mTouchMode == SCROLL_ZOOM_OUT) {
- // while fully zoomed out, move the virtual window
- moveZoomScrollWindow(x, y);
- break;
- }
- mVelocityTracker.addMovement(ev);
-
- int deltaX = (int) (mLastTouchX - x);
- int deltaY = (int) (mLastTouchY - y);
-
- if (mTouchMode != TOUCH_DRAG_MODE) {
- if (mTouchMode == TOUCH_SELECT_MODE) {
- mSelectX = mScrollX + (int) x;
- mSelectY = mScrollY + (int) y;
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "xtend=" + mSelectX + "," + mSelectY);
- }
- nativeMoveSelection(viewToContent(mSelectX)
- , viewToContent(mSelectY), true);
- invalidate();
- break;
- }
- if (mPreventDrag || (deltaX * deltaX + deltaY * deltaY)
- < mTouchSlopSquare) {
- break;
- }
-
- if (mTouchMode == TOUCH_SHORTPRESS_MODE
- || mTouchMode == TOUCH_SHORTPRESS_START_MODE) {
- mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
- } else if (mTouchMode == TOUCH_INIT_MODE) {
- mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
- }
-
- // if it starts nearly horizontal or vertical, enforce it
- int ax = Math.abs(deltaX);
- int ay = Math.abs(deltaY);
- if (ax > MAX_SLOPE_FOR_DIAG * ay) {
- mSnapScrollMode = SNAP_X;
- mSnapPositive = deltaX > 0;
- } else if (ay > MAX_SLOPE_FOR_DIAG * ax) {
- mSnapScrollMode = SNAP_Y;
- mSnapPositive = deltaY > 0;
- }
-
- mTouchMode = TOUCH_DRAG_MODE;
- WebViewCore.pauseUpdate(mWebViewCore);
- int contentX = viewToContent((int) x + mScrollX);
- int contentY = viewToContent((int) y + mScrollY);
- if (inEditingMode()) {
- mTextEntry.updateCachedTextfield();
- }
- nativeClearFocus(contentX, contentY);
- // remove the zoom anchor if there is any
- if (mZoomScale != 0) {
- mWebViewCore
- .sendMessage(EventHub.SET_SNAP_ANCHOR, 0, 0);
- }
- }
-
- // do pan
- int newScrollX = pinLocX(mScrollX + deltaX);
- deltaX = newScrollX - mScrollX;
- int newScrollY = pinLocY(mScrollY + deltaY);
- deltaY = newScrollY - mScrollY;
- boolean done = false;
- if (deltaX == 0 && deltaY == 0) {
- done = true;
- } else {
- if (mSnapScrollMode == SNAP_X || mSnapScrollMode == SNAP_Y) {
- int ax = Math.abs(deltaX);
- int ay = Math.abs(deltaY);
- if (mSnapScrollMode == SNAP_X) {
- // radical change means getting out of snap mode
- if (ay > MAX_SLOPE_FOR_DIAG * ax
- && ay > MIN_BREAK_SNAP_CROSS_DISTANCE) {
- mSnapScrollMode = SNAP_NONE;
- }
- // reverse direction means lock in the snap mode
- if ((ax > MAX_SLOPE_FOR_DIAG * ay) &&
- ((mSnapPositive &&
- deltaX < -mMinLockSnapReverseDistance)
- || (!mSnapPositive &&
- deltaX > mMinLockSnapReverseDistance))) {
- mSnapScrollMode = SNAP_X_LOCK;
- }
- } else {
- // radical change means getting out of snap mode
- if ((ax > MAX_SLOPE_FOR_DIAG * ay)
- && ax > MIN_BREAK_SNAP_CROSS_DISTANCE) {
- mSnapScrollMode = SNAP_NONE;
- }
- // reverse direction means lock in the snap mode
- if ((ay > MAX_SLOPE_FOR_DIAG * ax) &&
- ((mSnapPositive &&
- deltaY < -mMinLockSnapReverseDistance)
- || (!mSnapPositive &&
- deltaY > mMinLockSnapReverseDistance))) {
- mSnapScrollMode = SNAP_Y_LOCK;
- }
- }
- }
-
- if (mSnapScrollMode == SNAP_X
- || mSnapScrollMode == SNAP_X_LOCK) {
- scrollBy(deltaX, 0);
- mLastTouchX = x;
- } else if (mSnapScrollMode == SNAP_Y
- || mSnapScrollMode == SNAP_Y_LOCK) {
- scrollBy(0, deltaY);
- mLastTouchY = y;
- } else {
- scrollBy(deltaX, deltaY);
- mLastTouchX = x;
- mLastTouchY = y;
- }
- mLastTouchTime = eventTime;
- mUserScroll = true;
- }
-
- if (ZoomRingController.useOldZoom(mContext)) {
- boolean showPlusMinus = mMinZoomScale < mMaxZoomScale;
- boolean showMagnify = canZoomScrollOut();
- if (mZoomControls != null && (showPlusMinus || showMagnify)) {
- if (mZoomControls.getVisibility() == View.VISIBLE) {
- mPrivateHandler.removeCallbacks(mZoomControlRunnable);
- } else {
- mZoomControls.show(showPlusMinus, showMagnify);
- }
- mPrivateHandler.postDelayed(mZoomControlRunnable,
- ZOOM_CONTROLS_TIMEOUT);
- }
- }
- if (done) {
- // return false to indicate that we can't pan out of the
- // view space
- return false;
- }
- break;
- }
- case MotionEvent.ACTION_UP: {
- mLastTouchUpTime = eventTime;
- switch (mTouchMode) {
- case TOUCH_INIT_MODE: // tap
- if (mZoomRingController.isVisible()) {
- // don't trigger the link if zoom ring is visible,
- // but still allow the double tap
- mPrivateHandler.sendMessageDelayed(mPrivateHandler
- .obtainMessage(RELEASE_SINGLE_TAP,
- new Boolean(false)),
- DOUBLE_TAP_TIMEOUT);
- break;
- }
- mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
- if (getSettings().supportZoom()) {
- mPrivateHandler.sendMessageDelayed(mPrivateHandler
- .obtainMessage(RELEASE_SINGLE_TAP,
- new Boolean(true)),
- DOUBLE_TAP_TIMEOUT);
- } else {
- // do short press now
- mTouchMode = TOUCH_DONE_MODE;
- doShortPress();
- }
- break;
- case TOUCH_SELECT_MODE:
- commitCopy();
- mTouchSelection = false;
- break;
- case SCROLL_ZOOM_ANIMATION_IN:
- case SCROLL_ZOOM_ANIMATION_OUT:
- // no action during scroll animation
- break;
- case SCROLL_ZOOM_OUT:
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "ACTION_UP SCROLL_ZOOM_OUT"
- + " eventTime - mLastTouchTime="
- + (eventTime - mLastTouchTime));
- }
- // for now, always zoom back when the drag completes
- if (true || eventTime - mLastTouchTime < TAP_TIMEOUT) {
- // but if we tap, zoom in where we tap
- if (eventTime - mLastTouchTime < TAP_TIMEOUT) {
- zoomScrollTap(x, y);
- }
- // start zooming in back to the original view
- setZoomScrollIn();
- mTouchMode = SCROLL_ZOOM_ANIMATION_IN;
- invalidate();
- }
- break;
- case TOUCH_SHORTPRESS_START_MODE:
- case TOUCH_SHORTPRESS_MODE: {
- mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
- if (eventTime - mLastTouchTime < TAP_TIMEOUT
- && getSettings().supportZoom()) {
- // Note: window manager will not release ACTION_UP
- // until all the previous action events are
- // returned. If GC happens, it can cause
- // SWITCH_TO_SHORTPRESS message fired before
- // ACTION_UP sent even time stamp of ACTION_UP is
- // less than the tap time out. We need to treat this
- // as tap instead of short press.
- mTouchMode = TOUCH_INIT_MODE;
- mPrivateHandler.sendMessageDelayed(mPrivateHandler
- .obtainMessage(RELEASE_SINGLE_TAP,
- new Boolean(true)),
- DOUBLE_TAP_TIMEOUT);
- } else {
- mTouchMode = TOUCH_DONE_MODE;
- doShortPress();
- }
- break;
- }
- case TOUCH_DRAG_MODE:
- // if the user waits a while w/o moving before the
- // up, we don't want to do a fling
- if (eventTime - mLastTouchTime <= MIN_FLING_TIME) {
- mVelocityTracker.addMovement(ev);
- doFling();
- break;
- }
- WebViewCore.resumeUpdate(mWebViewCore);
- break;
- case TOUCH_DRAG_START_MODE:
- case TOUCH_DONE_MODE:
- // do nothing
- break;
- }
- // we also use mVelocityTracker == null to tell us that we are
- // not "moving around", so we can take the slower/prettier
- // mode in the drawing code
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- break;
- }
- case MotionEvent.ACTION_CANCEL: {
- // we also use mVelocityTracker == null to tell us that we are
- // not "moving around", so we can take the slower/prettier
- // mode in the drawing code
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- if (mTouchMode == SCROLL_ZOOM_OUT ||
- mTouchMode == SCROLL_ZOOM_ANIMATION_IN) {
- scrollTo(mZoomScrollX, mZoomScrollY);
- } else if (mTouchMode == TOUCH_DRAG_MODE) {
- WebViewCore.resumeUpdate(mWebViewCore);
- }
- mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
- mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
- mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP);
- mTouchMode = TOUCH_DONE_MODE;
- int contentX = viewToContent((int) mLastTouchX + mScrollX);
- int contentY = viewToContent((int) mLastTouchY + mScrollY);
- if (inEditingMode()) {
- mTextEntry.updateCachedTextfield();
- }
- nativeClearFocus(contentX, contentY);
- break;
- }
- }
- return true;
- }
-
- private long mTrackballFirstTime = 0;
- private long mTrackballLastTime = 0;
- private float mTrackballRemainsX = 0.0f;
- private float mTrackballRemainsY = 0.0f;
- private int mTrackballXMove = 0;
- private int mTrackballYMove = 0;
- private boolean mExtendSelection = false;
- private boolean mTouchSelection = false;
- private static final int TRACKBALL_KEY_TIMEOUT = 1000;
- private static final int TRACKBALL_TIMEOUT = 200;
- private static final int TRACKBALL_WAIT = 100;
- private static final int TRACKBALL_SCALE = 400;
- private static final int TRACKBALL_SCROLL_COUNT = 5;
- private static final int TRACKBALL_MOVE_COUNT = 10;
- private static final int TRACKBALL_MULTIPLIER = 3;
- private static final int SELECT_CURSOR_OFFSET = 16;
- private int mSelectX = 0;
- private int mSelectY = 0;
- private boolean mShiftIsPressed = false;
- private boolean mTrackballDown = false;
- private long mTrackballUpTime = 0;
- private long mLastFocusTime = 0;
- private Rect mLastFocusBounds;
-
- // Set by default; BrowserActivity clears to interpret trackball data
- // directly for movement. Currently, the framework only passes
- // arrow key events, not trackball events, from one child to the next
- private boolean mMapTrackballToArrowKeys = true;
-
- public void setMapTrackballToArrowKeys(boolean setMap) {
- mMapTrackballToArrowKeys = setMap;
- }
-
- void resetTrackballTime() {
- mTrackballLastTime = 0;
- }
-
- @Override
- public boolean onTrackballEvent(MotionEvent ev) {
- long time = ev.getEventTime();
- if ((ev.getMetaState() & KeyEvent.META_ALT_ON) != 0) {
- if (ev.getY() > 0) pageDown(true);
- if (ev.getY() < 0) pageUp(true);
- return true;
- }
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mPrivateHandler.removeMessages(SWITCH_TO_ENTER);
- mTrackballDown = true;
- if (mNativeClass != 0) {
- nativeRecordButtons(hasFocus() && hasWindowFocus(), true, true);
- }
- if (time - mLastFocusTime <= TRACKBALL_TIMEOUT
- && !mLastFocusBounds.equals(nativeGetFocusRingBounds())) {
- nativeSelectBestAt(mLastFocusBounds);
- }
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "onTrackballEvent down ev=" + ev
- + " time=" + time
- + " mLastFocusTime=" + mLastFocusTime);
- }
- if (isInTouchMode()) requestFocusFromTouch();
- return false; // let common code in onKeyDown at it
- }
- if (ev.getAction() == MotionEvent.ACTION_UP) {
- // LONG_PRESS_ENTER is set in common onKeyDown
- mPrivateHandler.removeMessages(LONG_PRESS_ENTER);
- mTrackballDown = false;
- mTrackballUpTime = time;
- if (mShiftIsPressed) {
- if (mExtendSelection) {
- commitCopy();
- } else {
- mExtendSelection = true;
- }
- }
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "onTrackballEvent up ev=" + ev
- + " time=" + time
- );
- }
- return false; // let common code in onKeyUp at it
- }
- if (mMapTrackballToArrowKeys && mShiftIsPressed == false) {
- if (LOGV_ENABLED) Log.v(LOGTAG, "onTrackballEvent gmail quit");
- return false;
- }
- // no move if we're still waiting on SWITCH_TO_ENTER timeout
- if (mTouchMode == TOUCH_DOUBLECLICK_MODE) {
- if (LOGV_ENABLED) Log.v(LOGTAG, "onTrackballEvent 2 click quit");
- return true;
- }
- if (mTrackballDown) {
- if (LOGV_ENABLED) Log.v(LOGTAG, "onTrackballEvent down quit");
- return true; // discard move if trackball is down
- }
- if (time - mTrackballUpTime < TRACKBALL_TIMEOUT) {
- if (LOGV_ENABLED) Log.v(LOGTAG, "onTrackballEvent up timeout quit");
- return true;
- }
- // TODO: alternatively we can do panning as touch does
- switchOutDrawHistory();
- if (time - mTrackballLastTime > TRACKBALL_TIMEOUT) {
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "onTrackballEvent time="
- + time + " last=" + mTrackballLastTime);
- }
- mTrackballFirstTime = time;
- mTrackballXMove = mTrackballYMove = 0;
- }
- mTrackballLastTime = time;
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "onTrackballEvent ev=" + ev + " time=" + time);
- }
- mTrackballRemainsX += ev.getX();
- mTrackballRemainsY += ev.getY();
- doTrackball(time);
- return true;
- }
-
- void moveSelection(float xRate, float yRate) {
- if (mNativeClass == 0)
- return;
- int width = getViewWidth();
- int height = getViewHeight();
- mSelectX += scaleTrackballX(xRate, width);
- mSelectY += scaleTrackballY(yRate, height);
- int maxX = width + mScrollX;
- int maxY = height + mScrollY;
- mSelectX = Math.min(maxX, Math.max(mScrollX - SELECT_CURSOR_OFFSET
- , mSelectX));
- mSelectY = Math.min(maxY, Math.max(mScrollY - SELECT_CURSOR_OFFSET
- , mSelectY));
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "moveSelection"
- + " mSelectX=" + mSelectX
- + " mSelectY=" + mSelectY
- + " mScrollX=" + mScrollX
- + " mScrollY=" + mScrollY
- + " xRate=" + xRate
- + " yRate=" + yRate
- );
- }
- nativeMoveSelection(viewToContent(mSelectX)
- , viewToContent(mSelectY), mExtendSelection);
- int scrollX = mSelectX < mScrollX ? -SELECT_CURSOR_OFFSET
- : mSelectX > maxX - SELECT_CURSOR_OFFSET ? SELECT_CURSOR_OFFSET
- : 0;
- int scrollY = mSelectY < mScrollY ? -SELECT_CURSOR_OFFSET
- : mSelectY > maxY - SELECT_CURSOR_OFFSET ? SELECT_CURSOR_OFFSET
- : 0;
- pinScrollBy(scrollX, scrollY, true, 0);
- Rect select = new Rect(mSelectX, mSelectY, mSelectX + 1, mSelectY + 1);
- requestRectangleOnScreen(select);
- invalidate();
- }
-
- private int scaleTrackballX(float xRate, int width) {
- int xMove = (int) (xRate / TRACKBALL_SCALE * width);
- int nextXMove = xMove;
- if (xMove > 0) {
- if (xMove > mTrackballXMove) {
- xMove -= mTrackballXMove;
- }
- } else if (xMove < mTrackballXMove) {
- xMove -= mTrackballXMove;
- }
- mTrackballXMove = nextXMove;
- return xMove;
- }
-
- private int scaleTrackballY(float yRate, int height) {
- int yMove = (int) (yRate / TRACKBALL_SCALE * height);
- int nextYMove = yMove;
- if (yMove > 0) {
- if (yMove > mTrackballYMove) {
- yMove -= mTrackballYMove;
- }
- } else if (yMove < mTrackballYMove) {
- yMove -= mTrackballYMove;
- }
- mTrackballYMove = nextYMove;
- return yMove;
- }
-
- private int keyCodeToSoundsEffect(int keyCode) {
- switch(keyCode) {
- case KeyEvent.KEYCODE_DPAD_UP:
- return SoundEffectConstants.NAVIGATION_UP;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- return SoundEffectConstants.NAVIGATION_RIGHT;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- return SoundEffectConstants.NAVIGATION_DOWN;
- case KeyEvent.KEYCODE_DPAD_LEFT:
- return SoundEffectConstants.NAVIGATION_LEFT;
- }
- throw new IllegalArgumentException("keyCode must be one of " +
- "{KEYCODE_DPAD_UP, KEYCODE_DPAD_RIGHT, KEYCODE_DPAD_DOWN, " +
- "KEYCODE_DPAD_LEFT}.");
- }
-
- private void doTrackball(long time) {
- int elapsed = (int) (mTrackballLastTime - mTrackballFirstTime);
- if (elapsed == 0) {
- elapsed = TRACKBALL_TIMEOUT;
- }
- float xRate = mTrackballRemainsX * 1000 / elapsed;
- float yRate = mTrackballRemainsY * 1000 / elapsed;
- if (mShiftIsPressed) {
- moveSelection(xRate, yRate);
- mTrackballRemainsX = mTrackballRemainsY = 0;
- return;
- }
- float ax = Math.abs(xRate);
- float ay = Math.abs(yRate);
- float maxA = Math.max(ax, ay);
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "doTrackball elapsed=" + elapsed
- + " xRate=" + xRate
- + " yRate=" + yRate
- + " mTrackballRemainsX=" + mTrackballRemainsX
- + " mTrackballRemainsY=" + mTrackballRemainsY);
- }
- int width = mContentWidth - getViewWidth();
- int height = mContentHeight - getViewHeight();
- if (width < 0) width = 0;
- if (height < 0) height = 0;
- if (mTouchMode == SCROLL_ZOOM_OUT) {
- int oldX = mZoomScrollX;
- int oldY = mZoomScrollY;
- int maxWH = Math.max(width, height);
- mZoomScrollX += scaleTrackballX(xRate, maxWH);
- mZoomScrollY += scaleTrackballY(yRate, maxWH);
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "doTrackball SCROLL_ZOOM_OUT"
- + " mZoomScrollX=" + mZoomScrollX
- + " mZoomScrollY=" + mZoomScrollY);
- }
- mZoomScrollX = Math.min(width, Math.max(0, mZoomScrollX));
- mZoomScrollY = Math.min(height, Math.max(0, mZoomScrollY));
- if (oldX != mZoomScrollX || oldY != mZoomScrollY) {
- invalidate();
- }
- mTrackballRemainsX = mTrackballRemainsY = 0;
- return;
- }
- ax = Math.abs(mTrackballRemainsX * TRACKBALL_MULTIPLIER);
- ay = Math.abs(mTrackballRemainsY * TRACKBALL_MULTIPLIER);
- maxA = Math.max(ax, ay);
- int count = Math.max(0, (int) maxA);
- int oldScrollX = mScrollX;
- int oldScrollY = mScrollY;
- if (count > 0) {
- int selectKeyCode = ax < ay ? mTrackballRemainsY < 0 ?
- KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DPAD_DOWN :
- mTrackballRemainsX < 0 ? KeyEvent.KEYCODE_DPAD_LEFT :
- KeyEvent.KEYCODE_DPAD_RIGHT;
- count = Math.min(count, TRACKBALL_MOVE_COUNT);
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "doTrackball keyCode=" + selectKeyCode
- + " count=" + count
- + " mTrackballRemainsX=" + mTrackballRemainsX
- + " mTrackballRemainsY=" + mTrackballRemainsY);
- }
- if (navHandledKey(selectKeyCode, count, false, time)) {
- playSoundEffect(keyCodeToSoundsEffect(selectKeyCode));
- }
- mTrackballRemainsX = mTrackballRemainsY = 0;
- }
- if (count >= TRACKBALL_SCROLL_COUNT) {
- int xMove = scaleTrackballX(xRate, width);
- int yMove = scaleTrackballY(yRate, height);
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "doTrackball pinScrollBy"
- + " count=" + count
- + " xMove=" + xMove + " yMove=" + yMove
- + " mScrollX-oldScrollX=" + (mScrollX-oldScrollX)
- + " mScrollY-oldScrollY=" + (mScrollY-oldScrollY)
- );
- }
- if (Math.abs(mScrollX - oldScrollX) > Math.abs(xMove)) {
- xMove = 0;
- }
- if (Math.abs(mScrollY - oldScrollY) > Math.abs(yMove)) {
- yMove = 0;
- }
- if (xMove != 0 || yMove != 0) {
- pinScrollBy(xMove, yMove, true, 0);
- }
- mUserScroll = true;
- }
- mWebViewCore.sendMessage(EventHub.UNBLOCK_FOCUS);
- }
-
- public void flingScroll(int vx, int vy) {
- int maxX = Math.max(computeHorizontalScrollRange() - getViewWidth(), 0);
- int maxY = Math.max(computeVerticalScrollRange() - getViewHeight(), 0);
-
- mScroller.fling(mScrollX, mScrollY, vx, vy, 0, maxX, 0, maxY);
- invalidate();
- }
-
- private void doFling() {
- if (mVelocityTracker == null) {
- return;
- }
- int maxX = Math.max(computeHorizontalScrollRange() - getViewWidth(), 0);
- int maxY = Math.max(computeVerticalScrollRange() - getViewHeight(), 0);
-
- mVelocityTracker.computeCurrentVelocity(1000);
- int vx = (int) mVelocityTracker.getXVelocity();
- int vy = (int) mVelocityTracker.getYVelocity();
-
- if (mSnapScrollMode != SNAP_NONE) {
- if (mSnapScrollMode == SNAP_X || mSnapScrollMode == SNAP_X_LOCK) {
- vy = 0;
- } else {
- vx = 0;
- }
- }
-
- if (true /* EMG release: make our fling more like Maps' */) {
- // maps cuts their velocity in half
- vx = vx * 3 / 4;
- vy = vy * 3 / 4;
- }
-
- mScroller.fling(mScrollX, mScrollY, -vx, -vy, 0, maxX, 0, maxY);
- // TODO: duration is calculated based on velocity, if the range is
- // small, the animation will stop before duration is up. We may
- // want to calculate how long the animation is going to run to precisely
- // resume the webcore update.
- final int time = mScroller.getDuration();
- mPrivateHandler.sendEmptyMessageDelayed(RESUME_WEBCORE_UPDATE, time);
- invalidate();
- }
-
- private boolean zoomWithPreview(float scale) {
- float oldScale = mActualScale;
-
- // snap to 100% if it is close
- if (scale > 0.95f && scale < 1.05f) {
- scale = 1.0f;
- }
-
- setNewZoomScale(scale, false);
-
- if (oldScale != mActualScale) {
- // use mZoomPickerScale to see zoom preview first
- mZoomStart = SystemClock.uptimeMillis();
- mInvInitialZoomScale = 1.0f / oldScale;
- mInvFinalZoomScale = 1.0f / mActualScale;
- mZoomScale = mActualScale;
- invalidate();
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Returns a view containing zoom controls i.e. +/- buttons. The caller is
- * in charge of installing this view to the view hierarchy. This view will
- * become visible when the user starts scrolling via touch and fade away if
- * the user does not interact with it.
- */
- public View getZoomControls() {
- if (!getSettings().supportZoom()) {
- Log.w(LOGTAG, "This WebView doesn't support zoom.");
- return null;
- }
- if (mZoomControls == null) {
- mZoomControls = createZoomControls();
-
- /*
- * need to be set to VISIBLE first so that getMeasuredHeight() in
- * {@link #onSizeChanged()} can return the measured value for proper
- * layout.
- */
- mZoomControls.setVisibility(View.VISIBLE);
- mZoomControlRunnable = new Runnable() {
- public void run() {
-
- /* Don't dismiss the controls if the user has
- * focus on them. Wait and check again later.
- */
- if (!mZoomControls.hasFocus()) {
- mZoomControls.hide();
- } else {
- mPrivateHandler.removeCallbacks(mZoomControlRunnable);
- mPrivateHandler.postDelayed(mZoomControlRunnable,
- ZOOM_CONTROLS_TIMEOUT);
- }
- }
- };
- }
- return mZoomControls;
- }
-
- /**
- * @hide pending API council? Assuming we make ZoomRingController itself
- * public, which I think we will.
- */
- public ZoomRingController getZoomRingController() {
- return mZoomRingController;
- }
-
- /**
- * Perform zoom in in the webview
- * @return TRUE if zoom in succeeds. FALSE if no zoom changes.
- */
- public boolean zoomIn() {
- // TODO: alternatively we can disallow this during draw history mode
- switchOutDrawHistory();
- return zoomWithPreview(mActualScale * 1.25f);
- }
-
- /**
- * Perform zoom out in the webview
- * @return TRUE if zoom out succeeds. FALSE if no zoom changes.
- */
- public boolean zoomOut() {
- // TODO: alternatively we can disallow this during draw history mode
- switchOutDrawHistory();
- return zoomWithPreview(mActualScale * 0.8f);
- }
-
- private ExtendedZoomControls createZoomControls() {
- ExtendedZoomControls zoomControls = new ExtendedZoomControls(mContext
- , null);
- zoomControls.setOnZoomInClickListener(new OnClickListener() {
- public void onClick(View v) {
- // reset time out
- mPrivateHandler.removeCallbacks(mZoomControlRunnable);
- mPrivateHandler.postDelayed(mZoomControlRunnable,
- ZOOM_CONTROLS_TIMEOUT);
- zoomIn();
- }
- });
- zoomControls.setOnZoomOutClickListener(new OnClickListener() {
- public void onClick(View v) {
- // reset time out
- mPrivateHandler.removeCallbacks(mZoomControlRunnable);
- mPrivateHandler.postDelayed(mZoomControlRunnable,
- ZOOM_CONTROLS_TIMEOUT);
- zoomOut();
- }
- });
- zoomControls.setOnZoomMagnifyClickListener(new OnClickListener() {
- public void onClick(View v) {
- // Hide the zoom ring
- mZoomRingController.setVisible(false);
-
- mPrivateHandler.removeCallbacks(mZoomControlRunnable);
- mPrivateHandler.postDelayed(mZoomControlRunnable,
- ZOOM_CONTROLS_TIMEOUT);
- zoomScrollOut();
- }
- });
- return zoomControls;
- }
-
- private void updateSelection() {
- if (mNativeClass == 0) {
- return;
- }
- // mLastTouchX and mLastTouchY are the point in the current viewport
- int contentX = viewToContent((int) mLastTouchX + mScrollX);
- int contentY = viewToContent((int) mLastTouchY + mScrollY);
- int contentSize = ViewConfiguration.getTouchSlop();
- Rect rect = new Rect(contentX - contentSize, contentY - contentSize,
- contentX + contentSize, contentY + contentSize);
- // If we were already focused on a textfield, update its cache.
- if (inEditingMode()) {
- mTextEntry.updateCachedTextfield();
- }
- nativeSelectBestAt(rect);
- }
-
- /*package*/ void shortPressOnTextField() {
- if (inEditingMode()) {
- View v = mTextEntry;
- int x = viewToContent((v.getLeft() + v.getRight()) >> 1);
- int y = viewToContent((v.getTop() + v.getBottom()) >> 1);
- int contentSize = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- nativeMotionUp(x, y, contentSize, true);
- }
- }
-
- private void doShortPress() {
- if (mNativeClass == 0) {
- return;
- }
- switchOutDrawHistory();
- // mLastTouchX and mLastTouchY are the point in the current viewport
- int contentX = viewToContent((int) mLastTouchX + mScrollX);
- int contentY = viewToContent((int) mLastTouchY + mScrollY);
- int contentSize = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- if (nativeMotionUp(contentX, contentY, contentSize, true)) {
- if (mLogEvent) {
- Checkin.updateStats(mContext.getContentResolver(),
- Checkin.Stats.Tag.BROWSER_SNAP_CENTER, 1, 0.0);
- }
- }
- if (nativeUpdateFocusNode() && !mFocusNode.mIsTextField
- && !mFocusNode.mIsTextArea) {
- playSoundEffect(SoundEffectConstants.CLICK);
- }
- }
-
- // Called by JNI to handle a touch on a node representing an email address,
- // address, or phone number
- private void overrideLoading(String url) {
- mCallbackProxy.uiOverrideUrlLoading(url);
- }
-
- @Override
- public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
- boolean result = false;
- if (inEditingMode()) {
- result = mTextEntry.requestFocus(direction, previouslyFocusedRect);
- } else {
- result = super.requestFocus(direction, previouslyFocusedRect);
- if (mWebViewCore.getSettings().getNeedInitialFocus()) {
- // For cases such as GMail, where we gain focus from a direction,
- // we want to move to the first available link.
- // FIXME: If there are no visible links, we may not want to
- int fakeKeyDirection = 0;
- switch(direction) {
- case View.FOCUS_UP:
- fakeKeyDirection = KeyEvent.KEYCODE_DPAD_UP;
- break;
- case View.FOCUS_DOWN:
- fakeKeyDirection = KeyEvent.KEYCODE_DPAD_DOWN;
- break;
- case View.FOCUS_LEFT:
- fakeKeyDirection = KeyEvent.KEYCODE_DPAD_LEFT;
- break;
- case View.FOCUS_RIGHT:
- fakeKeyDirection = KeyEvent.KEYCODE_DPAD_RIGHT;
- break;
- default:
- return result;
- }
- if (mNativeClass != 0 && !nativeUpdateFocusNode()) {
- navHandledKey(fakeKeyDirection, 1, true, 0);
- }
- }
- }
- return result;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
-
- int measuredHeight = heightSize;
- int measuredWidth = widthSize;
-
- // Grab the content size from WebViewCore.
- int contentHeight = mContentHeight;
- int contentWidth = mContentWidth;
-
-// Log.d(LOGTAG, "------- measure " + heightMode);
-
- if (heightMode != MeasureSpec.EXACTLY) {
- mHeightCanMeasure = true;
- measuredHeight = contentHeight;
- if (heightMode == MeasureSpec.AT_MOST) {
- // If we are larger than the AT_MOST height, then our height can
- // no longer be measured and we should scroll internally.
- if (measuredHeight > heightSize) {
- measuredHeight = heightSize;
- mHeightCanMeasure = false;
- }
- }
- } else {
- mHeightCanMeasure = false;
- }
- if (mNativeClass != 0) {
- nativeSetHeightCanMeasure(mHeightCanMeasure);
- }
- // For the width, always use the given size unless unspecified.
- if (widthMode == MeasureSpec.UNSPECIFIED) {
- mWidthCanMeasure = true;
- measuredWidth = contentWidth;
- } else {
- mWidthCanMeasure = false;
- }
-
- synchronized (this) {
- setMeasuredDimension(measuredWidth, measuredHeight);
- }
- }
-
- @Override
- public boolean requestChildRectangleOnScreen(View child,
- Rect rect,
- boolean immediate) {
- rect.offset(child.getLeft() - child.getScrollX(),
- child.getTop() - child.getScrollY());
-
- int height = getHeight() - getHorizontalScrollbarHeight();
- int screenTop = mScrollY;
- int screenBottom = screenTop + height;
-
- int scrollYDelta = 0;
-
- if (rect.bottom > screenBottom && rect.top > screenTop) {
- if (rect.height() > height) {
- scrollYDelta += (rect.top - screenTop);
- } else {
- scrollYDelta += (rect.bottom - screenBottom);
- }
- } else if (rect.top < screenTop) {
- scrollYDelta -= (screenTop - rect.top);
- }
-
- int width = getWidth() - getVerticalScrollbarWidth();
- int screenLeft = mScrollX;
- int screenRight = screenLeft + width;
-
- int scrollXDelta = 0;
-
- if (rect.right > screenRight && rect.left > screenLeft) {
- if (rect.width() > width) {
- scrollXDelta += (rect.left - screenLeft);
- } else {
- scrollXDelta += (rect.right - screenRight);
- }
- } else if (rect.left < screenLeft) {
- scrollXDelta -= (screenLeft - rect.left);
- }
-
- if ((scrollYDelta | scrollXDelta) != 0) {
- return pinScrollBy(scrollXDelta, scrollYDelta, !immediate, 0);
- }
-
- return false;
- }
-
- /* package */ void replaceTextfieldText(int oldStart, int oldEnd,
- String replace, int newStart, int newEnd) {
- HashMap arg = new HashMap();
- arg.put("focusData", new WebViewCore.FocusData(mFocusData));
- arg.put("replace", replace);
- arg.put("start", new Integer(newStart));
- arg.put("end", new Integer(newEnd));
- mWebViewCore.sendMessage(EventHub.REPLACE_TEXT, oldStart, oldEnd, arg);
- }
-
- /* package */ void passToJavaScript(String currentText, KeyEvent event) {
- HashMap arg = new HashMap();
- arg.put("focusData", new WebViewCore.FocusData(mFocusData));
- arg.put("event", event);
- arg.put("currentText", currentText);
- // Increase our text generation number, and pass it to webcore thread
- mTextGeneration++;
- mWebViewCore.sendMessage(EventHub.PASS_TO_JS, mTextGeneration, 0, arg);
- // WebKit's document state is not saved until about to leave the page.
- // To make sure the host application, like Browser, has the up to date
- // document state when it goes to background, we force to save the
- // document state.
- mWebViewCore.removeMessages(EventHub.SAVE_DOCUMENT_STATE);
- mWebViewCore.sendMessageDelayed(EventHub.SAVE_DOCUMENT_STATE,
- new WebViewCore.FocusData(mFocusData), 1000);
- }
-
- /* package */ WebViewCore getWebViewCore() {
- return mWebViewCore;
- }
-
- //-------------------------------------------------------------------------
- // Methods can be called from a separate thread, like WebViewCore
- // If it needs to call the View system, it has to send message.
- //-------------------------------------------------------------------------
-
- /**
- * General handler to receive message coming from webkit thread
- */
- class PrivateHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, msg.what < REMEMBER_PASSWORD || msg.what
- > INVAL_RECT_MSG_ID ? Integer.toString(msg.what)
- : HandlerDebugString[msg.what - REMEMBER_PASSWORD]);
- }
- switch (msg.what) {
- case REMEMBER_PASSWORD: {
- mDatabase.setUsernamePassword(
- msg.getData().getString("host"),
- msg.getData().getString("username"),
- msg.getData().getString("password"));
- ((Message) msg.obj).sendToTarget();
- break;
- }
- case NEVER_REMEMBER_PASSWORD: {
- mDatabase.setUsernamePassword(
- msg.getData().getString("host"), null, null);
- ((Message) msg.obj).sendToTarget();
- break;
- }
- case SWITCH_TO_SHORTPRESS: {
- if (mTouchMode == TOUCH_INIT_MODE) {
- mTouchMode = TOUCH_SHORTPRESS_START_MODE;
- updateSelection();
- }
- break;
- }
- case SWITCH_TO_LONGPRESS: {
- mTouchMode = TOUCH_DONE_MODE;
- performLongClick();
- updateTextEntry();
- break;
- }
- case RELEASE_SINGLE_TAP: {
- mTouchMode = TOUCH_DONE_MODE;
- if ((Boolean)msg.obj) {
- doShortPress();
- }
- break;
- }
- case SWITCH_TO_ENTER:
- if (LOGV_ENABLED) Log.v(LOGTAG, "SWITCH_TO_ENTER");
- mTouchMode = TOUCH_DONE_MODE;
- onKeyUp(KeyEvent.KEYCODE_ENTER
- , new KeyEvent(KeyEvent.ACTION_UP
- , KeyEvent.KEYCODE_ENTER));
- break;
- case SCROLL_BY_MSG_ID:
- setContentScrollBy(msg.arg1, msg.arg2, (Boolean) msg.obj);
- break;
- case SYNC_SCROLL_TO_MSG_ID:
- if (mUserScroll) {
- // if user has scrolled explicitly, don't sync the
- // scroll position any more
- mUserScroll = false;
- break;
- }
- // fall through
- case SCROLL_TO_MSG_ID:
- if (setContentScrollTo(msg.arg1, msg.arg2)) {
- // if we can't scroll to the exact position due to pin,
- // send a message to WebCore to re-scroll when we get a
- // new picture
- mUserScroll = false;
- mWebViewCore.sendMessage(EventHub.SYNC_SCROLL,
- msg.arg1, msg.arg2);
- }
- break;
- case SPAWN_SCROLL_TO_MSG_ID:
- spawnContentScrollTo(msg.arg1, msg.arg2);
- break;
- case NEW_PICTURE_MSG_ID:
- // called for new content
- final WebViewCore.DrawData draw =
- (WebViewCore.DrawData) msg.obj;
- final Point viewSize = draw.mViewPoint;
- if (mZoomScale > 0) {
- // use the same logic in sendViewSizeZoom() to make sure
- // the mZoomScale has matched the viewSize so that we
- // can clear mZoomScale
- if (Math.round(getViewWidth() / mZoomScale) == viewSize.x) {
- mZoomScale = 0;
- mWebViewCore.sendMessage(EventHub.SET_SNAP_ANCHOR,
- 0, 0);
- }
- }
- mMinContentWidth = msg.arg1;
- if (mMinContentWidth > MAX_FLOAT_CONTENT_WIDTH) {
- mMinZoomScale = (float) getViewWidth()
- / draw.mWidthHeight.x;
- }
- // We update the layout (i.e. request a layout from the
- // view system) if the last view size that we sent to
- // WebCore matches the view size of the picture we just
- // received in the fixed dimension.
- final boolean updateLayout = viewSize.x == mLastWidthSent
- && viewSize.y == mLastHeightSent;
- recordNewContentSize(draw.mWidthHeight.x,
- draw.mWidthHeight.y, updateLayout);
- if (LOGV_ENABLED) {
- Rect b = draw.mInvalRegion.getBounds();
- Log.v(LOGTAG, "NEW_PICTURE_MSG_ID {" +
- b.left+","+b.top+","+b.right+","+b.bottom+"}");
- }
- invalidate(contentToView(draw.mInvalRegion.getBounds()));
- if (mPictureListener != null) {
- mPictureListener.onNewPicture(WebView.this, capturePicture());
- }
- break;
- case WEBCORE_INITIALIZED_MSG_ID:
- // nativeCreate sets mNativeClass to a non-zero value
- nativeCreate(msg.arg1);
- break;
- case UPDATE_TEXTFIELD_TEXT_MSG_ID:
- // Make sure that the textfield is currently focused
- // and representing the same node as the pointer.
- if (inEditingMode() &&
- mTextEntry.isSameTextField(msg.arg1)) {
- if (msg.getData().getBoolean("password")) {
- Spannable text = (Spannable) mTextEntry.getText();
- int start = Selection.getSelectionStart(text);
- int end = Selection.getSelectionEnd(text);
- mTextEntry.setInPassword(true);
- // Restore the selection, which may have been
- // ruined by setInPassword.
- Spannable pword = (Spannable) mTextEntry.getText();
- Selection.setSelection(pword, start, end);
- // If the text entry has created more events, ignore
- // this one.
- } else if (msg.arg2 == mTextGeneration) {
- mTextEntry.setTextAndKeepSelection(
- (String) msg.obj);
- }
- }
- break;
- case DID_FIRST_LAYOUT_MSG_ID:
- if (mNativeClass == 0) {
- break;
- }
-// Do not reset the focus or clear the text; the user may have already
-// navigated or entered text at this point. The focus should have gotten
-// reset, if need be, when the focus cache was built. Similarly, the text
-// view should already be torn down and rebuilt if needed.
-// nativeResetFocus();
-// clearTextEntry();
- HashMap scaleLimit = (HashMap) msg.obj;
- int minScale = (Integer) scaleLimit.get("minScale");
- if (minScale == 0) {
- mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
- } else {
- mMinZoomScale = (float) (minScale / 100.0);
- }
- int maxScale = (Integer) scaleLimit.get("maxScale");
- if (maxScale == 0) {
- mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
- } else {
- mMaxZoomScale = (float) (maxScale / 100.0);
- }
- // If history Picture is drawn, don't update zoomWidth
- if (mDrawHistory) {
- break;
- }
- int width = getViewWidth();
- if (width == 0) {
- break;
- }
- int initialScale = msg.arg1;
- int viewportWidth = msg.arg2;
- // by default starting a new page with 100% zoom scale.
- float scale = 1.0f;
- if (mInitialScale > 0) {
- scale = mInitialScale / 100.0f;
- } else {
- if (mWebViewCore.getSettings().getUseWideViewPort()) {
- // force viewSizeChanged by setting mLastWidthSent
- // to 0
- mLastWidthSent = 0;
- }
- if (initialScale == 0) {
- // if viewportWidth is defined and it is smaller
- // than the view width, zoom in to fill the view
- if (viewportWidth > 0 && viewportWidth < width) {
- scale = (float) width / viewportWidth;
- }
- } else {
- scale = initialScale / 100.0f;
- }
- }
- setNewZoomScale(scale, false);
- break;
- case MARK_NODE_INVALID_ID:
- nativeMarkNodeInvalid(msg.arg1);
- break;
- case NOTIFY_FOCUS_SET_MSG_ID:
- if (mNativeClass != 0) {
- nativeNotifyFocusSet(inEditingMode());
- }
- break;
- case UPDATE_TEXT_ENTRY_MSG_ID:
- // this is sent after finishing resize in WebViewCore. Make
- // sure the text edit box is still on the screen.
- boolean alreadyThere = inEditingMode();
- if (alreadyThere && nativeUpdateFocusNode()) {
- FocusNode node = mFocusNode;
- if (node.mIsTextField || node.mIsTextArea) {
- mTextEntry.bringIntoView();
- }
- }
- updateTextEntry();
- break;
- case RECOMPUTE_FOCUS_MSG_ID:
- if (mNativeClass != 0) {
- nativeRecomputeFocus();
- }
- break;
- case INVAL_RECT_MSG_ID: {
- Rect r = (Rect)msg.obj;
- if (r == null) {
- invalidate();
- } else {
- // we need to scale r from content into view coords,
- // which viewInvalidate() does for us
- viewInvalidate(r.left, r.top, r.right, r.bottom);
- }
- break;
- }
- case UPDATE_TEXT_ENTRY_ADAPTER:
- HashMap data = (HashMap) msg.obj;
- if (mTextEntry.isSameTextField(msg.arg1)) {
- AutoCompleteAdapter adapter =
- (AutoCompleteAdapter) data.get("adapter");
- mTextEntry.setAdapterCustom(adapter);
- }
- break;
- case UPDATE_CLIPBOARD:
- String str = (String) msg.obj;
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "UPDATE_CLIPBOARD " + str);
- }
- try {
- IClipboard clip = IClipboard.Stub.asInterface(
- ServiceManager.getService("clipboard"));
- clip.setClipboardText(str);
- } catch (android.os.RemoteException e) {
- Log.e(LOGTAG, "Clipboard failed", e);
- }
- break;
- case RESUME_WEBCORE_UPDATE:
- WebViewCore.resumeUpdate(mWebViewCore);
- break;
-
- case LONG_PRESS_ENTER:
- // as this is shared by keydown and trackballdown, reset all
- // the states
- mGotEnterDown = false;
- mTrackballDown = false;
- // LONG_PRESS_ENTER is sent as a delayed message. If we
- // switch to windows overview, the WebView will be
- // temporarily removed from the view system. In that case,
- // do nothing.
- if (getParent() != null) {
- performLongClick();
- }
- break;
-
- case WEBCORE_NEED_TOUCH_EVENTS:
- mForwardTouchEvents = (msg.arg1 != 0);
- break;
-
- case PREVENT_TOUCH_ID:
- if (msg.arg1 == MotionEvent.ACTION_DOWN) {
- mPreventDrag = msg.arg2 == 1;
- if (mPreventDrag) {
- mTouchMode = TOUCH_DONE_MODE;
- }
- }
- break;
-
- case DISMISS_ZOOM_RING_TUTORIAL:
- mZoomRingController.finishZoomTutorial();
- break;
-
- default:
- super.handleMessage(msg);
- break;
- }
- }
- }
-
- // Class used to use a dropdown for a <select> element
- private class InvokeListBox implements Runnable {
- // Strings for the labels in the listbox.
- private String[] mArray;
- // Array representing whether each item is enabled.
- private boolean[] mEnableArray;
- // Whether the listbox allows multiple selection.
- private boolean mMultiple;
- // Passed in to a list with multiple selection to tell
- // which items are selected.
- private int[] mSelectedArray;
- // Passed in to a list with single selection to tell
- // where the initial selection is.
- private int mSelection;
-
- private Container[] mContainers;
-
- // Need these to provide stable ids to my ArrayAdapter,
- // which normally does not have stable ids. (Bug 1250098)
- private class Container extends Object {
- String mString;
- boolean mEnabled;
- int mId;
-
- public String toString() {
- return mString;
- }
- }
-
- /**
- * Subclass ArrayAdapter so we can disable OptionGroupLabels,
- * and allow filtering.
- */
- private class MyArrayListAdapter extends ArrayAdapter<Container> {
- public MyArrayListAdapter(Context context, Container[] objects, boolean multiple) {
- super(context,
- multiple ? com.android.internal.R.layout.select_dialog_multichoice :
- com.android.internal.R.layout.select_dialog_singlechoice,
- objects);
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- private Container item(int position) {
- if (position < 0 || position >= getCount()) {
- return null;
- }
- return (Container) getItem(position);
- }
-
- @Override
- public long getItemId(int position) {
- Container item = item(position);
- if (item == null) {
- return -1;
- }
- return item.mId;
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return false;
- }
-
- @Override
- public boolean isEnabled(int position) {
- Container item = item(position);
- if (item == null) {
- return false;
- }
- return item.mEnabled;
- }
- }
-
- private InvokeListBox(String[] array,
- boolean[] enabled, int[] selected) {
- mMultiple = true;
- mSelectedArray = selected;
-
- int length = array.length;
- mContainers = new Container[length];
- for (int i = 0; i < length; i++) {
- mContainers[i] = new Container();
- mContainers[i].mString = array[i];
- mContainers[i].mEnabled = enabled[i];
- mContainers[i].mId = i;
- }
- }
-
- private InvokeListBox(String[] array, boolean[] enabled, int
- selection) {
- mSelection = selection;
- mMultiple = false;
-
- int length = array.length;
- mContainers = new Container[length];
- for (int i = 0; i < length; i++) {
- mContainers[i] = new Container();
- mContainers[i].mString = array[i];
- mContainers[i].mEnabled = enabled[i];
- mContainers[i].mId = i;
- }
- }
-
- public void run() {
- final ListView listView = (ListView) LayoutInflater.from(mContext)
- .inflate(com.android.internal.R.layout.select_dialog, null);
- final MyArrayListAdapter adapter = new
- MyArrayListAdapter(mContext, mContainers, mMultiple);
- AlertDialog.Builder b = new AlertDialog.Builder(mContext)
- .setView(listView).setCancelable(true)
- .setInverseBackgroundForced(true);
-
- if (mMultiple) {
- b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- mWebViewCore.sendMessage(
- EventHub.LISTBOX_CHOICES,
- adapter.getCount(), 0,
- listView.getCheckedItemPositions());
- }});
- b.setNegativeButton(android.R.string.cancel, null);
- }
- final AlertDialog dialog = b.create();
- listView.setAdapter(adapter);
- listView.setFocusableInTouchMode(true);
- // There is a bug (1250103) where the checks in a ListView with
- // multiple items selected are associated with the positions, not
- // the ids, so the items do not properly retain their checks when
- // filtered. Do not allow filtering on multiple lists until
- // that bug is fixed.
-
- // Disable filter altogether
- // listView.setTextFilterEnabled(!mMultiple);
- if (mMultiple) {
- listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
- int length = mSelectedArray.length;
- for (int i = 0; i < length; i++) {
- listView.setItemChecked(mSelectedArray[i], true);
- }
- } else {
- listView.setOnItemClickListener(new OnItemClickListener() {
- public void onItemClick(AdapterView parent, View v,
- int position, long id) {
- mWebViewCore.sendMessage(
- EventHub.SINGLE_LISTBOX_CHOICE, (int)id, 0);
- dialog.dismiss();
- }
- });
- if (mSelection != -1) {
- listView.setSelection(mSelection);
- listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
- listView.setItemChecked(mSelection, true);
- }
- }
- dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- mWebViewCore.sendMessage(
- EventHub.SINGLE_LISTBOX_CHOICE, -2, 0);
- }
- });
- dialog.show();
- }
- }
-
- /*
- * Request a dropdown menu for a listbox with multiple selection.
- *
- * @param array Labels for the listbox.
- * @param enabledArray Which positions are enabled.
- * @param selectedArray Which positions are initally selected.
- */
- void requestListBox(String[] array, boolean[]enabledArray, int[]
- selectedArray) {
- mPrivateHandler.post(
- new InvokeListBox(array, enabledArray, selectedArray));
- }
-
- /*
- * Request a dropdown menu for a listbox with single selection or a single
- * <select> element.
- *
- * @param array Labels for the listbox.
- * @param enabledArray Which positions are enabled.
- * @param selection Which position is initally selected.
- */
- void requestListBox(String[] array, boolean[]enabledArray, int selection) {
- mPrivateHandler.post(
- new InvokeListBox(array, enabledArray, selection));
- }
-
- // called by JNI
- private void sendFinalFocus(int frame, int node, int x, int y) {
- WebViewCore.FocusData focusData = new WebViewCore.FocusData();
- focusData.mFrame = frame;
- focusData.mNode = node;
- focusData.mX = x;
- focusData.mY = y;
- mWebViewCore.sendMessage(EventHub.SET_FINAL_FOCUS,
- EventHub.NO_FOCUS_CHANGE_BLOCK, 0, focusData);
- }
-
- // called by JNI
- private void setFocusData(int moveGeneration, int buildGeneration,
- int frame, int node, int x, int y, boolean ignoreNullFocus) {
- mFocusData.mMoveGeneration = moveGeneration;
- mFocusData.mBuildGeneration = buildGeneration;
- mFocusData.mFrame = frame;
- mFocusData.mNode = node;
- mFocusData.mX = x;
- mFocusData.mY = y;
- mFocusData.mIgnoreNullFocus = ignoreNullFocus;
- }
-
- // called by JNI
- private void sendKitFocus() {
- WebViewCore.FocusData focusData = new WebViewCore.FocusData(mFocusData);
- mWebViewCore.sendMessage(EventHub.SET_KIT_FOCUS, focusData);
- }
-
- // called by JNI
- private void sendMotionUp(int touchGeneration, int buildGeneration,
- int frame, int node, int x, int y, int size, boolean isClick,
- boolean retry) {
- WebViewCore.TouchUpData touchUpData = new WebViewCore.TouchUpData();
- touchUpData.mMoveGeneration = touchGeneration;
- touchUpData.mBuildGeneration = buildGeneration;
- touchUpData.mSize = size;
- touchUpData.mIsClick = isClick;
- touchUpData.mRetry = retry;
- mFocusData.mFrame = touchUpData.mFrame = frame;
- mFocusData.mNode = touchUpData.mNode = node;
- mFocusData.mX = touchUpData.mX = x;
- mFocusData.mY = touchUpData.mY = y;
- mWebViewCore.sendMessage(EventHub.TOUCH_UP, touchUpData);
- }
-
-
- private int getScaledMaxXScroll() {
- int width;
- if (mHeightCanMeasure == false) {
- width = getViewWidth() / 4;
- } else {
- Rect visRect = new Rect();
- calcOurVisibleRect(visRect);
- width = visRect.width() / 2;
- }
- // FIXME the divisor should be retrieved from somewhere
- return viewToContent(width);
- }
-
- private int getScaledMaxYScroll() {
- int height;
- if (mHeightCanMeasure == false) {
- height = getViewHeight() / 4;
- } else {
- Rect visRect = new Rect();
- calcOurVisibleRect(visRect);
- height = visRect.height() / 2;
- }
- // FIXME the divisor should be retrieved from somewhere
- // the closest thing today is hard-coded into ScrollView.java
- // (from ScrollView.java, line 363) int maxJump = height/2;
- return viewToContent(height);
- }
-
- /**
- * Called by JNI to invalidate view
- */
- private void viewInvalidate() {
- invalidate();
- }
-
- // return true if the key was handled
- private boolean navHandledKey(int keyCode, int count, boolean noScroll
- , long time) {
- if (mNativeClass == 0) {
- return false;
- }
- mLastFocusTime = time;
- mLastFocusBounds = nativeGetFocusRingBounds();
- boolean keyHandled = nativeMoveFocus(keyCode, count, noScroll) == false;
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "navHandledKey mLastFocusBounds=" + mLastFocusBounds
- + " mLastFocusTime=" + mLastFocusTime
- + " handled=" + keyHandled);
- }
- if (keyHandled == false || mHeightCanMeasure == false) {
- return keyHandled;
- }
- Rect contentFocus = nativeGetFocusRingBounds();
- if (contentFocus.isEmpty()) return keyHandled;
- Rect viewFocus = contentToView(contentFocus);
- Rect visRect = new Rect();
- calcOurVisibleRect(visRect);
- Rect outset = new Rect(visRect);
- int maxXScroll = visRect.width() / 2;
- int maxYScroll = visRect.height() / 2;
- outset.inset(-maxXScroll, -maxYScroll);
- if (Rect.intersects(outset, viewFocus) == false) {
- return keyHandled;
- }
- // FIXME: Necessary because ScrollView/ListView do not scroll left/right
- int maxH = Math.min(viewFocus.right - visRect.right, maxXScroll);
- if (maxH > 0) {
- pinScrollBy(maxH, 0, true, 0);
- } else {
- maxH = Math.max(viewFocus.left - visRect.left, -maxXScroll);
- if (maxH < 0) {
- pinScrollBy(maxH, 0, true, 0);
- }
- }
- if (mLastFocusBounds.isEmpty()) return keyHandled;
- if (mLastFocusBounds.equals(contentFocus)) return keyHandled;
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "navHandledKey contentFocus=" + contentFocus);
- }
- requestRectangleOnScreen(viewFocus);
- mUserScroll = true;
- return keyHandled;
- }
-
- /**
- * Set the background color. It's white by default. Pass
- * zero to make the view transparent.
- * @param color the ARGB color described by Color.java
- */
- public void setBackgroundColor(int color) {
- mBackgroundColor = color;
- mWebViewCore.sendMessage(EventHub.SET_BACKGROUND_COLOR, color);
- }
-
- public void debugDump() {
- nativeDebugDump();
- mWebViewCore.sendMessage(EventHub.DUMP_NAVTREE);
- }
-
- /**
- * Update our cache with updatedText.
- * @param updatedText The new text to put in our cache.
- */
- /* package */ void updateCachedTextfield(String updatedText) {
- // Also place our generation number so that when we look at the cache
- // we recognize that it is up to date.
- nativeUpdateCachedTextfield(updatedText, mTextGeneration);
- }
-
- // Never call this version except by updateCachedTextfield(String) -
- // we always want to pass in our generation number.
- private native void nativeUpdateCachedTextfield(String updatedText,
- int generation);
- private native void nativeClearFocus(int x, int y);
- private native void nativeCreate(int ptr);
- private native void nativeDebugDump();
- private native void nativeDestroy();
- private native void nativeDrawFocusRing(Canvas content);
- private native void nativeDrawSelection(Canvas content
- , int x, int y, boolean extendSelection);
- private native void nativeDrawSelectionRegion(Canvas content);
- private native boolean nativeUpdateFocusNode();
- private native Rect nativeGetFocusRingBounds();
- private native Rect nativeGetNavBounds();
- private native void nativeInstrumentReport();
- private native void nativeMarkNodeInvalid(int node);
- // return true if the page has been scrolled
- private native boolean nativeMotionUp(int x, int y, int slop, boolean isClick);
- // returns false if it handled the key
- private native boolean nativeMoveFocus(int keyCode, int count,
- boolean noScroll);
- private native void nativeNotifyFocusSet(boolean inEditingMode);
- private native void nativeRecomputeFocus();
- // Like many other of our native methods, you must make sure that
- // mNativeClass is not null before calling this method.
- private native void nativeRecordButtons(boolean focused,
- boolean pressed, boolean invalidate);
- private native void nativeResetFocus();
- private native void nativeResetNavClipBounds();
- private native void nativeSelectBestAt(Rect rect);
- private native void nativeSetFindIsDown();
- private native void nativeSetFollowedLink(boolean followed);
- private native void nativeSetHeightCanMeasure(boolean measure);
- private native void nativeSetNavBounds(Rect rect);
- private native void nativeSetNavClipBounds(Rect rect);
- private native String nativeImageURI(int x, int y);
- /**
- * Returns true if the native focus nodes says it wants to handle key events
- * (ala plugins). This can only be called if mNativeClass is non-zero!
- */
- private native boolean nativeFocusNodeWantsKeyEvents();
- private native void nativeMoveSelection(int x, int y
- , boolean extendSelection);
- private native Region nativeGetSelection();
-
- private native void nativeDumpDisplayTree(String urlOrNull);
-}
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
deleted file mode 100644
index a185779..0000000
--- a/core/java/android/webkit/WebViewClient.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.graphics.Bitmap;
-import android.net.http.SslError;
-import android.os.Message;
-import android.view.KeyEvent;
-
-public class WebViewClient {
-
- /**
- * Give the host application a chance to take over the control when a new
- * url is about to be loaded in the current WebView. If WebViewClient is not
- * provided, by default WebView will ask Activity Manager to choose the
- * proper handler for the url. If WebViewClient is provided, return true
- * means the host application handles the url, while return false means the
- * current WebView handles the url.
- *
- * @param view The WebView that is initiating the callback.
- * @param url The url to be loaded.
- * @return True if the host application wants to leave the current WebView
- * and handle the url itself, otherwise return false.
- */
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- return false;
- }
-
- /**
- * Notify the host application that a page has started loading. This method
- * is called once for each main frame load so a page with iframes or
- * framesets will call onPageStarted one time for the main frame. This also
- * means that onPageStarted will not be called when the contents of an
- * embedded frame changes, i.e. clicking a link whose target is an iframe.
- *
- * @param view The WebView that is initiating the callback.
- * @param url The url to be loaded.
- * @param favicon The favicon for this page if it already exists in the
- * database.
- */
- public void onPageStarted(WebView view, String url, Bitmap favicon) {
- }
-
- /**
- * Notify the host application that a page has finished loading. This method
- * is called only for main frame. When onPageFinished() is called, the
- * rendering picture may not be updated yet. To get the notification for the
- * new Picture, use {@link WebView.PictureListener#onNewPicture}.
- *
- * @param view The WebView that is initiating the callback.
- * @param url The url of the page.
- */
- public void onPageFinished(WebView view, String url) {
- }
-
- /**
- * Notify the host application that the WebView will load the resource
- * specified by the given url.
- *
- * @param view The WebView that is initiating the callback.
- * @param url The url of the resource the WebView will load.
- */
- public void onLoadResource(WebView view, String url) {
- }
-
- /**
- * Notify the host application that there have been an excessive number of
- * HTTP redirects. As the host application if it would like to continue
- * trying to load the resource. The default behavior is to send the cancel
- * message.
- *
- * @param view The WebView that is initiating the callback.
- * @param cancelMsg The message to send if the host wants to cancel
- * @param continueMsg The message to send if the host wants to continue
- */
- public void onTooManyRedirects(WebView view, Message cancelMsg,
- Message continueMsg) {
- cancelMsg.sendToTarget();
- }
-
- /**
- * Report an error to an activity. These errors come up from WebCore, and
- * are network errors.
- *
- * @param view The WebView that is initiating the callback.
- * @param errorCode The HTTP error code.
- * @param description A String description.
- * @param failingUrl The url that failed.
- */
- public void onReceivedError(WebView view, int errorCode,
- String description, String failingUrl) {
- }
-
- /**
- * As the host application if the browser should resend data as the
- * requested page was a result of a POST. The default is to not resend the
- * data.
- *
- * @param view The WebView that is initiating the callback.
- * @param dontResend The message to send if the browser should not resend
- * @param resend The message to send if the browser should resend data
- */
- public void onFormResubmission(WebView view, Message dontResend,
- Message resend) {
- dontResend.sendToTarget();
- }
-
- /**
- * Notify the host application to update its visited links database.
- *
- * @param view The WebView that is initiating the callback.
- * @param url The url being visited.
- * @param isReload True if this url is being reloaded.
- */
- public void doUpdateVisitedHistory(WebView view, String url,
- boolean isReload) {
- }
-
- /**
- * Notify the host application to handle a ssl certificate error request
- * (display the error to the user and ask whether to proceed or not). The
- * host application has to call either handler.cancel() or handler.proceed()
- * as the connection is suspended and waiting for the response. The default
- * behavior is to cancel the load.
- *
- * @param view The WebView that is initiating the callback.
- * @param handler An SslErrorHandler object that will handle the user's
- * response.
- * @param error The SSL error object.
- * @hide - hide this because it contains a parameter of type SslError,
- * which is located in a hidden package.
- */
- public void onReceivedSslError(WebView view, SslErrorHandler handler,
- SslError error) {
- handler.cancel();
- }
-
- /**
- * Notify the host application to handle an authentication request. The
- * default behavior is to cancel the request.
- *
- * @param view The WebView that is initiating the callback.
- * @param handler The HttpAuthHandler that will handle the user's response.
- * @param host The host requiring authentication.
- * @param realm A description to help store user credentials for future
- * visits.
- */
- public void onReceivedHttpAuthRequest(WebView view,
- HttpAuthHandler handler, String host, String realm) {
- handler.cancel();
- }
-
- /**
- * Give the host application a chance to handle the key event synchronously.
- * e.g. menu shortcut key events need to be filtered this way. If return
- * true, WebView will not handle the key event. If return false, WebView
- * will always handle the key event, so none of the super in the view chain
- * will see the key event. The default behavior returns false.
- *
- * @param view The WebView that is initiating the callback.
- * @param event The key event.
- * @return True if the host application wants to handle the key event
- * itself, otherwise return false
- */
- public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
- return false;
- }
-
- /**
- * Notify the host application that a key was not handled by the WebView.
- * Except system keys, WebView always consumes the keys in the normal flow
- * or if shouldOverrideKeyEvent returns true. This is called asynchronously
- * from where the key is dispatched. It gives the host application an chance
- * to handle the unhandled key events.
- *
- * @param view The WebView that is initiating the callback.
- * @param event The key event.
- */
- public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
- }
-
- /**
- * Notify the host application that the scale applied to the WebView has
- * changed.
- *
- * @param view he WebView that is initiating the callback.
- * @param oldScale The old scale factor
- * @param newScale The new scale factor
- */
- public void onScaleChanged(WebView view, float oldScale, float newScale) {
- }
-}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
deleted file mode 100644
index a7261c5..0000000
--- a/core/java/android/webkit/WebViewCore.java
+++ /dev/null
@@ -1,1672 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.DrawFilter;
-import android.graphics.Paint;
-import android.graphics.PaintFlagsDrawFilter;
-import android.graphics.Picture;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Process;
-import android.util.Config;
-import android.util.Log;
-import android.util.SparseBooleanArray;
-import android.view.KeyEvent;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import junit.framework.Assert;
-
-final class WebViewCore {
-
- private static final String LOGTAG = "webcore";
- static final boolean DEBUG = false;
- static final boolean LOGV_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
-
- static {
- // Load libwebcore during static initialization. This happens in the
- // zygote process so it will be shared read-only across all app
- // processes.
- System.loadLibrary("webcore");
- }
-
- /*
- * WebViewCore always executes in the same thread as the native webkit.
- */
-
- // The WebView that corresponds to this WebViewCore.
- private WebView mWebView;
- // Proxy for handling callbacks from native code
- private final CallbackProxy mCallbackProxy;
- // Settings object for maintaining all settings
- private final WebSettings mSettings;
- // Context for initializing the BrowserFrame with the proper assets.
- private final Context mContext;
- // The pointer to a native view object.
- private int mNativeClass;
- // The BrowserFrame is an interface to the native Frame component.
- private BrowserFrame mBrowserFrame;
-
- /*
- * range is from 200 to 10,000. 0 is a special value means device-width. -1
- * means undefined.
- */
- private int mViewportWidth = -1;
-
- /*
- * range is from 200 to 10,000. 0 is a special value means device-height. -1
- * means undefined.
- */
- private int mViewportHeight = -1;
-
- /*
- * scale in percent, range is from 1 to 1000. 0 means undefined.
- */
- private int mViewportInitialScale = 0;
-
- /*
- * scale in percent, range is from 1 to 1000. 0 means undefined.
- */
- private int mViewportMinimumScale = 0;
-
- /*
- * scale in percent, range is from 1 to 1000. 0 means undefined.
- */
- private int mViewportMaximumScale = 0;
-
- private boolean mViewportUserScalable = true;
-
- private int mRestoredScale = 100;
- private int mRestoredX = 0;
- private int mRestoredY = 0;
-
- private int mWebkitScrollX = 0;
- private int mWebkitScrollY = 0;
-
- // The thread name used to identify the WebCore thread and for use in
- // debugging other classes that require operation within the WebCore thread.
- /* package */ static final String THREAD_NAME = "WebViewCoreThread";
-
- public WebViewCore(Context context, WebView w, CallbackProxy proxy) {
- // No need to assign this in the WebCore thread.
- mCallbackProxy = proxy;
- mWebView = w;
- // This context object is used to initialize the WebViewCore during
- // subwindow creation.
- mContext = context;
-
- // We need to wait for the initial thread creation before sending
- // a message to the WebCore thread.
- // XXX: This is the only time the UI thread will wait for the WebCore
- // thread!
- synchronized (WebViewCore.class) {
- if (sWebCoreHandler == null) {
- // Create a global thread and start it.
- Thread t = new Thread(new WebCoreThread());
- t.setName(THREAD_NAME);
- t.start();
- try {
- WebViewCore.class.wait();
- } catch (InterruptedException e) {
- Log.e(LOGTAG, "Caught exception while waiting for thread " +
- "creation.");
- Log.e(LOGTAG, Log.getStackTraceString(e));
- }
- }
- }
- // Create an EventHub to handle messages before and after the thread is
- // ready.
- mEventHub = new EventHub();
- // Create a WebSettings object for maintaining all settings
- mSettings = new WebSettings(mContext);
- // The WebIconDatabase needs to be initialized within the UI thread so
- // just request the instance here.
- WebIconDatabase.getInstance();
- // Send a message to initialize the WebViewCore.
- Message init = sWebCoreHandler.obtainMessage(
- WebCoreThread.INITIALIZE, this);
- sWebCoreHandler.sendMessage(init);
- }
-
- /* Initialize private data within the WebCore thread.
- */
- private void initialize() {
- /* Initialize our private BrowserFrame class to handle all
- * frame-related functions. We need to create a new view which
- * in turn creates a C level FrameView and attaches it to the frame.
- */
- mBrowserFrame = new BrowserFrame(mContext, this, mCallbackProxy,
- mSettings);
- // Sync the native settings and also create the WebCore thread handler.
- mSettings.syncSettingsAndCreateHandler(mBrowserFrame);
- // Create the handler and transfer messages for the IconDatabase
- WebIconDatabase.getInstance().createHandler();
- // The transferMessages call will transfer all pending messages to the
- // WebCore thread handler.
- mEventHub.transferMessages();
-
- // Send a message back to WebView to tell it that we have set up the
- // WebCore thread.
- if (mWebView != null) {
- Message.obtain(mWebView.mPrivateHandler,
- WebView.WEBCORE_INITIALIZED_MSG_ID,
- mNativeClass, 0).sendToTarget();
- }
-
- }
-
- /* Handle the initialization of WebViewCore during subwindow creation. This
- * method is called from the WebCore thread but it is called before the
- * INITIALIZE message can be handled.
- */
- /* package */ void initializeSubwindow() {
- // Go ahead and initialize the core components.
- initialize();
- // Remove the INITIALIZE method so we don't try to initialize twice.
- sWebCoreHandler.removeMessages(WebCoreThread.INITIALIZE, this);
- }
-
- /* Get the BrowserFrame component. This is used for subwindow creation and
- * is called only from BrowserFrame in the WebCore thread. */
- /* package */ BrowserFrame getBrowserFrame() {
- return mBrowserFrame;
- }
-
- //-------------------------------------------------------------------------
- // Common methods
- //-------------------------------------------------------------------------
-
- /**
- * Causes all timers to pause. This applies to all WebViews in the current
- * app process.
- */
- public static void pauseTimers() {
- if (BrowserFrame.sJavaBridge == null) {
- throw new IllegalStateException(
- "No WebView has been created in this process!");
- }
- BrowserFrame.sJavaBridge.pause();
- }
-
- /**
- * Resume all timers. This applies to all WebViews in the current process.
- */
- public static void resumeTimers() {
- if (BrowserFrame.sJavaBridge == null) {
- throw new IllegalStateException(
- "No WebView has been created in this process!");
- }
- BrowserFrame.sJavaBridge.resume();
- }
-
- public WebSettings getSettings() {
- return mSettings;
- }
-
- /**
- * Invoke a javascript alert.
- * @param message The message displayed in the alert.
- */
- protected void jsAlert(String url, String message) {
- mCallbackProxy.onJsAlert(url, message);
- }
-
- /**
- * Invoke a javascript confirm dialog.
- * @param message The message displayed in the dialog.
- * @return True if the user confirmed or false if the user cancelled.
- */
- protected boolean jsConfirm(String url, String message) {
- return mCallbackProxy.onJsConfirm(url, message);
- }
-
- /**
- * Invoke a javascript prompt dialog.
- * @param message The message to be displayed in the dialog.
- * @param defaultValue The default value in the prompt input.
- * @return The input from the user or null to indicate the user cancelled
- * the dialog.
- */
- protected String jsPrompt(String url, String message, String defaultValue) {
- return mCallbackProxy.onJsPrompt(url, message, defaultValue);
- }
-
- /**
- * Invoke a javascript before unload dialog.
- * @param url The url that is requesting the dialog.
- * @param message The message displayed in the dialog.
- * @return True if the user confirmed or false if the user cancelled. False
- * will cancel the navigation.
- */
- protected boolean jsUnload(String url, String message) {
- return mCallbackProxy.onJsBeforeUnload(url, message);
- }
-
- //-------------------------------------------------------------------------
- // JNI methods
- //-------------------------------------------------------------------------
-
- static native String nativeFindAddress(String addr);
-
- /**
- * Rebuild the nav cache if the dom changed.
- */
- private native void nativeCheckNavCache();
-
- /**
- * Empty the picture set.
- */
- private native void nativeClearContent();
-
- /**
- * Create a flat picture from the set of pictures.
- */
- private native void nativeCopyContentToPicture(Picture picture);
-
- /**
- * Draw the picture set with a background color. Returns true
- * if some individual picture took too long to draw and can be
- * split into parts. Called from the UI thread.
- */
- private native boolean nativeDrawContent(Canvas canvas, int color);
-
- /**
- * Redraw a portion of the picture set. The Point wh returns the
- * width and height of the overall picture.
- */
- private native boolean nativeRecordContent(Region invalRegion, Point wh);
-
- /**
- * Splits slow parts of the picture set. Called from the webkit
- * thread after nativeDrawContent returns true.
- */
- private native void nativeSplitContent();
-
- private native boolean nativeKey(int keyCode, int unichar,
- int repeatCount, boolean isShift, boolean isAlt, boolean isDown);
-
- private native boolean nativeClick();
-
- private native void nativeSendListBoxChoices(boolean[] choices, int size);
-
- private native void nativeSendListBoxChoice(int choice);
-
- /* Tell webkit what its width and height are, for the purposes
- of layout/line-breaking. These coordinates are in document space,
- which is the same as View coords unless we have zoomed the document
- (see nativeSetZoom).
- screenWidth is used by layout to wrap column around. If viewport uses
- fixed size, screenWidth can be different from width with zooming.
- should this be called nativeSetViewPortSize?
- */
- private native void nativeSetSize(int width, int height, int screenWidth,
- float scale, int realScreenWidth, int screenHeight);
-
- private native int nativeGetContentMinPrefWidth();
-
- // Start: functions that deal with text editing
- private native void nativeReplaceTextfieldText(int frame, int node, int x,
- int y, int oldStart, int oldEnd, String replace, int newStart,
- int newEnd);
-
- private native void passToJs(int frame, int node, int x, int y, int gen,
- String currentText, int keyCode, int keyValue, boolean down,
- boolean cap, boolean fn, boolean sym);
-
- private native void nativeSaveDocumentState(int frame);
-
- private native void nativeSetFinalFocus(int framePtr, int nodePtr, int x,
- int y, boolean block);
-
- private native void nativeSetKitFocus(int moveGeneration,
- int buildGeneration, int framePtr, int nodePtr, int x, int y,
- boolean ignoreNullFocus);
-
- private native String nativeRetrieveHref(int framePtr, int nodePtr);
-
- private native void nativeTouchUp(int touchGeneration,
- int buildGeneration, int framePtr, int nodePtr, int x, int y,
- int size, boolean isClick, boolean retry);
-
- private native boolean nativeHandleTouchEvent(int action, int x, int y);
-
- private native void nativeUnblockFocus();
-
- private native void nativeUpdateFrameCache();
-
- private native void nativeSetSnapAnchor(int x, int y);
-
- private native void nativeSnapToAnchor();
-
- private native void nativeSetBackgroundColor(int color);
-
- private native void nativeDumpDomTree(boolean useFile);
-
- private native void nativeDumpRenderTree(boolean useFile);
-
- private native void nativeDumpNavTree();
-
- private native void nativeRefreshPlugins(boolean reloadOpenPages);
-
- /**
- * Delete text from start to end in the focused textfield. If there is no
- * focus, or if start == end, silently fail. If start and end are out of
- * order, swap them.
- * @param start Beginning of selection to delete.
- * @param end End of selection to delete.
- */
- private native void nativeDeleteSelection(int frame, int node, int x, int y,
- int start, int end);
-
- /**
- * Set the selection to (start, end) in the focused textfield. If start and
- * end are out of order, swap them.
- * @param start Beginning of selection.
- * @param end End of selection.
- */
- private native void nativeSetSelection(int frame, int node, int x, int y,
- int start, int end);
-
- private native String nativeGetSelection(Region sel);
-
- // Register a scheme to be treated as local scheme so that it can access
- // local asset files for resources
- private native void nativeRegisterURLSchemeAsLocal(String scheme);
-
- // EventHub for processing messages
- private final EventHub mEventHub;
- // WebCore thread handler
- private static Handler sWebCoreHandler;
- // Class for providing Handler creation inside the WebCore thread.
- private static class WebCoreThread implements Runnable {
- // Message id for initializing a new WebViewCore.
- private static final int INITIALIZE = 0;
- private static final int REDUCE_PRIORITY = 1;
- private static final int RESUME_PRIORITY = 2;
- private static final int CACHE_TICKER = 3;
- private static final int BLOCK_CACHE_TICKER = 4;
- private static final int RESUME_CACHE_TICKER = 5;
-
- private static final int CACHE_TICKER_INTERVAL = 60 * 1000; // 1 minute
-
- private static boolean mCacheTickersBlocked = true;
-
- public void run() {
- Looper.prepare();
- Assert.assertNull(sWebCoreHandler);
- synchronized (WebViewCore.class) {
- sWebCoreHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case INITIALIZE:
- WebViewCore core = (WebViewCore) msg.obj;
- core.initialize();
- break;
-
- case REDUCE_PRIORITY:
- // 3 is an adjustable number.
- Process.setThreadPriority(
- Process.THREAD_PRIORITY_DEFAULT + 3 *
- Process.THREAD_PRIORITY_LESS_FAVORABLE);
- break;
-
- case RESUME_PRIORITY:
- Process.setThreadPriority(
- Process.THREAD_PRIORITY_DEFAULT);
- break;
-
- case CACHE_TICKER:
- if (!mCacheTickersBlocked) {
- CacheManager.endCacheTransaction();
- CacheManager.startCacheTransaction();
- sendMessageDelayed(
- obtainMessage(CACHE_TICKER),
- CACHE_TICKER_INTERVAL);
- }
- break;
-
- case BLOCK_CACHE_TICKER:
- if (CacheManager.endCacheTransaction()) {
- mCacheTickersBlocked = true;
- }
- break;
-
- case RESUME_CACHE_TICKER:
- if (CacheManager.startCacheTransaction()) {
- mCacheTickersBlocked = false;
- }
- break;
- }
- }
- };
- WebViewCore.class.notify();
- }
- Looper.loop();
- }
- }
-
- static class FocusData {
- FocusData() {}
- FocusData(FocusData d) {
- mMoveGeneration = d.mMoveGeneration;
- mBuildGeneration = d.mBuildGeneration;
- mFrame = d.mFrame;
- mNode = d.mNode;
- mX = d.mX;
- mY = d.mY;
- mIgnoreNullFocus = d.mIgnoreNullFocus;
- }
- int mMoveGeneration;
- int mBuildGeneration;
- int mFrame;
- int mNode;
- int mX;
- int mY;
- boolean mIgnoreNullFocus;
- }
-
- static class TouchUpData {
- int mMoveGeneration;
- int mBuildGeneration;
- int mFrame;
- int mNode;
- int mX;
- int mY;
- int mSize;
- boolean mIsClick;
- boolean mRetry;
- }
-
- static class TouchEventData {
- int mAction; // MotionEvent.getAction()
- int mX;
- int mY;
- }
-
- static final String[] HandlerDebugString = {
- "LOAD_URL", // = 100;
- "STOP_LOADING", // = 101;
- "RELOAD", // = 102;
- "KEY_DOWN", // = 103;
- "KEY_UP", // = 104;
- "VIEW_SIZE_CHANGED", // = 105;
- "GO_BACK_FORWARD", // = 106;
- "SET_SCROLL_OFFSET", // = 107;
- "RESTORE_STATE", // = 108;
- "PAUSE_TIMERS", // = 109;
- "RESUME_TIMERS", // = 110;
- "CLEAR_CACHE", // = 111;
- "CLEAR_HISTORY", // = 112;
- "SET_SELECTION", // = 113;
- "REPLACE_TEXT", // = 114;
- "PASS_TO_JS", // = 115;
- "SET_GLOBAL_BOUNDS", // = 116;
- "UPDATE_CACHE_AND_TEXT_ENTRY", // = 117;
- "CLICK", // = 118;
- "119",
- "DOC_HAS_IMAGES", // = 120;
- "SET_SNAP_ANCHOR", // = 121;
- "DELETE_SELECTION", // = 122;
- "LISTBOX_CHOICES", // = 123;
- "SINGLE_LISTBOX_CHOICE", // = 124;
- "125",
- "SET_BACKGROUND_COLOR", // = 126;
- "UNBLOCK_FOCUS", // = 127;
- "SAVE_DOCUMENT_STATE", // = 128;
- "GET_SELECTION", // = 129;
- "WEBKIT_DRAW", // = 130;
- "SYNC_SCROLL", // = 131;
- "REFRESH_PLUGINS", // = 132;
- "SPLIT_PICTURE_SET", // = 133;
- "CLEAR_CONTENT", // = 134;
- "SET_FINAL_FOCUS", // = 135;
- "SET_KIT_FOCUS", // = 136;
- "REQUEST_FOCUS_HREF", // = 137;
- "ADD_JS_INTERFACE", // = 138;
- "LOAD_DATA", // = 139;
- "TOUCH_UP", // = 140;
- "TOUCH_EVENT", // = 141;
- };
-
- class EventHub {
- // Message Ids
- static final int LOAD_URL = 100;
- static final int STOP_LOADING = 101;
- static final int RELOAD = 102;
- static final int KEY_DOWN = 103;
- static final int KEY_UP = 104;
- static final int VIEW_SIZE_CHANGED = 105;
- static final int GO_BACK_FORWARD = 106;
- static final int SET_SCROLL_OFFSET = 107;
- static final int RESTORE_STATE = 108;
- static final int PAUSE_TIMERS = 109;
- static final int RESUME_TIMERS = 110;
- static final int CLEAR_CACHE = 111;
- static final int CLEAR_HISTORY = 112;
- static final int SET_SELECTION = 113;
- static final int REPLACE_TEXT = 114;
- static final int PASS_TO_JS = 115;
- static final int SET_GLOBAL_BOUNDS = 116;
- static final int UPDATE_CACHE_AND_TEXT_ENTRY = 117;
- static final int CLICK = 118;
- static final int DOC_HAS_IMAGES = 120;
- static final int SET_SNAP_ANCHOR = 121;
- static final int DELETE_SELECTION = 122;
- static final int LISTBOX_CHOICES = 123;
- static final int SINGLE_LISTBOX_CHOICE = 124;
- static final int SET_BACKGROUND_COLOR = 126;
- static final int UNBLOCK_FOCUS = 127;
- static final int SAVE_DOCUMENT_STATE = 128;
- static final int GET_SELECTION = 129;
- static final int WEBKIT_DRAW = 130;
- static final int SYNC_SCROLL = 131;
- static final int REFRESH_PLUGINS = 132;
- static final int SPLIT_PICTURE_SET = 133;
- static final int CLEAR_CONTENT = 134;
-
- // UI nav messages
- static final int SET_FINAL_FOCUS = 135;
- static final int SET_KIT_FOCUS = 136;
- static final int REQUEST_FOCUS_HREF = 137;
- static final int ADD_JS_INTERFACE = 138;
- static final int LOAD_DATA = 139;
-
- // motion
- static final int TOUCH_UP = 140;
- // message used to pass UI touch events to WebCore
- static final int TOUCH_EVENT = 141;
-
- // Network-based messaging
- static final int CLEAR_SSL_PREF_TABLE = 150;
-
- // Test harness messages
- static final int REQUEST_EXT_REPRESENTATION = 160;
- static final int REQUEST_DOC_AS_TEXT = 161;
-
- // debugging
- static final int DUMP_DOMTREE = 170;
- static final int DUMP_RENDERTREE = 171;
- static final int DUMP_NAVTREE = 172;
-
- // private message ids
- private static final int DESTROY = 200;
-
- // flag values passed to message SET_FINAL_FOCUS
- static final int NO_FOCUS_CHANGE_BLOCK = 0;
- static final int BLOCK_FOCUS_CHANGE_UNTIL_KEY_UP = 1;
-
- // Private handler for WebCore messages.
- private Handler mHandler;
- // Message queue for containing messages before the WebCore thread is
- // ready.
- private ArrayList<Message> mMessages = new ArrayList<Message>();
- // Flag for blocking messages. This is used during DESTROY to avoid
- // posting more messages to the EventHub or to WebView's event handler.
- private boolean mBlockMessages;
-
- private int mTid;
- private int mSavedPriority;
-
- /**
- * Prevent other classes from creating an EventHub.
- */
- private EventHub() {}
-
- /**
- * Transfer all messages to the newly created webcore thread handler.
- */
- private void transferMessages() {
- mTid = Process.myTid();
- mSavedPriority = Process.getThreadPriority(mTid);
-
- mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, msg.what < LOAD_URL || msg.what
- > TOUCH_EVENT ? Integer.toString(msg.what)
- : HandlerDebugString[msg.what - LOAD_URL]);
- }
- switch (msg.what) {
- case WEBKIT_DRAW:
- webkitDraw();
- break;
-
- case DESTROY:
- // Time to take down the world. Cancel all pending
- // loads and destroy the native view and frame.
- mBrowserFrame.destroy();
- mBrowserFrame = null;
- mNativeClass = 0;
- break;
-
- case LOAD_URL:
- loadUrl((String) msg.obj);
- break;
-
- case LOAD_DATA:
- HashMap loadParams = (HashMap) msg.obj;
- String baseUrl = (String) loadParams.get("baseUrl");
- if (baseUrl != null) {
- int i = baseUrl.indexOf(':');
- if (i > 0) {
- /*
- * In 1.0, {@link
- * WebView#loadDataWithBaseURL} can access
- * local asset files as long as the data is
- * valid. In the new WebKit, the restriction
- * is tightened. To be compatible with 1.0,
- * we automatically add the scheme of the
- * baseUrl for local access as long as it is
- * not http(s)/ftp(s)/about/javascript
- */
- String scheme = baseUrl.substring(0, i);
- if (!scheme.startsWith("http") &&
- !scheme.startsWith("ftp") &&
- !scheme.startsWith("about") &&
- !scheme.startsWith("javascript")) {
- nativeRegisterURLSchemeAsLocal(scheme);
- }
- }
- }
- mBrowserFrame.loadData(baseUrl,
- (String) loadParams.get("data"),
- (String) loadParams.get("mimeType"),
- (String) loadParams.get("encoding"),
- (String) loadParams.get("failUrl"));
- break;
-
- case STOP_LOADING:
- // If the WebCore has committed the load, but not
- // finished the first layout yet, we need to set
- // first layout done to trigger the interpreted side sync
- // up with native side
- if (mBrowserFrame.committed()
- && !mBrowserFrame.firstLayoutDone()) {
- mBrowserFrame.didFirstLayout();
- }
- // Do this after syncing up the layout state.
- stopLoading();
- break;
-
- case RELOAD:
- mBrowserFrame.reload(false);
- break;
-
- case KEY_DOWN:
- key((KeyEvent) msg.obj, true);
- break;
-
- case KEY_UP:
- key((KeyEvent) msg.obj, false);
- break;
-
- case CLICK:
- nativeClick();
- break;
-
- case VIEW_SIZE_CHANGED:
- viewSizeChanged(msg.arg1, msg.arg2,
- ((Integer) msg.obj).intValue());
- break;
-
- case SET_SCROLL_OFFSET:
- // note: these are in document coordinates
- // (inv-zoom)
- nativeSetScrollOffset(msg.arg1, msg.arg2);
- break;
-
- case SET_GLOBAL_BOUNDS:
- Rect r = (Rect) msg.obj;
- nativeSetGlobalBounds(r.left, r.top, r.width(),
- r.height());
- break;
-
- case GO_BACK_FORWARD:
- // If it is a standard load and the load is not
- // committed yet, we interpret BACK as RELOAD
- if (!mBrowserFrame.committed() && msg.arg1 == -1 &&
- (mBrowserFrame.loadType() ==
- BrowserFrame.FRAME_LOADTYPE_STANDARD)) {
- mBrowserFrame.reload(true);
- } else {
- mBrowserFrame.goBackOrForward(msg.arg1);
- }
- break;
-
- case RESTORE_STATE:
- stopLoading();
- restoreState(msg.arg1);
- break;
-
- case PAUSE_TIMERS:
- mSavedPriority = Process.getThreadPriority(mTid);
- Process.setThreadPriority(mTid,
- Process.THREAD_PRIORITY_BACKGROUND);
- pauseTimers();
- if (CacheManager.disableTransaction()) {
- WebCoreThread.mCacheTickersBlocked = true;
- sWebCoreHandler.removeMessages(
- WebCoreThread.CACHE_TICKER);
- }
- break;
-
- case RESUME_TIMERS:
- Process.setThreadPriority(mTid, mSavedPriority);
- resumeTimers();
- if (CacheManager.enableTransaction()) {
- WebCoreThread.mCacheTickersBlocked = false;
- sWebCoreHandler.sendMessageDelayed(
- sWebCoreHandler.obtainMessage(
- WebCoreThread.CACHE_TICKER),
- WebCoreThread.CACHE_TICKER_INTERVAL);
- }
- break;
-
- case CLEAR_CACHE:
- mBrowserFrame.clearCache();
- if (msg.arg1 == 1) {
- CacheManager.removeAllCacheFiles();
- }
- break;
-
- case CLEAR_HISTORY:
- mCallbackProxy.getBackForwardList().
- close(mBrowserFrame.mNativeFrame);
- break;
-
- case REPLACE_TEXT:
- HashMap jMap = (HashMap) msg.obj;
- FocusData fData = (FocusData) jMap.get("focusData");
- String replace = (String) jMap.get("replace");
- int newStart =
- ((Integer) jMap.get("start")).intValue();
- int newEnd =
- ((Integer) jMap.get("end")).intValue();
- nativeReplaceTextfieldText(fData.mFrame,
- fData.mNode, fData.mX, fData.mY, msg.arg1,
- msg.arg2, replace, newStart, newEnd);
- break;
-
- case PASS_TO_JS: {
- HashMap jsMap = (HashMap) msg.obj;
- FocusData fDat = (FocusData) jsMap.get("focusData");
- KeyEvent evt = (KeyEvent) jsMap.get("event");
- int keyCode = evt.getKeyCode();
- int keyValue = evt.getUnicodeChar();
- int generation = msg.arg1;
- passToJs(fDat.mFrame, fDat.mNode, fDat.mX, fDat.mY,
- generation,
- (String) jsMap.get("currentText"),
- keyCode,
- keyValue,
- evt.isDown(),
- evt.isShiftPressed(), evt.isAltPressed(),
- evt.isSymPressed());
- break;
- }
-
- case SAVE_DOCUMENT_STATE: {
- FocusData fDat = (FocusData) msg.obj;
- nativeSaveDocumentState(fDat.mFrame);
- break;
- }
-
- case CLEAR_SSL_PREF_TABLE:
- Network.getInstance(mContext)
- .clearUserSslPrefTable();
- break;
-
- case TOUCH_UP:
- TouchUpData touchUpData = (TouchUpData) msg.obj;
- nativeTouchUp(touchUpData.mMoveGeneration,
- touchUpData.mBuildGeneration,
- touchUpData.mFrame, touchUpData.mNode,
- touchUpData.mX, touchUpData.mY,
- touchUpData.mSize, touchUpData.mIsClick,
- touchUpData.mRetry);
- break;
-
- case TOUCH_EVENT: {
- TouchEventData ted = (TouchEventData) msg.obj;
- Message.obtain(
- mWebView.mPrivateHandler,
- WebView.PREVENT_TOUCH_ID, ted.mAction,
- nativeHandleTouchEvent(ted.mAction, ted.mX,
- ted.mY) ? 1 : 0).sendToTarget();
- break;
- }
-
- case ADD_JS_INTERFACE:
- HashMap map = (HashMap) msg.obj;
- Object obj = map.get("object");
- String interfaceName = (String)
- map.get("interfaceName");
- mBrowserFrame.addJavascriptInterface(obj,
- interfaceName);
- break;
-
- case REQUEST_EXT_REPRESENTATION:
- mBrowserFrame.externalRepresentation(
- (Message) msg.obj);
- break;
-
- case REQUEST_DOC_AS_TEXT:
- mBrowserFrame.documentAsText((Message) msg.obj);
- break;
-
- case SET_FINAL_FOCUS:
- FocusData finalData = (FocusData) msg.obj;
- nativeSetFinalFocus(finalData.mFrame,
- finalData.mNode, finalData.mX,
- finalData.mY, msg.arg1
- != EventHub.NO_FOCUS_CHANGE_BLOCK);
- break;
-
- case UNBLOCK_FOCUS:
- nativeUnblockFocus();
- break;
-
- case SET_KIT_FOCUS:
- FocusData focusData = (FocusData) msg.obj;
- nativeSetKitFocus(focusData.mMoveGeneration,
- focusData.mBuildGeneration,
- focusData.mFrame, focusData.mNode,
- focusData.mX, focusData.mY,
- focusData.mIgnoreNullFocus);
- break;
-
- case REQUEST_FOCUS_HREF: {
- Message hrefMsg = (Message) msg.obj;
- String res = nativeRetrieveHref(msg.arg1, msg.arg2);
- hrefMsg.getData().putString("url", res);
- hrefMsg.sendToTarget();
- break;
- }
-
- case UPDATE_CACHE_AND_TEXT_ENTRY:
- nativeUpdateFrameCache();
- // FIXME: this should provide a minimal rectangle
- if (mWebView != null) {
- mWebView.postInvalidate();
- }
- sendUpdateTextEntry();
- break;
-
- case DOC_HAS_IMAGES:
- Message imageResult = (Message) msg.obj;
- imageResult.arg1 =
- mBrowserFrame.documentHasImages() ? 1 : 0;
- imageResult.sendToTarget();
- break;
-
- case SET_SNAP_ANCHOR:
- nativeSetSnapAnchor(msg.arg1, msg.arg2);
- break;
-
- case DELETE_SELECTION:
- FocusData delData = (FocusData) msg.obj;
- nativeDeleteSelection(delData.mFrame,
- delData.mNode, delData.mX,
- delData.mY, msg.arg1, msg.arg2);
- break;
-
- case SET_SELECTION:
- FocusData selData = (FocusData) msg.obj;
- nativeSetSelection(selData.mFrame,
- selData.mNode, selData.mX,
- selData.mY, msg.arg1, msg.arg2);
- break;
-
- case LISTBOX_CHOICES:
- SparseBooleanArray choices = (SparseBooleanArray)
- msg.obj;
- int choicesSize = msg.arg1;
- boolean[] choicesArray = new boolean[choicesSize];
- for (int c = 0; c < choicesSize; c++) {
- choicesArray[c] = choices.get(c);
- }
- nativeSendListBoxChoices(choicesArray,
- choicesSize);
- break;
-
- case SINGLE_LISTBOX_CHOICE:
- nativeSendListBoxChoice(msg.arg1);
- break;
-
- case SET_BACKGROUND_COLOR:
- nativeSetBackgroundColor(msg.arg1);
- break;
-
- case GET_SELECTION:
- String str = nativeGetSelection((Region) msg.obj);
- Message.obtain(mWebView.mPrivateHandler
- , WebView.UPDATE_CLIPBOARD, str)
- .sendToTarget();
- break;
-
- case DUMP_DOMTREE:
- nativeDumpDomTree(msg.arg1 == 1);
- break;
-
- case DUMP_RENDERTREE:
- nativeDumpRenderTree(msg.arg1 == 1);
- break;
-
- case DUMP_NAVTREE:
- nativeDumpNavTree();
- break;
-
- case SYNC_SCROLL:
- mWebkitScrollX = msg.arg1;
- mWebkitScrollY = msg.arg2;
- break;
-
- case REFRESH_PLUGINS:
- nativeRefreshPlugins(msg.arg1 != 0);
- break;
-
- case SPLIT_PICTURE_SET:
- nativeSplitContent();
- mSplitPictureIsScheduled = false;
- break;
-
- case CLEAR_CONTENT:
- // Clear the view so that onDraw() will draw nothing
- // but white background
- // (See public method WebView.clearView)
- nativeClearContent();
- break;
- }
- }
- };
- // Take all queued messages and resend them to the new handler.
- synchronized (this) {
- int size = mMessages.size();
- for (int i = 0; i < size; i++) {
- mHandler.sendMessage(mMessages.get(i));
- }
- mMessages = null;
- }
- }
-
- /**
- * Send a message internally to the queue or to the handler
- */
- private synchronized void sendMessage(Message msg) {
- if (mBlockMessages) {
- return;
- }
- if (mMessages != null) {
- mMessages.add(msg);
- } else {
- mHandler.sendMessage(msg);
- }
- }
-
- private synchronized void removeMessages(int what) {
- if (mBlockMessages) {
- return;
- }
- if (what == EventHub.WEBKIT_DRAW) {
- mDrawIsScheduled = false;
- }
- if (mMessages != null) {
- Log.w(LOGTAG, "Not supported in this case.");
- } else {
- mHandler.removeMessages(what);
- }
- }
-
- private synchronized void sendMessageDelayed(Message msg, long delay) {
- if (mBlockMessages) {
- return;
- }
- mHandler.sendMessageDelayed(msg, delay);
- }
-
- /**
- * Send a message internally to the front of the queue.
- */
- private synchronized void sendMessageAtFrontOfQueue(Message msg) {
- if (mBlockMessages) {
- return;
- }
- if (mMessages != null) {
- mMessages.add(0, msg);
- } else {
- mHandler.sendMessageAtFrontOfQueue(msg);
- }
- }
-
- /**
- * Remove all the messages.
- */
- private synchronized void removeMessages() {
- // reset mDrawIsScheduled flag as WEBKIT_DRAW may be removed
- mDrawIsScheduled = false;
- mSplitPictureIsScheduled = false;
- if (mMessages != null) {
- mMessages.clear();
- } else {
- mHandler.removeCallbacksAndMessages(null);
- }
- }
-
- /**
- * Block sending messages to the EventHub.
- */
- private synchronized void blockMessages() {
- mBlockMessages = true;
- }
- }
-
- //-------------------------------------------------------------------------
- // Methods called by host activity (in the same thread)
- //-------------------------------------------------------------------------
-
- void stopLoading() {
- if (LOGV_ENABLED) Log.v(LOGTAG, "CORE stopLoading");
- if (mBrowserFrame != null) {
- mBrowserFrame.stopLoading();
- }
- }
-
- //-------------------------------------------------------------------------
- // Methods called by WebView
- // If it refers to local variable, it needs synchronized().
- // If it needs WebCore, it has to send message.
- //-------------------------------------------------------------------------
-
- void sendMessage(Message msg) {
- mEventHub.sendMessage(msg);
- }
-
- void sendMessage(int what) {
- mEventHub.sendMessage(Message.obtain(null, what));
- }
-
- void sendMessage(int what, Object obj) {
- mEventHub.sendMessage(Message.obtain(null, what, obj));
- }
-
- void sendMessage(int what, int arg1) {
- // just ignore the second argument (make it 0)
- mEventHub.sendMessage(Message.obtain(null, what, arg1, 0));
- }
-
- void sendMessage(int what, int arg1, int arg2) {
- mEventHub.sendMessage(Message.obtain(null, what, arg1, arg2));
- }
-
- void sendMessage(int what, int arg1, Object obj) {
- // just ignore the second argument (make it 0)
- mEventHub.sendMessage(Message.obtain(null, what, arg1, 0, obj));
- }
-
- void sendMessage(int what, int arg1, int arg2, Object obj) {
- mEventHub.sendMessage(Message.obtain(null, what, arg1, arg2, obj));
- }
-
- void sendMessageDelayed(int what, Object obj, long delay) {
- mEventHub.sendMessageDelayed(Message.obtain(null, what, obj), delay);
- }
-
- void removeMessages(int what) {
- mEventHub.removeMessages(what);
- }
-
- void removeMessages() {
- mEventHub.removeMessages();
- }
-
- /**
- * Removes pending messages and trigger a DESTROY message to send to
- * WebCore.
- * Called from UI thread.
- */
- void destroy() {
- // We don't want anyone to post a message between removing pending
- // messages and sending the destroy message.
- synchronized (mEventHub) {
- mEventHub.removeMessages();
- mEventHub.sendMessageAtFrontOfQueue(
- Message.obtain(null, EventHub.DESTROY));
- mEventHub.blockMessages();
- mWebView = null;
- }
- }
-
- //-------------------------------------------------------------------------
- // WebViewCore private methods
- //-------------------------------------------------------------------------
-
- private void loadUrl(String url) {
- if (LOGV_ENABLED) Log.v(LOGTAG, " CORE loadUrl " + url);
- mBrowserFrame.loadUrl(url);
- }
-
- private void key(KeyEvent evt, boolean isDown) {
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "CORE key at " + System.currentTimeMillis() + ", "
- + evt);
- }
- if (!nativeKey(evt.getKeyCode(), evt.getUnicodeChar(),
- evt.getRepeatCount(), evt.isShiftPressed(), evt.isAltPressed(),
- isDown)) {
- // bubble up the event handling
- mCallbackProxy.onUnhandledKeyEvent(evt);
- }
- }
-
- // These values are used to avoid requesting a layout based on old values
- private int mCurrentViewWidth = 0;
- private int mCurrentViewHeight = 0;
-
- // Define a minimum screen width so that we won't wrap the paragraph to one
- // word per line during zoom-in.
- private static final int MIN_SCREEN_WIDTH = 160;
-
- // notify webkit that our virtual view size changed size (after inv-zoom)
- private void viewSizeChanged(int w, int h, int viewWidth) {
- if (LOGV_ENABLED) Log.v(LOGTAG, "CORE onSizeChanged");
- if (w == 0) {
- Log.w(LOGTAG, "skip viewSizeChanged as w is 0");
- return;
- }
- // negative scale indicate that WebCore should reuse the current scale
- float scale = (float) viewWidth / w;
- if (mSettings.getUseWideViewPort()
- && (w < mViewportWidth || mViewportWidth == -1)) {
- int width = mViewportWidth;
- int screenWidth = Math.max(w, MIN_SCREEN_WIDTH);
- if (mViewportWidth == -1) {
- if (mSettings.getLayoutAlgorithm() ==
- WebSettings.LayoutAlgorithm.NORMAL) {
- width = WebView.ZOOM_OUT_WIDTH;
- } else {
- /*
- * if a page's minimum preferred width is wider than the
- * given "w", use it instead to get better layout result. If
- * we start a page with MAX_ZOOM_WIDTH, "w" will be always
- * wider. If we start a page with screen width, due to the
- * delay between {@link #didFirstLayout} and
- * {@link #viewSizeChanged},
- * {@link #nativeGetContentMinPrefWidth} will return a more
- * accurate value than initial 0 to result a better layout.
- * In the worse case, the native width will be adjusted when
- * next zoom or screen orientation change happens.
- */
- int minContentWidth = nativeGetContentMinPrefWidth();
- if (minContentWidth > WebView.MAX_FLOAT_CONTENT_WIDTH) {
- // keep the same width and screen width so that there is
- // no reflow when zoom-out
- width = minContentWidth;
- screenWidth = Math.min(screenWidth, Math.abs(viewWidth));
- } else {
- width = Math.max(w, minContentWidth);
- }
- }
- }
- nativeSetSize(width, Math.round((float) width * h / w),
- screenWidth, scale, w, h);
- } else {
- nativeSetSize(w, h, w, scale, w, h);
- }
- // Remember the current width and height
- boolean needInvalidate = (mCurrentViewWidth == 0);
- mCurrentViewWidth = w;
- mCurrentViewHeight = h;
- if (needInvalidate) {
- // ensure {@link #webkitDraw} is called as we were blocking in
- // {@link #contentDraw} when mCurrentViewWidth is 0
- if (LOGV_ENABLED) Log.v(LOGTAG, "viewSizeChanged");
- contentDraw();
- }
- mEventHub.sendMessage(Message.obtain(null,
- EventHub.UPDATE_CACHE_AND_TEXT_ENTRY));
- }
-
- private void sendUpdateTextEntry() {
- if (mWebView != null) {
- Message.obtain(mWebView.mPrivateHandler,
- WebView.UPDATE_TEXT_ENTRY_MSG_ID).sendToTarget();
- }
- }
-
- // Used to avoid posting more than one draw message.
- private boolean mDrawIsScheduled;
-
- // Used to avoid posting more than one split picture message.
- private boolean mSplitPictureIsScheduled;
-
- // Used to suspend drawing.
- private boolean mDrawIsPaused;
-
- // Used to end scale+scroll mode, accessed by both threads
- boolean mEndScaleZoom = false;
-
- public class DrawData {
- public DrawData() {
- mInvalRegion = new Region();
- mWidthHeight = new Point();
- }
- public Region mInvalRegion;
- public Point mViewPoint;
- public Point mWidthHeight;
- }
-
- private void webkitDraw() {
- mDrawIsScheduled = false;
- DrawData draw = new DrawData();
- if (LOGV_ENABLED) Log.v(LOGTAG, "webkitDraw start");
- if (nativeRecordContent(draw.mInvalRegion, draw.mWidthHeight)
- == false) {
- if (LOGV_ENABLED) Log.v(LOGTAG, "webkitDraw abort");
- return;
- }
- if (mWebView != null) {
- // Send the native view size that was used during the most recent
- // layout.
- draw.mViewPoint = new Point(mCurrentViewWidth, mCurrentViewHeight);
- if (LOGV_ENABLED) Log.v(LOGTAG, "webkitDraw NEW_PICTURE_MSG_ID");
- Message.obtain(mWebView.mPrivateHandler,
- WebView.NEW_PICTURE_MSG_ID, nativeGetContentMinPrefWidth(),
- 0, draw).sendToTarget();
- nativeCheckNavCache();
- if (mWebkitScrollX != 0 || mWebkitScrollY != 0) {
- // as we have the new picture, try to sync the scroll position
- Message.obtain(mWebView.mPrivateHandler,
- WebView.SYNC_SCROLL_TO_MSG_ID, mWebkitScrollX,
- mWebkitScrollY).sendToTarget();
- mWebkitScrollX = mWebkitScrollY = 0;
- }
- // nativeSnapToAnchor() needs to be called after NEW_PICTURE_MSG_ID
- // is sent, so that scroll will be based on the new content size.
- nativeSnapToAnchor();
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // These are called from the UI thread, not our thread
-
- static final int ZOOM_BITS = Paint.FILTER_BITMAP_FLAG |
- Paint.DITHER_FLAG |
- Paint.SUBPIXEL_TEXT_FLAG;
- static final int SCROLL_BITS = Paint.FILTER_BITMAP_FLAG |
- Paint.DITHER_FLAG;
-
- final DrawFilter mZoomFilter =
- new PaintFlagsDrawFilter(ZOOM_BITS, Paint.LINEAR_TEXT_FLAG);
- final DrawFilter mScrollFilter =
- new PaintFlagsDrawFilter(SCROLL_BITS, 0);
-
- /* package */ void drawContentPicture(Canvas canvas, int color,
- boolean animatingZoom,
- boolean animatingScroll) {
- DrawFilter df = null;
- if (animatingZoom) {
- df = mZoomFilter;
- } else if (animatingScroll) {
- df = mScrollFilter;
- }
- canvas.setDrawFilter(df);
- boolean tookTooLong = nativeDrawContent(canvas, color);
- canvas.setDrawFilter(null);
- if (tookTooLong && mSplitPictureIsScheduled == false) {
- mSplitPictureIsScheduled = true;
- sendMessage(EventHub.SPLIT_PICTURE_SET);
- }
- }
-
- /*package*/ Picture copyContentPicture() {
- Picture result = new Picture();
- nativeCopyContentToPicture(result);
- return result;
- }
-
- static void pauseUpdate(WebViewCore core) {
- // remove the pending REDUCE_PRIORITY and RESUME_PRIORITY messages
- sWebCoreHandler.removeMessages(WebCoreThread.REDUCE_PRIORITY);
- sWebCoreHandler.removeMessages(WebCoreThread.RESUME_PRIORITY);
- sWebCoreHandler.sendMessageAtFrontOfQueue(sWebCoreHandler
- .obtainMessage(WebCoreThread.REDUCE_PRIORITY));
- // Note: there is one possible failure mode. If pauseUpdate() is called
- // from UI thread while in webcore thread WEBKIT_DRAW is just pulled out
- // of the queue and about to be executed. mDrawIsScheduled may be set to
- // false in webkitDraw(). So update won't be blocked. But at least the
- // webcore thread priority is still lowered.
- if (core != null) {
- synchronized (core) {
- core.mDrawIsPaused = true;
- core.mEventHub.removeMessages(EventHub.WEBKIT_DRAW);
- }
- }
- }
-
- static void resumeUpdate(WebViewCore core) {
- // remove the pending REDUCE_PRIORITY and RESUME_PRIORITY messages
- sWebCoreHandler.removeMessages(WebCoreThread.REDUCE_PRIORITY);
- sWebCoreHandler.removeMessages(WebCoreThread.RESUME_PRIORITY);
- sWebCoreHandler.sendMessageAtFrontOfQueue(sWebCoreHandler
- .obtainMessage(WebCoreThread.RESUME_PRIORITY));
- if (core != null) {
- synchronized (core) {
- core.mDrawIsScheduled = false;
- core.mDrawIsPaused = false;
- if (LOGV_ENABLED) Log.v(LOGTAG, "resumeUpdate");
- core.contentDraw();
- }
- }
- }
-
- static void startCacheTransaction() {
- sWebCoreHandler.sendMessage(sWebCoreHandler
- .obtainMessage(WebCoreThread.RESUME_CACHE_TICKER));
- }
-
- static void endCacheTransaction() {
- sWebCoreHandler.sendMessage(sWebCoreHandler
- .obtainMessage(WebCoreThread.BLOCK_CACHE_TICKER));
- }
-
- //////////////////////////////////////////////////////////////////////////
-
- private void restoreState(int index) {
- WebBackForwardList list = mCallbackProxy.getBackForwardList();
- int size = list.getSize();
- for (int i = 0; i < size; i++) {
- list.getItemAtIndex(i).inflate(mBrowserFrame.mNativeFrame);
- }
- mBrowserFrame.mLoadInitFromJava = true;
- list.restoreIndex(mBrowserFrame.mNativeFrame, index);
- mBrowserFrame.mLoadInitFromJava = false;
- }
-
- //-------------------------------------------------------------------------
- // Implement abstract methods in WebViewCore, native WebKit callback part
- //-------------------------------------------------------------------------
-
- // called from JNI or WebView thread
- /* package */ void contentDraw() {
- // don't update the Picture until we have an initial width and finish
- // the first layout
- if (mCurrentViewWidth == 0 || !mBrowserFrame.firstLayoutDone()) {
- return;
- }
- // only fire an event if this is our first request
- synchronized (this) {
- if (mDrawIsPaused || mDrawIsScheduled) {
- return;
- }
- mDrawIsScheduled = true;
- mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW));
- }
- }
-
- // called by JNI
- private void contentScrollBy(int dx, int dy, boolean animate) {
- if (!mBrowserFrame.firstLayoutDone()) {
- // Will this happen? If yes, we need to do something here.
- return;
- }
- if (mWebView != null) {
- Message.obtain(mWebView.mPrivateHandler,
- WebView.SCROLL_BY_MSG_ID, dx, dy,
- new Boolean(animate)).sendToTarget();
- }
- }
-
- // called by JNI
- private void contentScrollTo(int x, int y) {
- if (!mBrowserFrame.firstLayoutDone()) {
- /*
- * WebKit restore state will be called before didFirstLayout(),
- * remember the position as it has to be applied after restoring
- * zoom factor which is controlled by screenWidth.
- */
- mRestoredX = x;
- mRestoredY = y;
- return;
- }
- if (mWebView != null) {
- Message.obtain(mWebView.mPrivateHandler,
- WebView.SCROLL_TO_MSG_ID, x, y).sendToTarget();
- }
- }
-
- // called by JNI
- private void contentSpawnScrollTo(int x, int y) {
- if (!mBrowserFrame.firstLayoutDone()) {
- /*
- * WebKit restore state will be called before didFirstLayout(),
- * remember the position as it has to be applied after restoring
- * zoom factor which is controlled by screenWidth.
- */
- mRestoredX = x;
- mRestoredY = y;
- return;
- }
- if (mWebView != null) {
- Message.obtain(mWebView.mPrivateHandler,
- WebView.SPAWN_SCROLL_TO_MSG_ID, x, y).sendToTarget();
- }
- }
-
- // called by JNI
- private void sendMarkNodeInvalid(int node) {
- if (mWebView != null) {
- Message.obtain(mWebView.mPrivateHandler,
- WebView.MARK_NODE_INVALID_ID, node, 0).sendToTarget();
- }
- }
-
- // called by JNI
- private void sendNotifyFocusSet() {
- if (mWebView != null) {
- Message.obtain(mWebView.mPrivateHandler,
- WebView.NOTIFY_FOCUS_SET_MSG_ID).sendToTarget();
- }
- }
-
- // called by JNI
- private void sendNotifyProgressFinished() {
- sendUpdateTextEntry();
- // as CacheManager can behave based on database transaction, we need to
- // call tick() to trigger endTransaction
- sWebCoreHandler.removeMessages(WebCoreThread.CACHE_TICKER);
- sWebCoreHandler.sendMessage(sWebCoreHandler
- .obtainMessage(WebCoreThread.CACHE_TICKER));
- contentDraw();
- }
-
- // called by JNI
- private void sendRecomputeFocus() {
- if (mWebView != null) {
- Message.obtain(mWebView.mPrivateHandler,
- WebView.RECOMPUTE_FOCUS_MSG_ID).sendToTarget();
- }
- }
-
- /* Called by JNI. The coordinates are in doc coordinates, so they need to
- be scaled before they can be used by the view system, which happens
- in WebView since it (and its thread) know the current scale factor.
- */
- private void sendViewInvalidate(int left, int top, int right, int bottom) {
- if (mWebView != null) {
- Message.obtain(mWebView.mPrivateHandler,
- WebView.INVAL_RECT_MSG_ID,
- new Rect(left, top, right, bottom)).sendToTarget();
- }
- }
-
- /* package */ WebView getWebView() {
- return mWebView;
- }
-
- private native void setViewportSettingsFromNative();
-
- // called by JNI
- private void didFirstLayout() {
- // Trick to ensure that the Picture has the exact height for the content
- // by forcing to layout with 0 height after the page is ready, which is
- // indicated by didFirstLayout. This is essential to get rid of the
- // white space in the GMail which uses WebView for message view.
- if (mWebView != null && mWebView.mHeightCanMeasure) {
- mWebView.mLastHeightSent = 0;
- // Send a negative screen width to indicate that WebCore should
- // reuse the current scale
- mEventHub.sendMessage(Message.obtain(null,
- EventHub.VIEW_SIZE_CHANGED, mWebView.mLastWidthSent,
- mWebView.mLastHeightSent, -mWebView.mLastWidthSent));
- }
-
- mBrowserFrame.didFirstLayout();
-
- // reset the scroll position as it is a new page now
- mWebkitScrollX = mWebkitScrollY = 0;
-
- // set the viewport settings from WebKit
- setViewportSettingsFromNative();
-
- // infer the values if they are not defined.
- if (mViewportWidth == 0) {
- if (mViewportInitialScale == 0) {
- mViewportInitialScale = 100;
- }
- if (mViewportMinimumScale == 0) {
- mViewportMinimumScale = 100;
- }
- }
- if (mViewportUserScalable == false) {
- mViewportInitialScale = 100;
- mViewportMinimumScale = 100;
- mViewportMaximumScale = 100;
- }
- if (mViewportMinimumScale > mViewportInitialScale) {
- if (mViewportInitialScale == 0) {
- mViewportInitialScale = mViewportMinimumScale;
- } else {
- mViewportMinimumScale = mViewportInitialScale;
- }
- }
- if (mViewportMaximumScale > 0) {
- if (mViewportMaximumScale < mViewportInitialScale) {
- mViewportMaximumScale = mViewportInitialScale;
- } else if (mViewportInitialScale == 0) {
- mViewportInitialScale = mViewportMaximumScale;
- }
- }
- if (mViewportWidth < 0 && mViewportInitialScale == 100) {
- mViewportWidth = 0;
- }
-
- // now notify webview
- if (mWebView != null) {
- HashMap scaleLimit = new HashMap();
- scaleLimit.put("minScale", mViewportMinimumScale);
- scaleLimit.put("maxScale", mViewportMaximumScale);
-
- if (mRestoredScale > 0) {
- Message.obtain(mWebView.mPrivateHandler,
- WebView.DID_FIRST_LAYOUT_MSG_ID, mRestoredScale, 0,
- scaleLimit).sendToTarget();
- mRestoredScale = 0;
- } else {
- Message.obtain(mWebView.mPrivateHandler,
- WebView.DID_FIRST_LAYOUT_MSG_ID, mViewportInitialScale,
- mViewportWidth, scaleLimit).sendToTarget();
- }
-
- // if no restored offset, move the new page to (0, 0)
- Message.obtain(mWebView.mPrivateHandler, WebView.SCROLL_TO_MSG_ID,
- mRestoredX, mRestoredY).sendToTarget();
- mRestoredX = mRestoredY = 0;
-
- // force an early draw for quick feedback after the first layout
- if (mCurrentViewWidth != 0) {
- synchronized (this) {
- if (mDrawIsScheduled) {
- mEventHub.removeMessages(EventHub.WEBKIT_DRAW);
- }
- mDrawIsScheduled = true;
- mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null,
- EventHub.WEBKIT_DRAW));
- }
- }
- }
- }
-
- // called by JNI
- private void restoreScale(int scale) {
- if (mBrowserFrame.firstLayoutDone() == false) {
- mRestoredScale = scale;
- }
- }
-
- // called by JNI
- private void needTouchEvents(boolean need) {
- if (mWebView != null) {
- Message.obtain(mWebView.mPrivateHandler,
- WebView.WEBCORE_NEED_TOUCH_EVENTS, need ? 1 : 0, 0)
- .sendToTarget();
- }
- }
-
- // called by JNI
- private void updateTextfield(int ptr, boolean changeToPassword,
- String text, int textGeneration) {
- if (mWebView != null) {
- Message msg = Message.obtain(mWebView.mPrivateHandler,
- WebView.UPDATE_TEXTFIELD_TEXT_MSG_ID, ptr,
- textGeneration, text);
- msg.getData().putBoolean("password", changeToPassword);
- msg.sendToTarget();
- }
- }
-
- // these must be in document space (i.e. not scaled/zoomed).
- private native void nativeSetScrollOffset(int dx, int dy);
-
- private native void nativeSetGlobalBounds(int x, int y, int w, int h);
-
- // called by JNI
- private void requestListBox(String[] array, boolean[] enabledArray,
- int[] selectedArray) {
- if (mWebView != null) {
- mWebView.requestListBox(array, enabledArray, selectedArray);
- }
- }
-
- // called by JNI
- private void requestListBox(String[] array, boolean[] enabledArray,
- int selection) {
- if (mWebView != null) {
- mWebView.requestListBox(array, enabledArray, selection);
- }
-
- }
-}
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
deleted file mode 100644
index 1004e30..0000000
--- a/core/java/android/webkit/WebViewDatabase.java
+++ /dev/null
@@ -1,967 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.webkit;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Set;
-import java.util.Map.Entry;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteStatement;
-import android.util.Log;
-import android.webkit.CookieManager.Cookie;
-import android.webkit.CacheManager.CacheResult;
-
-public class WebViewDatabase {
- private static final String DATABASE_FILE = "webview.db";
- private static final String CACHE_DATABASE_FILE = "webviewCache.db";
-
- // log tag
- protected static final String LOGTAG = "webviewdatabase";
-
- private static final int DATABASE_VERSION = 9;
- // 2 -> 3 Modified Cache table to allow cache of redirects
- // 3 -> 4 Added Oma-Downloads table
- // 4 -> 5 Modified Cache table to support persistent contentLength
- // 5 -> 4 Removed Oma-Downoads table
- // 5 -> 6 Add INDEX for cache table
- // 6 -> 7 Change cache localPath from int to String
- // 7 -> 8 Move cache to its own db
- // 8 -> 9 Store both scheme and host when storing passwords
- private static final int CACHE_DATABASE_VERSION = 1;
-
- private static WebViewDatabase mInstance = null;
-
- private static SQLiteDatabase mDatabase = null;
- private static SQLiteDatabase mCacheDatabase = null;
-
- // synchronize locks
- private final Object mCookieLock = new Object();
- private final Object mPasswordLock = new Object();
- private final Object mFormLock = new Object();
- private final Object mHttpAuthLock = new Object();
-
- private static final String mTableNames[] = {
- "cookies", "password", "formurl", "formdata", "httpauth"
- };
-
- // Table ids (they are index to mTableNames)
- private static final int TABLE_COOKIES_ID = 0;
-
- private static final int TABLE_PASSWORD_ID = 1;
-
- private static final int TABLE_FORMURL_ID = 2;
-
- private static final int TABLE_FORMDATA_ID = 3;
-
- private static final int TABLE_HTTPAUTH_ID = 4;
-
- // column id strings for "_id" which can be used by any table
- private static final String ID_COL = "_id";
-
- private static final String[] ID_PROJECTION = new String[] {
- "_id"
- };
-
- // column id strings for "cookies" table
- private static final String COOKIES_NAME_COL = "name";
-
- private static final String COOKIES_VALUE_COL = "value";
-
- private static final String COOKIES_DOMAIN_COL = "domain";
-
- private static final String COOKIES_PATH_COL = "path";
-
- private static final String COOKIES_EXPIRES_COL = "expires";
-
- private static final String COOKIES_SECURE_COL = "secure";
-
- // column id strings for "cache" table
- private static final String CACHE_URL_COL = "url";
-
- private static final String CACHE_FILE_PATH_COL = "filepath";
-
- private static final String CACHE_LAST_MODIFY_COL = "lastmodify";
-
- private static final String CACHE_ETAG_COL = "etag";
-
- private static final String CACHE_EXPIRES_COL = "expires";
-
- private static final String CACHE_MIMETYPE_COL = "mimetype";
-
- private static final String CACHE_ENCODING_COL = "encoding";
-
- private static final String CACHE_HTTP_STATUS_COL = "httpstatus";
-
- private static final String CACHE_LOCATION_COL = "location";
-
- private static final String CACHE_CONTENTLENGTH_COL = "contentlength";
-
- // column id strings for "password" table
- private static final String PASSWORD_HOST_COL = "host";
-
- private static final String PASSWORD_USERNAME_COL = "username";
-
- private static final String PASSWORD_PASSWORD_COL = "password";
-
- // column id strings for "formurl" table
- private static final String FORMURL_URL_COL = "url";
-
- // column id strings for "formdata" table
- private static final String FORMDATA_URLID_COL = "urlid";
-
- private static final String FORMDATA_NAME_COL = "name";
-
- private static final String FORMDATA_VALUE_COL = "value";
-
- // column id strings for "httpauth" table
- private static final String HTTPAUTH_HOST_COL = "host";
-
- private static final String HTTPAUTH_REALM_COL = "realm";
-
- private static final String HTTPAUTH_USERNAME_COL = "username";
-
- private static final String HTTPAUTH_PASSWORD_COL = "password";
-
- // use InsertHelper to improve insert performance by 40%
- private static DatabaseUtils.InsertHelper mCacheInserter;
- private static int mCacheUrlColIndex;
- private static int mCacheFilePathColIndex;
- private static int mCacheLastModifyColIndex;
- private static int mCacheETagColIndex;
- private static int mCacheExpiresColIndex;
- private static int mCacheMimeTypeColIndex;
- private static int mCacheEncodingColIndex;
- private static int mCacheHttpStatusColIndex;
- private static int mCacheLocationColIndex;
- private static int mCacheContentLengthColIndex;
-
- private static int mCacheTransactionRefcount;
-
- private WebViewDatabase() {
- // Singleton only, use getInstance()
- }
-
- public static synchronized WebViewDatabase getInstance(Context context) {
- if (mInstance == null) {
- mInstance = new WebViewDatabase();
- mDatabase = context.openOrCreateDatabase(DATABASE_FILE, 0, null);
-
- // mDatabase should not be null,
- // the only case is RequestAPI test has problem to create db
- if (mDatabase != null && mDatabase.getVersion() != DATABASE_VERSION) {
- mDatabase.beginTransaction();
- try {
- upgradeDatabase();
- mDatabase.setTransactionSuccessful();
- } finally {
- mDatabase.endTransaction();
- }
- }
-
- if (mDatabase != null) {
- // use per table Mutex lock, turn off database lock, this
- // improves performance as database's ReentrantLock is expansive
- mDatabase.setLockingEnabled(false);
- }
-
- mCacheDatabase = context.openOrCreateDatabase(CACHE_DATABASE_FILE,
- 0, null);
-
- // mCacheDatabase should not be null,
- // the only case is RequestAPI test has problem to create db
- if (mCacheDatabase != null
- && mCacheDatabase.getVersion() != CACHE_DATABASE_VERSION) {
- mCacheDatabase.beginTransaction();
- try {
- upgradeCacheDatabase();
- bootstrapCacheDatabase();
- mCacheDatabase.setTransactionSuccessful();
- } finally {
- mCacheDatabase.endTransaction();
- }
- // Erase the files from the file system in the
- // case that the database was updated and the
- // there were existing cache content
- CacheManager.removeAllCacheFiles();
- }
-
- if (mCacheDatabase != null) {
- // use InsertHelper for faster insertion
- mCacheInserter = new DatabaseUtils.InsertHelper(mCacheDatabase,
- "cache");
- mCacheUrlColIndex = mCacheInserter
- .getColumnIndex(CACHE_URL_COL);
- mCacheFilePathColIndex = mCacheInserter
- .getColumnIndex(CACHE_FILE_PATH_COL);
- mCacheLastModifyColIndex = mCacheInserter
- .getColumnIndex(CACHE_LAST_MODIFY_COL);
- mCacheETagColIndex = mCacheInserter
- .getColumnIndex(CACHE_ETAG_COL);
- mCacheExpiresColIndex = mCacheInserter
- .getColumnIndex(CACHE_EXPIRES_COL);
- mCacheMimeTypeColIndex = mCacheInserter
- .getColumnIndex(CACHE_MIMETYPE_COL);
- mCacheEncodingColIndex = mCacheInserter
- .getColumnIndex(CACHE_ENCODING_COL);
- mCacheHttpStatusColIndex = mCacheInserter
- .getColumnIndex(CACHE_HTTP_STATUS_COL);
- mCacheLocationColIndex = mCacheInserter
- .getColumnIndex(CACHE_LOCATION_COL);
- mCacheContentLengthColIndex = mCacheInserter
- .getColumnIndex(CACHE_CONTENTLENGTH_COL);
- }
- }
-
- return mInstance;
- }
-
- private static void upgradeDatabase() {
- int oldVersion = mDatabase.getVersion();
- if (oldVersion != 0) {
- Log.i(LOGTAG, "Upgrading database from version "
- + oldVersion + " to "
- + DATABASE_VERSION + ", which will destroy old data");
- }
- boolean justPasswords = 8 == oldVersion && 9 == DATABASE_VERSION;
- if (!justPasswords) {
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_COOKIES_ID]);
- mDatabase.execSQL("DROP TABLE IF EXISTS cache");
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_FORMURL_ID]);
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_FORMDATA_ID]);
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_HTTPAUTH_ID]);
- }
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_PASSWORD_ID]);
-
- mDatabase.setVersion(DATABASE_VERSION);
-
- if (!justPasswords) {
- // cookies
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_COOKIES_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, "
- + COOKIES_NAME_COL + " TEXT, " + COOKIES_VALUE_COL
- + " TEXT, " + COOKIES_DOMAIN_COL + " TEXT, "
- + COOKIES_PATH_COL + " TEXT, " + COOKIES_EXPIRES_COL
- + " INTEGER, " + COOKIES_SECURE_COL + " INTEGER" + ");");
- mDatabase.execSQL("CREATE INDEX cookiesIndex ON "
- + mTableNames[TABLE_COOKIES_ID] + " (path)");
-
- // formurl
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMURL_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, " + FORMURL_URL_COL
- + " TEXT" + ");");
-
- // formdata
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMDATA_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, "
- + FORMDATA_URLID_COL + " INTEGER, " + FORMDATA_NAME_COL
- + " TEXT, " + FORMDATA_VALUE_COL + " TEXT," + " UNIQUE ("
- + FORMDATA_URLID_COL + ", " + FORMDATA_NAME_COL + ", "
- + FORMDATA_VALUE_COL + ") ON CONFLICT IGNORE);");
-
- // httpauth
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, "
- + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
- + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
- + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
- + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL + ", "
- + HTTPAUTH_USERNAME_COL + ") ON CONFLICT REPLACE);");
- }
- // passwords
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_PASSWORD_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, "
- + PASSWORD_HOST_COL + " TEXT, " + PASSWORD_USERNAME_COL
- + " TEXT, " + PASSWORD_PASSWORD_COL + " TEXT," + " UNIQUE ("
- + PASSWORD_HOST_COL + ", " + PASSWORD_USERNAME_COL
- + ") ON CONFLICT REPLACE);");
- }
-
- private static void upgradeCacheDatabase() {
- int oldVersion = mCacheDatabase.getVersion();
- if (oldVersion != 0) {
- Log.i(LOGTAG, "Upgrading cache database from version "
- + oldVersion + " to "
- + DATABASE_VERSION + ", which will destroy all old data");
- }
- mCacheDatabase.execSQL("DROP TABLE IF EXISTS cache");
- mCacheDatabase.setVersion(CACHE_DATABASE_VERSION);
- }
-
- private static void bootstrapCacheDatabase() {
- if (mCacheDatabase != null) {
- mCacheDatabase.execSQL("CREATE TABLE cache"
- + " (" + ID_COL + " INTEGER PRIMARY KEY, " + CACHE_URL_COL
- + " TEXT, " + CACHE_FILE_PATH_COL + " TEXT, "
- + CACHE_LAST_MODIFY_COL + " TEXT, " + CACHE_ETAG_COL
- + " TEXT, " + CACHE_EXPIRES_COL + " INTEGER, "
- + CACHE_MIMETYPE_COL + " TEXT, " + CACHE_ENCODING_COL
- + " TEXT," + CACHE_HTTP_STATUS_COL + " INTEGER, "
- + CACHE_LOCATION_COL + " TEXT, " + CACHE_CONTENTLENGTH_COL
- + " INTEGER, " + " UNIQUE (" + CACHE_URL_COL
- + ") ON CONFLICT REPLACE);");
- mCacheDatabase.execSQL("CREATE INDEX cacheUrlIndex ON cache ("
- + CACHE_URL_COL + ")");
- }
- }
-
- private boolean hasEntries(int tableId) {
- if (mDatabase == null) {
- return false;
- }
-
- Cursor cursor = mDatabase.query(mTableNames[tableId], ID_PROJECTION,
- null, null, null, null, null);
- boolean ret = cursor.moveToFirst() == true;
- cursor.close();
- return ret;
- }
-
- //
- // cookies functions
- //
-
- /**
- * Get cookies in the format of CookieManager.Cookie inside an ArrayList for
- * a given domain
- *
- * @return ArrayList<Cookie> If nothing is found, return an empty list.
- */
- ArrayList<Cookie> getCookiesForDomain(String domain) {
- ArrayList<Cookie> list = new ArrayList<Cookie>();
- if (domain == null || mDatabase == null) {
- return list;
- }
-
- synchronized (mCookieLock) {
- final String[] columns = new String[] {
- ID_COL, COOKIES_DOMAIN_COL, COOKIES_PATH_COL,
- COOKIES_NAME_COL, COOKIES_VALUE_COL, COOKIES_EXPIRES_COL,
- COOKIES_SECURE_COL
- };
- final String selection = "(" + COOKIES_DOMAIN_COL
- + " GLOB '*' || ?)";
- Cursor cursor = mDatabase.query(mTableNames[TABLE_COOKIES_ID],
- columns, selection, new String[] { domain }, null, null,
- null);
- if (cursor.moveToFirst()) {
- int domainCol = cursor.getColumnIndex(COOKIES_DOMAIN_COL);
- int pathCol = cursor.getColumnIndex(COOKIES_PATH_COL);
- int nameCol = cursor.getColumnIndex(COOKIES_NAME_COL);
- int valueCol = cursor.getColumnIndex(COOKIES_VALUE_COL);
- int expiresCol = cursor.getColumnIndex(COOKIES_EXPIRES_COL);
- int secureCol = cursor.getColumnIndex(COOKIES_SECURE_COL);
- do {
- Cookie cookie = new Cookie();
- cookie.domain = cursor.getString(domainCol);
- cookie.path = cursor.getString(pathCol);
- cookie.name = cursor.getString(nameCol);
- cookie.value = cursor.getString(valueCol);
- if (cursor.isNull(expiresCol)) {
- cookie.expires = -1;
- } else {
- cookie.expires = cursor.getLong(expiresCol);
- }
- cookie.secure = cursor.getShort(secureCol) != 0;
- cookie.mode = Cookie.MODE_NORMAL;
- list.add(cookie);
- } while (cursor.moveToNext());
- }
- cursor.close();
- return list;
- }
- }
-
- /**
- * Delete cookies which matches (domain, path, name).
- *
- * @param domain If it is null, nothing happens.
- * @param path If it is null, all the cookies match (domain) will be
- * deleted.
- * @param name If it is null, all the cookies match (domain, path) will be
- * deleted.
- */
- void deleteCookies(String domain, String path, String name) {
- if (domain == null || mDatabase == null) {
- return;
- }
-
- synchronized (mCookieLock) {
- final String where = "(" + COOKIES_DOMAIN_COL + " == ?) AND ("
- + COOKIES_PATH_COL + " == ?) AND (" + COOKIES_NAME_COL
- + " == ?)";
- mDatabase.delete(mTableNames[TABLE_COOKIES_ID], where,
- new String[] { domain, path, name });
- }
- }
-
- /**
- * Add a cookie to the database
- *
- * @param cookie
- */
- void addCookie(Cookie cookie) {
- if (cookie.domain == null || cookie.path == null || cookie.name == null
- || mDatabase == null) {
- return;
- }
-
- synchronized (mCookieLock) {
- ContentValues cookieVal = new ContentValues();
- cookieVal.put(COOKIES_DOMAIN_COL, cookie.domain);
- cookieVal.put(COOKIES_PATH_COL, cookie.path);
- cookieVal.put(COOKIES_NAME_COL, cookie.name);
- cookieVal.put(COOKIES_VALUE_COL, cookie.value);
- if (cookie.expires != -1) {
- cookieVal.put(COOKIES_EXPIRES_COL, cookie.expires);
- }
- cookieVal.put(COOKIES_SECURE_COL, cookie.secure);
- mDatabase.insert(mTableNames[TABLE_COOKIES_ID], null, cookieVal);
- }
- }
-
- /**
- * Whether there is any cookies in the database
- *
- * @return TRUE if there is cookie.
- */
- boolean hasCookies() {
- synchronized (mCookieLock) {
- return hasEntries(TABLE_COOKIES_ID);
- }
- }
-
- /**
- * Clear cookie database
- */
- void clearCookies() {
- if (mDatabase == null) {
- return;
- }
-
- synchronized (mCookieLock) {
- mDatabase.delete(mTableNames[TABLE_COOKIES_ID], null, null);
- }
- }
-
- /**
- * Clear session cookies, which means cookie doesn't have EXPIRES.
- */
- void clearSessionCookies() {
- if (mDatabase == null) {
- return;
- }
-
- final String sessionExpired = COOKIES_EXPIRES_COL + " ISNULL";
- synchronized (mCookieLock) {
- mDatabase.delete(mTableNames[TABLE_COOKIES_ID], sessionExpired,
- null);
- }
- }
-
- /**
- * Clear expired cookies
- *
- * @param now Time for now
- */
- void clearExpiredCookies(long now) {
- if (mDatabase == null) {
- return;
- }
-
- final String expires = COOKIES_EXPIRES_COL + " <= ?";
- synchronized (mCookieLock) {
- mDatabase.delete(mTableNames[TABLE_COOKIES_ID], expires,
- new String[] { Long.toString(now) });
- }
- }
-
- //
- // cache functions, can only be called from WebCoreThread
- //
-
- boolean startCacheTransaction() {
- if (++mCacheTransactionRefcount == 1) {
- mCacheDatabase.beginTransaction();
- return true;
- }
- return false;
- }
-
- boolean endCacheTransaction() {
- if (--mCacheTransactionRefcount == 0) {
- try {
- mCacheDatabase.setTransactionSuccessful();
- } finally {
- mCacheDatabase.endTransaction();
- }
- return true;
- }
- return false;
- }
-
- /**
- * Get a cache item.
- *
- * @param url The url
- * @return CacheResult The CacheManager.CacheResult
- */
- CacheResult getCache(String url) {
- if (url == null || mCacheDatabase == null) {
- return null;
- }
-
- Cursor cursor = mCacheDatabase.rawQuery("SELECT filepath, lastmodify, etag, expires, "
- + "mimetype, encoding, httpstatus, location, contentlength "
- + "FROM cache WHERE url = ?",
- new String[] { url });
-
- try {
- if (cursor.moveToFirst()) {
- CacheResult ret = new CacheResult();
- ret.localPath = cursor.getString(0);
- ret.lastModified = cursor.getString(1);
- ret.etag = cursor.getString(2);
- ret.expires = cursor.getLong(3);
- ret.mimeType = cursor.getString(4);
- ret.encoding = cursor.getString(5);
- ret.httpStatusCode = cursor.getInt(6);
- ret.location = cursor.getString(7);
- ret.contentLength = cursor.getLong(8);
- return ret;
- }
- } finally {
- if (cursor != null) cursor.close();
- }
- return null;
- }
-
- /**
- * Remove a cache item.
- *
- * @param url The url
- */
- void removeCache(String url) {
- if (url == null || mCacheDatabase == null) {
- return;
- }
-
- mCacheDatabase.execSQL("DELETE FROM cache WHERE url = ?", new String[] { url });
- }
-
- /**
- * Add or update a cache. CACHE_URL_COL is unique in the table.
- *
- * @param url The url
- * @param c The CacheManager.CacheResult
- */
- void addCache(String url, CacheResult c) {
- if (url == null || mCacheDatabase == null) {
- return;
- }
-
- mCacheInserter.prepareForInsert();
- mCacheInserter.bind(mCacheUrlColIndex, url);
- mCacheInserter.bind(mCacheFilePathColIndex, c.localPath);
- mCacheInserter.bind(mCacheLastModifyColIndex, c.lastModified);
- mCacheInserter.bind(mCacheETagColIndex, c.etag);
- mCacheInserter.bind(mCacheExpiresColIndex, c.expires);
- mCacheInserter.bind(mCacheMimeTypeColIndex, c.mimeType);
- mCacheInserter.bind(mCacheEncodingColIndex, c.encoding);
- mCacheInserter.bind(mCacheHttpStatusColIndex, c.httpStatusCode);
- mCacheInserter.bind(mCacheLocationColIndex, c.location);
- mCacheInserter.bind(mCacheContentLengthColIndex, c.contentLength);
- mCacheInserter.execute();
- }
-
- /**
- * Clear cache database
- */
- void clearCache() {
- if (mCacheDatabase == null) {
- return;
- }
-
- mCacheDatabase.delete("cache", null, null);
- }
-
- boolean hasCache() {
- if (mCacheDatabase == null) {
- return false;
- }
-
- Cursor cursor = mCacheDatabase.query("cache", ID_PROJECTION,
- null, null, null, null, null);
- boolean ret = cursor.moveToFirst() == true;
- cursor.close();
- return ret;
- }
-
- long getCacheTotalSize() {
- long size = 0;
- Cursor cursor = mCacheDatabase.rawQuery(
- "SELECT SUM(contentlength) as sum FROM cache", null);
- if (cursor.moveToFirst()) {
- size = cursor.getLong(0);
- }
- cursor.close();
- return size;
- }
-
- ArrayList<String> trimCache(long amount) {
- ArrayList<String> pathList = new ArrayList<String>(100);
- Cursor cursor = mCacheDatabase.rawQuery(
- "SELECT contentlength, filepath FROM cache ORDER BY expires ASC",
- null);
- if (cursor.moveToFirst()) {
- int batchSize = 100;
- StringBuilder pathStr = new StringBuilder(20 + 16 * batchSize);
- pathStr.append("DELETE FROM cache WHERE filepath IN (?");
- for (int i = 1; i < batchSize; i++) {
- pathStr.append(", ?");
- }
- pathStr.append(")");
- SQLiteStatement statement = mCacheDatabase.compileStatement(pathStr
- .toString());
- // as bindString() uses 1-based index, initialize index to 1
- int index = 1;
- do {
- long length = cursor.getLong(0);
- if (length == 0) {
- continue;
- }
- amount -= length;
- String filePath = cursor.getString(1);
- statement.bindString(index, filePath);
- pathList.add(filePath);
- if (index++ == batchSize) {
- statement.execute();
- statement.clearBindings();
- index = 1;
- }
- } while (cursor.moveToNext() && amount > 0);
- if (index > 1) {
- // there may be old bindings from the previous statement if
- // index is less than batchSize, which is Ok.
- statement.execute();
- }
- statement.close();
- }
- cursor.close();
- return pathList;
- }
-
- //
- // password functions
- //
-
- /**
- * Set password. Tuple (PASSWORD_HOST_COL, PASSWORD_USERNAME_COL) is unique.
- *
- * @param schemePlusHost The scheme and host for the password
- * @param username The username for the password. If it is null, it means
- * password can't be saved.
- * @param password The password
- */
- void setUsernamePassword(String schemePlusHost, String username,
- String password) {
- if (schemePlusHost == null || mDatabase == null) {
- return;
- }
-
- synchronized (mPasswordLock) {
- final ContentValues c = new ContentValues();
- c.put(PASSWORD_HOST_COL, schemePlusHost);
- c.put(PASSWORD_USERNAME_COL, username);
- c.put(PASSWORD_PASSWORD_COL, password);
- mDatabase.insert(mTableNames[TABLE_PASSWORD_ID], PASSWORD_HOST_COL,
- c);
- }
- }
-
- /**
- * Retrieve the username and password for a given host
- *
- * @param schemePlusHost The scheme and host which passwords applies to
- * @return String[] if found, String[0] is username, which can be null and
- * String[1] is password. Return null if it can't find anything.
- */
- String[] getUsernamePassword(String schemePlusHost) {
- if (schemePlusHost == null || mDatabase == null) {
- return null;
- }
-
- final String[] columns = new String[] {
- PASSWORD_USERNAME_COL, PASSWORD_PASSWORD_COL
- };
- final String selection = "(" + PASSWORD_HOST_COL + " == ?)";
- synchronized (mPasswordLock) {
- String[] ret = null;
- Cursor cursor = mDatabase.query(mTableNames[TABLE_PASSWORD_ID],
- columns, selection, new String[] { schemePlusHost }, null,
- null, null);
- if (cursor.moveToFirst()) {
- ret = new String[2];
- ret[0] = cursor.getString(
- cursor.getColumnIndex(PASSWORD_USERNAME_COL));
- ret[1] = cursor.getString(
- cursor.getColumnIndex(PASSWORD_PASSWORD_COL));
- }
- cursor.close();
- return ret;
- }
- }
-
- /**
- * Find out if there are any passwords saved.
- *
- * @return TRUE if there is passwords saved
- */
- public boolean hasUsernamePassword() {
- synchronized (mPasswordLock) {
- return hasEntries(TABLE_PASSWORD_ID);
- }
- }
-
- /**
- * Clear password database
- */
- public void clearUsernamePassword() {
- if (mDatabase == null) {
- return;
- }
-
- synchronized (mPasswordLock) {
- mDatabase.delete(mTableNames[TABLE_PASSWORD_ID], null, null);
- }
- }
-
- //
- // http authentication password functions
- //
-
- /**
- * Set HTTP authentication password. Tuple (HTTPAUTH_HOST_COL,
- * HTTPAUTH_REALM_COL, HTTPAUTH_USERNAME_COL) is unique.
- *
- * @param host The host for the password
- * @param realm The realm for the password
- * @param username The username for the password. If it is null, it means
- * password can't be saved.
- * @param password The password
- */
- void setHttpAuthUsernamePassword(String host, String realm, String username,
- String password) {
- if (host == null || realm == null || mDatabase == null) {
- return;
- }
-
- synchronized (mHttpAuthLock) {
- final ContentValues c = new ContentValues();
- c.put(HTTPAUTH_HOST_COL, host);
- c.put(HTTPAUTH_REALM_COL, realm);
- c.put(HTTPAUTH_USERNAME_COL, username);
- c.put(HTTPAUTH_PASSWORD_COL, password);
- mDatabase.insert(mTableNames[TABLE_HTTPAUTH_ID], HTTPAUTH_HOST_COL,
- c);
- }
- }
-
- /**
- * Retrieve the HTTP authentication username and password for a given
- * host+realm pair
- *
- * @param host The host the password applies to
- * @param realm The realm the password applies to
- * @return String[] if found, String[0] is username, which can be null and
- * String[1] is password. Return null if it can't find anything.
- */
- String[] getHttpAuthUsernamePassword(String host, String realm) {
- if (host == null || realm == null || mDatabase == null){
- return null;
- }
-
- final String[] columns = new String[] {
- HTTPAUTH_USERNAME_COL, HTTPAUTH_PASSWORD_COL
- };
- final String selection = "(" + HTTPAUTH_HOST_COL + " == ?) AND ("
- + HTTPAUTH_REALM_COL + " == ?)";
- synchronized (mHttpAuthLock) {
- String[] ret = null;
- Cursor cursor = mDatabase.query(mTableNames[TABLE_HTTPAUTH_ID],
- columns, selection, new String[] { host, realm }, null,
- null, null);
- if (cursor.moveToFirst()) {
- ret = new String[2];
- ret[0] = cursor.getString(
- cursor.getColumnIndex(HTTPAUTH_USERNAME_COL));
- ret[1] = cursor.getString(
- cursor.getColumnIndex(HTTPAUTH_PASSWORD_COL));
- }
- cursor.close();
- return ret;
- }
- }
-
- /**
- * Find out if there are any HTTP authentication passwords saved.
- *
- * @return TRUE if there are passwords saved
- */
- public boolean hasHttpAuthUsernamePassword() {
- synchronized (mHttpAuthLock) {
- return hasEntries(TABLE_HTTPAUTH_ID);
- }
- }
-
- /**
- * Clear HTTP authentication password database
- */
- public void clearHttpAuthUsernamePassword() {
- if (mDatabase == null) {
- return;
- }
-
- synchronized (mHttpAuthLock) {
- mDatabase.delete(mTableNames[TABLE_HTTPAUTH_ID], null, null);
- }
- }
-
- //
- // form data functions
- //
-
- /**
- * Set form data for a site. Tuple (FORMDATA_URLID_COL, FORMDATA_NAME_COL,
- * FORMDATA_VALUE_COL) is unique
- *
- * @param url The url of the site
- * @param formdata The form data in HashMap
- */
- void setFormData(String url, HashMap<String, String> formdata) {
- if (url == null || formdata == null || mDatabase == null) {
- return;
- }
-
- final String selection = "(" + FORMURL_URL_COL + " == ?)";
- synchronized (mFormLock) {
- long urlid = -1;
- Cursor cursor = mDatabase.query(mTableNames[TABLE_FORMURL_ID],
- ID_PROJECTION, selection, new String[] { url }, null, null,
- null);
- if (cursor.moveToFirst()) {
- urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
- } else {
- ContentValues c = new ContentValues();
- c.put(FORMURL_URL_COL, url);
- urlid = mDatabase.insert(
- mTableNames[TABLE_FORMURL_ID], null, c);
- }
- cursor.close();
- if (urlid >= 0) {
- Set<Entry<String, String>> set = formdata.entrySet();
- Iterator<Entry<String, String>> iter = set.iterator();
- ContentValues map = new ContentValues();
- map.put(FORMDATA_URLID_COL, urlid);
- while (iter.hasNext()) {
- Entry<String, String> entry = iter.next();
- map.put(FORMDATA_NAME_COL, entry.getKey());
- map.put(FORMDATA_VALUE_COL, entry.getValue());
- mDatabase.insert(mTableNames[TABLE_FORMDATA_ID], null, map);
- }
- }
- }
- }
-
- /**
- * Get all the values for a form entry with "name" in a given site
- *
- * @param url The url of the site
- * @param name The name of the form entry
- * @return A list of values. Return empty list if nothing is found.
- */
- ArrayList<String> getFormData(String url, String name) {
- ArrayList<String> values = new ArrayList<String>();
- if (url == null || name == null || mDatabase == null) {
- return values;
- }
-
- final String urlSelection = "(" + FORMURL_URL_COL + " == ?)";
- final String dataSelection = "(" + FORMDATA_URLID_COL + " == ?) AND ("
- + FORMDATA_NAME_COL + " == ?)";
- synchronized (mFormLock) {
- Cursor cursor = mDatabase.query(mTableNames[TABLE_FORMURL_ID],
- ID_PROJECTION, urlSelection, new String[] { url }, null,
- null, null);
- if (cursor.moveToFirst()) {
- long urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
- Cursor dataCursor = mDatabase.query(
- mTableNames[TABLE_FORMDATA_ID],
- new String[] { ID_COL, FORMDATA_VALUE_COL },
- dataSelection,
- new String[] { Long.toString(urlid), name }, null,
- null, null);
- if (dataCursor.moveToFirst()) {
- int valueCol =
- dataCursor.getColumnIndex(FORMDATA_VALUE_COL);
- do {
- values.add(dataCursor.getString(valueCol));
- } while (dataCursor.moveToNext());
- }
- dataCursor.close();
- }
- cursor.close();
- return values;
- }
- }
-
- /**
- * Find out if there is form data saved.
- *
- * @return TRUE if there is form data in the database
- */
- public boolean hasFormData() {
- synchronized (mFormLock) {
- return hasEntries(TABLE_FORMURL_ID);
- }
- }
-
- /**
- * Clear form database
- */
- public void clearFormData() {
- if (mDatabase == null) {
- return;
- }
-
- synchronized (mFormLock) {
- mDatabase.delete(mTableNames[TABLE_FORMURL_ID], null, null);
- mDatabase.delete(mTableNames[TABLE_FORMDATA_ID], null, null);
- }
- }
-}
diff --git a/core/java/android/webkit/gears/AndroidGpsLocationProvider.java b/core/java/android/webkit/gears/AndroidGpsLocationProvider.java
deleted file mode 100644
index 3646042..0000000
--- a/core/java/android/webkit/gears/AndroidGpsLocationProvider.java
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2008, The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// 3. Neither the name of Google Inc. nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.content.Context;
-import android.location.Location;
-import android.location.LocationListener;
-import android.location.LocationManager;
-import android.location.LocationProvider;
-import android.os.Bundle;
-import android.util.Log;
-import android.webkit.WebView;
-
-/**
- * GPS provider implementation for Android.
- */
-public final class AndroidGpsLocationProvider implements LocationListener {
- /**
- * Logging tag
- */
- private static final String TAG = "Gears-J-GpsProvider";
- /**
- * Our location manager instance.
- */
- private LocationManager locationManager;
- /**
- * The native object ID.
- */
- private long nativeObject;
-
- public AndroidGpsLocationProvider(WebView webview, long object) {
- nativeObject = object;
- locationManager = (LocationManager) webview.getContext().getSystemService(
- Context.LOCATION_SERVICE);
- if (locationManager == null) {
- Log.e(TAG,
- "AndroidGpsLocationProvider: could not get location manager.");
- throw new NullPointerException(
- "AndroidGpsLocationProvider: locationManager is null.");
- }
- // Register for location updates.
- try {
- locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
- this);
- } catch (IllegalArgumentException ex) {
- Log.e(TAG,
- "AndroidLocationGpsProvider: could not register for updates: " + ex);
- throw ex;
- } catch (SecurityException ex) {
- Log.e(TAG,
- "AndroidGpsLocationProvider: not allowed to register for update: "
- + ex);
- throw ex;
- }
- }
-
- /**
- * Called when the provider is no longer needed.
- */
- public void shutdown() {
- locationManager.removeUpdates(this);
- Log.i(TAG, "GPS provider closed.");
- }
-
- /**
- * Called when the location has changed.
- * @param location The new location, as a Location object.
- */
- public void onLocationChanged(Location location) {
- Log.i(TAG, "Location changed: " + location);
- nativeLocationChanged(location, nativeObject);
- }
-
- /**
- * Called when the provider status changes.
- *
- * @param provider the name of the location provider associated with this
- * update.
- * @param status {@link LocationProvider#OUT_OF_SERVICE} if the
- * provider is out of service, and this is not expected to change in the
- * near future; {@link LocationProvider#TEMPORARILY_UNAVAILABLE} if
- * the provider is temporarily unavailable but is expected to be available
- * shortly; and {@link LocationProvider#AVAILABLE} if the
- * provider is currently available.
- * @param extras an optional Bundle which will contain provider specific
- * status variables (such as number of satellites).
- */
- public void onStatusChanged(String provider, int status, Bundle extras) {
- Log.i(TAG, "Provider " + provider + " status changed to " + status);
- if (status == LocationProvider.OUT_OF_SERVICE ||
- status == LocationProvider.TEMPORARILY_UNAVAILABLE) {
- nativeProviderError(false, nativeObject);
- }
- }
-
- /**
- * Called when the provider is enabled.
- *
- * @param provider the name of the location provider that is now enabled.
- */
- public void onProviderEnabled(String provider) {
- Log.i(TAG, "Provider " + provider + " enabled.");
- // No need to notify the native side. It's enough to start sending
- // valid position fixes again.
- }
-
- /**
- * Called when the provider is disabled.
- *
- * @param provider the name of the location provider that is now disabled.
- */
- public void onProviderDisabled(String provider) {
- Log.i(TAG, "Provider " + provider + " disabled.");
- nativeProviderError(true, nativeObject);
- }
-
- /**
- * The native method called when a new location is available.
- * @param location is the new Location instance to pass to the native side.
- * @param nativeObject is a pointer to the corresponding
- * AndroidGpsLocationProvider C++ instance.
- */
- private native void nativeLocationChanged(Location location, long object);
-
- /**
- * The native method called when there is a GPS provder error.
- * @param isDisabled is true when the error signifies the fact that the GPS
- * HW is disabled. For other errors, this param is always false.
- * @param nativeObject is a pointer to the corresponding
- * AndroidGpsLocationProvider C++ instance.
- */
- private native void nativeProviderError(boolean isDisabled, long object);
-}
diff --git a/core/java/android/webkit/gears/AndroidRadioDataProvider.java b/core/java/android/webkit/gears/AndroidRadioDataProvider.java
deleted file mode 100644
index c920d45..0000000
--- a/core/java/android/webkit/gears/AndroidRadioDataProvider.java
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright 2008, The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// 3. Neither the name of Google Inc. nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.content.Context;
-import android.telephony.CellLocation;
-import android.telephony.ServiceState;
-import android.telephony.gsm.GsmCellLocation;
-import android.telephony.PhoneStateListener;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-import android.webkit.WebView;
-
-/**
- * Radio data provider implementation for Android.
- */
-public final class AndroidRadioDataProvider extends PhoneStateListener {
-
- /** Logging tag */
- private static final String TAG = "Gears-J-RadioProvider";
-
- /** Network types */
- private static final int RADIO_TYPE_UNKNOWN = 0;
- private static final int RADIO_TYPE_GSM = 1;
- private static final int RADIO_TYPE_WCDMA = 2;
-
- /** Simple container for radio data */
- public static final class RadioData {
- public int cellId = -1;
- public int locationAreaCode = -1;
- public int signalStrength = -1;
- public int mobileCountryCode = -1;
- public int mobileNetworkCode = -1;
- public int homeMobileCountryCode = -1;
- public int homeMobileNetworkCode = -1;
- public int radioType = RADIO_TYPE_UNKNOWN;
- public String carrierName;
-
- /**
- * Constructs radioData object from the given telephony data.
- * @param telephonyManager contains the TelephonyManager instance.
- * @param cellLocation contains information about the current GSM cell.
- * @param signalStrength is the strength of the network signal.
- * @param serviceState contains information about the network service.
- * @return a new RadioData object populated with the currently
- * available network information or null if there isn't
- * enough information.
- */
- public static RadioData getInstance(TelephonyManager telephonyManager,
- CellLocation cellLocation, int signalStrength,
- ServiceState serviceState) {
-
- if (!(cellLocation instanceof GsmCellLocation)) {
- // This also covers the case when cellLocation is null.
- // When that happens, we do not bother creating a
- // RadioData instance.
- return null;
- }
-
- RadioData radioData = new RadioData();
- GsmCellLocation gsmCellLocation = (GsmCellLocation) cellLocation;
-
- // Extract the cell id, LAC, and signal strength.
- radioData.cellId = gsmCellLocation.getCid();
- radioData.locationAreaCode = gsmCellLocation.getLac();
- radioData.signalStrength = signalStrength;
-
- // Extract the home MCC and home MNC.
- String operator = telephonyManager.getSimOperator();
- radioData.setMobileCodes(operator, true);
-
- if (serviceState != null) {
- // Extract the carrier name.
- radioData.carrierName = serviceState.getOperatorAlphaLong();
-
- // Extract the MCC and MNC.
- operator = serviceState.getOperatorNumeric();
- radioData.setMobileCodes(operator, false);
- }
-
- // Finally get the radio type.
- int type = telephonyManager.getNetworkType();
- if (type == TelephonyManager.NETWORK_TYPE_UMTS) {
- radioData.radioType = RADIO_TYPE_WCDMA;
- } else if (type == TelephonyManager.NETWORK_TYPE_GPRS
- || type == TelephonyManager.NETWORK_TYPE_EDGE) {
- radioData.radioType = RADIO_TYPE_GSM;
- }
-
- // Print out what we got.
- Log.i(TAG, "Got the following data:");
- Log.i(TAG, "CellId: " + radioData.cellId);
- Log.i(TAG, "LAC: " + radioData.locationAreaCode);
- Log.i(TAG, "MNC: " + radioData.mobileNetworkCode);
- Log.i(TAG, "MCC: " + radioData.mobileCountryCode);
- Log.i(TAG, "home MNC: " + radioData.homeMobileNetworkCode);
- Log.i(TAG, "home MCC: " + radioData.homeMobileCountryCode);
- Log.i(TAG, "Signal strength: " + radioData.signalStrength);
- Log.i(TAG, "Carrier: " + radioData.carrierName);
- Log.i(TAG, "Network type: " + radioData.radioType);
-
- return radioData;
- }
-
- private RadioData() {}
-
- /**
- * Parses a string containing a mobile country code and a mobile
- * network code and sets the corresponding member variables.
- * @param codes is the string to parse.
- * @param homeValues flags whether the codes are for the home operator.
- */
- private void setMobileCodes(String codes, boolean homeValues) {
- if (codes != null) {
- try {
- // The operator numeric format is 3 digit country code plus 2 or
- // 3 digit network code.
- int mcc = Integer.parseInt(codes.substring(0, 3));
- int mnc = Integer.parseInt(codes.substring(3));
- if (homeValues) {
- homeMobileCountryCode = mcc;
- homeMobileNetworkCode = mnc;
- } else {
- mobileCountryCode = mcc;
- mobileNetworkCode = mnc;
- }
- } catch (IndexOutOfBoundsException ex) {
- Log.e(
- TAG,
- "AndroidRadioDataProvider: Invalid operator numeric data: " + ex);
- } catch (NumberFormatException ex) {
- Log.e(
- TAG,
- "AndroidRadioDataProvider: Operator numeric format error: " + ex);
- }
- }
- }
- };
-
- /** The native object ID */
- private long nativeObject;
-
- /** The last known cellLocation */
- private CellLocation cellLocation = null;
-
- /** The last known signal strength */
- private int signalStrength = -1;
-
- /** The last known serviceState */
- private ServiceState serviceState = null;
-
- /**
- * Our TelephonyManager instance.
- */
- private TelephonyManager telephonyManager;
-
- /**
- * Public constructor. Uses the webview to get the Context object.
- */
- public AndroidRadioDataProvider(WebView webview, long object) {
- super();
- nativeObject = object;
- telephonyManager = (TelephonyManager) webview.getContext().getSystemService(
- Context.TELEPHONY_SERVICE);
- if (telephonyManager == null) {
- Log.e(TAG,
- "AndroidRadioDataProvider: could not get tepephony manager.");
- throw new NullPointerException(
- "AndroidRadioDataProvider: telephonyManager is null.");
- }
-
- // Register for cell id, signal strength and service state changed
- // notifications.
- telephonyManager.listen(this, PhoneStateListener.LISTEN_CELL_LOCATION
- | PhoneStateListener.LISTEN_SIGNAL_STRENGTH
- | PhoneStateListener.LISTEN_SERVICE_STATE);
- }
-
- /**
- * Should be called when the provider is no longer needed.
- */
- public void shutdown() {
- telephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
- Log.i(TAG, "AndroidRadioDataProvider shutdown.");
- }
-
- @Override
- public void onServiceStateChanged(ServiceState state) {
- serviceState = state;
- notifyListeners();
- }
-
- @Override
- public void onSignalStrengthChanged(int asu) {
- signalStrength = asu;
- notifyListeners();
- }
-
- @Override
- public void onCellLocationChanged(CellLocation location) {
- cellLocation = location;
- notifyListeners();
- }
-
- private void notifyListeners() {
- RadioData radioData = RadioData.getInstance(telephonyManager, cellLocation,
- signalStrength, serviceState);
- if (radioData != null) {
- onUpdateAvailable(radioData, nativeObject);
- }
- }
-
- /**
- * The native method called when new radio data is available.
- * @param radioData is the RadioData instance to pass to the native side.
- * @param nativeObject is a pointer to the corresponding
- * AndroidRadioDataProvider C++ instance.
- */
- private static native void onUpdateAvailable(
- RadioData radioData, long nativeObject);
-}
diff --git a/core/java/android/webkit/gears/AndroidWifiDataProvider.java b/core/java/android/webkit/gears/AndroidWifiDataProvider.java
deleted file mode 100644
index 7379f59..0000000
--- a/core/java/android/webkit/gears/AndroidWifiDataProvider.java
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2008, Google Inc.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// 3. Neither the name of Google Inc. nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Config;
-import android.util.Log;
-import android.webkit.WebView;
-import java.util.List;
-
-/**
- * WiFi data provider implementation for Android.
- * {@hide}
- */
-public final class AndroidWifiDataProvider extends BroadcastReceiver {
- /**
- * Logging tag
- */
- private static final String TAG = "Gears-J-WifiProvider";
- /**
- * Our Wifi manager instance.
- */
- private WifiManager mWifiManager;
- /**
- * The native object ID.
- */
- private long mNativeObject;
- /**
- * The Context instance.
- */
- private Context mContext;
-
- /**
- * Constructs a instance of this class and registers for wifi scan
- * updates. Note that this constructor must be called on a Looper
- * thread. Suitable threads can be created on the native side using
- * the AndroidLooperThread C++ class.
- */
- public AndroidWifiDataProvider(WebView webview, long object) {
- mNativeObject = object;
- mContext = webview.getContext();
- mWifiManager =
- (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
- if (mWifiManager == null) {
- Log.e(TAG,
- "AndroidWifiDataProvider: could not get location manager.");
- throw new NullPointerException(
- "AndroidWifiDataProvider: locationManager is null.");
- }
-
- // Create a Handler that identifies the message loop associated
- // with the current thread. Note that it is not necessary to
- // override handleMessage() at all since the Intent
- // ReceiverDispatcher (see the ActivityThread class) only uses
- // this handler to post a Runnable to this thread's loop.
- Handler handler = new Handler(Looper.myLooper());
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(mWifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
- mContext.registerReceiver(this, filter, null, handler);
-
- // Get the last scan results and pass them to the native side.
- // We can't just invoke the callback here, so we queue a message
- // to this thread's loop.
- handler.post(new Runnable() {
- public void run() {
- onUpdateAvailable(mWifiManager.getScanResults(), mNativeObject);
- }
- });
- }
-
- /**
- * Called when the provider is no longer needed.
- */
- public void shutdown() {
- mContext.unregisterReceiver(this);
- if (Config.LOGV) {
- Log.v(TAG, "Wifi provider closed.");
- }
- }
-
- /**
- * This method is called when the AndroidWifiDataProvider is receiving an
- * Intent broadcast.
- * @param context The Context in which the receiver is running.
- * @param intent The Intent being received.
- */
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(
- mWifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
- if (Config.LOGV) {
- Log.v(TAG, "Wifi scan resulst available");
- }
- onUpdateAvailable(mWifiManager.getScanResults(), mNativeObject);
- }
- }
-
- /**
- * The native method called when new wifi data is available.
- * @param scanResults is a list of ScanResults to pass to the native side.
- * @param nativeObject is a pointer to the corresponding
- * AndroidWifiDataProvider C++ instance.
- */
- private static native void onUpdateAvailable(
- List<ScanResult> scanResults, long nativeObject);
-}
diff --git a/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java b/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java
deleted file mode 100644
index 0569255..0000000
--- a/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java
+++ /dev/null
@@ -1,1122 +0,0 @@
-// Copyright 2008, The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// 3. Neither the name of Google Inc. nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.net.http.Headers;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.util.Config;
-import android.util.Log;
-import android.webkit.CacheManager;
-import android.webkit.CacheManager.CacheResult;
-import android.webkit.CookieManager;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.IOException;
-import java.lang.StringBuilder;
-import java.util.Date;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Iterator;
-
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.client.params.HttpClientParams;
-import org.apache.http.params.HttpParams;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpProtocolParams;
-import org.apache.http.HttpResponse;
-import org.apache.http.entity.AbstractHttpEntity;
-import org.apache.http.client.*;
-import org.apache.http.client.methods.*;
-import org.apache.http.impl.client.AbstractHttpClient;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
-import org.apache.http.conn.ssl.StrictHostnameVerifier;
-import org.apache.http.impl.cookie.DateUtils;
-import org.apache.http.util.CharArrayBuffer;
-
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Performs the underlying HTTP/HTTPS GET, POST, HEAD, PUT, DELETE requests.
- * <p> These are performed synchronously (blocking). The caller should
- * ensure that it is in a background thread if asynchronous behavior
- * is required. All data is pushed, so there is no need for JNI native
- * callbacks.
- * <p> This uses Apache's HttpClient framework to perform most
- * of the underlying network activity. The Android brower's cache,
- * android.webkit.CacheManager, is also used when caching is enabled,
- * and updated with new data. The android.webkit.CookieManager is also
- * queried and updated as necessary.
- * <p> The public interface is designed to be called by native code
- * through JNI, and to simplify coding none of the public methods will
- * surface a checked exception. Unchecked exceptions may still be
- * raised but only if the system is in an ill state, such as out of
- * memory.
- * <p> TODO: This isn't plumbed into LocalServer yet. Mutually
- * dependent on LocalServer - will attach the two together once both
- * are submitted.
- */
-public final class ApacheHttpRequestAndroid {
- /** Debug logging tag. */
- private static final String LOG_TAG = "Gears-J";
- /** HTTP response header line endings are CR-LF style. */
- private static final String HTTP_LINE_ENDING = "\r\n";
- /** Safe MIME type to use whenever it isn't specified. */
- private static final String DEFAULT_MIME_TYPE = "text/plain";
- /** Case-sensitive header keys */
- public static final String KEY_CONTENT_LENGTH = "Content-Length";
- public static final String KEY_EXPIRES = "Expires";
- public static final String KEY_LAST_MODIFIED = "Last-Modified";
- public static final String KEY_ETAG = "ETag";
- public static final String KEY_LOCATION = "Location";
- public static final String KEY_CONTENT_TYPE = "Content-Type";
- /** Number of bytes to send and receive on the HTTP connection in
- * one go. */
- private static final int BUFFER_SIZE = 4096;
-
- /** The first element of the String[] value in a headers map is the
- * unmodified (case-sensitive) key. */
- public static final int HEADERS_MAP_INDEX_KEY = 0;
- /** The second element of the String[] value in a headers map is the
- * associated value. */
- public static final int HEADERS_MAP_INDEX_VALUE = 1;
-
- /** Request headers, as key -> value map. */
- // TODO: replace this design by a simpler one (the C++ side has to
- // be modified too), where we do not store both the original header
- // and the lowercase one.
- private Map<String, String[]> mRequestHeaders =
- new HashMap<String, String[]>();
- /** Response headers, as a lowercase key -> value map. */
- private Map<String, String[]> mResponseHeaders =
- new HashMap<String, String[]>();
- /** The URL used for createCacheResult() */
- private String mCacheResultUrl;
- /** CacheResult being saved into, if inserting a new cache entry. */
- private CacheResult mCacheResult;
- /** Initialized by initChildThread(). Used to target abort(). */
- private Thread mBridgeThread;
-
- /** Our HttpClient */
- private AbstractHttpClient mClient;
- /** The HttpMethod associated with this request */
- private HttpRequestBase mMethod;
- /** The complete response line e.g "HTTP/1.0 200 OK" */
- private String mResponseLine;
- /** HTTP body stream, setup after connection. */
- private InputStream mBodyInputStream;
-
- /** HTTP Response Entity */
- private HttpResponse mResponse;
-
- /** Post Entity, used to stream the request to the server */
- private StreamEntity mPostEntity = null;
- /** Content lenght, mandatory when using POST */
- private long mContentLength;
-
- /** The request executes in a parallel thread */
- private Thread mHttpThread = null;
- /** protect mHttpThread, if interrupt() is called concurrently */
- private Lock mHttpThreadLock = new ReentrantLock();
- /** Flag set to true when the request thread is joined */
- private boolean mConnectionFinished = false;
- /** Flag set to true by interrupt() and/or connection errors */
- private boolean mConnectionFailed = false;
- /** Lock protecting the access to mConnectionFailed */
- private Lock mConnectionFailedLock = new ReentrantLock();
-
- /** Lock on the loop in StreamEntity */
- private Lock mStreamingReadyLock = new ReentrantLock();
- /** Condition variable used to signal the loop is ready... */
- private Condition mStreamingReady = mStreamingReadyLock.newCondition();
-
- /** Used to pass around the block of data POSTed */
- private Buffer mBuffer = new Buffer();
- /** Used to signal that the block of data has been written */
- private SignalConsumed mSignal = new SignalConsumed();
-
- // inner classes
-
- /**
- * Implements the http request
- */
- class Connection implements Runnable {
- public void run() {
- boolean problem = false;
- try {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "REQUEST : " + mMethod.getRequestLine());
- }
- mResponse = mClient.execute(mMethod);
- if (mResponse != null) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "response (status line): "
- + mResponse.getStatusLine());
- }
- mResponseLine = "" + mResponse.getStatusLine();
- } else {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "problem, response == null");
- }
- problem = true;
- }
- } catch (IOException e) {
- Log.e(LOG_TAG, "Connection IO exception ", e);
- problem = true;
- } catch (RuntimeException e) {
- Log.e(LOG_TAG, "Connection runtime exception ", e);
- problem = true;
- }
-
- if (!problem) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "Request complete ("
- + mMethod.getRequestLine() + ")");
- }
- } else {
- mConnectionFailedLock.lock();
- mConnectionFailed = true;
- mConnectionFailedLock.unlock();
- if (Config.LOGV) {
- Log.i(LOG_TAG, "Request FAILED ("
- + mMethod.getRequestLine() + ")");
- }
- // We abort the execution in order to shutdown and release
- // the underlying connection
- mMethod.abort();
- if (mPostEntity != null) {
- // If there is a post entity, we need to wake it up from
- // a potential deadlock
- mPostEntity.signalOutputStream();
- }
- }
- }
- }
-
- /**
- * simple buffer class implementing a producer/consumer model
- */
- class Buffer {
- private DataPacket mPacket;
- private boolean mEmpty = true;
- public synchronized void put(DataPacket packet) {
- while (!mEmpty) {
- try {
- wait();
- } catch (InterruptedException e) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "InterruptedException while putting " +
- "a DataPacket in the Buffer: " + e);
- }
- }
- }
- mPacket = packet;
- mEmpty = false;
- notify();
- }
- public synchronized DataPacket get() {
- while (mEmpty) {
- try {
- wait();
- } catch (InterruptedException e) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "InterruptedException while getting " +
- "a DataPacket in the Buffer: " + e);
- }
- }
- }
- mEmpty = true;
- notify();
- return mPacket;
- }
- }
-
- /**
- * utility class used to block until the packet is signaled as being
- * consumed
- */
- class SignalConsumed {
- private boolean mConsumed = false;
- public synchronized void waitUntilPacketConsumed() {
- while (!mConsumed) {
- try {
- wait();
- } catch (InterruptedException e) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "InterruptedException while waiting " +
- "until a DataPacket is consumed: " + e);
- }
- }
- }
- mConsumed = false;
- notify();
- }
- public synchronized void packetConsumed() {
- while (mConsumed) {
- try {
- wait();
- } catch (InterruptedException e) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "InterruptedException while indicating "
- + "that the DataPacket has been consumed: " + e);
- }
- }
- }
- mConsumed = true;
- notify();
- }
- }
-
- /**
- * Utility class encapsulating a packet of data
- */
- class DataPacket {
- private byte[] mContent;
- private int mLength;
- public DataPacket(byte[] content, int length) {
- mContent = content;
- mLength = length;
- }
- public byte[] getBytes() {
- return mContent;
- }
- public int getLength() {
- return mLength;
- }
- }
-
- /**
- * HttpEntity class to write the bytes received by the C++ thread
- * on the connection outputstream, in a streaming way.
- * This entity is executed in the request thread.
- * The writeTo() method is automatically called by the
- * HttpPost execution; upon reception, we loop while receiving
- * the data packets from the main thread, until completion
- * or error. When done, we flush the outputstream.
- * The main thread (sendPostData()) also blocks until the
- * outputstream is made available (or an error happens)
- */
- class StreamEntity implements HttpEntity {
- private OutputStream mOutputStream;
-
- // HttpEntity interface methods
-
- public boolean isRepeatable() {
- return false;
- }
-
- public boolean isChunked() {
- return false;
- }
-
- public long getContentLength() {
- return mContentLength;
- }
-
- public Header getContentType() {
- return null;
- }
-
- public Header getContentEncoding() {
- return null;
- }
-
- public InputStream getContent() throws IOException {
- return null;
- }
-
- public void writeTo(final OutputStream out) throws IOException {
- // We signal that the outputstream is available
- mStreamingReadyLock.lock();
- mOutputStream = out;
- mStreamingReady.signal();
- mStreamingReadyLock.unlock();
-
- // We then loop waiting on messages to process.
- boolean finished = false;
- while (!finished) {
- DataPacket packet = mBuffer.get();
- if (packet == null) {
- finished = true;
- } else {
- write(packet);
- }
- mSignal.packetConsumed();
- mConnectionFailedLock.lock();
- if (mConnectionFailed) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "stopping loop on error");
- }
- finished = true;
- }
- mConnectionFailedLock.unlock();
- }
- if (Config.LOGV) {
- Log.i(LOG_TAG, "flushing the outputstream...");
- }
- mOutputStream.flush();
- }
-
- public boolean isStreaming() {
- return true;
- }
-
- public void consumeContent() throws IOException {
- // Nothing to release
- }
-
- // local methods
-
- private void write(DataPacket packet) {
- try {
- if (mOutputStream == null) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "NO OUTPUT STREAM !!!");
- }
- return;
- }
- mOutputStream.write(packet.getBytes(), 0, packet.getLength());
- mOutputStream.flush();
- } catch (IOException e) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "exc: " + e);
- }
- mConnectionFailedLock.lock();
- mConnectionFailed = true;
- mConnectionFailedLock.unlock();
- }
- }
-
- public boolean isReady() {
- mStreamingReadyLock.lock();
- try {
- if (mOutputStream == null) {
- mStreamingReady.await();
- }
- } catch (InterruptedException e) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "InterruptedException in "
- + "StreamEntity::isReady() : ", e);
- }
- } finally {
- mStreamingReadyLock.unlock();
- }
- if (mOutputStream == null) {
- return false;
- }
- return true;
- }
-
- public void signalOutputStream() {
- mStreamingReadyLock.lock();
- mStreamingReady.signal();
- mStreamingReadyLock.unlock();
- }
- }
-
- /**
- * Initialize mBridgeThread using the TLS value of
- * Thread.currentThread(). Called on start up of the native child
- * thread.
- */
- public synchronized void initChildThread() {
- mBridgeThread = Thread.currentThread();
- }
-
- public void setContentLength(long length) {
- mContentLength = length;
- }
-
- /**
- * Analagous to the native-side HttpRequest::open() function. This
- * initializes an underlying HttpClient method, but does
- * not go to the wire. On success, this enables a call to send() to
- * initiate the transaction.
- *
- * @param method The HTTP method, e.g GET or POST.
- * @param url The URL to open.
- * @return True on success with a complete HTTP response.
- * False on failure.
- */
- public synchronized boolean open(String method, String url) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "open " + method + " " + url);
- }
- // Create the client
- if (mConnectionFailed) {
- // interrupt() could have been called even before open()
- return false;
- }
- mClient = new DefaultHttpClient();
- mClient.setHttpRequestRetryHandler(
- new DefaultHttpRequestRetryHandler(0, false));
- mBodyInputStream = null;
- mResponseLine = null;
- mResponseHeaders = null;
- mPostEntity = null;
- mHttpThread = null;
- mConnectionFailed = false;
- mConnectionFinished = false;
-
- // Create the method. We support everything that
- // Apache HttpClient supports, apart from TRACE.
- if ("GET".equalsIgnoreCase(method)) {
- mMethod = new HttpGet(url);
- } else if ("POST".equalsIgnoreCase(method)) {
- mMethod = new HttpPost(url);
- mPostEntity = new StreamEntity();
- ((HttpPost)mMethod).setEntity(mPostEntity);
- } else if ("HEAD".equalsIgnoreCase(method)) {
- mMethod = new HttpHead(url);
- } else if ("PUT".equalsIgnoreCase(method)) {
- mMethod = new HttpPut(url);
- } else if ("DELETE".equalsIgnoreCase(method)) {
- mMethod = new HttpDelete(url);
- } else {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "Method " + method + " not supported");
- }
- return false;
- }
- HttpParams params = mClient.getParams();
- // We handle the redirections C++-side
- HttpClientParams.setRedirecting(params, false);
- HttpProtocolParams.setUseExpectContinue(params, false);
- return true;
- }
-
- /**
- * We use this to start the connection thread (doing the method execute).
- * We usually always return true here, as the connection will run its
- * course in the thread.
- * We only return false if interrupted beforehand -- if a connection
- * problem happens, we will thus fail in either sendPostData() or
- * parseHeaders().
- */
- public synchronized boolean connectToRemote() {
- boolean ret = false;
- applyRequestHeaders();
- mConnectionFailedLock.lock();
- if (!mConnectionFailed) {
- mHttpThread = new Thread(new Connection());
- mHttpThread.start();
- }
- ret = mConnectionFailed;
- mConnectionFailedLock.unlock();
- return !ret;
- }
-
- /**
- * Get the complete response line of the HTTP request. Only valid on
- * completion of the transaction.
- * @return The complete HTTP response line, e.g "HTTP/1.0 200 OK".
- */
- public synchronized String getResponseLine() {
- return mResponseLine;
- }
-
- /**
- * Wait for the request thread completion
- * (unless already finished)
- */
- private void waitUntilConnectionFinished() {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "waitUntilConnectionFinished("
- + mConnectionFinished + ")");
- }
- if (!mConnectionFinished) {
- if (mHttpThread != null) {
- try {
- mHttpThread.join();
- mConnectionFinished = true;
- if (Config.LOGV) {
- Log.i(LOG_TAG, "http thread joined");
- }
- } catch (InterruptedException e) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "interrupted: " + e);
- }
- }
- } else {
- Log.e(LOG_TAG, ">>> Trying to join on mHttpThread " +
- "when it does not exist!");
- }
- }
- }
-
- // Headers handling
-
- /**
- * Receive all headers from the server and populate
- * mResponseHeaders.
- * @return True if headers are successfully received, False on
- * connection error.
- */
- public synchronized boolean parseHeaders() {
- mConnectionFailedLock.lock();
- if (mConnectionFailed) {
- mConnectionFailedLock.unlock();
- return false;
- }
- mConnectionFailedLock.unlock();
- waitUntilConnectionFinished();
- mResponseHeaders = new HashMap<String, String[]>();
- if (mResponse == null)
- return false;
-
- Header[] headers = mResponse.getAllHeaders();
- for (int i = 0; i < headers.length; i++) {
- Header header = headers[i];
- if (Config.LOGV) {
- Log.i(LOG_TAG, "header " + header.getName()
- + " -> " + header.getValue());
- }
- setResponseHeader(header.getName(), header.getValue());
- }
-
- return true;
- }
-
- /**
- * Set a header to send with the HTTP request. Will not take effect
- * on a transaction already in progress. The key is associated
- * case-insensitive, but stored case-sensitive.
- * @param name The name of the header, e.g "Set-Cookie".
- * @param value The value for this header, e.g "text/html".
- */
- public synchronized void setRequestHeader(String name, String value) {
- String[] mapValue = { name, value };
- if (Config.LOGV) {
- Log.i(LOG_TAG, "setRequestHeader: " + name + " => " + value);
- }
- if (name.equalsIgnoreCase(KEY_CONTENT_LENGTH)) {
- setContentLength(Long.parseLong(value));
- } else {
- mRequestHeaders.put(name.toLowerCase(), mapValue);
- }
- }
-
- /**
- * Returns the value associated with the given request header.
- * @param name The name of the request header, non-null, case-insensitive.
- * @return The value associated with the request header, or null if
- * not set, or error.
- */
- public synchronized String getRequestHeader(String name) {
- String[] value = mRequestHeaders.get(name.toLowerCase());
- if (value != null) {
- return value[HEADERS_MAP_INDEX_VALUE];
- } else {
- return null;
- }
- }
-
- private void applyRequestHeaders() {
- if (mMethod == null)
- return;
- Iterator<String[]> it = mRequestHeaders.values().iterator();
- while (it.hasNext()) {
- // Set the key case-sensitive.
- String[] entry = it.next();
- if (Config.LOGV) {
- Log.i(LOG_TAG, "apply header " + entry[HEADERS_MAP_INDEX_KEY] +
- " => " + entry[HEADERS_MAP_INDEX_VALUE]);
- }
- mMethod.setHeader(entry[HEADERS_MAP_INDEX_KEY],
- entry[HEADERS_MAP_INDEX_VALUE]);
- }
- }
-
- /**
- * Returns the value associated with the given response header.
- * @param name The name of the response header, non-null, case-insensitive.
- * @return The value associated with the response header, or null if
- * not set or error.
- */
- public synchronized String getResponseHeader(String name) {
- if (mResponseHeaders != null) {
- String[] value = mResponseHeaders.get(name.toLowerCase());
- if (value != null) {
- return value[HEADERS_MAP_INDEX_VALUE];
- } else {
- return null;
- }
- } else {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "getResponseHeader() called but "
- + "response not received");
- }
- return null;
- }
- }
-
- /**
- * Return all response headers, separated by CR-LF line endings, and
- * ending with a trailing blank line. This mimics the format of the
- * raw response header up to but not including the body.
- * @return A string containing the entire response header.
- */
- public synchronized String getAllResponseHeaders() {
- if (mResponseHeaders == null) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "getAllResponseHeaders() called but "
- + "response not received");
- }
- return null;
- }
- StringBuilder result = new StringBuilder();
- Iterator<String[]> it = mResponseHeaders.values().iterator();
- while (it.hasNext()) {
- String[] entry = it.next();
- // Output the "key: value" lines.
- result.append(entry[HEADERS_MAP_INDEX_KEY]);
- result.append(": ");
- result.append(entry[HEADERS_MAP_INDEX_VALUE]);
- result.append(HTTP_LINE_ENDING);
- }
- result.append(HTTP_LINE_ENDING);
- return result.toString();
- }
-
-
- /**
- * Set a response header and associated value. The key is associated
- * case-insensitively, but stored case-sensitively.
- * @param name Case sensitive request header key.
- * @param value The associated value.
- */
- private void setResponseHeader(String name, String value) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "Set response header " + name + ": " + value);
- }
- String mapValue[] = { name, value };
- mResponseHeaders.put(name.toLowerCase(), mapValue);
- }
-
- // Cookie handling
-
- /**
- * Get the cookie for the given URL.
- * @param url The fully qualified URL.
- * @return A string containing the cookie for the URL if it exists,
- * or null if not.
- */
- public static String getCookieForUrl(String url) {
- // Get the cookie for this URL, set as a header
- return CookieManager.getInstance().getCookie(url);
- }
-
- /**
- * Set the cookie for the given URL.
- * @param url The fully qualified URL.
- * @param cookie The new cookie value.
- * @return A string containing the cookie for the URL if it exists,
- * or null if not.
- */
- public static void setCookieForUrl(String url, String cookie) {
- // Get the cookie for this URL, set as a header
- CookieManager.getInstance().setCookie(url, cookie);
- }
-
- // Cache handling
-
- /**
- * Perform a request using LocalServer if possible. Initializes
- * class members so that receive() will obtain data from the stream
- * provided by the response.
- * @param url The fully qualified URL to try in LocalServer.
- * @return True if the url was found and is now setup to receive.
- * False if not found, with no side-effect.
- */
- public synchronized boolean useLocalServerResult(String url) {
- UrlInterceptHandlerGears handler =
- UrlInterceptHandlerGears.getInstance();
- if (handler == null) {
- return false;
- }
- UrlInterceptHandlerGears.ServiceResponse serviceResponse =
- handler.getServiceResponse(url, mRequestHeaders);
- if (serviceResponse == null) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "No response in LocalServer");
- }
- return false;
- }
- // LocalServer will handle this URL. Initialize stream and
- // response.
- mBodyInputStream = serviceResponse.getInputStream();
- mResponseLine = serviceResponse.getStatusLine();
- mResponseHeaders = serviceResponse.getResponseHeaders();
- if (Config.LOGV) {
- Log.i(LOG_TAG, "Got response from LocalServer: " + mResponseLine);
- }
- return true;
- }
-
- /**
- * Perform a request using the cache result if present. Initializes
- * class members so that receive() will obtain data from the cache.
- * @param url The fully qualified URL to try in the cache.
- * @return True is the url was found and is now setup to receive
- * from cache. False if not found, with no side-effect.
- */
- public synchronized boolean useCacheResult(String url) {
- // Try the browser's cache. CacheManager wants a Map<String, String>.
- Map<String, String> cacheRequestHeaders = new HashMap<String, String>();
- Iterator<Map.Entry<String, String[]>> it =
- mRequestHeaders.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry<String, String[]> entry = it.next();
- cacheRequestHeaders.put(
- entry.getKey(),
- entry.getValue()[HEADERS_MAP_INDEX_VALUE]);
- }
- CacheResult mCacheResult =
- CacheManager.getCacheFile(url, cacheRequestHeaders);
- if (mCacheResult == null) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "No CacheResult for " + url);
- }
- return false;
- }
- if (Config.LOGV) {
- Log.i(LOG_TAG, "Got CacheResult from browser cache");
- }
- // Check for expiry. -1 is "never", otherwise milliseconds since 1970.
- // Can be compared to System.currentTimeMillis().
- long expires = mCacheResult.getExpires();
- if (expires >= 0 && System.currentTimeMillis() >= expires) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "CacheResult expired "
- + (System.currentTimeMillis() - expires)
- + " milliseconds ago");
- }
- // Cache hit has expired. Do not return it.
- return false;
- }
- // Setup the mBodyInputStream to come from the cache.
- mBodyInputStream = mCacheResult.getInputStream();
- if (mBodyInputStream == null) {
- // Cache result may have gone away.
- if (Config.LOGV) {
- Log.i(LOG_TAG, "No mBodyInputStream for CacheResult " + url);
- }
- return false;
- }
- // Cache hit. Parse headers.
- synthesizeHeadersFromCacheResult(mCacheResult);
- return true;
- }
-
- /**
- * Take the limited set of headers in a CacheResult and synthesize
- * response headers.
- * @param cacheResult A CacheResult to populate mResponseHeaders with.
- */
- private void synthesizeHeadersFromCacheResult(CacheResult cacheResult) {
- int statusCode = cacheResult.getHttpStatusCode();
- // The status message is informal, so we can greatly simplify it.
- String statusMessage;
- if (statusCode >= 200 && statusCode < 300) {
- statusMessage = "OK";
- } else if (statusCode >= 300 && statusCode < 400) {
- statusMessage = "MOVED";
- } else {
- statusMessage = "UNAVAILABLE";
- }
- // Synthesize the response line.
- mResponseLine = "HTTP/1.1 " + statusCode + " " + statusMessage;
- if (Config.LOGV) {
- Log.i(LOG_TAG, "Synthesized " + mResponseLine);
- }
- // Synthesize the returned headers from cache.
- mResponseHeaders = new HashMap<String, String[]>();
- String contentLength = Long.toString(cacheResult.getContentLength());
- setResponseHeader(KEY_CONTENT_LENGTH, contentLength);
- long expires = cacheResult.getExpires();
- if (expires >= 0) {
- // "Expires" header is valid and finite. Milliseconds since 1970
- // epoch, formatted as RFC-1123.
- String expiresString = DateUtils.formatDate(new Date(expires));
- setResponseHeader(KEY_EXPIRES, expiresString);
- }
- String lastModified = cacheResult.getLastModified();
- if (lastModified != null) {
- // Last modification time of the page. Passed end-to-end, but
- // not used by us.
- setResponseHeader(KEY_LAST_MODIFIED, lastModified);
- }
- String eTag = cacheResult.getETag();
- if (eTag != null) {
- // Entity tag. A kind of GUID to identify identical resources.
- setResponseHeader(KEY_ETAG, eTag);
- }
- String location = cacheResult.getLocation();
- if (location != null) {
- // If valid, refers to the location of a redirect.
- setResponseHeader(KEY_LOCATION, location);
- }
- String mimeType = cacheResult.getMimeType();
- if (mimeType == null) {
- // Use a safe default MIME type when none is
- // specified. "text/plain" is safe to render in the browser
- // window (even if large) and won't be intepreted as anything
- // that would cause execution.
- mimeType = DEFAULT_MIME_TYPE;
- }
- String encoding = cacheResult.getEncoding();
- // Encoding may not be specified. No default.
- String contentType = mimeType;
- if (encoding != null) {
- if (encoding.length() > 0) {
- contentType += "; charset=" + encoding;
- }
- }
- setResponseHeader(KEY_CONTENT_TYPE, contentType);
- }
-
- /**
- * Create a CacheResult for this URL. This enables the repsonse body
- * to be sent in calls to appendCacheResult().
- * @param url The fully qualified URL to add to the cache.
- * @param responseCode The response code returned for the request, e.g 200.
- * @param mimeType The MIME type of the body, e.g "text/plain".
- * @param encoding The encoding, e.g "utf-8". Use "" for unknown.
- */
- public synchronized boolean createCacheResult(
- String url, int responseCode, String mimeType, String encoding) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "Making cache entry for " + url);
- }
- // Take the headers and parse them into a format needed by
- // CacheManager.
- Headers cacheHeaders = new Headers();
- Iterator<Map.Entry<String, String[]>> it =
- mResponseHeaders.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry<String, String[]> entry = it.next();
- // Headers.parseHeader() expects lowercase keys.
- String keyValue = entry.getKey() + ": "
- + entry.getValue()[HEADERS_MAP_INDEX_VALUE];
- CharArrayBuffer buffer = new CharArrayBuffer(keyValue.length());
- buffer.append(keyValue);
- // Parse it into the header container.
- cacheHeaders.parseHeader(buffer);
- }
- mCacheResult = CacheManager.createCacheFile(
- url, responseCode, cacheHeaders, mimeType, true);
- if (mCacheResult != null) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "Saving into cache");
- }
- mCacheResult.setEncoding(encoding);
- mCacheResultUrl = url;
- return true;
- } else {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "Couldn't create mCacheResult");
- }
- return false;
- }
- }
-
- /**
- * Add data from the response body to the CacheResult created with
- * createCacheResult().
- * @param data A byte array of the next sequential bytes in the
- * response body.
- * @param bytes The number of bytes to write from the start of
- * the array.
- * @return True if all bytes successfully written, false on failure.
- */
- public synchronized boolean appendCacheResult(byte[] data, int bytes) {
- if (mCacheResult == null) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "appendCacheResult() called without a "
- + "CacheResult initialized");
- }
- return false;
- }
- try {
- mCacheResult.getOutputStream().write(data, 0, bytes);
- } catch (IOException ex) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "Got IOException writing cache data: " + ex);
- }
- return false;
- }
- return true;
- }
-
- /**
- * Save the completed CacheResult into the CacheManager. This must
- * have been created first with createCacheResult().
- * @return Returns true if the entry has been successfully saved.
- */
- public synchronized boolean saveCacheResult() {
- if (mCacheResult == null || mCacheResultUrl == null) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "Tried to save cache result but "
- + "createCacheResult not called");
- }
- return false;
- }
-
- if (Config.LOGV) {
- Log.i(LOG_TAG, "Saving cache result");
- }
- CacheManager.saveCacheFile(mCacheResultUrl, mCacheResult);
- mCacheResult = null;
- mCacheResultUrl = null;
- return true;
- }
-
-
- /**
- * Interrupt a blocking IO operation. This will cause the child
- * thread to expediently return from an operation if it was stuck at
- * the time. Note that this inherently races, and unfortunately
- * requires the caller to loop.
- */
- public synchronized void interrupt() {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "INTERRUPT CALLED");
- }
- mConnectionFailedLock.lock();
- mConnectionFailed = true;
- mConnectionFailedLock.unlock();
- if (mMethod != null) {
- mMethod.abort();
- }
- if (mHttpThread != null) {
- waitUntilConnectionFinished();
- }
- }
-
- /**
- * Receive the next sequential bytes of the response body after
- * successful connection. This will receive up to the size of the
- * provided byte array. If there is no body, this will return 0
- * bytes on the first call after connection.
- * @param buf A pre-allocated byte array to receive data into.
- * @return The number of bytes from the start of the array which
- * have been filled, 0 on EOF, or negative on error.
- */
- public synchronized int receive(byte[] buf) {
- if (mBodyInputStream == null) {
- // If this is the first call, setup the InputStream. This may
- // fail if there were headers, but no body returned by the
- // server.
- try {
- if (mResponse != null) {
- HttpEntity entity = mResponse.getEntity();
- mBodyInputStream = entity.getContent();
- }
- } catch (IOException inputException) {
- if (Config.LOGV) {
- Log.i(LOG_TAG, "Failed to connect InputStream: "
- + inputException);
- }
- // Not unexpected. For example, 404 response return headers,
- // and sometimes a body with a detailed error.
- }
- if (mBodyInputStream == null) {
- // No error stream either. Treat as a 0 byte response.
- if (Config.LOGV) {
- Log.i(LOG_TAG, "No InputStream");
- }
- return 0; // EOF.
- }
- }
- int ret;
- try {
- int got = mBodyInputStream.read(buf);
- if (got > 0) {
- // Got some bytes, not EOF.
- ret = got;
- } else {
- // EOF.
- mBodyInputStream.close();
- ret = 0;
- }
- } catch (IOException e) {
- // An abort() interrupts us by calling close() on our stream.
- if (Config.LOGV) {
- Log.i(LOG_TAG, "Got IOException in mBodyInputStream.read(): ", e);
- }
- ret = -1;
- }
- return ret;
- }
-
- /**
- * For POST method requests, send a stream of data provided by the
- * native side in repeated callbacks.
- * We put the data in mBuffer, and wait until it is consumed
- * by the StreamEntity in the request thread.
- * @param data A byte array containing the data to sent, or null
- * if indicating EOF.
- * @param bytes The number of bytes from the start of the array to
- * send, or 0 if indicating EOF.
- * @return True if all bytes were successfully sent, false on error.
- */
- public boolean sendPostData(byte[] data, int bytes) {
- mConnectionFailedLock.lock();
- if (mConnectionFailed) {
- mConnectionFailedLock.unlock();
- return false;
- }
- mConnectionFailedLock.unlock();
- if (mPostEntity == null) return false;
-
- // We block until the outputstream is available
- // (or in case of connection error)
- if (!mPostEntity.isReady()) return false;
-
- if (data == null && bytes == 0) {
- mBuffer.put(null);
- } else {
- mBuffer.put(new DataPacket(data, bytes));
- }
- mSignal.waitUntilPacketConsumed();
-
- mConnectionFailedLock.lock();
- if (mConnectionFailed) {
- Log.e(LOG_TAG, "failure");
- mConnectionFailedLock.unlock();
- return false;
- }
- mConnectionFailedLock.unlock();
- return true;
- }
-
-}
diff --git a/core/java/android/webkit/gears/DesktopAndroid.java b/core/java/android/webkit/gears/DesktopAndroid.java
deleted file mode 100644
index ee8ca49..0000000
--- a/core/java/android/webkit/gears/DesktopAndroid.java
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2008 The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// 3. Neither the name of Google Inc. nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.content.Context;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.net.Uri;
-import android.util.Log;
-import android.webkit.WebView;
-
-/**
- * Utility class to create a shortcut on Android
- */
-public class DesktopAndroid {
-
- private static final String TAG = "Gears-J-Desktop";
- private static final String EXTRA_SHORTCUT_DUPLICATE = "duplicate";
- private static final String ACTION_INSTALL_SHORTCUT =
- "com.android.launcher.action.INSTALL_SHORTCUT";
-
- // Android now enforces a 64x64 limit for the icon
- private static int MAX_WIDTH = 64;
- private static int MAX_HEIGHT = 64;
-
- /**
- * Small utility function returning a Bitmap object.
- *
- * @param path the icon path
- */
- private static Bitmap getBitmap(String path) {
- return BitmapFactory.decodeFile(path);
- }
-
- /**
- * Create a shortcut for a webpage.
- *
- * <p>To set a shortcut on Android, we use the ACTION_INSTALL_SHORTCUT
- * from the default Home application. We only have to create an Intent
- * containing extra parameters specifying the shortcut.
- * <p>Note: the shortcut mechanism is not system wide and depends on the
- * Home application; if phone carriers decide to rewrite a Home application
- * that does not accept this Intent, no shortcut will be added.
- *
- * @param webview the webview we are called from
- * @param title the shortcut's title
- * @param url the shortcut's url
- * @param imagePath the local path of the shortcut's icon
- */
- public static void setShortcut(WebView webview, String title,
- String url, String imagePath) {
- Context context = webview.getContext();
-
- Intent viewWebPage = new Intent(Intent.ACTION_VIEW);
- viewWebPage.setData(Uri.parse(url));
- viewWebPage.addCategory(Intent.CATEGORY_BROWSABLE);
-
- Intent intent = new Intent(ACTION_INSTALL_SHORTCUT);
- intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, viewWebPage);
- intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, title);
-
- // We disallow the creation of duplicate shortcuts (i.e. same
- // url, same title, but different screen position).
- intent.putExtra(EXTRA_SHORTCUT_DUPLICATE, false);
-
- Bitmap bmp = getBitmap(imagePath);
- if (bmp != null) {
- if ((bmp.getWidth() > MAX_WIDTH) ||
- (bmp.getHeight() > MAX_HEIGHT)) {
- Bitmap scaledBitmap = Bitmap.createScaledBitmap(bmp,
- MAX_WIDTH, MAX_HEIGHT, true);
- intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, scaledBitmap);
- } else {
- intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, bmp);
- }
- } else {
- // This should not happen as we just downloaded the icon
- Log.e(TAG, "icon file <" + imagePath + "> not found");
- }
-
- context.sendBroadcast(intent);
- }
-
-}
diff --git a/core/java/android/webkit/gears/NativeDialog.java b/core/java/android/webkit/gears/NativeDialog.java
deleted file mode 100644
index 9e2b375..0000000
--- a/core/java/android/webkit/gears/NativeDialog.java
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2008 The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// 3. Neither the name of Google Inc. nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-import java.io.File;
-import java.lang.InterruptedException;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Utility class to call a modal native dialog on Android
- * The dialog itself is an Activity defined in the Browser.
- * @hide
- */
-public class NativeDialog {
-
- private static final String TAG = "Gears-J-NativeDialog";
-
- private final String DIALOG_PACKAGE = "com.android.browser";
- private final String DIALOG_CLASS = DIALOG_PACKAGE + ".GearsNativeDialog";
-
- private static Lock mLock = new ReentrantLock();
- private static Condition mDialogFinished = mLock.newCondition();
- private static String mResults = null;
-
- private static boolean mAsynchronousDialog;
-
- /**
- * Utility function to build the intent calling the
- * dialog activity
- */
- private Intent createIntent(String type, String arguments) {
- Intent intent = new Intent();
- intent.setClassName(DIALOG_PACKAGE, DIALOG_CLASS);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra("dialogArguments", arguments);
- intent.putExtra("dialogType", type);
- return intent;
- }
-
- /**
- * Opens a native dialog synchronously and waits for its completion.
- *
- * The dialog is an activity (GearsNativeDialog) provided by the Browser
- * that we call via startActivity(). Contrary to a normal activity though,
- * we need to block until it returns. To do so, we define a static lock
- * object in this class, which GearsNativeDialog can unlock once done
- */
- public String showDialog(Context context, String file,
- String arguments) {
-
- try {
- mAsynchronousDialog = false;
- mLock.lock();
- File path = new File(file);
- String fileName = path.getName();
- String type = fileName.substring(0, fileName.indexOf(".html"));
- Intent intent = createIntent(type, arguments);
-
- mResults = null;
- context.startActivity(intent);
- mDialogFinished.await();
- } catch (InterruptedException e) {
- Log.e(TAG, "exception e: " + e);
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "exception e: " + e);
- } finally {
- mLock.unlock();
- }
-
- return mResults;
- }
-
- /**
- * Opens a native dialog asynchronously
- *
- * The dialog is an activity (GearsNativeDialog) provided by the
- * Browser.
- */
- public void showAsyncDialog(Context context, String type,
- String arguments) {
- mAsynchronousDialog = true;
- Intent intent = createIntent(type, arguments);
- context.startActivity(intent);
- }
-
- /**
- * Static method that GearsNativeDialog calls to unlock us
- */
- public static void signalFinishedDialog() {
- if (!mAsynchronousDialog) {
- mLock.lock();
- mDialogFinished.signal();
- mLock.unlock();
- } else {
- // we call the native callback
- closeAsynchronousDialog(mResults);
- }
- }
-
- /**
- * Static method that GearsNativeDialog calls to set the
- * dialog's result
- */
- public static void closeDialog(String res) {
- mResults = res;
- }
-
- /**
- * Native callback method
- */
- private native static void closeAsynchronousDialog(String res);
-}
diff --git a/core/java/android/webkit/gears/PluginSettings.java b/core/java/android/webkit/gears/PluginSettings.java
deleted file mode 100644
index 2d0cc13..0000000
--- a/core/java/android/webkit/gears/PluginSettings.java
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2008 The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// 3. Neither the name of Google Inc. nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.content.Context;
-import android.util.Log;
-import android.webkit.Plugin;
-import android.webkit.Plugin.PreferencesClickHandler;
-
-/**
- * Simple bridge class intercepting the click in the
- * browser plugin list and calling the Gears settings
- * dialog.
- */
-public class PluginSettings {
-
- private static final String TAG = "Gears-J-PluginSettings";
- private Context mContext;
-
- public PluginSettings(Plugin plugin) {
- plugin.setClickHandler(new ClickHandler());
- }
-
- /**
- * We do not call the dialog synchronously here as the main
- * message loop would be blocked, so we call it via a secondary thread.
- */
- private class ClickHandler implements PreferencesClickHandler {
- public void handleClickEvent(Context context) {
- mContext = context.getApplicationContext();
- Thread startDialog = new Thread(new StartDialog(context));
- startDialog.start();
- }
- }
-
- /**
- * Simple wrapper class to call the gears native method in
- * a separate thread (the native code will then instanciate a NativeDialog
- * object which will start the GearsNativeDialog activity defined in
- * the Browser).
- */
- private class StartDialog implements Runnable {
- Context mContext;
-
- public StartDialog(Context context) {
- mContext = context;
- }
-
- public void run() {
- runSettingsDialog(mContext);
- }
- }
-
- private static native void runSettingsDialog(Context c);
-
-}
diff --git a/core/java/android/webkit/gears/UrlInterceptHandlerGears.java b/core/java/android/webkit/gears/UrlInterceptHandlerGears.java
deleted file mode 100644
index 2a5cbe9..0000000
--- a/core/java/android/webkit/gears/UrlInterceptHandlerGears.java
+++ /dev/null
@@ -1,501 +0,0 @@
-// Copyright 2008, The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// 3. Neither the name of Google Inc. nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.net.http.Headers;
-import android.util.Log;
-import android.webkit.CacheManager;
-import android.webkit.CacheManager.CacheResult;
-import android.webkit.Plugin;
-import android.webkit.UrlInterceptRegistry;
-import android.webkit.UrlInterceptHandler;
-import android.webkit.WebView;
-
-import org.apache.http.impl.cookie.DateUtils;
-import org.apache.http.util.CharArrayBuffer;
-
-import java.io.*;
-import java.util.*;
-
-/**
- * Services requests to handle URLs coming from the browser or
- * HttpRequestAndroid. This registers itself with the
- * UrlInterceptRegister in Android so we get a chance to service all
- * URLs passing through the browser before anything else.
- */
-public class UrlInterceptHandlerGears implements UrlInterceptHandler {
- /** Singleton instance. */
- private static UrlInterceptHandlerGears instance;
- /** Debug logging tag. */
- private static final String LOG_TAG = "Gears-J";
- /** Buffer size for reading/writing streams. */
- private static final int BUFFER_SIZE = 4096;
- /**
- * Number of milliseconds to expire LocalServer temporary entries in
- * the browser's cache. Somewhat arbitrarily chosen as a compromise
- * between being a) long enough not to expire during page load and
- * b) short enough to evict entries during a session. */
- private static final int CACHE_EXPIRY_MS = 60000; // 1 minute.
- /** Enable/disable all logging in this class. */
- private static boolean logEnabled = false;
- /** The unmodified (case-sensitive) key in the headers map is the
- * same index as used by HttpRequestAndroid. */
- public static final int HEADERS_MAP_INDEX_KEY =
- ApacheHttpRequestAndroid.HEADERS_MAP_INDEX_KEY;
- /** The associated value in the headers map is the same index as
- * used by HttpRequestAndroid. */
- public static final int HEADERS_MAP_INDEX_VALUE =
- ApacheHttpRequestAndroid.HEADERS_MAP_INDEX_VALUE;
-
- /**
- * Object passed to the native side, containing information about
- * the URL to service.
- */
- public static class ServiceRequest {
- // The URL being requested.
- private String url;
- // Request headers. Map of lowercase key to [ unmodified key, value ].
- private Map<String, String[]> requestHeaders;
-
- /**
- * Initialize members on construction.
- * @param url The URL being requested.
- * @param requestHeaders Headers associated with the request,
- * or null if none.
- * Map of lowercase key to [ unmodified key, value ].
- */
- public ServiceRequest(String url, Map<String, String[]> requestHeaders) {
- this.url = url;
- this.requestHeaders = requestHeaders;
- }
-
- /**
- * Returns the URL being requested.
- * @return The URL being requested.
- */
- public String getUrl() {
- return url;
- }
-
- /**
- * Get the value associated with a request header key, if any.
- * @param header The key to find, case insensitive.
- * @return The value associated with this header, or null if not found.
- */
- public String getRequestHeader(String header) {
- if (requestHeaders != null) {
- String[] value = requestHeaders.get(header.toLowerCase());
- if (value != null) {
- return value[HEADERS_MAP_INDEX_VALUE];
- } else {
- return null;
- }
- } else {
- return null;
- }
- }
- }
-
- /**
- * Object returned by the native side, containing information needed
- * to pass the entire response back to the browser or
- * HttpRequestAndroid. Works from either an in-memory array or a
- * file on disk.
- */
- public class ServiceResponse {
- // The response status code, e.g 200.
- private int statusCode;
- // The full status line, e.g "HTTP/1.1 200 OK".
- private String statusLine;
- // All headers associated with the response. Map of lowercase key
- // to [ unmodified key, value ].
- private Map<String, String[]> responseHeaders =
- new HashMap<String, String[]>();
- // The MIME type, e.g "text/html".
- private String mimeType;
- // The encoding, e.g "utf-8", or null if none.
- private String encoding;
- // The stream which contains the body when read().
- private InputStream inputStream;
-
- /**
- * Initialize members using an in-memory array to return the body.
- * @param statusCode The response status code, e.g 200.
- * @param statusLine The full status line, e.g "HTTP/1.1 200 OK".
- * @param mimeType The MIME type, e.g "text/html".
- * @param encoding Encoding, e.g "utf-8" or null if none.
- * @param body The response body as a byte array, non-empty.
- */
- void setResultArray(
- int statusCode,
- String statusLine,
- String mimeType,
- String encoding,
- byte[] body) {
- this.statusCode = statusCode;
- this.statusLine = statusLine;
- this.mimeType = mimeType;
- this.encoding = encoding;
- // Setup a stream to read out of the byte array.
- this.inputStream = new ByteArrayInputStream(body);
- }
-
- /**
- * Initialize members using a file on disk to return the body.
- * @param statusCode The response status code, e.g 200.
- * @param statusLine The full status line, e.g "HTTP/1.1 200 OK".
- * @param mimeType The MIME type, e.g "text/html".
- * @param encoding Encoding, e.g "utf-8" or null if none.
- * @param path Full path to the file containing the body.
- * @return True if the file is successfully setup to stream,
- * false on error such as file not found.
- */
- boolean setResultFile(
- int statusCode,
- String statusLine,
- String mimeType,
- String encoding,
- String path) {
- this.statusCode = statusCode;
- this.statusLine = statusLine;
- this.mimeType = mimeType;
- this.encoding = encoding;
- try {
- // Setup a stream to read out of a file on disk.
- this.inputStream = new FileInputStream(new File(path));
- return true;
- } catch (java.io.FileNotFoundException ex) {
- log("File not found: " + path);
- return false;
- }
- }
-
- /**
- * Set a response header, adding its settings to the header members.
- * @param key The case sensitive key for the response header,
- * e.g "Set-Cookie".
- * @param value The value associated with this key, e.g "cookie1234".
- */
- public void setResponseHeader(String key, String value) {
- // The map value contains the unmodified key (not lowercase).
- String[] mapValue = { key, value };
- responseHeaders.put(key.toLowerCase(), mapValue);
- }
-
- /**
- * Return the "Content-Type" header possibly supplied by a
- * previous setResponseHeader().
- * @return The "Content-Type" value, or null if not present.
- */
- public String getContentType() {
- // The map keys are lowercase.
- String[] value = responseHeaders.get("content-type");
- if (value != null) {
- return value[HEADERS_MAP_INDEX_VALUE];
- } else {
- return null;
- }
- }
-
- /**
- * Returns the HTTP status code for the response, supplied in
- * setResultArray() or setResultFile().
- * @return The HTTP statue code, e.g 200.
- */
- public int getStatusCode() {
- return statusCode;
- }
-
- /**
- * Returns the full HTTP status line for the response, supplied in
- * setResultArray() or setResultFile().
- * @return The HTTP statue line, e.g "HTTP/1.1 200 OK".
- */
- public String getStatusLine() {
- return statusLine;
- }
-
- /**
- * Get all response headers supplied in calls in
- * setResponseHeader().
- * @return A Map<String, String[]> containing all headers.
- */
- public Map<String, String[]> getResponseHeaders() {
- return responseHeaders;
- }
-
- /**
- * Returns the MIME type for the response, supplied in
- * setResultArray() or setResultFile().
- * @return The MIME type, e.g "text/html".
- */
- public String getMimeType() {
- return mimeType;
- }
-
- /**
- * Returns the encoding for the response, supplied in
- * setResultArray() or setResultFile(), or null if none.
- * @return The encoding, e.g "utf-8", or null if none.
- */
- public String getEncoding() {
- return encoding;
- }
-
- /**
- * Returns the InputStream setup by setResultArray() or
- * setResultFile() to allow reading data either from memory or
- * disk.
- * @return The InputStream containing the response body.
- */
- public InputStream getInputStream() {
- return inputStream;
- }
- }
-
- /**
- * Construct and initialize the singleton instance.
- */
- public UrlInterceptHandlerGears() {
- if (instance != null) {
- Log.e(LOG_TAG, "UrlInterceptHandlerGears singleton already constructed");
- throw new RuntimeException();
- }
- instance = this;
- }
-
- /**
- * Turn on/off logging in this class.
- * @param on Logging enable state.
- */
- public static void enableLogging(boolean on) {
- logEnabled = on;
- }
-
- /**
- * Get the singleton instance.
- * @return The singleton instance.
- */
- public static UrlInterceptHandlerGears getInstance() {
- return instance;
- }
-
- /**
- * Register the singleton instance with the browser's interception
- * mechanism.
- */
- public synchronized void register() {
- UrlInterceptRegistry.registerHandler(this);
- }
-
- /**
- * Unregister the singleton instance from the browser's interception
- * mechanism.
- */
- public synchronized void unregister() {
- UrlInterceptRegistry.unregisterHandler(this);
- }
-
- /**
- * Copy the entire InputStream to OutputStream.
- * @param inputStream The stream to read from.
- * @param outputStream The stream to write to.
- * @return True if the entire stream copied successfully, false on error.
- */
- private boolean copyStream(InputStream inputStream,
- OutputStream outputStream) {
- try {
- // Temporary buffer to copy stream through.
- byte[] buf = new byte[BUFFER_SIZE];
- for (;;) {
- // Read up to BUFFER_SIZE bytes.
- int bytes = inputStream.read(buf);
- if (bytes < 0) {
- break;
- }
- // Write the number of bytes we just read.
- outputStream.write(buf, 0, bytes);
- }
- } catch (IOException ex) {
- log("Got IOException copying stream: " + ex);
- return false;
- }
- return true;
- }
-
- /**
- * Given an URL, returns a CacheResult which contains the response
- * for the request. This implements the UrlInterceptHandler interface.
- *
- * @param url The fully qualified URL being requested.
- * @param requestHeaders The request headers for this URL.
- * @return If a response can be crafted, a CacheResult initialized
- * to return the surrogate response. If this URL cannot
- * be serviced, returns null.
- */
- public CacheResult service(String url, Map<String, String> requestHeaders) {
- // Thankfully the browser does call us with case-sensitive
- // headers. We just need to map it case-insensitive.
- Map<String, String[]> lowercaseRequestHeaders =
- new HashMap<String, String[]>();
- Iterator<Map.Entry<String, String>> requestHeadersIt =
- requestHeaders.entrySet().iterator();
- while (requestHeadersIt.hasNext()) {
- Map.Entry<String, String> entry = requestHeadersIt.next();
- String key = entry.getKey();
- String mapValue[] = { key, entry.getValue() };
- lowercaseRequestHeaders.put(key.toLowerCase(), mapValue);
- }
- ServiceResponse response = getServiceResponse(url, lowercaseRequestHeaders);
- if (response == null) {
- // No result for this URL.
- return null;
- }
- // Translate the ServiceResponse to a CacheResult.
- // Translate http -> gears, https -> gearss, so we don't overwrite
- // existing entries.
- String gearsUrl = "gears" + url.substring("http".length());
- // Set the result to expire, so that entries don't pollute the
- // browser's cache for too long.
- long now_ms = System.currentTimeMillis();
- String expires = DateUtils.formatDate(new Date(now_ms + CACHE_EXPIRY_MS));
- response.setResponseHeader(ApacheHttpRequestAndroid.KEY_EXPIRES, expires);
- // The browser is only interested in a small subset of headers,
- // contained in a Headers object. Iterate the map of all headers
- // and add them to Headers.
- Headers headers = new Headers();
- Iterator<Map.Entry<String, String[]>> responseHeadersIt =
- response.getResponseHeaders().entrySet().iterator();
- while (responseHeadersIt.hasNext()) {
- Map.Entry<String, String[]> entry = responseHeadersIt.next();
- // Headers.parseHeader() expects lowercase keys.
- String keyValue = entry.getKey() + ": "
- + entry.getValue()[HEADERS_MAP_INDEX_VALUE];
- CharArrayBuffer buffer = new CharArrayBuffer(keyValue.length());
- buffer.append(keyValue);
- // Parse it into the header container.
- headers.parseHeader(buffer);
- }
- CacheResult cacheResult = CacheManager.createCacheFile(
- gearsUrl,
- response.getStatusCode(),
- headers,
- response.getMimeType(),
- true); // forceCache
-
- if (cacheResult == null) {
- // With the no-cache policy we could end up
- // with a null result
- return null;
- }
-
- // Set encoding if specified.
- String encoding = response.getEncoding();
- if (encoding != null) {
- cacheResult.setEncoding(encoding);
- }
- // Copy the response body to the CacheResult. This handles all
- // combinations of memory vs on-disk on both sides.
- InputStream inputStream = response.getInputStream();
- OutputStream outputStream = cacheResult.getOutputStream();
- boolean copied = copyStream(inputStream, outputStream);
- // Close the input and output streams to relinquish their
- // resources earlier.
- try {
- inputStream.close();
- } catch (IOException ex) {
- log("IOException closing InputStream: " + ex);
- copied = false;
- }
- try {
- outputStream.close();
- } catch (IOException ex) {
- log("IOException closing OutputStream: " + ex);
- copied = false;
- }
- if (!copied) {
- log("copyStream of local result failed");
- return null;
- }
- // Save the entry into the browser's cache.
- CacheManager.saveCacheFile(gearsUrl, cacheResult);
- // Get it back from the cache, this time properly initialized to
- // be used for input.
- cacheResult = CacheManager.getCacheFile(gearsUrl, null);
- if (cacheResult != null) {
- log("Returning surrogate result");
- return cacheResult;
- } else {
- // Not an expected condition, but handle gracefully. Perhaps out
- // of memory or disk?
- Log.e(LOG_TAG, "Lost CacheResult between save and get. Can't serve.\n");
- return null;
- }
- }
-
- /**
- * Given an URL, returns a CacheResult and headers which contain the
- * response for the request.
- *
- * @param url The fully qualified URL being requested.
- * @param requestHeaders The request headers for this URL.
- * @return If a response can be crafted, a ServiceResponse is
- * created which contains all response headers and an InputStream
- * attached to the body. If there is no response, null is returned.
- */
- public ServiceResponse getServiceResponse(String url,
- Map<String, String[]> requestHeaders) {
- if (!url.startsWith("http://") && !url.startsWith("https://")) {
- // Don't know how to service non-HTTP URLs
- return null;
- }
- // Call the native handler to craft a response for this URL.
- return nativeService(new ServiceRequest(url, requestHeaders));
- }
-
- /**
- * Convenience debug function. Calls the Android logging
- * mechanism. logEnabled is not a constant, so if the string
- * evaluation is potentially expensive, the caller also needs to
- * check it.
- * @param str String to log to the Android console.
- */
- private void log(String str) {
- if (logEnabled) {
- Log.i(LOG_TAG, str);
- }
- }
-
- /**
- * Native method which handles the bulk of the request in LocalServer.
- * @param request A ServiceRequest object containing information about
- * the request.
- * @return If serviced, a ServiceResponse object containing all the
- * information to provide a response for the URL, or null
- * if no response available for this URL.
- */
- private native static ServiceResponse nativeService(ServiceRequest request);
-}
diff --git a/core/java/android/webkit/gears/VersionExtractor.java b/core/java/android/webkit/gears/VersionExtractor.java
deleted file mode 100644
index 172dacb..0000000
--- a/core/java/android/webkit/gears/VersionExtractor.java
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2008, The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// 3. Neither the name of Google Inc. nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.util.Log;
-import java.io.IOException;
-import java.io.StringReader;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.FactoryConfigurationError;
-import javax.xml.parsers.ParserConfigurationException;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.w3c.dom.Document;
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- * A class that can extract the Gears version and upgrade URL from an
- * xml document.
- */
-public final class VersionExtractor {
-
- /**
- * Logging tag
- */
- private static final String TAG = "Gears-J-VersionExtractor";
- /**
- * XML element names.
- */
- private static final String VERSION = "em:version";
- private static final String URL = "em:updateLink";
-
- /**
- * Parses the input xml string and invokes the native
- * setVersionAndUrl method.
- * @param xml is the XML string to parse.
- * @return true if the extraction is successful and false otherwise.
- */
- public static boolean extract(String xml, long nativeObject) {
- try {
- // Build the builders.
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- factory.setNamespaceAware(false);
- DocumentBuilder builder = factory.newDocumentBuilder();
-
- // Create the document.
- Document doc = builder.parse(new InputSource(new StringReader(xml)));
-
- // Look for the version and url elements and get their text
- // contents.
- String version = extractText(doc, VERSION);
- String url = extractText(doc, URL);
-
- // If we have both, let the native side know.
- if (version != null && url != null) {
- setVersionAndUrl(version, url, nativeObject);
- return true;
- }
-
- return false;
-
- } catch (FactoryConfigurationError ex) {
- Log.e(TAG, "Could not create the DocumentBuilderFactory " + ex);
- } catch (ParserConfigurationException ex) {
- Log.e(TAG, "Could not create the DocumentBuilder " + ex);
- } catch (SAXException ex) {
- Log.e(TAG, "Could not parse the xml " + ex);
- } catch (IOException ex) {
- Log.e(TAG, "Could not read the xml " + ex);
- }
-
- return false;
- }
-
- /**
- * Extracts the text content of the first element with the given name.
- * @param doc is the Document where the element is searched for.
- * @param elementName is name of the element to searched for.
- * @return the text content of the element or null if no such
- * element is found.
- */
- private static String extractText(Document doc, String elementName) {
- String text = null;
- NodeList node_list = doc.getElementsByTagName(elementName);
-
- if (node_list.getLength() > 0) {
- // We are only interested in the first node. Normally there
- // should not be more than one anyway.
- Node node = node_list.item(0);
-
- // Iterate through the text children.
- NodeList child_list = node.getChildNodes();
-
- try {
- for (int i = 0; i < child_list.getLength(); ++i) {
- Node child = child_list.item(i);
- if (child.getNodeType() == Node.TEXT_NODE) {
- if (text == null) {
- text = new String();
- }
- text += child.getNodeValue();
- }
- }
- } catch (DOMException ex) {
- Log.e(TAG, "getNodeValue() failed " + ex);
- }
- }
-
- if (text != null) {
- text = text.trim();
- }
-
- return text;
- }
-
- /**
- * Native method used to send the version and url back to the C++
- * side.
- */
- private static native void setVersionAndUrl(
- String version, String url, long nativeObject);
-}
diff --git a/core/java/android/webkit/gears/ZipInflater.java b/core/java/android/webkit/gears/ZipInflater.java
deleted file mode 100644
index f6b6be5..0000000
--- a/core/java/android/webkit/gears/ZipInflater.java
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright 2008, The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// 3. Neither the name of Google Inc. nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.os.StatFs;
-import android.util.Log;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.zip.CRC32;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-import java.util.zip.ZipInputStream;
-
-
-/**
- * A class that can inflate a zip archive.
- */
-public final class ZipInflater {
- /**
- * Logging tag
- */
- private static final String TAG = "Gears-J-ZipInflater";
-
- /**
- * The size of the buffer used to read from the archive.
- */
- private static final int BUFFER_SIZE_BYTES = 32 * 1024; // 32 KB.
- /**
- * The path navigation component (i.e. "../").
- */
- private static final String PATH_NAVIGATION_COMPONENT = ".." + File.separator;
- /**
- * The root of the data partition.
- */
- private static final String DATA_PARTITION_ROOT = "/data";
-
- /**
- * We need two be able to store two versions of gears in parallel:
- * - the zipped version
- * - the unzipped version, which will be loaded next time the browser is started.
- * We are conservative and do not attempt to unpack unless there enough free
- * space on the device to store 4 times the new Gears size.
- */
- private static final long SIZE_MULTIPLIER = 4;
-
- /**
- * Unzips the archive with the given name.
- * @param filename is the name of the zip to inflate.
- * @param path is the path where the zip should be unpacked. It must contain
- * a trailing separator, or the extraction will fail.
- * @return true if the extraction is successful and false otherwise.
- */
- public static boolean inflate(String filename, String path) {
- Log.i(TAG, "Extracting " + filename + " to " + path);
-
- // Check that the path ends with a separator.
- if (!path.endsWith(File.separator)) {
- Log.e(TAG, "Path missing trailing separator: " + path);
- return false;
- }
-
- boolean result = false;
-
- // Use a ZipFile to get an enumeration of the entries and
- // calculate the overall uncompressed size of the archive. Also
- // check for existing files or directories that have the same
- // name as the entries in the archive. Also check for invalid
- // entry names (e.g names that attempt to navigate to the
- // parent directory).
- ZipInputStream zipStream = null;
- long uncompressedSize = 0;
- try {
- ZipFile zipFile = new ZipFile(filename);
- try {
- Enumeration entries = zipFile.entries();
- while (entries.hasMoreElements()) {
- ZipEntry entry = (ZipEntry) entries.nextElement();
- uncompressedSize += entry.getSize();
- // Check against entry names that may attempt to navigate
- // out of the destination directory.
- if (entry.getName().indexOf(PATH_NAVIGATION_COMPONENT) >= 0) {
- throw new IOException("Illegal entry name: " + entry.getName());
- }
-
- // Check against entries with the same name as pre-existing files or
- // directories.
- File file = new File(path + entry.getName());
- if (file.exists()) {
- // A file or directory with the same name already exist.
- // This must not happen, so we treat this as an error.
- throw new IOException(
- "A file or directory with the same name already exists.");
- }
- }
- } finally {
- zipFile.close();
- }
-
- Log.i(TAG, "Determined uncompressed size: " + uncompressedSize);
- // Check we have enough space to unpack this archive.
- if (freeSpace() <= uncompressedSize * SIZE_MULTIPLIER) {
- throw new IOException("Not enough space to unpack this archive.");
- }
-
- zipStream = new ZipInputStream(
- new BufferedInputStream(new FileInputStream(filename)));
- ZipEntry entry;
- int counter;
- byte buffer[] = new byte[BUFFER_SIZE_BYTES];
-
- // Iterate through the entries and write each of them to a file.
- while ((entry = zipStream.getNextEntry()) != null) {
- File file = new File(path + entry.getName());
- if (entry.isDirectory()) {
- // If the entry denotes a directory, we need to create a
- // directory with the same name.
- file.mkdirs();
- } else {
- CRC32 checksum = new CRC32();
- BufferedOutputStream output = new BufferedOutputStream(
- new FileOutputStream(file),
- BUFFER_SIZE_BYTES);
- try {
- // Read the entry and write it to the file.
- while ((counter = zipStream.read(buffer, 0, BUFFER_SIZE_BYTES)) !=
- -1) {
- output.write(buffer, 0, counter);
- checksum.update(buffer, 0, counter);
- }
- output.flush();
- } finally {
- output.close();
- }
-
- if (checksum.getValue() != entry.getCrc()) {
- throw new IOException(
- "Integrity check failed for: " + entry.getName());
- }
- }
- zipStream.closeEntry();
- }
-
- result = true;
-
- } catch (FileNotFoundException ex) {
- Log.e(TAG, "The zip file could not be found. " + ex);
- } catch (IOException ex) {
- Log.e(TAG, "Could not read or write an entry. " + ex);
- } catch(IllegalArgumentException ex) {
- Log.e(TAG, "Could not create the BufferedOutputStream. " + ex);
- } finally {
- if (zipStream != null) {
- try {
- zipStream.close();
- } catch (IOException ex) {
- // Ignored.
- }
- }
- // Discard any exceptions and return the result to the native side.
- return result;
- }
- }
-
- private static final long freeSpace() {
- StatFs data_partition = new StatFs(DATA_PARTITION_ROOT);
- long freeSpace = data_partition.getAvailableBlocks() *
- data_partition.getBlockSize();
- Log.i(TAG, "Free space on the data partition: " + freeSpace);
- return freeSpace;
- }
-}
diff --git a/core/java/android/webkit/gears/package.html b/core/java/android/webkit/gears/package.html
deleted file mode 100644
index db6f78b..0000000
--- a/core/java/android/webkit/gears/package.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<body>
-{@hide}
-</body> \ No newline at end of file
diff --git a/core/java/android/webkit/package.html b/core/java/android/webkit/package.html
deleted file mode 100644
index 4ed08da..0000000
--- a/core/java/android/webkit/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<html>
-<body>
-Provides tools for browsing the web.
-<p>The only classes or interfaces in this package intended for use by SDK
-developers are WebView, BroswerCallbackAdapter, BrowserCallback, and CookieManager.
-</body>
-</html> \ No newline at end of file
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
deleted file mode 100644
index f362e22..0000000
--- a/core/java/android/widget/AbsListView.java
+++ /dev/null
@@ -1,3425 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.TransitionDrawable;
-import android.os.Debug;
-import android.os.Handler;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.HapticFeedbackConstants;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewDebug;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.view.inputmethod.InputMethodManager;
-import android.view.ContextMenu.ContextMenuInfo;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Common code shared between ListView and GridView
- *
- * @attr ref android.R.styleable#AbsListView_listSelector
- * @attr ref android.R.styleable#AbsListView_drawSelectorOnTop
- * @attr ref android.R.styleable#AbsListView_stackFromBottom
- * @attr ref android.R.styleable#AbsListView_scrollingCache
- * @attr ref android.R.styleable#AbsListView_textFilterEnabled
- * @attr ref android.R.styleable#AbsListView_transcriptMode
- * @attr ref android.R.styleable#AbsListView_cacheColorHint
- * @attr ref android.R.styleable#AbsListView_fastScrollEnabled
- * @attr ref android.R.styleable#AbsListView_smoothScrollbar
- */
-public abstract class AbsListView extends AdapterView<ListAdapter> implements TextWatcher,
- ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener,
- ViewTreeObserver.OnTouchModeChangeListener {
-
- /**
- * Disables the transcript mode.
- *
- * @see #setTranscriptMode(int)
- */
- public static final int TRANSCRIPT_MODE_DISABLED = 0;
- /**
- * The list will automatically scroll to the bottom when a data set change
- * notification is received and only if the last item is already visible
- * on screen.
- *
- * @see #setTranscriptMode(int)
- */
- public static final int TRANSCRIPT_MODE_NORMAL = 1;
- /**
- * The list will automatically scroll to the bottom, no matter what items
- * are currently visible.
- *
- * @see #setTranscriptMode(int)
- */
- public static final int TRANSCRIPT_MODE_ALWAYS_SCROLL = 2;
-
- /**
- * Indicates that we are not in the middle of a touch gesture
- */
- static final int TOUCH_MODE_REST = -1;
-
- /**
- * Indicates we just received the touch event and we are waiting to see if the it is a tap or a
- * scroll gesture.
- */
- static final int TOUCH_MODE_DOWN = 0;
-
- /**
- * Indicates the touch has been recognized as a tap and we are now waiting to see if the touch
- * is a longpress
- */
- static final int TOUCH_MODE_TAP = 1;
-
- /**
- * Indicates we have waited for everything we can wait for, but the user's finger is still down
- */
- static final int TOUCH_MODE_DONE_WAITING = 2;
-
- /**
- * Indicates the touch gesture is a scroll
- */
- static final int TOUCH_MODE_SCROLL = 3;
-
- /**
- * Indicates the view is in the process of being flung
- */
- static final int TOUCH_MODE_FLING = 4;
-
- /**
- * Indicates that the user is currently dragging the fast scroll thumb
- */
- static final int TOUCH_MODE_FAST_SCROLL = 5;
-
- /**
- * Regular layout - usually an unsolicited layout from the view system
- */
- static final int LAYOUT_NORMAL = 0;
-
- /**
- * Show the first item
- */
- static final int LAYOUT_FORCE_TOP = 1;
-
- /**
- * Force the selected item to be on somewhere on the screen
- */
- static final int LAYOUT_SET_SELECTION = 2;
-
- /**
- * Show the last item
- */
- static final int LAYOUT_FORCE_BOTTOM = 3;
-
- /**
- * Make a mSelectedItem appear in a specific location and build the rest of
- * the views from there. The top is specified by mSpecificTop.
- */
- static final int LAYOUT_SPECIFIC = 4;
-
- /**
- * Layout to sync as a result of a data change. Restore mSyncPosition to have its top
- * at mSpecificTop
- */
- static final int LAYOUT_SYNC = 5;
-
- /**
- * Layout as a result of using the navigation keys
- */
- static final int LAYOUT_MOVE_SELECTION = 6;
-
- /**
- * Controls how the next layout will happen
- */
- int mLayoutMode = LAYOUT_NORMAL;
-
- /**
- * Should be used by subclasses to listen to changes in the dataset
- */
- AdapterDataSetObserver mDataSetObserver;
-
- /**
- * The adapter containing the data to be displayed by this view
- */
- ListAdapter mAdapter;
-
- /**
- * Indicates whether the list selector should be drawn on top of the children or behind
- */
- boolean mDrawSelectorOnTop = false;
-
- /**
- * The drawable used to draw the selector
- */
- Drawable mSelector;
-
- /**
- * Defines the selector's location and dimension at drawing time
- */
- Rect mSelectorRect = new Rect();
-
- /**
- * The data set used to store unused views that should be reused during the next layout
- * to avoid creating new ones
- */
- final RecycleBin mRecycler = new RecycleBin();
-
- /**
- * The selection's left padding
- */
- int mSelectionLeftPadding = 0;
-
- /**
- * The selection's top padding
- */
- int mSelectionTopPadding = 0;
-
- /**
- * The selection's right padding
- */
- int mSelectionRightPadding = 0;
-
- /**
- * The selection's bottom padding
- */
- int mSelectionBottomPadding = 0;
-
- /**
- * This view's padding
- */
- Rect mListPadding = new Rect();
-
- /**
- * Subclasses must retain their measure spec from onMeasure() into this member
- */
- int mWidthMeasureSpec = 0;
-
- /**
- * The top scroll indicator
- */
- View mScrollUp;
-
- /**
- * The down scroll indicator
- */
- View mScrollDown;
-
- /**
- * When the view is scrolling, this flag is set to true to indicate subclasses that
- * the drawing cache was enabled on the children
- */
- boolean mCachingStarted;
-
- /**
- * The position of the view that received the down motion event
- */
- int mMotionPosition;
-
- /**
- * The offset to the top of the mMotionPosition view when the down motion event was received
- */
- int mMotionViewOriginalTop;
-
- /**
- * The desired offset to the top of the mMotionPosition view after a scroll
- */
- int mMotionViewNewTop;
-
- /**
- * The X value associated with the the down motion event
- */
- int mMotionX;
-
- /**
- * The Y value associated with the the down motion event
- */
- int mMotionY;
-
- /**
- * One of TOUCH_MODE_REST, TOUCH_MODE_DOWN, TOUCH_MODE_TAP, TOUCH_MODE_SCROLL, or
- * TOUCH_MODE_DONE_WAITING
- */
- int mTouchMode = TOUCH_MODE_REST;
-
- /**
- * Y value from on the previous motion event (if any)
- */
- int mLastY;
-
- /**
- * How far the finger moved before we started scrolling
- */
- int mMotionCorrection;
-
- /**
- * Determines speed during touch scrolling
- */
- private VelocityTracker mVelocityTracker;
-
- /**
- * Handles one frame of a fling
- */
- private FlingRunnable mFlingRunnable;
-
- /**
- * The offset in pixels form the top of the AdapterView to the top
- * of the currently selected view. Used to save and restore state.
- */
- int mSelectedTop = 0;
-
- /**
- * Indicates whether the list is stacked from the bottom edge or
- * the top edge.
- */
- boolean mStackFromBottom;
-
- /**
- * When set to true, the list automatically discards the children's
- * bitmap cache after scrolling.
- */
- boolean mScrollingCacheEnabled;
-
- /**
- * Whether or not to enable the fast scroll feature on this list
- */
- boolean mFastScrollEnabled;
-
- /**
- * Optional callback to notify client when scroll position has changed
- */
- private OnScrollListener mOnScrollListener;
-
- /**
- * Keeps track of our accessory window
- */
- PopupWindow mPopup;
-
- /**
- * Used with type filter window
- */
- EditText mTextFilter;
-
- /**
- * Indicates whether to use pixels-based or position-based scrollbar
- * properties.
- */
- private boolean mSmoothScrollbarEnabled = true;
-
- /**
- * Indicates that this view supports filtering
- */
- private boolean mTextFilterEnabled;
-
- /**
- * Indicates that this view is currently displaying a filtered view of the data
- */
- private boolean mFiltered;
-
- /**
- * Rectangle used for hit testing children
- */
- private Rect mTouchFrame;
-
- /**
- * The position to resurrect the selected position to.
- */
- int mResurrectToPosition = INVALID_POSITION;
-
- private ContextMenuInfo mContextMenuInfo = null;
-
- /**
- * Used to request a layout when we changed touch mode
- */
- private static final int TOUCH_MODE_UNKNOWN = -1;
- private static final int TOUCH_MODE_ON = 0;
- private static final int TOUCH_MODE_OFF = 1;
-
- private int mLastTouchMode = TOUCH_MODE_UNKNOWN;
-
- private static final boolean PROFILE_SCROLLING = false;
- private boolean mScrollProfilingStarted = false;
-
- private static final boolean PROFILE_FLINGING = false;
- private boolean mFlingProfilingStarted = false;
-
- /**
- * The last CheckForLongPress runnable we posted, if any
- */
- private CheckForLongPress mPendingCheckForLongPress;
-
- /**
- * The last CheckForTap runnable we posted, if any
- */
- private Runnable mPendingCheckForTap;
-
- /**
- * The last CheckForKeyLongPress runnable we posted, if any
- */
- private CheckForKeyLongPress mPendingCheckForKeyLongPress;
-
- /**
- * Acts upon click
- */
- private AbsListView.PerformClick mPerformClick;
-
- /**
- * This view is in transcript mode -- it shows the bottom of the list when the data
- * changes
- */
- private int mTranscriptMode;
-
- /**
- * Indicates that this list is always drawn on top of a solid, single-color, opaque
- * background
- */
- private int mCacheColorHint;
-
- /**
- * The select child's view (from the adapter's getView) is enabled.
- */
- private boolean mIsChildViewEnabled;
-
- /**
- * The last scroll state reported to clients through {@link OnScrollListener}.
- */
- private int mLastScrollState = OnScrollListener.SCROLL_STATE_IDLE;
-
- /**
- * Helper object that renders and controls the fast scroll thumb.
- */
- private FastScroller mFastScroller;
-
- private int mTouchSlop;
-
- private float mDensityScale;
-
- /**
- * Interface definition for a callback to be invoked when the list or grid
- * has been scrolled.
- */
- public interface OnScrollListener {
-
- /**
- * The view is not scrolling. Note navigating the list using the trackball counts as
- * being in the idle state since these transitions are not animated.
- */
- public static int SCROLL_STATE_IDLE = 0;
-
- /**
- * The user is scrolling using touch, and their finger is still on the screen
- */
- public static int SCROLL_STATE_TOUCH_SCROLL = 1;
-
- /**
- * The user had previously been scrolling using touch and had performed a fling. The
- * animation is now coasting to a stop
- */
- public static int SCROLL_STATE_FLING = 2;
-
- /**
- * Callback method to be invoked while the list view or grid view is being scrolled. If the
- * view is being scrolled, this method will be called before the next frame of the scroll is
- * rendered. In particular, it will be called before any calls to
- * {@link Adapter#getView(int, View, ViewGroup)}.
- *
- * @param view The view whose scroll state is being reported
- *
- * @param scrollState The current scroll state. One of {@link #SCROLL_STATE_IDLE},
- * {@link #SCROLL_STATE_TOUCH_SCROLL} or {@link #SCROLL_STATE_IDLE}.
- */
- public void onScrollStateChanged(AbsListView view, int scrollState);
-
- /**
- * Callback method to be invoked when the list or grid has been scrolled. This will be
- * called after the scroll has completed
- * @param view The view whose scroll state is being reported
- * @param firstVisibleItem the index of the first visible cell (ignore if
- * visibleItemCount == 0)
- * @param visibleItemCount the number of visible cells
- * @param totalItemCount the number of items in the list adaptor
- */
- public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
- int totalItemCount);
- }
-
- public AbsListView(Context context) {
- super(context);
- initAbsListView();
-
- setVerticalScrollBarEnabled(true);
- TypedArray a = context.obtainStyledAttributes(R.styleable.View);
- initializeScrollbars(a);
- a.recycle();
- }
-
- public AbsListView(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.absListViewStyle);
- }
-
- public AbsListView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- initAbsListView();
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.AbsListView, defStyle, 0);
-
- Drawable d = a.getDrawable(com.android.internal.R.styleable.AbsListView_listSelector);
- if (d != null) {
- setSelector(d);
- }
-
- mDrawSelectorOnTop = a.getBoolean(
- com.android.internal.R.styleable.AbsListView_drawSelectorOnTop, false);
-
- boolean stackFromBottom = a.getBoolean(R.styleable.AbsListView_stackFromBottom, false);
- setStackFromBottom(stackFromBottom);
-
- boolean scrollingCacheEnabled = a.getBoolean(R.styleable.AbsListView_scrollingCache, true);
- setScrollingCacheEnabled(scrollingCacheEnabled);
-
- boolean useTextFilter = a.getBoolean(R.styleable.AbsListView_textFilterEnabled, false);
- setTextFilterEnabled(useTextFilter);
-
- int transcriptMode = a.getInt(R.styleable.AbsListView_transcriptMode,
- TRANSCRIPT_MODE_DISABLED);
- setTranscriptMode(transcriptMode);
-
- int color = a.getColor(R.styleable.AbsListView_cacheColorHint, 0);
- setCacheColorHint(color);
-
- boolean enableFastScroll = a.getBoolean(R.styleable.AbsListView_fastScrollEnabled, false);
- setFastScrollEnabled(enableFastScroll);
-
- boolean smoothScrollbar = a.getBoolean(R.styleable.AbsListView_smoothScrollbar, true);
- setSmoothScrollbarEnabled(smoothScrollbar);
-
- a.recycle();
- }
-
- /**
- * Enables fast scrolling by letting the user quickly scroll through lists by
- * dragging the fast scroll thumb. The adapter attached to the list may want
- * to implement {@link SectionIndexer} if it wishes to display alphabet preview and
- * jump between sections of the list.
- * @see SectionIndexer
- * @see #isFastScrollEnabled()
- * @param enabled whether or not to enable fast scrolling
- */
- public void setFastScrollEnabled(boolean enabled) {
- mFastScrollEnabled = enabled;
- if (enabled) {
- if (mFastScroller == null) {
- mFastScroller = new FastScroller(getContext(), this);
- }
- } else {
- if (mFastScroller != null) {
- mFastScroller.stop();
- mFastScroller = null;
- }
- }
- }
-
- /**
- * Returns the current state of the fast scroll feature.
- * @see #setFastScrollEnabled(boolean)
- * @return true if fast scroll is enabled, false otherwise
- */
- @ViewDebug.ExportedProperty
- public boolean isFastScrollEnabled() {
- return mFastScrollEnabled;
- }
-
- /**
- * If fast scroll is visible, then don't draw the vertical scrollbar.
- * @hide
- */
- @Override
- protected boolean isVerticalScrollBarHidden() {
- return mFastScroller != null && mFastScroller.isVisible();
- }
-
- /**
- * When smooth scrollbar is enabled, the position and size of the scrollbar thumb
- * is computed based on the number of visible pixels in the visible items. This
- * however assumes that all list items have the same height. If you use a list in
- * which items have different heights, the scrollbar will change appearance as the
- * user scrolls through the list. To avoid this issue, you need to disable this
- * property.
- *
- * When smooth scrollbar is disabled, the position and size of the scrollbar thumb
- * is based solely on the number of items in the adapter and the position of the
- * visible items inside the adapter. This provides a stable scrollbar as the user
- * navigates through a list of items with varying heights.
- *
- * @param enabled Whether or not to enable smooth scrollbar.
- *
- * @see #setSmoothScrollbarEnabled(boolean)
- * @attr ref android.R.styleable#AbsListView_smoothScrollbar
- */
- public void setSmoothScrollbarEnabled(boolean enabled) {
- mSmoothScrollbarEnabled = enabled;
- }
-
- /**
- * Returns the current state of the fast scroll feature.
- *
- * @return True if smooth scrollbar is enabled is enabled, false otherwise.
- *
- * @see #setSmoothScrollbarEnabled(boolean)
- */
- @ViewDebug.ExportedProperty
- public boolean isSmoothScrollbarEnabled() {
- return mSmoothScrollbarEnabled;
- }
-
- /**
- * Set the listener that will receive notifications every time the list scrolls.
- *
- * @param l the scroll listener
- */
- public void setOnScrollListener(OnScrollListener l) {
- mOnScrollListener = l;
- invokeOnItemScrollListener();
- }
-
- /**
- * Notify our scroll listener (if there is one) of a change in scroll state
- */
- void invokeOnItemScrollListener() {
- if (mFastScroller != null) {
- mFastScroller.onScroll(this, mFirstPosition, getChildCount(), mItemCount);
- }
- if (mOnScrollListener != null) {
- mOnScrollListener.onScroll(this, mFirstPosition, getChildCount(), mItemCount);
- }
- }
-
- /**
- * Indicates whether the children's drawing cache is used during a scroll.
- * By default, the drawing cache is enabled but this will consume more memory.
- *
- * @return true if the scrolling cache is enabled, false otherwise
- *
- * @see #setScrollingCacheEnabled(boolean)
- * @see View#setDrawingCacheEnabled(boolean)
- */
- @ViewDebug.ExportedProperty
- public boolean isScrollingCacheEnabled() {
- return mScrollingCacheEnabled;
- }
-
- /**
- * Enables or disables the children's drawing cache during a scroll.
- * By default, the drawing cache is enabled but this will use more memory.
- *
- * When the scrolling cache is enabled, the caches are kept after the
- * first scrolling. You can manually clear the cache by calling
- * {@link android.view.ViewGroup#setChildrenDrawingCacheEnabled(boolean)}.
- *
- * @param enabled true to enable the scroll cache, false otherwise
- *
- * @see #isScrollingCacheEnabled()
- * @see View#setDrawingCacheEnabled(boolean)
- */
- public void setScrollingCacheEnabled(boolean enabled) {
- if (mScrollingCacheEnabled && !enabled) {
- clearScrollingCache();
- }
- mScrollingCacheEnabled = enabled;
- }
-
- /**
- * Enables or disables the type filter window. If enabled, typing when
- * this view has focus will filter the children to match the users input.
- * Note that the {@link Adapter} used by this view must implement the
- * {@link Filterable} interface.
- *
- * @param textFilterEnabled true to enable type filtering, false otherwise
- *
- * @see Filterable
- */
- public void setTextFilterEnabled(boolean textFilterEnabled) {
- mTextFilterEnabled = textFilterEnabled;
- }
-
- /**
- * Indicates whether type filtering is enabled for this view
- *
- * @return true if type filtering is enabled, false otherwise
- *
- * @see #setTextFilterEnabled(boolean)
- * @see Filterable
- */
- @ViewDebug.ExportedProperty
- public boolean isTextFilterEnabled() {
- return mTextFilterEnabled;
- }
-
- @Override
- public void getFocusedRect(Rect r) {
- View view = getSelectedView();
- if (view != null) {
- // the focused rectangle of the selected view offset into the
- // coordinate space of this view.
- view.getFocusedRect(r);
- offsetDescendantRectToMyCoords(view, r);
- } else {
- // otherwise, just the norm
- super.getFocusedRect(r);
- }
- }
-
- private void initAbsListView() {
- // Setting focusable in touch mode will set the focusable property to true
- setFocusableInTouchMode(true);
- setWillNotDraw(false);
- setAlwaysDrawnWithCacheEnabled(false);
- setScrollingCacheEnabled(true);
-
- mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
- mDensityScale = getContext().getResources().getDisplayMetrics().density;
- }
-
- private void useDefaultSelector() {
- setSelector(getResources().getDrawable(
- com.android.internal.R.drawable.list_selector_background));
- }
-
- /**
- * Indicates whether the content of this view is pinned to, or stacked from,
- * the bottom edge.
- *
- * @return true if the content is stacked from the bottom edge, false otherwise
- */
- @ViewDebug.ExportedProperty
- public boolean isStackFromBottom() {
- return mStackFromBottom;
- }
-
- /**
- * When stack from bottom is set to true, the list fills its content starting from
- * the bottom of the view.
- *
- * @param stackFromBottom true to pin the view's content to the bottom edge,
- * false to pin the view's content to the top edge
- */
- public void setStackFromBottom(boolean stackFromBottom) {
- if (mStackFromBottom != stackFromBottom) {
- mStackFromBottom = stackFromBottom;
- requestLayoutIfNecessary();
- }
- }
-
- void requestLayoutIfNecessary() {
- if (getChildCount() > 0) {
- resetList();
- requestLayout();
- invalidate();
- }
- }
-
- static class SavedState extends BaseSavedState {
- long selectedId;
- long firstId;
- int viewTop;
- int position;
- int height;
- String filter;
-
- /**
- * Constructor called from {@link AbsListView#onSaveInstanceState()}
- */
- SavedState(Parcelable superState) {
- super(superState);
- }
-
- /**
- * Constructor called from {@link #CREATOR}
- */
- private SavedState(Parcel in) {
- super(in);
- selectedId = in.readLong();
- firstId = in.readLong();
- viewTop = in.readInt();
- position = in.readInt();
- height = in.readInt();
- filter = in.readString();
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- super.writeToParcel(out, flags);
- out.writeLong(selectedId);
- out.writeLong(firstId);
- out.writeInt(viewTop);
- out.writeInt(position);
- out.writeInt(height);
- out.writeString(filter);
- }
-
- @Override
- public String toString() {
- return "AbsListView.SavedState{"
- + Integer.toHexString(System.identityHashCode(this))
- + " selectedId=" + selectedId
- + " firstId=" + firstId
- + " viewTop=" + viewTop
- + " position=" + position
- + " height=" + height
- + " filter=" + filter + "}";
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR
- = new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
- @Override
- public Parcelable onSaveInstanceState() {
- /*
- * This doesn't really make sense as the place to dismiss the
- * popup, but there don't seem to be any other useful hooks
- * that happen early enough to keep from getting complaints
- * about having leaked the window.
- */
- dismissPopup();
-
- Parcelable superState = super.onSaveInstanceState();
-
- SavedState ss = new SavedState(superState);
-
- boolean haveChildren = getChildCount() > 0;
- long selectedId = getSelectedItemId();
- ss.selectedId = selectedId;
- ss.height = getHeight();
-
- if (selectedId >= 0) {
- // Remember the selection
- ss.viewTop = mSelectedTop;
- ss.position = getSelectedItemPosition();
- ss.firstId = INVALID_POSITION;
- } else {
- if (haveChildren) {
- // Remember the position of the first child
- View v = getChildAt(0);
- ss.viewTop = v.getTop();
- ss.position = mFirstPosition;
- ss.firstId = mAdapter.getItemId(mFirstPosition);
- } else {
- ss.viewTop = 0;
- ss.firstId = INVALID_POSITION;
- ss.position = 0;
- }
- }
-
- ss.filter = null;
- if (mFiltered) {
- final EditText textFilter = mTextFilter;
- if (textFilter != null) {
- Editable filterText = textFilter.getText();
- if (filterText != null) {
- ss.filter = filterText.toString();
- }
- }
- }
-
- return ss;
- }
-
- @Override
- public void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
-
- super.onRestoreInstanceState(ss.getSuperState());
- mDataChanged = true;
-
- mSyncHeight = ss.height;
-
- if (ss.selectedId >= 0) {
- mNeedSync = true;
- mSyncRowId = ss.selectedId;
- mSyncPosition = ss.position;
- mSpecificTop = ss.viewTop;
- mSyncMode = SYNC_SELECTED_POSITION;
- } else if (ss.firstId >= 0) {
- setSelectedPositionInt(INVALID_POSITION);
- // Do this before setting mNeedSync since setNextSelectedPosition looks at mNeedSync
- setNextSelectedPositionInt(INVALID_POSITION);
- mNeedSync = true;
- mSyncRowId = ss.firstId;
- mSyncPosition = ss.position;
- mSpecificTop = ss.viewTop;
- mSyncMode = SYNC_FIRST_POSITION;
- }
-
- // Don't restore the type filter window when there is no keyboard
- if (acceptFilter()) {
- String filterText = ss.filter;
- setFilterText(filterText);
- }
-
- requestLayout();
- }
-
- private boolean acceptFilter() {
- final Context context = mContext;
- final Configuration configuration = context.getResources().getConfiguration();
- final boolean keyboardShowing = configuration.keyboardHidden !=
- Configuration.KEYBOARDHIDDEN_YES;
- final boolean hasKeyboard = configuration.keyboard != Configuration.KEYBOARD_NOKEYS;
- final InputMethodManager inputManager = (InputMethodManager)
- context.getSystemService(Context.INPUT_METHOD_SERVICE);
- return (hasKeyboard && keyboardShowing) ||
- (!hasKeyboard && !inputManager.isFullscreenMode());
- }
-
- /**
- * Sets the initial value for the text filter.
- * @param filterText The text to use for the filter.
- *
- * @see #setTextFilterEnabled
- */
- public void setFilterText(String filterText) {
- // TODO: Should we check for acceptFilter()?
- if (mTextFilterEnabled && filterText != null && filterText.length() > 0) {
- createTextFilter(false);
- // This is going to call our listener onTextChanged, but we might not
- // be ready to bring up a window yet
- mTextFilter.setText(filterText);
- mTextFilter.setSelection(filterText.length());
- if (mAdapter instanceof Filterable) {
- // if mPopup is non-null, then onTextChanged will do the filtering
- if (mPopup == null) {
- Filter f = ((Filterable) mAdapter).getFilter();
- f.filter(filterText);
- }
- // Set filtered to true so we will display the filter window when our main
- // window is ready
- mFiltered = true;
- mDataSetObserver.clearSavedState();
- }
- }
- }
-
- @Override
- protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
- super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
- if (gainFocus && mSelectedPosition < 0 && !isInTouchMode()) {
- resurrectSelection();
- }
- }
-
- @Override
- public void requestLayout() {
- if (!mBlockLayoutRequests && !mInLayout) {
- super.requestLayout();
- }
- }
-
- /**
- * The list is empty. Clear everything out.
- */
- void resetList() {
- removeAllViewsInLayout();
- mFirstPosition = 0;
- mDataChanged = false;
- mNeedSync = false;
- mOldSelectedPosition = INVALID_POSITION;
- mOldSelectedRowId = INVALID_ROW_ID;
- setSelectedPositionInt(INVALID_POSITION);
- setNextSelectedPositionInt(INVALID_POSITION);
- mSelectedTop = 0;
- mSelectorRect.setEmpty();
- invalidate();
- }
-
- @Override
- protected int computeVerticalScrollExtent() {
- final int count = getChildCount();
- if (count > 0) {
- if (mSmoothScrollbarEnabled) {
- int extent = count * 100;
-
- View view = getChildAt(0);
- final int top = view.getTop();
- int height = view.getHeight();
- if (height > 0) {
- extent += (top * 100) / height;
- }
-
- view = getChildAt(count - 1);
- final int bottom = view.getBottom();
- height = view.getHeight();
- if (height > 0) {
- extent -= ((bottom - getHeight()) * 100) / height;
- }
-
- return extent;
- } else {
- return 1;
- }
- }
- return 0;
- }
-
- @Override
- protected int computeVerticalScrollOffset() {
- final int firstPosition = mFirstPosition;
- final int childCount = getChildCount();
- if (firstPosition >= 0 && childCount > 0) {
- if (mSmoothScrollbarEnabled) {
- final View view = getChildAt(0);
- final int top = view.getTop();
- int height = view.getHeight();
- if (height > 0) {
- return Math.max(firstPosition * 100 - (top * 100) / height, 0);
- }
- } else {
- int index;
- final int count = mItemCount;
- if (firstPosition == 0) {
- index = 0;
- } else if (firstPosition + childCount == count) {
- index = count;
- } else {
- index = firstPosition + childCount / 2;
- }
- return (int) (firstPosition + childCount * (index / (float) count));
- }
- }
- return 0;
- }
-
- @Override
- protected int computeVerticalScrollRange() {
- return mSmoothScrollbarEnabled ? Math.max(mItemCount * 100, 0) : mItemCount;
- }
-
- @Override
- protected float getTopFadingEdgeStrength() {
- final int count = getChildCount();
- final float fadeEdge = super.getTopFadingEdgeStrength();
- if (count == 0) {
- return fadeEdge;
- } else {
- if (mFirstPosition > 0) {
- return 1.0f;
- }
-
- final int top = getChildAt(0).getTop();
- final float fadeLength = (float) getVerticalFadingEdgeLength();
- return top < mPaddingTop ? (float) -(top - mPaddingTop) / fadeLength : fadeEdge;
- }
- }
-
- @Override
- protected float getBottomFadingEdgeStrength() {
- final int count = getChildCount();
- final float fadeEdge = super.getBottomFadingEdgeStrength();
- if (count == 0) {
- return fadeEdge;
- } else {
- if (mFirstPosition + count - 1 < mItemCount - 1) {
- return 1.0f;
- }
-
- final int bottom = getChildAt(count - 1).getBottom();
- final int height = getHeight();
- final float fadeLength = (float) getVerticalFadingEdgeLength();
- return bottom > height - mPaddingBottom ?
- (float) (bottom - height + mPaddingBottom) / fadeLength : fadeEdge;
- }
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (mSelector == null) {
- useDefaultSelector();
- }
- final Rect listPadding = mListPadding;
- listPadding.left = mSelectionLeftPadding + mPaddingLeft;
- listPadding.top = mSelectionTopPadding + mPaddingTop;
- listPadding.right = mSelectionRightPadding + mPaddingRight;
- listPadding.bottom = mSelectionBottomPadding + mPaddingBottom;
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
- mInLayout = true;
- layoutChildren();
- mInLayout = false;
- }
-
- /**
- * @hide
- */
- @Override
- protected boolean setFrame(int left, int top, int right, int bottom) {
- final boolean changed = super.setFrame(left, top, right, bottom);
-
- // Reposition the popup when the frame has changed. This includes
- // translating the widget, not just changing its dimension. The
- // filter popup needs to follow the widget.
- if (mFiltered && changed && getWindowVisibility() == View.VISIBLE && mPopup != null &&
- mPopup.isShowing()) {
- positionPopup(true);
- }
-
- return changed;
- }
-
- protected void layoutChildren() {
- }
-
- void updateScrollIndicators() {
- if (mScrollUp != null) {
- boolean canScrollUp;
- // 0th element is not visible
- canScrollUp = mFirstPosition > 0;
-
- // ... Or top of 0th element is not visible
- if (!canScrollUp) {
- if (getChildCount() > 0) {
- View child = getChildAt(0);
- canScrollUp = child.getTop() < mListPadding.top;
- }
- }
-
- mScrollUp.setVisibility(canScrollUp ? View.VISIBLE : View.INVISIBLE);
- }
-
- if (mScrollDown != null) {
- boolean canScrollDown;
- int count = getChildCount();
-
- // Last item is not visible
- canScrollDown = (mFirstPosition + count) < mItemCount;
-
- // ... Or bottom of the last element is not visible
- if (!canScrollDown && count > 0) {
- View child = getChildAt(count - 1);
- canScrollDown = child.getBottom() > mBottom - mListPadding.bottom;
- }
-
- mScrollDown.setVisibility(canScrollDown ? View.VISIBLE : View.INVISIBLE);
- }
- }
-
- @Override
- @ViewDebug.ExportedProperty
- public View getSelectedView() {
- if (mItemCount > 0 && mSelectedPosition >= 0) {
- return getChildAt(mSelectedPosition - mFirstPosition);
- } else {
- return null;
- }
- }
-
- /**
- * List padding is the maximum of the normal view's padding and the padding of the selector.
- *
- * @see android.view.View#getPaddingTop()
- * @see #getSelector()
- *
- * @return The top list padding.
- */
- public int getListPaddingTop() {
- return mListPadding.top;
- }
-
- /**
- * List padding is the maximum of the normal view's padding and the padding of the selector.
- *
- * @see android.view.View#getPaddingBottom()
- * @see #getSelector()
- *
- * @return The bottom list padding.
- */
- public int getListPaddingBottom() {
- return mListPadding.bottom;
- }
-
- /**
- * List padding is the maximum of the normal view's padding and the padding of the selector.
- *
- * @see android.view.View#getPaddingLeft()
- * @see #getSelector()
- *
- * @return The left list padding.
- */
- public int getListPaddingLeft() {
- return mListPadding.left;
- }
-
- /**
- * List padding is the maximum of the normal view's padding and the padding of the selector.
- *
- * @see android.view.View#getPaddingRight()
- * @see #getSelector()
- *
- * @return The right list padding.
- */
- public int getListPaddingRight() {
- return mListPadding.right;
- }
-
- /**
- * Get a view and have it show the data associated with the specified
- * position. This is called when we have already discovered that the view is
- * not available for reuse in the recycle bin. The only choices left are
- * converting an old view or making a new one.
- *
- * @param position The position to display
- * @return A view displaying the data associated with the specified position
- */
- View obtainView(int position) {
- View scrapView;
-
- scrapView = mRecycler.getScrapView(position);
-
- View child;
- if (scrapView != null) {
- if (ViewDebug.TRACE_RECYCLER) {
- ViewDebug.trace(scrapView, ViewDebug.RecyclerTraceType.RECYCLE_FROM_SCRAP_HEAP,
- position, -1);
- }
-
- child = mAdapter.getView(position, scrapView, this);
-
- if (ViewDebug.TRACE_RECYCLER) {
- ViewDebug.trace(child, ViewDebug.RecyclerTraceType.BIND_VIEW,
- position, getChildCount());
- }
-
- if (child != scrapView) {
- mRecycler.addScrapView(scrapView);
- if (mCacheColorHint != 0) {
- child.setDrawingCacheBackgroundColor(mCacheColorHint);
- }
- if (ViewDebug.TRACE_RECYCLER) {
- ViewDebug.trace(scrapView, ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP,
- position, -1);
- }
- }
- } else {
- child = mAdapter.getView(position, null, this);
- if (mCacheColorHint != 0) {
- child.setDrawingCacheBackgroundColor(mCacheColorHint);
- }
- if (ViewDebug.TRACE_RECYCLER) {
- ViewDebug.trace(child, ViewDebug.RecyclerTraceType.NEW_VIEW,
- position, getChildCount());
- }
- }
-
- return child;
- }
-
- void positionSelector(View sel) {
- final Rect selectorRect = mSelectorRect;
- selectorRect.set(sel.getLeft(), sel.getTop(), sel.getRight(), sel.getBottom());
- positionSelector(selectorRect.left, selectorRect.top, selectorRect.right,
- selectorRect.bottom);
-
- final boolean isChildViewEnabled = mIsChildViewEnabled;
- if (sel.isEnabled() != isChildViewEnabled) {
- mIsChildViewEnabled = !isChildViewEnabled;
- refreshDrawableState();
- }
- }
-
- private void positionSelector(int l, int t, int r, int b) {
- mSelectorRect.set(l - mSelectionLeftPadding, t - mSelectionTopPadding, r
- + mSelectionRightPadding, b + mSelectionBottomPadding);
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- int saveCount = 0;
- final boolean clipToPadding = (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;
- if (clipToPadding) {
- saveCount = canvas.save();
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
- canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop,
- scrollX + mRight - mLeft - mPaddingRight,
- scrollY + mBottom - mTop - mPaddingBottom);
- mGroupFlags &= ~CLIP_TO_PADDING_MASK;
- }
-
- final boolean drawSelectorOnTop = mDrawSelectorOnTop;
- if (!drawSelectorOnTop) {
- drawSelector(canvas);
- }
-
- super.dispatchDraw(canvas);
-
- if (drawSelectorOnTop) {
- drawSelector(canvas);
- }
-
- if (clipToPadding) {
- canvas.restoreToCount(saveCount);
- mGroupFlags |= CLIP_TO_PADDING_MASK;
- }
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- if (getChildCount() > 0) {
- mDataChanged = true;
- rememberSyncState();
- }
- if (mFastScroller != null) {
- mFastScroller.onSizeChanged(w, h, oldw, oldh);
- }
- }
-
- /**
- * @return True if the current touch mode requires that we draw the selector in the pressed
- * state.
- */
- boolean touchModeDrawsInPressedState() {
- // FIXME use isPressed for this
- switch (mTouchMode) {
- case TOUCH_MODE_TAP:
- case TOUCH_MODE_DONE_WAITING:
- return true;
- default:
- return false;
- }
- }
-
- /**
- * Indicates whether this view is in a state where the selector should be drawn. This will
- * happen if we have focus but are not in touch mode, or we are in the middle of displaying
- * the pressed state for an item.
- *
- * @return True if the selector should be shown
- */
- boolean shouldShowSelector() {
- return (hasFocus() && !isInTouchMode()) || touchModeDrawsInPressedState();
- }
-
- private void drawSelector(Canvas canvas) {
- if (shouldShowSelector() && mSelectorRect != null && !mSelectorRect.isEmpty()) {
- final Drawable selector = mSelector;
- selector.setBounds(mSelectorRect);
- selector.draw(canvas);
- }
- }
-
- /**
- * Controls whether the selection highlight drawable should be drawn on top of the item or
- * behind it.
- *
- * @param onTop If true, the selector will be drawn on the item it is highlighting. The default
- * is false.
- *
- * @attr ref android.R.styleable#AbsListView_drawSelectorOnTop
- */
- public void setDrawSelectorOnTop(boolean onTop) {
- mDrawSelectorOnTop = onTop;
- }
-
- /**
- * Set a Drawable that should be used to highlight the currently selected item.
- *
- * @param resID A Drawable resource to use as the selection highlight.
- *
- * @attr ref android.R.styleable#AbsListView_listSelector
- */
- public void setSelector(int resID) {
- setSelector(getResources().getDrawable(resID));
- }
-
- public void setSelector(Drawable sel) {
- if (mSelector != null) {
- mSelector.setCallback(null);
- unscheduleDrawable(mSelector);
- }
- mSelector = sel;
- Rect padding = new Rect();
- sel.getPadding(padding);
- mSelectionLeftPadding = padding.left;
- mSelectionTopPadding = padding.top;
- mSelectionRightPadding = padding.right;
- mSelectionBottomPadding = padding.bottom;
- sel.setCallback(this);
- sel.setState(getDrawableState());
- }
-
- /**
- * Returns the selector {@link android.graphics.drawable.Drawable} that is used to draw the
- * selection in the list.
- *
- * @return the drawable used to display the selector
- */
- public Drawable getSelector() {
- return mSelector;
- }
-
- /**
- * Sets the selector state to "pressed" and posts a CheckForKeyLongPress to see if
- * this is a long press.
- */
- void keyPressed() {
- Drawable selector = mSelector;
- Rect selectorRect = mSelectorRect;
- if (selector != null && (isFocused() || touchModeDrawsInPressedState())
- && selectorRect != null && !selectorRect.isEmpty()) {
-
- final View v = getChildAt(mSelectedPosition - mFirstPosition);
-
- if (v != null) v.setPressed(true);
- setPressed(true);
-
- final boolean longClickable = isLongClickable();
- Drawable d = selector.getCurrent();
- if (d != null && d instanceof TransitionDrawable) {
- if (longClickable) {
- ((TransitionDrawable) d).startTransition(ViewConfiguration
- .getLongPressTimeout());
- } else {
- ((TransitionDrawable) d).resetTransition();
- }
- }
- if (longClickable && !mDataChanged) {
- if (mPendingCheckForKeyLongPress == null) {
- mPendingCheckForKeyLongPress = new CheckForKeyLongPress();
- }
- mPendingCheckForKeyLongPress.rememberWindowAttachCount();
- postDelayed(mPendingCheckForKeyLongPress, ViewConfiguration.getLongPressTimeout());
- }
- }
- }
-
- public void setScrollIndicators(View up, View down) {
- mScrollUp = up;
- mScrollDown = down;
- }
-
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
- if (mSelector != null) {
- mSelector.setState(getDrawableState());
- }
- }
-
- @Override
- protected int[] onCreateDrawableState(int extraSpace) {
- // If the child view is enabled then do the default behavior.
- if (mIsChildViewEnabled) {
- // Common case
- return super.onCreateDrawableState(extraSpace);
- }
-
- // The selector uses this View's drawable state. The selected child view
- // is disabled, so we need to remove the enabled state from the drawable
- // states.
- final int enabledState = ENABLED_STATE_SET[0];
-
- // If we don't have any extra space, it will return one of the static state arrays,
- // and clearing the enabled state on those arrays is a bad thing! If we specify
- // we need extra space, it will create+copy into a new array that safely mutable.
- int[] state = super.onCreateDrawableState(extraSpace + 1);
- int enabledPos = -1;
- for (int i = state.length - 1; i >= 0; i--) {
- if (state[i] == enabledState) {
- enabledPos = i;
- break;
- }
- }
-
- // Remove the enabled state
- if (enabledPos >= 0) {
- System.arraycopy(state, enabledPos + 1, state, enabledPos,
- state.length - enabledPos - 1);
- }
-
- return state;
- }
-
- @Override
- public boolean verifyDrawable(Drawable dr) {
- return mSelector == dr || super.verifyDrawable(dr);
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- final ViewTreeObserver treeObserver = getViewTreeObserver();
- if (treeObserver != null) {
- treeObserver.addOnTouchModeChangeListener(this);
- }
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
- final ViewTreeObserver treeObserver = getViewTreeObserver();
- if (treeObserver != null) {
- treeObserver.removeOnTouchModeChangeListener(this);
- }
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasWindowFocus) {
- super.onWindowFocusChanged(hasWindowFocus);
-
- final int touchMode = isInTouchMode() ? TOUCH_MODE_ON : TOUCH_MODE_OFF;
-
- if (!hasWindowFocus) {
- setChildrenDrawingCacheEnabled(false);
- removeCallbacks(mFlingRunnable);
- // Always hide the type filter
- dismissPopup();
-
- if (touchMode == TOUCH_MODE_OFF) {
- // Remember the last selected element
- mResurrectToPosition = mSelectedPosition;
- }
- } else {
- if (mFiltered) {
- // Show the type filter only if a filter is in effect
- showPopup();
- }
-
- // If we changed touch mode since the last time we had focus
- if (touchMode != mLastTouchMode && mLastTouchMode != TOUCH_MODE_UNKNOWN) {
- // If we come back in trackball mode, we bring the selection back
- if (touchMode == TOUCH_MODE_OFF) {
- // This will trigger a layout
- resurrectSelection();
-
- // If we come back in touch mode, then we want to hide the selector
- } else {
- hideSelector();
- mLayoutMode = LAYOUT_NORMAL;
- layoutChildren();
- }
- }
- }
-
- mLastTouchMode = touchMode;
- }
-
- /**
- * Creates the ContextMenuInfo returned from {@link #getContextMenuInfo()}. This
- * methods knows the view, position and ID of the item that received the
- * long press.
- *
- * @param view The view that received the long press.
- * @param position The position of the item that received the long press.
- * @param id The ID of the item that received the long press.
- * @return The extra information that should be returned by
- * {@link #getContextMenuInfo()}.
- */
- ContextMenuInfo createContextMenuInfo(View view, int position, long id) {
- return new AdapterContextMenuInfo(view, position, id);
- }
-
- /**
- * A base class for Runnables that will check that their view is still attached to
- * the original window as when the Runnable was created.
- *
- */
- private class WindowRunnnable {
- private int mOriginalAttachCount;
-
- public void rememberWindowAttachCount() {
- mOriginalAttachCount = getWindowAttachCount();
- }
-
- public boolean sameWindow() {
- return hasWindowFocus() && getWindowAttachCount() == mOriginalAttachCount;
- }
- }
-
- private class PerformClick extends WindowRunnnable implements Runnable {
- View mChild;
- int mClickMotionPosition;
-
- public void run() {
- // The data has changed since we posted this action in the event queue,
- // bail out before bad things happen
- if (mDataChanged) return;
-
- if (mAdapter != null && mItemCount > 0 &&
- mClickMotionPosition < mAdapter.getCount() && sameWindow()) {
- performItemClick(mChild, mClickMotionPosition, getAdapter().getItemId(
- mClickMotionPosition));
- }
- }
- }
-
- private class CheckForLongPress extends WindowRunnnable implements Runnable {
- public void run() {
- final int motionPosition = mMotionPosition;
- final View child = getChildAt(motionPosition - mFirstPosition);
- if (child != null) {
- final int longPressPosition = mMotionPosition;
- final long longPressId = mAdapter.getItemId(mMotionPosition);
-
- boolean handled = false;
- if (sameWindow() && !mDataChanged) {
- handled = performLongPress(child, longPressPosition, longPressId);
- }
- if (handled) {
- mTouchMode = TOUCH_MODE_REST;
- setPressed(false);
- child.setPressed(false);
- } else {
- mTouchMode = TOUCH_MODE_DONE_WAITING;
- }
-
- }
- }
- }
-
- private class CheckForKeyLongPress extends WindowRunnnable implements Runnable {
- public void run() {
- if (isPressed() && mSelectedPosition >= 0) {
- int index = mSelectedPosition - mFirstPosition;
- View v = getChildAt(index);
-
- if (!mDataChanged) {
- boolean handled = false;
- if (sameWindow()) {
- handled = performLongPress(v, mSelectedPosition, mSelectedRowId);
- }
- if (handled) {
- setPressed(false);
- v.setPressed(false);
- }
- } else {
- setPressed(false);
- if (v != null) v.setPressed(false);
- }
- }
- }
- }
-
- private boolean performLongPress(final View child,
- final int longPressPosition, final long longPressId) {
- boolean handled = false;
-
- if (mOnItemLongClickListener != null) {
- handled = mOnItemLongClickListener.onItemLongClick(AbsListView.this, child,
- longPressPosition, longPressId);
- }
- if (!handled) {
- mContextMenuInfo = createContextMenuInfo(child, longPressPosition, longPressId);
- handled = super.showContextMenuForChild(AbsListView.this);
- }
- if (handled) {
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- }
- return handled;
- }
-
- @Override
- protected ContextMenuInfo getContextMenuInfo() {
- return mContextMenuInfo;
- }
-
- @Override
- public boolean showContextMenuForChild(View originalView) {
- final int longPressPosition = getPositionForView(originalView);
- if (longPressPosition >= 0) {
- final long longPressId = mAdapter.getItemId(longPressPosition);
- boolean handled = false;
-
- if (mOnItemLongClickListener != null) {
- handled = mOnItemLongClickListener.onItemLongClick(AbsListView.this, originalView,
- longPressPosition, longPressId);
- }
- if (!handled) {
- mContextMenuInfo = createContextMenuInfo(
- getChildAt(longPressPosition - mFirstPosition),
- longPressPosition, longPressId);
- handled = super.showContextMenuForChild(originalView);
- }
-
- return handled;
- }
- return false;
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_ENTER:
- if (isPressed() && mSelectedPosition >= 0 && mAdapter != null &&
- mSelectedPosition < mAdapter.getCount()) {
- final View view = getChildAt(mSelectedPosition - mFirstPosition);
- performItemClick(view, mSelectedPosition, mSelectedRowId);
- setPressed(false);
- if (view != null) view.setPressed(false);
- return true;
- }
- }
- return super.onKeyUp(keyCode, event);
- }
-
- @Override
- protected void dispatchSetPressed(boolean pressed) {
- // Don't dispatch setPressed to our children. We call setPressed on ourselves to
- // get the selector in the right state, but we don't want to press each child.
- }
-
- /**
- * Maps a point to a position in the list.
- *
- * @param x X in local coordinate
- * @param y Y in local coordinate
- * @return The position of the item which contains the specified point, or
- * {@link #INVALID_POSITION} if the point does not intersect an item.
- */
- public int pointToPosition(int x, int y) {
- Rect frame = mTouchFrame;
- if (frame == null) {
- mTouchFrame = new Rect();
- frame = mTouchFrame;
- }
-
- final int count = getChildCount();
- for (int i = count - 1; i >= 0; i--) {
- final View child = getChildAt(i);
- if (child.getVisibility() == View.VISIBLE) {
- child.getHitRect(frame);
- if (frame.contains(x, y)) {
- return mFirstPosition + i;
- }
- }
- }
- return INVALID_POSITION;
- }
-
-
- /**
- * Maps a point to a the rowId of the item which intersects that point.
- *
- * @param x X in local coordinate
- * @param y Y in local coordinate
- * @return The rowId of the item which contains the specified point, or {@link #INVALID_ROW_ID}
- * if the point does not intersect an item.
- */
- public long pointToRowId(int x, int y) {
- int position = pointToPosition(x, y);
- if (position >= 0) {
- return mAdapter.getItemId(position);
- }
- return INVALID_ROW_ID;
- }
-
- final class CheckForTap implements Runnable {
- public void run() {
- if (mTouchMode == TOUCH_MODE_DOWN) {
- mTouchMode = TOUCH_MODE_TAP;
- final View child = getChildAt(mMotionPosition - mFirstPosition);
- if (child != null && !child.hasFocusable()) {
- mLayoutMode = LAYOUT_NORMAL;
-
- if (!mDataChanged) {
- layoutChildren();
- child.setPressed(true);
- positionSelector(child);
- setPressed(true);
-
- final int longPressTimeout = ViewConfiguration.getLongPressTimeout();
- final boolean longClickable = isLongClickable();
-
- if (mSelector != null) {
- Drawable d = mSelector.getCurrent();
- if (d != null && d instanceof TransitionDrawable) {
- if (longClickable) {
- ((TransitionDrawable) d).startTransition(longPressTimeout);
- } else {
- ((TransitionDrawable) d).resetTransition();
- }
- }
- }
-
- if (longClickable) {
- if (mPendingCheckForLongPress == null) {
- mPendingCheckForLongPress = new CheckForLongPress();
- }
- mPendingCheckForLongPress.rememberWindowAttachCount();
- postDelayed(mPendingCheckForLongPress, longPressTimeout);
- } else {
- mTouchMode = TOUCH_MODE_DONE_WAITING;
- }
- } else {
- mTouchMode = TOUCH_MODE_DONE_WAITING;
- }
- }
- }
- }
- }
-
- private boolean startScrollIfNeeded(int deltaY) {
- // Check if we have moved far enough that it looks more like a
- // scroll than a tap
- final int distance = Math.abs(deltaY);
- if (distance > mTouchSlop) {
- createScrollingCache();
- mTouchMode = TOUCH_MODE_SCROLL;
- mMotionCorrection = deltaY;
- final Handler handler = getHandler();
- // Handler should not be null unless the AbsListView is not attached to a
- // window, which would make it very hard to scroll it... but the monkeys
- // say it's possible.
- if (handler != null) {
- handler.removeCallbacks(mPendingCheckForLongPress);
- }
- setPressed(false);
- View motionView = getChildAt(mMotionPosition - mFirstPosition);
- if (motionView != null) {
- motionView.setPressed(false);
- }
- reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
- // Time to start stealing events! Once we've stolen them, don't let anyone
- // steal from us
- requestDisallowInterceptTouchEvent(true);
- return true;
- }
-
- return false;
- }
-
- public void onTouchModeChanged(boolean isInTouchMode) {
- if (isInTouchMode) {
- // Get rid of the selection when we enter touch mode
- hideSelector();
- // Layout, but only if we already have done so previously.
- // (Otherwise may clobber a LAYOUT_SYNC layout that was requested to restore
- // state.)
- if (getHeight() > 0 && getChildCount() > 0) {
- // We do not lose focus initiating a touch (since AbsListView is focusable in
- // touch mode). Force an initial layout to get rid of the selection.
- mLayoutMode = LAYOUT_NORMAL;
- layoutChildren();
- }
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
-
- if (mFastScroller != null) {
- boolean intercepted = mFastScroller.onTouchEvent(ev);
- if (intercepted) {
- return true;
- }
- }
- final int action = ev.getAction();
- final int x = (int) ev.getX();
- final int y = (int) ev.getY();
-
- View v;
- int deltaY;
-
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(ev);
-
- switch (action) {
- case MotionEvent.ACTION_DOWN: {
- int motionPosition = pointToPosition(x, y);
- if (!mDataChanged) {
- if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
- && (getAdapter().isEnabled(motionPosition))) {
- // User clicked on an actual view (and was not stopping a fling). It might be a
- // click or a scroll. Assume it is a click until proven otherwise
- mTouchMode = TOUCH_MODE_DOWN;
- // FIXME Debounce
- if (mPendingCheckForTap == null) {
- mPendingCheckForTap = new CheckForTap();
- }
- postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
- } else {
- if (ev.getEdgeFlags() != 0 && motionPosition < 0) {
- // If we couldn't find a view to click on, but the down event was touching
- // the edge, we will bail out and try again. This allows the edge correcting
- // code in ViewRoot to try to find a nearby view to select
- return false;
- }
- // User clicked on whitespace, or stopped a fling. It is a scroll.
- createScrollingCache();
- mTouchMode = TOUCH_MODE_SCROLL;
- motionPosition = findMotionRow(y);
- reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
- }
- }
-
- if (motionPosition >= 0) {
- // Remember where the motion event started
- v = getChildAt(motionPosition - mFirstPosition);
- mMotionViewOriginalTop = v.getTop();
- mMotionX = x;
- mMotionY = y;
- mMotionPosition = motionPosition;
- }
- mLastY = Integer.MIN_VALUE;
- break;
- }
-
- case MotionEvent.ACTION_MOVE: {
- deltaY = y - mMotionY;
- switch (mTouchMode) {
- case TOUCH_MODE_DOWN:
- case TOUCH_MODE_TAP:
- case TOUCH_MODE_DONE_WAITING:
- // Check if we have moved far enough that it looks more like a
- // scroll than a tap
- startScrollIfNeeded(deltaY);
- break;
- case TOUCH_MODE_SCROLL:
- if (PROFILE_SCROLLING) {
- if (!mScrollProfilingStarted) {
- Debug.startMethodTracing("AbsListViewScroll");
- mScrollProfilingStarted = true;
- }
- }
-
- if (y != mLastY) {
- deltaY -= mMotionCorrection;
- int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY;
- trackMotionScroll(deltaY, incrementalDeltaY);
-
- // Check to see if we have bumped into the scroll limit
- View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
- if (motionView != null) {
- // Check if the top of the motion view is where it is
- // supposed to be
- if (motionView.getTop() != mMotionViewNewTop) {
- // We did not scroll the full amount. Treat this essentially like the
- // start of a new touch scroll
- final int motionPosition = findMotionRow(y);
-
- mMotionCorrection = 0;
- motionView = getChildAt(motionPosition - mFirstPosition);
- mMotionViewOriginalTop = motionView.getTop();
- mMotionY = y;
- mMotionPosition = motionPosition;
- }
- }
- mLastY = y;
- }
- break;
- }
-
- break;
- }
-
- case MotionEvent.ACTION_UP: {
- switch (mTouchMode) {
- case TOUCH_MODE_DOWN:
- case TOUCH_MODE_TAP:
- case TOUCH_MODE_DONE_WAITING:
- final int motionPosition = mMotionPosition;
- final View child = getChildAt(motionPosition - mFirstPosition);
- if (child != null && !child.hasFocusable()) {
- if (mTouchMode != TOUCH_MODE_DOWN) {
- child.setPressed(false);
- }
-
- if (mPerformClick == null) {
- mPerformClick = new PerformClick();
- }
-
- final AbsListView.PerformClick performClick = mPerformClick;
- performClick.mChild = child;
- performClick.mClickMotionPosition = motionPosition;
- performClick.rememberWindowAttachCount();
-
- mResurrectToPosition = motionPosition;
-
- if (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP) {
- final Handler handler = getHandler();
- if (handler != null) {
- handler.removeCallbacks(mTouchMode == TOUCH_MODE_DOWN ?
- mPendingCheckForTap : mPendingCheckForLongPress);
- }
- mLayoutMode = LAYOUT_NORMAL;
- mTouchMode = TOUCH_MODE_TAP;
- if (!mDataChanged) {
- setSelectedPositionInt(mMotionPosition);
- layoutChildren();
- child.setPressed(true);
- positionSelector(child);
- setPressed(true);
- if (mSelector != null) {
- Drawable d = mSelector.getCurrent();
- if (d != null && d instanceof TransitionDrawable) {
- ((TransitionDrawable)d).resetTransition();
- }
- }
- postDelayed(new Runnable() {
- public void run() {
- child.setPressed(false);
- setPressed(false);
- if (!mDataChanged) {
- post(performClick);
- }
- mTouchMode = TOUCH_MODE_REST;
- }
- }, ViewConfiguration.getPressedStateDuration());
- }
- return true;
- } else {
- if (!mDataChanged) {
- post(performClick);
- }
- }
- }
- mTouchMode = TOUCH_MODE_REST;
- break;
- case TOUCH_MODE_SCROLL:
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(1000);
- int initialVelocity = (int)velocityTracker.getYVelocity();
-
- if ((Math.abs(initialVelocity) >
- ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity()) &&
- (getChildCount() > 0)) {
- if (mFlingRunnable == null) {
- mFlingRunnable = new FlingRunnable();
- }
- reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
- mFlingRunnable.start(-initialVelocity);
- } else {
- mTouchMode = TOUCH_MODE_REST;
- reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
- }
- }
-
- setPressed(false);
-
- // Need to redraw since we probably aren't drawing the selector anymore
- invalidate();
-
- final Handler handler = getHandler();
- if (handler != null) {
- handler.removeCallbacks(mPendingCheckForLongPress);
- }
-
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
-
- if (PROFILE_SCROLLING) {
- if (mScrollProfilingStarted) {
- Debug.stopMethodTracing();
- mScrollProfilingStarted = false;
- }
- }
- break;
- }
-
- case MotionEvent.ACTION_CANCEL: {
- mTouchMode = TOUCH_MODE_REST;
- setPressed(false);
- View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
- if (motionView != null) {
- motionView.setPressed(false);
- }
- clearScrollingCache();
-
- final Handler handler = getHandler();
- if (handler != null) {
- handler.removeCallbacks(mPendingCheckForLongPress);
- }
-
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- }
-
- }
-
- return true;
- }
-
- @Override
- public void draw(Canvas canvas) {
- super.draw(canvas);
- if (mFastScroller != null) {
- mFastScroller.draw(canvas);
- }
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- int action = ev.getAction();
- int x = (int) ev.getX();
- int y = (int) ev.getY();
- View v;
-
- if (mFastScroller != null) {
- boolean intercepted = mFastScroller.onInterceptTouchEvent(ev);
- if (intercepted) {
- return true;
- }
- }
-
- switch (action) {
- case MotionEvent.ACTION_DOWN: {
- int motionPosition = findMotionRow(y);
- if (mTouchMode != TOUCH_MODE_FLING && motionPosition >= 0) {
- // User clicked on an actual view (and was not stopping a fling).
- // Remember where the motion event started
- v = getChildAt(motionPosition - mFirstPosition);
- mMotionViewOriginalTop = v.getTop();
- mMotionX = x;
- mMotionY = y;
- mMotionPosition = motionPosition;
- mTouchMode = TOUCH_MODE_DOWN;
- clearScrollingCache();
- }
- mLastY = Integer.MIN_VALUE;
- break;
- }
-
- case MotionEvent.ACTION_MOVE: {
- switch (mTouchMode) {
- case TOUCH_MODE_DOWN:
- if (startScrollIfNeeded(y - mMotionY)) {
- return true;
- }
- break;
- }
- break;
- }
-
- case MotionEvent.ACTION_UP: {
- mTouchMode = TOUCH_MODE_REST;
- reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
- break;
- }
- }
-
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void addTouchables(ArrayList<View> views) {
- final int count = getChildCount();
- final int firstPosition = mFirstPosition;
- final ListAdapter adapter = mAdapter;
-
- if (adapter == null) {
- return;
- }
-
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (adapter.isEnabled(firstPosition + i)) {
- views.add(child);
- }
- child.addTouchables(views);
- }
- }
-
- /**
- * Fires an "on scroll state changed" event to the registered
- * {@link android.widget.AbsListView.OnScrollListener}, if any. The state change
- * is fired only if the specified state is different from the previously known state.
- *
- * @param newState The new scroll state.
- */
- void reportScrollStateChange(int newState) {
- if (newState != mLastScrollState) {
- if (mOnScrollListener != null) {
- mOnScrollListener.onScrollStateChanged(this, newState);
- mLastScrollState = newState;
- }
- }
- }
-
- /**
- * Responsible for fling behavior. Use {@link #start(int)} to
- * initiate a fling. Each frame of the fling is handled in {@link #run()}.
- * A FlingRunnable will keep re-posting itself until the fling is done.
- *
- */
- private class FlingRunnable implements Runnable {
- /**
- * Tracks the decay of a fling scroll
- */
- private Scroller mScroller;
-
- /**
- * Y value reported by mScroller on the previous fling
- */
- private int mLastFlingY;
-
- public FlingRunnable() {
- mScroller = new Scroller(getContext());
- }
-
- public void start(int initialVelocity) {
- int initialY = initialVelocity < 0 ? Integer.MAX_VALUE : 0;
- mLastFlingY = initialY;
- mScroller.fling(0, initialY, 0, initialVelocity,
- 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
- mTouchMode = TOUCH_MODE_FLING;
- post(this);
-
- if (PROFILE_FLINGING) {
- if (!mFlingProfilingStarted) {
- Debug.startMethodTracing("AbsListViewFling");
- mFlingProfilingStarted = true;
- }
- }
- }
-
- private void endFling() {
- mTouchMode = TOUCH_MODE_REST;
- reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
- clearScrollingCache();
- }
-
- public void run() {
- if (mTouchMode != TOUCH_MODE_FLING) {
- return;
- }
-
- if (mItemCount == 0 || getChildCount() == 0) {
- endFling();
- return;
- }
-
- final Scroller scroller = mScroller;
- boolean more = scroller.computeScrollOffset();
- final int y = scroller.getCurrY();
-
- // Flip sign to convert finger direction to list items direction
- // (e.g. finger moving down means list is moving towards the top)
- int delta = mLastFlingY - y;
-
- // Pretend that each frame of a fling scroll is a touch scroll
- if (delta > 0) {
- // List is moving towards the top. Use first view as mMotionPosition
- mMotionPosition = mFirstPosition;
- final View firstView = getChildAt(0);
- mMotionViewOriginalTop = firstView.getTop();
-
- // Don't fling more than 1 screen
- delta = Math.min(getHeight() - mPaddingBottom - mPaddingTop - 1, delta);
- } else {
- // List is moving towards the bottom. Use last view as mMotionPosition
- int offsetToLast = getChildCount() - 1;
- mMotionPosition = mFirstPosition + offsetToLast;
-
- final View lastView = getChildAt(offsetToLast);
- mMotionViewOriginalTop = lastView.getTop();
-
- // Don't fling more than 1 screen
- delta = Math.max(-(getHeight() - mPaddingBottom - mPaddingTop - 1), delta);
- }
-
- trackMotionScroll(delta, delta);
-
- // Check to see if we have bumped into the scroll limit
- View motionView = getChildAt(mMotionPosition - mFirstPosition);
- if (motionView != null) {
- // Check if the top of the motion view is where it is
- // supposed to be
- if (motionView.getTop() != mMotionViewNewTop) {
- more = false;
- }
- }
-
- if (more) {
- mLastFlingY = y;
- post(this);
- } else {
- endFling();
- if (PROFILE_FLINGING) {
- if (mFlingProfilingStarted) {
- Debug.stopMethodTracing();
- mFlingProfilingStarted = false;
- }
- }
- }
- }
- }
-
- private void createScrollingCache() {
- if (mScrollingCacheEnabled && !mCachingStarted) {
- setChildrenDrawnWithCacheEnabled(true);
- setChildrenDrawingCacheEnabled(true);
- mCachingStarted = true;
- }
- }
-
- private void clearScrollingCache() {
- if (mCachingStarted) {
- setChildrenDrawnWithCacheEnabled(false);
- if ((mPersistentDrawingCache & PERSISTENT_SCROLLING_CACHE) == 0) {
- setChildrenDrawingCacheEnabled(false);
- }
- if (!isAlwaysDrawnWithCacheEnabled()) {
- invalidate();
- }
- mCachingStarted = false;
- }
- }
-
- /**
- * Track a motion scroll
- *
- * @param deltaY Amount to offset mMotionView. This is the accumulated delta since the motion
- * began. Positive numbers mean the user's finger is moving down the screen.
- * @param incrementalDeltaY Change in deltaY from the previous event.
- */
- void trackMotionScroll(int deltaY, int incrementalDeltaY) {
- final int childCount = getChildCount();
- if (childCount == 0) {
- return;
- }
-
- final int firstTop = getChildAt(0).getTop();
- final int lastBottom = getChildAt(childCount - 1).getBottom();
-
- final Rect listPadding = mListPadding;
-
- // FIXME account for grid vertical spacing too?
- final int spaceAbove = listPadding.top - firstTop;
- final int end = getHeight() - listPadding.bottom;
- final int spaceBelow = lastBottom - end;
-
- final int height = getHeight() - mPaddingBottom - mPaddingTop;
- if (deltaY < 0) {
- deltaY = Math.max(-(height - 1), deltaY);
- } else {
- deltaY = Math.min(height - 1, deltaY);
- }
-
- if (incrementalDeltaY < 0) {
- incrementalDeltaY = Math.max(-(height - 1), incrementalDeltaY);
- } else {
- incrementalDeltaY = Math.min(height - 1, incrementalDeltaY);
- }
-
- final int absIncrementalDeltaY = Math.abs(incrementalDeltaY);
-
- if (spaceAbove >= absIncrementalDeltaY && spaceBelow >= absIncrementalDeltaY) {
- hideSelector();
- offsetChildrenTopAndBottom(incrementalDeltaY);
- invalidate();
- mMotionViewNewTop = mMotionViewOriginalTop + deltaY;
- } else {
- final int firstPosition = mFirstPosition;
-
- if (firstPosition == 0 && firstTop >= listPadding.top && deltaY > 0) {
- // Don't need to move views down if the top of the first position is already visible
- return;
- }
-
- if (firstPosition + childCount == mItemCount && lastBottom <= end && deltaY < 0) {
- // Don't need to move views up if the bottom of the last position is already visible
- return;
- }
-
- final boolean down = incrementalDeltaY < 0;
-
- hideSelector();
-
- final int headerViewsCount = getHeaderViewsCount();
- final int footerViewsStart = mItemCount - getFooterViewsCount();
-
- int start = 0;
- int count = 0;
-
- if (down) {
- final int top = listPadding.top - incrementalDeltaY;
- for (int i = 0; i < childCount; i++) {
- final View child = getChildAt(i);
- if (child.getBottom() >= top) {
- break;
- } else {
- count++;
- int position = firstPosition + i;
- if (position >= headerViewsCount && position < footerViewsStart) {
- mRecycler.addScrapView(child);
-
- if (ViewDebug.TRACE_RECYCLER) {
- ViewDebug.trace(child,
- ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP,
- firstPosition + i, -1);
- }
- }
- }
- }
- } else {
- final int bottom = getHeight() - listPadding.bottom - incrementalDeltaY;
- for (int i = childCount - 1; i >= 0; i--) {
- final View child = getChildAt(i);
- if (child.getTop() <= bottom) {
- break;
- } else {
- start = i;
- count++;
- int position = firstPosition + i;
- if (position >= headerViewsCount && position < footerViewsStart) {
- mRecycler.addScrapView(child);
-
- if (ViewDebug.TRACE_RECYCLER) {
- ViewDebug.trace(child,
- ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP,
- firstPosition + i, -1);
- }
- }
- }
- }
- }
-
- mMotionViewNewTop = mMotionViewOriginalTop + deltaY;
-
- mBlockLayoutRequests = true;
- detachViewsFromParent(start, count);
- offsetChildrenTopAndBottom(incrementalDeltaY);
-
- if (down) {
- mFirstPosition += count;
- }
-
- invalidate();
- fillGap(down);
- mBlockLayoutRequests = false;
-
- invokeOnItemScrollListener();
- }
- }
-
- /**
- * Returns the number of header views in the list. Header views are special views
- * at the top of the list that should not be recycled during a layout.
- *
- * @return The number of header views, 0 in the default implementation.
- */
- int getHeaderViewsCount() {
- return 0;
- }
-
- /**
- * Returns the number of footer views in the list. Footer views are special views
- * at the bottom of the list that should not be recycled during a layout.
- *
- * @return The number of footer views, 0 in the default implementation.
- */
- int getFooterViewsCount() {
- return 0;
- }
-
- /**
- * Fills the gap left open by a touch-scroll. During a touch scroll, children that
- * remain on screen are shifted and the other ones are discarded. The role of this
- * method is to fill the gap thus created by performing a partial layout in the
- * empty space.
- *
- * @param down true if the scroll is going down, false if it is going up
- */
- abstract void fillGap(boolean down);
-
- void hideSelector() {
- if (mSelectedPosition != INVALID_POSITION) {
- mResurrectToPosition = mSelectedPosition;
- if (mNextSelectedPosition >= 0 && mNextSelectedPosition != mSelectedPosition) {
- mResurrectToPosition = mNextSelectedPosition;
- }
- setSelectedPositionInt(INVALID_POSITION);
- setNextSelectedPositionInt(INVALID_POSITION);
- mSelectedTop = 0;
- mSelectorRect.setEmpty();
- }
- }
-
- /**
- * @return A position to select. First we try mSelectedPosition. If that has been clobbered by
- * entering touch mode, we then try mResurrectToPosition. Values are pinned to the range
- * of items available in the adapter
- */
- int reconcileSelectedPosition() {
- int position = mSelectedPosition;
- if (position < 0) {
- position = mResurrectToPosition;
- }
- position = Math.max(0, position);
- position = Math.min(position, mItemCount - 1);
- return position;
- }
-
- /**
- * Find the row closest to y. This row will be used as the motion row when scrolling
- *
- * @param y Where the user touched
- * @return The position of the first (or only) item in the row closest to y
- */
- abstract int findMotionRow(int y);
-
- /**
- * Causes all the views to be rebuilt and redrawn.
- */
- public void invalidateViews() {
- mDataChanged = true;
- rememberSyncState();
- requestLayout();
- invalidate();
- }
-
- /**
- * Makes the item at the supplied position selected.
- *
- * @param position the position of the new selection
- */
- abstract void setSelectionInt(int position);
-
- /**
- * Attempt to bring the selection back if the user is switching from touch
- * to trackball mode
- * @return Whether selection was set to something.
- */
- boolean resurrectSelection() {
- final int childCount = getChildCount();
-
- if (childCount <= 0) {
- return false;
- }
-
- int selectedTop = 0;
- int selectedPos;
- int childrenTop = mListPadding.top;
- int childrenBottom = mBottom - mTop - mListPadding.bottom;
- final int firstPosition = mFirstPosition;
- final int toPosition = mResurrectToPosition;
- boolean down = true;
-
- if (toPosition >= firstPosition && toPosition < firstPosition + childCount) {
- selectedPos = toPosition;
-
- final View selected = getChildAt(selectedPos - mFirstPosition);
- selectedTop = selected.getTop();
- int selectedBottom = selected.getBottom();
-
- // We are scrolled, don't get in the fade
- if (selectedTop < childrenTop) {
- selectedTop = childrenTop + getVerticalFadingEdgeLength();
- } else if (selectedBottom > childrenBottom) {
- selectedTop = childrenBottom - selected.getMeasuredHeight()
- - getVerticalFadingEdgeLength();
- }
- } else {
- if (toPosition < firstPosition) {
- // Default to selecting whatever is first
- selectedPos = firstPosition;
- for (int i = 0; i < childCount; i++) {
- final View v = getChildAt(i);
- final int top = v.getTop();
-
- if (i == 0) {
- // Remember the position of the first item
- selectedTop = top;
- // See if we are scrolled at all
- if (firstPosition > 0 || top < childrenTop) {
- // If we are scrolled, don't select anything that is
- // in the fade region
- childrenTop += getVerticalFadingEdgeLength();
- }
- }
- if (top >= childrenTop) {
- // Found a view whose top is fully visisble
- selectedPos = firstPosition + i;
- selectedTop = top;
- break;
- }
- }
- } else {
- final int itemCount = mItemCount;
- down = false;
- selectedPos = firstPosition + childCount - 1;
-
- for (int i = childCount - 1; i >= 0; i--) {
- final View v = getChildAt(i);
- final int top = v.getTop();
- final int bottom = v.getBottom();
-
- if (i == childCount - 1) {
- selectedTop = top;
- if (firstPosition + childCount < itemCount || bottom > childrenBottom) {
- childrenBottom -= getVerticalFadingEdgeLength();
- }
- }
-
- if (bottom <= childrenBottom) {
- selectedPos = firstPosition + i;
- selectedTop = top;
- break;
- }
- }
- }
- }
-
- mResurrectToPosition = INVALID_POSITION;
- removeCallbacks(mFlingRunnable);
- mTouchMode = TOUCH_MODE_REST;
- clearScrollingCache();
- mSpecificTop = selectedTop;
- selectedPos = lookForSelectablePosition(selectedPos, down);
- if (selectedPos >= firstPosition && selectedPos <= getLastVisiblePosition()) {
- mLayoutMode = LAYOUT_SPECIFIC;
- setSelectionInt(selectedPos);
- invokeOnItemScrollListener();
- } else {
- selectedPos = INVALID_POSITION;
- }
- reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
-
- return selectedPos >= 0;
- }
-
- @Override
- protected void handleDataChanged() {
- int count = mItemCount;
- if (count > 0) {
-
- int newPos;
-
- int selectablePos;
-
- // Find the row we are supposed to sync to
- if (mNeedSync) {
- // Update this first, since setNextSelectedPositionInt inspects it
- mNeedSync = false;
-
- if (mTranscriptMode == TRANSCRIPT_MODE_ALWAYS_SCROLL ||
- (mTranscriptMode == TRANSCRIPT_MODE_NORMAL &&
- mFirstPosition + getChildCount() >= mOldItemCount)) {
- mLayoutMode = LAYOUT_FORCE_BOTTOM;
- return;
- }
-
- switch (mSyncMode) {
- case SYNC_SELECTED_POSITION:
- if (isInTouchMode()) {
- // We saved our state when not in touch mode. (We know this because
- // mSyncMode is SYNC_SELECTED_POSITION.) Now we are trying to
- // restore in touch mode. Just leave mSyncPosition as it is (possibly
- // adjusting if the available range changed) and return.
- mLayoutMode = LAYOUT_SYNC;
- mSyncPosition = Math.min(Math.max(0, mSyncPosition), count - 1);
-
- return;
- } else {
- // See if we can find a position in the new data with the same
- // id as the old selection. This will change mSyncPosition.
- newPos = findSyncPosition();
- if (newPos >= 0) {
- // Found it. Now verify that new selection is still selectable
- selectablePos = lookForSelectablePosition(newPos, true);
- if (selectablePos == newPos) {
- // Same row id is selected
- mSyncPosition = newPos;
-
- if (mSyncHeight == getHeight()) {
- // If we are at the same height as when we saved state, try
- // to restore the scroll position too.
- mLayoutMode = LAYOUT_SYNC;
- } else {
- // We are not the same height as when the selection was saved, so
- // don't try to restore the exact position
- mLayoutMode = LAYOUT_SET_SELECTION;
- }
-
- // Restore selection
- setNextSelectedPositionInt(newPos);
- return;
- }
- }
- }
- break;
- case SYNC_FIRST_POSITION:
- // Leave mSyncPosition as it is -- just pin to available range
- mLayoutMode = LAYOUT_SYNC;
- mSyncPosition = Math.min(Math.max(0, mSyncPosition), count - 1);
-
- return;
- }
- }
-
- if (!isInTouchMode()) {
- // We couldn't find matching data -- try to use the same position
- newPos = getSelectedItemPosition();
-
- // Pin position to the available range
- if (newPos >= count) {
- newPos = count - 1;
- }
- if (newPos < 0) {
- newPos = 0;
- }
-
- // Make sure we select something selectable -- first look down
- selectablePos = lookForSelectablePosition(newPos, true);
-
- if (selectablePos >= 0) {
- setNextSelectedPositionInt(selectablePos);
- return;
- } else {
- // Looking down didn't work -- try looking up
- selectablePos = lookForSelectablePosition(newPos, false);
- if (selectablePos >= 0) {
- setNextSelectedPositionInt(selectablePos);
- return;
- }
- }
- } else {
-
- // We already know where we want to resurrect the selection
- if (mResurrectToPosition >= 0) {
- return;
- }
- }
-
- }
-
- // Nothing is selected. Give up and reset everything.
- mLayoutMode = mStackFromBottom ? LAYOUT_FORCE_BOTTOM : LAYOUT_FORCE_TOP;
- mSelectedPosition = INVALID_POSITION;
- mSelectedRowId = INVALID_ROW_ID;
- mNextSelectedPosition = INVALID_POSITION;
- mNextSelectedRowId = INVALID_ROW_ID;
- mNeedSync = false;
- checkSelectionChanged();
- }
-
- /**
- * Removes the filter window
- */
- void dismissPopup() {
- if (mPopup != null) {
- mPopup.dismiss();
- }
- }
-
- /**
- * Shows the filter window
- */
- private void showPopup() {
- // Make sure we have a window before showing the popup
- if (getWindowVisibility() == View.VISIBLE) {
- positionPopup(false);
- // Make sure we get focus if we are showing the popup
- checkFocus();
- }
- }
-
- private void positionPopup(boolean update) {
- int screenHeight = getResources().getDisplayMetrics().heightPixels;
- final int[] xy = new int[2];
- getLocationOnScreen(xy);
- // TODO: The 20 below should come from the theme and be expressed in dip
- // TODO: And the gravity should be defined in the theme as well
- final int bottomGap = screenHeight - xy[1] - getHeight() + (int) (mDensityScale * 20);
- if (!update) {
- mPopup.showAtLocation(this, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL,
- xy[0], bottomGap);
- } else {
- mPopup.update(xy[0], bottomGap, -1, -1);
- }
- }
-
- /**
- * What is the distance between the source and destination rectangles given the direction of
- * focus navigation between them? The direction basically helps figure out more quickly what is
- * self evident by the relationship between the rects...
- *
- * @param source the source rectangle
- * @param dest the destination rectangle
- * @param direction the direction
- * @return the distance between the rectangles
- */
- static int getDistance(Rect source, Rect dest, int direction) {
- int sX, sY; // source x, y
- int dX, dY; // dest x, y
- switch (direction) {
- case View.FOCUS_RIGHT:
- sX = source.right;
- sY = source.top + source.height() / 2;
- dX = dest.left;
- dY = dest.top + dest.height() / 2;
- break;
- case View.FOCUS_DOWN:
- sX = source.left + source.width() / 2;
- sY = source.bottom;
- dX = dest.left + dest.width() / 2;
- dY = dest.top;
- break;
- case View.FOCUS_LEFT:
- sX = source.left;
- sY = source.top + source.height() / 2;
- dX = dest.right;
- dY = dest.top + dest.height() / 2;
- break;
- case View.FOCUS_UP:
- sX = source.left + source.width() / 2;
- sY = source.top;
- dX = dest.left + dest.width() / 2;
- dY = dest.bottom;
- break;
- default:
- throw new IllegalArgumentException("direction must be one of "
- + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
- }
- int deltaX = dX - sX;
- int deltaY = dY - sY;
- return deltaY * deltaY + deltaX * deltaX;
- }
-
- @Override
- protected boolean isInFilterMode() {
- return mFiltered;
- }
-
- /**
- * Sends a key to the text filter window
- *
- * @param keyCode The keycode for the event
- * @param event The actual key event
- *
- * @return True if the text filter handled the event, false otherwise.
- */
- boolean sendToTextFilter(int keyCode, int count, KeyEvent event) {
- if (!mTextFilterEnabled || !(getAdapter() instanceof Filterable) ||
- ((Filterable) getAdapter()).getFilter() == null) {
- return false;
- }
-
- boolean handled = false;
- boolean okToSend = true;
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_ENTER:
- okToSend = false;
- break;
- case KeyEvent.KEYCODE_BACK:
- if (mFiltered && mPopup != null && mPopup.isShowing() &&
- event.getAction() == KeyEvent.ACTION_DOWN) {
- handled = true;
- mTextFilter.setText("");
- }
- okToSend = false;
- break;
- case KeyEvent.KEYCODE_SPACE:
- // Only send spaces once we are filtered
- okToSend = mFiltered = true;
- break;
- }
-
- if (okToSend && acceptFilter()) {
- createTextFilter(true);
-
- KeyEvent forwardEvent = event;
- if (forwardEvent.getRepeatCount() > 0) {
- forwardEvent = new KeyEvent(event, event.getEventTime(), 0);
- }
-
- int action = event.getAction();
- switch (action) {
- case KeyEvent.ACTION_DOWN:
- handled = mTextFilter.onKeyDown(keyCode, forwardEvent);
- break;
-
- case KeyEvent.ACTION_UP:
- handled = mTextFilter.onKeyUp(keyCode, forwardEvent);
- break;
-
- case KeyEvent.ACTION_MULTIPLE:
- handled = mTextFilter.onKeyMultiple(keyCode, count, event);
- break;
- }
- }
- return handled;
- }
-
- /**
- * Creates the window for the text filter and populates it with an EditText field;
- *
- * @param animateEntrance true if the window should appear with an animation
- */
- private void createTextFilter(boolean animateEntrance) {
- if (mPopup == null) {
- Context c = getContext();
- PopupWindow p = new PopupWindow(c);
- LayoutInflater layoutInflater = (LayoutInflater) c
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mTextFilter = (EditText) layoutInflater.inflate(
- com.android.internal.R.layout.typing_filter, null);
- mTextFilter.addTextChangedListener(this);
- p.setFocusable(false);
- p.setTouchable(false);
- p.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
- p.setContentView(mTextFilter);
- p.setWidth(LayoutParams.WRAP_CONTENT);
- p.setHeight(LayoutParams.WRAP_CONTENT);
- p.setBackgroundDrawable(null);
- mPopup = p;
- getViewTreeObserver().addOnGlobalLayoutListener(this);
- }
- if (animateEntrance) {
- mPopup.setAnimationStyle(com.android.internal.R.style.Animation_TypingFilter);
- } else {
- mPopup.setAnimationStyle(com.android.internal.R.style.Animation_TypingFilterRestore);
- }
- }
-
- /**
- * Clear the text filter.
- */
- public void clearTextFilter() {
- if (mFiltered) {
- mTextFilter.setText("");
- mFiltered = false;
- if (mPopup != null && mPopup.isShowing()) {
- dismissPopup();
- }
- }
- }
-
- /**
- * Returns if the ListView currently has a text filter.
- */
- public boolean hasTextFilter() {
- return mFiltered;
- }
-
- public void onGlobalLayout() {
- if (isShown()) {
- // Show the popup if we are filtered
- if (mFiltered && mPopup != null && !mPopup.isShowing()) {
- showPopup();
- }
- } else {
- // Hide the popup when we are no longer visible
- if (mPopup.isShowing()) {
- dismissPopup();
- }
- }
-
- }
-
- /**
- * For our text watcher that associated with the text filter
- */
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- /**
- * For our text watcher that associated with the text filter. Performs the actual
- * filtering as the text changes.
- */
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- if (mPopup != null) {
- int length = s.length();
- boolean showing = mPopup.isShowing();
- if (!showing && length > 0) {
- // Show the filter popup if necessary
- showPopup();
- mFiltered = true;
- } else if (showing && length == 0) {
- // Remove the filter popup if the user has cleared all text
- mPopup.dismiss();
- mFiltered = false;
- }
- if (mAdapter instanceof Filterable) {
- Filter f = ((Filterable) mAdapter).getFilter();
- // Filter should not be null when we reach this part
- if (f != null) {
- f.filter(s, this);
- } else {
- throw new IllegalStateException("You cannot call onTextChanged with a non "
- + "filterable adapter");
- }
- }
- }
- }
-
- /**
- * For our text watcher that associated with the text filter
- */
- public void afterTextChanged(Editable s) {
- }
-
- public void onFilterComplete(int count) {
- if (mSelectedPosition < 0 && count > 0) {
- mResurrectToPosition = INVALID_POSITION;
- resurrectSelection();
- }
- }
-
- @Override
- protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return new LayoutParams(p);
- }
-
- @Override
- public LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new AbsListView.LayoutParams(getContext(), attrs);
- }
-
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof AbsListView.LayoutParams;
- }
-
- /**
- * Puts the list or grid into transcript mode. In this mode the list or grid will always scroll
- * to the bottom to show new items.
- *
- * @param mode the transcript mode to set
- *
- * @see #TRANSCRIPT_MODE_DISABLED
- * @see #TRANSCRIPT_MODE_NORMAL
- * @see #TRANSCRIPT_MODE_ALWAYS_SCROLL
- */
- public void setTranscriptMode(int mode) {
- mTranscriptMode = mode;
- }
-
- /**
- * Returns the current transcript mode.
- *
- * @return {@link #TRANSCRIPT_MODE_DISABLED}, {@link #TRANSCRIPT_MODE_NORMAL} or
- * {@link #TRANSCRIPT_MODE_ALWAYS_SCROLL}
- */
- public int getTranscriptMode() {
- return mTranscriptMode;
- }
-
- @Override
- public int getSolidColor() {
- return mCacheColorHint;
- }
-
- /**
- * When set to a non-zero value, the cache color hint indicates that this list is always drawn
- * on top of a solid, single-color, opaque background
- *
- * @param color The background color
- */
- public void setCacheColorHint(int color) {
- mCacheColorHint = color;
- }
-
- /**
- * When set to a non-zero value, the cache color hint indicates that this list is always drawn
- * on top of a solid, single-color, opaque background
- *
- * @return The cache color hint
- */
- public int getCacheColorHint() {
- return mCacheColorHint;
- }
-
- /**
- * Move all views (excluding headers and footers) held by this AbsListView into the supplied
- * List. This includes views displayed on the screen as well as views stored in AbsListView's
- * internal view recycler.
- *
- * @param views A list into which to put the reclaimed views
- */
- public void reclaimViews(List<View> views) {
- int childCount = getChildCount();
- RecyclerListener listener = mRecycler.mRecyclerListener;
-
- // Reclaim views on screen
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- AbsListView.LayoutParams lp = (AbsListView.LayoutParams)child.getLayoutParams();
- // Don't reclaim header or footer views, or views that should be ignored
- if (lp != null && mRecycler.shouldRecycleViewType(lp.viewType)) {
- views.add(child);
- if (listener != null) {
- // Pretend they went through the scrap heap
- listener.onMovedToScrapHeap(child);
- }
- }
- }
- mRecycler.reclaimScrapViews(views);
- removeAllViewsInLayout();
- }
-
- /**
- * Sets the recycler listener to be notified whenever a View is set aside in
- * the recycler for later reuse. This listener can be used to free resources
- * associated to the View.
- *
- * @param listener The recycler listener to be notified of views set aside
- * in the recycler.
- *
- * @see android.widget.AbsListView.RecycleBin
- * @see android.widget.AbsListView.RecyclerListener
- */
- public void setRecyclerListener(RecyclerListener listener) {
- mRecycler.mRecyclerListener = listener;
- }
-
- /**
- * AbsListView extends LayoutParams to provide a place to hold the view type.
- */
- public static class LayoutParams extends ViewGroup.LayoutParams {
- /**
- * View type for this view, as returned by
- * {@link android.widget.Adapter#getItemViewType(int) }
- */
- int viewType;
-
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
- }
-
- public LayoutParams(int w, int h) {
- super(w, h);
- }
-
- public LayoutParams(int w, int h, int viewType) {
- super(w, h);
- this.viewType = viewType;
- }
-
- public LayoutParams(ViewGroup.LayoutParams source) {
- super(source);
- }
- }
-
- /**
- * A RecyclerListener is used to receive a notification whenever a View is placed
- * inside the RecycleBin's scrap heap. This listener is used to free resources
- * associated to Views placed in the RecycleBin.
- *
- * @see android.widget.AbsListView.RecycleBin
- * @see android.widget.AbsListView#setRecyclerListener(android.widget.AbsListView.RecyclerListener)
- */
- public static interface RecyclerListener {
- /**
- * Indicates that the specified View was moved into the recycler's scrap heap.
- * The view is not displayed on screen any more and any expensive resource
- * associated with the view should be discarded.
- *
- * @param view
- */
- void onMovedToScrapHeap(View view);
- }
-
- /**
- * The RecycleBin facilitates reuse of views across layouts. The RecycleBin has two levels of
- * storage: ActiveViews and ScrapViews. ActiveViews are those views which were onscreen at the
- * start of a layout. By construction, they are displaying current information. At the end of
- * layout, all views in ActiveViews are demoted to ScrapViews. ScrapViews are old views that
- * could potentially be used by the adapter to avoid allocating views unnecessarily.
- *
- * @see android.widget.AbsListView#setRecyclerListener(android.widget.AbsListView.RecyclerListener)
- * @see android.widget.AbsListView.RecyclerListener
- */
- class RecycleBin {
- private RecyclerListener mRecyclerListener;
-
- /**
- * The position of the first view stored in mActiveViews.
- */
- private int mFirstActivePosition;
-
- /**
- * Views that were on screen at the start of layout. This array is populated at the start of
- * layout, and at the end of layout all view in mActiveViews are moved to mScrapViews.
- * Views in mActiveViews represent a contiguous range of Views, with position of the first
- * view store in mFirstActivePosition.
- */
- private View[] mActiveViews = new View[0];
-
- /**
- * Unsorted views that can be used by the adapter as a convert view.
- */
- private ArrayList<View>[] mScrapViews;
-
- private int mViewTypeCount;
-
- private ArrayList<View> mCurrentScrap;
-
- public void setViewTypeCount(int viewTypeCount) {
- if (viewTypeCount < 1) {
- throw new IllegalArgumentException("Can't have a viewTypeCount < 1");
- }
- //noinspection unchecked
- ArrayList<View>[] scrapViews = new ArrayList[viewTypeCount];
- for (int i = 0; i < viewTypeCount; i++) {
- scrapViews[i] = new ArrayList<View>();
- }
- mViewTypeCount = viewTypeCount;
- mCurrentScrap = scrapViews[0];
- mScrapViews = scrapViews;
- }
-
- public boolean shouldRecycleViewType(int viewType) {
- return viewType >= 0;
- }
-
- /**
- * Clears the scrap heap.
- */
- void clear() {
- if (mViewTypeCount == 1) {
- final ArrayList<View> scrap = mCurrentScrap;
- final int scrapCount = scrap.size();
- for (int i = 0; i < scrapCount; i++) {
- removeDetachedView(scrap.remove(scrapCount - 1 - i), false);
- }
- } else {
- final int typeCount = mViewTypeCount;
- for (int i = 0; i < typeCount; i++) {
- final ArrayList<View> scrap = mScrapViews[i];
- final int scrapCount = scrap.size();
- for (int j = 0; j < scrapCount; j++) {
- removeDetachedView(scrap.remove(scrapCount - 1 - j), false);
- }
- }
- }
- }
-
- /**
- * Fill ActiveViews with all of the children of the AbsListView.
- *
- * @param childCount The minimum number of views mActiveViews should hold
- * @param firstActivePosition The position of the first view that will be stored in
- * mActiveViews
- */
- void fillActiveViews(int childCount, int firstActivePosition) {
- if (mActiveViews.length < childCount) {
- mActiveViews = new View[childCount];
- }
- mFirstActivePosition = firstActivePosition;
-
- final View[] activeViews = mActiveViews;
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- AbsListView.LayoutParams lp = (AbsListView.LayoutParams)child.getLayoutParams();
- // Don't put header or footer views into the scrap heap
- if (lp != null && lp.viewType != AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER) {
- // Note: We do place AdapterView.ITEM_VIEW_TYPE_IGNORE in active views.
- // However, we will NOT place them into scrap views.
- activeViews[i] = getChildAt(i);
- }
- }
- }
-
- /**
- * Get the view corresponding to the specified position. The view will be removed from
- * mActiveViews if it is found.
- *
- * @param position The position to look up in mActiveViews
- * @return The view if it is found, null otherwise
- */
- View getActiveView(int position) {
- int index = position - mFirstActivePosition;
- final View[] activeViews = mActiveViews;
- if (index >=0 && index < activeViews.length) {
- final View match = activeViews[index];
- activeViews[index] = null;
- return match;
- }
- return null;
- }
-
- /**
- * @return A view from the ScrapViews collection. These are unordered.
- */
- View getScrapView(int position) {
- ArrayList<View> scrapViews;
- if (mViewTypeCount == 1) {
- scrapViews = mCurrentScrap;
- int size = scrapViews.size();
- if (size > 0) {
- return scrapViews.remove(size - 1);
- } else {
- return null;
- }
- } else {
- int whichScrap = mAdapter.getItemViewType(position);
- if (whichScrap >= 0 && whichScrap < mScrapViews.length) {
- scrapViews = mScrapViews[whichScrap];
- int size = scrapViews.size();
- if (size > 0) {
- return scrapViews.remove(size - 1);
- }
- }
- }
- return null;
- }
-
- /**
- * Put a view into the ScapViews list. These views are unordered.
- *
- * @param scrap The view to add
- */
- void addScrapView(View scrap) {
- AbsListView.LayoutParams lp = (AbsListView.LayoutParams) scrap.getLayoutParams();
- if (lp == null) {
- return;
- }
-
- // Don't put header or footer views or views that should be ignored
- // into the scrap heap
- int viewType = lp.viewType;
- if (!shouldRecycleViewType(viewType)) {
- return;
- }
-
- if (mViewTypeCount == 1) {
- mCurrentScrap.add(scrap);
- } else {
- mScrapViews[viewType].add(scrap);
- }
-
- if (mRecyclerListener != null) {
- mRecyclerListener.onMovedToScrapHeap(scrap);
- }
- }
-
- /**
- * Move all views remaining in mActiveViews to mScrapViews.
- */
- void scrapActiveViews() {
- final View[] activeViews = mActiveViews;
- final boolean hasListener = mRecyclerListener != null;
- final boolean multipleScraps = mViewTypeCount > 1;
-
- ArrayList<View> scrapViews = mCurrentScrap;
- final int count = activeViews.length;
- for (int i = 0; i < count; ++i) {
- final View victim = activeViews[i];
- if (victim != null) {
- int whichScrap = ((AbsListView.LayoutParams)
- victim.getLayoutParams()).viewType;
-
- activeViews[i] = null;
-
- if (whichScrap == AdapterView.ITEM_VIEW_TYPE_IGNORE) {
- // Do not move views that should be ignored
- continue;
- }
-
- if (multipleScraps) {
- scrapViews = mScrapViews[whichScrap];
- }
- scrapViews.add(victim);
-
- if (hasListener) {
- mRecyclerListener.onMovedToScrapHeap(victim);
- }
-
- if (ViewDebug.TRACE_RECYCLER) {
- ViewDebug.trace(victim,
- ViewDebug.RecyclerTraceType.MOVE_FROM_ACTIVE_TO_SCRAP_HEAP,
- mFirstActivePosition + i, -1);
- }
- }
- }
-
- pruneScrapViews();
- }
-
- /**
- * Makes sure that the size of mScrapViews does not exceed the size of mActiveViews.
- * (This can happen if an adapter does not recycle its views).
- */
- private void pruneScrapViews() {
- final int maxViews = mActiveViews.length;
- final int viewTypeCount = mViewTypeCount;
- final ArrayList<View>[] scrapViews = mScrapViews;
- for (int i = 0; i < viewTypeCount; ++i) {
- final ArrayList<View> scrapPile = scrapViews[i];
- int size = scrapPile.size();
- final int extras = size - maxViews;
- size--;
- for (int j = 0; j < extras; j++) {
- removeDetachedView(scrapPile.remove(size--), false);
- }
- }
- }
-
- /**
- * Puts all views in the scrap heap into the supplied list.
- */
- void reclaimScrapViews(List<View> views) {
- if (mViewTypeCount == 1) {
- views.addAll(mCurrentScrap);
- } else {
- final int viewTypeCount = mViewTypeCount;
- final ArrayList<View>[] scrapViews = mScrapViews;
- for (int i = 0; i < viewTypeCount; ++i) {
- final ArrayList<View> scrapPile = scrapViews[i];
- views.addAll(scrapPile);
- }
- }
- }
- }
-}
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
deleted file mode 100644
index b046a6b..0000000
--- a/core/java/android/widget/AbsSeekBar.java
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-
-public abstract class AbsSeekBar extends ProgressBar {
-
- private Drawable mThumb;
- private int mThumbOffset;
-
- /**
- * On touch, this offset plus the scaled value from the position of the
- * touch will form the progress value. Usually 0.
- */
- float mTouchProgressOffset;
-
- /**
- * Whether this is user seekable.
- */
- boolean mIsUserSeekable = true;
-
- private static final int NO_ALPHA = 0xFF;
- float mDisabledAlpha;
-
- public AbsSeekBar(Context context) {
- super(context);
- }
-
- public AbsSeekBar(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public AbsSeekBar(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.SeekBar, defStyle, 0);
- Drawable thumb = a.getDrawable(com.android.internal.R.styleable.SeekBar_thumb);
- setThumb(thumb);
- int thumbOffset =
- a.getDimensionPixelOffset(com.android.internal.R.styleable.SeekBar_thumbOffset, 0);
- setThumbOffset(thumbOffset);
- a.recycle();
-
- a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.Theme, 0, 0);
- mDisabledAlpha = a.getFloat(com.android.internal.R.styleable.Theme_disabledAlpha, 0.5f);
- a.recycle();
- }
-
- /**
- * Sets the thumb that will be drawn at the end of the progress meter within the SeekBar
- *
- * @param thumb Drawable representing the thumb
- */
- public void setThumb(Drawable thumb) {
- if (thumb != null) {
- thumb.setCallback(this);
- }
- mThumb = thumb;
- invalidate();
- }
-
- /**
- * @see #setThumbOffset(int)
- */
- public int getThumbOffset() {
- return mThumbOffset;
- }
-
- /**
- * Sets the thumb offset that allows the thumb to extend out of the range of
- * the track.
- *
- * @param thumbOffset The offset amount in pixels.
- */
- public void setThumbOffset(int thumbOffset) {
- mThumbOffset = thumbOffset;
- invalidate();
- }
-
- @Override
- protected boolean verifyDrawable(Drawable who) {
- return who == mThumb || super.verifyDrawable(who);
- }
-
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
-
- Drawable progressDrawable = getProgressDrawable();
- if (progressDrawable != null) {
- progressDrawable.setAlpha(isEnabled() ? NO_ALPHA : (int) (NO_ALPHA * mDisabledAlpha));
- }
-
- if (mThumb != null && mThumb.isStateful()) {
- int[] state = getDrawableState();
- mThumb.setState(state);
- }
- }
-
- @Override
- void onProgressRefresh(float scale, boolean fromUser) {
- Drawable thumb = mThumb;
- if (thumb != null) {
- setThumbPos(getWidth(), getHeight(), thumb, scale, Integer.MIN_VALUE);
- /*
- * Since we draw translated, the drawable's bounds that it signals
- * for invalidation won't be the actual bounds we want invalidated,
- * so just invalidate this whole view.
- */
- invalidate();
- }
- }
-
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- Drawable d = getCurrentDrawable();
- Drawable thumb = mThumb;
- int thumbHeight = thumb == null ? 0 : thumb.getIntrinsicHeight();
- // The max height does not incorporate padding, whereas the height
- // parameter does
- int trackHeight = Math.min(mMaxHeight, h - mPaddingTop - mPaddingBottom);
-
- int max = getMax();
- float scale = max > 0 ? (float) getProgress() / (float) max : 0;
-
- if (thumbHeight > trackHeight) {
- if (thumb != null) {
- setThumbPos(w, h, thumb, scale, 0);
- }
- int gapForCenteringTrack = (thumbHeight - trackHeight) / 2;
- if (d != null) {
- // Canvas will be translated by the padding, so 0,0 is where we start drawing
- d.setBounds(0, gapForCenteringTrack,
- w - mPaddingRight - mPaddingLeft, h - mPaddingBottom - gapForCenteringTrack
- - mPaddingTop);
- }
- } else {
- if (d != null) {
- // Canvas will be translated by the padding, so 0,0 is where we start drawing
- d.setBounds(0, 0, w - mPaddingRight - mPaddingLeft, h - mPaddingBottom
- - mPaddingTop);
- }
- int gap = (trackHeight - thumbHeight) / 2;
- if (thumb != null) {
- setThumbPos(w, h, thumb, scale, gap);
- }
- }
- }
-
- /**
- * @param gap If set to {@link Integer#MIN_VALUE}, this will be ignored and
- * the old vertical bounds will be used.
- */
- private void setThumbPos(int w, int h, Drawable thumb, float scale, int gap) {
- int available = w - mPaddingLeft - mPaddingRight;
- int thumbWidth = thumb.getIntrinsicWidth();
- int thumbHeight = thumb.getIntrinsicHeight();
- available -= thumbWidth;
-
- // The extra space for the thumb to move on the track
- available += mThumbOffset * 2;
-
- int thumbPos = (int) (scale * available);
-
- int topBound, bottomBound;
- if (gap == Integer.MIN_VALUE) {
- Rect oldBounds = thumb.getBounds();
- topBound = oldBounds.top;
- bottomBound = oldBounds.bottom;
- } else {
- topBound = gap;
- bottomBound = gap + thumbHeight;
- }
-
- // Canvas will be translated, so 0,0 is where we start drawing
- thumb.setBounds(thumbPos, topBound, thumbPos + thumbWidth, bottomBound);
- }
-
- @Override
- protected synchronized void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (mThumb != null) {
- canvas.save();
- // Translate the padding. For the x, we need to allow the thumb to
- // draw in its extra space
- canvas.translate(mPaddingLeft - mThumbOffset, mPaddingTop);
- mThumb.draw(canvas);
- canvas.restore();
- }
- }
-
- @Override
- protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- Drawable d = getCurrentDrawable();
-
- int thumbHeight = mThumb == null ? 0 : mThumb.getIntrinsicHeight();
- int dw = 0;
- int dh = 0;
- if (d != null) {
- dw = Math.max(mMinWidth, Math.min(mMaxWidth, d.getIntrinsicWidth()));
- dh = Math.max(mMinHeight, Math.min(mMaxHeight, d.getIntrinsicHeight()));
- dh = Math.max(thumbHeight, dh);
- }
- dw += mPaddingLeft + mPaddingRight;
- dh += mPaddingTop + mPaddingBottom;
-
- setMeasuredDimension(resolveSize(dw, widthMeasureSpec),
- resolveSize(dh, heightMeasureSpec));
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (!mIsUserSeekable || !isEnabled()) {
- return false;
- }
-
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- setPressed(true);
- onStartTrackingTouch();
- trackTouchEvent(event);
- break;
-
- case MotionEvent.ACTION_MOVE:
- trackTouchEvent(event);
- attemptClaimDrag();
- break;
-
- case MotionEvent.ACTION_UP:
- trackTouchEvent(event);
- onStopTrackingTouch();
- setPressed(false);
- break;
-
- case MotionEvent.ACTION_CANCEL:
- onStopTrackingTouch();
- setPressed(false);
- break;
- }
- return true;
- }
-
- private void trackTouchEvent(MotionEvent event) {
- final int width = getWidth();
- final int available = width - mPaddingLeft - mPaddingRight;
- int x = (int)event.getX();
- float scale;
- float progress = 0;
- if (x < mPaddingLeft) {
- scale = 0.0f;
- } else if (x > width - mPaddingRight) {
- scale = 1.0f;
- } else {
- scale = (float)(x - mPaddingLeft) / (float)available;
- progress = mTouchProgressOffset;
- }
-
- final int max = getMax();
- progress += scale * max;
- if (progress < 0) {
- progress = 0;
- } else if (progress > max) {
- progress = max;
- }
-
- setProgress((int) progress, true);
- }
-
- /**
- * Tries to claim the user's drag motion, and requests disallowing any
- * ancestors from stealing events in the drag.
- */
- private void attemptClaimDrag() {
- if (mParent != null) {
- mParent.requestDisallowInterceptTouchEvent(true);
- }
- }
-
- /**
- * This is called when the user has started touching this widget.
- */
- void onStartTrackingTouch() {
- }
-
- /**
- * This is called when the user either releases his touch or the touch is
- * canceled.
- */
- void onStopTrackingTouch() {
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- int progress = getProgress();
-
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- if (progress <= 0) break;
- setProgress(progress - 1, true);
- return true;
-
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- if (progress >= getMax()) break;
- setProgress(progress + 1, true);
- return true;
- }
-
- return super.onKeyDown(keyCode, event);
- }
-
-}
diff --git a/core/java/android/widget/AbsSpinner.java b/core/java/android/widget/AbsSpinner.java
deleted file mode 100644
index 424a936..0000000
--- a/core/java/android/widget/AbsSpinner.java
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import com.android.internal.R;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.database.DataSetObserver;
-import android.graphics.Rect;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.util.SparseArray;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.Interpolator;
-
-
-/**
- * An abstract base class for spinner widgets. SDK users will probably not
- * need to use this class.
- *
- * @attr ref android.R.styleable#AbsSpinner_entries
- */
-public abstract class AbsSpinner extends AdapterView<SpinnerAdapter> {
-
- SpinnerAdapter mAdapter;
-
- int mHeightMeasureSpec;
- int mWidthMeasureSpec;
- boolean mBlockLayoutRequests;
- int mSelectionLeftPadding = 0;
- int mSelectionTopPadding = 0;
- int mSelectionRightPadding = 0;
- int mSelectionBottomPadding = 0;
- Rect mSpinnerPadding = new Rect();
- View mSelectedView = null;
- Interpolator mInterpolator;
-
- RecycleBin mRecycler = new RecycleBin();
- private DataSetObserver mDataSetObserver;
-
-
- /** Temporary frame to hold a child View's frame rectangle */
- private Rect mTouchFrame;
-
- public AbsSpinner(Context context) {
- super(context);
- initAbsSpinner();
- }
-
- public AbsSpinner(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public AbsSpinner(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- initAbsSpinner();
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.AbsSpinner, defStyle, 0);
-
- CharSequence[] entries = a.getTextArray(R.styleable.AbsSpinner_entries);
- if (entries != null) {
- ArrayAdapter<CharSequence> adapter =
- new ArrayAdapter<CharSequence>(context,
- R.layout.simple_spinner_item, entries);
- adapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
- setAdapter(adapter);
- }
-
- a.recycle();
- }
-
- /**
- * Common code for different constructor flavors
- */
- private void initAbsSpinner() {
- setFocusable(true);
- setWillNotDraw(false);
- }
-
-
- /**
- * The Adapter is used to provide the data which backs this Spinner.
- * It also provides methods to transform spinner items based on their position
- * relative to the selected item.
- * @param adapter The SpinnerAdapter to use for this Spinner
- */
- @Override
- public void setAdapter(SpinnerAdapter adapter) {
- if (null != mAdapter) {
- mAdapter.unregisterDataSetObserver(mDataSetObserver);
- resetList();
- }
-
- mAdapter = adapter;
-
- mOldSelectedPosition = INVALID_POSITION;
- mOldSelectedRowId = INVALID_ROW_ID;
-
- if (mAdapter != null) {
- mOldItemCount = mItemCount;
- mItemCount = mAdapter.getCount();
- checkFocus();
-
- mDataSetObserver = new AdapterDataSetObserver();
- mAdapter.registerDataSetObserver(mDataSetObserver);
-
- int position = mItemCount > 0 ? 0 : INVALID_POSITION;
-
- setSelectedPositionInt(position);
- setNextSelectedPositionInt(position);
-
- if (mItemCount == 0) {
- // Nothing selected
- checkSelectionChanged();
- }
-
- } else {
- checkFocus();
- resetList();
- // Nothing selected
- checkSelectionChanged();
- }
-
- requestLayout();
- }
-
- /**
- * Clear out all children from the list
- */
- void resetList() {
- mDataChanged = false;
- mNeedSync = false;
-
- removeAllViewsInLayout();
- mOldSelectedPosition = INVALID_POSITION;
- mOldSelectedRowId = INVALID_ROW_ID;
-
- setSelectedPositionInt(INVALID_POSITION);
- setNextSelectedPositionInt(INVALID_POSITION);
- invalidate();
- }
-
- /**
- * @see android.view.View#measure(int, int)
- *
- * Figure out the dimensions of this Spinner. The width comes from
- * the widthMeasureSpec as Spinnners can't have their width set to
- * UNSPECIFIED. The height is based on the height of the selected item
- * plus padding.
- */
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int widthSize;
- int heightSize;
-
- mSpinnerPadding.left = mPaddingLeft > mSelectionLeftPadding ? mPaddingLeft
- : mSelectionLeftPadding;
- mSpinnerPadding.top = mPaddingTop > mSelectionTopPadding ? mPaddingTop
- : mSelectionTopPadding;
- mSpinnerPadding.right = mPaddingRight > mSelectionRightPadding ? mPaddingRight
- : mSelectionRightPadding;
- mSpinnerPadding.bottom = mPaddingBottom > mSelectionBottomPadding ? mPaddingBottom
- : mSelectionBottomPadding;
-
- if (mDataChanged) {
- handleDataChanged();
- }
-
- int preferredHeight = 0;
- int preferredWidth = 0;
- boolean needsMeasuring = true;
-
- int selectedPosition = getSelectedItemPosition();
- if (selectedPosition >= 0 && mAdapter != null) {
- // Try looking in the recycler. (Maybe we were measured once already)
- View view = mRecycler.get(selectedPosition);
- if (view == null) {
- // Make a new one
- view = mAdapter.getView(selectedPosition, null, this);
- }
-
- if (view != null) {
- // Put in recycler for re-measuring and/or layout
- mRecycler.put(selectedPosition, view);
- }
-
- if (view != null) {
- if (view.getLayoutParams() == null) {
- mBlockLayoutRequests = true;
- view.setLayoutParams(generateDefaultLayoutParams());
- mBlockLayoutRequests = false;
- }
- measureChild(view, widthMeasureSpec, heightMeasureSpec);
-
- preferredHeight = getChildHeight(view) + mSpinnerPadding.top + mSpinnerPadding.bottom;
- preferredWidth = getChildWidth(view) + mSpinnerPadding.left + mSpinnerPadding.right;
-
- needsMeasuring = false;
- }
- }
-
- if (needsMeasuring) {
- // No views -- just use padding
- preferredHeight = mSpinnerPadding.top + mSpinnerPadding.bottom;
- if (widthMode == MeasureSpec.UNSPECIFIED) {
- preferredWidth = mSpinnerPadding.left + mSpinnerPadding.right;
- }
- }
-
- preferredHeight = Math.max(preferredHeight, getSuggestedMinimumHeight());
- preferredWidth = Math.max(preferredWidth, getSuggestedMinimumWidth());
-
- heightSize = resolveSize(preferredHeight, heightMeasureSpec);
- widthSize = resolveSize(preferredWidth, widthMeasureSpec);
-
- setMeasuredDimension(widthSize, heightSize);
- mHeightMeasureSpec = heightMeasureSpec;
- mWidthMeasureSpec = widthMeasureSpec;
- }
-
-
- int getChildHeight(View child) {
- return child.getMeasuredHeight();
- }
-
- int getChildWidth(View child) {
- return child.getMeasuredWidth();
- }
-
- @Override
- protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
- return new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- }
-
- void recycleAllViews() {
- int childCount = getChildCount();
- final AbsSpinner.RecycleBin recycleBin = mRecycler;
-
- // All views go in recycler
- for (int i=0; i<childCount; i++) {
- View v = getChildAt(i);
- int index = mFirstPosition + i;
- recycleBin.put(index, v);
- }
- }
-
- @Override
- void handleDataChanged() {
- // FIXME -- this is called from both measure and layout.
- // This is harmless right now, but we don't want to do redundant work if
- // this gets more complicated
- super.handleDataChanged();
- }
-
-
-
- /**
- * Jump directly to a specific item in the adapter data.
- */
- public void setSelection(int position, boolean animate) {
- // Animate only if requested position is already on screen somewhere
- boolean shouldAnimate = animate && mFirstPosition <= position &&
- position <= mFirstPosition + getChildCount() - 1;
- setSelectionInt(position, shouldAnimate);
- }
-
-
- @Override
- public void setSelection(int position) {
- setNextSelectedPositionInt(position);
- requestLayout();
- invalidate();
- }
-
-
- /**
- * Makes the item at the supplied position selected.
- *
- * @param position Position to select
- * @param animate Should the transition be animated
- *
- */
- void setSelectionInt(int position, boolean animate) {
- if (position != mOldSelectedPosition) {
- mBlockLayoutRequests = true;
- int delta = position - mSelectedPosition;
- setNextSelectedPositionInt(position);
- layout(delta, animate);
- mBlockLayoutRequests = false;
- }
- }
-
- abstract void layout(int delta, boolean animate);
-
- @Override
- public View getSelectedView() {
- if (mItemCount > 0 && mSelectedPosition >= 0) {
- return getChildAt(mSelectedPosition - mFirstPosition);
- } else {
- return null;
- }
- }
-
- /**
- * Override to prevent spamming ourselves with layout requests
- * as we place views
- *
- * @see android.view.View#requestLayout()
- */
- @Override
- public void requestLayout() {
- if (!mBlockLayoutRequests) {
- super.requestLayout();
- }
- }
-
-
-
- @Override
- public SpinnerAdapter getAdapter() {
- return mAdapter;
- }
-
- @Override
- public int getCount() {
- return mItemCount;
- }
-
- /**
- * Maps a point to a position in the list.
- *
- * @param x X in local coordinate
- * @param y Y in local coordinate
- * @return The position of the item which contains the specified point, or
- * {@link #INVALID_POSITION} if the point does not intersect an item.
- */
- public int pointToPosition(int x, int y) {
- Rect frame = mTouchFrame;
- if (frame == null) {
- mTouchFrame = new Rect();
- frame = mTouchFrame;
- }
-
- final int count = getChildCount();
- for (int i = count - 1; i >= 0; i--) {
- View child = getChildAt(i);
- if (child.getVisibility() == View.VISIBLE) {
- child.getHitRect(frame);
- if (frame.contains(x, y)) {
- return mFirstPosition + i;
- }
- }
- }
- return INVALID_POSITION;
- }
-
- static class SavedState extends BaseSavedState {
- long selectedId;
- int position;
-
- /**
- * Constructor called from {@link AbsSpinner#onSaveInstanceState()}
- */
- SavedState(Parcelable superState) {
- super(superState);
- }
-
- /**
- * Constructor called from {@link #CREATOR}
- */
- private SavedState(Parcel in) {
- super(in);
- selectedId = in.readLong();
- position = in.readInt();
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- super.writeToParcel(out, flags);
- out.writeLong(selectedId);
- out.writeInt(position);
- }
-
- @Override
- public String toString() {
- return "AbsSpinner.SavedState{"
- + Integer.toHexString(System.identityHashCode(this))
- + " selectedId=" + selectedId
- + " position=" + position + "}";
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR
- = new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
- @Override
- public Parcelable onSaveInstanceState() {
- Parcelable superState = super.onSaveInstanceState();
- SavedState ss = new SavedState(superState);
- ss.selectedId = getSelectedItemId();
- if (ss.selectedId >= 0) {
- ss.position = getSelectedItemPosition();
- } else {
- ss.position = INVALID_POSITION;
- }
- return ss;
- }
-
- @Override
- public void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
-
- super.onRestoreInstanceState(ss.getSuperState());
-
- if (ss.selectedId >= 0) {
- mDataChanged = true;
- mNeedSync = true;
- mSyncRowId = ss.selectedId;
- mSyncPosition = ss.position;
- mSyncMode = SYNC_SELECTED_POSITION;
- requestLayout();
- }
- }
-
- class RecycleBin {
- private SparseArray<View> mScrapHeap = new SparseArray<View>();
-
- public void put(int position, View v) {
- mScrapHeap.put(position, v);
- }
-
- View get(int position) {
- // System.out.print("Looking for " + position);
- View result = mScrapHeap.get(position);
- if (result != null) {
- // System.out.println(" HIT");
- mScrapHeap.delete(position);
- } else {
- // System.out.println(" MISS");
- }
- return result;
- }
-
- View peek(int position) {
- // System.out.print("Looking for " + position);
- return mScrapHeap.get(position);
- }
-
- void clear() {
- final SparseArray<View> scrapHeap = mScrapHeap;
- final int count = scrapHeap.size();
- for (int i = 0; i < count; i++) {
- final View view = scrapHeap.valueAt(i);
- if (view != null) {
- removeDetachedView(view, true);
- }
- }
- scrapHeap.clear();
- }
- }
-}
diff --git a/core/java/android/widget/AbsoluteLayout.java b/core/java/android/widget/AbsoluteLayout.java
deleted file mode 100644
index c77f7ae..0000000
--- a/core/java/android/widget/AbsoluteLayout.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.RemoteViews.RemoteView;
-
-
-/**
- * A layout that lets you specify exact locations (x/y coordinates) of its
- * children. Absolute layouts are less flexible and harder to maintain than
- * other types of layouts without absolute positioning.
- *
- * <p><strong>XML attributes</strong></p> <p> See {@link
- * android.R.styleable#ViewGroup ViewGroup Attributes}, {@link
- * android.R.styleable#View View Attributes}</p>
- *
- * @deprecated Use {@link android.widget.FrameLayout}, {@link android.widget.RelativeLayout}
- * or a custom layout instead.
- */
-@Deprecated
-@RemoteView
-public class AbsoluteLayout extends ViewGroup {
- public AbsoluteLayout(Context context) {
- super(context);
- }
-
- public AbsoluteLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public AbsoluteLayout(Context context, AttributeSet attrs,
- int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int count = getChildCount();
-
- int maxHeight = 0;
- int maxWidth = 0;
-
- // Find out how big everyone wants to be
- measureChildren(widthMeasureSpec, heightMeasureSpec);
-
- // Find rightmost and bottom-most child
- for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
- if (child.getVisibility() != GONE) {
- int childRight;
- int childBottom;
-
- AbsoluteLayout.LayoutParams lp
- = (AbsoluteLayout.LayoutParams) child.getLayoutParams();
-
- childRight = lp.x + child.getMeasuredWidth();
- childBottom = lp.y + child.getMeasuredHeight();
-
- maxWidth = Math.max(maxWidth, childRight);
- maxHeight = Math.max(maxHeight, childBottom);
- }
- }
-
- // Account for padding too
- maxWidth += mPaddingLeft + mPaddingRight;
- maxHeight += mPaddingTop + mPaddingBottom;
-
- // Check against minimum height and width
- maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
- maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
-
- setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
- resolveSize(maxHeight, heightMeasureSpec));
- }
-
- /**
- * Returns a set of layout parameters with a width of
- * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT},
- * a height of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}
- * and with the coordinates (0, 0).
- */
- @Override
- protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
- return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0, 0);
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t,
- int r, int b) {
- int count = getChildCount();
-
- for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
- if (child.getVisibility() != GONE) {
-
- AbsoluteLayout.LayoutParams lp =
- (AbsoluteLayout.LayoutParams) child.getLayoutParams();
-
- int childLeft = mPaddingLeft + lp.x;
- int childTop = mPaddingTop + lp.y;
- child.layout(childLeft, childTop,
- childLeft + child.getMeasuredWidth(),
- childTop + child.getMeasuredHeight());
-
- }
- }
- }
-
- @Override
- public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new AbsoluteLayout.LayoutParams(getContext(), attrs);
- }
-
- // Override to allow type-checking of LayoutParams.
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof AbsoluteLayout.LayoutParams;
- }
-
- @Override
- protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return new LayoutParams(p);
- }
-
- /**
- * Per-child layout information associated with AbsoluteLayout.
- * See
- * {@link android.R.styleable#AbsoluteLayout_Layout Absolute Layout Attributes}
- * for a list of all child view attributes that this class supports.
- */
- public static class LayoutParams extends ViewGroup.LayoutParams {
- /**
- * The horizontal, or X, location of the child within the view group.
- */
- public int x;
- /**
- * The vertical, or Y, location of the child within the view group.
- */
- public int y;
-
- /**
- * Creates a new set of layout parameters with the specified width,
- * height and location.
- *
- * @param width the width, either {@link #FILL_PARENT},
- {@link #WRAP_CONTENT} or a fixed size in pixels
- * @param height the height, either {@link #FILL_PARENT},
- {@link #WRAP_CONTENT} or a fixed size in pixels
- * @param x the X location of the child
- * @param y the Y location of the child
- */
- public LayoutParams(int width, int height, int x, int y) {
- super(width, height);
- this.x = x;
- this.y = y;
- }
-
- /**
- * Creates a new set of layout parameters. The values are extracted from
- * the supplied attributes set and context. The XML attributes mapped
- * to this set of layout parameters are:
- *
- * <ul>
- * <li><code>layout_x</code>: the X location of the child</li>
- * <li><code>layout_y</code>: the Y location of the child</li>
- * <li>All the XML attributes from
- * {@link android.view.ViewGroup.LayoutParams}</li>
- * </ul>
- *
- * @param c the application environment
- * @param attrs the set of attributes fom which to extract the layout
- * parameters values
- */
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
- TypedArray a = c.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.AbsoluteLayout_Layout);
- x = a.getDimensionPixelOffset(
- com.android.internal.R.styleable.AbsoluteLayout_Layout_layout_x, 0);
- y = a.getDimensionPixelOffset(
- com.android.internal.R.styleable.AbsoluteLayout_Layout_layout_y, 0);
- a.recycle();
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(ViewGroup.LayoutParams source) {
- super(source);
- }
-
- @Override
- public String debug(String output) {
- return output + "Absolute.LayoutParams={width="
- + sizeToString(width) + ", height=" + sizeToString(height)
- + " x=" + x + " y=" + y + "}";
- }
- }
-}
-
-
diff --git a/core/java/android/widget/Adapter.java b/core/java/android/widget/Adapter.java
deleted file mode 100644
index f2b3e2a..0000000
--- a/core/java/android/widget/Adapter.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.database.DataSetObserver;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * An Adapter object acts as a bridge between an {@link AdapterView} and the
- * underlying data for that view. The Adapter provides access to the data items.
- * The Adapter is also responsible for making a {@link android.view.View} for
- * each item in the data set.
- *
- * @see android.widget.ArrayAdapter
- * @see android.widget.CursorAdapter
- * @see android.widget.SimpleCursorAdapter
- */
-public interface Adapter {
- /**
- * Register an observer that is called when changes happen to the data used by this adapter.
- *
- * @param observer the object that gets notified when the data set changes.
- */
- void registerDataSetObserver(DataSetObserver observer);
-
- /**
- * Unregister an observer that has previously been registered with this
- * adapter via {@link #registerDataSetObserver}.
- *
- * @param observer the object to unregister.
- */
- void unregisterDataSetObserver(DataSetObserver observer);
-
- /**
- * How many items are in the data set represented by this Adapter.
- *
- * @return Count of items.
- */
- int getCount();
-
- /**
- * Get the data item associated with the specified position in the data set.
- *
- * @param position Position of the item whose data we want within the adapter's
- * data set.
- * @return The data at the specified position.
- */
- Object getItem(int position);
-
- /**
- * Get the row id associated with the specified position in the list.
- *
- * @param position The position of the item within the adapter's data set whose row id we want.
- * @return The id of the item at the specified position.
- */
- long getItemId(int position);
-
- /**
- * Indicated whether the item ids are stable across changes to the
- * underlying data.
- *
- * @return True if the same id always refers to the same object.
- */
- boolean hasStableIds();
-
- /**
- * Get a View that displays the data at the specified position in the data set. You can either
- * create a View manually or inflate it from an XML layout file. When the View is inflated, the
- * parent View (GridView, ListView...) will apply default layout parameters unless you use
- * {@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)}
- * to specify a root view and to prevent attachment to the root.
- *
- * @param position The position of the item within the adapter's data set of the item whose view
- * we want.
- * @param convertView The old view to reuse, if possible. Note: You should check that this view
- * is non-null and of an appropriate type before using. If it is not possible to convert
- * this view to display the correct data, this method can create a new view.
- * @param parent The parent that this view will eventually be attached to
- * @return A View corresponding to the data at the specified position.
- */
- View getView(int position, View convertView, ViewGroup parent);
-
- /**
- * An item view type that causes the {@link AdapterView} to ignore the item
- * view. For example, this can be used if the client does not want a
- * particular view to be given for conversion in
- * {@link #getView(int, View, ViewGroup)}.
- *
- * @see #getItemViewType(int)
- * @see #getViewTypeCount()
- */
- static final int IGNORE_ITEM_VIEW_TYPE = AdapterView.ITEM_VIEW_TYPE_IGNORE;
-
- /**
- * Get the type of View that will be created by {@link #getView} for the specified item.
- *
- * @param position The position of the item within the adapter's data set whose view type we
- * want.
- * @return An integer representing the type of View. Two views should share the same type if one
- * can be converted to the other in {@link #getView}. Note: Integers must be in the
- * range 0 to {@link #getViewTypeCount} - 1. {@link #IGNORE_ITEM_VIEW_TYPE} can
- * also be returned.
- * @see #IGNORE_ITEM_VIEW_TYPE
- */
- int getItemViewType(int position);
-
- /**
- * <p>
- * Returns the number of types of Views that will be created by
- * {@link #getView}. Each type represents a set of views that can be
- * converted in {@link #getView}. If the adapter always returns the same
- * type of View for all items, this method should return 1.
- * </p>
- * <p>
- * This method will only be called when when the adapter is set on the
- * the {@link AdapterView}.
- * </p>
- *
- * @return The number of types of Views that will be created by this adapter
- */
- int getViewTypeCount();
-
- static final int NO_SELECTION = Integer.MIN_VALUE;
-
- /**
- * @return true if this adapter doesn't contain any data. This is used to determine
- * whether the empty view should be displayed. A typical implementation will return
- * getCount() == 0 but since getCount() includes the headers and footers, specialized
- * adapters might want a different behavior.
- */
- boolean isEmpty();
-}
-
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
deleted file mode 100644
index 173e80f..0000000
--- a/core/java/android/widget/AdapterView.java
+++ /dev/null
@@ -1,1097 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.database.DataSetObserver;
-import android.os.Handler;
-import android.os.Parcelable;
-import android.os.SystemClock;
-import android.util.AttributeSet;
-import android.util.SparseArray;
-import android.view.ContextMenu;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewDebug;
-import android.view.SoundEffectConstants;
-import android.view.ContextMenu.ContextMenuInfo;
-
-
-/**
- * An AdapterView is a view whose children are determined by an {@link Adapter}.
- *
- * <p>
- * See {@link ListView}, {@link GridView}, {@link Spinner} and
- * {@link Gallery} for commonly used subclasses of AdapterView.
- */
-public abstract class AdapterView<T extends Adapter> extends ViewGroup {
-
- /**
- * The item view type returned by {@link Adapter#getItemViewType(int)} when
- * the adapter does not want the item's view recycled.
- */
- public static final int ITEM_VIEW_TYPE_IGNORE = -1;
-
- /**
- * The item view type returned by {@link Adapter#getItemViewType(int)} when
- * the item is a header or footer.
- */
- public static final int ITEM_VIEW_TYPE_HEADER_OR_FOOTER = -2;
-
- /**
- * The position of the first child displayed
- */
- @ViewDebug.ExportedProperty
- int mFirstPosition = 0;
-
- /**
- * The offset in pixels from the top of the AdapterView to the top
- * of the view to select during the next layout.
- */
- int mSpecificTop;
-
- /**
- * Position from which to start looking for mSyncRowId
- */
- int mSyncPosition;
-
- /**
- * Row id to look for when data has changed
- */
- long mSyncRowId = INVALID_ROW_ID;
-
- /**
- * Height of the view when mSyncPosition and mSyncRowId where set
- */
- long mSyncHeight;
-
- /**
- * True if we need to sync to mSyncRowId
- */
- boolean mNeedSync = false;
-
- /**
- * Indicates whether to sync based on the selection or position. Possible
- * values are {@link #SYNC_SELECTED_POSITION} or
- * {@link #SYNC_FIRST_POSITION}.
- */
- int mSyncMode;
-
- /**
- * Our height after the last layout
- */
- private int mLayoutHeight;
-
- /**
- * Sync based on the selected child
- */
- static final int SYNC_SELECTED_POSITION = 0;
-
- /**
- * Sync based on the first child displayed
- */
- static final int SYNC_FIRST_POSITION = 1;
-
- /**
- * Maximum amount of time to spend in {@link #findSyncPosition()}
- */
- static final int SYNC_MAX_DURATION_MILLIS = 100;
-
- /**
- * Indicates that this view is currently being laid out.
- */
- boolean mInLayout = false;
-
- /**
- * The listener that receives notifications when an item is selected.
- */
- OnItemSelectedListener mOnItemSelectedListener;
-
- /**
- * The listener that receives notifications when an item is clicked.
- */
- OnItemClickListener mOnItemClickListener;
-
- /**
- * The listener that receives notifications when an item is long clicked.
- */
- OnItemLongClickListener mOnItemLongClickListener;
-
- /**
- * True if the data has changed since the last layout
- */
- boolean mDataChanged;
-
- /**
- * The position within the adapter's data set of the item to select
- * during the next layout.
- */
- @ViewDebug.ExportedProperty
- int mNextSelectedPosition = INVALID_POSITION;
-
- /**
- * The item id of the item to select during the next layout.
- */
- long mNextSelectedRowId = INVALID_ROW_ID;
-
- /**
- * The position within the adapter's data set of the currently selected item.
- */
- @ViewDebug.ExportedProperty
- int mSelectedPosition = INVALID_POSITION;
-
- /**
- * The item id of the currently selected item.
- */
- long mSelectedRowId = INVALID_ROW_ID;
-
- /**
- * View to show if there are no items to show.
- */
- View mEmptyView;
-
- /**
- * The number of items in the current adapter.
- */
- @ViewDebug.ExportedProperty
- int mItemCount;
-
- /**
- * The number of items in the adapter before a data changed event occured.
- */
- int mOldItemCount;
-
- /**
- * Represents an invalid position. All valid positions are in the range 0 to 1 less than the
- * number of items in the current adapter.
- */
- public static final int INVALID_POSITION = -1;
-
- /**
- * Represents an empty or invalid row id
- */
- public static final long INVALID_ROW_ID = Long.MIN_VALUE;
-
- /**
- * The last selected position we used when notifying
- */
- int mOldSelectedPosition = INVALID_POSITION;
-
- /**
- * The id of the last selected position we used when notifying
- */
- long mOldSelectedRowId = INVALID_ROW_ID;
-
- /**
- * Indicates what focusable state is requested when calling setFocusable().
- * In addition to this, this view has other criteria for actually
- * determining the focusable state (such as whether its empty or the text
- * filter is shown).
- *
- * @see #setFocusable(boolean)
- * @see #checkFocus()
- */
- private boolean mDesiredFocusableState;
- private boolean mDesiredFocusableInTouchModeState;
-
- private SelectionNotifier mSelectionNotifier;
- /**
- * When set to true, calls to requestLayout() will not propagate up the parent hierarchy.
- * This is used to layout the children during a layout pass.
- */
- boolean mBlockLayoutRequests = false;
-
- public AdapterView(Context context) {
- super(context);
- }
-
- public AdapterView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public AdapterView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
-
- /**
- * Interface definition for a callback to be invoked when an item in this
- * AdapterView has been clicked.
- */
- public interface OnItemClickListener {
-
- /**
- * Callback method to be invoked when an item in this AdapterView has
- * been clicked.
- * <p>
- * Implementers can call getItemAtPosition(position) if they need
- * to access the data associated with the selected item.
- *
- * @param parent The AdapterView where the click happened.
- * @param view The view within the AdapterView that was clicked (this
- * will be a view provided by the adapter)
- * @param position The position of the view in the adapter.
- * @param id The row id of the item that was clicked.
- */
- void onItemClick(AdapterView<?> parent, View view, int position, long id);
- }
-
- /**
- * Register a callback to be invoked when an item in this AdapterView has
- * been clicked.
- *
- * @param listener The callback that will be invoked.
- */
- public void setOnItemClickListener(OnItemClickListener listener) {
- mOnItemClickListener = listener;
- }
-
- /**
- * @return The callback to be invoked with an item in this AdapterView has
- * been clicked, or null id no callback has been set.
- */
- public final OnItemClickListener getOnItemClickListener() {
- return mOnItemClickListener;
- }
-
- /**
- * Call the OnItemClickListener, if it is defined.
- *
- * @param view The view within the AdapterView that was clicked.
- * @param position The position of the view in the adapter.
- * @param id The row id of the item that was clicked.
- * @return True if there was an assigned OnItemClickListener that was
- * called, false otherwise is returned.
- */
- public boolean performItemClick(View view, int position, long id) {
- if (mOnItemClickListener != null) {
- playSoundEffect(SoundEffectConstants.CLICK);
- mOnItemClickListener.onItemClick(this, view, position, id);
- return true;
- }
-
- return false;
- }
-
- /**
- * Interface definition for a callback to be invoked when an item in this
- * view has been clicked and held.
- */
- public interface OnItemLongClickListener {
- /**
- * Callback method to be invoked when an item in this view has been
- * clicked and held.
- *
- * Implementers can call getItemAtPosition(position) if they need to access
- * the data associated with the selected item.
- *
- * @param parent The AbsListView where the click happened
- * @param view The view within the AbsListView that was clicked
- * @param position The position of the view in the list
- * @param id The row id of the item that was clicked
- *
- * @return true if the callback consumed the long click, false otherwise
- */
- boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id);
- }
-
-
- /**
- * Register a callback to be invoked when an item in this AdapterView has
- * been clicked and held
- *
- * @param listener The callback that will run
- */
- public void setOnItemLongClickListener(OnItemLongClickListener listener) {
- if (!isLongClickable()) {
- setLongClickable(true);
- }
- mOnItemLongClickListener = listener;
- }
-
- /**
- * @return The callback to be invoked with an item in this AdapterView has
- * been clicked and held, or null id no callback as been set.
- */
- public final OnItemLongClickListener getOnItemLongClickListener() {
- return mOnItemLongClickListener;
- }
-
- /**
- * Interface definition for a callback to be invoked when
- * an item in this view has been selected.
- */
- public interface OnItemSelectedListener {
- /**
- * Callback method to be invoked when an item in this view has been
- * selected.
- *
- * Impelmenters can call getItemAtPosition(position) if they need to access the
- * data associated with the selected item.
- *
- * @param parent The AdapterView where the selection happened
- * @param view The view within the AdapterView that was clicked
- * @param position The position of the view in the adapter
- * @param id The row id of the item that is selected
- */
- void onItemSelected(AdapterView<?> parent, View view, int position, long id);
-
- /**
- * Callback method to be invoked when the selection disappears from this
- * view. The selection can disappear for instance when touch is activated
- * or when the adapter becomes empty.
- *
- * @param parent The AdapterView that now contains no selected item.
- */
- void onNothingSelected(AdapterView<?> parent);
- }
-
-
- /**
- * Register a callback to be invoked when an item in this AdapterView has
- * been selected.
- *
- * @param listener The callback that will run
- */
- public void setOnItemSelectedListener(OnItemSelectedListener listener) {
- mOnItemSelectedListener = listener;
- }
-
- public final OnItemSelectedListener getOnItemSelectedListener() {
- return mOnItemSelectedListener;
- }
-
- /**
- * Extra menu information provided to the
- * {@link android.view.View.OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo) }
- * callback when a context menu is brought up for this AdapterView.
- *
- */
- public static class AdapterContextMenuInfo implements ContextMenu.ContextMenuInfo {
-
- public AdapterContextMenuInfo(View targetView, int position, long id) {
- this.targetView = targetView;
- this.position = position;
- this.id = id;
- }
-
- /**
- * The child view for which the context menu is being displayed. This
- * will be one of the children of this AdapterView.
- */
- public View targetView;
-
- /**
- * The position in the adapter for which the context menu is being
- * displayed.
- */
- public int position;
-
- /**
- * The row id of the item for which the context menu is being displayed.
- */
- public long id;
- }
-
- /**
- * Returns the adapter currently associated with this widget.
- *
- * @return The adapter used to provide this view's content.
- */
- public abstract T getAdapter();
-
- /**
- * Sets the adapter that provides the data and the views to represent the data
- * in this widget.
- *
- * @param adapter The adapter to use to create this view's content.
- */
- public abstract void setAdapter(T adapter);
-
- /**
- * This method is not supported and throws an UnsupportedOperationException when called.
- *
- * @param child Ignored.
- *
- * @throws UnsupportedOperationException Every time this method is invoked.
- */
- @Override
- public void addView(View child) {
- throw new UnsupportedOperationException("addView(View) is not supported in AdapterView");
- }
-
- /**
- * This method is not supported and throws an UnsupportedOperationException when called.
- *
- * @param child Ignored.
- * @param index Ignored.
- *
- * @throws UnsupportedOperationException Every time this method is invoked.
- */
- @Override
- public void addView(View child, int index) {
- throw new UnsupportedOperationException("addView(View, int) is not supported in AdapterView");
- }
-
- /**
- * This method is not supported and throws an UnsupportedOperationException when called.
- *
- * @param child Ignored.
- * @param params Ignored.
- *
- * @throws UnsupportedOperationException Every time this method is invoked.
- */
- @Override
- public void addView(View child, LayoutParams params) {
- throw new UnsupportedOperationException("addView(View, LayoutParams) "
- + "is not supported in AdapterView");
- }
-
- /**
- * This method is not supported and throws an UnsupportedOperationException when called.
- *
- * @param child Ignored.
- * @param index Ignored.
- * @param params Ignored.
- *
- * @throws UnsupportedOperationException Every time this method is invoked.
- */
- @Override
- public void addView(View child, int index, LayoutParams params) {
- throw new UnsupportedOperationException("addView(View, int, LayoutParams) "
- + "is not supported in AdapterView");
- }
-
- /**
- * This method is not supported and throws an UnsupportedOperationException when called.
- *
- * @param child Ignored.
- *
- * @throws UnsupportedOperationException Every time this method is invoked.
- */
- @Override
- public void removeView(View child) {
- throw new UnsupportedOperationException("removeView(View) is not supported in AdapterView");
- }
-
- /**
- * This method is not supported and throws an UnsupportedOperationException when called.
- *
- * @param index Ignored.
- *
- * @throws UnsupportedOperationException Every time this method is invoked.
- */
- @Override
- public void removeViewAt(int index) {
- throw new UnsupportedOperationException("removeViewAt(int) is not supported in AdapterView");
- }
-
- /**
- * This method is not supported and throws an UnsupportedOperationException when called.
- *
- * @throws UnsupportedOperationException Every time this method is invoked.
- */
- @Override
- public void removeAllViews() {
- throw new UnsupportedOperationException("removeAllViews() is not supported in AdapterView");
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- mLayoutHeight = getHeight();
- }
-
- /**
- * Return the position of the currently selected item within the adapter's data set
- *
- * @return int Position (starting at 0), or {@link #INVALID_POSITION} if there is nothing selected.
- */
- @ViewDebug.CapturedViewProperty
- public int getSelectedItemPosition() {
- return mNextSelectedPosition;
- }
-
- /**
- * @return The id corresponding to the currently selected item, or {@link #INVALID_ROW_ID}
- * if nothing is selected.
- */
- @ViewDebug.CapturedViewProperty
- public long getSelectedItemId() {
- return mNextSelectedRowId;
- }
-
- /**
- * @return The view corresponding to the currently selected item, or null
- * if nothing is selected
- */
- public abstract View getSelectedView();
-
- /**
- * @return The data corresponding to the currently selected item, or
- * null if there is nothing selected.
- */
- public Object getSelectedItem() {
- T adapter = getAdapter();
- int selection = getSelectedItemPosition();
- if (adapter != null && adapter.getCount() > 0 && selection >= 0) {
- return adapter.getItem(selection);
- } else {
- return null;
- }
- }
-
- /**
- * @return The number of items owned by the Adapter associated with this
- * AdapterView. (This is the number of data items, which may be
- * larger than the number of visible view.)
- */
- @ViewDebug.CapturedViewProperty
- public int getCount() {
- return mItemCount;
- }
-
- /**
- * Get the position within the adapter's data set for the view, where view is a an adapter item
- * or a descendant of an adapter item.
- *
- * @param view an adapter item, or a descendant of an adapter item. This must be visible in this
- * AdapterView at the time of the call.
- * @return the position within the adapter's data set of the view, or {@link #INVALID_POSITION}
- * if the view does not correspond to a list item (or it is not currently visible).
- */
- public int getPositionForView(View view) {
- View listItem = view;
- try {
- View v;
- while (!(v = (View) listItem.getParent()).equals(this)) {
- listItem = v;
- }
- } catch (ClassCastException e) {
- // We made it up to the window without find this list view
- return INVALID_POSITION;
- }
-
- // Search the children for the list item
- final int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- if (getChildAt(i).equals(listItem)) {
- return mFirstPosition + i;
- }
- }
-
- // Child not found!
- return INVALID_POSITION;
- }
-
- /**
- * Returns the position within the adapter's data set for the first item
- * displayed on screen.
- *
- * @return The position within the adapter's data set
- */
- public int getFirstVisiblePosition() {
- return mFirstPosition;
- }
-
- /**
- * Returns the position within the adapter's data set for the last item
- * displayed on screen.
- *
- * @return The position within the adapter's data set
- */
- public int getLastVisiblePosition() {
- return mFirstPosition + getChildCount() - 1;
- }
-
- /**
- * Sets the currently selected item
- * @param position Index (starting at 0) of the data item to be selected.
- */
- public abstract void setSelection(int position);
-
- /**
- * Sets the view to show if the adapter is empty
- */
- public void setEmptyView(View emptyView) {
- mEmptyView = emptyView;
-
- final T adapter = getAdapter();
- final boolean empty = ((adapter == null) || adapter.isEmpty());
- updateEmptyStatus(empty);
- }
-
- /**
- * When the current adapter is empty, the AdapterView can display a special view
- * call the empty view. The empty view is used to provide feedback to the user
- * that no data is available in this AdapterView.
- *
- * @return The view to show if the adapter is empty.
- */
- public View getEmptyView() {
- return mEmptyView;
- }
-
- /**
- * Indicates whether this view is in filter mode. Filter mode can for instance
- * be enabled by a user when typing on the keyboard.
- *
- * @return True if the view is in filter mode, false otherwise.
- */
- boolean isInFilterMode() {
- return false;
- }
-
- @Override
- public void setFocusable(boolean focusable) {
- final T adapter = getAdapter();
- final boolean empty = adapter == null || adapter.getCount() == 0;
-
- mDesiredFocusableState = focusable;
- if (!focusable) {
- mDesiredFocusableInTouchModeState = false;
- }
-
- super.setFocusable(focusable && (!empty || isInFilterMode()));
- }
-
- @Override
- public void setFocusableInTouchMode(boolean focusable) {
- final T adapter = getAdapter();
- final boolean empty = adapter == null || adapter.getCount() == 0;
-
- mDesiredFocusableInTouchModeState = focusable;
- if (focusable) {
- mDesiredFocusableState = true;
- }
-
- super.setFocusableInTouchMode(focusable && (!empty || isInFilterMode()));
- }
-
- void checkFocus() {
- final T adapter = getAdapter();
- final boolean empty = adapter == null || adapter.getCount() == 0;
- final boolean focusable = !empty || isInFilterMode();
- // The order in which we set focusable in touch mode/focusable may matter
- // for the client, see View.setFocusableInTouchMode() comments for more
- // details
- super.setFocusableInTouchMode(focusable && mDesiredFocusableInTouchModeState);
- super.setFocusable(focusable && mDesiredFocusableState);
- if (mEmptyView != null) {
- updateEmptyStatus((adapter == null) || adapter.isEmpty());
- }
- }
-
- /**
- * Update the status of the list based on the empty parameter. If empty is true and
- * we have an empty view, display it. In all the other cases, make sure that the listview
- * is VISIBLE and that the empty view is GONE (if it's not null).
- */
- private void updateEmptyStatus(boolean empty) {
- if (isInFilterMode()) {
- empty = false;
- }
-
- if (empty) {
- if (mEmptyView != null) {
- mEmptyView.setVisibility(View.VISIBLE);
- setVisibility(View.GONE);
- } else {
- // If the caller just removed our empty view, make sure the list view is visible
- setVisibility(View.VISIBLE);
- }
-
- // We are now GONE, so pending layouts will not be dispatched.
- // Force one here to make sure that the state of the list matches
- // the state of the adapter.
- if (mDataChanged) {
- this.onLayout(false, mLeft, mTop, mRight, mBottom);
- }
- } else {
- if (mEmptyView != null) mEmptyView.setVisibility(View.GONE);
- setVisibility(View.VISIBLE);
- }
- }
-
- /**
- * Gets the data associated with the specified position in the list.
- *
- * @param position Which data to get
- * @return The data associated with the specified position in the list
- */
- public Object getItemAtPosition(int position) {
- T adapter = getAdapter();
- return (adapter == null || position < 0) ? null : adapter.getItem(position);
- }
-
- public long getItemIdAtPosition(int position) {
- T adapter = getAdapter();
- return (adapter == null || position < 0) ? INVALID_ROW_ID : adapter.getItemId(position);
- }
-
- @Override
- public void setOnClickListener(OnClickListener l) {
- throw new RuntimeException("Don't call setOnClickListener for an AdapterView. "
- + "You probably want setOnItemClickListener instead");
- }
-
- /**
- * Override to prevent freezing of any views created by the adapter.
- */
- @Override
- protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
- dispatchFreezeSelfOnly(container);
- }
-
- /**
- * Override to prevent thawing of any views created by the adapter.
- */
- @Override
- protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
- dispatchThawSelfOnly(container);
- }
-
- class AdapterDataSetObserver extends DataSetObserver {
-
- private Parcelable mInstanceState = null;
-
- @Override
- public void onChanged() {
- mDataChanged = true;
- mOldItemCount = mItemCount;
- mItemCount = getAdapter().getCount();
-
- // Detect the case where a cursor that was previously invalidated has
- // been repopulated with new data.
- if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
- && mOldItemCount == 0 && mItemCount > 0) {
- AdapterView.this.onRestoreInstanceState(mInstanceState);
- mInstanceState = null;
- } else {
- rememberSyncState();
- }
- checkFocus();
- requestLayout();
- }
-
- @Override
- public void onInvalidated() {
- mDataChanged = true;
-
- if (AdapterView.this.getAdapter().hasStableIds()) {
- // Remember the current state for the case where our hosting activity is being
- // stopped and later restarted
- mInstanceState = AdapterView.this.onSaveInstanceState();
- }
-
- // Data is invalid so we should reset our state
- mOldItemCount = mItemCount;
- mItemCount = 0;
- mSelectedPosition = INVALID_POSITION;
- mSelectedRowId = INVALID_ROW_ID;
- mNextSelectedPosition = INVALID_POSITION;
- mNextSelectedRowId = INVALID_ROW_ID;
- mNeedSync = false;
- checkSelectionChanged();
-
- checkFocus();
- requestLayout();
- }
-
- public void clearSavedState() {
- mInstanceState = null;
- }
- }
-
- private class SelectionNotifier extends Handler implements Runnable {
- public void run() {
- if (mDataChanged) {
- // Data has changed between when this SelectionNotifier
- // was posted and now. We need to wait until the AdapterView
- // has been synched to the new data.
- post(this);
- } else {
- fireOnSelected();
- }
- }
- }
-
- void selectionChanged() {
- if (mOnItemSelectedListener != null) {
- if (mInLayout || mBlockLayoutRequests) {
- // If we are in a layout traversal, defer notification
- // by posting. This ensures that the view tree is
- // in a consistent state and is able to accomodate
- // new layout or invalidate requests.
- if (mSelectionNotifier == null) {
- mSelectionNotifier = new SelectionNotifier();
- }
- mSelectionNotifier.post(mSelectionNotifier);
- } else {
- fireOnSelected();
- }
- }
- }
-
- private void fireOnSelected() {
- if (mOnItemSelectedListener == null)
- return;
-
- int selection = this.getSelectedItemPosition();
- if (selection >= 0) {
- View v = getSelectedView();
- mOnItemSelectedListener.onItemSelected(this, v, selection,
- getAdapter().getItemId(selection));
- } else {
- mOnItemSelectedListener.onNothingSelected(this);
- }
- }
-
- @Override
- protected boolean canAnimate() {
- return super.canAnimate() && mItemCount > 0;
- }
-
- void handleDataChanged() {
- final int count = mItemCount;
- boolean found = false;
-
- if (count > 0) {
-
- int newPos;
-
- // Find the row we are supposed to sync to
- if (mNeedSync) {
- // Update this first, since setNextSelectedPositionInt inspects
- // it
- mNeedSync = false;
-
- // See if we can find a position in the new data with the same
- // id as the old selection
- newPos = findSyncPosition();
- if (newPos >= 0) {
- // Verify that new selection is selectable
- int selectablePos = lookForSelectablePosition(newPos, true);
- if (selectablePos == newPos) {
- // Same row id is selected
- setNextSelectedPositionInt(newPos);
- found = true;
- }
- }
- }
- if (!found) {
- // Try to use the same position if we can't find matching data
- newPos = getSelectedItemPosition();
-
- // Pin position to the available range
- if (newPos >= count) {
- newPos = count - 1;
- }
- if (newPos < 0) {
- newPos = 0;
- }
-
- // Make sure we select something selectable -- first look down
- int selectablePos = lookForSelectablePosition(newPos, true);
- if (selectablePos < 0) {
- // Looking down didn't work -- try looking up
- selectablePos = lookForSelectablePosition(newPos, false);
- }
- if (selectablePos >= 0) {
- setNextSelectedPositionInt(selectablePos);
- checkSelectionChanged();
- found = true;
- }
- }
- }
- if (!found) {
- // Nothing is selected
- mSelectedPosition = INVALID_POSITION;
- mSelectedRowId = INVALID_ROW_ID;
- mNextSelectedPosition = INVALID_POSITION;
- mNextSelectedRowId = INVALID_ROW_ID;
- mNeedSync = false;
- checkSelectionChanged();
- }
- }
-
- void checkSelectionChanged() {
- if ((mSelectedPosition != mOldSelectedPosition) || (mSelectedRowId != mOldSelectedRowId)) {
- selectionChanged();
- mOldSelectedPosition = mSelectedPosition;
- mOldSelectedRowId = mSelectedRowId;
- }
- }
-
- /**
- * Searches the adapter for a position matching mSyncRowId. The search starts at mSyncPosition
- * and then alternates between moving up and moving down until 1) we find the right position, or
- * 2) we run out of time, or 3) we have looked at every position
- *
- * @return Position of the row that matches mSyncRowId, or {@link #INVALID_POSITION} if it can't
- * be found
- */
- int findSyncPosition() {
- int count = mItemCount;
-
- if (count == 0) {
- return INVALID_POSITION;
- }
-
- long idToMatch = mSyncRowId;
- int seed = mSyncPosition;
-
- // If there isn't a selection don't hunt for it
- if (idToMatch == INVALID_ROW_ID) {
- return INVALID_POSITION;
- }
-
- // Pin seed to reasonable values
- seed = Math.max(0, seed);
- seed = Math.min(count - 1, seed);
-
- long endTime = SystemClock.uptimeMillis() + SYNC_MAX_DURATION_MILLIS;
-
- long rowId;
-
- // first position scanned so far
- int first = seed;
-
- // last position scanned so far
- int last = seed;
-
- // True if we should move down on the next iteration
- boolean next = false;
-
- // True when we have looked at the first item in the data
- boolean hitFirst;
-
- // True when we have looked at the last item in the data
- boolean hitLast;
-
- // Get the item ID locally (instead of getItemIdAtPosition), so
- // we need the adapter
- T adapter = getAdapter();
- if (adapter == null) {
- return INVALID_POSITION;
- }
-
- while (SystemClock.uptimeMillis() <= endTime) {
- rowId = adapter.getItemId(seed);
- if (rowId == idToMatch) {
- // Found it!
- return seed;
- }
-
- hitLast = last == count - 1;
- hitFirst = first == 0;
-
- if (hitLast && hitFirst) {
- // Looked at everything
- break;
- }
-
- if (hitFirst || (next && !hitLast)) {
- // Either we hit the top, or we are trying to move down
- last++;
- seed = last;
- // Try going up next time
- next = false;
- } else if (hitLast || (!next && !hitFirst)) {
- // Either we hit the bottom, or we are trying to move up
- first--;
- seed = first;
- // Try going down next time
- next = true;
- }
-
- }
-
- return INVALID_POSITION;
- }
-
- /**
- * Find a position that can be selected (i.e., is not a separator).
- *
- * @param position The starting position to look at.
- * @param lookDown Whether to look down for other positions.
- * @return The next selectable position starting at position and then searching either up or
- * down. Returns {@link #INVALID_POSITION} if nothing can be found.
- */
- int lookForSelectablePosition(int position, boolean lookDown) {
- return position;
- }
-
- /**
- * Utility to keep mSelectedPosition and mSelectedRowId in sync
- * @param position Our current position
- */
- void setSelectedPositionInt(int position) {
- mSelectedPosition = position;
- mSelectedRowId = getItemIdAtPosition(position);
- }
-
- /**
- * Utility to keep mNextSelectedPosition and mNextSelectedRowId in sync
- * @param position Intended value for mSelectedPosition the next time we go
- * through layout
- */
- void setNextSelectedPositionInt(int position) {
- mNextSelectedPosition = position;
- mNextSelectedRowId = getItemIdAtPosition(position);
- // If we are trying to sync to the selection, update that too
- if (mNeedSync && mSyncMode == SYNC_SELECTED_POSITION && position >= 0) {
- mSyncPosition = position;
- mSyncRowId = mNextSelectedRowId;
- }
- }
-
- /**
- * Remember enough information to restore the screen state when the data has
- * changed.
- *
- */
- void rememberSyncState() {
- if (getChildCount() > 0) {
- mNeedSync = true;
- mSyncHeight = mLayoutHeight;
- if (mSelectedPosition >= 0) {
- // Sync the selection state
- View v = getChildAt(mSelectedPosition - mFirstPosition);
- mSyncRowId = mNextSelectedRowId;
- mSyncPosition = mNextSelectedPosition;
- if (v != null) {
- mSpecificTop = v.getTop();
- }
- mSyncMode = SYNC_SELECTED_POSITION;
- } else {
- // Sync the based on the offset of the first view
- View v = getChildAt(0);
- T adapter = getAdapter();
- if (mFirstPosition >= 0 && mFirstPosition < adapter.getCount()) {
- mSyncRowId = adapter.getItemId(mFirstPosition);
- } else {
- mSyncRowId = NO_ID;
- }
- mSyncPosition = mFirstPosition;
- if (v != null) {
- mSpecificTop = v.getTop();
- }
- mSyncMode = SYNC_FIRST_POSITION;
- }
- }
- }
-}
diff --git a/core/java/android/widget/AlphabetIndexer.java b/core/java/android/widget/AlphabetIndexer.java
deleted file mode 100644
index bbabaaa..0000000
--- a/core/java/android/widget/AlphabetIndexer.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.database.Cursor;
-import android.database.DataSetObserver;
-import android.util.SparseIntArray;
-
-/**
- * A helper class for adapters that implement the SectionIndexer interface.
- * If the items in the adapter are sorted by simple alphabet-based sorting, then
- * this class provides a way to do fast indexing of large lists using binary search.
- * It caches the indices that have been determined through the binary search and also
- * invalidates the cache if changes occur in the cursor.
- * <p/>
- * Your adapter is responsible for updating the cursor by calling {@link #setCursor} if the
- * cursor changes. {@link #getPositionForSection} method does the binary search for the starting
- * index of a given section (alphabet).
- * @hide pending API council approval
- */
-public class AlphabetIndexer extends DataSetObserver implements SectionIndexer {
-
- /**
- * Cursor that is used by the adapter of the list view.
- */
- protected Cursor mDataCursor;
-
- /**
- * The index of the cursor column that this list is sorted on.
- */
- protected int mColumnIndex;
-
- /**
- * The string of characters that make up the indexing sections.
- */
- protected CharSequence mAlphabet;
-
- /**
- * Cached length of the alphabet array.
- */
- private int mAlphabetLength;
-
- /**
- * This contains a cache of the computed indices so far. It will get reset whenever
- * the dataset changes or the cursor changes.
- */
- private SparseIntArray mAlphaMap;
-
- /**
- * Use a collator to compare strings in a localized manner.
- */
- private java.text.Collator mCollator;
-
- /**
- * The section array converted from the alphabet string.
- */
- private String[] mAlphabetArray;
-
- /**
- * Constructs the indexer.
- * @param cursor the cursor containing the data set
- * @param sortedColumnIndex the column number in the cursor that is sorted
- * alphabetically
- * @param alphabet string containing the alphabet, with space as the first character.
- * For example, use the string " ABCDEFGHIJKLMNOPQRSTUVWXYZ" for English indexing.
- * The characters must be uppercase and be sorted in ascii/unicode order. Basically
- * characters in the alphabet will show up as preview letters.
- */
- public AlphabetIndexer(Cursor cursor, int sortedColumnIndex, CharSequence alphabet) {
- mDataCursor = cursor;
- mColumnIndex = sortedColumnIndex;
- mAlphabet = alphabet;
- mAlphabetLength = alphabet.length();
- mAlphabetArray = new String[mAlphabetLength];
- for (int i = 0; i < mAlphabetLength; i++) {
- mAlphabetArray[i] = Character.toString(mAlphabet.charAt(i));
- }
- mAlphaMap = new SparseIntArray(mAlphabetLength);
- if (cursor != null) {
- cursor.registerDataSetObserver(this);
- }
- // Get a Collator for the current locale for string comparisons.
- mCollator = java.text.Collator.getInstance();
- mCollator.setStrength(java.text.Collator.PRIMARY);
- }
-
- /**
- * Returns the section array constructed from the alphabet provided in the constructor.
- * @return the section array
- */
- public Object[] getSections() {
- return mAlphabetArray;
- }
-
- /**
- * Sets a new cursor as the data set and resets the cache of indices.
- * @param cursor the new cursor to use as the data set
- */
- public void setCursor(Cursor cursor) {
- if (mDataCursor != null) {
- mDataCursor.unregisterDataSetObserver(this);
- }
- mDataCursor = cursor;
- if (cursor != null) {
- mDataCursor.registerDataSetObserver(this);
- }
- mAlphaMap.clear();
- }
-
- /**
- * Default implementation compares the first character of word with letter.
- */
- protected int compare(String word, String letter) {
- return mCollator.compare(word.substring(0, 1), letter);
- }
-
- /**
- * Performs a binary search or cache lookup to find the first row that
- * matches a given section's starting letter.
- * @param sectionIndex the section to search for
- * @return the row index of the first occurrence, or the nearest next letter.
- * For instance, if searching for "T" and no "T" is found, then the first
- * row starting with "U" or any higher letter is returned. If there is no
- * data following "T" at all, then the list size is returned.
- */
- public int getPositionForSection(int sectionIndex) {
- final SparseIntArray alphaMap = mAlphaMap;
- final Cursor cursor = mDataCursor;
-
- if (cursor == null || mAlphabet == null) {
- return 0;
- }
-
- // Check bounds
- if (sectionIndex <= 0) {
- return 0;
- }
- if (sectionIndex >= mAlphabetLength) {
- sectionIndex = mAlphabetLength - 1;
- }
-
- int savedCursorPos = cursor.getPosition();
-
- int count = cursor.getCount();
- int start = 0;
- int end = count;
- int pos;
-
- char letter = mAlphabet.charAt(sectionIndex);
- String targetLetter = Character.toString(letter);
- int key = letter;
- // Check map
- if (Integer.MIN_VALUE != (pos = alphaMap.get(key, Integer.MIN_VALUE))) {
- // Is it approximate? Using negative value to indicate that it's
- // an approximation and positive value when it is the accurate
- // position.
- if (pos < 0) {
- pos = -pos;
- end = pos;
- } else {
- // Not approximate, this is the confirmed start of section, return it
- return pos;
- }
- }
-
- // Do we have the position of the previous section?
- if (sectionIndex > 0) {
- int prevLetter =
- mAlphabet.charAt(sectionIndex - 1);
- int prevLetterPos = alphaMap.get(prevLetter, Integer.MIN_VALUE);
- if (prevLetterPos != Integer.MIN_VALUE) {
- start = Math.abs(prevLetterPos);
- }
- }
-
- // Now that we have a possibly optimized start and end, let's binary search
-
- pos = (end + start) / 2;
-
- while (pos < end) {
- // Get letter at pos
- cursor.moveToPosition(pos);
- String curName = cursor.getString(mColumnIndex);
- if (curName == null) {
- if (pos == 0) {
- break;
- } else {
- pos--;
- continue;
- }
- }
- int diff = compare(curName, targetLetter);
- if (diff != 0) {
- // Commenting out approximation code because it doesn't work for certain
- // lists with custom comparators
- // Enter approximation in hash if a better solution doesn't exist
- // String startingLetter = Character.toString(getFirstLetter(curName));
- // int startingLetterKey = startingLetter.charAt(0);
- // int curPos = alphaMap.get(startingLetterKey, Integer.MIN_VALUE);
- // if (curPos == Integer.MIN_VALUE || Math.abs(curPos) > pos) {
- // Negative pos indicates that it is an approximation
- // alphaMap.put(startingLetterKey, -pos);
- // }
- // if (mCollator.compare(startingLetter, targetLetter) < 0) {
- if (diff < 0) {
- start = pos + 1;
- if (start >= count) {
- pos = count;
- break;
- }
- } else {
- end = pos;
- }
- } else {
- // They're the same, but that doesn't mean it's the start
- if (start == pos) {
- // This is it
- break;
- } else {
- // Need to go further lower to find the starting row
- end = pos;
- }
- }
- pos = (start + end) / 2;
- }
- alphaMap.put(key, pos);
- cursor.moveToPosition(savedCursorPos);
- return pos;
- }
-
- /**
- * Returns the section index for a given position in the list by querying the item
- * and comparing it with all items in the section array.
- */
- public int getSectionForPosition(int position) {
- int savedCursorPos = mDataCursor.getPosition();
- mDataCursor.moveToPosition(position);
- mDataCursor.moveToPosition(savedCursorPos);
- String curName = mDataCursor.getString(mColumnIndex);
- // Linear search, as there are only a few items in the section index
- // Could speed this up later if it actually gets used.
- for (int i = 0; i < mAlphabetLength; i++) {
- char letter = mAlphabet.charAt(i);
- String targetLetter = Character.toString(letter);
- if (compare(curName, targetLetter) == 0) {
- return i;
- }
- }
- return 0; // Don't recognize the letter - falls under zero'th section
- }
-
- /*
- * @hide
- */
- @Override
- public void onChanged() {
- super.onChanged();
- mAlphaMap.clear();
- }
-
- /*
- * @hide
- */
- @Override
- public void onInvalidated() {
- super.onInvalidated();
- mAlphaMap.clear();
- }
-}
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
deleted file mode 100644
index cf9c588..0000000
--- a/core/java/android/widget/AnalogClock.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.BroadcastReceiver;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.text.format.Time;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.RemoteViews.RemoteView;
-
-import java.util.TimeZone;
-
-/**
- * This widget display an analogic clock with two hands for hours and
- * minutes.
- */
-@RemoteView
-public class AnalogClock extends View {
- private Time mCalendar;
-
- private Drawable mHourHand;
- private Drawable mMinuteHand;
- private Drawable mDial;
-
- private int mDialWidth;
- private int mDialHeight;
-
- private boolean mAttached;
- private long mLastTime;
-
- private final Handler mHandler = new Handler();
- private float mMinutes;
- private float mHour;
- private boolean mChanged;
-
- public AnalogClock(Context context) {
- this(context, null);
- }
-
- public AnalogClock(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public AnalogClock(Context context, AttributeSet attrs,
- int defStyle) {
- super(context, attrs, defStyle);
- Resources r = mContext.getResources();
- TypedArray a =
- context.obtainStyledAttributes(
- attrs, com.android.internal.R.styleable.AnalogClock, defStyle, 0);
-
- mDial = a.getDrawable(com.android.internal.R.styleable.AnalogClock_dial);
- if (mDial == null) {
- mDial = r.getDrawable(com.android.internal.R.drawable.clock_dial);
- }
-
- mHourHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_hour);
- if (mHourHand == null) {
- mHourHand = r.getDrawable(com.android.internal.R.drawable.clock_hand_hour);
- }
-
- mMinuteHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_minute);
- if (mMinuteHand == null) {
- mMinuteHand = r.getDrawable(com.android.internal.R.drawable.clock_hand_minute);
- }
-
- mCalendar = new Time();
-
- mDialWidth = mDial.getIntrinsicWidth();
- mDialHeight = mDial.getIntrinsicHeight();
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- onTimeChanged();
- if (!mAttached) {
- mAttached = true;
- IntentFilter filter = new IntentFilter();
-
- filter.addAction(Intent.ACTION_TIME_TICK);
- filter.addAction(Intent.ACTION_TIME_CHANGED);
- filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
-
- getContext().registerReceiver(mIntentReceiver, filter, null, mHandler);
- }
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- if (mAttached) {
- getContext().unregisterReceiver(mIntentReceiver);
- mAttached = false;
- }
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
- float hScale = 1.0f;
- float vScale = 1.0f;
-
- if (widthMode != MeasureSpec.UNSPECIFIED && widthSize < mDialWidth) {
- hScale = (float) widthSize / (float) mDialWidth;
- }
-
- if (heightMode != MeasureSpec.UNSPECIFIED && heightSize < mDialHeight) {
- vScale = (float )heightSize / (float) mDialHeight;
- }
-
- float scale = Math.min(hScale, vScale);
-
- setMeasuredDimension(resolveSize((int) (mDialWidth * scale), widthMeasureSpec),
- resolveSize((int) (mDialHeight * scale), heightMeasureSpec));
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- mChanged = true;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- boolean changed = mChanged;
- if (changed) {
- mChanged = false;
- }
-
- int availableWidth = mRight - mLeft;
- int availableHeight = mBottom - mTop;
-
- int x = availableWidth / 2;
- int y = availableHeight / 2;
-
- final Drawable dial = mDial;
- int w = dial.getIntrinsicWidth();
- int h = dial.getIntrinsicHeight();
-
- boolean scaled = false;
-
- if (availableWidth < w || availableHeight < h) {
- scaled = true;
- float scale = Math.min((float) availableWidth / (float) w,
- (float) availableHeight / (float) h);
- canvas.save();
- canvas.scale(scale, scale, x, y);
- }
-
- if (changed) {
- dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
- }
- dial.draw(canvas);
-
- canvas.save();
- canvas.rotate(mHour / 12.0f * 360.0f, x, y);
- final Drawable hourHand = mHourHand;
- if (changed) {
- w = hourHand.getIntrinsicWidth();
- h = hourHand.getIntrinsicHeight();
- hourHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
- }
- hourHand.draw(canvas);
- canvas.restore();
-
- canvas.save();
- canvas.rotate(mMinutes / 60.0f * 360.0f, x, y);
-
- final Drawable minuteHand = mMinuteHand;
- if (changed) {
- w = minuteHand.getIntrinsicWidth();
- h = minuteHand.getIntrinsicHeight();
- minuteHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
- }
- minuteHand.draw(canvas);
- canvas.restore();
-
- if (scaled) {
- canvas.restore();
- }
- }
-
- private void onTimeChanged() {
- long time = System.currentTimeMillis();
- mCalendar.set(time);
- mLastTime = time;
-
- int hour = mCalendar.hour;
- int minute = mCalendar.minute;
- int second = mCalendar.second;
-
- mMinutes = minute + second / 60.0f;
- mHour = hour + mMinutes / 60.0f;
- mChanged = true;
- }
-
- private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
- String tz = intent.getStringExtra("time-zone");
- mCalendar = new Time(TimeZone.getTimeZone(tz).getID());
- } else {
- mCalendar = new Time();
- }
-
- onTimeChanged();
-
- invalidate();
- }
- };
-}
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
deleted file mode 100755
index 5fa00e7..0000000
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-package android.widget;
-
-import com.android.internal.R;
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
-import android.content.pm.PermissionGroupInfo;
-import android.content.pm.PermissionInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import java.io.File;
-import java.text.Collator;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * This class contains the SecurityPermissions view implementation.
- * Initially the package's advanced or dangerous security permissions
- * are displayed under categorized
- * groups. Clicking on the additional permissions presents
- * extended information consisting of all groups and permissions.
- * To use this view define a LinearLayout or any ViewGroup and add this
- * view by instantiating AppSecurityPermissions and invoking getPermissionsView.
- *
- * {@hide}
- */
-public class AppSecurityPermissions implements View.OnClickListener {
-
- private enum State {
- NO_PERMS,
- DANGEROUS_ONLY,
- NORMAL_ONLY,
- BOTH
- }
-
- private final static String TAG = "AppSecurityPermissions";
- private boolean localLOGV = false;
- private Context mContext;
- private LayoutInflater mInflater;
- private PackageManager mPm;
- private LinearLayout mPermsView;
- private Map<String, String> mDangerousMap;
- private Map<String, String> mNormalMap;
- private List<PermissionInfo> mPermsList;
- private String mDefaultGrpLabel;
- private String mDefaultGrpName="DefaultGrp";
- private String mPermFormat;
- private Drawable mNormalIcon;
- private Drawable mDangerousIcon;
- private boolean mExpanded;
- private Drawable mShowMaxIcon;
- private Drawable mShowMinIcon;
- private View mShowMore;
- private TextView mShowMoreText;
- private ImageView mShowMoreIcon;
- private State mCurrentState;
- private LinearLayout mNonDangerousList;
- private LinearLayout mDangerousList;
- private HashMap<String, CharSequence> mGroupLabelCache;
- private View mNoPermsView;
-
- public AppSecurityPermissions(Context context, List<PermissionInfo> permList) {
- mContext = context;
- mPm = mContext.getPackageManager();
- mPermsList = permList;
- }
-
- public AppSecurityPermissions(Context context, String packageName) {
- mContext = context;
- mPm = mContext.getPackageManager();
- mPermsList = new ArrayList<PermissionInfo>();
- Set<PermissionInfo> permSet = new HashSet<PermissionInfo>();
- PackageInfo pkgInfo;
- try {
- pkgInfo = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
- } catch (NameNotFoundException e) {
- Log.w(TAG, "Could'nt retrieve permissions for package:"+packageName);
- return;
- }
- // Extract all user permissions
- if((pkgInfo.applicationInfo != null) && (pkgInfo.applicationInfo.uid != -1)) {
- getAllUsedPermissions(pkgInfo.applicationInfo.uid, permSet);
- }
- for(PermissionInfo tmpInfo : permSet) {
- mPermsList.add(tmpInfo);
- }
- }
-
- public AppSecurityPermissions(Context context, PackageParser.Package pkg) {
- mContext = context;
- mPm = mContext.getPackageManager();
- mPermsList = new ArrayList<PermissionInfo>();
- Set<PermissionInfo> permSet = new HashSet<PermissionInfo>();
- if(pkg == null) {
- return;
- }
- // Extract shared user permissions if any
- if(pkg.mSharedUserId != null) {
- int sharedUid;
- try {
- sharedUid = mPm.getUidForSharedUser(pkg.mSharedUserId);
- } catch (NameNotFoundException e) {
- Log.w(TAG, "Could'nt retrieve shared user id for:"+pkg.packageName);
- return;
- }
- getAllUsedPermissions(sharedUid, permSet);
- } else {
- ArrayList<String> strList = pkg.requestedPermissions;
- int size;
- if((strList == null) || ((size = strList.size()) == 0)) {
- return;
- }
- // Extract permissions defined in current package
- extractPerms(strList.toArray(new String[size]), permSet);
- }
- for(PermissionInfo tmpInfo : permSet) {
- mPermsList.add(tmpInfo);
- }
- }
-
- public PackageParser.Package getPackageInfo(Uri packageURI) {
- final String archiveFilePath = packageURI.getPath();
- PackageParser packageParser = new PackageParser(archiveFilePath);
- File sourceFile = new File(archiveFilePath);
- DisplayMetrics metrics = new DisplayMetrics();
- metrics.setToDefaults();
- return packageParser.parsePackage(sourceFile, archiveFilePath, metrics, 0);
- }
-
- private void getAllUsedPermissions(int sharedUid, Set<PermissionInfo> permSet) {
- String sharedPkgList[] = mPm.getPackagesForUid(sharedUid);
- if(sharedPkgList == null || (sharedPkgList.length == 0)) {
- return;
- }
- for(String sharedPkg : sharedPkgList) {
- getPermissionsForPackage(sharedPkg, permSet);
- }
- }
-
- private void getPermissionsForPackage(String packageName,
- Set<PermissionInfo> permSet) {
- PackageInfo pkgInfo;
- try {
- pkgInfo = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
- } catch (NameNotFoundException e) {
- Log.w(TAG, "Could'nt retrieve permissions for package:"+packageName);
- return;
- }
- if(pkgInfo == null) {
- return;
- }
- String strList[] = pkgInfo.requestedPermissions;
- if(strList == null) {
- return;
- }
- extractPerms(strList, permSet);
- }
-
- private void extractPerms(String strList[], Set<PermissionInfo> permSet) {
- if((strList == null) || (strList.length == 0)) {
- return;
- }
- for(String permName:strList) {
- try {
- PermissionInfo tmpPermInfo = mPm.getPermissionInfo(permName, 0);
- if(tmpPermInfo != null) {
- permSet.add(tmpPermInfo);
- }
- } catch (NameNotFoundException e) {
- Log.i(TAG, "Ignoring unknown permission:"+permName);
- }
- }
- }
-
- public int getPermissionCount() {
- return mPermsList.size();
- }
-
- public View getPermissionsView() {
-
- mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mPermsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
- mShowMore = mPermsView.findViewById(R.id.show_more);
- mShowMoreIcon = (ImageView) mShowMore.findViewById(R.id.show_more_icon);
- mShowMoreText = (TextView) mShowMore.findViewById(R.id.show_more_text);
- mDangerousList = (LinearLayout) mPermsView.findViewById(R.id.dangerous_perms_list);
- mNonDangerousList = (LinearLayout) mPermsView.findViewById(R.id.non_dangerous_perms_list);
- mNoPermsView = mPermsView.findViewById(R.id.no_permissions);
-
- // Set up the LinearLayout that acts like a list item.
- mShowMore.setClickable(true);
- mShowMore.setOnClickListener(this);
- mShowMore.setFocusable(true);
- mShowMore.setBackgroundResource(android.R.drawable.list_selector_background);
-
- // Pick up from framework resources instead.
- mDefaultGrpLabel = mContext.getString(R.string.default_permission_group);
- mPermFormat = mContext.getString(R.string.permissions_format);
- mNormalIcon = mContext.getResources().getDrawable(R.drawable.ic_text_dot);
- mDangerousIcon = mContext.getResources().getDrawable(R.drawable.ic_bullet_key_permission);
- mShowMaxIcon = mContext.getResources().getDrawable(R.drawable.expander_ic_maximized);
- mShowMinIcon = mContext.getResources().getDrawable(R.drawable.expander_ic_minimized);
-
- // Set permissions view
- setPermissions(mPermsList);
- return mPermsView;
- }
-
- /**
- * Canonicalizes the group description before it is displayed to the user.
- *
- * TODO check for internationalization issues remove trailing '.' in str1
- */
- private String canonicalizeGroupDesc(String groupDesc) {
- if ((groupDesc == null) || (groupDesc.length() == 0)) {
- return null;
- }
- // Both str1 and str2 are non-null and are non-zero in size.
- int len = groupDesc.length();
- if(groupDesc.charAt(len-1) == '.') {
- groupDesc = groupDesc.substring(0, len-1);
- }
- return groupDesc;
- }
-
- /**
- * Utility method that concatenates two strings defined by mPermFormat.
- * a null value is returned if both str1 and str2 are null, if one of the strings
- * is null the other non null value is returned without formatting
- * this is to placate initial error checks
- */
- private String formatPermissions(String groupDesc, CharSequence permDesc) {
- if(groupDesc == null) {
- if(permDesc == null) {
- return null;
- }
- return permDesc.toString();
- }
- groupDesc = canonicalizeGroupDesc(groupDesc);
- if(permDesc == null) {
- return groupDesc;
- }
- // groupDesc and permDesc are non null
- return String.format(mPermFormat, groupDesc, permDesc.toString());
- }
-
- private CharSequence getGroupLabel(String grpName) {
- if (grpName == null) {
- //return default label
- return mDefaultGrpLabel;
- }
- CharSequence cachedLabel = mGroupLabelCache.get(grpName);
- if (cachedLabel != null) {
- return cachedLabel;
- }
- PermissionGroupInfo pgi;
- try {
- pgi = mPm.getPermissionGroupInfo(grpName, 0);
- } catch (NameNotFoundException e) {
- Log.i(TAG, "Invalid group name:" + grpName);
- return null;
- }
- CharSequence label = pgi.loadLabel(mPm).toString();
- mGroupLabelCache.put(grpName, label);
- return label;
- }
-
- /**
- * Utility method that displays permissions from a map containing group name and
- * list of permission descriptions.
- */
- private void displayPermissions(boolean dangerous) {
- Map<String, String> permInfoMap = dangerous ? mDangerousMap : mNormalMap;
- LinearLayout permListView = dangerous ? mDangerousList : mNonDangerousList;
- permListView.removeAllViews();
-
- Set<String> permInfoStrSet = permInfoMap.keySet();
- for (String loopPermGrpInfoStr : permInfoStrSet) {
- CharSequence grpLabel = getGroupLabel(loopPermGrpInfoStr);
- //guaranteed that grpLabel wont be null since permissions without groups
- //will belong to the default group
- if(localLOGV) Log.i(TAG, "Adding view group:" + grpLabel + ", desc:"
- + permInfoMap.get(loopPermGrpInfoStr));
- permListView.addView(getPermissionItemView(grpLabel,
- permInfoMap.get(loopPermGrpInfoStr), dangerous));
- }
- }
-
- private void displayNoPermissions() {
- mNoPermsView.setVisibility(View.VISIBLE);
- }
-
- private View getPermissionItemView(CharSequence grpName, String permList,
- boolean dangerous) {
- View permView = mInflater.inflate(R.layout.app_permission_item, null);
- Drawable icon = dangerous ? mDangerousIcon : mNormalIcon;
- int grpColor = dangerous ? R.color.perms_dangerous_grp_color :
- R.color.perms_normal_grp_color;
- int permColor = dangerous ? R.color.perms_dangerous_perm_color :
- R.color.perms_normal_perm_color;
-
- TextView permGrpView = (TextView) permView.findViewById(R.id.permission_group);
- TextView permDescView = (TextView) permView.findViewById(R.id.permission_list);
- permGrpView.setTextColor(mContext.getResources().getColor(grpColor));
- permDescView.setTextColor(mContext.getResources().getColor(permColor));
-
- ImageView imgView = (ImageView)permView.findViewById(R.id.perm_icon);
- imgView.setImageDrawable(icon);
- if(grpName != null) {
- permGrpView.setText(grpName);
- permDescView.setText(permList);
- } else {
- permGrpView.setText(permList);
- permDescView.setVisibility(View.GONE);
- }
- return permView;
- }
-
- private void showPermissions() {
-
- switch(mCurrentState) {
- case NO_PERMS:
- displayNoPermissions();
- break;
-
- case DANGEROUS_ONLY:
- displayPermissions(true);
- break;
-
- case NORMAL_ONLY:
- displayPermissions(false);
- break;
-
- case BOTH:
- displayPermissions(true);
- if (mExpanded) {
- displayPermissions(false);
- mShowMoreIcon.setImageDrawable(mShowMaxIcon);
- mShowMoreText.setText(R.string.perms_hide);
- mNonDangerousList.setVisibility(View.VISIBLE);
- } else {
- mShowMoreIcon.setImageDrawable(mShowMinIcon);
- mShowMoreText.setText(R.string.perms_show_all);
- mNonDangerousList.setVisibility(View.GONE);
- }
- mShowMore.setVisibility(View.VISIBLE);
- break;
- }
- }
-
- private boolean isDisplayablePermission(PermissionInfo pInfo) {
- if(pInfo.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS ||
- pInfo.protectionLevel == PermissionInfo.PROTECTION_NORMAL) {
- return true;
- }
- return false;
- }
-
- /*
- * Utility method that aggregates all permission descriptions categorized by group
- * Say group1 has perm11, perm12, perm13, the group description will be
- * perm11_Desc, perm12_Desc, perm13_Desc
- */
- private void aggregateGroupDescs(
- Map<String, List<PermissionInfo> > map, Map<String, String> retMap) {
- if(map == null) {
- return;
- }
- if(retMap == null) {
- return;
- }
- Set<String> grpNames = map.keySet();
- Iterator<String> grpNamesIter = grpNames.iterator();
- while(grpNamesIter.hasNext()) {
- String grpDesc = null;
- String grpNameKey = grpNamesIter.next();
- List<PermissionInfo> grpPermsList = map.get(grpNameKey);
- if(grpPermsList == null) {
- continue;
- }
- for(PermissionInfo permInfo: grpPermsList) {
- CharSequence permDesc = permInfo.loadLabel(mPm);
- grpDesc = formatPermissions(grpDesc, permDesc);
- }
- // Insert grpDesc into map
- if(grpDesc != null) {
- if(localLOGV) Log.i(TAG, "Group:"+grpNameKey+" description:"+grpDesc.toString());
- retMap.put(grpNameKey, grpDesc.toString());
- }
- }
- }
-
- private static class PermissionInfoComparator implements Comparator<PermissionInfo> {
- private PackageManager mPm;
- private final Collator sCollator = Collator.getInstance();
- PermissionInfoComparator(PackageManager pm) {
- mPm = pm;
- }
- public final int compare(PermissionInfo a, PermissionInfo b) {
- CharSequence sa = a.loadLabel(mPm);
- CharSequence sb = b.loadLabel(mPm);
- return sCollator.compare(sa, sb);
- }
- }
-
- private void setPermissions(List<PermissionInfo> permList) {
- mGroupLabelCache = new HashMap<String, CharSequence>();
- //add the default label so that uncategorized permissions can go here
- mGroupLabelCache.put(mDefaultGrpName, mDefaultGrpLabel);
-
- // Map containing group names and a list of permissions under that group
- // categorized as dangerous
- mDangerousMap = new HashMap<String, String>();
- // Map containing group names and a list of permissions under that group
- // categorized as normal
- mNormalMap = new HashMap<String, String>();
-
- // Additional structures needed to ensure that permissions are unique under
- // each group
- Map<String, List<PermissionInfo>> dangerousMap =
- new HashMap<String, List<PermissionInfo>>();
- Map<String, List<PermissionInfo> > normalMap =
- new HashMap<String, List<PermissionInfo>>();
- PermissionInfoComparator permComparator = new PermissionInfoComparator(mPm);
-
- if (permList != null) {
- // First pass to group permissions
- for (PermissionInfo pInfo : permList) {
- if(localLOGV) Log.i(TAG, "Processing permission:"+pInfo.name);
- if(!isDisplayablePermission(pInfo)) {
- if(localLOGV) Log.i(TAG, "Permission:"+pInfo.name+" is not displayable");
- continue;
- }
- Map<String, List<PermissionInfo> > permInfoMap =
- (pInfo.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) ?
- dangerousMap : normalMap;
- String grpName = (pInfo.group == null) ? mDefaultGrpName : pInfo.group;
- if(localLOGV) Log.i(TAG, "Permission:"+pInfo.name+" belongs to group:"+grpName);
- List<PermissionInfo> grpPermsList = permInfoMap.get(grpName);
- if(grpPermsList == null) {
- grpPermsList = new ArrayList<PermissionInfo>();
- permInfoMap.put(grpName, grpPermsList);
- grpPermsList.add(pInfo);
- } else {
- int idx = Collections.binarySearch(grpPermsList, pInfo, permComparator);
- if(localLOGV) Log.i(TAG, "idx="+idx+", list.size="+grpPermsList.size());
- if (idx < 0) {
- idx = -idx-1;
- grpPermsList.add(idx, pInfo);
- }
- }
- }
- // Second pass to actually form the descriptions
- // Look at dangerous permissions first
- aggregateGroupDescs(dangerousMap, mDangerousMap);
- aggregateGroupDescs(normalMap, mNormalMap);
- }
-
- mCurrentState = State.NO_PERMS;
- if(mDangerousMap.size() > 0) {
- mCurrentState = (mNormalMap.size() > 0) ? State.BOTH : State.DANGEROUS_ONLY;
- } else if(mNormalMap.size() > 0) {
- mCurrentState = State.NORMAL_ONLY;
- }
- if(localLOGV) Log.i(TAG, "mCurrentState=" + mCurrentState);
- showPermissions();
- }
-
- public void onClick(View v) {
- if(localLOGV) Log.i(TAG, "mExpanded="+mExpanded);
- mExpanded = !mExpanded;
- showPermissions();
- }
-}
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
deleted file mode 100644
index c65a3ce..0000000
--- a/core/java/android/widget/ArrayAdapter.java
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * A ListAdapter that manages a ListView backed by an array of arbitrary
- * objects. By default this class expects that the provided resource id references
- * a single TextView. If you want to use a more complex layout, use the constructors that
- * also takes a field id. That field id should reference a TextView in the larger layout
- * resource.
- *
- * However the TextView is referenced, it will be filled with the toString() of each object in
- * the array. You can add lists or arrays of custom objects. Override the toString() method
- * of your objects to determine what text will be displayed for the item in the list.
- *
- * To use something other than TextViews for the array display, for instance, ImageViews,
- * or to have some of data besides toString() results fill the views,
- * override {@link #getView(int, View, ViewGroup)} to return the type of view you want.
- */
-public class ArrayAdapter<T> extends BaseAdapter implements Filterable {
- /**
- * Contains the list of objects that represent the data of this ArrayAdapter.
- * The content of this list is referred to as "the array" in the documentation.
- */
- private List<T> mObjects;
-
- /**
- * Lock used to modify the content of {@link #mObjects}. Any write operation
- * performed on the array should be synchronized on this lock. This lock is also
- * used by the filter (see {@link #getFilter()} to make a synchronized copy of
- * the original array of data.
- */
- private final Object mLock = new Object();
-
- /**
- * The resource indicating what views to inflate to display the content of this
- * array adapter.
- */
- private int mResource;
-
- /**
- * The resource indicating what views to inflate to display the content of this
- * array adapter in a drop down widget.
- */
- private int mDropDownResource;
-
- /**
- * If the inflated resource is not a TextView, {@link #mFieldId} is used to find
- * a TextView inside the inflated views hierarchy. This field must contain the
- * identifier that matches the one defined in the resource file.
- */
- private int mFieldId = 0;
-
- /**
- * Indicates whether or not {@link #notifyDataSetChanged()} must be called whenever
- * {@link #mObjects} is modified.
- */
- private boolean mNotifyOnChange = true;
-
- private Context mContext;
-
- private ArrayList<T> mOriginalValues;
- private ArrayFilter mFilter;
-
- private LayoutInflater mInflater;
-
- /**
- * Constructor
- *
- * @param context The current context.
- * @param textViewResourceId The resource ID for a layout file containing a TextView to use when
- * instantiating views.
- */
- public ArrayAdapter(Context context, int textViewResourceId) {
- init(context, textViewResourceId, 0, new ArrayList<T>());
- }
-
- /**
- * Constructor
- *
- * @param context The current context.
- * @param resource The resource ID for a layout file containing a layout to use when
- * instantiating views.
- * @param textViewResourceId The id of the TextView within the layout resource to be populated
- */
- public ArrayAdapter(Context context, int resource, int textViewResourceId) {
- init(context, resource, textViewResourceId, new ArrayList<T>());
- }
-
- /**
- * Constructor
- *
- * @param context The current context.
- * @param textViewResourceId The resource ID for a layout file containing a TextView to use when
- * instantiating views.
- * @param objects The objects to represent in the ListView.
- */
- public ArrayAdapter(Context context, int textViewResourceId, T[] objects) {
- init(context, textViewResourceId, 0, Arrays.asList(objects));
- }
-
- /**
- * Constructor
- *
- * @param context The current context.
- * @param resource The resource ID for a layout file containing a layout to use when
- * instantiating views.
- * @param textViewResourceId The id of the TextView within the layout resource to be populated
- * @param objects The objects to represent in the ListView.
- */
- public ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects) {
- init(context, resource, textViewResourceId, Arrays.asList(objects));
- }
-
- /**
- * Constructor
- *
- * @param context The current context.
- * @param textViewResourceId The resource ID for a layout file containing a TextView to use when
- * instantiating views.
- * @param objects The objects to represent in the ListView.
- */
- public ArrayAdapter(Context context, int textViewResourceId, List<T> objects) {
- init(context, textViewResourceId, 0, objects);
- }
-
- /**
- * Constructor
- *
- * @param context The current context.
- * @param resource The resource ID for a layout file containing a layout to use when
- * instantiating views.
- * @param textViewResourceId The id of the TextView within the layout resource to be populated
- * @param objects The objects to represent in the ListView.
- */
- public ArrayAdapter(Context context, int resource, int textViewResourceId, List<T> objects) {
- init(context, resource, textViewResourceId, objects);
- }
-
- /**
- * Adds the specified object at the end of the array.
- *
- * @param object The object to add at the end of the array.
- */
- public void add(T object) {
- if (mOriginalValues != null) {
- synchronized (mLock) {
- mOriginalValues.add(object);
- if (mNotifyOnChange) notifyDataSetChanged();
- }
- } else {
- mObjects.add(object);
- if (mNotifyOnChange) notifyDataSetChanged();
- }
- }
-
- /**
- * Inserts the specified object at the specified index in the array.
- *
- * @param object The object to insert into the array.
- * @param index The index at which the object must be inserted.
- */
- public void insert(T object, int index) {
- if (mOriginalValues != null) {
- synchronized (mLock) {
- mOriginalValues.add(index, object);
- if (mNotifyOnChange) notifyDataSetChanged();
- }
- } else {
- mObjects.add(index, object);
- if (mNotifyOnChange) notifyDataSetChanged();
- }
- }
-
- /**
- * Removes the specified object from the array.
- *
- * @param object The object to remove.
- */
- public void remove(T object) {
- if (mOriginalValues != null) {
- synchronized (mLock) {
- mOriginalValues.remove(object);
- }
- } else {
- mObjects.remove(object);
- }
- if (mNotifyOnChange) notifyDataSetChanged();
- }
-
- /**
- * Remove all elements from the list.
- */
- public void clear() {
- if (mOriginalValues != null) {
- synchronized (mLock) {
- mOriginalValues.clear();
- }
- } else {
- mObjects.clear();
- }
- if (mNotifyOnChange) notifyDataSetChanged();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void notifyDataSetChanged() {
- super.notifyDataSetChanged();
- mNotifyOnChange = true;
- }
-
- /**
- * Control whether methods that change the list ({@link #add},
- * {@link #insert}, {@link #remove}, {@link #clear}) automatically call
- * {@link #notifyDataSetChanged}. If set to false, caller must
- * manually call notifyDataSetChanged() to have the changes
- * reflected in the attached view.
- *
- * The default is true, and calling notifyDataSetChanged()
- * resets the flag to true.
- *
- * @param notifyOnChange if true, modifications to the list will
- * automatically call {@link
- * #notifyDataSetChanged}
- */
- public void setNotifyOnChange(boolean notifyOnChange) {
- mNotifyOnChange = notifyOnChange;
- }
-
- private void init(Context context, int resource, int textViewResourceId, List<T> objects) {
- mContext = context;
- mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mResource = mDropDownResource = resource;
- mObjects = objects;
- mFieldId = textViewResourceId;
- }
-
- /**
- * Returns the context associated with this array adapter. The context is used
- * to create views from the resource passed to the constructor.
- *
- * @return The Context associated with this adapter.
- */
- public Context getContext() {
- return mContext;
- }
-
- /**
- * {@inheritDoc}
- */
- public int getCount() {
- return mObjects.size();
- }
-
- /**
- * {@inheritDoc}
- */
- public T getItem(int position) {
- return mObjects.get(position);
- }
-
- /**
- * Returns the position of the specified item in the array.
- *
- * @param item The item to retrieve the position of.
- *
- * @return The position of the specified item.
- */
- public int getPosition(T item) {
- return mObjects.indexOf(item);
- }
-
- /**
- * {@inheritDoc}
- */
- public long getItemId(int position) {
- return position;
- }
-
- /**
- * {@inheritDoc}
- */
- public View getView(int position, View convertView, ViewGroup parent) {
- return createViewFromResource(position, convertView, parent, mResource);
- }
-
- private View createViewFromResource(int position, View convertView, ViewGroup parent,
- int resource) {
- View view;
- TextView text;
-
- if (convertView == null) {
- view = mInflater.inflate(resource, parent, false);
- } else {
- view = convertView;
- }
-
- try {
- if (mFieldId == 0) {
- // If no custom field is assigned, assume the whole resource is a TextView
- text = (TextView) view;
- } else {
- // Otherwise, find the TextView field within the layout
- text = (TextView) view.findViewById(mFieldId);
- }
- } catch (ClassCastException e) {
- Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
- throw new IllegalStateException(
- "ArrayAdapter requires the resource ID to be a TextView", e);
- }
-
- text.setText(getItem(position).toString());
-
- return view;
- }
-
- /**
- * <p>Sets the layout resource to create the drop down views.</p>
- *
- * @param resource the layout resource defining the drop down views
- * @see #getDropDownView(int, android.view.View, android.view.ViewGroup)
- */
- public void setDropDownViewResource(int resource) {
- this.mDropDownResource = resource;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public View getDropDownView(int position, View convertView, ViewGroup parent) {
- return createViewFromResource(position, convertView, parent, mDropDownResource);
- }
-
- /**
- * Creates a new ArrayAdapter from external resources. The content of the array is
- * obtained through {@link android.content.res.Resources#getTextArray(int)}.
- *
- * @param context The application's environment.
- * @param textArrayResId The identifier of the array to use as the data source.
- * @param textViewResId The identifier of the layout used to create views.
- *
- * @return An ArrayAdapter<CharSequence>.
- */
- public static ArrayAdapter<CharSequence> createFromResource(Context context,
- int textArrayResId, int textViewResId) {
- CharSequence[] strings = context.getResources().getTextArray(textArrayResId);
- return new ArrayAdapter<CharSequence>(context, textViewResId, strings);
- }
-
- /**
- * {@inheritDoc}
- */
- public Filter getFilter() {
- if (mFilter == null) {
- mFilter = new ArrayFilter();
- }
- return mFilter;
- }
-
- /**
- * <p>An array filter constrains the content of the array adapter with
- * a prefix. Each item that does not start with the supplied prefix
- * is removed from the list.</p>
- */
- private class ArrayFilter extends Filter {
- @Override
- protected FilterResults performFiltering(CharSequence prefix) {
- FilterResults results = new FilterResults();
-
- if (mOriginalValues == null) {
- synchronized (mLock) {
- mOriginalValues = new ArrayList<T>(mObjects);
- }
- }
-
- if (prefix == null || prefix.length() == 0) {
- synchronized (mLock) {
- ArrayList<T> list = new ArrayList<T>(mOriginalValues);
- results.values = list;
- results.count = list.size();
- }
- } else {
- String prefixString = prefix.toString().toLowerCase();
-
- final ArrayList<T> values = mOriginalValues;
- final int count = values.size();
-
- final ArrayList<T> newValues = new ArrayList<T>(count);
-
- for (int i = 0; i < count; i++) {
- final T value = values.get(i);
- final String valueText = value.toString().toLowerCase();
-
- // First match against the whole, non-splitted value
- if (valueText.startsWith(prefixString)) {
- newValues.add(value);
- } else {
- final String[] words = valueText.split(" ");
- final int wordCount = words.length;
-
- for (int k = 0; k < wordCount; k++) {
- if (words[k].startsWith(prefixString)) {
- newValues.add(value);
- break;
- }
- }
- }
- }
-
- results.values = newValues;
- results.count = newValues.size();
- }
-
- return results;
- }
-
- @Override
- protected void publishResults(CharSequence constraint, FilterResults results) {
- //noinspection unchecked
- mObjects = (List<T>) results.values;
- if (results.count > 0) {
- notifyDataSetChanged();
- } else {
- notifyDataSetInvalidated();
- }
- }
- }
-}
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
deleted file mode 100644
index 7a51676..0000000
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ /dev/null
@@ -1,1071 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.text.Editable;
-import android.text.Selection;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.EditorInfo;
-
-import com.android.internal.R;
-
-
-/**
- * <p>An editable text view that shows completion suggestions automatically
- * while the user is typing. The list of suggestions is displayed in a drop
- * down menu from which the user can choose an item to replace the content
- * of the edit box with.</p>
- *
- * <p>The drop down can be dismissed at any time by pressing the back key or,
- * if no item is selected in the drop down, by pressing the enter/dpad center
- * key.</p>
- *
- * <p>The list of suggestions is obtained from a data adapter and appears
- * only after a given number of characters defined by
- * {@link #getThreshold() the threshold}.</p>
- *
- * <p>The following code snippet shows how to create a text view which suggests
- * various countries names while the user is typing:</p>
- *
- * <pre class="prettyprint">
- * public class CountriesActivity extends Activity {
- * protected void onCreate(Bundle icicle) {
- * super.onCreate(icicle);
- * setContentView(R.layout.countries);
- *
- * ArrayAdapter&lt;String&gt; adapter = new ArrayAdapter&lt;String&gt;(this,
- * android.R.layout.simple_dropdown_item_1line, COUNTRIES);
- * AutoCompleteTextView textView = (AutoCompleteTextView)
- * findViewById(R.id.countries_list);
- * textView.setAdapter(adapter);
- * }
- *
- * private static final String[] COUNTRIES = new String[] {
- * "Belgium", "France", "Italy", "Germany", "Spain"
- * };
- * }
- * </pre>
- *
- * @attr ref android.R.styleable#AutoCompleteTextView_completionHint
- * @attr ref android.R.styleable#AutoCompleteTextView_completionThreshold
- * @attr ref android.R.styleable#AutoCompleteTextView_completionHintView
- * @attr ref android.R.styleable#AutoCompleteTextView_dropDownSelector
- */
-public class AutoCompleteTextView extends EditText implements Filter.FilterListener {
- static final boolean DEBUG = false;
- static final String TAG = "AutoCompleteTextView";
-
- private static final int HINT_VIEW_ID = 0x17;
-
- private CharSequence mHintText;
- private int mHintResource;
-
- private ListAdapter mAdapter;
- private Filter mFilter;
- private int mThreshold;
-
- private PopupWindow mPopup;
- private DropDownListView mDropDownList;
- private int mDropDownVerticalOffset;
- private int mDropDownHorizontalOffset;
-
- private Drawable mDropDownListHighlight;
-
- private AdapterView.OnItemClickListener mItemClickListener;
- private AdapterView.OnItemSelectedListener mItemSelectedListener;
-
- private final DropDownItemClickListener mDropDownItemClickListener =
- new DropDownItemClickListener();
-
- private int mLastKeyCode = KeyEvent.KEYCODE_UNKNOWN;
- private boolean mOpenBefore;
-
- private Validator mValidator = null;
-
- private boolean mBlockCompletion;
-
- private AutoCompleteTextView.ListSelectorHider mHideSelector;
-
- // Indicates whether this AutoCompleteTextView is attached to a window or not
- // The widget is attached to a window when mAttachCount > 0
- private int mAttachCount;
-
- public AutoCompleteTextView(Context context) {
- this(context, null);
- }
-
- public AutoCompleteTextView(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.autoCompleteTextViewStyle);
- }
-
- public AutoCompleteTextView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- mPopup = new PopupWindow(context, attrs,
- com.android.internal.R.attr.autoCompleteTextViewStyle);
-
- TypedArray a =
- context.obtainStyledAttributes(
- attrs, com.android.internal.R.styleable.AutoCompleteTextView, defStyle, 0);
-
- mThreshold = a.getInt(
- R.styleable.AutoCompleteTextView_completionThreshold, 2);
-
- mHintText = a.getText(R.styleable.AutoCompleteTextView_completionHint);
-
- mDropDownListHighlight = a.getDrawable(
- R.styleable.AutoCompleteTextView_dropDownSelector);
- mDropDownVerticalOffset = (int)
- a.getDimension(R.styleable.AutoCompleteTextView_dropDownVerticalOffset, 0.0f);
- mDropDownHorizontalOffset = (int)
- a.getDimension(R.styleable.AutoCompleteTextView_dropDownHorizontalOffset, 0.0f);
-
- mHintResource = a.getResourceId(R.styleable.AutoCompleteTextView_completionHintView,
- R.layout.simple_dropdown_hint);
-
- // Always turn on the auto complete input type flag, since it
- // makes no sense to use this widget without it.
- int inputType = getInputType();
- if ((inputType&EditorInfo.TYPE_MASK_CLASS)
- == EditorInfo.TYPE_CLASS_TEXT) {
- inputType |= EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE;
- setRawInputType(inputType);
- }
-
- a.recycle();
-
- setFocusable(true);
-
- addTextChangedListener(new MyWatcher());
- }
-
- /**
- * Sets this to be single line; a separate method so
- * MultiAutoCompleteTextView can skip this.
- */
- /* package */ void finishInit() {
- setSingleLine();
- }
-
- /**
- * <p>Sets the optional hint text that is displayed at the bottom of the
- * the matching list. This can be used as a cue to the user on how to
- * best use the list, or to provide extra information.</p>
- *
- * @param hint the text to be displayed to the user
- *
- * @attr ref android.R.styleable#AutoCompleteTextView_completionHint
- */
- public void setCompletionHint(CharSequence hint) {
- mHintText = hint;
- }
-
- /**
- * <p>Returns the number of characters the user must type before the drop
- * down list is shown.</p>
- *
- * @return the minimum number of characters to type to show the drop down
- *
- * @see #setThreshold(int)
- */
- public int getThreshold() {
- return mThreshold;
- }
-
- /**
- * <p>Specifies the minimum number of characters the user has to type in the
- * edit box before the drop down list is shown.</p>
- *
- * <p>When <code>threshold</code> is less than or equals 0, a threshold of
- * 1 is applied.</p>
- *
- * @param threshold the number of characters to type before the drop down
- * is shown
- *
- * @see #getThreshold()
- *
- * @attr ref android.R.styleable#AutoCompleteTextView_completionThreshold
- */
- public void setThreshold(int threshold) {
- if (threshold <= 0) {
- threshold = 1;
- }
-
- mThreshold = threshold;
- }
-
- /**
- * <p>Sets the listener that will be notified when the user clicks an item
- * in the drop down list.</p>
- *
- * @param l the item click listener
- */
- public void setOnItemClickListener(AdapterView.OnItemClickListener l) {
- mItemClickListener = l;
- }
-
- /**
- * <p>Sets the listener that will be notified when the user selects an item
- * in the drop down list.</p>
- *
- * @param l the item selected listener
- */
- public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener l) {
- mItemSelectedListener = l;
- }
-
- /**
- * <p>Returns the listener that is notified whenever the user clicks an item
- * in the drop down list.</p>
- *
- * @return the item click listener
- *
- * @deprecated Use {@link #getOnItemClickListener()} intead
- */
- @Deprecated
- public AdapterView.OnItemClickListener getItemClickListener() {
- return mItemClickListener;
- }
-
- /**
- * <p>Returns the listener that is notified whenever the user selects an
- * item in the drop down list.</p>
- *
- * @return the item selected listener
- *
- * @deprecated Use {@link #getOnItemSelectedListener()} intead
- */
- @Deprecated
- public AdapterView.OnItemSelectedListener getItemSelectedListener() {
- return mItemSelectedListener;
- }
-
- /**
- * <p>Returns the listener that is notified whenever the user clicks an item
- * in the drop down list.</p>
- *
- * @return the item click listener
- */
- public AdapterView.OnItemClickListener getOnItemClickListener() {
- return mItemClickListener;
- }
-
- /**
- * <p>Returns the listener that is notified whenever the user selects an
- * item in the drop down list.</p>
- *
- * @return the item selected listener
- */
- public AdapterView.OnItemSelectedListener getOnItemSelectedListener() {
- return mItemSelectedListener;
- }
-
- /**
- * <p>Returns a filterable list adapter used for auto completion.</p>
- *
- * @return a data adapter used for auto completion
- */
- public ListAdapter getAdapter() {
- return mAdapter;
- }
-
- /**
- * <p>Changes the list of data used for auto completion. The provided list
- * must be a filterable list adapter.</p>
- *
- * <p>The caller is still responsible for managing any resources used by the adapter.
- * Notably, when the AutoCompleteTextView is closed or released, the adapter is not notified.
- * A common case is the use of {@link android.widget.CursorAdapter}, which
- * contains a {@link android.database.Cursor} that must be closed. This can be done
- * automatically (see
- * {@link android.app.Activity#startManagingCursor(android.database.Cursor)
- * startManagingCursor()}),
- * or by manually closing the cursor when the AutoCompleteTextView is dismissed.</p>
- *
- * @param adapter the adapter holding the auto completion data
- *
- * @see #getAdapter()
- * @see android.widget.Filterable
- * @see android.widget.ListAdapter
- */
- public <T extends ListAdapter & Filterable> void setAdapter(T adapter) {
- mAdapter = adapter;
- if (mAdapter != null) {
- //noinspection unchecked
- mFilter = ((Filterable) mAdapter).getFilter();
- } else {
- mFilter = null;
- }
-
- if (mDropDownList != null) {
- mDropDownList.setAdapter(mAdapter);
- }
- }
-
- @Override
- public boolean onKeyPreIme(int keyCode, KeyEvent event) {
- if (isPopupShowing()) {
- // special case for the back key, we do not even try to send it
- // to the drop down list but instead, consume it immediately
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- dismissDropDown();
- return true;
- }
- }
- return super.onKeyPreIme(keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (isPopupShowing() && mDropDownList.getSelectedItemPosition() >= 0) {
- boolean consumed = mDropDownList.onKeyUp(keyCode, event);
- if (consumed) {
- switch (keyCode) {
- // if the list accepts the key events and the key event
- // was a click, the text view gets the selected item
- // from the drop down as its content
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- performCompletion();
- return true;
- }
- }
- }
- return super.onKeyUp(keyCode, event);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- // when the drop down is shown, we drive it directly
- if (isPopupShowing()) {
- // the key events are forwarded to the list in the drop down view
- // note that ListView handles space but we don't want that to happen
- // also if selection is not currently in the drop down, then don't
- // let center or enter presses go there since that would cause it
- // to select one of its items
- if (keyCode != KeyEvent.KEYCODE_SPACE
- && (mDropDownList.getSelectedItemPosition() >= 0
- || (keyCode != KeyEvent.KEYCODE_ENTER
- && keyCode != KeyEvent.KEYCODE_DPAD_CENTER))) {
- int curIndex = mDropDownList.getSelectedItemPosition();
- boolean consumed;
- final boolean below = !mPopup.isAboveAnchor();
- if ((below && keyCode == KeyEvent.KEYCODE_DPAD_UP && curIndex <= 0) ||
- (!below && keyCode == KeyEvent.KEYCODE_DPAD_DOWN && curIndex >=
- mDropDownList.getAdapter().getCount() - 1)) {
- // When the selection is at the top, we block the key
- // event to prevent focus from moving.
- mDropDownList.hideSelector();
- mDropDownList.requestLayout();
- mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
- mPopup.update();
- return true;
- }
- consumed = mDropDownList.onKeyDown(keyCode, event);
- if (DEBUG) Log.v(TAG, "Key down: code=" + keyCode + " list consumed="
- + consumed);
- if (consumed) {
- // If it handled the key event, then the user is
- // navigating in the list, so we should put it in front.
- mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
- // Here's a little trick we need to do to make sure that
- // the list view is actually showing its focus indicator,
- // by ensuring it has focus and getting its window out
- // of touch mode.
- mDropDownList.requestFocusFromTouch();
- if (false) {
- // Update whether the pop-up is in front of or behind
- // the input method, depending on whether the user has
- // moved down in it.
- mPopup.setInputMethodMode(curIndex > 0
- ? PopupWindow.INPUT_METHOD_NOT_NEEDED
- : PopupWindow.INPUT_METHOD_NEEDED);
- }
- mPopup.update();
-
- switch (keyCode) {
- // avoid passing the focus from the text view to the
- // next component
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- case KeyEvent.KEYCODE_DPAD_UP:
- return true;
- }
- } else {
- if (below && keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
- // when the selection is at the bottom, we block the
- // event to avoid going to the next focusable widget
- Adapter adapter = mDropDownList.getAdapter();
- if (adapter != null && curIndex == adapter.getCount() - 1) {
- return true;
- }
- } else if (!below && keyCode == KeyEvent.KEYCODE_DPAD_UP && curIndex == 0) {
- return true;
- }
- }
- }
- } else {
- switch(keyCode) {
- case KeyEvent.KEYCODE_DPAD_DOWN:
- performValidation();
- }
- }
-
- mLastKeyCode = keyCode;
- boolean handled = super.onKeyDown(keyCode, event);
- mLastKeyCode = KeyEvent.KEYCODE_UNKNOWN;
-
- return handled;
- }
-
- /**
- * Returns <code>true</code> if the amount of text in the field meets
- * or exceeds the {@link #getThreshold} requirement. You can override
- * this to impose a different standard for when filtering will be
- * triggered.
- */
- public boolean enoughToFilter() {
- if (DEBUG) Log.v(TAG, "Enough to filter: len=" + getText().length()
- + " threshold=" + mThreshold);
- return getText().length() >= mThreshold;
- }
-
- /**
- * This is used to watch for edits to the text view. Note that we call
- * to methods on the auto complete text view class so that we can access
- * private vars without going through thunks.
- */
- private class MyWatcher implements TextWatcher {
- public void afterTextChanged(Editable s) {
- doAfterTextChanged();
- }
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- doBeforeTextChanged();
- }
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
- }
-
- void doBeforeTextChanged() {
- if (mBlockCompletion) return;
-
- // when text is changed, inserted or deleted, we attempt to show
- // the drop down
- mOpenBefore = isPopupShowing();
- if (DEBUG) Log.v(TAG, "before text changed: open=" + mOpenBefore);
- }
-
- void doAfterTextChanged() {
- if (mBlockCompletion) return;
-
- // if the list was open before the keystroke, but closed afterwards,
- // then something in the keystroke processing (an input filter perhaps)
- // called performCompletion() and we shouldn't do any more processing.
- if (DEBUG) Log.v(TAG, "after text changed: openBefore=" + mOpenBefore
- + " open=" + isPopupShowing());
- if (mOpenBefore && !isPopupShowing()) {
- return;
- }
-
- // the drop down is shown only when a minimum number of characters
- // was typed in the text view
- if (enoughToFilter()) {
- if (mFilter != null) {
- performFiltering(getText(), mLastKeyCode);
- }
- } else {
- // drop down is automatically dismissed when enough characters
- // are deleted from the text view
- dismissDropDown();
- if (mFilter != null) {
- mFilter.filter(null);
- }
- }
- }
-
- /**
- * <p>Indicates whether the popup menu is showing.</p>
- *
- * @return true if the popup menu is showing, false otherwise
- */
- public boolean isPopupShowing() {
- return mPopup.isShowing();
- }
-
- /**
- * <p>Converts the selected item from the drop down list into a sequence
- * of character that can be used in the edit box.</p>
- *
- * @param selectedItem the item selected by the user for completion
- *
- * @return a sequence of characters representing the selected suggestion
- */
- protected CharSequence convertSelectionToString(Object selectedItem) {
- return mFilter.convertResultToString(selectedItem);
- }
-
- /**
- * <p>Clear the list selection. This may only be temporary, as user input will often bring
- * it back.
- */
- public void clearListSelection() {
- if (mDropDownList != null) {
- mDropDownList.hideSelector();
- mDropDownList.requestLayout();
- }
- }
-
- /**
- * Set the position of the dropdown view selection.
- *
- * @param position The position to move the selector to.
- */
- public void setListSelection(int position) {
- if (mPopup.isShowing() && (mDropDownList != null)) {
- mDropDownList.setSelection(position);
- // ListView.setSelection() will call requestLayout()
- }
- }
-
- /**
- * Get the position of the dropdown view selection, if there is one. Returns
- * {@link ListView#INVALID_POSITION ListView.INVALID_POSITION} if there is no dropdown or if
- * there is no selection.
- *
- * @return the position of the current selection, if there is one, or
- * {@link ListView#INVALID_POSITION ListView.INVALID_POSITION} if not.
- *
- * @see ListView#getSelectedItemPosition()
- */
- public int getListSelection() {
- if (mPopup.isShowing() && (mDropDownList != null)) {
- return mDropDownList.getSelectedItemPosition();
- }
- return ListView.INVALID_POSITION;
- }
-
- /**
- * <p>Starts filtering the content of the drop down list. The filtering
- * pattern is the content of the edit box. Subclasses should override this
- * method to filter with a different pattern, for instance a substring of
- * <code>text</code>.</p>
- *
- * @param text the filtering pattern
- * @param keyCode the last character inserted in the edit box; beware that
- * this will be null when text is being added through a soft input method.
- */
- @SuppressWarnings({ "UnusedDeclaration" })
- protected void performFiltering(CharSequence text, int keyCode) {
- mFilter.filter(text, this);
- }
-
- /**
- * <p>Performs the text completion by converting the selected item from
- * the drop down list into a string, replacing the text box's content with
- * this string and finally dismissing the drop down menu.</p>
- */
- public void performCompletion() {
- performCompletion(null, -1, -1);
- }
-
- @Override
- public void onCommitCompletion(CompletionInfo completion) {
- if (isPopupShowing()) {
- mBlockCompletion = true;
- replaceText(completion.getText());
- mBlockCompletion = false;
-
- if (mItemClickListener != null) {
- final DropDownListView list = mDropDownList;
- // Note that we don't have a View here, so we will need to
- // supply null. Hopefully no existing apps crash...
- mItemClickListener.onItemClick(list, null, completion.getPosition(),
- completion.getId());
- }
- }
- }
-
- private void performCompletion(View selectedView, int position, long id) {
- if (isPopupShowing()) {
- Object selectedItem;
- if (position < 0) {
- selectedItem = mDropDownList.getSelectedItem();
- } else {
- selectedItem = mAdapter.getItem(position);
- }
- if (selectedItem == null) {
- Log.w(TAG, "performCompletion: no selected item");
- return;
- }
-
- mBlockCompletion = true;
- replaceText(convertSelectionToString(selectedItem));
- mBlockCompletion = false;
-
- if (mItemClickListener != null) {
- final DropDownListView list = mDropDownList;
-
- if (selectedView == null || position < 0) {
- selectedView = list.getSelectedView();
- position = list.getSelectedItemPosition();
- id = list.getSelectedItemId();
- }
- mItemClickListener.onItemClick(list, selectedView, position, id);
- }
- }
-
- dismissDropDown();
- }
-
- /**
- * Identifies whether the view is currently performing a text completion, so subclasses
- * can decide whether to respond to text changed events.
- */
- public boolean isPerformingCompletion() {
- return mBlockCompletion;
- }
-
- /**
- * <p>Performs the text completion by replacing the current text by the
- * selected item. Subclasses should override this method to avoid replacing
- * the whole content of the edit box.</p>
- *
- * @param text the selected suggestion in the drop down list
- */
- protected void replaceText(CharSequence text) {
- setText(text);
- // make sure we keep the caret at the end of the text view
- Editable spannable = getText();
- Selection.setSelection(spannable, spannable.length());
- }
-
- public void onFilterComplete(int count) {
- if (mAttachCount <= 0) return;
-
- /*
- * This checks enoughToFilter() again because filtering requests
- * are asynchronous, so the result may come back after enough text
- * has since been deleted to make it no longer appropriate
- * to filter.
- */
-
- if (count > 0 && enoughToFilter()) {
- if (hasFocus() && hasWindowFocus()) {
- showDropDown();
- }
- } else {
- dismissDropDown();
- }
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasWindowFocus) {
- super.onWindowFocusChanged(hasWindowFocus);
- performValidation();
- if (!hasWindowFocus) {
- dismissDropDown();
- }
- }
-
- @Override
- protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
- super.onFocusChanged(focused, direction, previouslyFocusedRect);
- performValidation();
- if (!focused) {
- dismissDropDown();
- }
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- mAttachCount++;
- }
-
- @Override
- protected void onDetachedFromWindow() {
- dismissDropDown();
- mAttachCount--;
- super.onDetachedFromWindow();
- }
-
- /**
- * <p>Closes the drop down if present on screen.</p>
- */
- public void dismissDropDown() {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) {
- imm.displayCompletions(this, null);
- }
- mPopup.dismiss();
- mPopup.setContentView(null);
- mDropDownList = null;
- }
-
- @Override
- protected boolean setFrame(int l, int t, int r, int b) {
- boolean result = super.setFrame(l, t, r, b);
-
- if (mPopup.isShowing()) {
- mPopup.update(this, r - l, -1);
- }
-
- return result;
- }
-
- /**
- * <p>Displays the drop down on screen.</p>
- */
- public void showDropDown() {
- int height = buildDropDown();
- if (mPopup.isShowing()) {
- mPopup.update(this, mDropDownHorizontalOffset, mDropDownVerticalOffset,
- getWidth(), height);
- } else {
- mPopup.setWindowLayoutMode(0, ViewGroup.LayoutParams.WRAP_CONTENT);
- mPopup.setWidth(getWidth());
- mPopup.setHeight(height);
- mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
- mPopup.setOutsideTouchable(true);
- mPopup.setTouchInterceptor(new PopupTouchIntercepter());
- mPopup.showAsDropDown(this, mDropDownHorizontalOffset, mDropDownVerticalOffset);
- mDropDownList.setSelection(ListView.INVALID_POSITION);
- mDropDownList.hideSelector();
- mDropDownList.requestFocus();
- post(mHideSelector);
- }
- }
-
- /**
- * <p>Builds the popup window's content and returns the height the popup
- * should have. Returns -1 when the content already exists.</p>
- *
- * @return the content's height or -1 if content already exists
- */
- private int buildDropDown() {
- ViewGroup dropDownView;
- int otherHeights = 0;
-
- if (mAdapter != null) {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) {
- int N = mAdapter.getCount();
- if (N > 20) N = 20;
- CompletionInfo[] completions = new CompletionInfo[N];
- for (int i = 0; i < N; i++) {
- Object item = mAdapter.getItem(i);
- long id = mAdapter.getItemId(i);
- completions[i] = new CompletionInfo(id, i,
- convertSelectionToString(item));
- }
- imm.displayCompletions(this, completions);
- }
- }
-
- if (mDropDownList == null) {
- Context context = getContext();
-
- mHideSelector = new ListSelectorHider();
-
- mDropDownList = new DropDownListView(context);
- mDropDownList.setSelector(mDropDownListHighlight);
- mDropDownList.setAdapter(mAdapter);
- mDropDownList.setVerticalFadingEdgeEnabled(true);
- mDropDownList.setOnItemClickListener(mDropDownItemClickListener);
- mDropDownList.setFocusable(true);
- mDropDownList.setFocusableInTouchMode(true);
-
- if (mItemSelectedListener != null) {
- mDropDownList.setOnItemSelectedListener(mItemSelectedListener);
- }
-
- dropDownView = mDropDownList;
-
- View hintView = getHintView(context);
- if (hintView != null) {
- // if an hint has been specified, we accomodate more space for it and
- // add a text view in the drop down menu, at the bottom of the list
- LinearLayout hintContainer = new LinearLayout(context);
- hintContainer.setOrientation(LinearLayout.VERTICAL);
-
- LinearLayout.LayoutParams hintParams = new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT, 0, 1.0f
- );
- hintContainer.addView(dropDownView, hintParams);
- hintContainer.addView(hintView);
-
- // measure the hint's height to find how much more vertical space
- // we need to add to the drop down's height
- int widthSpec = MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST);
- int heightSpec = MeasureSpec.UNSPECIFIED;
- hintView.measure(widthSpec, heightSpec);
-
- hintParams = (LinearLayout.LayoutParams) hintView.getLayoutParams();
- otherHeights = hintView.getMeasuredHeight() + hintParams.topMargin
- + hintParams.bottomMargin;
-
- dropDownView = hintContainer;
- }
-
- mPopup.setContentView(dropDownView);
- } else {
- dropDownView = (ViewGroup) mPopup.getContentView();
- final View view = dropDownView.findViewById(HINT_VIEW_ID);
- if (view != null) {
- LinearLayout.LayoutParams hintParams =
- (LinearLayout.LayoutParams) view.getLayoutParams();
- otherHeights = view.getMeasuredHeight() + hintParams.topMargin
- + hintParams.bottomMargin;
- }
- }
-
- // Max height available on the screen for a popup anchored to us
- final int maxHeight = mPopup.getMaxAvailableHeight(this, mDropDownVerticalOffset);
- //otherHeights += dropDownView.getPaddingTop() + dropDownView.getPaddingBottom();
-
- return mDropDownList.measureHeightOfChildren(MeasureSpec.UNSPECIFIED,
- 0, ListView.NO_POSITION, maxHeight - otherHeights, 2) + otherHeights;
- }
-
- private View getHintView(Context context) {
- if (mHintText != null && mHintText.length() > 0) {
- final TextView hintView = (TextView) LayoutInflater.from(context).inflate(
- mHintResource, null).findViewById(com.android.internal.R.id.text1);
- hintView.setText(mHintText);
- hintView.setId(HINT_VIEW_ID);
- return hintView;
- } else {
- return null;
- }
- }
-
- /**
- * Sets the validator used to perform text validation.
- *
- * @param validator The validator used to validate the text entered in this widget.
- *
- * @see #getValidator()
- * @see #performValidation()
- */
- public void setValidator(Validator validator) {
- mValidator = validator;
- }
-
- /**
- * Returns the Validator set with {@link #setValidator},
- * or <code>null</code> if it was not set.
- *
- * @see #setValidator(android.widget.AutoCompleteTextView.Validator)
- * @see #performValidation()
- */
- public Validator getValidator() {
- return mValidator;
- }
-
- /**
- * If a validator was set on this view and the current string is not valid,
- * ask the validator to fix it.
- *
- * @see #getValidator()
- * @see #setValidator(android.widget.AutoCompleteTextView.Validator)
- */
- public void performValidation() {
- if (mValidator == null) return;
-
- CharSequence text = getText();
-
- if (!TextUtils.isEmpty(text) && !mValidator.isValid(text)) {
- setText(mValidator.fixText(text));
- }
- }
-
- /**
- * Returns the Filter obtained from {@link Filterable#getFilter},
- * or <code>null</code> if {@link #setAdapter} was not called with
- * a Filterable.
- */
- protected Filter getFilter() {
- return mFilter;
- }
-
- private class ListSelectorHider implements Runnable {
- public void run() {
- if (mDropDownList != null) {
- mDropDownList.hideSelector();
- mDropDownList.requestLayout();
- }
- }
- }
-
- private class PopupTouchIntercepter implements OnTouchListener {
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
- mPopup.update();
- }
- return false;
- }
- }
-
- private class DropDownItemClickListener implements AdapterView.OnItemClickListener {
- public void onItemClick(AdapterView parent, View v, int position, long id) {
- performCompletion(v, position, id);
- }
- }
-
- /**
- * <p>Wrapper class for a ListView. This wrapper hijacks the focus to
- * make sure the list uses the appropriate drawables and states when
- * displayed on screen within a drop down. The focus is never actually
- * passed to the drop down; the list only looks focused.</p>
- */
- private static class DropDownListView extends ListView {
- /**
- * <p>Creates a new list view wrapper.</p>
- *
- * @param context this view's context
- */
- public DropDownListView(Context context) {
- super(context, null, com.android.internal.R.attr.dropDownListViewStyle);
- }
-
- /**
- * <p>Avoids jarring scrolling effect by ensuring that list elements
- * made of a text view fit on a single line.</p>
- *
- * @param position the item index in the list to get a view for
- * @return the view for the specified item
- */
- @Override
- protected View obtainView(int position) {
- View view = super.obtainView(position);
-
- if (view instanceof TextView) {
- ((TextView) view).setHorizontallyScrolling(true);
- }
-
- return view;
- }
-
- /**
- * <p>Returns the top padding of the currently selected view.</p>
- *
- * @return the height of the top padding for the selection
- */
- public int getSelectionPaddingTop() {
- return mSelectionTopPadding;
- }
-
- /**
- * <p>Returns the bottom padding of the currently selected view.</p>
- *
- * @return the height of the bottom padding for the selection
- */
- public int getSelectionPaddingBottom() {
- return mSelectionBottomPadding;
- }
-
- /**
- * <p>Returns the focus state in the drop down.</p>
- *
- * @return true always
- */
- @Override
- public boolean hasWindowFocus() {
- return true;
- }
-
- /**
- * <p>Returns the focus state in the drop down.</p>
- *
- * @return true always
- */
- @Override
- public boolean isFocused() {
- return true;
- }
-
- /**
- * <p>Returns the focus state in the drop down.</p>
- *
- * @return true always
- */
- @Override
- public boolean hasFocus() {
- return true;
- }
-
- protected int[] onCreateDrawableState(int extraSpace) {
- int[] res = super.onCreateDrawableState(extraSpace);
- if (false) {
- StringBuilder sb = new StringBuilder("Created drawable state: [");
- for (int i=0; i<res.length; i++) {
- if (i > 0) sb.append(", ");
- sb.append("0x");
- sb.append(Integer.toHexString(res[i]));
- }
- sb.append("]");
- Log.i(TAG, sb.toString());
- }
- return res;
- }
- }
-
- /**
- * This interface is used to make sure that the text entered in this TextView complies to
- * a certain format. Since there is no foolproof way to prevent the user from leaving
- * this View with an incorrect value in it, all we can do is try to fix it ourselves
- * when this happens.
- */
- public interface Validator {
- /**
- * Validates the specified text.
- *
- * @return true If the text currently in the text editor is valid.
- *
- * @see #fixText(CharSequence)
- */
- boolean isValid(CharSequence text);
-
- /**
- * Corrects the specified text to make it valid.
- *
- * @param invalidText A string that doesn't pass validation: isValid(invalidText)
- * returns false
- *
- * @return A string based on invalidText such as invoking isValid() on it returns true.
- *
- * @see #isValid(CharSequence)
- */
- CharSequence fixText(CharSequence invalidText);
- }
-}
diff --git a/core/java/android/widget/BaseAdapter.java b/core/java/android/widget/BaseAdapter.java
deleted file mode 100644
index 1921d73..0000000
--- a/core/java/android/widget/BaseAdapter.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.database.DataSetObservable;
-import android.database.DataSetObserver;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * Common base class of common implementation for an {@link Adapter} that can be
- * used in both {@link ListView} (by implementing the specialized
- * {@link ListAdapter} interface} and {@link Spinner} (by implementing the
- * specialized {@link SpinnerAdapter} interface.
- */
-public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
- private final DataSetObservable mDataSetObservable = new DataSetObservable();
-
- public boolean hasStableIds() {
- return false;
- }
-
- public void registerDataSetObserver(DataSetObserver observer) {
- mDataSetObservable.registerObserver(observer);
- }
-
- public void unregisterDataSetObserver(DataSetObserver observer) {
- mDataSetObservable.unregisterObserver(observer);
- }
-
- public void notifyDataSetChanged() {
- mDataSetObservable.notifyChanged();
- }
-
- public void notifyDataSetInvalidated() {
- mDataSetObservable.notifyInvalidated();
- }
-
- public boolean areAllItemsEnabled() {
- return true;
- }
-
- public boolean isEnabled(int position) {
- return true;
- }
-
- public View getDropDownView(int position, View convertView, ViewGroup parent) {
- return getView(position, convertView, parent);
- }
-
- public int getItemViewType(int position) {
- return 0;
- }
-
- public int getViewTypeCount() {
- return 1;
- }
-
- public boolean isEmpty() {
- return getCount() == 0;
- }
-}
diff --git a/core/java/android/widget/BaseExpandableListAdapter.java b/core/java/android/widget/BaseExpandableListAdapter.java
deleted file mode 100644
index 1bba7f0..0000000
--- a/core/java/android/widget/BaseExpandableListAdapter.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.database.DataSetObservable;
-import android.database.DataSetObserver;
-import android.view.KeyEvent;
-
-/**
- * Base class for a {@link ExpandableListAdapter} used to provide data and Views
- * from some data to an expandable list view.
- * <p>
- * Adapters inheriting this class should verify that the base implementations of
- * {@link #getCombinedChildId(long, long)} and {@link #getCombinedGroupId(long)}
- * are correct in generating unique IDs from the group/children IDs.
- * <p>
- * @see SimpleExpandableListAdapter
- * @see SimpleCursorTreeAdapter
- */
-public abstract class BaseExpandableListAdapter implements ExpandableListAdapter {
- private final DataSetObservable mDataSetObservable = new DataSetObservable();
-
- public void registerDataSetObserver(DataSetObserver observer) {
- mDataSetObservable.registerObserver(observer);
- }
-
- public void unregisterDataSetObserver(DataSetObserver observer) {
- mDataSetObservable.unregisterObserver(observer);
- }
-
- /**
- * {@see DataSetObservable#notifyInvalidated()}
- */
- public void notifyDataSetInvalidated() {
- mDataSetObservable.notifyInvalidated();
- }
-
- /**
- * {@see DataSetObservable#notifyChanged()}
- */
- public void notifyDataSetChanged() {
- mDataSetObservable.notifyChanged();
- }
-
- public boolean areAllItemsEnabled() {
- return true;
- }
-
- public void onGroupCollapsed(int groupPosition) {
- }
-
- public void onGroupExpanded(int groupPosition) {
- }
-
- /**
- * Override this method if you foresee a clash in IDs based on this scheme:
- * <p>
- * Base implementation returns a long:
- * <li> bit 0: Whether this ID points to a child (unset) or group (set), so for this method
- * this bit will be 1.
- * <li> bit 1-31: Lower 31 bits of the groupId
- * <li> bit 32-63: Lower 32 bits of the childId.
- * <p>
- * {@inheritDoc}
- */
- public long getCombinedChildId(long groupId, long childId) {
- return 0x8000000000000000L | ((groupId & 0x7FFFFFFF) << 32) | (childId & 0xFFFFFFFF);
- }
-
- /**
- * Override this method if you foresee a clash in IDs based on this scheme:
- * <p>
- * Base implementation returns a long:
- * <li> bit 0: Whether this ID points to a child (unset) or group (set), so for this method
- * this bit will be 0.
- * <li> bit 1-31: Lower 31 bits of the groupId
- * <li> bit 32-63: Lower 32 bits of the childId.
- * <p>
- * {@inheritDoc}
- */
- public long getCombinedGroupId(long groupId) {
- return (groupId & 0x7FFFFFFF) << 32;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isEmpty() {
- return getGroupCount() == 0;
- }
-
-}
diff --git a/core/java/android/widget/Button.java b/core/java/android/widget/Button.java
deleted file mode 100644
index 5e692d4..0000000
--- a/core/java/android/widget/Button.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.KeyEvent;
-import android.widget.RemoteViews.RemoteView;
-
-
-/**
- * <p>
- * <code>Button</code> represents a push-button widget. Push-buttons can be
- * pressed, or clicked, by the user to perform an action. A typical use of a
- * push-button in an activity would be the following:
- * </p>
- *
- * <pre class="prettyprint">
- * public class MyActivity extends Activity {
- * protected void onCreate(Bundle icicle) {
- * super.onCreate(icicle);
- *
- * setContentView(R.layout.content_layout_id);
- *
- * final Button button = (Button) findViewById(R.id.button_id);
- * button.setOnClickListener(new View.OnClickListener() {
- * public void onClick(View v) {
- * // Perform action on click
- * }
- * });
- * }
- * }
- * </pre>
- *
- * <p><strong>XML attributes</strong></p>
- * <p>
- * See {@link android.R.styleable#Button Button Attributes},
- * {@link android.R.styleable#TextView TextView Attributes},
- * {@link android.R.styleable#View View Attributes}
- * </p>
- */
-@RemoteView
-public class Button extends TextView {
- public Button(Context context) {
- this(context, null);
- }
-
- public Button(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.buttonStyle);
- }
-
- public Button(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-}
diff --git a/core/java/android/widget/CheckBox.java b/core/java/android/widget/CheckBox.java
deleted file mode 100644
index ff63a24..0000000
--- a/core/java/android/widget/CheckBox.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-
-/**
- * <p>
- * A checkbox is a specific type of two-states button that can be either
- * checked or unchecked. A example usage of a checkbox inside your activity
- * would be the following:
- * </p>
- *
- * <pre class="prettyprint">
- * public class MyActivity extends Activity {
- * protected void onCreate(Bundle icicle) {
- * super.onCreate(icicle);
- *
- * setContentView(R.layout.content_layout_id);
- *
- * final CheckBox checkBox = (CheckBox) findViewById(R.id.checkbox_id);
- * if (checkBox.isChecked()) {
- * checkBox.setChecked(false);
- * }
- * }
- * }
- * </pre>
- *
- * <p><strong>XML attributes</strong></p>
- * <p>
- * See {@link android.R.styleable#CompoundButton CompoundButton Attributes},
- * {@link android.R.styleable#Button Button Attributes},
- * {@link android.R.styleable#TextView TextView Attributes},
- * {@link android.R.styleable#View View Attributes}
- * </p>
- */
-public class CheckBox extends CompoundButton {
- public CheckBox(Context context) {
- this(context, null);
- }
-
- public CheckBox(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.checkboxStyle);
- }
-
- public CheckBox(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-}
diff --git a/core/java/android/widget/Checkable.java b/core/java/android/widget/Checkable.java
deleted file mode 100644
index eb97b4a..0000000
--- a/core/java/android/widget/Checkable.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-/**
- * Defines an extension for views that make them checkable.
- *
- */
-public interface Checkable {
-
- /**
- * Change the checked state of the view
- *
- * @param checked The new checked state
- */
- void setChecked(boolean checked);
-
- /**
- * @return The current checked state of the view
- */
- boolean isChecked();
-
- /**
- * Change the checked state of the view to the inverse of its current state
- *
- */
- void toggle();
-}
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
deleted file mode 100644
index f5a0b1c..0000000
--- a/core/java/android/widget/CheckedTextView.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.Gravity;
-
-import com.android.internal.R;
-
-
-/**
- * An extension to TextView that supports the {@link android.widget.Checkable} interface.
- * This is useful when used in a {@link android.widget.ListView ListView} where the it's
- * {@link android.widget.ListView#setChoiceMode(int) setChoiceMode} has been set to
- * something other than {@link android.widget.ListView#CHOICE_MODE_NONE CHOICE_MODE_NONE}.
- *
- */
-public abstract class CheckedTextView extends TextView implements Checkable {
- private boolean mChecked;
- private int mCheckMarkResource;
- private Drawable mCheckMarkDrawable;
- private int mBasePaddingRight;
- private int mCheckMarkWidth;
-
- private static final int[] CHECKED_STATE_SET = {
- R.attr.state_checked
- };
-
- public CheckedTextView(Context context) {
- this(context, null);
- }
-
- public CheckedTextView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public CheckedTextView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- R.styleable.CheckedTextView, defStyle, 0);
-
- Drawable d = a.getDrawable(R.styleable.CheckedTextView_checkMark);
- if (d != null) {
- setCheckMarkDrawable(d);
- }
-
- boolean checked = a.getBoolean(R.styleable.CheckedTextView_checked, false);
- setChecked(checked);
-
- a.recycle();
- }
-
- public void toggle() {
- setChecked(!mChecked);
- }
-
- public boolean isChecked() {
- return mChecked;
- }
-
- /**
- * <p>Changes the checked state of this text view.</p>
- *
- * @param checked true to check the text, false to uncheck it
- */
- public void setChecked(boolean checked) {
- if (mChecked != checked) {
- mChecked = checked;
- refreshDrawableState();
- }
- }
-
-
- /**
- * Set the checkmark to a given Drawable, identified by its resourece id. This will be drawn
- * when {@link #isChecked()} is true.
- *
- * @param resid The Drawable to use for the checkmark.
- */
- public void setCheckMarkDrawable(int resid) {
- if (resid != 0 && resid == mCheckMarkResource) {
- return;
- }
-
- mCheckMarkResource = resid;
-
- Drawable d = null;
- if (mCheckMarkResource != 0) {
- d = getResources().getDrawable(mCheckMarkResource);
- }
- setCheckMarkDrawable(d);
- }
-
- /**
- * Set the checkmark to a given Drawable. This will be drawn when {@link #isChecked()} is true.
- *
- * @param d The Drawable to use for the checkmark.
- */
- public void setCheckMarkDrawable(Drawable d) {
- if (d != null) {
- if (mCheckMarkDrawable != null) {
- mCheckMarkDrawable.setCallback(null);
- unscheduleDrawable(mCheckMarkDrawable);
- }
- d.setCallback(this);
- d.setVisible(getVisibility() == VISIBLE, false);
- d.setState(CHECKED_STATE_SET);
- setMinHeight(d.getIntrinsicHeight());
-
- mCheckMarkWidth = d.getIntrinsicWidth();
- mPaddingRight = mCheckMarkWidth + mBasePaddingRight;
- d.setState(getDrawableState());
- mCheckMarkDrawable = d;
- } else {
- mPaddingRight = mBasePaddingRight;
- }
- requestLayout();
- }
-
- @Override
- public void setPadding(int left, int top, int right, int bottom) {
- super.setPadding(left, top, right, bottom);
- mBasePaddingRight = mPaddingRight;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- final Drawable checkMarkDrawable = mCheckMarkDrawable;
- if (checkMarkDrawable != null) {
- final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
- final int height = checkMarkDrawable.getIntrinsicHeight();
-
- int y = 0;
-
- switch (verticalGravity) {
- case Gravity.BOTTOM:
- y = getHeight() - height;
- break;
- case Gravity.CENTER_VERTICAL:
- y = (getHeight() - height) / 2;
- break;
- }
-
- int right = getWidth();
- checkMarkDrawable.setBounds(
- right - mCheckMarkWidth - mBasePaddingRight,
- y,
- right - mBasePaddingRight,
- y + height);
- checkMarkDrawable.draw(canvas);
- }
- }
-
- @Override
- protected int[] onCreateDrawableState(int extraSpace) {
- final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
- if (isChecked()) {
- mergeDrawableStates(drawableState, CHECKED_STATE_SET);
- }
- return drawableState;
- }
-
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
-
- if (mCheckMarkDrawable != null) {
- int[] myDrawableState = getDrawableState();
-
- // Set the state of the Drawable
- mCheckMarkDrawable.setState(myDrawableState);
-
- invalidate();
- }
- }
-
-}
diff --git a/core/java/android/widget/Chronometer.java b/core/java/android/widget/Chronometer.java
deleted file mode 100644
index 369221e..0000000
--- a/core/java/android/widget/Chronometer.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemClock;
-import android.text.format.DateUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.widget.RemoteViews.RemoteView;
-
-import java.util.Formatter;
-import java.util.IllegalFormatException;
-import java.util.Locale;
-
-/**
- * Class that implements a simple timer.
- * <p>
- * You can give it a start time in the {@link SystemClock#elapsedRealtime} timebase,
- * and it counts up from that, or if you don't give it a base time, it will use the
- * time at which you call {@link #start}. By default it will display the current
- * timer value in the form "MM:SS" or "H:MM:SS", or you can use {@link #setFormat}
- * to format the timer value into an arbitrary string.
- *
- * @attr ref android.R.styleable#Chronometer_format
- */
-@RemoteView
-public class Chronometer extends TextView {
- private static final String TAG = "Chronometer";
-
- /**
- * A callback that notifies when the chronometer has incremented on its own.
- */
- public interface OnChronometerTickListener {
-
- /**
- * Notification that the chronometer has changed.
- */
- void onChronometerTick(Chronometer chronometer);
-
- }
-
- private long mBase;
- private boolean mVisible;
- private boolean mStarted;
- private boolean mRunning;
- private boolean mLogged;
- private String mFormat;
- private Formatter mFormatter;
- private Locale mFormatterLocale;
- private Object[] mFormatterArgs = new Object[1];
- private StringBuilder mFormatBuilder;
- private OnChronometerTickListener mOnChronometerTickListener;
-
- /**
- * Initialize this Chronometer object.
- * Sets the base to the current time.
- */
- public Chronometer(Context context) {
- this(context, null, 0);
- }
-
- /**
- * Initialize with standard view layout information.
- * Sets the base to the current time.
- */
- public Chronometer(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- /**
- * Initialize with standard view layout information and style.
- * Sets the base to the current time.
- */
- public Chronometer(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(
- attrs,
- com.android.internal.R.styleable.Chronometer, defStyle, 0);
- setFormat(a.getString(com.android.internal.R.styleable.Chronometer_format));
- a.recycle();
-
- init();
- }
-
- private void init() {
- mBase = SystemClock.elapsedRealtime();
- updateText(mBase);
- }
-
- /**
- * Set the time that the count-up timer is in reference to.
- *
- * @param base Use the {@link SystemClock#elapsedRealtime} time base.
- */
- @android.view.RemotableViewMethod
- public void setBase(long base) {
- mBase = base;
- updateText(SystemClock.elapsedRealtime());
- }
-
- /**
- * Return the base time as set through {@link #setBase}.
- */
- public long getBase() {
- return mBase;
- }
-
- /**
- * Sets the format string used for display. The Chronometer will display
- * this string, with the first "%s" replaced by the current timer value in
- * "MM:SS" or "H:MM:SS" form.
- *
- * If the format string is null, or if you never call setFormat(), the
- * Chronometer will simply display the timer value in "MM:SS" or "H:MM:SS"
- * form.
- *
- * @param format the format string.
- */
- @android.view.RemotableViewMethod
- public void setFormat(String format) {
- mFormat = format;
- if (format != null && mFormatBuilder == null) {
- mFormatBuilder = new StringBuilder(format.length() * 2);
- }
- }
-
- /**
- * Returns the current format string as set through {@link #setFormat}.
- */
- public String getFormat() {
- return mFormat;
- }
-
- /**
- * Sets the listener to be called when the chronometer changes.
- *
- * @param listener The listener.
- */
- public void setOnChronometerTickListener(OnChronometerTickListener listener) {
- mOnChronometerTickListener = listener;
- }
-
- /**
- * @return The listener (may be null) that is listening for chronometer change
- * events.
- */
- public OnChronometerTickListener getOnChronometerTickListener() {
- return mOnChronometerTickListener;
- }
-
- /**
- * Start counting up. This does not affect the base as set from {@link #setBase}, just
- * the view display.
- *
- * Chronometer works by regularly scheduling messages to the handler, even when the
- * Widget is not visible. To make sure resource leaks do not occur, the user should
- * make sure that each start() call has a reciprocal call to {@link #stop}.
- */
- public void start() {
- mStarted = true;
- updateRunning();
- }
-
- /**
- * Stop counting up. This does not affect the base as set from {@link #setBase}, just
- * the view display.
- *
- * This stops the messages to the handler, effectively releasing resources that would
- * be held as the chronometer is running, via {@link #start}.
- */
- public void stop() {
- mStarted = false;
- updateRunning();
- }
-
- /**
- * The same as calling {@link #start} or {@link #stop}.
- */
- @android.view.RemotableViewMethod
- public void setStarted(boolean started) {
- mStarted = started;
- updateRunning();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- mVisible = false;
- updateRunning();
- }
-
- @Override
- protected void onWindowVisibilityChanged(int visibility) {
- super.onWindowVisibilityChanged(visibility);
- mVisible = visibility == VISIBLE;
- updateRunning();
- }
-
- private void updateText(long now) {
- long seconds = now - mBase;
- seconds /= 1000;
- String text = DateUtils.formatElapsedTime(seconds);
-
- if (mFormat != null) {
- Locale loc = Locale.getDefault();
- if (mFormatter == null || !loc.equals(mFormatterLocale)) {
- mFormatterLocale = loc;
- mFormatter = new Formatter(mFormatBuilder, loc);
- }
- mFormatBuilder.setLength(0);
- mFormatterArgs[0] = text;
- try {
- mFormatter.format(mFormat, mFormatterArgs);
- text = mFormatBuilder.toString();
- } catch (IllegalFormatException ex) {
- if (!mLogged) {
- Log.w(TAG, "Illegal format string: " + mFormat);
- mLogged = true;
- }
- }
- }
- setText(text);
- }
-
- private void updateRunning() {
- boolean running = mVisible && mStarted;
- if (running != mRunning) {
- if (running) {
- updateText(SystemClock.elapsedRealtime());
- mHandler.sendMessageDelayed(Message.obtain(), 1000);
- }
- mRunning = running;
- }
- }
-
- private Handler mHandler = new Handler() {
- public void handleMessage(Message m) {
- if (mStarted) {
- updateText(SystemClock.elapsedRealtime());
- dispatchChronometerTick();
- sendMessageDelayed(Message.obtain(), 1000);
- }
- }
- };
-
- void dispatchChronometerTick() {
- if (mOnChronometerTickListener != null) {
- mOnChronometerTickListener.onChronometerTick(this);
- }
- }
-}
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
deleted file mode 100644
index d4482dc..0000000
--- a/core/java/android/widget/CompoundButton.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import com.android.internal.R;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.view.Gravity;
-
-
-/**
- * <p>
- * A button with two states, checked and unchecked. When the button is pressed
- * or clicked, the state changes automatically.
- * </p>
- *
- * <p><strong>XML attributes</strong></p>
- * <p>
- * See {@link android.R.styleable#CompoundButton
- * CompoundButton Attributes}, {@link android.R.styleable#Button Button
- * Attributes}, {@link android.R.styleable#TextView TextView Attributes}, {@link
- * android.R.styleable#View View Attributes}
- * </p>
- */
-public abstract class CompoundButton extends Button implements Checkable {
- private boolean mChecked;
- private int mButtonResource;
- private boolean mBroadcasting;
- private Drawable mButtonDrawable;
- private OnCheckedChangeListener mOnCheckedChangeListener;
- private OnCheckedChangeListener mOnCheckedChangeWidgetListener;
-
- private static final int[] CHECKED_STATE_SET = {
- R.attr.state_checked
- };
-
- public CompoundButton(Context context) {
- this(context, null);
- }
-
- public CompoundButton(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public CompoundButton(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a =
- context.obtainStyledAttributes(
- attrs, com.android.internal.R.styleable.CompoundButton, defStyle, 0);
-
- Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button);
- if (d != null) {
- setButtonDrawable(d);
- }
-
- boolean checked = a
- .getBoolean(com.android.internal.R.styleable.CompoundButton_checked, false);
- setChecked(checked);
-
- a.recycle();
- }
-
- public void toggle() {
- setChecked(!mChecked);
- }
-
- @Override
- public boolean performClick() {
- /*
- * XXX: These are tiny, need some surrounding 'expanded touch area',
- * which will need to be implemented in Button if we only override
- * performClick()
- */
-
- /* When clicked, toggle the state */
- toggle();
- return super.performClick();
- }
-
- public boolean isChecked() {
- return mChecked;
- }
-
- /**
- * <p>Changes the checked state of this button.</p>
- *
- * @param checked true to check the button, false to uncheck it
- */
- public void setChecked(boolean checked) {
- if (mChecked != checked) {
- mChecked = checked;
- refreshDrawableState();
-
- // Avoid infinite recursions if setChecked() is called from a listener
- if (mBroadcasting) {
- return;
- }
-
- mBroadcasting = true;
- if (mOnCheckedChangeListener != null) {
- mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
- }
- if (mOnCheckedChangeWidgetListener != null) {
- mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
- }
- mBroadcasting = false;
- }
- }
-
- /**
- * Register a callback to be invoked when the checked state of this button
- * changes.
- *
- * @param listener the callback to call on checked state change
- */
- public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
- mOnCheckedChangeListener = listener;
- }
-
- /**
- * Register a callback to be invoked when the checked state of this button
- * changes. This callback is used for internal purpose only.
- *
- * @param listener the callback to call on checked state change
- * @hide
- */
- void setOnCheckedChangeWidgetListener(OnCheckedChangeListener listener) {
- mOnCheckedChangeWidgetListener = listener;
- }
-
- /**
- * Interface definition for a callback to be invoked when the checked state
- * of a compound button changed.
- */
- public static interface OnCheckedChangeListener {
- /**
- * Called when the checked state of a compound button has changed.
- *
- * @param buttonView The compound button view whose state has changed.
- * @param isChecked The new checked state of buttonView.
- */
- void onCheckedChanged(CompoundButton buttonView, boolean isChecked);
- }
-
- /**
- * Set the background to a given Drawable, identified by its resource id.
- *
- * @param resid the resource id of the drawable to use as the background
- */
- public void setButtonDrawable(int resid) {
- if (resid != 0 && resid == mButtonResource) {
- return;
- }
-
- mButtonResource = resid;
-
- Drawable d = null;
- if (mButtonResource != 0) {
- d = getResources().getDrawable(mButtonResource);
- }
- setButtonDrawable(d);
- }
-
- /**
- * Set the background to a given Drawable
- *
- * @param d The Drawable to use as the background
- */
- public void setButtonDrawable(Drawable d) {
- if (d != null) {
- if (mButtonDrawable != null) {
- mButtonDrawable.setCallback(null);
- unscheduleDrawable(mButtonDrawable);
- }
- d.setCallback(this);
- d.setState(getDrawableState());
- d.setVisible(getVisibility() == VISIBLE, false);
- mButtonDrawable = d;
- mButtonDrawable.setState(null);
- setMinHeight(mButtonDrawable.getIntrinsicHeight());
- }
-
- refreshDrawableState();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- final Drawable buttonDrawable = mButtonDrawable;
- if (buttonDrawable != null) {
- final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
- final int height = buttonDrawable.getIntrinsicHeight();
-
- int y = 0;
-
- switch (verticalGravity) {
- case Gravity.BOTTOM:
- y = getHeight() - height;
- break;
- case Gravity.CENTER_VERTICAL:
- y = (getHeight() - height) / 2;
- break;
- }
-
- buttonDrawable.setBounds(0, y, buttonDrawable.getIntrinsicWidth(), y + height);
- buttonDrawable.draw(canvas);
- }
- }
-
- @Override
- protected int[] onCreateDrawableState(int extraSpace) {
- final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
- if (isChecked()) {
- mergeDrawableStates(drawableState, CHECKED_STATE_SET);
- }
- return drawableState;
- }
-
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
-
- if (mButtonDrawable != null) {
- int[] myDrawableState = getDrawableState();
-
- // Set the state of the Drawable
- mButtonDrawable.setState(myDrawableState);
-
- invalidate();
- }
- }
-
- @Override
- protected boolean verifyDrawable(Drawable who) {
- return super.verifyDrawable(who) || who == mButtonDrawable;
- }
-
- static class SavedState extends BaseSavedState {
- boolean checked;
-
- /**
- * Constructor called from {@link CompoundButton#onSaveInstanceState()}
- */
- SavedState(Parcelable superState) {
- super(superState);
- }
-
- /**
- * Constructor called from {@link #CREATOR}
- */
- private SavedState(Parcel in) {
- super(in);
- checked = (Boolean)in.readValue(null);
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- super.writeToParcel(out, flags);
- out.writeValue(checked);
- }
-
- @Override
- public String toString() {
- return "CompoundButton.SavedState{"
- + Integer.toHexString(System.identityHashCode(this))
- + " checked=" + checked + "}";
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR
- = new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
- @Override
- public Parcelable onSaveInstanceState() {
- // Force our ancestor class to save its state
- setFreezesText(true);
- Parcelable superState = super.onSaveInstanceState();
-
- SavedState ss = new SavedState(superState);
-
- ss.checked = isChecked();
- return ss;
- }
-
- @Override
- public void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
-
- super.onRestoreInstanceState(ss.getSuperState());
- setChecked(ss.checked);
- requestLayout();
- }
-}
diff --git a/core/java/android/widget/CursorAdapter.java b/core/java/android/widget/CursorAdapter.java
deleted file mode 100644
index 3d758e7..0000000
--- a/core/java/android/widget/CursorAdapter.java
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.database.DataSetObserver;
-import android.os.Handler;
-import android.util.Config;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * Adapter that exposes data from a {@link android.database.Cursor Cursor} to a
- * {@link android.widget.ListView ListView} widget. The Cursor must include
- * a column named "_id" or this class will not work.
- */
-public abstract class CursorAdapter extends BaseAdapter implements Filterable,
- CursorFilter.CursorFilterClient {
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected boolean mDataValid;
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected boolean mAutoRequery;
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected Cursor mCursor;
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected Context mContext;
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected int mRowIDColumn;
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected ChangeObserver mChangeObserver;
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected DataSetObserver mDataSetObserver = new MyDataSetObserver();
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected CursorFilter mCursorFilter;
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected FilterQueryProvider mFilterQueryProvider;
-
- /**
- * Constructor. The adapter will call requery() on the cursor whenever
- * it changes so that the most recent data is always displayed.
- *
- * @param c The cursor from which to get the data.
- * @param context The context
- */
- public CursorAdapter(Context context, Cursor c) {
- init(context, c, true);
- }
-
- /**
- * Constructor
- * @param c The cursor from which to get the data.
- * @param context The context
- * @param autoRequery If true the adapter will call requery() on the
- * cursor whenever it changes so the most recent
- * data is always displayed.
- */
- public CursorAdapter(Context context, Cursor c, boolean autoRequery) {
- init(context, c, autoRequery);
- }
-
- protected void init(Context context, Cursor c, boolean autoRequery) {
- boolean cursorPresent = c != null;
- mAutoRequery = autoRequery;
- mCursor = c;
- mDataValid = cursorPresent;
- mContext = context;
- mRowIDColumn = cursorPresent ? c.getColumnIndexOrThrow("_id") : -1;
- mChangeObserver = new ChangeObserver();
- if (cursorPresent) {
- c.registerContentObserver(mChangeObserver);
- c.registerDataSetObserver(mDataSetObserver);
- }
- }
-
- /**
- * Returns the cursor.
- * @return the cursor.
- */
- public Cursor getCursor() {
- return mCursor;
- }
-
- /**
- * @see android.widget.ListAdapter#getCount()
- */
- public final int getCount() {
- if (mDataValid && mCursor != null) {
- return mCursor.getCount();
- } else {
- return 0;
- }
- }
-
- /**
- * @see android.widget.ListAdapter#getItem(int)
- */
- public final Object getItem(int position) {
- if (mDataValid && mCursor != null) {
- mCursor.moveToPosition(position);
- return mCursor;
- } else {
- return null;
- }
- }
-
- /**
- * @see android.widget.ListAdapter#getItemId(int)
- */
- public final long getItemId(int position) {
- if (mDataValid && mCursor != null) {
- if (mCursor.moveToPosition(position)) {
- return mCursor.getLong(mRowIDColumn);
- } else {
- return 0;
- }
- } else {
- return 0;
- }
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- /**
- * @see android.widget.ListAdapter#getView(int, View, ViewGroup)
- */
- public View getView(int position, View convertView, ViewGroup parent) {
- if (!mDataValid) {
- throw new IllegalStateException("this should only be called when the cursor is valid");
- }
- if (!mCursor.moveToPosition(position)) {
- throw new IllegalStateException("couldn't move cursor to position " + position);
- }
- View v;
- if (convertView == null) {
- v = newView(mContext, mCursor, parent);
- } else {
- v = convertView;
- }
- bindView(v, mContext, mCursor);
- return v;
- }
-
- @Override
- public View getDropDownView(int position, View convertView, ViewGroup parent) {
- if (mDataValid) {
- mCursor.moveToPosition(position);
- View v;
- if (convertView == null) {
- v = newDropDownView(mContext, mCursor, parent);
- } else {
- v = convertView;
- }
- bindView(v, mContext, mCursor);
- return v;
- } else {
- return null;
- }
- }
-
- /**
- * Makes a new view to hold the data pointed to by cursor.
- * @param context Interface to application's global information
- * @param cursor The cursor from which to get the data. The cursor is already
- * moved to the correct position.
- * @param parent The parent to which the new view is attached to
- * @return the newly created view.
- */
- public abstract View newView(Context context, Cursor cursor, ViewGroup parent);
-
- /**
- * Makes a new drop down view to hold the data pointed to by cursor.
- * @param context Interface to application's global information
- * @param cursor The cursor from which to get the data. The cursor is already
- * moved to the correct position.
- * @param parent The parent to which the new view is attached to
- * @return the newly created view.
- */
- public View newDropDownView(Context context, Cursor cursor, ViewGroup parent) {
- return newView(context, cursor, parent);
- }
-
- /**
- * Bind an existing view to the data pointed to by cursor
- * @param view Existing view, returned earlier by newView
- * @param context Interface to application's global information
- * @param cursor The cursor from which to get the data. The cursor is already
- * moved to the correct position.
- */
- public abstract void bindView(View view, Context context, Cursor cursor);
-
- /**
- * Change the underlying cursor to a new cursor. If there is an existing cursor it will be
- * closed.
- *
- * @param cursor the new cursor to be used
- */
- public void changeCursor(Cursor cursor) {
- if (cursor == mCursor) {
- return;
- }
- if (mCursor != null) {
- mCursor.unregisterContentObserver(mChangeObserver);
- mCursor.unregisterDataSetObserver(mDataSetObserver);
- mCursor.close();
- }
- mCursor = cursor;
- if (cursor != null) {
- cursor.registerContentObserver(mChangeObserver);
- cursor.registerDataSetObserver(mDataSetObserver);
- mRowIDColumn = cursor.getColumnIndexOrThrow("_id");
- mDataValid = true;
- // notify the observers about the new cursor
- notifyDataSetChanged();
- } else {
- mRowIDColumn = -1;
- mDataValid = false;
- // notify the observers about the lack of a data set
- notifyDataSetInvalidated();
- }
- }
-
- /**
- * <p>Converts the cursor into a CharSequence. Subclasses should override this
- * method to convert their results. The default implementation returns an
- * empty String for null values or the default String representation of
- * the value.</p>
- *
- * @param cursor the cursor to convert to a CharSequence
- * @return a CharSequence representing the value
- */
- public CharSequence convertToString(Cursor cursor) {
- return cursor == null ? "" : cursor.toString();
- }
-
- /**
- * Runs a query with the specified constraint. This query is requested
- * by the filter attached to this adapter.
- *
- * The query is provided by a
- * {@link android.widget.FilterQueryProvider}.
- * If no provider is specified, the current cursor is not filtered and returned.
- *
- * After this method returns the resulting cursor is passed to {@link #changeCursor(Cursor)}
- * and the previous cursor is closed.
- *
- * This method is always executed on a background thread, not on the
- * application's main thread (or UI thread.)
- *
- * Contract: when constraint is null or empty, the original results,
- * prior to any filtering, must be returned.
- *
- * @param constraint the constraint with which the query must be filtered
- *
- * @return a Cursor representing the results of the new query
- *
- * @see #getFilter()
- * @see #getFilterQueryProvider()
- * @see #setFilterQueryProvider(android.widget.FilterQueryProvider)
- */
- public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
- if (mFilterQueryProvider != null) {
- return mFilterQueryProvider.runQuery(constraint);
- }
-
- return mCursor;
- }
-
- public Filter getFilter() {
- if (mCursorFilter == null) {
- mCursorFilter = new CursorFilter(this);
- }
- return mCursorFilter;
- }
-
- /**
- * Returns the query filter provider used for filtering. When the
- * provider is null, no filtering occurs.
- *
- * @return the current filter query provider or null if it does not exist
- *
- * @see #setFilterQueryProvider(android.widget.FilterQueryProvider)
- * @see #runQueryOnBackgroundThread(CharSequence)
- */
- public FilterQueryProvider getFilterQueryProvider() {
- return mFilterQueryProvider;
- }
-
- /**
- * Sets the query filter provider used to filter the current Cursor.
- * The provider's
- * {@link android.widget.FilterQueryProvider#runQuery(CharSequence)}
- * method is invoked when filtering is requested by a client of
- * this adapter.
- *
- * @param filterQueryProvider the filter query provider or null to remove it
- *
- * @see #getFilterQueryProvider()
- * @see #runQueryOnBackgroundThread(CharSequence)
- */
- public void setFilterQueryProvider(FilterQueryProvider filterQueryProvider) {
- mFilterQueryProvider = filterQueryProvider;
- }
-
- private class ChangeObserver extends ContentObserver {
- public ChangeObserver() {
- super(new Handler());
- }
-
- @Override
- public boolean deliverSelfNotifications() {
- return true;
- }
-
- @Override
- public void onChange(boolean selfChange) {
- if (mAutoRequery && mCursor != null && !mCursor.isClosed()) {
- if (Config.LOGV) Log.v("Cursor", "Auto requerying " + mCursor + " due to update");
- mDataValid = mCursor.requery();
- }
- }
- }
-
- private class MyDataSetObserver extends DataSetObserver {
- @Override
- public void onChanged() {
- mDataValid = true;
- notifyDataSetChanged();
- }
-
- @Override
- public void onInvalidated() {
- mDataValid = false;
- notifyDataSetInvalidated();
- }
- }
-
-}
diff --git a/core/java/android/widget/CursorFilter.java b/core/java/android/widget/CursorFilter.java
deleted file mode 100644
index dbded69..0000000
--- a/core/java/android/widget/CursorFilter.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.database.Cursor;
-
-/**
- * <p>The CursorFilter delegates most of the work to the CursorAdapter.
- * Subclasses should override these delegate methods to run the queries
- * and convert the results into String that can be used by auto-completion
- * widgets.</p>
- */
-class CursorFilter extends Filter {
-
- CursorFilterClient mClient;
-
- interface CursorFilterClient {
- CharSequence convertToString(Cursor cursor);
- Cursor runQueryOnBackgroundThread(CharSequence constraint);
- Cursor getCursor();
- void changeCursor(Cursor cursor);
- }
-
- CursorFilter(CursorFilterClient client) {
- mClient = client;
- }
-
- @Override
- public CharSequence convertResultToString(Object resultValue) {
- return mClient.convertToString((Cursor) resultValue);
- }
-
- @Override
- protected FilterResults performFiltering(CharSequence constraint) {
- Cursor cursor = mClient.runQueryOnBackgroundThread(constraint);
-
- FilterResults results = new FilterResults();
- if (cursor != null) {
- results.count = cursor.getCount();
- results.values = cursor;
- } else {
- results.count = 0;
- results.values = null;
- }
- return results;
- }
-
- @Override
- protected void publishResults(CharSequence constraint, FilterResults results) {
- Cursor oldCursor = mClient.getCursor();
-
- if (results.values != null && results.values != oldCursor) {
- mClient.changeCursor((Cursor) results.values);
- }
- }
-}
diff --git a/core/java/android/widget/CursorTreeAdapter.java b/core/java/android/widget/CursorTreeAdapter.java
deleted file mode 100644
index 7b9b7bd..0000000
--- a/core/java/android/widget/CursorTreeAdapter.java
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.app.Activity;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.database.DataSetObserver;
-import android.os.Handler;
-import android.util.Config;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * An adapter that exposes data from a series of {@link Cursor}s to an
- * {@link ExpandableListView} widget. The top-level {@link Cursor} (that is
- * given in the constructor) exposes the groups, while subsequent {@link Cursor}s
- * returned from {@link #getChildrenCursor(Cursor)} expose children within a
- * particular group. The Cursors must include a column named "_id" or this class
- * will not work.
- */
-public abstract class CursorTreeAdapter extends BaseExpandableListAdapter implements Filterable,
- CursorFilter.CursorFilterClient {
- private Context mContext;
- private Handler mHandler;
- private boolean mAutoRequery;
-
- /** The cursor helper that is used to get the groups */
- MyCursorHelper mGroupCursorHelper;
-
- /**
- * The map of a group position to the group's children cursor helper (the
- * cursor helper that is used to get the children for that group)
- */
- SparseArray<MyCursorHelper> mChildrenCursorHelpers;
-
- // Filter related
- CursorFilter mCursorFilter;
- FilterQueryProvider mFilterQueryProvider;
-
- /**
- * Constructor. The adapter will call {@link Cursor#requery()} on the cursor whenever
- * it changes so that the most recent data is always displayed.
- *
- * @param cursor The cursor from which to get the data for the groups.
- */
- public CursorTreeAdapter(Cursor cursor, Context context) {
- init(cursor, context, true);
- }
-
- /**
- * Constructor.
- *
- * @param cursor The cursor from which to get the data for the groups.
- * @param context The context
- * @param autoRequery If true the adapter will call {@link Cursor#requery()}
- * on the cursor whenever it changes so the most recent data is
- * always displayed.
- */
- public CursorTreeAdapter(Cursor cursor, Context context, boolean autoRequery) {
- init(cursor, context, autoRequery);
- }
-
- private void init(Cursor cursor, Context context, boolean autoRequery) {
- mContext = context;
- mHandler = new Handler();
- mAutoRequery = autoRequery;
-
- mGroupCursorHelper = new MyCursorHelper(cursor);
- mChildrenCursorHelpers = new SparseArray<MyCursorHelper>();
- }
-
- /**
- * Gets the cursor helper for the children in the given group.
- *
- * @param groupPosition The group whose children will be returned
- * @param requestCursor Whether to request a Cursor via
- * {@link #getChildrenCursor(Cursor)} (true), or to assume a call
- * to {@link #setChildrenCursor(int, Cursor)} will happen shortly
- * (false).
- * @return The cursor helper for the children of the given group
- */
- synchronized MyCursorHelper getChildrenCursorHelper(int groupPosition, boolean requestCursor) {
- MyCursorHelper cursorHelper = mChildrenCursorHelpers.get(groupPosition);
-
- if (cursorHelper == null) {
- if (mGroupCursorHelper.moveTo(groupPosition) == null) return null;
-
- final Cursor cursor = getChildrenCursor(mGroupCursorHelper.getCursor());
- cursorHelper = new MyCursorHelper(cursor);
- mChildrenCursorHelpers.put(groupPosition, cursorHelper);
- }
-
- return cursorHelper;
- }
-
- /**
- * Gets the Cursor for the children at the given group. Subclasses must
- * implement this method to return the children data for a particular group.
- * <p>
- * If you want to asynchronously query a provider to prevent blocking the
- * UI, it is possible to return null and at a later time call
- * {@link #setChildrenCursor(int, Cursor)}.
- * <p>
- * It is your responsibility to manage this Cursor through the Activity
- * lifecycle. It is a good idea to use {@link Activity#managedQuery} which
- * will handle this for you. In some situations, the adapter will deactivate
- * the Cursor on its own, but this will not always be the case, so please
- * ensure the Cursor is properly managed.
- *
- * @param groupCursor The cursor pointing to the group whose children cursor
- * should be returned
- * @return The cursor for the children of a particular group, or null.
- */
- abstract protected Cursor getChildrenCursor(Cursor groupCursor);
-
- /**
- * Sets the group Cursor.
- *
- * @param cursor The Cursor to set for the group.
- */
- public void setGroupCursor(Cursor cursor) {
- mGroupCursorHelper.changeCursor(cursor, false);
- }
-
- /**
- * Sets the children Cursor for a particular group.
- * <p>
- * This is useful when asynchronously querying to prevent blocking the UI.
- *
- * @param groupPosition The group whose children are being set via this Cursor.
- * @param childrenCursor The Cursor that contains the children of the group.
- */
- public void setChildrenCursor(int groupPosition, Cursor childrenCursor) {
-
- /*
- * Don't request a cursor from the subclass, instead we will be setting
- * the cursor ourselves.
- */
- MyCursorHelper childrenCursorHelper = getChildrenCursorHelper(groupPosition, false);
-
- /*
- * Don't release any cursor since we know exactly what data is changing
- * (this cursor, which is still valid).
- */
- childrenCursorHelper.changeCursor(childrenCursor, false);
- }
-
- public Cursor getChild(int groupPosition, int childPosition) {
- // Return this group's children Cursor pointing to the particular child
- return getChildrenCursorHelper(groupPosition, true).moveTo(childPosition);
- }
-
- public long getChildId(int groupPosition, int childPosition) {
- return getChildrenCursorHelper(groupPosition, true).getId(childPosition);
- }
-
- public int getChildrenCount(int groupPosition) {
- MyCursorHelper helper = getChildrenCursorHelper(groupPosition, true);
- return (mGroupCursorHelper.isValid() && helper != null) ? helper.getCount() : 0;
- }
-
- public Cursor getGroup(int groupPosition) {
- // Return the group Cursor pointing to the given group
- return mGroupCursorHelper.moveTo(groupPosition);
- }
-
- public int getGroupCount() {
- return mGroupCursorHelper.getCount();
- }
-
- public long getGroupId(int groupPosition) {
- return mGroupCursorHelper.getId(groupPosition);
- }
-
- public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
- ViewGroup parent) {
- Cursor cursor = mGroupCursorHelper.moveTo(groupPosition);
- if (cursor == null) {
- throw new IllegalStateException("this should only be called when the cursor is valid");
- }
-
- View v;
- if (convertView == null) {
- v = newGroupView(mContext, cursor, isExpanded, parent);
- } else {
- v = convertView;
- }
- bindGroupView(v, mContext, cursor, isExpanded);
- return v;
- }
-
- /**
- * Makes a new group view to hold the group data pointed to by cursor.
- *
- * @param context Interface to application's global information
- * @param cursor The group cursor from which to get the data. The cursor is
- * already moved to the correct position.
- * @param isExpanded Whether the group is expanded.
- * @param parent The parent to which the new view is attached to
- * @return The newly created view.
- */
- protected abstract View newGroupView(Context context, Cursor cursor, boolean isExpanded,
- ViewGroup parent);
-
- /**
- * Bind an existing view to the group data pointed to by cursor.
- *
- * @param view Existing view, returned earlier by newGroupView.
- * @param context Interface to application's global information
- * @param cursor The cursor from which to get the data. The cursor is
- * already moved to the correct position.
- * @param isExpanded Whether the group is expanded.
- */
- protected abstract void bindGroupView(View view, Context context, Cursor cursor,
- boolean isExpanded);
-
- public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
- View convertView, ViewGroup parent) {
- MyCursorHelper cursorHelper = getChildrenCursorHelper(groupPosition, true);
-
- Cursor cursor = cursorHelper.moveTo(childPosition);
- if (cursor == null) {
- throw new IllegalStateException("this should only be called when the cursor is valid");
- }
-
- View v;
- if (convertView == null) {
- v = newChildView(mContext, cursor, isLastChild, parent);
- } else {
- v = convertView;
- }
- bindChildView(v, mContext, cursor, isLastChild);
- return v;
- }
-
- /**
- * Makes a new child view to hold the data pointed to by cursor.
- *
- * @param context Interface to application's global information
- * @param cursor The cursor from which to get the data. The cursor is
- * already moved to the correct position.
- * @param isLastChild Whether the child is the last child within its group.
- * @param parent The parent to which the new view is attached to
- * @return the newly created view.
- */
- protected abstract View newChildView(Context context, Cursor cursor, boolean isLastChild,
- ViewGroup parent);
-
- /**
- * Bind an existing view to the child data pointed to by cursor
- *
- * @param view Existing view, returned earlier by newChildView
- * @param context Interface to application's global information
- * @param cursor The cursor from which to get the data. The cursor is
- * already moved to the correct position.
- * @param isLastChild Whether the child is the last child within its group.
- */
- protected abstract void bindChildView(View view, Context context, Cursor cursor,
- boolean isLastChild);
-
- public boolean isChildSelectable(int groupPosition, int childPosition) {
- return true;
- }
-
- public boolean hasStableIds() {
- return true;
- }
-
- private synchronized void releaseCursorHelpers() {
- for (int pos = mChildrenCursorHelpers.size() - 1; pos >= 0; pos--) {
- mChildrenCursorHelpers.valueAt(pos).deactivate();
- }
-
- mChildrenCursorHelpers.clear();
- }
-
- @Override
- public void notifyDataSetChanged() {
- notifyDataSetChanged(true);
- }
-
- /**
- * Notifies a data set change, but with the option of not releasing any
- * cached cursors.
- *
- * @param releaseCursors Whether to release and deactivate any cached
- * cursors.
- */
- public void notifyDataSetChanged(boolean releaseCursors) {
-
- if (releaseCursors) {
- releaseCursorHelpers();
- }
-
- super.notifyDataSetChanged();
- }
-
- @Override
- public void notifyDataSetInvalidated() {
- releaseCursorHelpers();
- super.notifyDataSetInvalidated();
- }
-
- @Override
- public void onGroupCollapsed(int groupPosition) {
- deactivateChildrenCursorHelper(groupPosition);
- }
-
- /**
- * Deactivates the Cursor and removes the helper from cache.
- *
- * @param groupPosition The group whose children Cursor and helper should be
- * deactivated.
- */
- synchronized void deactivateChildrenCursorHelper(int groupPosition) {
- MyCursorHelper cursorHelper = getChildrenCursorHelper(groupPosition, true);
- mChildrenCursorHelpers.remove(groupPosition);
- cursorHelper.deactivate();
- }
-
- /**
- * @see CursorAdapter#convertToString(Cursor)
- */
- public String convertToString(Cursor cursor) {
- return cursor == null ? "" : cursor.toString();
- }
-
- /**
- * @see CursorAdapter#runQueryOnBackgroundThread(CharSequence)
- */
- public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
- if (mFilterQueryProvider != null) {
- return mFilterQueryProvider.runQuery(constraint);
- }
-
- return mGroupCursorHelper.getCursor();
- }
-
- public Filter getFilter() {
- if (mCursorFilter == null) {
- mCursorFilter = new CursorFilter(this);
- }
- return mCursorFilter;
- }
-
- /**
- * @see CursorAdapter#getFilterQueryProvider()
- */
- public FilterQueryProvider getFilterQueryProvider() {
- return mFilterQueryProvider;
- }
-
- /**
- * @see CursorAdapter#setFilterQueryProvider(FilterQueryProvider)
- */
- public void setFilterQueryProvider(FilterQueryProvider filterQueryProvider) {
- mFilterQueryProvider = filterQueryProvider;
- }
-
- /**
- * @see CursorAdapter#changeCursor(Cursor)
- */
- public void changeCursor(Cursor cursor) {
- mGroupCursorHelper.changeCursor(cursor, true);
- }
-
- /**
- * @see CursorAdapter#getCursor()
- */
- public Cursor getCursor() {
- return mGroupCursorHelper.getCursor();
- }
-
- /**
- * Helper class for Cursor management:
- * <li> Data validity
- * <li> Funneling the content and data set observers from a Cursor to a
- * single data set observer for widgets
- * <li> ID from the Cursor for use in adapter IDs
- * <li> Swapping cursors but maintaining other metadata
- */
- class MyCursorHelper {
- private Cursor mCursor;
- private boolean mDataValid;
- private int mRowIDColumn;
- private MyContentObserver mContentObserver;
- private MyDataSetObserver mDataSetObserver;
-
- MyCursorHelper(Cursor cursor) {
- final boolean cursorPresent = cursor != null;
- mCursor = cursor;
- mDataValid = cursorPresent;
- mRowIDColumn = cursorPresent ? cursor.getColumnIndex("_id") : -1;
- mContentObserver = new MyContentObserver();
- mDataSetObserver = new MyDataSetObserver();
- if (cursorPresent) {
- cursor.registerContentObserver(mContentObserver);
- cursor.registerDataSetObserver(mDataSetObserver);
- }
- }
-
- Cursor getCursor() {
- return mCursor;
- }
-
- int getCount() {
- if (mDataValid && mCursor != null) {
- return mCursor.getCount();
- } else {
- return 0;
- }
- }
-
- long getId(int position) {
- if (mDataValid && mCursor != null) {
- if (mCursor.moveToPosition(position)) {
- return mCursor.getLong(mRowIDColumn);
- } else {
- return 0;
- }
- } else {
- return 0;
- }
- }
-
- Cursor moveTo(int position) {
- if (mDataValid && (mCursor != null) && mCursor.moveToPosition(position)) {
- return mCursor;
- } else {
- return null;
- }
- }
-
- void changeCursor(Cursor cursor, boolean releaseCursors) {
- if (cursor == mCursor) return;
-
- deactivate();
- mCursor = cursor;
- if (cursor != null) {
- cursor.registerContentObserver(mContentObserver);
- cursor.registerDataSetObserver(mDataSetObserver);
- mRowIDColumn = cursor.getColumnIndex("_id");
- mDataValid = true;
- // notify the observers about the new cursor
- notifyDataSetChanged(releaseCursors);
- } else {
- mRowIDColumn = -1;
- mDataValid = false;
- // notify the observers about the lack of a data set
- notifyDataSetInvalidated();
- }
- }
-
- void deactivate() {
- if (mCursor == null) {
- return;
- }
-
- mCursor.unregisterContentObserver(mContentObserver);
- mCursor.unregisterDataSetObserver(mDataSetObserver);
- mCursor.deactivate();
- mCursor = null;
- }
-
- boolean isValid() {
- return mDataValid && mCursor != null;
- }
-
- private class MyContentObserver extends ContentObserver {
- public MyContentObserver() {
- super(mHandler);
- }
-
- @Override
- public boolean deliverSelfNotifications() {
- return true;
- }
-
- @Override
- public void onChange(boolean selfChange) {
- if (mAutoRequery && mCursor != null) {
- if (Config.LOGV) Log.v("Cursor", "Auto requerying " + mCursor +
- " due to update");
- mDataValid = mCursor.requery();
- }
- }
- }
-
- private class MyDataSetObserver extends DataSetObserver {
- @Override
- public void onChanged() {
- mDataValid = true;
- notifyDataSetChanged();
- }
-
- @Override
- public void onInvalidated() {
- mDataValid = false;
- notifyDataSetInvalidated();
- }
- }
- }
-}
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
deleted file mode 100644
index 54f2707..0000000
--- a/core/java/android/widget/DatePicker.java
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.annotation.Widget;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.format.DateFormat;
-import android.util.AttributeSet;
-import android.util.SparseArray;
-import android.view.LayoutInflater;
-
-import com.android.internal.R;
-import com.android.internal.widget.NumberPicker;
-import com.android.internal.widget.NumberPicker.OnChangedListener;
-
-import java.text.DateFormatSymbols;
-import java.util.Calendar;
-
-/**
- * A view for selecting a month / year / day based on a calendar like layout.
- *
- * For a dialog using this view, see {@link android.app.DatePickerDialog}.
- */
-@Widget
-public class DatePicker extends FrameLayout {
-
- private static final int DEFAULT_START_YEAR = 1900;
- private static final int DEFAULT_END_YEAR = 2100;
-
- /* UI Components */
- private final NumberPicker mDayPicker;
- private final NumberPicker mMonthPicker;
- private final NumberPicker mYearPicker;
-
- /**
- * How we notify users the date has changed.
- */
- private OnDateChangedListener mOnDateChangedListener;
-
- private int mDay;
- private int mMonth;
- private int mYear;
-
- /**
- * The callback used to indicate the user changes the date.
- */
- public interface OnDateChangedListener {
-
- /**
- * @param view The view associated with this listener.
- * @param year The year that was set.
- * @param monthOfYear The month that was set (0-11) for compatibility
- * with {@link java.util.Calendar}.
- * @param dayOfMonth The day of the month that was set.
- */
- void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth);
- }
-
- public DatePicker(Context context) {
- this(context, null);
- }
-
- public DatePicker(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public DatePicker(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(R.layout.date_picker, this, true);
-
- mDayPicker = (NumberPicker) findViewById(R.id.day);
- mDayPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
- mDayPicker.setSpeed(100);
- mDayPicker.setOnChangeListener(new OnChangedListener() {
- public void onChanged(NumberPicker picker, int oldVal, int newVal) {
- mDay = newVal;
- if (mOnDateChangedListener != null) {
- mOnDateChangedListener.onDateChanged(DatePicker.this, mYear, mMonth, mDay);
- }
- }
- });
- mMonthPicker = (NumberPicker) findViewById(R.id.month);
- mMonthPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
- DateFormatSymbols dfs = new DateFormatSymbols();
- mMonthPicker.setRange(1, 12, dfs.getShortMonths());
- mMonthPicker.setSpeed(200);
- mMonthPicker.setOnChangeListener(new OnChangedListener() {
- public void onChanged(NumberPicker picker, int oldVal, int newVal) {
-
- /* We display the month 1-12 but store it 0-11 so always
- * subtract by one to ensure our internal state is always 0-11
- */
- mMonth = newVal - 1;
- if (mOnDateChangedListener != null) {
- mOnDateChangedListener.onDateChanged(DatePicker.this, mYear, mMonth, mDay);
- }
- updateDaySpinner();
- }
- });
- mYearPicker = (NumberPicker) findViewById(R.id.year);
- mYearPicker.setSpeed(100);
- mYearPicker.setOnChangeListener(new OnChangedListener() {
- public void onChanged(NumberPicker picker, int oldVal, int newVal) {
- mYear = newVal;
- if (mOnDateChangedListener != null) {
- mOnDateChangedListener.onDateChanged(DatePicker.this, mYear, mMonth, mDay);
- }
- }
- });
-
- // attributes
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker);
-
- int mStartYear = a.getInt(R.styleable.DatePicker_startYear, DEFAULT_START_YEAR);
- int mEndYear = a.getInt(R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
- mYearPicker.setRange(mStartYear, mEndYear);
-
- a.recycle();
-
- // initialize to current date
- Calendar cal = Calendar.getInstance();
- init(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), null);
-
- // re-order the number pickers to match the current date format
- reorderPickers();
-
- if (!isEnabled()) {
- setEnabled(false);
- }
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- super.setEnabled(enabled);
- mDayPicker.setEnabled(enabled);
- mMonthPicker.setEnabled(enabled);
- mYearPicker.setEnabled(enabled);
- }
-
- private void reorderPickers() {
- char[] order = DateFormat.getDateFormatOrder(mContext);
-
- /* Default order is month, date, year so if that's the order then
- * do nothing.
- */
- if ((order[0] == DateFormat.MONTH) && (order[1] == DateFormat.DATE)) {
- return;
- }
-
- /* Remove the 3 pickers from their parent and then add them back in the
- * required order.
- */
- LinearLayout parent = (LinearLayout) findViewById(R.id.parent);
- parent.removeAllViews();
- for (char c : order) {
- if (c == DateFormat.DATE) {
- parent.addView(mDayPicker);
- } else if (c == DateFormat.MONTH) {
- parent.addView(mMonthPicker);
- } else {
- parent.addView (mYearPicker);
- }
- }
- }
-
- public void updateDate(int year, int monthOfYear, int dayOfMonth) {
- mYear = year;
- mMonth = monthOfYear;
- mDay = dayOfMonth;
- updateSpinners();
- }
-
- private static class SavedState extends BaseSavedState {
-
- private final int mYear;
- private final int mMonth;
- private final int mDay;
-
- /**
- * Constructor called from {@link DatePicker#onSaveInstanceState()}
- */
- private SavedState(Parcelable superState, int year, int month, int day) {
- super(superState);
- mYear = year;
- mMonth = month;
- mDay = day;
- }
-
- /**
- * Constructor called from {@link #CREATOR}
- */
- private SavedState(Parcel in) {
- super(in);
- mYear = in.readInt();
- mMonth = in.readInt();
- mDay = in.readInt();
- }
-
- public int getYear() {
- return mYear;
- }
-
- public int getMonth() {
- return mMonth;
- }
-
- public int getDay() {
- return mDay;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(mYear);
- dest.writeInt(mMonth);
- dest.writeInt(mDay);
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR =
- new Creator<SavedState>() {
-
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
-
- /**
- * Override so we are in complete control of save / restore for this widget.
- */
- @Override
- protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
- dispatchThawSelfOnly(container);
- }
-
- @Override
- protected Parcelable onSaveInstanceState() {
- Parcelable superState = super.onSaveInstanceState();
-
- return new SavedState(superState, mYear, mMonth, mDay);
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
- super.onRestoreInstanceState(ss.getSuperState());
- mYear = ss.getYear();
- mMonth = ss.getMonth();
- mDay = ss.getDay();
- }
-
- /**
- * Initialize the state.
- * @param year The initial year.
- * @param monthOfYear The initial month.
- * @param dayOfMonth The initial day of the month.
- * @param onDateChangedListener How user is notified date is changed by user, can be null.
- */
- public void init(int year, int monthOfYear, int dayOfMonth,
- OnDateChangedListener onDateChangedListener) {
- mYear = year;
- mMonth = monthOfYear;
- mDay = dayOfMonth;
- mOnDateChangedListener = onDateChangedListener;
- updateSpinners();
- }
-
- private void updateSpinners() {
- updateDaySpinner();
- mYearPicker.setCurrent(mYear);
-
- /* The month display uses 1-12 but our internal state stores it
- * 0-11 so add one when setting the display.
- */
- mMonthPicker.setCurrent(mMonth + 1);
- }
-
- private void updateDaySpinner() {
- Calendar cal = Calendar.getInstance();
- cal.set(mYear, mMonth, mDay);
- int max = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
- mDayPicker.setRange(1, max);
- mDayPicker.setCurrent(mDay);
- }
-
- public int getYear() {
- return mYear;
- }
-
- public int getMonth() {
- return mMonth;
- }
-
- public int getDayOfMonth() {
- return mDay;
- }
-}
diff --git a/core/java/android/widget/DialerFilter.java b/core/java/android/widget/DialerFilter.java
deleted file mode 100644
index a23887f..0000000
--- a/core/java/android/widget/DialerFilter.java
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.view.KeyEvent;
-import android.text.Editable;
-import android.text.InputFilter;
-import android.text.Selection;
-import android.text.Spannable;
-import android.text.Spanned;
-import android.text.TextWatcher;
-import android.text.method.DialerKeyListener;
-import android.text.method.KeyListener;
-import android.text.method.TextKeyListener;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.KeyCharacterMap;
-import android.view.View;
-import android.graphics.Rect;
-
-
-
-public class DialerFilter extends RelativeLayout
-{
- public DialerFilter(Context context) {
- super(context);
- }
-
- public DialerFilter(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- // Setup the filter view
- mInputFilters = new InputFilter[] { new InputFilter.AllCaps() };
-
- mHint = (EditText) findViewById(com.android.internal.R.id.hint);
- if (mHint == null) {
- throw new IllegalStateException("DialerFilter must have a child EditText named hint");
- }
- mHint.setFilters(mInputFilters);
-
- mLetters = mHint;
- mLetters.setKeyListener(TextKeyListener.getInstance());
- mLetters.setMovementMethod(null);
- mLetters.setFocusable(false);
-
- // Setup the digits view
- mPrimary = (EditText) findViewById(com.android.internal.R.id.primary);
- if (mPrimary == null) {
- throw new IllegalStateException("DialerFilter must have a child EditText named primary");
- }
- mPrimary.setFilters(mInputFilters);
-
- mDigits = mPrimary;
- mDigits.setKeyListener(DialerKeyListener.getInstance());
- mDigits.setMovementMethod(null);
- mDigits.setFocusable(false);
-
- // Look for an icon
- mIcon = (ImageView) findViewById(com.android.internal.R.id.icon);
-
- // Setup focus & highlight for this view
- setFocusable(true);
-
- // Default the mode based on the keyboard
- KeyCharacterMap kmap
- = KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD);
- mIsQwerty = kmap.getKeyboardType() != KeyCharacterMap.NUMERIC;
- if (mIsQwerty) {
- Log.i("DialerFilter", "This device looks to be QWERTY");
-// setMode(DIGITS_AND_LETTERS);
- } else {
- Log.i("DialerFilter", "This device looks to be 12-KEY");
-// setMode(DIGITS_ONLY);
- }
-
- // XXX Force the mode to QWERTY for now, since 12-key isn't supported
- mIsQwerty = true;
- setMode(DIGITS_AND_LETTERS);
- }
-
- /**
- * Only show the icon view when focused, if there is one.
- */
- @Override
- protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
- super.onFocusChanged(focused, direction, previouslyFocusedRect);
-
- if (mIcon != null) {
- mIcon.setVisibility(focused ? View.VISIBLE : View.GONE);
- }
- }
-
-
- public boolean isQwertyKeyboard() {
- return mIsQwerty;
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- boolean handled = false;
-
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- break;
-
- case KeyEvent.KEYCODE_DEL:
- switch (mMode) {
- case DIGITS_AND_LETTERS:
- handled = mDigits.onKeyDown(keyCode, event);
- handled &= mLetters.onKeyDown(keyCode, event);
- break;
-
- case DIGITS_AND_LETTERS_NO_DIGITS:
- handled = mLetters.onKeyDown(keyCode, event);
- if (mLetters.getText().length() == mDigits.getText().length()) {
- setMode(DIGITS_AND_LETTERS);
- }
- break;
-
- case DIGITS_AND_LETTERS_NO_LETTERS:
- if (mDigits.getText().length() == mLetters.getText().length()) {
- mLetters.onKeyDown(keyCode, event);
- setMode(DIGITS_AND_LETTERS);
- }
- handled = mDigits.onKeyDown(keyCode, event);
- break;
-
- case DIGITS_ONLY:
- handled = mDigits.onKeyDown(keyCode, event);
- break;
-
- case LETTERS_ONLY:
- handled = mLetters.onKeyDown(keyCode, event);
- break;
- }
- break;
-
- default:
- //mIsQwerty = msg.getKeyIsQwertyKeyboard();
-
- switch (mMode) {
- case DIGITS_AND_LETTERS:
- handled = mLetters.onKeyDown(keyCode, event);
-
- // pass this throw so the shift state is correct (for example,
- // on a standard QWERTY keyboard, * and 8 are on the same key)
- if (KeyEvent.isModifierKey(keyCode)) {
- mDigits.onKeyDown(keyCode, event);
- handled = true;
- break;
- }
-
- // Only check to see if the digit is valid if the key is a printing key
- // in the TextKeyListener. This prevents us from hiding the digits
- // line when keys like UP and DOWN are hit.
- // XXX note that KEYCODE_TAB is special-cased here for
- // devices that share tab and 0 on a single key.
- boolean isPrint = event.isPrintingKey();
- if (isPrint || keyCode == KeyEvent.KEYCODE_SPACE
- || keyCode == KeyEvent.KEYCODE_TAB) {
- char c = event.getMatch(DialerKeyListener.CHARACTERS);
- if (c != 0) {
- handled &= mDigits.onKeyDown(keyCode, event);
- } else {
- setMode(DIGITS_AND_LETTERS_NO_DIGITS);
- }
- }
- break;
-
- case DIGITS_AND_LETTERS_NO_LETTERS:
- case DIGITS_ONLY:
- handled = mDigits.onKeyDown(keyCode, event);
- break;
-
- case DIGITS_AND_LETTERS_NO_DIGITS:
- case LETTERS_ONLY:
- handled = mLetters.onKeyDown(keyCode, event);
- break;
- }
- }
-
- if (!handled) {
- return super.onKeyDown(keyCode, event);
- } else {
- return true;
- }
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- boolean a = mLetters.onKeyUp(keyCode, event);
- boolean b = mDigits.onKeyUp(keyCode, event);
- return a || b;
- }
-
- public int getMode() {
- return mMode;
- }
-
- /**
- * Change the mode of the widget.
- *
- * @param newMode The mode to switch to.
- */
- public void setMode(int newMode) {
- switch (newMode) {
- case DIGITS_AND_LETTERS:
- makeDigitsPrimary();
- mLetters.setVisibility(View.VISIBLE);
- mDigits.setVisibility(View.VISIBLE);
- break;
-
- case DIGITS_ONLY:
- makeDigitsPrimary();
- mLetters.setVisibility(View.GONE);
- mDigits.setVisibility(View.VISIBLE);
- break;
-
- case LETTERS_ONLY:
- makeLettersPrimary();
- mLetters.setVisibility(View.VISIBLE);
- mDigits.setVisibility(View.GONE);
- break;
-
- case DIGITS_AND_LETTERS_NO_LETTERS:
- makeDigitsPrimary();
- mLetters.setVisibility(View.INVISIBLE);
- mDigits.setVisibility(View.VISIBLE);
- break;
-
- case DIGITS_AND_LETTERS_NO_DIGITS:
- makeLettersPrimary();
- mLetters.setVisibility(View.VISIBLE);
- mDigits.setVisibility(View.INVISIBLE);
- break;
-
- }
- int oldMode = mMode;
- mMode = newMode;
- onModeChange(oldMode, newMode);
- }
-
- private void makeLettersPrimary() {
- if (mPrimary == mDigits) {
- swapPrimaryAndHint(true);
- }
- }
-
- private void makeDigitsPrimary() {
- if (mPrimary == mLetters) {
- swapPrimaryAndHint(false);
- }
- }
-
- private void swapPrimaryAndHint(boolean makeLettersPrimary) {
- Editable lettersText = mLetters.getText();
- Editable digitsText = mDigits.getText();
- KeyListener lettersInput = mLetters.getKeyListener();
- KeyListener digitsInput = mDigits.getKeyListener();
-
- if (makeLettersPrimary) {
- mLetters = mPrimary;
- mDigits = mHint;
- } else {
- mLetters = mHint;
- mDigits = mPrimary;
- }
-
- mLetters.setKeyListener(lettersInput);
- mLetters.setText(lettersText);
- lettersText = mLetters.getText();
- Selection.setSelection(lettersText, lettersText.length());
-
- mDigits.setKeyListener(digitsInput);
- mDigits.setText(digitsText);
- digitsText = mDigits.getText();
- Selection.setSelection(digitsText, digitsText.length());
-
- // Reset the filters
- mPrimary.setFilters(mInputFilters);
- mHint.setFilters(mInputFilters);
- }
-
-
- public CharSequence getLetters() {
- if (mLetters.getVisibility() == View.VISIBLE) {
- return mLetters.getText();
- } else {
- return "";
- }
- }
-
- public CharSequence getDigits() {
- if (mDigits.getVisibility() == View.VISIBLE) {
- return mDigits.getText();
- } else {
- return "";
- }
- }
-
- public CharSequence getFilterText() {
- if (mMode != DIGITS_ONLY) {
- return getLetters();
- } else {
- return getDigits();
- }
- }
-
- public void append(String text) {
- switch (mMode) {
- case DIGITS_AND_LETTERS:
- mDigits.getText().append(text);
- mLetters.getText().append(text);
- break;
-
- case DIGITS_AND_LETTERS_NO_LETTERS:
- case DIGITS_ONLY:
- mDigits.getText().append(text);
- break;
-
- case DIGITS_AND_LETTERS_NO_DIGITS:
- case LETTERS_ONLY:
- mLetters.getText().append(text);
- break;
- }
- }
-
- /**
- * Clears both the digits and the filter text.
- */
- public void clearText() {
- Editable text;
-
- text = mLetters.getText();
- text.clear();
-
- text = mDigits.getText();
- text.clear();
-
- // Reset the mode based on the hardware type
- if (mIsQwerty) {
- setMode(DIGITS_AND_LETTERS);
- } else {
- setMode(DIGITS_ONLY);
- }
- }
-
- public void setLettersWatcher(TextWatcher watcher) {
- CharSequence text = mLetters.getText();
- Spannable span = (Spannable)text;
- span.setSpan(watcher, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- }
-
- public void setDigitsWatcher(TextWatcher watcher) {
- CharSequence text = mDigits.getText();
- Spannable span = (Spannable)text;
- span.setSpan(watcher, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- }
-
- public void setFilterWatcher(TextWatcher watcher) {
- if (mMode != DIGITS_ONLY) {
- setLettersWatcher(watcher);
- } else {
- setDigitsWatcher(watcher);
- }
- }
-
- public void removeFilterWatcher(TextWatcher watcher) {
- Spannable text;
- if (mMode != DIGITS_ONLY) {
- text = mLetters.getText();
- } else {
- text = mDigits.getText();
- }
- text.removeSpan(watcher);
- }
-
- /**
- * Called right after the mode changes to give subclasses the option to
- * restyle, etc.
- */
- protected void onModeChange(int oldMode, int newMode) {
- }
-
- /** This mode has both lines */
- public static final int DIGITS_AND_LETTERS = 1;
- /** This mode is when after starting in {@link #DIGITS_AND_LETTERS} mode the filter
- * has removed all possibility of the digits matching, leaving only the letters line */
- public static final int DIGITS_AND_LETTERS_NO_DIGITS = 2;
- /** This mode is when after starting in {@link #DIGITS_AND_LETTERS} mode the filter
- * has removed all possibility of the letters matching, leaving only the digits line */
- public static final int DIGITS_AND_LETTERS_NO_LETTERS = 3;
- /** This mode has only the digits line */
- public static final int DIGITS_ONLY = 4;
- /** This mode has only the letters line */
- public static final int LETTERS_ONLY = 5;
-
- EditText mLetters;
- EditText mDigits;
- EditText mPrimary;
- EditText mHint;
- InputFilter mInputFilters[];
- ImageView mIcon;
- int mMode;
- private boolean mIsQwerty;
-}
diff --git a/core/java/android/widget/DigitalClock.java b/core/java/android/widget/DigitalClock.java
deleted file mode 100644
index 379883a..0000000
--- a/core/java/android/widget/DigitalClock.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.text.format.DateFormat;
-import android.util.AttributeSet;
-
-import java.util.Calendar;
-
-/**
- * Like AnalogClock, but digital. Shows seconds.
- *
- * FIXME: implement separate views for hours/minutes/seconds, so
- * proportional fonts don't shake rendering
- */
-
-public class DigitalClock extends TextView {
-
- Calendar mCalendar;
- private final static String m12 = "h:mm:ss aa";
- private final static String m24 = "k:mm:ss";
- private FormatChangeObserver mFormatChangeObserver;
-
- private Runnable mTicker;
- private Handler mHandler;
-
- private boolean mTickerStopped = false;
-
- String mFormat;
-
- public DigitalClock(Context context) {
- super(context);
- initClock(context);
- }
-
- public DigitalClock(Context context, AttributeSet attrs) {
- super(context, attrs);
- initClock(context);
- }
-
- private void initClock(Context context) {
- Resources r = mContext.getResources();
-
- if (mCalendar == null) {
- mCalendar = Calendar.getInstance();
- }
-
- mFormatChangeObserver = new FormatChangeObserver();
- getContext().getContentResolver().registerContentObserver(
- Settings.System.CONTENT_URI, true, mFormatChangeObserver);
-
- setFormat();
- }
-
- @Override
- protected void onAttachedToWindow() {
- mTickerStopped = false;
- super.onAttachedToWindow();
- mHandler = new Handler();
-
- /**
- * requests a tick on the next hard-second boundary
- */
- mTicker = new Runnable() {
- public void run() {
- if (mTickerStopped) return;
- mCalendar.setTimeInMillis(System.currentTimeMillis());
- setText(DateFormat.format(mFormat, mCalendar));
- invalidate();
- long now = SystemClock.uptimeMillis();
- long next = now + (1000 - now % 1000);
- mHandler.postAtTime(mTicker, next);
- }
- };
- mTicker.run();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- mTickerStopped = true;
- }
-
- /**
- * Pulls 12/24 mode from system settings
- */
- private boolean get24HourMode() {
- return android.text.format.DateFormat.is24HourFormat(getContext());
- }
-
- private void setFormat() {
- if (get24HourMode()) {
- mFormat = m24;
- } else {
- mFormat = m12;
- }
- }
-
- private class FormatChangeObserver extends ContentObserver {
- public FormatChangeObserver() {
- super(new Handler());
- }
-
- @Override
- public void onChange(boolean selfChange) {
- setFormat();
- }
- }
-}
diff --git a/core/java/android/widget/DoubleDigitManager.java b/core/java/android/widget/DoubleDigitManager.java
deleted file mode 100644
index 1eea1fb..0000000
--- a/core/java/android/widget/DoubleDigitManager.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.os.Handler;
-
-/**
- * Provides callbacks indicating the steps in two digit pressing within a
- * timeout.
- *
- * Package private: only relevant in helping {@link TimeSpinnerHelper}.
- */
-class DoubleDigitManager {
-
- private final long timeoutInMillis;
- private final CallBack mCallBack;
-
- private Integer intermediateDigit;
-
- /**
- * @param timeoutInMillis How long after the first digit is pressed does
- * the user have to press the second digit?
- * @param callBack The callback to indicate what's going on with the user.
- */
- public DoubleDigitManager(long timeoutInMillis, CallBack callBack) {
- this.timeoutInMillis = timeoutInMillis;
- mCallBack = callBack;
- }
-
- /**
- * Report to this manager that a digit was pressed.
- * @param digit
- */
- public void reportDigit(int digit) {
- if (intermediateDigit == null) {
- intermediateDigit = digit;
-
- new Handler().postDelayed(new Runnable() {
- public void run() {
- if (intermediateDigit != null) {
- mCallBack.singleDigitFinal(intermediateDigit);
- intermediateDigit = null;
- }
- }
- }, timeoutInMillis);
-
- if (!mCallBack.singleDigitIntermediate(digit)) {
-
- // this wasn't a good candidate for the intermediate digit,
- // make it the final digit (since there is no opportunity to
- // reject the final digit).
- intermediateDigit = null;
- mCallBack.singleDigitFinal(digit);
- }
- } else if (mCallBack.twoDigitsFinal(intermediateDigit, digit)) {
- intermediateDigit = null;
- }
- }
-
- /**
- * The callback to indicate what is going on with the digits pressed.
- */
- static interface CallBack {
-
- /**
- * A digit was pressed, and there are no intermediate digits.
- * @param digit The digit pressed.
- * @return Whether the digit was accepted; how the user of this manager
- * tells us that the intermediate digit is acceptable as an
- * intermediate digit.
- */
- boolean singleDigitIntermediate(int digit);
-
- /**
- * A single digit was pressed, and it is 'the final answer'.
- * - a single digit pressed, and the timeout expires.
- * - a single digit pressed, and {@link #singleDigitIntermediate}
- * returned false.
- * @param digit The digit.
- */
- void singleDigitFinal(int digit);
-
- /**
- * The user pressed digit1, then digit2 within the timeout.
- * @param digit1
- * @param digit2
- */
- boolean twoDigitsFinal(int digit1, int digit2);
- }
-
-}
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
deleted file mode 100644
index 57aca24..0000000
--- a/core/java/android/widget/EditText.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.text.*;
-import android.text.method.*;
-import android.content.Context;
-import android.util.AttributeSet;
-
-
-/*
- * This is supposed to be a *very* thin veneer over TextView.
- * Do not make any changes here that do anything that a TextView
- * with a key listener and a movement method wouldn't do!
- */
-
-/**
- * EditText is a thin veneer over TextView that configures itself
- * to be editable.
- * <p>
- * <b>XML attributes</b>
- * <p>
- * See {@link android.R.styleable#EditText EditText Attributes},
- * {@link android.R.styleable#TextView TextView Attributes},
- * {@link android.R.styleable#View View Attributes}
- */
-public class EditText extends TextView {
- public EditText(Context context) {
- this(context, null);
- }
-
- public EditText(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.editTextStyle);
- }
-
- public EditText(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected boolean getDefaultEditable() {
- return true;
- }
-
- @Override
- protected MovementMethod getDefaultMovementMethod() {
- return ArrowKeyMovementMethod.getInstance();
- }
-
- @Override
- public Editable getText() {
- return (Editable) super.getText();
- }
-
- @Override
- public void setText(CharSequence text, BufferType type) {
- super.setText(text, BufferType.EDITABLE);
- }
-
- /**
- * Convenience for {@link Selection#setSelection(Spannable, int, int)}.
- */
- public void setSelection(int start, int stop) {
- Selection.setSelection(getText(), start, stop);
- }
-
- /**
- * Convenience for {@link Selection#setSelection(Spannable, int)}.
- */
- public void setSelection(int index) {
- Selection.setSelection(getText(), index);
- }
-
- /**
- * Convenience for {@link Selection#selectAll}.
- */
- public void selectAll() {
- Selection.selectAll(getText());
- }
-
- /**
- * Convenience for {@link Selection#extendSelection}.
- */
- public void extendSelection(int index) {
- Selection.extendSelection(getText(), index);
- }
-
- @Override
- public void setEllipsize(TextUtils.TruncateAt ellipsis) {
- if (ellipsis == TextUtils.TruncateAt.MARQUEE) {
- throw new IllegalArgumentException("EditText cannot use the ellipsize mode "
- + "TextUtils.TruncateAt.MARQUEE");
- }
- super.setEllipsize(ellipsis);
- }
-}
diff --git a/core/java/android/widget/ExpandableListAdapter.java b/core/java/android/widget/ExpandableListAdapter.java
deleted file mode 100644
index b75983c..0000000
--- a/core/java/android/widget/ExpandableListAdapter.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.database.DataSetObserver;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * An adapter that links a {@link ExpandableListView} with the underlying
- * data. The implementation of this interface will provide access
- * to the data of the children (categorized by groups), and also instantiate
- * {@link View}s for children and groups.
- */
-public interface ExpandableListAdapter {
- /**
- * @see Adapter#registerDataSetObserver(DataSetObserver)
- */
- void registerDataSetObserver(DataSetObserver observer);
-
- /**
- * @see Adapter#unregisterDataSetObserver(DataSetObserver)
- */
- void unregisterDataSetObserver(DataSetObserver observer);
-
- /**
- * Gets the number of groups.
- *
- * @return the number of groups
- */
- int getGroupCount();
-
- /**
- * Gets the number of children in a specified group.
- *
- * @param groupPosition the position of the group for which the children
- * count should be returned
- * @return the children count in the specified group
- */
- int getChildrenCount(int groupPosition);
-
- /**
- * Gets the data associated with the given group.
- *
- * @param groupPosition the position of the group
- * @return the data child for the specified group
- */
- Object getGroup(int groupPosition);
-
- /**
- * Gets the data associated with the given child within the given group.
- *
- * @param groupPosition the position of the group that the child resides in
- * @param childPosition the position of the child with respect to other
- * children in the group
- * @return the data of the child
- */
- Object getChild(int groupPosition, int childPosition);
-
- /**
- * Gets the ID for the group at the given position. This group ID must be
- * unique across groups. The combined ID (see
- * {@link #getCombinedGroupId(long)}) must be unique across ALL items
- * (groups and all children).
- *
- * @param groupPosition the position of the group for which the ID is wanted
- * @return the ID associated with the group
- */
- long getGroupId(int groupPosition);
-
- /**
- * Gets the ID for the given child within the given group. This ID must be
- * unique across all children within the group. The combined ID (see
- * {@link #getCombinedChildId(long, long)}) must be unique across ALL items
- * (groups and all children).
- *
- * @param groupPosition the position of the group that contains the child
- * @param childPosition the position of the child within the group for which
- * the ID is wanted
- * @return the ID associated with the child
- */
- long getChildId(int groupPosition, int childPosition);
-
- /**
- * Indicates whether the child and group IDs are stable across changes to the
- * underlying data.
- *
- * @return whether or not the same ID always refers to the same object
- * @see Adapter#hasStableIds()
- */
- boolean hasStableIds();
-
- /**
- * Gets a View that displays the given group. This View is only for the
- * group--the Views for the group's children will be fetched using
- * getChildrenView.
- *
- * @param groupPosition the position of the group for which the View is
- * returned
- * @param isExpanded whether the group is expanded or collapsed
- * @param convertView the old view to reuse, if possible. You should check
- * that this view is non-null and of an appropriate type before
- * using. If it is not possible to convert this view to display
- * the correct data, this method can create a new view. It is not
- * guaranteed that the convertView will have been previously
- * created by
- * {@link #getGroupView(int, boolean, View, ViewGroup)}.
- * @param parent the parent that this view will eventually be attached to
- * @return the View corresponding to the group at the specified position
- */
- View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent);
-
- /**
- * Gets a View that displays the data for the given child within the given
- * group.
- *
- * @param groupPosition the position of the group that contains the child
- * @param childPosition the position of the child (for which the View is
- * returned) within the group
- * @param isLastChild Whether the child is the last child within the group
- * @param convertView the old view to reuse, if possible. You should check
- * that this view is non-null and of an appropriate type before
- * using. If it is not possible to convert this view to display
- * the correct data, this method can create a new view. It is not
- * guaranteed that the convertView will have been previously
- * created by
- * {@link #getChildView(int, int, boolean, View, ViewGroup)}.
- * @param parent the parent that this view will eventually be attached to
- * @return the View corresponding to the child at the specified position
- */
- View getChildView(int groupPosition, int childPosition, boolean isLastChild,
- View convertView, ViewGroup parent);
-
- /**
- * Whether the child at the specified position is selectable.
- *
- * @param groupPosition the position of the group that contains the child
- * @param childPosition the position of the child within the group
- * @return whether the child is selectable.
- */
- boolean isChildSelectable(int groupPosition, int childPosition);
-
- /**
- * @see ListAdapter#areAllItemsEnabled()
- */
- boolean areAllItemsEnabled();
-
- /**
- * @see ListAdapter#isEmpty()
- */
- boolean isEmpty();
-
- /**
- * Called when a group is expanded.
- *
- * @param groupPosition The group being expanded.
- */
- void onGroupExpanded(int groupPosition);
-
- /**
- * Called when a group is collapsed.
- *
- * @param groupPosition The group being collapsed.
- */
- void onGroupCollapsed(int groupPosition);
-
- /**
- * Gets an ID for a child that is unique across any item (either group or
- * child) that is in this list. Expandable lists require each item (group or
- * child) to have a unique ID among all children and groups in the list.
- * This method is responsible for returning that unique ID given a child's
- * ID and its group's ID. Furthermore, if {@link #hasStableIds()} is true, the
- * returned ID must be stable as well.
- *
- * @param groupId The ID of the group that contains this child.
- * @param childId The ID of the child.
- * @return The unique (and possibly stable) ID of the child across all
- * groups and children in this list.
- */
- long getCombinedChildId(long groupId, long childId);
-
- /**
- * Gets an ID for a group that is unique across any item (either group or
- * child) that is in this list. Expandable lists require each item (group or
- * child) to have a unique ID among all children and groups in the list.
- * This method is responsible for returning that unique ID given a group's
- * ID. Furthermore, if {@link #hasStableIds()} is true, the returned ID must be
- * stable as well.
- *
- * @param groupId The ID of the group
- * @return The unique (and possibly stable) ID of the group across all
- * groups and children in this list.
- */
- long getCombinedGroupId(long groupId);
-}
diff --git a/core/java/android/widget/ExpandableListConnector.java b/core/java/android/widget/ExpandableListConnector.java
deleted file mode 100644
index ccce7c1..0000000
--- a/core/java/android/widget/ExpandableListConnector.java
+++ /dev/null
@@ -1,1009 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.database.DataSetObserver;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.SystemClock;
-import android.view.View;
-import android.view.ViewGroup;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/*
- * Implementation notes:
- *
- * <p>
- * Terminology:
- * <li> flPos - Flat list position, the position used by ListView
- * <li> gPos - Group position, the position of a group among all the groups
- * <li> cPos - Child position, the position of a child among all the children
- * in a group
- */
-
-/**
- * A {@link BaseAdapter} that provides data/Views in an expandable list (offers
- * features such as collapsing/expanding groups containing children). By
- * itself, this adapter has no data and is a connector to a
- * {@link ExpandableListAdapter} which provides the data.
- * <p>
- * Internally, this connector translates the flat list position that the
- * ListAdapter expects to/from group and child positions that the ExpandableListAdapter
- * expects.
- */
-class ExpandableListConnector extends BaseAdapter implements Filterable {
- /**
- * The ExpandableListAdapter to fetch the data/Views for this expandable list
- */
- private ExpandableListAdapter mExpandableListAdapter;
-
- /**
- * List of metadata for the currently expanded groups. The metadata consists
- * of data essential for efficiently translating between flat list positions
- * and group/child positions. See {@link GroupMetadata}.
- */
- private ArrayList<GroupMetadata> mExpGroupMetadataList;
-
- /** The number of children from all currently expanded groups */
- private int mTotalExpChildrenCount;
-
- /** The maximum number of allowable expanded groups. Defaults to 'no limit' */
- private int mMaxExpGroupCount = Integer.MAX_VALUE;
-
- /** Change observer used to have ExpandableListAdapter changes pushed to us */
- private DataSetObserver mDataSetObserver = new MyDataSetObserver();
-
- /**
- * Constructs the connector
- */
- public ExpandableListConnector(ExpandableListAdapter expandableListAdapter) {
- mExpGroupMetadataList = new ArrayList<GroupMetadata>();
-
- setExpandableListAdapter(expandableListAdapter);
- }
-
- /**
- * Point to the {@link ExpandableListAdapter} that will give us data/Views
- *
- * @param expandableListAdapter the adapter that supplies us with data/Views
- */
- public void setExpandableListAdapter(ExpandableListAdapter expandableListAdapter) {
- if (mExpandableListAdapter != null) {
- mExpandableListAdapter.unregisterDataSetObserver(mDataSetObserver);
- }
-
- mExpandableListAdapter = expandableListAdapter;
- expandableListAdapter.registerDataSetObserver(mDataSetObserver);
- }
-
- /**
- * Translates a flat list position to either a) group pos if the specified
- * flat list position corresponds to a group, or b) child pos if it
- * corresponds to a child. Performs a binary search on the expanded
- * groups list to find the flat list pos if it is an exp group, otherwise
- * finds where the flat list pos fits in between the exp groups.
- *
- * @param flPos the flat list position to be translated
- * @return the group position or child position of the specified flat list
- * position encompassed in a {@link PositionMetadata} object
- * that contains additional useful info for insertion, etc.
- */
- PositionMetadata getUnflattenedPos(final int flPos) {
- /* Keep locally since frequent use */
- final ArrayList<GroupMetadata> egml = mExpGroupMetadataList;
- final int numExpGroups = egml.size();
-
- /* Binary search variables */
- int leftExpGroupIndex = 0;
- int rightExpGroupIndex = numExpGroups - 1;
- int midExpGroupIndex = 0;
- GroupMetadata midExpGm;
-
- if (numExpGroups == 0) {
- /*
- * There aren't any expanded groups (hence no visible children
- * either), so flPos must be a group and its group pos will be the
- * same as its flPos
- */
- return PositionMetadata.obtain(flPos, ExpandableListPosition.GROUP, flPos,
- -1, null, 0);
- }
-
- /*
- * Binary search over the expanded groups to find either the exact
- * expanded group (if we're looking for a group) or the group that
- * contains the child we're looking for. If we are looking for a
- * collapsed group, we will not have a direct match here, but we will
- * find the expanded group just before the group we're searching for (so
- * then we can calculate the group position of the group we're searching
- * for). If there isn't an expanded group prior to the group being
- * searched for, then the group being searched for's group position is
- * the same as the flat list position (since there are no children before
- * it, and all groups before it are collapsed).
- */
- while (leftExpGroupIndex <= rightExpGroupIndex) {
- midExpGroupIndex =
- (rightExpGroupIndex - leftExpGroupIndex) / 2
- + leftExpGroupIndex;
- midExpGm = egml.get(midExpGroupIndex);
-
- if (flPos > midExpGm.lastChildFlPos) {
- /*
- * The flat list position is after the current middle group's
- * last child's flat list position, so search right
- */
- leftExpGroupIndex = midExpGroupIndex + 1;
- } else if (flPos < midExpGm.flPos) {
- /*
- * The flat list position is before the current middle group's
- * flat list position, so search left
- */
- rightExpGroupIndex = midExpGroupIndex - 1;
- } else if (flPos == midExpGm.flPos) {
- /*
- * The flat list position is this middle group's flat list
- * position, so we've found an exact hit
- */
- return PositionMetadata.obtain(flPos, ExpandableListPosition.GROUP,
- midExpGm.gPos, -1, midExpGm, midExpGroupIndex);
- } else if (flPos <= midExpGm.lastChildFlPos
- /* && flPos > midGm.flPos as deduced from previous
- * conditions */) {
- /* The flat list position is a child of the middle group */
-
- /*
- * Subtract the first child's flat list position from the
- * specified flat list pos to get the child's position within
- * the group
- */
- final int childPos = flPos - (midExpGm.flPos + 1);
- return PositionMetadata.obtain(flPos, ExpandableListPosition.CHILD,
- midExpGm.gPos, childPos, midExpGm, midExpGroupIndex);
- }
- }
-
- /*
- * If we've reached here, it means the flat list position must be a
- * group that is not expanded, since otherwise we would have hit it
- * in the above search.
- */
-
-
- /**
- * If we are to expand this group later, where would it go in the
- * mExpGroupMetadataList ?
- */
- int insertPosition = 0;
-
- /** What is its group position in the list of all groups? */
- int groupPos = 0;
-
- /*
- * To figure out exact insertion and prior group positions, we need to
- * determine how we broke out of the binary search. We backtrack
- * to see this.
- */
- if (leftExpGroupIndex > midExpGroupIndex) {
-
- /*
- * This would occur in the first conditional, so the flat list
- * insertion position is after the left group. Also, the
- * leftGroupPos is one more than it should be (since that broke out
- * of our binary search), so we decrement it.
- */
- final GroupMetadata leftExpGm = egml.get(leftExpGroupIndex-1);
-
- insertPosition = leftExpGroupIndex;
-
- /*
- * Sums the number of groups between the prior exp group and this
- * one, and then adds it to the prior group's group pos
- */
- groupPos =
- (flPos - leftExpGm.lastChildFlPos) + leftExpGm.gPos;
- } else if (rightExpGroupIndex < midExpGroupIndex) {
-
- /*
- * This would occur in the second conditional, so the flat list
- * insertion position is before the right group. Also, the
- * rightGroupPos is one less than it should be, so increment it.
- */
- final GroupMetadata rightExpGm = egml.get(++rightExpGroupIndex);
-
- insertPosition = rightExpGroupIndex;
-
- /*
- * Subtracts this group's flat list pos from the group after's flat
- * list position to find out how many groups are in between the two
- * groups. Then, subtracts that number from the group after's group
- * pos to get this group's pos.
- */
- groupPos = rightExpGm.gPos - (rightExpGm.flPos - flPos);
- } else {
- // TODO: clean exit
- throw new RuntimeException("Unknown state");
- }
-
- return PositionMetadata.obtain(flPos, ExpandableListPosition.GROUP, groupPos, -1,
- null, insertPosition);
- }
-
- /**
- * Translates either a group pos or a child pos (+ group it belongs to) to a
- * flat list position. If searching for a child and its group is not expanded, this will
- * return null since the child isn't being shown in the ListView, and hence it has no
- * position.
- *
- * @param pos a {@link ExpandableListPosition} representing either a group position
- * or child position
- * @return the flat list position encompassed in a {@link PositionMetadata}
- * object that contains additional useful info for insertion, etc., or null.
- */
- PositionMetadata getFlattenedPos(final ExpandableListPosition pos) {
- final ArrayList<GroupMetadata> egml = mExpGroupMetadataList;
- final int numExpGroups = egml.size();
-
- /* Binary search variables */
- int leftExpGroupIndex = 0;
- int rightExpGroupIndex = numExpGroups - 1;
- int midExpGroupIndex = 0;
- GroupMetadata midExpGm;
-
- if (numExpGroups == 0) {
- /*
- * There aren't any expanded groups, so flPos must be a group and
- * its flPos will be the same as its group pos. The
- * insert position is 0 (since the list is empty).
- */
- return PositionMetadata.obtain(pos.groupPos, pos.type,
- pos.groupPos, pos.childPos, null, 0);
- }
-
- /*
- * Binary search over the expanded groups to find either the exact
- * expanded group (if we're looking for a group) or the group that
- * contains the child we're looking for.
- */
- while (leftExpGroupIndex <= rightExpGroupIndex) {
- midExpGroupIndex = (rightExpGroupIndex - leftExpGroupIndex)/2 + leftExpGroupIndex;
- midExpGm = egml.get(midExpGroupIndex);
-
- if (pos.groupPos > midExpGm.gPos) {
- /*
- * It's after the current middle group, so search right
- */
- leftExpGroupIndex = midExpGroupIndex + 1;
- } else if (pos.groupPos < midExpGm.gPos) {
- /*
- * It's before the current middle group, so search left
- */
- rightExpGroupIndex = midExpGroupIndex - 1;
- } else if (pos.groupPos == midExpGm.gPos) {
- /*
- * It's this middle group, exact hit
- */
-
- if (pos.type == ExpandableListPosition.GROUP) {
- /* If it's a group, give them this matched group's flPos */
- return PositionMetadata.obtain(midExpGm.flPos, pos.type,
- pos.groupPos, pos.childPos, midExpGm, midExpGroupIndex);
- } else if (pos.type == ExpandableListPosition.CHILD) {
- /* If it's a child, calculate the flat list pos */
- return PositionMetadata.obtain(midExpGm.flPos + pos.childPos
- + 1, pos.type, pos.groupPos, pos.childPos,
- midExpGm, midExpGroupIndex);
- } else {
- return null;
- }
- }
- }
-
- /*
- * If we've reached here, it means there was no match in the expanded
- * groups, so it must be a collapsed group that they're search for
- */
- if (pos.type != ExpandableListPosition.GROUP) {
- /* If it isn't a group, return null */
- return null;
- }
-
- /*
- * To figure out exact insertion and prior group positions, we need to
- * determine how we broke out of the binary search. We backtrack to see
- * this.
- */
- if (leftExpGroupIndex > midExpGroupIndex) {
-
- /*
- * This would occur in the first conditional, so the flat list
- * insertion position is after the left group.
- *
- * The leftGroupPos is one more than it should be (from the binary
- * search loop) so we subtract 1 to get the actual left group. Since
- * the insertion point is AFTER the left group, we keep this +1
- * value as the insertion point
- */
- final GroupMetadata leftExpGm = egml.get(leftExpGroupIndex-1);
- final int flPos =
- leftExpGm.lastChildFlPos
- + (pos.groupPos - leftExpGm.gPos);
-
- return PositionMetadata.obtain(flPos, pos.type, pos.groupPos,
- pos.childPos, null, leftExpGroupIndex);
- } else if (rightExpGroupIndex < midExpGroupIndex) {
-
- /*
- * This would occur in the second conditional, so the flat list
- * insertion position is before the right group. Also, the
- * rightGroupPos is one less than it should be (from binary search
- * loop), so we increment to it.
- */
- final GroupMetadata rightExpGm = egml.get(++rightExpGroupIndex);
- final int flPos =
- rightExpGm.flPos
- - (rightExpGm.gPos - pos.groupPos);
- return PositionMetadata.obtain(flPos, pos.type, pos.groupPos,
- pos.childPos, null, rightExpGroupIndex);
- } else {
- return null;
- }
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return mExpandableListAdapter.areAllItemsEnabled();
- }
-
- @Override
- public boolean isEnabled(int flatListPos) {
- final ExpandableListPosition pos = getUnflattenedPos(flatListPos).position;
-
- boolean retValue;
- if (pos.type == ExpandableListPosition.CHILD) {
- retValue = mExpandableListAdapter.isChildSelectable(pos.groupPos, pos.childPos);
- } else {
- // Groups are always selectable
- retValue = true;
- }
-
- pos.recycle();
-
- return retValue;
- }
-
- public int getCount() {
- /*
- * Total count for the list view is the number groups plus the
- * number of children from currently expanded groups (a value we keep
- * cached in this class)
- */
- return mExpandableListAdapter.getGroupCount() + mTotalExpChildrenCount;
- }
-
- public Object getItem(int flatListPos) {
- final PositionMetadata posMetadata = getUnflattenedPos(flatListPos);
-
- Object retValue;
- if (posMetadata.position.type == ExpandableListPosition.GROUP) {
- retValue = mExpandableListAdapter
- .getGroup(posMetadata.position.groupPos);
- } else if (posMetadata.position.type == ExpandableListPosition.CHILD) {
- retValue = mExpandableListAdapter.getChild(posMetadata.position.groupPos,
- posMetadata.position.childPos);
- } else {
- // TODO: clean exit
- throw new RuntimeException("Flat list position is of unknown type");
- }
-
- posMetadata.recycle();
-
- return retValue;
- }
-
- public long getItemId(int flatListPos) {
- final PositionMetadata posMetadata = getUnflattenedPos(flatListPos);
- final long groupId = mExpandableListAdapter.getGroupId(posMetadata.position.groupPos);
-
- long retValue;
- if (posMetadata.position.type == ExpandableListPosition.GROUP) {
- retValue = mExpandableListAdapter.getCombinedGroupId(groupId);
- } else if (posMetadata.position.type == ExpandableListPosition.CHILD) {
- final long childId = mExpandableListAdapter.getChildId(posMetadata.position.groupPos,
- posMetadata.position.childPos);
- retValue = mExpandableListAdapter.getCombinedChildId(groupId, childId);
- } else {
- // TODO: clean exit
- throw new RuntimeException("Flat list position is of unknown type");
- }
-
- posMetadata.recycle();
-
- return retValue;
- }
-
- public View getView(int flatListPos, View convertView, ViewGroup parent) {
- final PositionMetadata posMetadata = getUnflattenedPos(flatListPos);
-
- View retValue;
- if (posMetadata.position.type == ExpandableListPosition.GROUP) {
- retValue = mExpandableListAdapter.getGroupView(posMetadata.position.groupPos, posMetadata
- .isExpanded(), convertView, parent);
- } else if (posMetadata.position.type == ExpandableListPosition.CHILD) {
- final boolean isLastChild = posMetadata.groupMetadata.lastChildFlPos == flatListPos;
-
- retValue = mExpandableListAdapter.getChildView(posMetadata.position.groupPos,
- posMetadata.position.childPos, isLastChild, convertView, parent);
- } else {
- // TODO: clean exit
- throw new RuntimeException("Flat list position is of unknown type");
- }
-
- posMetadata.recycle();
-
- return retValue;
- }
-
- @Override
- public int getItemViewType(int flatListPos) {
- final ExpandableListPosition pos = getUnflattenedPos(flatListPos).position;
-
- int retValue;
- if (pos.type == ExpandableListPosition.GROUP) {
- retValue = 0;
- } else {
- retValue = 1;
- }
-
- pos.recycle();
-
- return retValue;
- }
-
- @Override
- public int getViewTypeCount() {
- return 2;
- }
-
- @Override
- public boolean hasStableIds() {
- return mExpandableListAdapter.hasStableIds();
- }
-
- /**
- * Traverses the expanded group metadata list and fills in the flat list
- * positions.
- *
- * @param forceChildrenCountRefresh Forces refreshing of the children count
- * for all expanded groups.
- * @param syncGroupPositions Whether to search for the group positions
- * based on the group IDs. This should only be needed when calling
- * this from an onChanged callback.
- */
- @SuppressWarnings("unchecked")
- private void refreshExpGroupMetadataList(boolean forceChildrenCountRefresh,
- boolean syncGroupPositions) {
- final ArrayList<GroupMetadata> egml = mExpGroupMetadataList;
- int egmlSize = egml.size();
- int curFlPos = 0;
-
- /* Update child count as we go through */
- mTotalExpChildrenCount = 0;
-
- if (syncGroupPositions) {
- // We need to check whether any groups have moved positions
- boolean positionsChanged = false;
-
- for (int i = egmlSize - 1; i >= 0; i--) {
- GroupMetadata curGm = egml.get(i);
- int newGPos = findGroupPosition(curGm.gId, curGm.gPos);
- if (newGPos != curGm.gPos) {
- if (newGPos == AdapterView.INVALID_POSITION) {
- // Doh, just remove it from the list of expanded groups
- egml.remove(i);
- egmlSize--;
- }
-
- curGm.gPos = newGPos;
- if (!positionsChanged) positionsChanged = true;
- }
- }
-
- if (positionsChanged) {
- // At least one group changed positions, so re-sort
- Collections.sort(egml);
- }
- }
-
- int gChildrenCount;
- int lastGPos = 0;
- for (int i = 0; i < egmlSize; i++) {
- /* Store in local variable since we'll access freq */
- GroupMetadata curGm = egml.get(i);
-
- /*
- * Get the number of children, try to refrain from calling
- * another class's method unless we have to (so do a subtraction)
- */
- if ((curGm.lastChildFlPos == GroupMetadata.REFRESH) || forceChildrenCountRefresh) {
- gChildrenCount = mExpandableListAdapter.getChildrenCount(curGm.gPos);
- } else {
- /* Num children for this group is its last child's fl pos minus
- * the group's fl pos
- */
- gChildrenCount = curGm.lastChildFlPos - curGm.flPos;
- }
-
- /* Update */
- mTotalExpChildrenCount += gChildrenCount;
-
- /*
- * This skips the collapsed groups and increments the flat list
- * position (for subsequent exp groups) by accounting for the collapsed
- * groups
- */
- curFlPos += (curGm.gPos - lastGPos);
- lastGPos = curGm.gPos;
-
- /* Update the flat list positions, and the current flat list pos */
- curGm.flPos = curFlPos;
- curFlPos += gChildrenCount;
- curGm.lastChildFlPos = curFlPos;
- }
- }
-
- /**
- * Collapse a group in the grouped list view
- *
- * @param groupPos position of the group to collapse
- */
- boolean collapseGroup(int groupPos) {
- PositionMetadata pm = getFlattenedPos(ExpandableListPosition.obtain(
- ExpandableListPosition.GROUP, groupPos, -1, -1));
- if (pm == null) return false;
-
- boolean retValue = collapseGroup(pm);
- pm.recycle();
- return retValue;
- }
-
- boolean collapseGroup(PositionMetadata posMetadata) {
- /*
- * Collapsing requires removal from mExpGroupMetadataList
- */
-
- /*
- * If it is null, it must be already collapsed. This group metadata
- * object should have been set from the search that returned the
- * position metadata object.
- */
- if (posMetadata.groupMetadata == null) return false;
-
- // Remove the group from the list of expanded groups
- mExpGroupMetadataList.remove(posMetadata.groupMetadata);
-
- // Refresh the metadata
- refreshExpGroupMetadataList(false, false);
-
- // Notify of change
- notifyDataSetChanged();
-
- // Give the callback
- mExpandableListAdapter.onGroupCollapsed(posMetadata.groupMetadata.gPos);
-
- return true;
- }
-
- /**
- * Expand a group in the grouped list view
- * @param groupPos the group to be expanded
- */
- boolean expandGroup(int groupPos) {
- PositionMetadata pm = getFlattenedPos(ExpandableListPosition.obtain(
- ExpandableListPosition.GROUP, groupPos, -1, -1));
- boolean retValue = expandGroup(pm);
- pm.recycle();
- return retValue;
- }
-
- boolean expandGroup(PositionMetadata posMetadata) {
- /*
- * Expanding requires insertion into the mExpGroupMetadataList
- */
-
- if (posMetadata.position.groupPos < 0) {
- // TODO clean exit
- throw new RuntimeException("Need group");
- }
-
- if (mMaxExpGroupCount == 0) return false;
-
- // Check to see if it's already expanded
- if (posMetadata.groupMetadata != null) return false;
-
- /* Restrict number of exp groups to mMaxExpGroupCount */
- if (mExpGroupMetadataList.size() >= mMaxExpGroupCount) {
- /* Collapse a group */
- // TODO: Collapse something not on the screen instead of the first one?
- // TODO: Could write overloaded function to take GroupMetadata to collapse
- GroupMetadata collapsedGm = mExpGroupMetadataList.get(0);
-
- int collapsedIndex = mExpGroupMetadataList.indexOf(collapsedGm);
-
- collapseGroup(collapsedGm.gPos);
-
- /* Decrement index if it is after the group we removed */
- if (posMetadata.groupInsertIndex > collapsedIndex) {
- posMetadata.groupInsertIndex--;
- }
- }
-
- GroupMetadata expandedGm = GroupMetadata.obtain(
- GroupMetadata.REFRESH,
- GroupMetadata.REFRESH,
- posMetadata.position.groupPos,
- mExpandableListAdapter.getGroupId(posMetadata.position.groupPos));
-
- mExpGroupMetadataList.add(posMetadata.groupInsertIndex, expandedGm);
-
- // Refresh the metadata
- refreshExpGroupMetadataList(false, false);
-
- // Notify of change
- notifyDataSetChanged();
-
- // Give the callback
- mExpandableListAdapter.onGroupExpanded(expandedGm.gPos);
-
- return true;
- }
-
- /**
- * Whether the given group is currently expanded.
- * @param groupPosition The group to check.
- * @return Whether the group is currently expanded.
- */
- public boolean isGroupExpanded(int groupPosition) {
- GroupMetadata groupMetadata;
- for (int i = mExpGroupMetadataList.size() - 1; i >= 0; i--) {
- groupMetadata = mExpGroupMetadataList.get(i);
-
- if (groupMetadata.gPos == groupPosition) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Set the maximum number of groups that can be expanded at any given time
- */
- public void setMaxExpGroupCount(int maxExpGroupCount) {
- mMaxExpGroupCount = maxExpGroupCount;
- }
-
- ExpandableListAdapter getAdapter() {
- return mExpandableListAdapter;
- }
-
- public Filter getFilter() {
- ExpandableListAdapter adapter = getAdapter();
- if (adapter instanceof Filterable) {
- return ((Filterable) adapter).getFilter();
- } else {
- return null;
- }
- }
-
- ArrayList<GroupMetadata> getExpandedGroupMetadataList() {
- return mExpGroupMetadataList;
- }
-
- void setExpandedGroupMetadataList(ArrayList<GroupMetadata> expandedGroupMetadataList) {
-
- if ((expandedGroupMetadataList == null) || (mExpandableListAdapter == null)) {
- return;
- }
-
- // Make sure our current data set is big enough for the previously
- // expanded groups, if not, ignore this request
- int numGroups = mExpandableListAdapter.getGroupCount();
- for (int i = expandedGroupMetadataList.size() - 1; i >= 0; i--) {
- if (expandedGroupMetadataList.get(i).gPos >= numGroups) {
- // Doh, for some reason the client doesn't have some of the groups
- return;
- }
- }
-
- mExpGroupMetadataList = expandedGroupMetadataList;
- refreshExpGroupMetadataList(true, false);
- }
-
- @Override
- public boolean isEmpty() {
- ExpandableListAdapter adapter = getAdapter();
- return adapter != null ? adapter.isEmpty() : true;
- }
-
- /**
- * Searches the expandable list adapter for a group position matching the
- * given group ID. The search starts at the given seed position and then
- * alternates between moving up and moving down until 1) we find the right
- * position, or 2) we run out of time, or 3) we have looked at every
- * position
- *
- * @return Position of the row that matches the given row ID, or
- * {@link AdapterView#INVALID_POSITION} if it can't be found
- * @see AdapterView#findSyncPosition()
- */
- int findGroupPosition(long groupIdToMatch, int seedGroupPosition) {
- int count = mExpandableListAdapter.getGroupCount();
-
- if (count == 0) {
- return AdapterView.INVALID_POSITION;
- }
-
- // If there isn't a selection don't hunt for it
- if (groupIdToMatch == AdapterView.INVALID_ROW_ID) {
- return AdapterView.INVALID_POSITION;
- }
-
- // Pin seed to reasonable values
- seedGroupPosition = Math.max(0, seedGroupPosition);
- seedGroupPosition = Math.min(count - 1, seedGroupPosition);
-
- long endTime = SystemClock.uptimeMillis() + AdapterView.SYNC_MAX_DURATION_MILLIS;
-
- long rowId;
-
- // first position scanned so far
- int first = seedGroupPosition;
-
- // last position scanned so far
- int last = seedGroupPosition;
-
- // True if we should move down on the next iteration
- boolean next = false;
-
- // True when we have looked at the first item in the data
- boolean hitFirst;
-
- // True when we have looked at the last item in the data
- boolean hitLast;
-
- // Get the item ID locally (instead of getItemIdAtPosition), so
- // we need the adapter
- ExpandableListAdapter adapter = getAdapter();
- if (adapter == null) {
- return AdapterView.INVALID_POSITION;
- }
-
- while (SystemClock.uptimeMillis() <= endTime) {
- rowId = adapter.getGroupId(seedGroupPosition);
- if (rowId == groupIdToMatch) {
- // Found it!
- return seedGroupPosition;
- }
-
- hitLast = last == count - 1;
- hitFirst = first == 0;
-
- if (hitLast && hitFirst) {
- // Looked at everything
- break;
- }
-
- if (hitFirst || (next && !hitLast)) {
- // Either we hit the top, or we are trying to move down
- last++;
- seedGroupPosition = last;
- // Try going up next time
- next = false;
- } else if (hitLast || (!next && !hitFirst)) {
- // Either we hit the bottom, or we are trying to move up
- first--;
- seedGroupPosition = first;
- // Try going down next time
- next = true;
- }
-
- }
-
- return AdapterView.INVALID_POSITION;
- }
-
- protected class MyDataSetObserver extends DataSetObserver {
- @Override
- public void onChanged() {
- refreshExpGroupMetadataList(true, true);
-
- notifyDataSetChanged();
- }
-
- @Override
- public void onInvalidated() {
- refreshExpGroupMetadataList(true, true);
-
- notifyDataSetInvalidated();
- }
- }
-
- /**
- * Metadata about an expanded group to help convert from a flat list
- * position to either a) group position for groups, or b) child position for
- * children
- */
- static class GroupMetadata implements Parcelable, Comparable {
- final static int REFRESH = -1;
-
- /** This group's flat list position */
- int flPos;
-
- /* firstChildFlPos isn't needed since it's (flPos + 1) */
-
- /**
- * This group's last child's flat list position, so basically
- * the range of this group in the flat list
- */
- int lastChildFlPos;
-
- /**
- * This group's group position
- */
- int gPos;
-
- /**
- * This group's id
- */
- long gId;
-
- private GroupMetadata() {
- }
-
- static GroupMetadata obtain(int flPos, int lastChildFlPos, int gPos, long gId) {
- GroupMetadata gm = new GroupMetadata();
- gm.flPos = flPos;
- gm.lastChildFlPos = lastChildFlPos;
- gm.gPos = gPos;
- gm.gId = gId;
- return gm;
- }
-
- public int compareTo(Object another) {
- if (another == null || !(another instanceof GroupMetadata)) {
- throw new ClassCastException();
- }
-
- return gPos - ((GroupMetadata) another).gPos;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(flPos);
- dest.writeInt(lastChildFlPos);
- dest.writeInt(gPos);
- dest.writeLong(gId);
- }
-
- public static final Parcelable.Creator<GroupMetadata> CREATOR =
- new Parcelable.Creator<GroupMetadata>() {
-
- public GroupMetadata createFromParcel(Parcel in) {
- GroupMetadata gm = GroupMetadata.obtain(
- in.readInt(),
- in.readInt(),
- in.readInt(),
- in.readLong());
- return gm;
- }
-
- public GroupMetadata[] newArray(int size) {
- return new GroupMetadata[size];
- }
- };
-
- }
-
- /**
- * Data type that contains an expandable list position (can refer to either a group
- * or child) and some extra information regarding referred item (such as
- * where to insert into the flat list, etc.)
- */
- static public class PositionMetadata {
-
- private static final int MAX_POOL_SIZE = 5;
- private static ArrayList<PositionMetadata> sPool =
- new ArrayList<PositionMetadata>(MAX_POOL_SIZE);
-
- /** Data type to hold the position and its type (child/group) */
- public ExpandableListPosition position;
-
- /**
- * Link back to the expanded GroupMetadata for this group. Useful for
- * removing the group from the list of expanded groups inside the
- * connector when we collapse the group, and also as a check to see if
- * the group was expanded or collapsed (this will be null if the group
- * is collapsed since we don't keep that group's metadata)
- */
- public GroupMetadata groupMetadata;
-
- /**
- * For groups that are collapsed, we use this as the index (in
- * mExpGroupMetadataList) to insert this group when we are expanding
- * this group.
- */
- public int groupInsertIndex;
-
- private void resetState() {
- position = null;
- groupMetadata = null;
- groupInsertIndex = 0;
- }
-
- /**
- * Use {@link #obtain(int, int, int, int, GroupMetadata, int)}
- */
- private PositionMetadata() {
- }
-
- static PositionMetadata obtain(int flatListPos, int type, int groupPos,
- int childPos, GroupMetadata groupMetadata, int groupInsertIndex) {
- PositionMetadata pm = getRecycledOrCreate();
- pm.position = ExpandableListPosition.obtain(type, groupPos, childPos, flatListPos);
- pm.groupMetadata = groupMetadata;
- pm.groupInsertIndex = groupInsertIndex;
- return pm;
- }
-
- private static PositionMetadata getRecycledOrCreate() {
- PositionMetadata pm;
- synchronized (sPool) {
- if (sPool.size() > 0) {
- pm = sPool.remove(0);
- } else {
- return new PositionMetadata();
- }
- }
- pm.resetState();
- return pm;
- }
-
- public void recycle() {
- synchronized (sPool) {
- if (sPool.size() < MAX_POOL_SIZE) {
- sPool.add(this);
- }
- }
- }
-
- /**
- * Checks whether the group referred to in this object is expanded,
- * or not (at the time this object was created)
- *
- * @return whether the group at groupPos is expanded or not
- */
- public boolean isExpanded() {
- return groupMetadata != null;
- }
- }
-}
diff --git a/core/java/android/widget/ExpandableListPosition.java b/core/java/android/widget/ExpandableListPosition.java
deleted file mode 100644
index e8d6113..0000000
--- a/core/java/android/widget/ExpandableListPosition.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import java.util.ArrayList;
-
-/**
- * ExpandableListPosition can refer to either a group's position or a child's
- * position. Referring to a child's position requires both a group position (the
- * group containing the child) and a child position (the child's position within
- * that group). To create objects, use {@link #obtainChildPosition(int, int)} or
- * {@link #obtainGroupPosition(int)}.
- */
-class ExpandableListPosition {
-
- private static final int MAX_POOL_SIZE = 5;
- private static ArrayList<ExpandableListPosition> sPool =
- new ArrayList<ExpandableListPosition>(MAX_POOL_SIZE);
-
- /**
- * This data type represents a child position
- */
- public final static int CHILD = 1;
-
- /**
- * This data type represents a group position
- */
- public final static int GROUP = 2;
-
- /**
- * The position of either the group being referred to, or the parent
- * group of the child being referred to
- */
- public int groupPos;
-
- /**
- * The position of the child within its parent group
- */
- public int childPos;
-
- /**
- * The position of the item in the flat list (optional, used internally when
- * the corresponding flat list position for the group or child is known)
- */
- int flatListPos;
-
- /**
- * What type of position this ExpandableListPosition represents
- */
- public int type;
-
- private void resetState() {
- groupPos = 0;
- childPos = 0;
- flatListPos = 0;
- type = 0;
- }
-
- private ExpandableListPosition() {
- }
-
- long getPackedPosition() {
- if (type == CHILD) return ExpandableListView.getPackedPositionForChild(groupPos, childPos);
- else return ExpandableListView.getPackedPositionForGroup(groupPos);
- }
-
- static ExpandableListPosition obtainGroupPosition(int groupPosition) {
- return obtain(GROUP, groupPosition, 0, 0);
- }
-
- static ExpandableListPosition obtainChildPosition(int groupPosition, int childPosition) {
- return obtain(CHILD, groupPosition, childPosition, 0);
- }
-
- static ExpandableListPosition obtainPosition(long packedPosition) {
- if (packedPosition == ExpandableListView.PACKED_POSITION_VALUE_NULL) {
- return null;
- }
-
- ExpandableListPosition elp = getRecycledOrCreate();
- elp.groupPos = ExpandableListView.getPackedPositionGroup(packedPosition);
- if (ExpandableListView.getPackedPositionType(packedPosition) ==
- ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
- elp.type = CHILD;
- elp.childPos = ExpandableListView.getPackedPositionChild(packedPosition);
- } else {
- elp.type = GROUP;
- }
- return elp;
- }
-
- static ExpandableListPosition obtain(int type, int groupPos, int childPos, int flatListPos) {
- ExpandableListPosition elp = getRecycledOrCreate();
- elp.type = type;
- elp.groupPos = groupPos;
- elp.childPos = childPos;
- elp.flatListPos = flatListPos;
- return elp;
- }
-
- private static ExpandableListPosition getRecycledOrCreate() {
- ExpandableListPosition elp;
- synchronized (sPool) {
- if (sPool.size() > 0) {
- elp = sPool.remove(0);
- } else {
- return new ExpandableListPosition();
- }
- }
- elp.resetState();
- return elp;
- }
-
- public void recycle() {
- synchronized (sPool) {
- if (sPool.size() < MAX_POOL_SIZE) {
- sPool.add(this);
- }
- }
- }
-}
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
deleted file mode 100644
index 0fc8f49..0000000
--- a/core/java/android/widget/ExpandableListView.java
+++ /dev/null
@@ -1,1094 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.ColorDrawable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.view.ContextMenu;
-import android.view.SoundEffectConstants;
-import android.view.View;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.widget.ExpandableListConnector.PositionMetadata;
-
-/**
- * A view that shows items in a vertically scrolling two-level list. This
- * differs from the {@link ListView} by allowing two levels: groups which can
- * individually be expanded to show its children. The items come from the
- * {@link ExpandableListAdapter} associated with this view.
- * <p>
- * Expandable lists are able to show an indicator beside each item to display
- * the item's current state (the states are usually one of expanded group,
- * collapsed group, child, or last child). Use
- * {@link #setChildIndicator(Drawable)} or {@link #setGroupIndicator(Drawable)}
- * (or the corresponding XML attributes) to set these indicators (see the docs
- * for each method to see additional state that each Drawable can have). The
- * default style for an {@link ExpandableListView} provides indicators which
- * will be shown next to Views given to the {@link ExpandableListView}. The
- * layouts android.R.layout.simple_expandable_list_item_1 and
- * android.R.layout.simple_expandable_list_item_2 (which should be used with
- * {@link SimpleCursorTreeAdapter}) contain the preferred position information
- * for indicators.
- * <p>
- * The context menu information set by an {@link ExpandableListView} will be a
- * {@link ExpandableListContextMenuInfo} object with
- * {@link ExpandableListContextMenuInfo#packedPosition} being a packed position
- * that can be used with {@link #getPackedPositionType(long)} and the other
- * similar methods.
- * <p>
- * <em><b>Note:</b></em> You cannot use the value <code>wrap_content</code>
- * for the <code>android:layout_height</code> attribute of a
- * ExpandableListView in XML if the parent's size is also not strictly specified
- * (for example, if the parent were ScrollView you could not specify
- * wrap_content since it also can be any length. However, you can use
- * wrap_content if the ExpandableListView parent has a specific size, such as
- * 100 pixels.
- *
- * @attr ref android.R.styleable#ExpandableListView_groupIndicator
- * @attr ref android.R.styleable#ExpandableListView_indicatorLeft
- * @attr ref android.R.styleable#ExpandableListView_indicatorRight
- * @attr ref android.R.styleable#ExpandableListView_childIndicator
- * @attr ref android.R.styleable#ExpandableListView_childIndicatorLeft
- * @attr ref android.R.styleable#ExpandableListView_childIndicatorRight
- * @attr ref android.R.styleable#ExpandableListView_childDivider
- */
-public class ExpandableListView extends ListView {
-
- /**
- * The packed position represents a group.
- */
- public static final int PACKED_POSITION_TYPE_GROUP = 0;
-
- /**
- * The packed position represents a child.
- */
- public static final int PACKED_POSITION_TYPE_CHILD = 1;
-
- /**
- * The packed position represents a neither/null/no preference.
- */
- public static final int PACKED_POSITION_TYPE_NULL = 2;
-
- /**
- * The value for a packed position that represents neither/null/no
- * preference. This value is not otherwise possible since a group type
- * (first bit 0) should not have a child position filled.
- */
- public static final long PACKED_POSITION_VALUE_NULL = 0x00000000FFFFFFFFL;
-
- /** The mask (in packed position representation) for the child */
- private static final long PACKED_POSITION_MASK_CHILD = 0x00000000FFFFFFFFL;
-
- /** The mask (in packed position representation) for the group */
- private static final long PACKED_POSITION_MASK_GROUP = 0x7FFFFFFF00000000L;
-
- /** The mask (in packed position representation) for the type */
- private static final long PACKED_POSITION_MASK_TYPE = 0x8000000000000000L;
-
- /** The shift amount (in packed position representation) for the group */
- private static final long PACKED_POSITION_SHIFT_GROUP = 32;
-
- /** The shift amount (in packed position representation) for the type */
- private static final long PACKED_POSITION_SHIFT_TYPE = 63;
-
- /** The mask (in integer child position representation) for the child */
- private static final long PACKED_POSITION_INT_MASK_CHILD = 0xFFFFFFFF;
-
- /** The mask (in integer group position representation) for the group */
- private static final long PACKED_POSITION_INT_MASK_GROUP = 0x7FFFFFFF;
-
- /** Serves as the glue/translator between a ListView and an ExpandableListView */
- private ExpandableListConnector mConnector;
-
- /** Gives us Views through group+child positions */
- private ExpandableListAdapter mAdapter;
-
- /** Left bound for drawing the indicator. */
- private int mIndicatorLeft;
-
- /** Right bound for drawing the indicator. */
- private int mIndicatorRight;
-
- /**
- * Left bound for drawing the indicator of a child. Value of
- * {@link #CHILD_INDICATOR_INHERIT} means use mIndicatorLeft.
- */
- private int mChildIndicatorLeft;
-
- /**
- * Right bound for drawing the indicator of a child. Value of
- * {@link #CHILD_INDICATOR_INHERIT} means use mIndicatorRight.
- */
- private int mChildIndicatorRight;
-
- /**
- * Denotes when a child indicator should inherit this bound from the generic
- * indicator bounds
- */
- public static final int CHILD_INDICATOR_INHERIT = -1;
-
- /** The indicator drawn next to a group. */
- private Drawable mGroupIndicator;
-
- /** The indicator drawn next to a child. */
- private Drawable mChildIndicator;
-
- private static final int[] EMPTY_STATE_SET = {};
-
- /** State indicating the group is expanded. */
- private static final int[] GROUP_EXPANDED_STATE_SET =
- {R.attr.state_expanded};
-
- /** State indicating the group is empty (has no children). */
- private static final int[] GROUP_EMPTY_STATE_SET =
- {R.attr.state_empty};
-
- /** State indicating the group is expanded and empty (has no children). */
- private static final int[] GROUP_EXPANDED_EMPTY_STATE_SET =
- {R.attr.state_expanded, R.attr.state_empty};
-
- /** States for the group where the 0th bit is expanded and 1st bit is empty. */
- private static final int[][] GROUP_STATE_SETS = {
- EMPTY_STATE_SET, // 00
- GROUP_EXPANDED_STATE_SET, // 01
- GROUP_EMPTY_STATE_SET, // 10
- GROUP_EXPANDED_EMPTY_STATE_SET // 11
- };
-
- /** State indicating the child is the last within its group. */
- private static final int[] CHILD_LAST_STATE_SET =
- {R.attr.state_last};
-
- /** Drawable to be used as a divider when it is adjacent to any children */
- private Drawable mChildDivider;
- private boolean mClipChildDivider;
-
- // Bounds of the indicator to be drawn
- private final Rect mIndicatorRect = new Rect();
-
- public ExpandableListView(Context context) {
- this(context, null);
- }
-
- public ExpandableListView(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.expandableListViewStyle);
- }
-
- public ExpandableListView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a =
- context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ExpandableListView, defStyle,
- 0);
-
- mGroupIndicator = a
- .getDrawable(com.android.internal.R.styleable.ExpandableListView_groupIndicator);
- mChildIndicator = a
- .getDrawable(com.android.internal.R.styleable.ExpandableListView_childIndicator);
- mIndicatorLeft = a
- .getDimensionPixelSize(com.android.internal.R.styleable.ExpandableListView_indicatorLeft, 0);
- mIndicatorRight = a
- .getDimensionPixelSize(com.android.internal.R.styleable.ExpandableListView_indicatorRight, 0);
- mChildIndicatorLeft = a.getDimensionPixelSize(
- com.android.internal.R.styleable.ExpandableListView_childIndicatorLeft, CHILD_INDICATOR_INHERIT);
- mChildIndicatorRight = a.getDimensionPixelSize(
- com.android.internal.R.styleable.ExpandableListView_childIndicatorRight, CHILD_INDICATOR_INHERIT);
- mChildDivider = a.getDrawable(com.android.internal.R.styleable.ExpandableListView_childDivider);
-
- a.recycle();
- }
-
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- // Draw children, etc.
- super.dispatchDraw(canvas);
-
- // If we have any indicators to draw, we do it here
- if ((mChildIndicator == null) && (mGroupIndicator == null)) {
- return;
- }
-
- int saveCount = 0;
- final boolean clipToPadding = (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;
- if (clipToPadding) {
- saveCount = canvas.save();
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
- canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop,
- scrollX + mRight - mLeft - mPaddingRight,
- scrollY + mBottom - mTop - mPaddingBottom);
- }
-
- final int headerViewsCount = getHeaderViewsCount();
-
- final int lastChildFlPos = mItemCount - getFooterViewsCount() - headerViewsCount - 1;
-
- final int myB = mBottom;
-
- PositionMetadata pos;
- View item;
- Drawable indicator;
- int t, b;
-
- // Start at a value that is neither child nor group
- int lastItemType = ~(ExpandableListPosition.CHILD | ExpandableListPosition.GROUP);
-
- final Rect indicatorRect = mIndicatorRect;
-
- // The "child" mentioned in the following two lines is this
- // View's child, not referring to an expandable list's
- // notion of a child (as opposed to a group)
- final int childCount = getChildCount();
- for (int i = 0, childFlPos = mFirstPosition - headerViewsCount; i < childCount;
- i++, childFlPos++) {
-
- if (childFlPos < 0) {
- // This child is header
- continue;
- } else if (childFlPos > lastChildFlPos) {
- // This child is footer, so are all subsequent children
- break;
- }
-
- item = getChildAt(i);
- t = item.getTop();
- b = item.getBottom();
-
- // This item isn't on the screen
- if ((b < 0) || (t > myB)) continue;
-
- // Get more expandable list-related info for this item
- pos = mConnector.getUnflattenedPos(childFlPos);
-
- // If this item type and the previous item type are different, then we need to change
- // the left & right bounds
- if (pos.position.type != lastItemType) {
- if (pos.position.type == ExpandableListPosition.CHILD) {
- indicatorRect.left = (mChildIndicatorLeft == CHILD_INDICATOR_INHERIT) ?
- mIndicatorLeft : mChildIndicatorLeft;
- indicatorRect.right = (mChildIndicatorRight == CHILD_INDICATOR_INHERIT) ?
- mIndicatorRight : mChildIndicatorRight;
- } else {
- indicatorRect.left = mIndicatorLeft;
- indicatorRect.right = mIndicatorRight;
- }
-
- lastItemType = pos.position.type;
- }
-
- if (indicatorRect.left != indicatorRect.right) {
- // Use item's full height + the divider height
- if (mStackFromBottom) {
- // See ListView#dispatchDraw
- indicatorRect.top = t;// - mDividerHeight;
- indicatorRect.bottom = b;
- } else {
- indicatorRect.top = t;
- indicatorRect.bottom = b;// + mDividerHeight;
- }
-
- // Get the indicator (with its state set to the item's state)
- indicator = getIndicator(pos);
- if (indicator != null) {
- // Draw the indicator
- indicator.setBounds(indicatorRect);
- indicator.draw(canvas);
- }
- }
-
- pos.recycle();
- }
-
- if (clipToPadding) {
- canvas.restoreToCount(saveCount);
- }
- }
-
- /**
- * Gets the indicator for the item at the given position. If the indicator
- * is stateful, the state will be given to the indicator.
- *
- * @param pos The flat list position of the item whose indicator
- * should be returned.
- * @return The indicator in the proper state.
- */
- private Drawable getIndicator(PositionMetadata pos) {
- Drawable indicator;
-
- if (pos.position.type == ExpandableListPosition.GROUP) {
- indicator = mGroupIndicator;
-
- if (indicator != null && indicator.isStateful()) {
- // Empty check based on availability of data. If the groupMetadata isn't null,
- // we do a check on it. Otherwise, the group is collapsed so we consider it
- // empty for performance reasons.
- boolean isEmpty = (pos.groupMetadata == null) ||
- (pos.groupMetadata.lastChildFlPos == pos.groupMetadata.flPos);
-
- final int stateSetIndex =
- (pos.isExpanded() ? 1 : 0) | // Expanded?
- (isEmpty ? 2 : 0); // Empty?
- indicator.setState(GROUP_STATE_SETS[stateSetIndex]);
- }
- } else {
- indicator = mChildIndicator;
-
- if (indicator != null && indicator.isStateful()) {
- // No need for a state sets array for the child since it only has two states
- final int stateSet[] = pos.position.flatListPos == pos.groupMetadata.lastChildFlPos
- ? CHILD_LAST_STATE_SET
- : EMPTY_STATE_SET;
- indicator.setState(stateSet);
- }
- }
-
- return indicator;
- }
-
- /**
- * Sets the drawable that will be drawn adjacent to every child in the list. This will
- * be drawn using the same height as the normal divider ({@link #setDivider(Drawable)}) or
- * if it does not have an intrinsic height, the height set by {@link #setDividerHeight(int)}.
- *
- * @param childDivider The drawable to use.
- */
- public void setChildDivider(Drawable childDivider) {
- mChildDivider = childDivider;
- mClipChildDivider = childDivider != null && childDivider instanceof ColorDrawable;
- }
-
- @Override
- void drawDivider(Canvas canvas, Rect bounds, int childIndex) {
- int flatListPosition = childIndex + mFirstPosition;
-
- // Only proceed as possible child if the divider isn't above all items (if it is above
- // all items, then the item below it has to be a group)
- if (flatListPosition >= 0) {
- PositionMetadata pos = mConnector.getUnflattenedPos(flatListPosition);
- // If this item is a child, or it is a non-empty group that is expanded
- if ((pos.position.type == ExpandableListPosition.CHILD) || (pos.isExpanded() &&
- pos.groupMetadata.lastChildFlPos != pos.groupMetadata.flPos)) {
- // These are the cases where we draw the child divider
- final Drawable divider = mChildDivider;
- final boolean clip = mClipChildDivider;
- if (!clip) {
- divider.setBounds(bounds);
- } else {
- canvas.save();
- canvas.clipRect(bounds);
- }
- divider.draw(canvas);
- if (clip) {
- canvas.restore();
- }
- pos.recycle();
- return;
- }
- pos.recycle();
- }
-
- // Otherwise draw the default divider
- super.drawDivider(canvas, bounds, flatListPosition);
- }
-
- /**
- * This overloaded method should not be used, instead use
- * {@link #setAdapter(ExpandableListAdapter)}.
- * <p>
- * {@inheritDoc}
- */
- @Override
- public void setAdapter(ListAdapter adapter) {
- throw new RuntimeException(
- "For ExpandableListView, use setAdapter(ExpandableListAdapter) instead of " +
- "setAdapter(ListAdapter)");
- }
-
- /**
- * This method should not be used, use {@link #getExpandableListAdapter()}.
- */
- @Override
- public ListAdapter getAdapter() {
- /*
- * The developer should never really call this method on an
- * ExpandableListView, so it would be nice to throw a RuntimeException,
- * but AdapterView calls this
- */
- return super.getAdapter();
- }
-
- /**
- * Register a callback to be invoked when an item has been clicked and the
- * caller prefers to receive a ListView-style position instead of a group
- * and/or child position. In most cases, the caller should use
- * {@link #setOnGroupClickListener} and/or {@link #setOnChildClickListener}.
- * <p />
- * {@inheritDoc}
- */
- @Override
- public void setOnItemClickListener(OnItemClickListener l) {
- super.setOnItemClickListener(l);
- }
-
- /**
- * Sets the adapter that provides data to this view.
- * @param adapter The adapter that provides data to this view.
- */
- public void setAdapter(ExpandableListAdapter adapter) {
- // Set member variable
- mAdapter = adapter;
-
- if (adapter != null) {
- // Create the connector
- mConnector = new ExpandableListConnector(adapter);
- } else {
- mConnector = null;
- }
-
- // Link the ListView (superclass) to the expandable list data through the connector
- super.setAdapter(mConnector);
- }
-
- /**
- * Gets the adapter that provides data to this view.
- * @return The adapter that provides data to this view.
- */
- public ExpandableListAdapter getExpandableListAdapter() {
- return mAdapter;
- }
-
- @Override
- public boolean performItemClick(View v, int position, long id) {
- // Ignore clicks in header/footers
- final int headerViewsCount = getHeaderViewsCount();
- final int footerViewsStart = mItemCount - getFooterViewsCount();
-
- if (position < headerViewsCount || position >= footerViewsStart) {
- // Clicked on a header/footer, so ignore pass it on to super
- return super.performItemClick(v, position, id);
- }
-
- // Internally handle the item click
- return handleItemClick(v, position - headerViewsCount, id);
- }
-
- /**
- * This will either expand/collapse groups (if a group was clicked) or pass
- * on the click to the proper child (if a child was clicked)
- *
- * @param position The flat list position. This has already been factored to
- * remove the header/footer.
- * @param id The ListAdapter ID, not the group or child ID.
- */
- boolean handleItemClick(View v, int position, long id) {
- final PositionMetadata posMetadata = mConnector.getUnflattenedPos(position);
-
- id = getChildOrGroupId(posMetadata.position);
-
- boolean returnValue;
- if (posMetadata.position.type == ExpandableListPosition.GROUP) {
- /* It's a group, so handle collapsing/expanding */
-
- if (posMetadata.isExpanded()) {
- /* Collapse it */
- mConnector.collapseGroup(posMetadata);
-
- playSoundEffect(SoundEffectConstants.CLICK);
-
- if (mOnGroupCollapseListener != null) {
- mOnGroupCollapseListener.onGroupCollapse(posMetadata.position.groupPos);
- }
-
- } else {
- /* It's a group click, so pass on event */
- if (mOnGroupClickListener != null) {
- if (mOnGroupClickListener.onGroupClick(this, v,
- posMetadata.position.groupPos, id)) {
- posMetadata.recycle();
- return true;
- }
- }
-
- /* Expand it */
- mConnector.expandGroup(posMetadata);
-
- playSoundEffect(SoundEffectConstants.CLICK);
-
- if (mOnGroupExpandListener != null) {
- mOnGroupExpandListener.onGroupExpand(posMetadata.position.groupPos);
- }
- }
-
- returnValue = true;
- } else {
- /* It's a child, so pass on event */
- if (mOnChildClickListener != null) {
- playSoundEffect(SoundEffectConstants.CLICK);
- return mOnChildClickListener.onChildClick(this, v, posMetadata.position.groupPos,
- posMetadata.position.childPos, id);
- }
-
- returnValue = false;
- }
-
- posMetadata.recycle();
-
- return returnValue;
- }
-
- /**
- * Expand a group in the grouped list view
- *
- * @param groupPos the group to be expanded
- * @return True if the group was expanded, false otherwise (if the group
- * was already expanded, this will return false)
- */
- public boolean expandGroup(int groupPos) {
- boolean retValue = mConnector.expandGroup(groupPos);
-
- if (mOnGroupExpandListener != null) {
- mOnGroupExpandListener.onGroupExpand(groupPos);
- }
-
- return retValue;
- }
-
- /**
- * Collapse a group in the grouped list view
- *
- * @param groupPos position of the group to collapse
- * @return True if the group was collapsed, false otherwise (if the group
- * was already collapsed, this will return false)
- */
- public boolean collapseGroup(int groupPos) {
- boolean retValue = mConnector.collapseGroup(groupPos);
-
- if (mOnGroupCollapseListener != null) {
- mOnGroupCollapseListener.onGroupCollapse(groupPos);
- }
-
- return retValue;
- }
-
- /** Used for being notified when a group is collapsed */
- public interface OnGroupCollapseListener {
- /**
- * Callback method to be invoked when a group in this expandable list has
- * been collapsed.
- *
- * @param groupPosition The group position that was collapsed
- */
- void onGroupCollapse(int groupPosition);
- }
-
- private OnGroupCollapseListener mOnGroupCollapseListener;
-
- public void setOnGroupCollapseListener(
- OnGroupCollapseListener onGroupCollapseListener) {
- mOnGroupCollapseListener = onGroupCollapseListener;
- }
-
- /** Used for being notified when a group is expanded */
- public interface OnGroupExpandListener {
- /**
- * Callback method to be invoked when a group in this expandable list has
- * been expanded.
- *
- * @param groupPosition The group position that was expanded
- */
- void onGroupExpand(int groupPosition);
- }
-
- private OnGroupExpandListener mOnGroupExpandListener;
-
- public void setOnGroupExpandListener(
- OnGroupExpandListener onGroupExpandListener) {
- mOnGroupExpandListener = onGroupExpandListener;
- }
-
- /**
- * Interface definition for a callback to be invoked when a group in this
- * expandable list has been clicked.
- */
- public interface OnGroupClickListener {
- /**
- * Callback method to be invoked when a group in this expandable list has
- * been clicked.
- *
- * @param parent The ExpandableListConnector where the click happened
- * @param v The view within the expandable list/ListView that was clicked
- * @param groupPosition The group position that was clicked
- * @param id The row id of the group that was clicked
- * @return True if the click was handled
- */
- boolean onGroupClick(ExpandableListView parent, View v, int groupPosition,
- long id);
- }
-
- private OnGroupClickListener mOnGroupClickListener;
-
- public void setOnGroupClickListener(OnGroupClickListener onGroupClickListener) {
- mOnGroupClickListener = onGroupClickListener;
- }
-
- /**
- * Interface definition for a callback to be invoked when a child in this
- * expandable list has been clicked.
- */
- public interface OnChildClickListener {
- /**
- * Callback method to be invoked when a child in this expandable list has
- * been clicked.
- *
- * @param parent The ExpandableListView where the click happened
- * @param v The view within the expandable list/ListView that was clicked
- * @param groupPosition The group position that contains the child that
- * was clicked
- * @param childPosition The child position within the group
- * @param id The row id of the child that was clicked
- * @return True if the click was handled
- */
- boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
- int childPosition, long id);
- }
-
- private OnChildClickListener mOnChildClickListener;
-
- public void setOnChildClickListener(OnChildClickListener onChildClickListener) {
- mOnChildClickListener = onChildClickListener;
- }
-
- /**
- * Converts a flat list position (the raw position of an item (child or
- * group) in the list) to an group and/or child position (represented in a
- * packed position). This is useful in situations where the caller needs to
- * use the underlying {@link ListView}'s methods. Use
- * {@link ExpandableListView#getPackedPositionType} ,
- * {@link ExpandableListView#getPackedPositionChild},
- * {@link ExpandableListView#getPackedPositionGroup} to unpack.
- *
- * @param flatListPosition The flat list position to be converted.
- * @return The group and/or child position for the given flat list position
- * in packed position representation.
- */
- public long getExpandableListPosition(int flatListPosition) {
- PositionMetadata pm = mConnector.getUnflattenedPos(flatListPosition);
- long packedPos = pm.position.getPackedPosition();
- pm.recycle();
- return packedPos;
- }
-
- /**
- * Converts a group and/or child position to a flat list position. This is
- * useful in situations where the caller needs to use the underlying
- * {@link ListView}'s methods.
- *
- * @param packedPosition The group and/or child positions to be converted in
- * packed position representation. Use
- * {@link #getPackedPositionForChild(int, int)} or
- * {@link #getPackedPositionForGroup(int)}.
- * @return The flat list position for the given child or group.
- */
- public int getFlatListPosition(long packedPosition) {
- PositionMetadata pm = mConnector.getFlattenedPos(ExpandableListPosition
- .obtainPosition(packedPosition));
- int retValue = pm.position.flatListPos;
- pm.recycle();
- return retValue;
- }
-
- /**
- * Gets the position of the currently selected group or child (along with
- * its type). Can return {@link #PACKED_POSITION_VALUE_NULL} if no selection.
- *
- * @return A packed position containing the currently selected group or
- * child's position and type. #PACKED_POSITION_VALUE_NULL if no selection.
- */
- public long getSelectedPosition() {
- final int selectedPos = getSelectedItemPosition();
- if (selectedPos == -1) return PACKED_POSITION_VALUE_NULL;
-
- return getExpandableListPosition(selectedPos);
- }
-
- /**
- * Gets the ID of the currently selected group or child. Can return -1 if no
- * selection.
- *
- * @return The ID of the currently selected group or child. -1 if no
- * selection.
- */
- public long getSelectedId() {
- long packedPos = getSelectedPosition();
- if (packedPos == PACKED_POSITION_VALUE_NULL) return -1;
-
- int groupPos = getPackedPositionGroup(packedPos);
-
- if (getPackedPositionType(packedPos) == PACKED_POSITION_TYPE_GROUP) {
- // It's a group
- return mAdapter.getGroupId(groupPos);
- } else {
- // It's a child
- return mAdapter.getChildId(groupPos, getPackedPositionChild(packedPos));
- }
- }
-
- /**
- * Sets the selection to the specified group.
- * @param groupPosition The position of the group that should be selected.
- */
- public void setSelectedGroup(int groupPosition) {
- ExpandableListPosition elGroupPos = ExpandableListPosition
- .obtainGroupPosition(groupPosition);
- PositionMetadata pm = mConnector.getFlattenedPos(elGroupPos);
- elGroupPos.recycle();
- super.setSelection(pm.position.flatListPos);
- pm.recycle();
- }
-
- /**
- * Sets the selection to the specified child. If the child is in a collapsed
- * group, the group will only be expanded and child subsequently selected if
- * shouldExpandGroup is set to true, otherwise the method will return false.
- *
- * @param groupPosition The position of the group that contains the child.
- * @param childPosition The position of the child within the group.
- * @param shouldExpandGroup Whether the child's group should be expanded if
- * it is collapsed.
- * @return Whether the selection was successfully set on the child.
- */
- public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) {
- ExpandableListPosition elChildPos = ExpandableListPosition.obtainChildPosition(
- groupPosition, childPosition);
- PositionMetadata flatChildPos = mConnector.getFlattenedPos(elChildPos);
-
- if (flatChildPos == null) {
- // The child's group isn't expanded
-
- // Shouldn't expand the group, so return false for we didn't set the selection
- if (!shouldExpandGroup) return false;
-
- expandGroup(groupPosition);
-
- flatChildPos = mConnector.getFlattenedPos(elChildPos);
-
- // Sanity check
- if (flatChildPos == null) {
- throw new IllegalStateException("Could not find child");
- }
- }
-
- super.setSelection(flatChildPos.position.flatListPos);
-
- elChildPos.recycle();
- flatChildPos.recycle();
-
- return true;
- }
-
- /**
- * Whether the given group is currently expanded.
- *
- * @param groupPosition The group to check.
- * @return Whether the group is currently expanded.
- */
- public boolean isGroupExpanded(int groupPosition) {
- return mConnector.isGroupExpanded(groupPosition);
- }
-
- /**
- * Gets the type of a packed position. See
- * {@link #getPackedPositionForChild(int, int)}.
- *
- * @param packedPosition The packed position for which to return the type.
- * @return The type of the position contained within the packed position,
- * either {@link #PACKED_POSITION_TYPE_CHILD}, {@link #PACKED_POSITION_TYPE_GROUP}, or
- * {@link #PACKED_POSITION_TYPE_NULL}.
- */
- public static int getPackedPositionType(long packedPosition) {
- if (packedPosition == PACKED_POSITION_VALUE_NULL) {
- return PACKED_POSITION_TYPE_NULL;
- }
-
- return (packedPosition & PACKED_POSITION_MASK_TYPE) == PACKED_POSITION_MASK_TYPE
- ? PACKED_POSITION_TYPE_CHILD
- : PACKED_POSITION_TYPE_GROUP;
- }
-
- /**
- * Gets the group position from a packed position. See
- * {@link #getPackedPositionForChild(int, int)}.
- *
- * @param packedPosition The packed position from which the group position
- * will be returned.
- * @return The group position portion of the packed position. If this does
- * not contain a group, returns -1.
- */
- public static int getPackedPositionGroup(long packedPosition) {
- // Null
- if (packedPosition == PACKED_POSITION_VALUE_NULL) return -1;
-
- return (int) ((packedPosition & PACKED_POSITION_MASK_GROUP) >> PACKED_POSITION_SHIFT_GROUP);
- }
-
- /**
- * Gets the child position from a packed position that is of
- * {@link #PACKED_POSITION_TYPE_CHILD} type (use {@link #getPackedPositionType(long)}).
- * To get the group that this child belongs to, use
- * {@link #getPackedPositionGroup(long)}. See
- * {@link #getPackedPositionForChild(int, int)}.
- *
- * @param packedPosition The packed position from which the child position
- * will be returned.
- * @return The child position portion of the packed position. If this does
- * not contain a child, returns -1.
- */
- public static int getPackedPositionChild(long packedPosition) {
- // Null
- if (packedPosition == PACKED_POSITION_VALUE_NULL) return -1;
-
- // Group since a group type clears this bit
- if ((packedPosition & PACKED_POSITION_MASK_TYPE) != PACKED_POSITION_MASK_TYPE) return -1;
-
- return (int) (packedPosition & PACKED_POSITION_MASK_CHILD);
- }
-
- /**
- * Returns the packed position representation of a child's position.
- * <p>
- * In general, a packed position should be used in
- * situations where the position given to/returned from an
- * {@link ExpandableListAdapter} or {@link ExpandableListView} method can
- * either be a child or group. The two positions are packed into a single
- * long which can be unpacked using
- * {@link #getPackedPositionChild(long)},
- * {@link #getPackedPositionGroup(long)}, and
- * {@link #getPackedPositionType(long)}.
- *
- * @param groupPosition The child's parent group's position.
- * @param childPosition The child position within the group.
- * @return The packed position representation of the child (and parent group).
- */
- public static long getPackedPositionForChild(int groupPosition, int childPosition) {
- return (((long)PACKED_POSITION_TYPE_CHILD) << PACKED_POSITION_SHIFT_TYPE)
- | ((((long)groupPosition) & PACKED_POSITION_INT_MASK_GROUP)
- << PACKED_POSITION_SHIFT_GROUP)
- | (childPosition & PACKED_POSITION_INT_MASK_CHILD);
- }
-
- /**
- * Returns the packed position representation of a group's position. See
- * {@link #getPackedPositionForChild(int, int)}.
- *
- * @param groupPosition The child's parent group's position.
- * @return The packed position representation of the group.
- */
- public static long getPackedPositionForGroup(int groupPosition) {
- // No need to OR a type in because PACKED_POSITION_GROUP == 0
- return ((((long)groupPosition) & PACKED_POSITION_INT_MASK_GROUP)
- << PACKED_POSITION_SHIFT_GROUP);
- }
-
- @Override
- ContextMenuInfo createContextMenuInfo(View view, int flatListPosition, long id) {
- PositionMetadata pm = mConnector.getUnflattenedPos(flatListPosition);
- ExpandableListPosition pos = pm.position;
- pm.recycle();
-
- id = getChildOrGroupId(pos);
- long packedPosition = pos.getPackedPosition();
- pos.recycle();
-
- return new ExpandableListContextMenuInfo(view, packedPosition, id);
- }
-
- /**
- * Gets the ID of the group or child at the given <code>position</code>.
- * This is useful since there is no ListAdapter ID -> ExpandableListAdapter
- * ID conversion mechanism (in some cases, it isn't possible).
- *
- * @param position The position of the child or group whose ID should be
- * returned.
- */
- private long getChildOrGroupId(ExpandableListPosition position) {
- if (position.type == ExpandableListPosition.CHILD) {
- return mAdapter.getChildId(position.groupPos, position.childPos);
- } else {
- return mAdapter.getGroupId(position.groupPos);
- }
- }
-
- /**
- * Sets the indicator to be drawn next to a child.
- *
- * @param childIndicator The drawable to be used as an indicator. If the
- * child is the last child for a group, the state
- * {@link android.R.attr#state_last} will be set.
- */
- public void setChildIndicator(Drawable childIndicator) {
- mChildIndicator = childIndicator;
- }
-
- /**
- * Sets the drawing bounds for the child indicator. For either, you can
- * specify {@link #CHILD_INDICATOR_INHERIT} to use inherit from the general
- * indicator's bounds.
- *
- * @see #setIndicatorBounds(int, int)
- * @param left The left position (relative to the left bounds of this View)
- * to start drawing the indicator.
- * @param right The right position (relative to the left bounds of this
- * View) to end the drawing of the indicator.
- */
- public void setChildIndicatorBounds(int left, int right) {
- mChildIndicatorLeft = left;
- mChildIndicatorRight = right;
- }
-
- /**
- * Sets the indicator to be drawn next to a group.
- *
- * @param groupIndicator The drawable to be used as an indicator. If the
- * group is empty, the state {@link android.R.attr#state_empty} will be
- * set. If the group is expanded, the state
- * {@link android.R.attr#state_expanded} will be set.
- */
- public void setGroupIndicator(Drawable groupIndicator) {
- mGroupIndicator = groupIndicator;
- }
-
- /**
- * Sets the drawing bounds for the indicators (at minimum, the group indicator
- * is affected by this; the child indicator is affected by this if the
- * child indicator bounds are set to inherit).
- *
- * @see #setChildIndicatorBounds(int, int)
- * @param left The left position (relative to the left bounds of this View)
- * to start drawing the indicator.
- * @param right The right position (relative to the left bounds of this
- * View) to end the drawing of the indicator.
- */
- public void setIndicatorBounds(int left, int right) {
- mIndicatorLeft = left;
- mIndicatorRight = right;
- }
-
- /**
- * Extra menu information specific to an {@link ExpandableListView} provided
- * to the
- * {@link android.view.View.OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo) }
- * callback when a context menu is brought up for this AdapterView.
- */
- public static class ExpandableListContextMenuInfo implements ContextMenu.ContextMenuInfo {
-
- public ExpandableListContextMenuInfo(View targetView, long packedPosition, long id) {
- this.targetView = targetView;
- this.packedPosition = packedPosition;
- this.id = id;
- }
-
- /**
- * The view for which the context menu is being displayed. This
- * will be one of the children Views of this {@link ExpandableListView}.
- */
- public View targetView;
-
- /**
- * The packed position in the list represented by the adapter for which
- * the context menu is being displayed. Use the methods
- * {@link ExpandableListView#getPackedPositionType},
- * {@link ExpandableListView#getPackedPositionChild}, and
- * {@link ExpandableListView#getPackedPositionGroup} to unpack this.
- */
- public long packedPosition;
-
- /**
- * The ID of the item (group or child) for which the context menu is
- * being displayed.
- */
- public long id;
- }
-
- static class SavedState extends BaseSavedState {
- ArrayList<ExpandableListConnector.GroupMetadata> expandedGroupMetadataList;
-
- /**
- * Constructor called from {@link ExpandableListView#onSaveInstanceState()}
- */
- SavedState(
- Parcelable superState,
- ArrayList<ExpandableListConnector.GroupMetadata> expandedGroupMetadataList) {
- super(superState);
- this.expandedGroupMetadataList = expandedGroupMetadataList;
- }
-
- /**
- * Constructor called from {@link #CREATOR}
- */
- private SavedState(Parcel in) {
- super(in);
- expandedGroupMetadataList = new ArrayList<ExpandableListConnector.GroupMetadata>();
- in.readList(expandedGroupMetadataList, ExpandableListConnector.class.getClassLoader());
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- super.writeToParcel(out, flags);
- out.writeList(expandedGroupMetadataList);
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR
- = new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
- @Override
- public Parcelable onSaveInstanceState() {
- Parcelable superState = super.onSaveInstanceState();
- return new SavedState(superState,
- mConnector != null ? mConnector.getExpandedGroupMetadataList() : null);
- }
-
- @Override
- public void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
- super.onRestoreInstanceState(ss.getSuperState());
-
- if (mConnector != null && ss.expandedGroupMetadataList != null) {
- mConnector.setExpandedGroupMetadataList(ss.expandedGroupMetadataList);
- }
- }
-
-}
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
deleted file mode 100644
index 57e21e4..0000000
--- a/core/java/android/widget/FastScroller.java
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.SystemClock;
-import android.util.TypedValue;
-import android.view.MotionEvent;
-
-/**
- * Helper class for AbsListView to draw and control the Fast Scroll thumb
- */
-class FastScroller {
-
- // Minimum number of pages to justify showing a fast scroll thumb
- private static int MIN_PAGES = 4;
- // Scroll thumb not showing
- private static final int STATE_NONE = 0;
- // Not implemented yet - fade-in transition
- private static final int STATE_ENTER = 1;
- // Scroll thumb visible and moving along with the scrollbar
- private static final int STATE_VISIBLE = 2;
- // Scroll thumb being dragged by user
- private static final int STATE_DRAGGING = 3;
- // Scroll thumb fading out due to inactivity timeout
- private static final int STATE_EXIT = 4;
-
- private Drawable mThumbDrawable;
- private Drawable mOverlayDrawable;
-
- private int mThumbH;
- private int mThumbW;
- private int mThumbY;
-
- private RectF mOverlayPos;
- private int mOverlaySize = 104;
-
- private AbsListView mList;
- private boolean mScrollCompleted;
- private int mVisibleItem;
- private Paint mPaint;
- private int mListOffset;
-
- private Object [] mSections;
- private String mSectionText;
- private boolean mDrawOverlay;
- private ScrollFade mScrollFade;
-
- private int mState;
-
- private Handler mHandler = new Handler();
-
- private BaseAdapter mListAdapter;
- private SectionIndexer mSectionIndexer;
-
- private boolean mChangedBounds;
-
- public FastScroller(Context context, AbsListView listView) {
- mList = listView;
- init(context);
- }
-
- public void setState(int state) {
- switch (state) {
- case STATE_NONE:
- mHandler.removeCallbacks(mScrollFade);
- mList.invalidate();
- break;
- case STATE_VISIBLE:
- if (mState != STATE_VISIBLE) { // Optimization
- resetThumbPos();
- }
- // Fall through
- case STATE_DRAGGING:
- mHandler.removeCallbacks(mScrollFade);
- break;
- case STATE_EXIT:
- int viewWidth = mList.getWidth();
- mList.invalidate(viewWidth - mThumbW, mThumbY, viewWidth, mThumbY + mThumbH);
- break;
- }
- mState = state;
- }
-
- public int getState() {
- return mState;
- }
-
- private void resetThumbPos() {
- final int viewWidth = mList.getWidth();
- // Bounds are always top right. Y coordinate get's translated during draw
- mThumbDrawable.setBounds(viewWidth - mThumbW, 0, viewWidth, mThumbH);
- mThumbDrawable.setAlpha(ScrollFade.ALPHA_MAX);
- }
-
- private void useThumbDrawable(Drawable drawable) {
- mThumbDrawable = drawable;
- mThumbW = 64; //mCurrentThumb.getIntrinsicWidth();
- mThumbH = 52; //mCurrentThumb.getIntrinsicHeight();
- mChangedBounds = true;
- }
-
- private void init(Context context) {
- // Get both the scrollbar states drawables
- final Resources res = context.getResources();
- useThumbDrawable(res.getDrawable(
- com.android.internal.R.drawable.scrollbar_handle_accelerated_anim2));
-
- mOverlayDrawable = res.getDrawable(
- com.android.internal.R.drawable.menu_submenu_background);
-
- mScrollCompleted = true;
-
- getSections();
-
- mOverlayPos = new RectF();
- mScrollFade = new ScrollFade();
- mPaint = new Paint();
- mPaint.setAntiAlias(true);
- mPaint.setTextAlign(Paint.Align.CENTER);
- mPaint.setTextSize(mOverlaySize / 2);
- TypedArray ta = context.getTheme().obtainStyledAttributes(new int[] {
- android.R.attr.textColorPrimary });
- ColorStateList textColor = ta.getColorStateList(ta.getIndex(0));
- int textColorNormal = textColor.getDefaultColor();
- mPaint.setColor(textColorNormal);
- mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
-
- mState = STATE_NONE;
- }
-
- void stop() {
- setState(STATE_NONE);
- }
-
- boolean isVisible() {
- return !(mState == STATE_NONE);
- }
-
- public void draw(Canvas canvas) {
-
- if (mState == STATE_NONE) {
- // No need to draw anything
- return;
- }
-
- final int y = mThumbY;
- final int viewWidth = mList.getWidth();
- final FastScroller.ScrollFade scrollFade = mScrollFade;
-
- int alpha = -1;
- if (mState == STATE_EXIT) {
- alpha = scrollFade.getAlpha();
- if (alpha < ScrollFade.ALPHA_MAX / 2) {
- mThumbDrawable.setAlpha(alpha * 2);
- }
- int left = viewWidth - (mThumbW * alpha) / ScrollFade.ALPHA_MAX;
- mThumbDrawable.setBounds(left, 0, viewWidth, mThumbH);
- mChangedBounds = true;
- }
-
- canvas.translate(0, y);
- mThumbDrawable.draw(canvas);
- canvas.translate(0, -y);
-
- // If user is dragging the scroll bar, draw the alphabet overlay
- if (mState == STATE_DRAGGING && mDrawOverlay) {
- mOverlayDrawable.draw(canvas);
- final Paint paint = mPaint;
- float descent = paint.descent();
- final RectF rectF = mOverlayPos;
- canvas.drawText(mSectionText, (int) (rectF.left + rectF.right) / 2,
- (int) (rectF.bottom + rectF.top) / 2 + mOverlaySize / 4 - descent, paint);
- } else if (mState == STATE_EXIT) {
- if (alpha == 0) { // Done with exit
- setState(STATE_NONE);
- } else {
- mList.invalidate(viewWidth - mThumbW, y, viewWidth, y + mThumbH);
- }
- }
- }
-
- void onSizeChanged(int w, int h, int oldw, int oldh) {
- if (mThumbDrawable != null) {
- mThumbDrawable.setBounds(w - mThumbW, 0, w, mThumbH);
- }
- final RectF pos = mOverlayPos;
- pos.left = (w - mOverlaySize) / 2;
- pos.right = pos.left + mOverlaySize;
- pos.top = h / 10; // 10% from top
- pos.bottom = pos.top + mOverlaySize;
- if (mOverlayDrawable != null) {
- mOverlayDrawable.setBounds((int) pos.left, (int) pos.top,
- (int) pos.right, (int) pos.bottom);
- }
- }
-
- void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
- int totalItemCount) {
- // Are there enough pages to require fast scroll?
- if (visibleItemCount > 0 && totalItemCount / visibleItemCount < MIN_PAGES) {
- if (mState != STATE_NONE) {
- setState(STATE_NONE);
- }
- return;
- }
- if (totalItemCount - visibleItemCount > 0 && mState != STATE_DRAGGING ) {
- mThumbY = ((mList.getHeight() - mThumbH) * firstVisibleItem)
- / (totalItemCount - visibleItemCount);
- if (mChangedBounds) {
- resetThumbPos();
- mChangedBounds = false;
- }
- }
- mScrollCompleted = true;
- if (firstVisibleItem == mVisibleItem) {
- return;
- }
- mVisibleItem = firstVisibleItem;
- if (mState != STATE_DRAGGING) {
- setState(STATE_VISIBLE);
- mHandler.postDelayed(mScrollFade, 1500);
- }
- }
-
- private void getSections() {
- Adapter adapter = mList.getAdapter();
- mSectionIndexer = null;
- if (adapter instanceof HeaderViewListAdapter) {
- mListOffset = ((HeaderViewListAdapter)adapter).getHeadersCount();
- adapter = ((HeaderViewListAdapter)adapter).getWrappedAdapter();
- }
- if (adapter instanceof ExpandableListConnector) {
- ExpandableListAdapter expAdapter = ((ExpandableListConnector)adapter).getAdapter();
- if (expAdapter instanceof SectionIndexer) {
- mSectionIndexer = (SectionIndexer) expAdapter;
- mListAdapter = (BaseAdapter) adapter;
- mSections = mSectionIndexer.getSections();
- }
- } else {
- if (adapter instanceof SectionIndexer) {
- mListAdapter = (BaseAdapter) adapter;
- mSectionIndexer = (SectionIndexer) adapter;
- mSections = mSectionIndexer.getSections();
-
- } else {
- mListAdapter = (BaseAdapter) adapter;
- mSections = new String[] { " " };
- }
- }
- }
-
- private void scrollTo(float position) {
- int count = mList.getCount();
- mScrollCompleted = false;
- float fThreshold = (1.0f / count) / 8;
- final Object[] sections = mSections;
- int sectionIndex;
- if (sections != null && sections.length > 1) {
- final int nSections = sections.length;
- int section = (int) (position * nSections);
- if (section >= nSections) {
- section = nSections - 1;
- }
- int exactSection = section;
- sectionIndex = section;
- int index = mSectionIndexer.getPositionForSection(section);
- // Given the expected section and index, the following code will
- // try to account for missing sections (no names starting with..)
- // It will compute the scroll space of surrounding empty sections
- // and interpolate the currently visible letter's range across the
- // available space, so that there is always some list movement while
- // the user moves the thumb.
- int nextIndex = count;
- int prevIndex = index;
- int prevSection = section;
- int nextSection = section + 1;
- // Assume the next section is unique
- if (section < nSections - 1) {
- nextIndex = mSectionIndexer.getPositionForSection(section + 1);
- }
-
- // Find the previous index if we're slicing the previous section
- if (nextIndex == index) {
- // Non-existent letter
- while (section > 0) {
- section--;
- prevIndex = mSectionIndexer.getPositionForSection(section);
- if (prevIndex != index) {
- prevSection = section;
- sectionIndex = section;
- break;
- }
- }
- }
- // Find the next index, in case the assumed next index is not
- // unique. For instance, if there is no P, then request for P's
- // position actually returns Q's. So we need to look ahead to make
- // sure that there is really a Q at Q's position. If not, move
- // further down...
- int nextNextSection = nextSection + 1;
- while (nextNextSection < nSections &&
- mSectionIndexer.getPositionForSection(nextNextSection) == nextIndex) {
- nextNextSection++;
- nextSection++;
- }
- // Compute the beginning and ending scroll range percentage of the
- // currently visible letter. This could be equal to or greater than
- // (1 / nSections).
- float fPrev = (float) prevSection / nSections;
- float fNext = (float) nextSection / nSections;
- if (prevSection == exactSection && position - fPrev < fThreshold) {
- index = prevIndex;
- } else {
- index = prevIndex + (int) ((nextIndex - prevIndex) * (position - fPrev)
- / (fNext - fPrev));
- }
- // Don't overflow
- if (index > count - 1) index = count - 1;
-
- if (mList instanceof ExpandableListView) {
- ExpandableListView expList = (ExpandableListView) mList;
- expList.setSelectionFromTop(expList.getFlatListPosition(
- ExpandableListView.getPackedPositionForGroup(index + mListOffset)), 0);
- } else if (mList instanceof ListView) {
- ((ListView)mList).setSelectionFromTop(index + mListOffset, 0);
- } else {
- mList.setSelection(index + mListOffset);
- }
- } else {
- int index = (int) (position * count);
- if (mList instanceof ExpandableListView) {
- ExpandableListView expList = (ExpandableListView) mList;
- expList.setSelectionFromTop(expList.getFlatListPosition(
- ExpandableListView.getPackedPositionForGroup(index + mListOffset)), 0);
- } else if (mList instanceof ListView) {
- ((ListView)mList).setSelectionFromTop(index + mListOffset, 0);
- } else {
- mList.setSelection(index + mListOffset);
- }
- sectionIndex = -1;
- }
-
- if (sectionIndex >= 0) {
- String text = mSectionText = sections[sectionIndex].toString();
- mDrawOverlay = (text.length() != 1 || text.charAt(0) != ' ') &&
- sectionIndex < sections.length;
- } else {
- mDrawOverlay = false;
- }
- }
-
- private void cancelFling() {
- // Cancel the list fling
- MotionEvent cancelFling = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
- mList.onTouchEvent(cancelFling);
- cancelFling.recycle();
- }
-
- boolean onInterceptTouchEvent(MotionEvent ev) {
- if (mState > STATE_NONE && ev.getAction() == MotionEvent.ACTION_DOWN) {
- if (ev.getX() > mList.getWidth() - mThumbW && ev.getY() >= mThumbY &&
- ev.getY() <= mThumbY + mThumbH) {
- setState(STATE_DRAGGING);
- return true;
- }
- }
- return false;
- }
-
- boolean onTouchEvent(MotionEvent me) {
- if (mState == STATE_NONE) {
- return false;
- }
- if (me.getAction() == MotionEvent.ACTION_DOWN) {
- if (me.getX() > mList.getWidth() - mThumbW
- && me.getY() >= mThumbY
- && me.getY() <= mThumbY + mThumbH) {
-
- setState(STATE_DRAGGING);
- if (mListAdapter == null && mList != null) {
- getSections();
- }
-
- cancelFling();
- return true;
- }
- } else if (me.getAction() == MotionEvent.ACTION_UP) {
- if (mState == STATE_DRAGGING) {
- setState(STATE_VISIBLE);
- final Handler handler = mHandler;
- handler.removeCallbacks(mScrollFade);
- handler.postDelayed(mScrollFade, 1000);
- return true;
- }
- } else if (me.getAction() == MotionEvent.ACTION_MOVE) {
- if (mState == STATE_DRAGGING) {
- final int viewHeight = mList.getHeight();
- // Jitter
- int newThumbY = (int) me.getY() - mThumbH + 10;
- if (newThumbY < 0) {
- newThumbY = 0;
- } else if (newThumbY + mThumbH > viewHeight) {
- newThumbY = viewHeight - mThumbH;
- }
- if (Math.abs(mThumbY - newThumbY) < 2) {
- return true;
- }
- mThumbY = newThumbY;
- // If the previous scrollTo is still pending
- if (mScrollCompleted) {
- scrollTo((float) mThumbY / (viewHeight - mThumbH));
- }
- return true;
- }
- }
- return false;
- }
-
- public class ScrollFade implements Runnable {
-
- long mStartTime;
- long mFadeDuration;
- static final int ALPHA_MAX = 208;
- static final long FADE_DURATION = 200;
-
- void startFade() {
- mFadeDuration = FADE_DURATION;
- mStartTime = SystemClock.uptimeMillis();
- setState(STATE_EXIT);
- }
-
- int getAlpha() {
- if (getState() != STATE_EXIT) {
- return ALPHA_MAX;
- }
- int alpha;
- long now = SystemClock.uptimeMillis();
- if (now > mStartTime + mFadeDuration) {
- alpha = 0;
- } else {
- alpha = (int) (ALPHA_MAX - ((now - mStartTime) * ALPHA_MAX) / mFadeDuration);
- }
- return alpha;
- }
-
- public void run() {
- if (getState() != STATE_EXIT) {
- startFade();
- return;
- }
-
- if (getAlpha() > 0) {
- mList.invalidate();
- } else {
- setState(STATE_NONE);
- }
- }
- }
-}
diff --git a/core/java/android/widget/Filter.java b/core/java/android/widget/Filter.java
deleted file mode 100644
index a2316cf..0000000
--- a/core/java/android/widget/Filter.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.util.Log;
-
-/**
- * <p>A filter constrains data with a filtering pattern.</p>
- *
- * <p>Filters are usually created by {@link android.widget.Filterable}
- * classes.</p>
- *
- * <p>Filtering operations performed by calling {@link #filter(CharSequence)} or
- * {@link #filter(CharSequence, android.widget.Filter.FilterListener)} are
- * performed asynchronously. When these methods are called, a filtering request
- * is posted in a request queue and processed later. Any call to one of these
- * methods will cancel any previous non-executed filtering request.</p>
- *
- * @see android.widget.Filterable
- */
-public abstract class Filter {
- private static final String LOG_TAG = "Filter";
-
- private static final String THREAD_NAME = "Filter";
- private static final int FILTER_TOKEN = 0xD0D0F00D;
- private static final int FINISH_TOKEN = 0xDEADBEEF;
-
- private Handler mThreadHandler;
- private Handler mResultHandler;
- private String mConstraint;
- private boolean mConstraintIsValid = false;
-
- /**
- * <p>Creates a new asynchronous filter.</p>
- */
- public Filter() {
- mResultHandler = new ResultsHandler();
- }
-
- /**
- * <p>Starts an asynchronous filtering operation. Calling this method
- * cancels all previous non-executed filtering requests and posts a new
- * filtering request that will be executed later.</p>
- *
- * @param constraint the constraint used to filter the data
- *
- * @see #filter(CharSequence, android.widget.Filter.FilterListener)
- */
- public final void filter(CharSequence constraint) {
- filter(constraint, null);
- }
-
- /**
- * <p>Starts an asynchronous filtering operation. Calling this method
- * cancels all previous non-executed filtering requests and posts a new
- * filtering request that will be executed later.</p>
- *
- * <p>Upon completion, the listener is notified.</p>
- *
- * @param constraint the constraint used to filter the data
- * @param listener a listener notified upon completion of the operation
- *
- * @see #filter(CharSequence)
- * @see #performFiltering(CharSequence)
- * @see #publishResults(CharSequence, android.widget.Filter.FilterResults)
- */
- public final void filter(CharSequence constraint, FilterListener listener) {
- synchronized (this) {
- String constraintAsString = constraint != null ? constraint.toString() : null;
- if (mConstraintIsValid && (
- (constraintAsString == null && mConstraint == null) ||
- (constraintAsString != null && constraintAsString.equals(mConstraint)))) {
- // nothing to do
- return;
- }
-
- if (mThreadHandler == null) {
- HandlerThread thread = new HandlerThread(THREAD_NAME);
- thread.start();
- mThreadHandler = new RequestHandler(thread.getLooper());
- }
-
- Message message = mThreadHandler.obtainMessage(FILTER_TOKEN);
-
- RequestArguments args = new RequestArguments();
- // make sure we use an immutable copy of the constraint, so that
- // it doesn't change while the filter operation is in progress
- args.constraint = constraintAsString;
- args.listener = listener;
- message.obj = args;
-
- mThreadHandler.removeMessages(FILTER_TOKEN);
- mThreadHandler.removeMessages(FINISH_TOKEN);
- mThreadHandler.sendMessage(message);
-
- mConstraint = constraintAsString;
- mConstraintIsValid = true;
- }
- }
-
- /**
- * <p>Invoked in a worker thread to filter the data according to the
- * constraint. Subclasses must implement this method to perform the
- * filtering operation. Results computed by the filtering operation
- * must be returned as a {@link android.widget.Filter.FilterResults} that
- * will then be published in the UI thread through
- * {@link #publishResults(CharSequence,
- * android.widget.Filter.FilterResults)}.</p>
- *
- * <p><strong>Contract:</strong> When the constraint is null, the original
- * data must be restored.</p>
- *
- * @param constraint the constraint used to filter the data
- * @return the results of the filtering operation
- *
- * @see #filter(CharSequence, android.widget.Filter.FilterListener)
- * @see #publishResults(CharSequence, android.widget.Filter.FilterResults)
- * @see android.widget.Filter.FilterResults
- */
- protected abstract FilterResults performFiltering(CharSequence constraint);
-
- /**
- * <p>Invoked in the UI thread to publish the filtering results in the
- * user interface. Subclasses must implement this method to display the
- * results computed in {@link #performFiltering}.</p>
- *
- * @param constraint the constraint used to filter the data
- * @param results the results of the filtering operation
- *
- * @see #filter(CharSequence, android.widget.Filter.FilterListener)
- * @see #performFiltering(CharSequence)
- * @see android.widget.Filter.FilterResults
- */
- protected abstract void publishResults(CharSequence constraint,
- FilterResults results);
-
- /**
- * <p>Converts a value from the filtered set into a CharSequence. Subclasses
- * should override this method to convert their results. The default
- * implementation returns an empty String for null values or the default
- * String representation of the value.</p>
- *
- * @param resultValue the value to convert to a CharSequence
- * @return a CharSequence representing the value
- */
- public CharSequence convertResultToString(Object resultValue) {
- return resultValue == null ? "" : resultValue.toString();
- }
-
- /**
- * <p>Holds the results of a filtering operation. The results are the values
- * computed by the filtering operation and the number of these values.</p>
- */
- protected static class FilterResults {
- public FilterResults() {
- // nothing to see here
- }
-
- /**
- * <p>Contains all the values computed by the filtering operation.</p>
- */
- public Object values;
-
- /**
- * <p>Contains the number of values computed by the filtering
- * operation.</p>
- */
- public int count;
- }
-
- /**
- * <p>Listener used to receive a notification upon completion of a filtering
- * operation.</p>
- */
- public static interface FilterListener {
- /**
- * <p>Notifies the end of a filtering operation.</p>
- *
- * @param count the number of values computed by the filter
- */
- public void onFilterComplete(int count);
- }
-
- /**
- * <p>Worker thread handler. When a new filtering request is posted from
- * {@link android.widget.Filter#filter(CharSequence, android.widget.Filter.FilterListener)},
- * it is sent to this handler.</p>
- */
- private class RequestHandler extends Handler {
- public RequestHandler(Looper looper) {
- super(looper);
- }
-
- /**
- * <p>Handles filtering requests by calling
- * {@link Filter#performFiltering} and then sending a message
- * with the results to the results handler.</p>
- *
- * @param msg the filtering request
- */
- public void handleMessage(Message msg) {
- int what = msg.what;
- Message message;
- switch (what) {
- case FILTER_TOKEN:
- RequestArguments args = (RequestArguments) msg.obj;
- try {
- args.results = performFiltering(args.constraint);
- } catch (Exception e) {
- args.results = new FilterResults();
- Log.w(LOG_TAG, "An exception occured during performFiltering()!", e);
- } finally {
- message = mResultHandler.obtainMessage(what);
- message.obj = args;
- message.sendToTarget();
- }
-
- synchronized (this) {
- if (mThreadHandler != null) {
- Message finishMessage = mThreadHandler.obtainMessage(FINISH_TOKEN);
- mThreadHandler.sendMessageDelayed(finishMessage, 3000);
- }
- }
- break;
- case FINISH_TOKEN:
- synchronized (this) {
- if (mThreadHandler != null) {
- mThreadHandler.getLooper().quit();
- mThreadHandler = null;
- }
- }
- break;
- }
- }
- }
-
- /**
- * <p>Handles the results of a filtering operation. The results are
- * handled in the UI thread.</p>
- */
- private class ResultsHandler extends Handler {
- /**
- * <p>Messages received from the request handler are processed in the
- * UI thread. The processing involves calling
- * {@link Filter#publishResults(CharSequence,
- * android.widget.Filter.FilterResults)}
- * to post the results back in the UI and then notifying the listener,
- * if any.</p>
- *
- * @param msg the filtering results
- */
- @Override
- public void handleMessage(Message msg) {
- RequestArguments args = (RequestArguments) msg.obj;
-
- publishResults(args.constraint, args.results);
- if (args.listener != null) {
- int count = args.results != null ? args.results.count : -1;
- args.listener.onFilterComplete(count);
- }
- }
- }
-
- /**
- * <p>Holds the arguments of a filtering request as well as the results
- * of the request.</p>
- */
- private static class RequestArguments {
- /**
- * <p>The constraint used to filter the data.</p>
- */
- CharSequence constraint;
-
- /**
- * <p>The listener to notify upon completion. Can be null.</p>
- */
- FilterListener listener;
-
- /**
- * <p>The results of the filtering operation.</p>
- */
- FilterResults results;
- }
-}
diff --git a/core/java/android/widget/FilterQueryProvider.java b/core/java/android/widget/FilterQueryProvider.java
deleted file mode 100644
index 740d2f0..0000000
--- a/core/java/android/widget/FilterQueryProvider.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.database.Cursor;
-
-/**
- * This class can be used by external clients of CursorAdapter and
- * CursorTreeAdapter to define how the content of the adapter should be
- * filtered.
- *
- * @see #runQuery(CharSequence)
- */
-public interface FilterQueryProvider {
- /**
- * Runs a query with the specified constraint. This query is requested
- * by the filter attached to this adapter.
- *
- * Contract: when constraint is null or empty, the original results,
- * prior to any filtering, must be returned.
- *
- * @param constraint the constraint with which the query must
- * be filtered
- *
- * @return a Cursor representing the results of the new query
- */
- Cursor runQuery(CharSequence constraint);
-}
diff --git a/core/java/android/widget/Filterable.java b/core/java/android/widget/Filterable.java
deleted file mode 100644
index f7c8d59..0000000
--- a/core/java/android/widget/Filterable.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-/**
- * <p>Defines a filterable behavior. A filterable class can have its data
- * constrained by a filter. Filterable classes are usually
- * {@link android.widget.Adapter} implementations.</p>
- *
- * @see android.widget.Filter
- */
-public interface Filterable {
- /**
- * <p>Returns a filter that can be used to constrain data with a filtering
- * pattern.</p>
- *
- * <p>This method is usually implemented by {@link android.widget.Adapter}
- * classes.</p>
- *
- * @return a filter used to constrain data
- */
- Filter getFilter();
-}
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
deleted file mode 100644
index 8aafee2..0000000
--- a/core/java/android/widget/FrameLayout.java
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Gravity;
-import android.widget.RemoteViews.RemoteView;
-
-
-/**
- * FrameLayout is designed to block out an area on the screen to display
- * a single item. You can add multiple children to a FrameLayout, but all
- * children are pegged to the top left of the screen.
- * Children are drawn in a stack, with the most recently added child on top.
- * The size of the frame layout is the size of its largest child (plus padding), visible
- * or not (if the FrameLayout's parent permits). Views that are GONE are used for sizing
- * only if {@link #setMeasureAllChildren(boolean) setConsiderGoneChildrenWhenMeasuring()}
- * is set to true.
- *
- * @attr ref android.R.styleable#FrameLayout_foreground
- * @attr ref android.R.styleable#FrameLayout_foregroundGravity
- * @attr ref android.R.styleable#FrameLayout_measureAllChildren
- */
-@RemoteView
-public class FrameLayout extends ViewGroup {
- boolean mMeasureAllChildren = false;
-
- private Drawable mForeground;
- private int mForegroundPaddingLeft = 0;
- private int mForegroundPaddingTop = 0;
- private int mForegroundPaddingRight = 0;
- private int mForegroundPaddingBottom = 0;
-
- private final Rect mSelfBounds = new Rect();
- private final Rect mOverlayBounds = new Rect();
- private int mForegroundGravity = Gravity.FILL;
-
- public FrameLayout(Context context) {
- super(context);
- }
-
- public FrameLayout(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public FrameLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.FrameLayout,
- defStyle, 0);
-
- final Drawable d = a.getDrawable(com.android.internal.R.styleable.FrameLayout_foreground);
- if (d != null) {
- setForeground(d);
- }
-
- if (a.getBoolean(com.android.internal.R.styleable.FrameLayout_measureAllChildren, false)) {
- setMeasureAllChildren(true);
- }
-
- mForegroundGravity = a.getInt(com.android.internal.R.styleable.FrameLayout_foregroundGravity,
- mForegroundGravity);
-
- a.recycle();
- }
-
- /**
- * Describes how the foreground is positioned. Defaults to FILL.
- *
- * @param foregroundGravity See {@link android.view.Gravity}
- *
- * @attr ref android.R.styleable#FrameLayout_foregroundGravity
- */
- @android.view.RemotableViewMethod
- public void setForegroundGravity(int foregroundGravity) {
- if (mForegroundGravity != foregroundGravity) {
- if ((foregroundGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
- foregroundGravity |= Gravity.LEFT;
- }
-
- if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
- foregroundGravity |= Gravity.TOP;
- }
-
- mForegroundGravity = foregroundGravity;
- requestLayout();
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected boolean verifyDrawable(Drawable who) {
- return super.verifyDrawable(who) || (who == mForeground);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
- if (mForeground != null && mForeground.isStateful()) {
- mForeground.setState(getDrawableState());
- }
- }
-
- /**
- * Returns a set of layout parameters with a width of
- * {@link android.view.ViewGroup.LayoutParams#FILL_PARENT},
- * and a height of {@link android.view.ViewGroup.LayoutParams#FILL_PARENT}.
- */
- @Override
- protected LayoutParams generateDefaultLayoutParams() {
- return new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
- }
-
- /**
- * Supply a Drawable that is to be rendered on top of all of the child
- * views in the frame layout. Any padding in the Drawable will be taken
- * into account by ensuring that the children are inset to be placed
- * inside of the padding area.
- *
- * @param drawable The Drawable to be drawn on top of the children.
- *
- * @attr ref android.R.styleable#FrameLayout_foreground
- */
- public void setForeground(Drawable drawable) {
- if (mForeground != drawable) {
- if (mForeground != null) {
- mForeground.setCallback(null);
- unscheduleDrawable(mForeground);
- }
-
- mForeground = drawable;
- mForegroundPaddingLeft = 0;
- mForegroundPaddingTop = 0;
- mForegroundPaddingRight = 0;
- mForegroundPaddingBottom = 0;
-
- if (drawable != null) {
- setWillNotDraw(false);
- drawable.setCallback(this);
- if (drawable.isStateful()) {
- drawable.setState(getDrawableState());
- }
- Rect padding = new Rect();
- if (drawable.getPadding(padding)) {
- mForegroundPaddingLeft = padding.left;
- mForegroundPaddingTop = padding.top;
- mForegroundPaddingRight = padding.right;
- mForegroundPaddingBottom = padding.bottom;
- }
- } else {
- setWillNotDraw(true);
- }
- requestLayout();
- invalidate();
- }
- }
-
- /**
- * Returns the drawable used as the foreground of this FrameLayout. The
- * foreground drawable, if non-null, is always drawn on top of the children.
- *
- * @return A Drawable or null if no foreground was set.
- */
- public Drawable getForeground() {
- return mForeground;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int count = getChildCount();
-
- int maxHeight = 0;
- int maxWidth = 0;
-
- // Find rightmost and bottommost child
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (mMeasureAllChildren || child.getVisibility() != GONE) {
- measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
- maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
- maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
- }
- }
-
- // Account for padding too
- maxWidth += mPaddingLeft + mPaddingRight + mForegroundPaddingLeft + mForegroundPaddingRight;
- maxHeight += mPaddingTop + mPaddingBottom + mForegroundPaddingTop + mForegroundPaddingBottom;
-
- // Check against our minimum height and width
- maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
- maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
-
- // Check against our foreground's minimum height and width
- final Drawable drawable = getForeground();
- if (drawable != null) {
- maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
- maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
- }
-
- setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
- resolveSize(maxHeight, heightMeasureSpec));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- final int count = getChildCount();
-
- final int parentLeft = mPaddingLeft + mForegroundPaddingLeft;
- final int parentRight = right - left - mPaddingRight - mForegroundPaddingRight;
-
- final int parentTop = mPaddingTop + mForegroundPaddingTop;
- final int parentBottom = bottom - top - mPaddingBottom - mForegroundPaddingBottom;
-
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.getVisibility() != GONE) {
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
- final int width = child.getMeasuredWidth();
- final int height = child.getMeasuredHeight();
-
- int childLeft = parentLeft;
- int childTop = parentTop;
-
- final int gravity = lp.gravity;
-
- if (gravity != -1) {
- final int horizontalGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
- final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
-
- switch (horizontalGravity) {
- case Gravity.LEFT:
- childLeft = parentLeft + lp.leftMargin;
- break;
- case Gravity.CENTER_HORIZONTAL:
- childLeft = parentLeft + (parentRight - parentLeft + lp.leftMargin +
- lp.rightMargin - width) / 2;
- break;
- case Gravity.RIGHT:
- childLeft = parentRight - width - lp.rightMargin;
- break;
- default:
- childLeft = parentLeft + lp.leftMargin;
- }
-
- switch (verticalGravity) {
- case Gravity.TOP:
- childTop = parentTop + lp.topMargin;
- break;
- case Gravity.CENTER_VERTICAL:
- childTop = parentTop + (parentBottom - parentTop + lp.topMargin +
- lp.bottomMargin - height) / 2;
- break;
- case Gravity.BOTTOM:
- childTop = parentBottom - height - lp.bottomMargin;
- break;
- default:
- childTop = parentTop + lp.topMargin;
- }
- }
-
- child.layout(childLeft, childTop, childLeft + width, childTop + height);
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
-
- final Drawable foreground = mForeground;
- if (foreground != null) {
- final Rect selfBounds = mSelfBounds;
- final Rect overlayBounds = mOverlayBounds;
-
- selfBounds.set(0, 0, w, h);
- Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
- foreground.getIntrinsicHeight(), selfBounds, overlayBounds);
-
- foreground.setBounds(overlayBounds);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void draw(Canvas canvas) {
- super.draw(canvas);
-
- if (mForeground != null) {
- mForeground.draw(canvas);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean gatherTransparentRegion(Region region) {
- boolean opaque = super.gatherTransparentRegion(region);
- if (region != null && mForeground != null) {
- applyDrawableToTransparentRegion(mForeground, region);
- }
- return opaque;
- }
-
- /**
- * Determines whether to measure all children or just those in
- * the VISIBLE or INVISIBLE state when measuring. Defaults to false.
- * @param measureAll true to consider children marked GONE, false otherwise.
- * Default value is false.
- *
- * @attr ref android.R.styleable#FrameLayout_measureAllChildren
- */
- @android.view.RemotableViewMethod
- public void setMeasureAllChildren(boolean measureAll) {
- mMeasureAllChildren = measureAll;
- }
-
- /**
- * Determines whether to measure all children or just those in
- * the VISIBLE or INVISIBLE state when measuring.
- */
- public boolean getConsiderGoneChildrenWhenMeasuring() {
- return mMeasureAllChildren;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new FrameLayout.LayoutParams(getContext(), attrs);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof LayoutParams;
- }
-
- @Override
- protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return new LayoutParams(p);
- }
-
- /**
- * Per-child layout information for layouts that support margins.
- * See {@link android.R.styleable#FrameLayout_Layout FrameLayout Layout Attributes}
- * for a list of all child view attributes that this class supports.
- */
- public static class LayoutParams extends MarginLayoutParams {
- /**
- * The gravity to apply with the View to which these layout parameters
- * are associated.
- *
- * @see android.view.Gravity
- */
- public int gravity = -1;
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
-
- TypedArray a = c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.FrameLayout_Layout);
- gravity = a.getInt(com.android.internal.R.styleable.FrameLayout_Layout_layout_gravity, -1);
- a.recycle();
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(int width, int height) {
- super(width, height);
- }
-
- /**
- * Creates a new set of layout parameters with the specified width, height
- * and weight.
- *
- * @param width the width, either {@link #FILL_PARENT},
- * {@link #WRAP_CONTENT} or a fixed size in pixels
- * @param height the height, either {@link #FILL_PARENT},
- * {@link #WRAP_CONTENT} or a fixed size in pixels
- * @param gravity the gravity
- *
- * @see android.view.Gravity
- */
- public LayoutParams(int width, int height, int gravity) {
- super(width, height);
- this.gravity = gravity;
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(ViewGroup.LayoutParams source) {
- super(source);
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(ViewGroup.MarginLayoutParams source) {
- super(source);
- }
- }
-}
-
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
deleted file mode 100644
index e7b303a..0000000
--- a/core/java/android/widget/Gallery.java
+++ /dev/null
@@ -1,1408 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import com.android.internal.R;
-
-import android.annotation.Widget;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.util.Config;
-import android.util.Log;
-import android.view.GestureDetector;
-import android.view.Gravity;
-import android.view.HapticFeedbackConstants;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.SoundEffectConstants;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.animation.Transformation;
-import android.widget.AbsSpinner;
-import android.widget.Scroller;
-
-/**
- * A view that shows items in a center-locked, horizontally scrolling list.
- * <p>
- * The default values for the Gallery assume you will be using
- * {@link android.R.styleable#Theme_galleryItemBackground} as the background for
- * each View given to the Gallery from the Adapter. If you are not doing this,
- * you may need to adjust some Gallery properties, such as the spacing.
- * <p>
- * Views given to the Gallery should use {@link Gallery.LayoutParams} as their
- * layout parameters type.
- *
- * @attr ref android.R.styleable#Gallery_animationDuration
- * @attr ref android.R.styleable#Gallery_spacing
- * @attr ref android.R.styleable#Gallery_gravity
- */
-@Widget
-public class Gallery extends AbsSpinner implements GestureDetector.OnGestureListener {
-
- private static final String TAG = "Gallery";
-
- private static final boolean localLOGV = Config.LOGV;
-
- /**
- * Duration in milliseconds from the start of a scroll during which we're
- * unsure whether the user is scrolling or flinging.
- */
- private static final int SCROLL_TO_FLING_UNCERTAINTY_TIMEOUT = 250;
-
- /**
- * Horizontal spacing between items.
- */
- private int mSpacing = 0;
-
- /**
- * How long the transition animation should run when a child view changes
- * position, measured in milliseconds.
- */
- private int mAnimationDuration = 400;
-
- /**
- * The alpha of items that are not selected.
- */
- private float mUnselectedAlpha;
-
- /**
- * Left most edge of a child seen so far during layout.
- */
- private int mLeftMost;
-
- /**
- * Right most edge of a child seen so far during layout.
- */
- private int mRightMost;
-
- private int mGravity;
-
- /**
- * Helper for detecting touch gestures.
- */
- private GestureDetector mGestureDetector;
-
- /**
- * The position of the item that received the user's down touch.
- */
- private int mDownTouchPosition;
-
- /**
- * The view of the item that received the user's down touch.
- */
- private View mDownTouchView;
-
- /**
- * Executes the delta scrolls from a fling or scroll movement.
- */
- private FlingRunnable mFlingRunnable = new FlingRunnable();
-
- /**
- * Sets mSuppressSelectionChanged = false. This is used to set it to false
- * in the future. It will also trigger a selection changed.
- */
- private Runnable mDisableSuppressSelectionChangedRunnable = new Runnable() {
- public void run() {
- mSuppressSelectionChanged = false;
- selectionChanged();
- }
- };
-
- /**
- * When fling runnable runs, it resets this to false. Any method along the
- * path until the end of its run() can set this to true to abort any
- * remaining fling. For example, if we've reached either the leftmost or
- * rightmost item, we will set this to true.
- */
- private boolean mShouldStopFling;
-
- /**
- * The currently selected item's child.
- */
- private View mSelectedChild;
-
- /**
- * Whether to continuously callback on the item selected listener during a
- * fling.
- */
- private boolean mShouldCallbackDuringFling = true;
-
- /**
- * Whether to callback when an item that is not selected is clicked.
- */
- private boolean mShouldCallbackOnUnselectedItemClick = true;
-
- /**
- * If true, do not callback to item selected listener.
- */
- private boolean mSuppressSelectionChanged;
-
- /**
- * If true, we have received the "invoke" (center or enter buttons) key
- * down. This is checked before we action on the "invoke" key up, and is
- * subsequently cleared.
- */
- private boolean mReceivedInvokeKeyDown;
-
- private AdapterContextMenuInfo mContextMenuInfo;
-
- /**
- * If true, this onScroll is the first for this user's drag (remember, a
- * drag sends many onScrolls).
- */
- private boolean mIsFirstScroll;
-
- public Gallery(Context context) {
- this(context, null);
- }
-
- public Gallery(Context context, AttributeSet attrs) {
- this(context, attrs, R.attr.galleryStyle);
- }
-
- public Gallery(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- mGestureDetector = new GestureDetector(context, this);
- mGestureDetector.setIsLongpressEnabled(true);
-
- TypedArray a = context.obtainStyledAttributes(
- attrs, com.android.internal.R.styleable.Gallery, defStyle, 0);
-
- int index = a.getInt(com.android.internal.R.styleable.Gallery_gravity, -1);
- if (index >= 0) {
- setGravity(index);
- }
-
- int animationDuration =
- a.getInt(com.android.internal.R.styleable.Gallery_animationDuration, -1);
- if (animationDuration > 0) {
- setAnimationDuration(animationDuration);
- }
-
- int spacing =
- a.getDimensionPixelOffset(com.android.internal.R.styleable.Gallery_spacing, 0);
- setSpacing(spacing);
-
- float unselectedAlpha = a.getFloat(
- com.android.internal.R.styleable.Gallery_unselectedAlpha, 0.5f);
- setUnselectedAlpha(unselectedAlpha);
-
- a.recycle();
-
- // We draw the selected item last (because otherwise the item to the
- // right overlaps it)
- mGroupFlags |= FLAG_USE_CHILD_DRAWING_ORDER;
-
- mGroupFlags |= FLAG_SUPPORT_STATIC_TRANSFORMATIONS;
- }
-
- /**
- * Whether or not to callback on any {@link #getOnItemSelectedListener()}
- * while the items are being flinged. If false, only the final selected item
- * will cause the callback. If true, all items between the first and the
- * final will cause callbacks.
- *
- * @param shouldCallback Whether or not to callback on the listener while
- * the items are being flinged.
- */
- public void setCallbackDuringFling(boolean shouldCallback) {
- mShouldCallbackDuringFling = shouldCallback;
- }
-
- /**
- * Whether or not to callback when an item that is not selected is clicked.
- * If false, the item will become selected (and re-centered). If true, the
- * {@link #getOnItemClickListener()} will get the callback.
- *
- * @param shouldCallback Whether or not to callback on the listener when a
- * item that is not selected is clicked.
- * @hide
- */
- public void setCallbackOnUnselectedItemClick(boolean shouldCallback) {
- mShouldCallbackOnUnselectedItemClick = shouldCallback;
- }
-
- /**
- * Sets how long the transition animation should run when a child view
- * changes position. Only relevant if animation is turned on.
- *
- * @param animationDurationMillis The duration of the transition, in
- * milliseconds.
- *
- * @attr ref android.R.styleable#Gallery_animationDuration
- */
- public void setAnimationDuration(int animationDurationMillis) {
- mAnimationDuration = animationDurationMillis;
- }
-
- /**
- * Sets the spacing between items in a Gallery
- *
- * @param spacing The spacing in pixels between items in the Gallery
- *
- * @attr ref android.R.styleable#Gallery_spacing
- */
- public void setSpacing(int spacing) {
- mSpacing = spacing;
- }
-
- /**
- * Sets the alpha of items that are not selected in the Gallery.
- *
- * @param unselectedAlpha the alpha for the items that are not selected.
- *
- * @attr ref android.R.styleable#Gallery_unselectedAlpha
- */
- public void setUnselectedAlpha(float unselectedAlpha) {
- mUnselectedAlpha = unselectedAlpha;
- }
-
- @Override
- protected boolean getChildStaticTransformation(View child, Transformation t) {
-
- t.clear();
- t.setAlpha(child == mSelectedChild ? 1.0f : mUnselectedAlpha);
-
- return true;
- }
-
- @Override
- protected int computeHorizontalScrollExtent() {
- // Only 1 item is considered to be selected
- return 1;
- }
-
- @Override
- protected int computeHorizontalScrollOffset() {
- // Current scroll position is the same as the selected position
- return mSelectedPosition;
- }
-
- @Override
- protected int computeHorizontalScrollRange() {
- // Scroll range is the same as the item count
- return mItemCount;
- }
-
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof LayoutParams;
- }
-
- @Override
- protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return new LayoutParams(p);
- }
-
- @Override
- public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new LayoutParams(getContext(), attrs);
- }
-
- @Override
- protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
- /*
- * Gallery expects Gallery.LayoutParams.
- */
- return new Gallery.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
-
- /*
- * Remember that we are in layout to prevent more layout request from
- * being generated.
- */
- mInLayout = true;
- layout(0, false);
- mInLayout = false;
- }
-
- @Override
- int getChildHeight(View child) {
- return child.getMeasuredHeight();
- }
-
- /**
- * Tracks a motion scroll. In reality, this is used to do just about any
- * movement to items (touch scroll, arrow-key scroll, set an item as selected).
- *
- * @param deltaX Change in X from the previous event.
- */
- void trackMotionScroll(int deltaX) {
-
- if (getChildCount() == 0) {
- return;
- }
-
- boolean toLeft = deltaX < 0;
-
- int limitedDeltaX = getLimitedMotionScrollAmount(toLeft, deltaX);
- if (limitedDeltaX != deltaX) {
- // The above call returned a limited amount, so stop any scrolls/flings
- mFlingRunnable.endFling(false);
- onFinishedMovement();
- }
-
- offsetChildrenLeftAndRight(limitedDeltaX);
-
- detachOffScreenChildren(toLeft);
-
- if (toLeft) {
- // If moved left, there will be empty space on the right
- fillToGalleryRight();
- } else {
- // Similarly, empty space on the left
- fillToGalleryLeft();
- }
-
- // Clear unused views
- mRecycler.clear();
-
- setSelectionToCenterChild();
-
- invalidate();
- }
-
- int getLimitedMotionScrollAmount(boolean motionToLeft, int deltaX) {
- int extremeItemPosition = motionToLeft ? mItemCount - 1 : 0;
- View extremeChild = getChildAt(extremeItemPosition - mFirstPosition);
-
- if (extremeChild == null) {
- return deltaX;
- }
-
- int extremeChildCenter = getCenterOfView(extremeChild);
- int galleryCenter = getCenterOfGallery();
-
- if (motionToLeft) {
- if (extremeChildCenter <= galleryCenter) {
-
- // The extreme child is past his boundary point!
- return 0;
- }
- } else {
- if (extremeChildCenter >= galleryCenter) {
-
- // The extreme child is past his boundary point!
- return 0;
- }
- }
-
- int centerDifference = galleryCenter - extremeChildCenter;
-
- return motionToLeft
- ? Math.max(centerDifference, deltaX)
- : Math.min(centerDifference, deltaX);
- }
-
- /**
- * Offset the horizontal location of all children of this view by the
- * specified number of pixels.
- *
- * @param offset the number of pixels to offset
- */
- private void offsetChildrenLeftAndRight(int offset) {
- for (int i = getChildCount() - 1; i >= 0; i--) {
- getChildAt(i).offsetLeftAndRight(offset);
- }
- }
-
- /**
- * @return The center of this Gallery.
- */
- private int getCenterOfGallery() {
- return (getWidth() - mPaddingLeft - mPaddingRight) / 2 + mPaddingLeft;
- }
-
- /**
- * @return The center of the given view.
- */
- private static int getCenterOfView(View view) {
- return view.getLeft() + view.getWidth() / 2;
- }
-
- /**
- * Detaches children that are off the screen (i.e.: Gallery bounds).
- *
- * @param toLeft Whether to detach children to the left of the Gallery, or
- * to the right.
- */
- private void detachOffScreenChildren(boolean toLeft) {
- int numChildren = getChildCount();
- int firstPosition = mFirstPosition;
- int start = 0;
- int count = 0;
-
- if (toLeft) {
- final int galleryLeft = mPaddingLeft;
- for (int i = 0; i < numChildren; i++) {
- final View child = getChildAt(i);
- if (child.getRight() >= galleryLeft) {
- break;
- } else {
- count++;
- mRecycler.put(firstPosition + i, child);
- }
- }
- } else {
- final int galleryRight = getWidth() - mPaddingRight;
- for (int i = numChildren - 1; i >= 0; i--) {
- final View child = getChildAt(i);
- if (child.getLeft() <= galleryRight) {
- break;
- } else {
- start = i;
- count++;
- mRecycler.put(firstPosition + i, child);
- }
- }
- }
-
- detachViewsFromParent(start, count);
-
- if (toLeft) {
- mFirstPosition += count;
- }
- }
-
- /**
- * Scrolls the items so that the selected item is in its 'slot' (its center
- * is the gallery's center).
- */
- private void scrollIntoSlots() {
-
- if (getChildCount() == 0 || mSelectedChild == null) return;
-
- int selectedCenter = getCenterOfView(mSelectedChild);
- int targetCenter = getCenterOfGallery();
-
- int scrollAmount = targetCenter - selectedCenter;
- if (scrollAmount != 0) {
- mFlingRunnable.startUsingDistance(scrollAmount);
- } else {
- onFinishedMovement();
- }
- }
-
- private void onFinishedMovement() {
- if (mSuppressSelectionChanged) {
- mSuppressSelectionChanged = false;
-
- // We haven't been callbacking during the fling, so do it now
- super.selectionChanged();
- }
- }
-
- @Override
- void selectionChanged() {
- if (!mSuppressSelectionChanged) {
- super.selectionChanged();
- }
- }
-
- /**
- * Looks for the child that is closest to the center and sets it as the
- * selected child.
- */
- private void setSelectionToCenterChild() {
-
- View selView = mSelectedChild;
- if (mSelectedChild == null) return;
-
- int galleryCenter = getCenterOfGallery();
-
- if (selView != null) {
-
- // Common case where the current selected position is correct
- if (selView.getLeft() <= galleryCenter && selView.getRight() >= galleryCenter) {
- return;
- }
- }
-
- // TODO better search
- int closestEdgeDistance = Integer.MAX_VALUE;
- int newSelectedChildIndex = 0;
- for (int i = getChildCount() - 1; i >= 0; i--) {
-
- View child = getChildAt(i);
-
- if (child.getLeft() <= galleryCenter && child.getRight() >= galleryCenter) {
- // This child is in the center
- newSelectedChildIndex = i;
- break;
- }
-
- int childClosestEdgeDistance = Math.min(Math.abs(child.getLeft() - galleryCenter),
- Math.abs(child.getRight() - galleryCenter));
- if (childClosestEdgeDistance < closestEdgeDistance) {
- closestEdgeDistance = childClosestEdgeDistance;
- newSelectedChildIndex = i;
- }
- }
-
- int newPos = mFirstPosition + newSelectedChildIndex;
-
- if (newPos != mSelectedPosition) {
- setSelectedPositionInt(newPos);
- setNextSelectedPositionInt(newPos);
- checkSelectionChanged();
- }
- }
-
- /**
- * Creates and positions all views for this Gallery.
- * <p>
- * We layout rarely, most of the time {@link #trackMotionScroll(int)} takes
- * care of repositioning, adding, and removing children.
- *
- * @param delta Change in the selected position. +1 means the selection is
- * moving to the right, so views are scrolling to the left. -1
- * means the selection is moving to the left.
- */
- @Override
- void layout(int delta, boolean animate) {
-
- int childrenLeft = mSpinnerPadding.left;
- int childrenWidth = mRight - mLeft - mSpinnerPadding.left - mSpinnerPadding.right;
-
- if (mDataChanged) {
- handleDataChanged();
- }
-
- // Handle an empty gallery by removing all views.
- if (mItemCount == 0) {
- resetList();
- return;
- }
-
- // Update to the new selected position.
- if (mNextSelectedPosition >= 0) {
- setSelectedPositionInt(mNextSelectedPosition);
- }
-
- // All views go in recycler while we are in layout
- recycleAllViews();
-
- // Clear out old views
- //removeAllViewsInLayout();
- detachAllViewsFromParent();
-
- /*
- * These will be used to give initial positions to views entering the
- * gallery as we scroll
- */
- mRightMost = 0;
- mLeftMost = 0;
-
- // Make selected view and center it
-
- /*
- * mFirstPosition will be decreased as we add views to the left later
- * on. The 0 for x will be offset in a couple lines down.
- */
- mFirstPosition = mSelectedPosition;
- View sel = makeAndAddView(mSelectedPosition, 0, 0, true);
-
- // Put the selected child in the center
- Gallery.LayoutParams lp = (Gallery.LayoutParams) sel.getLayoutParams();
- int selectedOffset = childrenLeft + (childrenWidth / 2) - (sel.getWidth() / 2);
- sel.offsetLeftAndRight(selectedOffset);
-
- fillToGalleryRight();
- fillToGalleryLeft();
-
- // Flush any cached views that did not get reused above
- mRecycler.clear();
-
- invalidate();
- checkSelectionChanged();
-
- mDataChanged = false;
- mNeedSync = false;
- setNextSelectedPositionInt(mSelectedPosition);
-
- updateSelectedItemMetadata();
- }
-
- private void fillToGalleryLeft() {
- int itemSpacing = mSpacing;
- int galleryLeft = mPaddingLeft;
-
- // Set state for initial iteration
- View prevIterationView = getChildAt(0);
- int curPosition;
- int curRightEdge;
-
- if (prevIterationView != null) {
- curPosition = mFirstPosition - 1;
- curRightEdge = prevIterationView.getLeft() - itemSpacing;
- } else {
- // No children available!
- curPosition = 0;
- curRightEdge = mRight - mLeft - mPaddingRight;
- mShouldStopFling = true;
- }
-
- while (curRightEdge > galleryLeft && curPosition >= 0) {
- prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition,
- curRightEdge, false);
-
- // Remember some state
- mFirstPosition = curPosition;
-
- // Set state for next iteration
- curRightEdge = prevIterationView.getLeft() - itemSpacing;
- curPosition--;
- }
- }
-
- private void fillToGalleryRight() {
- int itemSpacing = mSpacing;
- int galleryRight = mRight - mLeft - mPaddingRight;
- int numChildren = getChildCount();
- int numItems = mItemCount;
-
- // Set state for initial iteration
- View prevIterationView = getChildAt(numChildren - 1);
- int curPosition;
- int curLeftEdge;
-
- if (prevIterationView != null) {
- curPosition = mFirstPosition + numChildren;
- curLeftEdge = prevIterationView.getRight() + itemSpacing;
- } else {
- mFirstPosition = curPosition = mItemCount - 1;
- curLeftEdge = mPaddingLeft;
- mShouldStopFling = true;
- }
-
- while (curLeftEdge < galleryRight && curPosition < numItems) {
- prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition,
- curLeftEdge, true);
-
- // Set state for next iteration
- curLeftEdge = prevIterationView.getRight() + itemSpacing;
- curPosition++;
- }
- }
-
- /**
- * Obtain a view, either by pulling an existing view from the recycler or by
- * getting a new one from the adapter. If we are animating, make sure there
- * is enough information in the view's layout parameters to animate from the
- * old to new positions.
- *
- * @param position Position in the gallery for the view to obtain
- * @param offset Offset from the selected position
- * @param x X-coordintate indicating where this view should be placed. This
- * will either be the left or right edge of the view, depending on
- * the fromLeft paramter
- * @param fromLeft Are we posiitoning views based on the left edge? (i.e.,
- * building from left to right)?
- * @return A view that has been added to the gallery
- */
- private View makeAndAddView(int position, int offset, int x,
- boolean fromLeft) {
-
- View child;
-
- if (!mDataChanged) {
- child = mRecycler.get(position);
- if (child != null) {
- // Can reuse an existing view
- Gallery.LayoutParams lp = (Gallery.LayoutParams)
- child.getLayoutParams();
-
- int childLeft = child.getLeft();
-
- // Remember left and right edges of where views have been placed
- mRightMost = Math.max(mRightMost, childLeft
- + child.getMeasuredWidth());
- mLeftMost = Math.min(mLeftMost, childLeft);
-
- // Position the view
- setUpChild(child, offset, x, fromLeft);
-
- return child;
- }
- }
-
- // Nothing found in the recycler -- ask the adapter for a view
- child = mAdapter.getView(position, null, this);
-
- // Position the view
- setUpChild(child, offset, x, fromLeft);
-
- return child;
- }
-
- /**
- * Helper for makeAndAddView to set the position of a view and fill out its
- * layout paramters.
- *
- * @param child The view to position
- * @param offset Offset from the selected position
- * @param x X-coordintate indicating where this view should be placed. This
- * will either be the left or right edge of the view, depending on
- * the fromLeft paramter
- * @param fromLeft Are we posiitoning views based on the left edge? (i.e.,
- * building from left to right)?
- */
- private void setUpChild(View child, int offset, int x, boolean fromLeft) {
-
- // Respect layout params that are already in the view. Otherwise
- // make some up...
- Gallery.LayoutParams lp = (Gallery.LayoutParams)
- child.getLayoutParams();
- if (lp == null) {
- lp = (Gallery.LayoutParams) generateDefaultLayoutParams();
- }
-
- addViewInLayout(child, fromLeft ? -1 : 0, lp);
-
- child.setSelected(offset == 0);
-
- // Get measure specs
- int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec,
- mSpinnerPadding.top + mSpinnerPadding.bottom, lp.height);
- int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec,
- mSpinnerPadding.left + mSpinnerPadding.right, lp.width);
-
- // Measure child
- child.measure(childWidthSpec, childHeightSpec);
-
- int childLeft;
- int childRight;
-
- // Position vertically based on gravity setting
- int childTop = calculateTop(child, lp, true);
- int childBottom = childTop + child.getMeasuredHeight();
-
- int width = child.getMeasuredWidth();
- if (fromLeft) {
- childLeft = x;
- childRight = childLeft + width;
- } else {
- childLeft = x - width;
- childRight = x;
- }
-
- child.layout(childLeft, childTop, childRight, childBottom);
- }
-
- /**
- * Figure out vertical placement based on mGravity
- *
- * @param child Child to place
- * @param lp LayoutParams for this view (just so we don't keep looking them
- * up)
- * @return Where the top of the child should be
- */
- private int calculateTop(View child, Gallery.LayoutParams lp, boolean duringLayout) {
- int myHeight = duringLayout ? mMeasuredHeight : getHeight();
- int childHeight = duringLayout ? child.getMeasuredHeight() : child.getHeight();
-
- int childTop = 0;
-
- switch (mGravity) {
- case Gravity.TOP:
- childTop = mSpinnerPadding.top;
- break;
- case Gravity.CENTER_VERTICAL:
- int availableSpace = myHeight - mSpinnerPadding.bottom
- - mSpinnerPadding.top - childHeight;
- childTop = mSpinnerPadding.top + (availableSpace / 2);
- break;
- case Gravity.BOTTOM:
- childTop = myHeight - mSpinnerPadding.bottom - childHeight;
- break;
- }
- return childTop;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
-
- // Give everything to the gesture detector
- boolean retValue = mGestureDetector.onTouchEvent(event);
-
- int action = event.getAction();
- if (action == MotionEvent.ACTION_UP) {
- // Helper method for lifted finger
- onUp();
- } else if (action == MotionEvent.ACTION_CANCEL) {
- onCancel();
- }
-
- return retValue;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean onSingleTapUp(MotionEvent e) {
-
- if (mDownTouchPosition >= 0) {
-
- // An item tap should make it selected, so scroll to this child.
- scrollToChild(mDownTouchPosition - mFirstPosition);
-
- // Also pass the click so the client knows, if it wants to.
- if (mShouldCallbackOnUnselectedItemClick || mDownTouchPosition == mSelectedPosition) {
- performItemClick(mDownTouchView, mDownTouchPosition, mAdapter
- .getItemId(mDownTouchPosition));
- }
-
- return true;
- }
-
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
-
- if (!mShouldCallbackDuringFling) {
- // We want to suppress selection changes
-
- // Remove any future code to set mSuppressSelectionChanged = false
- removeCallbacks(mDisableSuppressSelectionChangedRunnable);
-
- // This will get reset once we scroll into slots
- if (!mSuppressSelectionChanged) mSuppressSelectionChanged = true;
- }
-
- // Fling the gallery!
- mFlingRunnable.startUsingVelocity((int) -velocityX);
-
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
-
- if (localLOGV) Log.v(TAG, String.valueOf(e2.getX() - e1.getX()));
-
- /*
- * Now's a good time to tell our parent to stop intercepting our events!
- * The user has moved more than the slop amount, since GestureDetector
- * ensures this before calling this method. Also, if a parent is more
- * interested in this touch's events than we are, it would have
- * intercepted them by now (for example, we can assume when a Gallery is
- * in the ListView, a vertical scroll would not end up in this method
- * since a ListView would have intercepted it by now).
- */
- mParent.requestDisallowInterceptTouchEvent(true);
-
- // As the user scrolls, we want to callback selection changes so related-
- // info on the screen is up-to-date with the gallery's selection
- if (!mShouldCallbackDuringFling) {
- if (mIsFirstScroll) {
- /*
- * We're not notifying the client of selection changes during
- * the fling, and this scroll could possibly be a fling. Don't
- * do selection changes until we're sure it is not a fling.
- */
- if (!mSuppressSelectionChanged) mSuppressSelectionChanged = true;
- postDelayed(mDisableSuppressSelectionChangedRunnable, SCROLL_TO_FLING_UNCERTAINTY_TIMEOUT);
- }
- } else {
- if (mSuppressSelectionChanged) mSuppressSelectionChanged = false;
- }
-
- // Track the motion
- trackMotionScroll(-1 * (int) distanceX);
-
- mIsFirstScroll = false;
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean onDown(MotionEvent e) {
-
- // Kill any existing fling/scroll
- mFlingRunnable.stop(false);
-
- // Get the item's view that was touched
- mDownTouchPosition = pointToPosition((int) e.getX(), (int) e.getY());
-
- if (mDownTouchPosition >= 0) {
- mDownTouchView = getChildAt(mDownTouchPosition - mFirstPosition);
- mDownTouchView.setPressed(true);
- }
-
- // Reset the multiple-scroll tracking state
- mIsFirstScroll = true;
-
- // Must return true to get matching events for this down event.
- return true;
- }
-
- /**
- * Called when a touch event's action is MotionEvent.ACTION_UP.
- */
- void onUp() {
-
- if (mFlingRunnable.mScroller.isFinished()) {
- scrollIntoSlots();
- }
-
- dispatchUnpress();
- }
-
- /**
- * Called when a touch event's action is MotionEvent.ACTION_CANCEL.
- */
- void onCancel() {
- onUp();
- }
-
- /**
- * {@inheritDoc}
- */
- public void onLongPress(MotionEvent e) {
-
- if (mDownTouchPosition < 0) {
- return;
- }
-
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- long id = getItemIdAtPosition(mDownTouchPosition);
- dispatchLongPress(mDownTouchView, mDownTouchPosition, id);
- }
-
- // Unused methods from GestureDetector.OnGestureListener below
-
- /**
- * {@inheritDoc}
- */
- public void onShowPress(MotionEvent e) {
- }
-
- // Unused methods from GestureDetector.OnGestureListener above
-
- private void dispatchPress(View child) {
-
- if (child != null) {
- child.setPressed(true);
- }
-
- setPressed(true);
- }
-
- private void dispatchUnpress() {
-
- for (int i = getChildCount() - 1; i >= 0; i--) {
- getChildAt(i).setPressed(false);
- }
-
- setPressed(false);
- }
-
- @Override
- public void dispatchSetSelected(boolean selected) {
- /*
- * We don't want to pass the selected state given from its parent to its
- * children since this widget itself has a selected state to give to its
- * children.
- */
- }
-
- @Override
- protected void dispatchSetPressed(boolean pressed) {
-
- // Show the pressed state on the selected child
- if (mSelectedChild != null) {
- mSelectedChild.setPressed(pressed);
- }
- }
-
- @Override
- protected ContextMenuInfo getContextMenuInfo() {
- return mContextMenuInfo;
- }
-
- @Override
- public boolean showContextMenuForChild(View originalView) {
-
- final int longPressPosition = getPositionForView(originalView);
- if (longPressPosition < 0) {
- return false;
- }
-
- final long longPressId = mAdapter.getItemId(longPressPosition);
- return dispatchLongPress(originalView, longPressPosition, longPressId);
- }
-
- @Override
- public boolean showContextMenu() {
-
- if (isPressed() && mSelectedPosition >= 0) {
- int index = mSelectedPosition - mFirstPosition;
- View v = getChildAt(index);
- return dispatchLongPress(v, mSelectedPosition, mSelectedRowId);
- }
-
- return false;
- }
-
- private boolean dispatchLongPress(View view, int position, long id) {
- boolean handled = false;
-
- if (mOnItemLongClickListener != null) {
- handled = mOnItemLongClickListener.onItemLongClick(this, mDownTouchView,
- mDownTouchPosition, id);
- }
-
- if (!handled) {
- mContextMenuInfo = new AdapterContextMenuInfo(view, position, id);
- handled = super.showContextMenuForChild(this);
- }
-
- if (handled) {
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- }
-
- return handled;
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- // Gallery steals all key events
- return event.dispatch(this);
- }
-
- /**
- * Handles left, right, and clicking
- * @see android.view.View#onKeyDown
- */
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- switch (keyCode) {
-
- case KeyEvent.KEYCODE_DPAD_LEFT:
- if (movePrevious()) {
- playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
- }
- return true;
-
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- if (moveNext()) {
- playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
- }
- return true;
-
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_ENTER:
- mReceivedInvokeKeyDown = true;
- // fallthrough to default handling
- }
-
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_ENTER: {
-
- if (mReceivedInvokeKeyDown) {
- if (mItemCount > 0) {
-
- dispatchPress(mSelectedChild);
- postDelayed(new Runnable() {
- public void run() {
- dispatchUnpress();
- }
- }, ViewConfiguration.getPressedStateDuration());
-
- int selectedIndex = mSelectedPosition - mFirstPosition;
- performItemClick(getChildAt(selectedIndex), mSelectedPosition, mAdapter
- .getItemId(mSelectedPosition));
- }
- }
-
- // Clear the flag
- mReceivedInvokeKeyDown = false;
-
- return true;
- }
- }
-
- return super.onKeyUp(keyCode, event);
- }
-
- boolean movePrevious() {
- if (mItemCount > 0 && mSelectedPosition > 0) {
- scrollToChild(mSelectedPosition - mFirstPosition - 1);
- return true;
- } else {
- return false;
- }
- }
-
- boolean moveNext() {
- if (mItemCount > 0 && mSelectedPosition < mItemCount - 1) {
- scrollToChild(mSelectedPosition - mFirstPosition + 1);
- return true;
- } else {
- return false;
- }
- }
-
- private boolean scrollToChild(int childPosition) {
- View child = getChildAt(childPosition);
-
- if (child != null) {
- int distance = getCenterOfGallery() - getCenterOfView(child);
- mFlingRunnable.startUsingDistance(distance);
- return true;
- }
-
- return false;
- }
-
- @Override
- void setSelectedPositionInt(int position) {
- super.setSelectedPositionInt(position);
-
- // Updates any metadata we keep about the selected item.
- updateSelectedItemMetadata();
- }
-
- private void updateSelectedItemMetadata() {
-
- View oldSelectedChild = mSelectedChild;
-
- View child = mSelectedChild = getChildAt(mSelectedPosition - mFirstPosition);
- if (child == null) {
- return;
- }
-
- child.setSelected(true);
- child.setFocusable(true);
-
- if (hasFocus()) {
- child.requestFocus();
- }
-
- // We unfocus the old child down here so the above hasFocus check
- // returns true
- if (oldSelectedChild != null) {
-
- // Make sure its drawable state doesn't contain 'selected'
- oldSelectedChild.setSelected(false);
-
- // Make sure it is not focusable anymore, since otherwise arrow keys
- // can make this one be focused
- oldSelectedChild.setFocusable(false);
- }
-
- }
-
- /**
- * Describes how the child views are aligned.
- * @param gravity
- *
- * @attr ref android.R.styleable#Gallery_gravity
- */
- public void setGravity(int gravity)
- {
- if (mGravity != gravity) {
- mGravity = gravity;
- requestLayout();
- }
- }
-
- @Override
- protected int getChildDrawingOrder(int childCount, int i) {
- int selectedIndex = mSelectedPosition - mFirstPosition;
-
- // Just to be safe
- if (selectedIndex < 0) return i;
-
- if (i == childCount - 1) {
- // Draw the selected child last
- return selectedIndex;
- } else if (i >= selectedIndex) {
- // Move the children to the right of the selected child earlier one
- return i + 1;
- } else {
- // Keep the children to the left of the selected child the same
- return i;
- }
- }
-
- @Override
- protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
- super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
-
- /*
- * The gallery shows focus by focusing the selected item. So, give
- * focus to our selected item instead. We steal keys from our
- * selected item elsewhere.
- */
- if (gainFocus && mSelectedChild != null) {
- mSelectedChild.requestFocus(direction);
- }
-
- }
-
- /**
- * Responsible for fling behavior. Use {@link #startUsingVelocity(int)} to
- * initiate a fling. Each frame of the fling is handled in {@link #run()}.
- * A FlingRunnable will keep re-posting itself until the fling is done.
- *
- */
- private class FlingRunnable implements Runnable {
- /**
- * Tracks the decay of a fling scroll
- */
- private Scroller mScroller;
-
- /**
- * X value reported by mScroller on the previous fling
- */
- private int mLastFlingX;
-
- public FlingRunnable() {
- mScroller = new Scroller(getContext());
- }
-
- private void startCommon() {
- // Remove any pending flings
- removeCallbacks(this);
- }
-
- public void startUsingVelocity(int initialVelocity) {
- if (initialVelocity == 0) return;
-
- startCommon();
-
- int initialX = initialVelocity < 0 ? Integer.MAX_VALUE : 0;
- mLastFlingX = initialX;
- mScroller.fling(initialX, 0, initialVelocity, 0,
- 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
- post(this);
- }
-
- public void startUsingDistance(int distance) {
- if (distance == 0) return;
-
- startCommon();
-
- mLastFlingX = 0;
- mScroller.startScroll(0, 0, -distance, 0, mAnimationDuration);
- post(this);
- }
-
- public void stop(boolean scrollIntoSlots) {
- removeCallbacks(this);
- endFling(scrollIntoSlots);
- }
-
- private void endFling(boolean scrollIntoSlots) {
- /*
- * Force the scroller's status to finished (without setting its
- * position to the end)
- */
- mScroller.forceFinished(true);
-
- if (scrollIntoSlots) scrollIntoSlots();
- }
-
- public void run() {
-
- if (mItemCount == 0) {
- endFling(true);
- return;
- }
-
- mShouldStopFling = false;
-
- final Scroller scroller = mScroller;
- boolean more = scroller.computeScrollOffset();
- final int x = scroller.getCurrX();
-
- // Flip sign to convert finger direction to list items direction
- // (e.g. finger moving down means list is moving towards the top)
- int delta = mLastFlingX - x;
-
- // Pretend that each frame of a fling scroll is a touch scroll
- if (delta > 0) {
- // Moving towards the left. Use first view as mDownTouchPosition
- mDownTouchPosition = mFirstPosition;
-
- // Don't fling more than 1 screen
- delta = Math.min(getWidth() - mPaddingLeft - mPaddingRight - 1, delta);
- } else {
- // Moving towards the right. Use last view as mDownTouchPosition
- int offsetToLast = getChildCount() - 1;
- mDownTouchPosition = mFirstPosition + offsetToLast;
-
- // Don't fling more than 1 screen
- delta = Math.max(-(getWidth() - mPaddingRight - mPaddingLeft - 1), delta);
- }
-
- trackMotionScroll(delta);
-
- if (more && !mShouldStopFling) {
- mLastFlingX = x;
- post(this);
- } else {
- endFling(true);
- }
- }
-
- }
-
- /**
- * Gallery extends LayoutParams to provide a place to hold current
- * Transformation information along with previous position/transformation
- * info.
- *
- */
- public static class LayoutParams extends ViewGroup.LayoutParams {
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
- }
-
- public LayoutParams(int w, int h) {
- super(w, h);
- }
-
- public LayoutParams(ViewGroup.LayoutParams source) {
- super(source);
- }
- }
-}
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
deleted file mode 100644
index 38bfc7c..0000000
--- a/core/java/android/widget/GridView.java
+++ /dev/null
@@ -1,1842 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.SoundEffectConstants;
-import android.view.animation.GridLayoutAnimationController;
-
-
-/**
- * A view that shows items in two-dimensional scrolling grid. The items in the
- * grid come from the {@link ListAdapter} associated with this view.
- */
-public class GridView extends AbsListView {
- public static final int NO_STRETCH = 0;
- public static final int STRETCH_SPACING = 1;
- public static final int STRETCH_COLUMN_WIDTH = 2;
- public static final int STRETCH_SPACING_UNIFORM = 3;
-
- public static final int AUTO_FIT = -1;
-
- private int mNumColumns = AUTO_FIT;
-
- private int mHorizontalSpacing = 0;
- private int mRequestedHorizontalSpacing;
- private int mVerticalSpacing = 0;
- private int mStretchMode = STRETCH_COLUMN_WIDTH;
- private int mColumnWidth;
- private int mRequestedColumnWidth;
- private int mRequestedNumColumns;
-
- private View mReferenceView = null;
- private View mReferenceViewInSelectedRow = null;
-
- private int mGravity = Gravity.LEFT;
-
- private final Rect mTempRect = new Rect();
-
- public GridView(Context context) {
- super(context);
- }
-
- public GridView(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.gridViewStyle);
- }
-
- public GridView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.GridView, defStyle, 0);
-
- int hSpacing = a.getDimensionPixelOffset(
- com.android.internal.R.styleable.GridView_horizontalSpacing, 0);
- setHorizontalSpacing(hSpacing);
-
- int vSpacing = a.getDimensionPixelOffset(
- com.android.internal.R.styleable.GridView_verticalSpacing, 0);
- setVerticalSpacing(vSpacing);
-
- int index = a.getInt(com.android.internal.R.styleable.GridView_stretchMode, STRETCH_COLUMN_WIDTH);
- if (index >= 0) {
- setStretchMode(index);
- }
-
- int columnWidth = a.getDimensionPixelOffset(com.android.internal.R.styleable.GridView_columnWidth, -1);
- if (columnWidth > 0) {
- setColumnWidth(columnWidth);
- }
-
- int numColumns = a.getInt(com.android.internal.R.styleable.GridView_numColumns, 1);
- setNumColumns(numColumns);
-
- index = a.getInt(com.android.internal.R.styleable.GridView_gravity, -1);
- if (index >= 0) {
- setGravity(index);
- }
-
- a.recycle();
- }
-
- @Override
- public ListAdapter getAdapter() {
- return mAdapter;
- }
-
- /**
- * Sets the data behind this GridView.
- *
- * @param adapter the adapter providing the grid's data
- */
- @Override
- public void setAdapter(ListAdapter adapter) {
- if (null != mAdapter) {
- mAdapter.unregisterDataSetObserver(mDataSetObserver);
- }
-
- resetList();
- mRecycler.clear();
- mAdapter = adapter;
-
- mOldSelectedPosition = INVALID_POSITION;
- mOldSelectedRowId = INVALID_ROW_ID;
-
- if (mAdapter != null) {
- mOldItemCount = mItemCount;
- mItemCount = mAdapter.getCount();
- mDataChanged = true;
- checkFocus();
-
- mDataSetObserver = new AdapterDataSetObserver();
- mAdapter.registerDataSetObserver(mDataSetObserver);
-
- mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());
-
- int position;
- if (mStackFromBottom) {
- position = lookForSelectablePosition(mItemCount - 1, false);
- } else {
- position = lookForSelectablePosition(0, true);
- }
- setSelectedPositionInt(position);
- setNextSelectedPositionInt(position);
- checkSelectionChanged();
- } else {
- checkFocus();
- // Nothing selected
- checkSelectionChanged();
- }
-
- requestLayout();
- }
-
- @Override
- int lookForSelectablePosition(int position, boolean lookDown) {
- final ListAdapter adapter = mAdapter;
- if (adapter == null || isInTouchMode()) {
- return INVALID_POSITION;
- }
-
- if (position < 0 || position >= mItemCount) {
- return INVALID_POSITION;
- }
- return position;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- void fillGap(boolean down) {
- final int numColumns = mNumColumns;
- final int verticalSpacing = mVerticalSpacing;
-
- final int count = getChildCount();
-
- if (down) {
- final int startOffset = count > 0 ?
- getChildAt(count - 1).getBottom() + verticalSpacing : getListPaddingTop();
- int position = mFirstPosition + count;
- if (mStackFromBottom) {
- position += numColumns - 1;
- }
- fillDown(position, startOffset);
- correctTooHigh(numColumns, verticalSpacing, getChildCount());
- } else {
- final int startOffset = count > 0 ?
- getChildAt(0).getTop() - verticalSpacing : getHeight() - getListPaddingBottom();
- int position = mFirstPosition;
- if (!mStackFromBottom) {
- position -= numColumns;
- } else {
- position--;
- }
- fillUp(position, startOffset);
- correctTooLow(numColumns, verticalSpacing, getChildCount());
- }
- }
-
- /**
- * Fills the list from pos down to the end of the list view.
- *
- * @param pos The first position to put in the list
- *
- * @param nextTop The location where the top of the item associated with pos
- * should be drawn
- *
- * @return The view that is currently selected, if it happens to be in the
- * range that we draw.
- */
- private View fillDown(int pos, int nextTop) {
- View selectedView = null;
-
- final int end = (mBottom - mTop) - mListPadding.bottom;
-
- while (nextTop < end && pos < mItemCount) {
- View temp = makeRow(pos, nextTop, true);
- if (temp != null) {
- selectedView = temp;
- }
-
- nextTop = mReferenceView.getBottom() + mVerticalSpacing;
-
- pos += mNumColumns;
- }
-
- return selectedView;
- }
-
- private View makeRow(int startPos, int y, boolean flow) {
- final int columnWidth = mColumnWidth;
- final int horizontalSpacing = mHorizontalSpacing;
-
- int last;
- int nextLeft = mListPadding.left + ((mStretchMode == STRETCH_SPACING_UNIFORM) ? horizontalSpacing : 0);
-
- if (!mStackFromBottom) {
- last = Math.min(startPos + mNumColumns, mItemCount);
- } else {
- last = startPos + 1;
- startPos = Math.max(0, startPos - mNumColumns + 1);
-
- if (last - startPos < mNumColumns) {
- nextLeft += (mNumColumns - (last - startPos)) * (columnWidth + horizontalSpacing);
- }
- }
-
- View selectedView = null;
-
- final boolean hasFocus = shouldShowSelector();
- final boolean inClick = touchModeDrawsInPressedState();
- final int selectedPosition = mSelectedPosition;
-
- mReferenceView = null;
-
- for (int pos = startPos; pos < last; pos++) {
- // is this the selected item?
- boolean selected = pos == selectedPosition;
- // does the list view have focus or contain focus
-
- final int where = flow ? -1 : pos - startPos;
- final View child = makeAndAddView(pos, y, flow, nextLeft, selected, where);
- mReferenceView = child;
-
- nextLeft += columnWidth;
- if (pos < last - 1) {
- nextLeft += horizontalSpacing;
- }
-
- if (selected && (hasFocus || inClick)) {
- selectedView = child;
- }
- }
-
- if (selectedView != null) {
- mReferenceViewInSelectedRow = mReferenceView;
- }
-
- return selectedView;
- }
-
- /**
- * Fills the list from pos up to the top of the list view.
- *
- * @param pos The first position to put in the list
- *
- * @param nextBottom The location where the bottom of the item associated
- * with pos should be drawn
- *
- * @return The view that is currently selected
- */
- private View fillUp(int pos, int nextBottom) {
- View selectedView = null;
-
- final int end = mListPadding.top;
-
- while (nextBottom > end && pos >= 0) {
-
- View temp = makeRow(pos, nextBottom, false);
- if (temp != null) {
- selectedView = temp;
- }
-
- nextBottom = mReferenceView.getTop() - mVerticalSpacing;
-
- mFirstPosition = pos;
-
- pos -= mNumColumns;
- }
-
- if (mStackFromBottom) {
- mFirstPosition = Math.max(0, pos + 1);
- }
-
- return selectedView;
- }
-
- /**
- * Fills the list from top to bottom, starting with mFirstPosition
- *
- * @param nextTop The location where the top of the first item should be
- * drawn
- *
- * @return The view that is currently selected
- */
- private View fillFromTop(int nextTop) {
- mFirstPosition = Math.min(mFirstPosition, mSelectedPosition);
- mFirstPosition = Math.min(mFirstPosition, mItemCount - 1);
- if (mFirstPosition < 0) {
- mFirstPosition = 0;
- }
- mFirstPosition -= mFirstPosition % mNumColumns;
- return fillDown(mFirstPosition, nextTop);
- }
-
- private View fillFromBottom(int lastPosition, int nextBottom) {
- lastPosition = Math.max(lastPosition, mSelectedPosition);
- lastPosition = Math.min(lastPosition, mItemCount - 1);
-
- final int invertedPosition = mItemCount - 1 - lastPosition;
- lastPosition = mItemCount - 1 - (invertedPosition - (invertedPosition % mNumColumns));
-
- return fillUp(lastPosition, nextBottom);
- }
-
- private View fillSelection(int childrenTop, int childrenBottom) {
- final int selectedPosition = reconcileSelectedPosition();
- final int numColumns = mNumColumns;
- final int verticalSpacing = mVerticalSpacing;
-
- int rowStart;
- int rowEnd = -1;
-
- if (!mStackFromBottom) {
- rowStart = selectedPosition - (selectedPosition % numColumns);
- } else {
- final int invertedSelection = mItemCount - 1 - selectedPosition;
-
- rowEnd = mItemCount - 1 - (invertedSelection - (invertedSelection % numColumns));
- rowStart = Math.max(0, rowEnd - numColumns + 1);
- }
-
- final int fadingEdgeLength = getVerticalFadingEdgeLength();
- final int topSelectionPixel = getTopSelectionPixel(childrenTop, fadingEdgeLength, rowStart);
-
- final View sel = makeRow(mStackFromBottom ? rowEnd : rowStart, topSelectionPixel, true);
- mFirstPosition = rowStart;
-
- final View referenceView = mReferenceView;
-
- if (!mStackFromBottom) {
- fillDown(rowStart + numColumns, referenceView.getBottom() + verticalSpacing);
- pinToBottom(childrenBottom);
- fillUp(rowStart - numColumns, referenceView.getTop() - verticalSpacing);
- adjustViewsUpOrDown();
- } else {
- final int bottomSelectionPixel = getBottomSelectionPixel(childrenBottom,
- fadingEdgeLength, numColumns, rowStart);
- final int offset = bottomSelectionPixel - referenceView.getBottom();
- offsetChildrenTopAndBottom(offset);
- fillUp(rowStart - 1, referenceView.getTop() - verticalSpacing);
- pinToTop(childrenTop);
- fillDown(rowEnd + numColumns, referenceView.getBottom() + verticalSpacing);
- adjustViewsUpOrDown();
- }
-
- return sel;
- }
-
- private void pinToTop(int childrenTop) {
- if (mFirstPosition == 0) {
- final int top = getChildAt(0).getTop();
- final int offset = childrenTop - top;
- if (offset < 0) {
- offsetChildrenTopAndBottom(offset);
- }
- }
- }
-
- private void pinToBottom(int childrenBottom) {
- final int count = getChildCount();
- if (mFirstPosition + count == mItemCount) {
- final int bottom = getChildAt(count - 1).getBottom();
- final int offset = childrenBottom - bottom;
- if (offset > 0) {
- offsetChildrenTopAndBottom(offset);
- }
- }
- }
-
- @Override
- int findMotionRow(int y) {
- final int childCount = getChildCount();
- if (childCount > 0) {
-
- final int numColumns = mNumColumns;
- if (!mStackFromBottom) {
- for (int i = 0; i < childCount; i += numColumns) {
- if (y <= getChildAt(i).getBottom()) {
- return mFirstPosition + i;
- }
- }
- } else {
- for (int i = childCount - 1; i >= 0; i -= numColumns) {
- if (y >= getChildAt(i).getTop()) {
- return mFirstPosition + i;
- }
- }
- }
-
- return mFirstPosition + childCount - 1;
- }
- return INVALID_POSITION;
- }
-
- /**
- * Layout during a scroll that results from tracking motion events. Places
- * the mMotionPosition view at the offset specified by mMotionViewTop, and
- * then build surrounding views from there.
- *
- * @param position the position at which to start filling
- * @param top the top of the view at that position
- * @return The selected view, or null if the selected view is outside the
- * visible area.
- */
- private View fillSpecific(int position, int top) {
- final int numColumns = mNumColumns;
-
- int motionRowStart;
- int motionRowEnd = -1;
-
- if (!mStackFromBottom) {
- motionRowStart = position - (position % numColumns);
- } else {
- final int invertedSelection = mItemCount - 1 - position;
-
- motionRowEnd = mItemCount - 1 - (invertedSelection - (invertedSelection % numColumns));
- motionRowStart = Math.max(0, motionRowEnd - numColumns + 1);
- }
-
- final View temp = makeRow(mStackFromBottom ? motionRowEnd : motionRowStart, top, true);
-
- // Possibly changed again in fillUp if we add rows above this one.
- mFirstPosition = motionRowStart;
-
- final View referenceView = mReferenceView;
- final int verticalSpacing = mVerticalSpacing;
-
- View above;
- View below;
-
- if (!mStackFromBottom) {
- above = fillUp(motionRowStart - numColumns, referenceView.getTop() - verticalSpacing);
- adjustViewsUpOrDown();
- below = fillDown(motionRowStart + numColumns, referenceView.getBottom() + verticalSpacing);
- // Check if we have dragged the bottom of the grid too high
- final int childCount = getChildCount();
- if (childCount > 0) {
- correctTooHigh(numColumns, verticalSpacing, childCount);
- }
- } else {
- below = fillDown(motionRowEnd + numColumns, referenceView.getBottom() + verticalSpacing);
- adjustViewsUpOrDown();
- above = fillUp(motionRowStart - 1, referenceView.getTop() - verticalSpacing);
- // Check if we have dragged the bottom of the grid too high
- final int childCount = getChildCount();
- if (childCount > 0) {
- correctTooLow(numColumns, verticalSpacing, childCount);
- }
- }
-
- if (temp != null) {
- return temp;
- } else if (above != null) {
- return above;
- } else {
- return below;
- }
- }
-
- private void correctTooHigh(int numColumns, int verticalSpacing, int childCount) {
- // First see if the last item is visible
- final int lastPosition = mFirstPosition + childCount - 1;
- if (lastPosition == mItemCount - 1 && childCount > 0) {
- // Get the last child ...
- final View lastChild = getChildAt(childCount - 1);
-
- // ... and its bottom edge
- final int lastBottom = lastChild.getBottom();
- // This is bottom of our drawable area
- final int end = (mBottom - mTop) - mListPadding.bottom;
-
- // This is how far the bottom edge of the last view is from the bottom of the
- // drawable area
- int bottomOffset = end - lastBottom;
-
- final View firstChild = getChildAt(0);
- final int firstTop = firstChild.getTop();
-
- // Make sure we are 1) Too high, and 2) Either there are more rows above the
- // first row or the first row is scrolled off the top of the drawable area
- if (bottomOffset > 0 && (mFirstPosition > 0 || firstTop < mListPadding.top)) {
- if (mFirstPosition == 0) {
- // Don't pull the top too far down
- bottomOffset = Math.min(bottomOffset, mListPadding.top - firstTop);
- }
-
- // Move everything down
- offsetChildrenTopAndBottom(bottomOffset);
- if (mFirstPosition > 0) {
- // Fill the gap that was opened above mFirstPosition with more rows, if
- // possible
- fillUp(mFirstPosition - (mStackFromBottom ? 1 : numColumns),
- firstChild.getTop() - verticalSpacing);
- // Close up the remaining gap
- adjustViewsUpOrDown();
- }
- }
- }
- }
-
- private void correctTooLow(int numColumns, int verticalSpacing, int childCount) {
- if (mFirstPosition == 0 && childCount > 0) {
- // Get the first child ...
- final View firstChild = getChildAt(0);
-
- // ... and its top edge
- final int firstTop = firstChild.getTop();
-
- // This is top of our drawable area
- final int start = mListPadding.top;
-
- // This is bottom of our drawable area
- final int end = (mBottom - mTop) - mListPadding.bottom;
-
- // This is how far the top edge of the first view is from the top of the
- // drawable area
- int topOffset = firstTop - start;
- final View lastChild = getChildAt(childCount - 1);
- final int lastBottom = lastChild.getBottom();
- final int lastPosition = mFirstPosition + childCount - 1;
-
- // Make sure we are 1) Too low, and 2) Either there are more rows below the
- // last row or the last row is scrolled off the bottom of the drawable area
- if (topOffset > 0 && (lastPosition < mItemCount - 1 || lastBottom > end)) {
- if (lastPosition == mItemCount - 1 ) {
- // Don't pull the bottom too far up
- topOffset = Math.min(topOffset, lastBottom - end);
- }
-
- // Move everything up
- offsetChildrenTopAndBottom(-topOffset);
- if (lastPosition < mItemCount - 1) {
- // Fill the gap that was opened below the last position with more rows, if
- // possible
- fillDown(lastPosition + (!mStackFromBottom ? 1 : numColumns),
- lastChild.getBottom() + verticalSpacing);
- // Close up the remaining gap
- adjustViewsUpOrDown();
- }
- }
- }
- }
-
- /**
- * Fills the grid based on positioning the new selection at a specific
- * location. The selection may be moved so that it does not intersect the
- * faded edges. The grid is then filled upwards and downwards from there.
- *
- * @param selectedTop Where the selected item should be
- * @param childrenTop Where to start drawing children
- * @param childrenBottom Last pixel where children can be drawn
- * @return The view that currently has selection
- */
- private View fillFromSelection(int selectedTop, int childrenTop, int childrenBottom) {
- final int fadingEdgeLength = getVerticalFadingEdgeLength();
- final int selectedPosition = mSelectedPosition;
- final int numColumns = mNumColumns;
- final int verticalSpacing = mVerticalSpacing;
-
- int rowStart;
- int rowEnd = -1;
-
- if (!mStackFromBottom) {
- rowStart = selectedPosition - (selectedPosition % numColumns);
- } else {
- int invertedSelection = mItemCount - 1 - selectedPosition;
-
- rowEnd = mItemCount - 1 - (invertedSelection - (invertedSelection % numColumns));
- rowStart = Math.max(0, rowEnd - numColumns + 1);
- }
-
- View sel;
- View referenceView;
-
- int topSelectionPixel = getTopSelectionPixel(childrenTop, fadingEdgeLength, rowStart);
- int bottomSelectionPixel = getBottomSelectionPixel(childrenBottom, fadingEdgeLength,
- numColumns, rowStart);
-
- sel = makeRow(mStackFromBottom ? rowEnd : rowStart, selectedTop, true);
- // Possibly changed again in fillUp if we add rows above this one.
- mFirstPosition = rowStart;
-
- referenceView = mReferenceView;
- adjustForTopFadingEdge(referenceView, topSelectionPixel, bottomSelectionPixel);
- adjustForBottomFadingEdge(referenceView, topSelectionPixel, bottomSelectionPixel);
-
- if (!mStackFromBottom) {
- fillUp(rowStart - numColumns, referenceView.getTop() - verticalSpacing);
- adjustViewsUpOrDown();
- fillDown(rowStart + numColumns, referenceView.getBottom() + verticalSpacing);
- } else {
- fillDown(rowEnd + numColumns, referenceView.getBottom() + verticalSpacing);
- adjustViewsUpOrDown();
- fillUp(rowStart - 1, referenceView.getTop() - verticalSpacing);
- }
-
-
- return sel;
- }
-
- /**
- * Calculate the bottom-most pixel we can draw the selection into
- *
- * @param childrenBottom Bottom pixel were children can be drawn
- * @param fadingEdgeLength Length of the fading edge in pixels, if present
- * @param numColumns Number of columns in the grid
- * @param rowStart The start of the row that will contain the selection
- * @return The bottom-most pixel we can draw the selection into
- */
- private int getBottomSelectionPixel(int childrenBottom, int fadingEdgeLength,
- int numColumns, int rowStart) {
- // Last pixel we can draw the selection into
- int bottomSelectionPixel = childrenBottom;
- if (rowStart + numColumns - 1 < mItemCount - 1) {
- bottomSelectionPixel -= fadingEdgeLength;
- }
- return bottomSelectionPixel;
- }
-
- /**
- * Calculate the top-most pixel we can draw the selection into
- *
- * @param childrenTop Top pixel were children can be drawn
- * @param fadingEdgeLength Length of the fading edge in pixels, if present
- * @param rowStart The start of the row that will contain the selection
- * @return The top-most pixel we can draw the selection into
- */
- private int getTopSelectionPixel(int childrenTop, int fadingEdgeLength, int rowStart) {
- // first pixel we can draw the selection into
- int topSelectionPixel = childrenTop;
- if (rowStart > 0) {
- topSelectionPixel += fadingEdgeLength;
- }
- return topSelectionPixel;
- }
-
- /**
- * Move all views upwards so the selected row does not interesect the bottom
- * fading edge (if necessary).
- *
- * @param childInSelectedRow A child in the row that contains the selection
- * @param topSelectionPixel The topmost pixel we can draw the selection into
- * @param bottomSelectionPixel The bottommost pixel we can draw the
- * selection into
- */
- private void adjustForBottomFadingEdge(View childInSelectedRow,
- int topSelectionPixel, int bottomSelectionPixel) {
- // Some of the newly selected item extends below the bottom of the
- // list
- if (childInSelectedRow.getBottom() > bottomSelectionPixel) {
-
- // Find space available above the selection into which we can
- // scroll upwards
- int spaceAbove = childInSelectedRow.getTop() - topSelectionPixel;
-
- // Find space required to bring the bottom of the selected item
- // fully into view
- int spaceBelow = childInSelectedRow.getBottom() - bottomSelectionPixel;
- int offset = Math.min(spaceAbove, spaceBelow);
-
- // Now offset the selected item to get it into view
- offsetChildrenTopAndBottom(-offset);
- }
- }
-
- /**
- * Move all views upwards so the selected row does not interesect the top
- * fading edge (if necessary).
- *
- * @param childInSelectedRow A child in the row that contains the selection
- * @param topSelectionPixel The topmost pixel we can draw the selection into
- * @param bottomSelectionPixel The bottommost pixel we can draw the
- * selection into
- */
- private void adjustForTopFadingEdge(View childInSelectedRow,
- int topSelectionPixel, int bottomSelectionPixel) {
- // Some of the newly selected item extends above the top of the list
- if (childInSelectedRow.getTop() < topSelectionPixel) {
- // Find space required to bring the top of the selected item
- // fully into view
- int spaceAbove = topSelectionPixel - childInSelectedRow.getTop();
-
- // Find space available below the selection into which we can
- // scroll downwards
- int spaceBelow = bottomSelectionPixel - childInSelectedRow.getBottom();
- int offset = Math.min(spaceAbove, spaceBelow);
-
- // Now offset the selected item to get it into view
- offsetChildrenTopAndBottom(offset);
- }
- }
-
- /**
- * Fills the grid based on positioning the new selection relative to the old
- * selection. The new selection will be placed at, above, or below the
- * location of the new selection depending on how the selection is moving.
- * The selection will then be pinned to the visible part of the screen,
- * excluding the edges that are faded. The grid is then filled upwards and
- * downwards from there.
- *
- * @param delta Which way we are moving
- * @param childrenTop Where to start drawing children
- * @param childrenBottom Last pixel where children can be drawn
- * @return The view that currently has selection
- */
- private View moveSelection(int delta, int childrenTop, int childrenBottom) {
- final int fadingEdgeLength = getVerticalFadingEdgeLength();
- final int selectedPosition = mSelectedPosition;
- final int numColumns = mNumColumns;
- final int verticalSpacing = mVerticalSpacing;
-
- int oldRowStart;
- int rowStart;
- int rowEnd = -1;
-
- if (!mStackFromBottom) {
- oldRowStart = (selectedPosition - delta) - ((selectedPosition - delta) % numColumns);
-
- rowStart = selectedPosition - (selectedPosition % numColumns);
- } else {
- int invertedSelection = mItemCount - 1 - selectedPosition;
-
- rowEnd = mItemCount - 1 - (invertedSelection - (invertedSelection % numColumns));
- rowStart = Math.max(0, rowEnd - numColumns + 1);
-
- invertedSelection = mItemCount - 1 - (selectedPosition - delta);
- oldRowStart = mItemCount - 1 - (invertedSelection - (invertedSelection % numColumns));
- oldRowStart = Math.max(0, oldRowStart - numColumns + 1);
- }
-
- final int rowDelta = rowStart - oldRowStart;
-
- final int topSelectionPixel = getTopSelectionPixel(childrenTop, fadingEdgeLength, rowStart);
- final int bottomSelectionPixel = getBottomSelectionPixel(childrenBottom, fadingEdgeLength,
- numColumns, rowStart);
-
- // Possibly changed again in fillUp if we add rows above this one.
- mFirstPosition = rowStart;
-
- View sel;
- View referenceView;
-
- if (rowDelta > 0) {
- /*
- * Case 1: Scrolling down.
- */
-
- final int oldBottom = mReferenceViewInSelectedRow == null ? 0 :
- mReferenceViewInSelectedRow.getBottom();
-
- sel = makeRow(mStackFromBottom ? rowEnd : rowStart, oldBottom + verticalSpacing, true);
- referenceView = mReferenceView;
-
- adjustForBottomFadingEdge(referenceView, topSelectionPixel, bottomSelectionPixel);
- } else if (rowDelta < 0) {
- /*
- * Case 2: Scrolling up.
- */
- final int oldTop = mReferenceViewInSelectedRow == null ?
- 0 : mReferenceViewInSelectedRow .getTop();
-
- sel = makeRow(mStackFromBottom ? rowEnd : rowStart, oldTop - verticalSpacing, false);
- referenceView = mReferenceView;
-
- adjustForTopFadingEdge(referenceView, topSelectionPixel, bottomSelectionPixel);
- } else {
- /*
- * Keep selection where it was
- */
- final int oldTop = mReferenceViewInSelectedRow == null ?
- 0 : mReferenceViewInSelectedRow .getTop();
-
- sel = makeRow(mStackFromBottom ? rowEnd : rowStart, oldTop, true);
- referenceView = mReferenceView;
- }
-
- if (!mStackFromBottom) {
- fillUp(rowStart - numColumns, referenceView.getTop() - verticalSpacing);
- adjustViewsUpOrDown();
- fillDown(rowStart + numColumns, referenceView.getBottom() + verticalSpacing);
- } else {
- fillDown(rowEnd + numColumns, referenceView.getBottom() + verticalSpacing);
- adjustViewsUpOrDown();
- fillUp(rowStart - 1, referenceView.getTop() - verticalSpacing);
- }
-
- return sel;
- }
-
- private void determineColumns(int availableSpace) {
- final int requestedHorizontalSpacing = mRequestedHorizontalSpacing;
- final int stretchMode = mStretchMode;
- final int requestedColumnWidth = mRequestedColumnWidth;
-
- if (mRequestedNumColumns == AUTO_FIT) {
- if (requestedColumnWidth > 0) {
- // Client told us to pick the number of columns
- mNumColumns = (availableSpace + requestedHorizontalSpacing) /
- (requestedColumnWidth + requestedHorizontalSpacing);
- } else {
- // Just make up a number if we don't have enough info
- mNumColumns = 2;
- }
- } else {
- // We picked the columns
- mNumColumns = mRequestedNumColumns;
- }
-
- if (mNumColumns <= 0) {
- mNumColumns = 1;
- }
-
- switch (stretchMode) {
- case NO_STRETCH:
- // Nobody stretches
- mColumnWidth = requestedColumnWidth;
- mHorizontalSpacing = requestedHorizontalSpacing;
- break;
-
- default:
- int spaceLeftOver = availableSpace - (mNumColumns * requestedColumnWidth) -
- ((mNumColumns - 1) * requestedHorizontalSpacing);
- switch (stretchMode) {
- case STRETCH_COLUMN_WIDTH:
- // Stretch the columns
- mColumnWidth = requestedColumnWidth + spaceLeftOver / mNumColumns;
- mHorizontalSpacing = requestedHorizontalSpacing;
- break;
-
- case STRETCH_SPACING:
- // Stretch the spacing between columns
- mColumnWidth = requestedColumnWidth;
- if (mNumColumns > 1) {
- mHorizontalSpacing = requestedHorizontalSpacing +
- spaceLeftOver / (mNumColumns - 1);
- } else {
- mHorizontalSpacing = requestedHorizontalSpacing + spaceLeftOver;
- }
- break;
-
- case STRETCH_SPACING_UNIFORM:
- // Stretch the spacing between columns
- mColumnWidth = requestedColumnWidth;
- if (mNumColumns > 1) {
- mHorizontalSpacing = requestedHorizontalSpacing +
- spaceLeftOver / (mNumColumns + 1);
- } else {
- mHorizontalSpacing = requestedHorizontalSpacing + spaceLeftOver;
- }
- break;
- }
-
- break;
- }
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // Sets up mListPadding
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
- if (widthMode == MeasureSpec.UNSPECIFIED) {
- if (mColumnWidth > 0) {
- widthSize = mColumnWidth + mListPadding.left + mListPadding.right;
- } else {
- widthSize = mListPadding.left + mListPadding.right;
- }
- widthSize += getVerticalScrollbarWidth();
- }
-
- int childWidth = widthSize - mListPadding.left - mListPadding.right;
- determineColumns(childWidth);
-
- int childHeight = 0;
-
- mItemCount = mAdapter == null ? 0 : mAdapter.getCount();
- final int count = mItemCount;
- if (count > 0) {
- final View child = obtainView(0);
- final int childViewType = mAdapter.getItemViewType(0);
-
- AbsListView.LayoutParams lp = (AbsListView.LayoutParams) child.getLayoutParams();
- if (lp == null) {
- lp = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT, 0);
- child.setLayoutParams(lp);
- }
- lp.viewType = childViewType;
-
- final int childWidthSpec = ViewGroup.getChildMeasureSpec(widthMeasureSpec,
- mListPadding.left + mListPadding.right, lp.width);
-
- int lpHeight = lp.height;
-
- int childHeightSpec;
- if (lpHeight > 0) {
- childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
- } else {
- childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- }
-
- child.measure(childWidthSpec, childHeightSpec);
- childHeight = child.getMeasuredHeight();
-
- if (mRecycler.shouldRecycleViewType(childViewType)) {
- mRecycler.addScrapView(child);
- }
- }
-
- if (heightMode == MeasureSpec.UNSPECIFIED) {
- heightSize = mListPadding.top + mListPadding.bottom + childHeight +
- getVerticalFadingEdgeLength() * 2;
- }
-
- if (heightMode == MeasureSpec.AT_MOST) {
- int ourSize = mListPadding.top + mListPadding.bottom;
-
- final int numColumns = mNumColumns;
- for (int i = 0; i < count; i += numColumns) {
- ourSize += childHeight;
- if (i + numColumns < count) {
- ourSize += mVerticalSpacing;
- }
- if (ourSize >= heightSize) {
- ourSize = heightSize;
- break;
- }
- }
- heightSize = ourSize;
- }
-
- setMeasuredDimension(widthSize, heightSize);
- mWidthMeasureSpec = widthMeasureSpec;
- }
-
- @Override
- protected void attachLayoutAnimationParameters(View child,
- ViewGroup.LayoutParams params, int index, int count) {
-
- GridLayoutAnimationController.AnimationParameters animationParams =
- (GridLayoutAnimationController.AnimationParameters) params.layoutAnimationParameters;
-
- if (animationParams == null) {
- animationParams = new GridLayoutAnimationController.AnimationParameters();
- params.layoutAnimationParameters = animationParams;
- }
-
- animationParams.count = count;
- animationParams.index = index;
- animationParams.columnsCount = mNumColumns;
- animationParams.rowsCount = count / mNumColumns;
-
- if (!mStackFromBottom) {
- animationParams.column = index % mNumColumns;
- animationParams.row = index / mNumColumns;
- } else {
- final int invertedIndex = count - 1 - index;
-
- animationParams.column = mNumColumns - 1 - (invertedIndex % mNumColumns);
- animationParams.row = animationParams.rowsCount - 1 - invertedIndex / mNumColumns;
- }
- }
-
- @Override
- protected void layoutChildren() {
- final boolean blockLayoutRequests = mBlockLayoutRequests;
- if (!blockLayoutRequests) {
- mBlockLayoutRequests = true;
- }
-
- try {
- super.layoutChildren();
-
- invalidate();
-
- if (mAdapter == null) {
- resetList();
- invokeOnItemScrollListener();
- return;
- }
-
- final int childrenTop = mListPadding.top;
- final int childrenBottom = mBottom - mTop - mListPadding.bottom;
-
- int childCount = getChildCount();
- int index;
- int delta = 0;
-
- View sel;
- View oldSel = null;
- View oldFirst = null;
- View newSel = null;
-
- // Remember stuff we will need down below
- switch (mLayoutMode) {
- case LAYOUT_SET_SELECTION:
- index = mNextSelectedPosition - mFirstPosition;
- if (index >= 0 && index < childCount) {
- newSel = getChildAt(index);
- }
- break;
- case LAYOUT_FORCE_TOP:
- case LAYOUT_FORCE_BOTTOM:
- case LAYOUT_SPECIFIC:
- case LAYOUT_SYNC:
- break;
- case LAYOUT_MOVE_SELECTION:
- if (mNextSelectedPosition >= 0) {
- delta = mNextSelectedPosition - mSelectedPosition;
- }
- break;
- default:
- // Remember the previously selected view
- index = mSelectedPosition - mFirstPosition;
- if (index >= 0 && index < childCount) {
- oldSel = getChildAt(index);
- }
-
- // Remember the previous first child
- oldFirst = getChildAt(0);
- }
-
- boolean dataChanged = mDataChanged;
- if (dataChanged) {
- handleDataChanged();
- }
-
- // Handle the empty set by removing all views that are visible
- // and calling it a day
- if (mItemCount == 0) {
- resetList();
- invokeOnItemScrollListener();
- return;
- }
-
- setSelectedPositionInt(mNextSelectedPosition);
-
- // Pull all children into the RecycleBin.
- // These views will be reused if possible
- final int firstPosition = mFirstPosition;
- final RecycleBin recycleBin = mRecycler;
-
- if (dataChanged) {
- for (int i = 0; i < childCount; i++) {
- recycleBin.addScrapView(getChildAt(i));
- }
- } else {
- recycleBin.fillActiveViews(childCount, firstPosition);
- }
-
- // Clear out old views
- //removeAllViewsInLayout();
- detachAllViewsFromParent();
-
- switch (mLayoutMode) {
- case LAYOUT_SET_SELECTION:
- if (newSel != null) {
- sel = fillFromSelection(newSel.getTop(), childrenTop, childrenBottom);
- } else {
- sel = fillSelection(childrenTop, childrenBottom);
- }
- break;
- case LAYOUT_FORCE_TOP:
- mFirstPosition = 0;
- sel = fillFromTop(childrenTop);
- adjustViewsUpOrDown();
- break;
- case LAYOUT_FORCE_BOTTOM:
- sel = fillUp(mItemCount - 1, childrenBottom);
- adjustViewsUpOrDown();
- break;
- case LAYOUT_SPECIFIC:
- sel = fillSpecific(mSelectedPosition, mSpecificTop);
- break;
- case LAYOUT_SYNC:
- sel = fillSpecific(mSyncPosition, mSpecificTop);
- break;
- case LAYOUT_MOVE_SELECTION:
- // Move the selection relative to its old position
- sel = moveSelection(delta, childrenTop, childrenBottom);
- break;
- default:
- if (childCount == 0) {
- if (!mStackFromBottom) {
- setSelectedPositionInt(0);
- sel = fillFromTop(childrenTop);
- } else {
- final int last = mItemCount - 1;
- setSelectedPositionInt(last);
- sel = fillFromBottom(last, childrenBottom);
- }
- } else {
- if (mSelectedPosition >= 0 && mSelectedPosition < mItemCount) {
- sel = fillSpecific(mSelectedPosition, oldSel == null ?
- childrenTop : oldSel.getTop());
- } else if (mFirstPosition < mItemCount) {
- sel = fillSpecific(mFirstPosition, oldFirst == null ?
- childrenTop : oldFirst.getTop());
- } else {
- sel = fillSpecific(0, childrenTop);
- }
- }
- break;
- }
-
- // Flush any cached views that did not get reused above
- recycleBin.scrapActiveViews();
-
- if (sel != null) {
- positionSelector(sel);
- mSelectedTop = sel.getTop();
- } else {
- mSelectedTop = 0;
- mSelectorRect.setEmpty();
- }
-
- mLayoutMode = LAYOUT_NORMAL;
- mDataChanged = false;
- mNeedSync = false;
- setNextSelectedPositionInt(mSelectedPosition);
-
- updateScrollIndicators();
-
- if (mItemCount > 0) {
- checkSelectionChanged();
- }
-
- invokeOnItemScrollListener();
- } finally {
- if (!blockLayoutRequests) {
- mBlockLayoutRequests = false;
- }
- }
- }
-
-
- /**
- * Obtain the view and add it to our list of children. The view can be made
- * fresh, converted from an unused view, or used as is if it was in the
- * recycle bin.
- *
- * @param position Logical position in the list
- * @param y Top or bottom edge of the view to add
- * @param flow if true, align top edge to y. If false, align bottom edge to
- * y.
- * @param childrenLeft Left edge where children should be positioned
- * @param selected Is this position selected?
- * @param where to add new item in the list
- * @return View that was added
- */
- private View makeAndAddView(int position, int y, boolean flow, int childrenLeft,
- boolean selected, int where) {
- View child;
-
- if (!mDataChanged) {
- // Try to use an exsiting view for this position
- child = mRecycler.getActiveView(position);
- if (child != null) {
- // Found it -- we're using an existing child
- // This just needs to be positioned
- setupChild(child, position, y, flow, childrenLeft, selected, true, where);
- return child;
- }
- }
-
- // Make a new view for this position, or convert an unused view if
- // possible
- child = obtainView(position);
-
- // This needs to be positioned and measured
- setupChild(child, position, y, flow, childrenLeft, selected, false, where);
-
- return child;
- }
-
- /**
- * Add a view as a child and make sure it is measured (if necessary) and
- * positioned properly.
- *
- * @param child The view to add
- * @param position The position of the view
- * @param y The y position relative to which this view will be positioned
- * @param flow if true, align top edge to y. If false, align bottom edge
- * to y.
- * @param childrenLeft Left edge where children should be positioned
- * @param selected Is this position selected?
- * @param recycled Has this view been pulled from the recycle bin? If so it
- * does not need to be remeasured.
- * @param where Where to add the item in the list
- *
- */
- private void setupChild(View child, int position, int y, boolean flow, int childrenLeft,
- boolean selected, boolean recycled, int where) {
- boolean isSelected = selected && shouldShowSelector();
-
- final boolean updateChildSelected = isSelected != child.isSelected();
- boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested();
-
- // Respect layout params that are already in the view. Otherwise make
- // some up...
- AbsListView.LayoutParams p = (AbsListView.LayoutParams)child.getLayoutParams();
- if (p == null) {
- p = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT, 0);
- }
- p.viewType = mAdapter.getItemViewType(position);
-
- if (recycled) {
- attachViewToParent(child, where, p);
- } else {
- addViewInLayout(child, where, p, true);
- }
-
- if (updateChildSelected) {
- child.setSelected(isSelected);
- if (isSelected) {
- requestFocus();
- }
- }
-
- if (needToMeasure) {
- int childHeightSpec = ViewGroup.getChildMeasureSpec(
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 0, p.height);
-
- int childWidthSpec = ViewGroup.getChildMeasureSpec(
- MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY), 0, p.width);
- child.measure(childWidthSpec, childHeightSpec);
- } else {
- cleanupLayoutState(child);
- }
-
- final int w = child.getMeasuredWidth();
- final int h = child.getMeasuredHeight();
-
- int childLeft;
- final int childTop = flow ? y : y - h;
-
- switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- childLeft = childrenLeft;
- break;
- case Gravity.CENTER_HORIZONTAL:
- childLeft = childrenLeft + ((mColumnWidth - w) / 2);
- break;
- case Gravity.RIGHT:
- childLeft = childrenLeft + mColumnWidth - w;
- break;
- default:
- childLeft = childrenLeft;
- break;
- }
-
- if (needToMeasure) {
- final int childRight = childLeft + w;
- final int childBottom = childTop + h;
- child.layout(childLeft, childTop, childRight, childBottom);
- } else {
- child.offsetLeftAndRight(childLeft - child.getLeft());
- child.offsetTopAndBottom(childTop - child.getTop());
- }
-
- if (mCachingStarted) {
- child.setDrawingCacheEnabled(true);
- }
- }
-
- /**
- * Sets the currently selected item
- *
- * @param position Index (starting at 0) of the data item to be selected.
- *
- * If in touch mode, the item will not be selected but it will still be positioned
- * appropriately.
- */
- @Override
- public void setSelection(int position) {
- if (!isInTouchMode()) {
- setNextSelectedPositionInt(position);
- } else {
- mResurrectToPosition = position;
- }
- mLayoutMode = LAYOUT_SET_SELECTION;
- requestLayout();
- }
-
- /**
- * Makes the item at the supplied position selected.
- *
- * @param position the position of the new selection
- */
- @Override
- void setSelectionInt(int position) {
- mBlockLayoutRequests = true;
- setNextSelectedPositionInt(position);
- layoutChildren();
-
- mBlockLayoutRequests = false;
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- return commonKey(keyCode, 1, event);
- }
-
- @Override
- public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
- return commonKey(keyCode, repeatCount, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- return commonKey(keyCode, 1, event);
- }
-
- private boolean commonKey(int keyCode, int count, KeyEvent event) {
- if (mAdapter == null) {
- return false;
- }
-
- if (mDataChanged) {
- layoutChildren();
- }
-
- boolean handled = false;
- int action = event.getAction();
-
- if (action != KeyEvent.ACTION_UP) {
- if (mSelectedPosition < 0) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_SPACE:
- case KeyEvent.KEYCODE_ENTER:
- resurrectSelection();
- return true;
- }
- }
-
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- handled = arrowScroll(FOCUS_LEFT);
- break;
-
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- handled = arrowScroll(FOCUS_RIGHT);
- break;
-
- case KeyEvent.KEYCODE_DPAD_UP:
- if (!event.isAltPressed()) {
- handled = arrowScroll(FOCUS_UP);
-
- } else {
- handled = fullScroll(FOCUS_UP);
- }
- break;
-
- case KeyEvent.KEYCODE_DPAD_DOWN:
- if (!event.isAltPressed()) {
- handled = arrowScroll(FOCUS_DOWN);
- } else {
- handled = fullScroll(FOCUS_DOWN);
- }
- break;
-
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_ENTER: {
- if (getChildCount() > 0 && event.getRepeatCount() == 0) {
- keyPressed();
- }
-
- return true;
- }
-
- case KeyEvent.KEYCODE_SPACE:
- if (mPopup == null || !mPopup.isShowing()) {
- if (!event.isShiftPressed()) {
- handled = pageScroll(FOCUS_DOWN);
- } else {
- handled = pageScroll(FOCUS_UP);
- }
- }
- break;
- }
- }
-
- if (!handled) {
- handled = sendToTextFilter(keyCode, count, event);
- }
-
- if (handled) {
- return true;
- } else {
- switch (action) {
- case KeyEvent.ACTION_DOWN:
- return super.onKeyDown(keyCode, event);
- case KeyEvent.ACTION_UP:
- return super.onKeyUp(keyCode, event);
- case KeyEvent.ACTION_MULTIPLE:
- return super.onKeyMultiple(keyCode, count, event);
- default:
- return false;
- }
- }
- }
-
- /**
- * Scrolls up or down by the number of items currently present on screen.
- *
- * @param direction either {@link View#FOCUS_UP} or {@link View#FOCUS_DOWN}
- * @return whether selection was moved
- */
- boolean pageScroll(int direction) {
- int nextPage = -1;
-
- if (direction == FOCUS_UP) {
- nextPage = Math.max(0, mSelectedPosition - getChildCount() - 1);
- } else if (direction == FOCUS_DOWN) {
- nextPage = Math.min(mItemCount - 1, mSelectedPosition + getChildCount() - 1);
- }
-
- if (nextPage >= 0) {
- setSelectionInt(nextPage);
- invokeOnItemScrollListener();
- return true;
- }
-
- return false;
- }
-
- /**
- * Go to the last or first item if possible.
- *
- * @param direction either {@link View#FOCUS_UP} or {@link View#FOCUS_DOWN}.
- *
- * @return Whether selection was moved.
- */
- boolean fullScroll(int direction) {
- boolean moved = false;
- if (direction == FOCUS_UP) {
- mLayoutMode = LAYOUT_SET_SELECTION;
- setSelectionInt(0);
- invokeOnItemScrollListener();
- moved = true;
- } else if (direction == FOCUS_DOWN) {
- mLayoutMode = LAYOUT_SET_SELECTION;
- setSelectionInt(mItemCount - 1);
- invokeOnItemScrollListener();
- moved = true;
- }
-
- return moved;
- }
-
- /**
- * Scrolls to the next or previous item, horizontally or vertically.
- *
- * @param direction either {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT},
- * {@link View#FOCUS_UP} or {@link View#FOCUS_DOWN}
- *
- * @return whether selection was moved
- */
- boolean arrowScroll(int direction) {
- final int selectedPosition = mSelectedPosition;
- final int numColumns = mNumColumns;
-
- int startOfRowPos;
- int endOfRowPos;
-
- boolean moved = false;
-
- if (!mStackFromBottom) {
- startOfRowPos = (selectedPosition / numColumns) * numColumns;
- endOfRowPos = Math.min(startOfRowPos + numColumns - 1, mItemCount - 1);
- } else {
- final int invertedSelection = mItemCount - 1 - selectedPosition;
- endOfRowPos = mItemCount - 1 - (invertedSelection / numColumns) * numColumns;
- startOfRowPos = Math.max(0, endOfRowPos - numColumns + 1);
- }
-
- switch (direction) {
- case FOCUS_UP:
- if (startOfRowPos > 0) {
- mLayoutMode = LAYOUT_MOVE_SELECTION;
- setSelectionInt(Math.max(0, selectedPosition - numColumns));
- moved = true;
- }
- break;
- case FOCUS_DOWN:
- if (endOfRowPos < mItemCount - 1) {
- mLayoutMode = LAYOUT_MOVE_SELECTION;
- setSelectionInt(Math.min(selectedPosition + numColumns, mItemCount - 1));
- moved = true;
- }
- break;
- case FOCUS_LEFT:
- if (selectedPosition > startOfRowPos) {
- mLayoutMode = LAYOUT_MOVE_SELECTION;
- setSelectionInt(selectedPosition - 1);
- moved = true;
- }
- break;
- case FOCUS_RIGHT:
- if (selectedPosition < endOfRowPos) {
- mLayoutMode = LAYOUT_MOVE_SELECTION;
- setSelectionInt(selectedPosition + 1);
- moved = true;
- }
- break;
- }
-
- if (moved) {
- playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
- invokeOnItemScrollListener();
- }
-
- return moved;
- }
-
- @Override
- protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
- super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
-
- int closestChildIndex = -1;
- if (gainFocus && previouslyFocusedRect != null) {
- previouslyFocusedRect.offset(mScrollX, mScrollY);
-
- // figure out which item should be selected based on previously
- // focused rect
- Rect otherRect = mTempRect;
- int minDistance = Integer.MAX_VALUE;
- final int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- // only consider view's on appropriate edge of grid
- if (!isCandidateSelection(i, direction)) {
- continue;
- }
-
- final View other = getChildAt(i);
- other.getDrawingRect(otherRect);
- offsetDescendantRectToMyCoords(other, otherRect);
- int distance = getDistance(previouslyFocusedRect, otherRect, direction);
-
- if (distance < minDistance) {
- minDistance = distance;
- closestChildIndex = i;
- }
- }
- }
-
- if (closestChildIndex >= 0) {
- setSelection(closestChildIndex + mFirstPosition);
- } else {
- requestLayout();
- }
- }
-
- /**
- * Is childIndex a candidate for next focus given the direction the focus
- * change is coming from?
- * @param childIndex The index to check.
- * @param direction The direction, one of
- * {FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}
- * @return Whether childIndex is a candidate.
- */
- private boolean isCandidateSelection(int childIndex, int direction) {
- final int count = getChildCount();
- final int invertedIndex = count - 1 - childIndex;
-
- int rowStart;
- int rowEnd;
-
- if (!mStackFromBottom) {
- rowStart = childIndex - (childIndex % mNumColumns);
- rowEnd = Math.max(rowStart + mNumColumns - 1, count);
- } else {
- rowEnd = count - 1 - (invertedIndex - (invertedIndex % mNumColumns));
- rowStart = Math.max(0, rowEnd - mNumColumns + 1);
- }
-
- switch (direction) {
- case View.FOCUS_RIGHT:
- // coming from left, selection is only valid if it is on left
- // edge
- return childIndex == rowStart;
- case View.FOCUS_DOWN:
- // coming from top; only valid if in top row
- return rowStart == 0;
- case View.FOCUS_LEFT:
- // coming from right, must be on right edge
- return childIndex == rowEnd;
- case View.FOCUS_UP:
- // coming from bottom, need to be in last row
- return rowEnd == count - 1;
- default:
- throw new IllegalArgumentException("direction must be one of "
- + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
- }
- }
-
- /**
- * Describes how the child views are horizontally aligned. Defaults to Gravity.LEFT
- *
- * @param gravity the gravity to apply to this grid's children
- *
- * @attr ref android.R.styleable#GridView_gravity
- */
- public void setGravity(int gravity) {
- if (mGravity != gravity) {
- mGravity = gravity;
- requestLayoutIfNecessary();
- }
- }
-
- /**
- * Set the amount of horizontal (x) spacing to place between each item
- * in the grid.
- *
- * @param horizontalSpacing The amount of horizontal space between items,
- * in pixels.
- *
- * @attr ref android.R.styleable#GridView_horizontalSpacing
- */
- public void setHorizontalSpacing(int horizontalSpacing) {
- if (horizontalSpacing != mRequestedHorizontalSpacing) {
- mRequestedHorizontalSpacing = horizontalSpacing;
- requestLayoutIfNecessary();
- }
- }
-
-
- /**
- * Set the amount of vertical (y) spacing to place between each item
- * in the grid.
- *
- * @param verticalSpacing The amount of vertical space between items,
- * in pixels.
- *
- * @attr ref android.R.styleable#GridView_verticalSpacing
- */
- public void setVerticalSpacing(int verticalSpacing) {
- if (verticalSpacing != mVerticalSpacing) {
- mVerticalSpacing = verticalSpacing;
- requestLayoutIfNecessary();
- }
- }
-
- /**
- * Control how items are stretched to fill their space.
- *
- * @param stretchMode Either {@link #NO_STRETCH},
- * {@link #STRETCH_SPACING}, {@link #STRETCH_SPACING_UNIFORM}, or {@link #STRETCH_COLUMN_WIDTH}.
- *
- * @attr ref android.R.styleable#GridView_stretchMode
- */
- public void setStretchMode(int stretchMode) {
- if (stretchMode != mStretchMode) {
- mStretchMode = stretchMode;
- requestLayoutIfNecessary();
- }
- }
-
- public int getStretchMode() {
- return mStretchMode;
- }
-
- /**
- * Set the width of columns in the grid.
- *
- * @param columnWidth The column width, in pixels.
- *
- * @attr ref android.R.styleable#GridView_columnWidth
- */
- public void setColumnWidth(int columnWidth) {
- if (columnWidth != mRequestedColumnWidth) {
- mRequestedColumnWidth = columnWidth;
- requestLayoutIfNecessary();
- }
- }
-
- /**
- * Set the number of columns in the grid
- *
- * @param numColumns The desired number of columns.
- *
- * @attr ref android.R.styleable#GridView_numColumns
- */
- public void setNumColumns(int numColumns) {
- if (numColumns != mRequestedNumColumns) {
- mRequestedNumColumns = numColumns;
- requestLayoutIfNecessary();
- }
- }
-
- /**
- * Make sure views are touching the top or bottom edge, as appropriate for
- * our gravity
- */
- private void adjustViewsUpOrDown() {
- final int childCount = getChildCount();
-
- if (childCount > 0) {
- int delta;
- View child;
-
- if (!mStackFromBottom) {
- // Uh-oh -- we came up short. Slide all views up to make them
- // align with the top
- child = getChildAt(0);
- delta = child.getTop() - mListPadding.top;
- if (mFirstPosition != 0) {
- // It's OK to have some space above the first item if it is
- // part of the vertical spacing
- delta -= mVerticalSpacing;
- }
- if (delta < 0) {
- // We only are looking to see if we are too low, not too high
- delta = 0;
- }
- } else {
- // we are too high, slide all views down to align with bottom
- child = getChildAt(childCount - 1);
- delta = child.getBottom() - (getHeight() - mListPadding.bottom);
-
- if (mFirstPosition + childCount < mItemCount) {
- // It's OK to have some space below the last item if it is
- // part of the vertical spacing
- delta += mVerticalSpacing;
- }
-
- if (delta > 0) {
- // We only are looking to see if we are too high, not too low
- delta = 0;
- }
- }
-
- if (delta != 0) {
- offsetChildrenTopAndBottom(-delta);
- }
- }
- }
-
- @Override
- protected int computeVerticalScrollExtent() {
- final int count = getChildCount();
- if (count > 0) {
- final int numColumns = mNumColumns;
- final int rowCount = (count + numColumns - 1) / numColumns;
-
- int extent = rowCount * 100;
-
- View view = getChildAt(0);
- final int top = view.getTop();
- int height = view.getHeight();
- if (height > 0) {
- extent += (top * 100) / height;
- }
-
- view = getChildAt(count - 1);
- final int bottom = view.getBottom();
- height = view.getHeight();
- if (height > 0) {
- extent -= ((bottom - getHeight()) * 100) / height;
- }
-
- return extent;
- }
- return 0;
- }
-
- @Override
- protected int computeVerticalScrollOffset() {
- if (mFirstPosition >= 0 && getChildCount() > 0) {
- final View view = getChildAt(0);
- final int top = view.getTop();
- int height = view.getHeight();
- if (height > 0) {
- final int whichRow = mFirstPosition / mNumColumns;
- return Math.max(whichRow * 100 - (top * 100) / height, 0);
- }
- }
- return 0;
- }
-
- @Override
- protected int computeVerticalScrollRange() {
- // TODO: Account for vertical spacing too
- final int numColumns = mNumColumns;
- final int rowCount = (mItemCount + numColumns - 1) / numColumns;
- return Math.max(rowCount * 100, 0);
- }
-}
-
diff --git a/core/java/android/widget/HeaderViewListAdapter.java b/core/java/android/widget/HeaderViewListAdapter.java
deleted file mode 100644
index b0e5f7e..0000000
--- a/core/java/android/widget/HeaderViewListAdapter.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.database.DataSetObserver;
-import android.view.View;
-import android.view.ViewGroup;
-
-import java.util.ArrayList;
-
-/**
- * ListAdapter used when a ListView has header views. This ListAdapter
- * wraps another one and also keeps track of the header views and their
- * associated data objects.
- *<p>This is intended as a base class; you will probably not need to
- * use this class directly in your own code.
- *
- */
-public class HeaderViewListAdapter implements WrapperListAdapter, Filterable {
-
- private ListAdapter mAdapter;
-
- ArrayList<ListView.FixedViewInfo> mHeaderViewInfos;
- ArrayList<ListView.FixedViewInfo> mFooterViewInfos;
- boolean mAreAllFixedViewsSelectable;
-
- private boolean mIsFilterable;
-
- public HeaderViewListAdapter(ArrayList<ListView.FixedViewInfo> headerViewInfos,
- ArrayList<ListView.FixedViewInfo> footerViewInfos,
- ListAdapter adapter) {
- mAdapter = adapter;
- mIsFilterable = adapter instanceof Filterable;
-
- mHeaderViewInfos = headerViewInfos;
- mFooterViewInfos = footerViewInfos;
-
- mAreAllFixedViewsSelectable =
- areAllListInfosSelectable(mHeaderViewInfos)
- && areAllListInfosSelectable(mFooterViewInfos);
- }
-
- public int getHeadersCount() {
- return mHeaderViewInfos == null ? 0 : mHeaderViewInfos.size();
- }
-
- public int getFootersCount() {
- return mFooterViewInfos == null ? 0 : mFooterViewInfos.size();
- }
-
- public boolean isEmpty() {
- return mAdapter == null || mAdapter.isEmpty();
- }
-
- private boolean areAllListInfosSelectable(ArrayList<ListView.FixedViewInfo> infos) {
- if (infos != null) {
- for (ListView.FixedViewInfo info : infos) {
- if (!info.isSelectable) {
- return false;
- }
- }
- }
- return true;
- }
-
- public boolean removeHeader(View v) {
- for (int i = 0; i < mHeaderViewInfos.size(); i++) {
- ListView.FixedViewInfo info = mHeaderViewInfos.get(i);
- if (info.view == v) {
- mHeaderViewInfos.remove(i);
-
- mAreAllFixedViewsSelectable =
- areAllListInfosSelectable(mHeaderViewInfos)
- && areAllListInfosSelectable(mFooterViewInfos);
-
- return true;
- }
- }
-
- return false;
- }
-
- public boolean removeFooter(View v) {
- for (int i = 0; i < mFooterViewInfos.size(); i++) {
- ListView.FixedViewInfo info = mFooterViewInfos.get(i);
- if (info.view == v) {
- mFooterViewInfos.remove(i);
-
- mAreAllFixedViewsSelectable =
- areAllListInfosSelectable(mHeaderViewInfos)
- && areAllListInfosSelectable(mFooterViewInfos);
-
- return true;
- }
- }
-
- return false;
- }
-
- public int getCount() {
- if (mAdapter != null) {
- return getFootersCount() + getHeadersCount() + mAdapter.getCount();
- } else {
- return getFootersCount() + getHeadersCount();
- }
- }
-
- public boolean areAllItemsEnabled() {
- if (mAdapter != null) {
- return mAreAllFixedViewsSelectable && mAdapter.areAllItemsEnabled();
- } else {
- return true;
- }
- }
-
- public boolean isEnabled(int position) {
- int numHeaders = getHeadersCount();
- if (mAdapter != null && position >= numHeaders) {
- int adjPosition = position - numHeaders;
- int adapterCount = mAdapter.getCount();
- if (adjPosition >= adapterCount && mFooterViewInfos != null) {
- return mFooterViewInfos.get(adjPosition - adapterCount).isSelectable;
- } else {
- return mAdapter.isEnabled(adjPosition);
- }
- } else if (position < numHeaders && mHeaderViewInfos != null) {
- return mHeaderViewInfos.get(position).isSelectable;
- }
- return true;
- }
-
- public Object getItem(int position) {
- int numHeaders = getHeadersCount();
- if (mAdapter != null && position >= numHeaders) {
- int adjPosition = position - numHeaders;
- int adapterCount = mAdapter.getCount();
- if (adjPosition >= adapterCount && mFooterViewInfos != null) {
- return mFooterViewInfos.get(adjPosition - adapterCount).data;
- } else {
- return mAdapter.getItem(adjPosition);
- }
- } else if (position < numHeaders && mHeaderViewInfos != null) {
- return mHeaderViewInfos.get(position).data;
- }
- return null;
- }
-
- public long getItemId(int position) {
- int numHeaders = getHeadersCount();
- if (mAdapter != null && position >= numHeaders) {
- int adjPosition = position - numHeaders;
- int adapterCnt = mAdapter.getCount();
- if (adjPosition < adapterCnt) {
- return mAdapter.getItemId(adjPosition);
- }
- }
- return -1;
- }
-
- public boolean hasStableIds() {
- if (mAdapter != null) {
- return mAdapter.hasStableIds();
- }
- return false;
- }
-
- public View getView(int position, View convertView, ViewGroup parent) {
- int numHeaders = getHeadersCount();
- if (mAdapter != null && position >= numHeaders) {
- int adjPosition = position - numHeaders;
- int adapterCount = mAdapter.getCount();
- if (adjPosition >= adapterCount) {
- if (mFooterViewInfos != null) {
- return mFooterViewInfos.get(adjPosition - adapterCount).view;
- }
- } else {
- return mAdapter.getView(adjPosition, convertView, parent);
- }
- } else if (position < numHeaders) {
- return mHeaderViewInfos.get(position).view;
- }
- return null;
- }
-
- public int getItemViewType(int position) {
- int numHeaders = getHeadersCount();
- if (mAdapter != null && position >= numHeaders) {
- int adjPosition = position - numHeaders;
- int adapterCount = mAdapter.getCount();
- if (adjPosition < adapterCount) {
- return mAdapter.getItemViewType(adjPosition);
- }
- }
-
- return AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
- }
-
- public int getViewTypeCount() {
- if (mAdapter != null) {
- return mAdapter.getViewTypeCount();
- }
- return 1;
- }
-
- public void registerDataSetObserver(DataSetObserver observer) {
- if (mAdapter != null) {
- mAdapter.registerDataSetObserver(observer);
- }
- }
-
- public void unregisterDataSetObserver(DataSetObserver observer) {
- if (mAdapter != null) {
- mAdapter.unregisterDataSetObserver(observer);
- }
- }
-
- public Filter getFilter() {
- if (mIsFilterable) {
- return ((Filterable) mAdapter).getFilter();
- }
- return null;
- }
-
- public ListAdapter getWrappedAdapter() {
- return mAdapter;
- }
-}
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
deleted file mode 100644
index 96fe595..0000000
--- a/core/java/android/widget/HorizontalScrollView.java
+++ /dev/null
@@ -1,1197 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.util.AttributeSet;
-import android.graphics.Rect;
-import android.view.View;
-import android.view.VelocityTracker;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.KeyEvent;
-import android.view.FocusFinder;
-import android.view.MotionEvent;
-import android.view.ViewParent;
-import android.view.animation.AnimationUtils;
-import android.content.Context;
-import android.content.res.TypedArray;
-
-import java.util.List;
-
-/**
- * Layout container for a view hierarchy that can be scrolled by the user,
- * allowing it to be larger than the physical display. A HorizontalScrollView
- * is a {@link FrameLayout}, meaning you should place one child in it
- * containing the entire contents to scroll; this child may itself be a layout
- * manager with a complex hierarchy of objects. A child that is often used
- * is a {@link LinearLayout} in a horizontal orientation, presenting a horizontal
- * array of top-level items that the user can scroll through.
- *
- * <p>You should never use a HorizontalScrollView with a {@link ListView}, since
- * ListView takes care of its own scrolling. Most importantly, doing this
- * defeats all of the important optimizations in ListView for dealing with
- * large lists, since it effectively forces the ListView to display its entire
- * list of items to fill up the infinite container supplied by HorizontalScrollView.
- *
- * <p>The {@link TextView} class also
- * takes care of its own scrolling, so does not require a ScrollView, but
- * using the two together is possible to achieve the effect of a text view
- * within a larger container.
- *
- * <p>HorizontalScrollView only supports horizontal scrolling.
- */
-public class HorizontalScrollView extends FrameLayout {
- private static final int ANIMATED_SCROLL_GAP = ScrollView.ANIMATED_SCROLL_GAP;
-
- private static final float MAX_SCROLL_FACTOR = ScrollView.MAX_SCROLL_FACTOR;
-
-
- private long mLastScroll;
-
- private final Rect mTempRect = new Rect();
- private Scroller mScroller;
-
- /**
- * Flag to indicate that we are moving focus ourselves. This is so the
- * code that watches for focus changes initiated outside this ScrollView
- * knows that it does not have to do anything.
- */
- private boolean mScrollViewMovedFocus;
-
- /**
- * Position of the last motion event.
- */
- private float mLastMotionX;
-
- /**
- * True when the layout has changed but the traversal has not come through yet.
- * Ideally the view hierarchy would keep track of this for us.
- */
- private boolean mIsLayoutDirty = true;
-
- /**
- * The child to give focus to in the event that a child has requested focus while the
- * layout is dirty. This prevents the scroll from being wrong if the child has not been
- * laid out before requesting focus.
- */
- private View mChildToScrollTo = null;
-
- /**
- * True if the user is currently dragging this ScrollView around. This is
- * not the same as 'is being flinged', which can be checked by
- * mScroller.isFinished() (flinging begins when the user lifts his finger).
- */
- private boolean mIsBeingDragged = false;
-
- /**
- * Determines speed during touch scrolling
- */
- private VelocityTracker mVelocityTracker;
-
- /**
- * When set to true, the scroll view measure its child to make it fill the currently
- * visible area.
- */
- private boolean mFillViewport;
-
- /**
- * Whether arrow scrolling is animated.
- */
- private boolean mSmoothScrollingEnabled = true;
-
- private int mTouchSlop;
-
- public HorizontalScrollView(Context context) {
- this(context, null);
- }
-
- public HorizontalScrollView(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.horizontalScrollViewStyle);
- }
-
- public HorizontalScrollView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- initScrollView();
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- android.R.styleable.HorizontalScrollView, defStyle, 0);
-
- setFillViewport(a.getBoolean(android.R.styleable.HorizontalScrollView_fillViewport, false));
-
- a.recycle();
- }
-
- @Override
- protected float getLeftFadingEdgeStrength() {
- if (getChildCount() == 0) {
- return 0.0f;
- }
-
- final int length = getHorizontalFadingEdgeLength();
- if (mScrollX < length) {
- return mScrollX / (float) length;
- }
-
- return 1.0f;
- }
-
- @Override
- protected float getRightFadingEdgeStrength() {
- if (getChildCount() == 0) {
- return 0.0f;
- }
-
- final int length = getHorizontalFadingEdgeLength();
- final int rightEdge = getWidth() - mPaddingRight;
- final int span = getChildAt(0).getRight() - mScrollX - rightEdge;
- if (span < length) {
- return span / (float) length;
- }
-
- return 1.0f;
- }
-
- /**
- * @return The maximum amount this scroll view will scroll in response to
- * an arrow event.
- */
- public int getMaxScrollAmount() {
- return (int) (MAX_SCROLL_FACTOR * (mRight - mLeft));
- }
-
-
- private void initScrollView() {
- mScroller = new Scroller(getContext());
- setFocusable(true);
- setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
- setWillNotDraw(false);
- mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- }
-
- @Override
- public void addView(View child) {
- if (getChildCount() > 0) {
- throw new IllegalStateException("HorizontalScrollView can host only one direct child");
- }
-
- super.addView(child);
- }
-
- @Override
- public void addView(View child, int index) {
- if (getChildCount() > 0) {
- throw new IllegalStateException("HorizontalScrollView can host only one direct child");
- }
-
- super.addView(child, index);
- }
-
- @Override
- public void addView(View child, ViewGroup.LayoutParams params) {
- if (getChildCount() > 0) {
- throw new IllegalStateException("HorizontalScrollView can host only one direct child");
- }
-
- super.addView(child, params);
- }
-
- @Override
- public void addView(View child, int index, ViewGroup.LayoutParams params) {
- if (getChildCount() > 0) {
- throw new IllegalStateException("HorizontalScrollView can host only one direct child");
- }
-
- super.addView(child, index, params);
- }
-
- /**
- * @return Returns true this HorizontalScrollView can be scrolled
- */
- private boolean canScroll() {
- View child = getChildAt(0);
- if (child != null) {
- int childWidth = child.getWidth();
- return getWidth() < childWidth + mPaddingLeft + mPaddingRight ;
- }
- return false;
- }
-
- /**
- * Indicates whether this ScrollView's content is stretched to fill the viewport.
- *
- * @return True if the content fills the viewport, false otherwise.
- */
- public boolean isFillViewport() {
- return mFillViewport;
- }
-
- /**
- * Indicates this ScrollView whether it should stretch its content width to fill
- * the viewport or not.
- *
- * @param fillViewport True to stretch the content's width to the viewport's
- * boundaries, false otherwise.
- */
- public void setFillViewport(boolean fillViewport) {
- if (fillViewport != mFillViewport) {
- mFillViewport = fillViewport;
- requestLayout();
- }
- }
-
- /**
- * @return Whether arrow scrolling will animate its transition.
- */
- public boolean isSmoothScrollingEnabled() {
- return mSmoothScrollingEnabled;
- }
-
- /**
- * Set whether arrow scrolling will animate its transition.
- * @param smoothScrollingEnabled whether arrow scrolling will animate its transition
- */
- public void setSmoothScrollingEnabled(boolean smoothScrollingEnabled) {
- mSmoothScrollingEnabled = smoothScrollingEnabled;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
- if (!mFillViewport) {
- return;
- }
-
- final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- if (widthMode == MeasureSpec.UNSPECIFIED) {
- return;
- }
-
- final View child = getChildAt(0);
- int width = getMeasuredWidth();
- if (child.getMeasuredHeight() < width) {
- final FrameLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
- int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, mPaddingTop
- + mPaddingBottom, lp.height);
- width -= mPaddingLeft;
- width -= mPaddingRight;
- int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
-
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- }
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- // Let the focused view and/or our descendants get the key first
- boolean handled = super.dispatchKeyEvent(event);
- if (handled) {
- return true;
- }
- return executeKeyEvent(event);
- }
-
- /**
- * You can call this function yourself to have the scroll view perform
- * scrolling from a key event, just as if the event had been dispatched to
- * it by the view hierarchy.
- *
- * @param event The key event to execute.
- * @return Return true if the event was handled, else false.
- */
- public boolean executeKeyEvent(KeyEvent event) {
- mTempRect.setEmpty();
-
- if (!canScroll()) {
- if (isFocused()) {
- View currentFocused = findFocus();
- if (currentFocused == this) currentFocused = null;
- View nextFocused = FocusFinder.getInstance().findNextFocus(this,
- currentFocused, View.FOCUS_RIGHT);
- return nextFocused != null && nextFocused != this &&
- nextFocused.requestFocus(View.FOCUS_RIGHT);
- }
- return false;
- }
-
- boolean handled = false;
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- switch (event.getKeyCode()) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- if (!event.isAltPressed()) {
- handled = arrowScroll(View.FOCUS_LEFT);
- } else {
- handled = fullScroll(View.FOCUS_LEFT);
- }
- break;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- if (!event.isAltPressed()) {
- handled = arrowScroll(View.FOCUS_RIGHT);
- } else {
- handled = fullScroll(View.FOCUS_RIGHT);
- }
- break;
- case KeyEvent.KEYCODE_SPACE:
- pageScroll(event.isShiftPressed() ? View.FOCUS_LEFT : View.FOCUS_RIGHT);
- break;
- }
- }
-
- return handled;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- /*
- * This method JUST determines whether we want to intercept the motion.
- * If we return true, onMotionEvent will be called and we do the actual
- * scrolling there.
- */
-
- /*
- * Shortcut the most recurring case: the user is in the dragging
- * state and he is moving his finger. We want to intercept this
- * motion.
- */
- final int action = ev.getAction();
- if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) {
- return true;
- }
-
- if (!canScroll()) {
- mIsBeingDragged = false;
- return false;
- }
-
- final float x = ev.getX();
-
- switch (action) {
- case MotionEvent.ACTION_MOVE:
- /*
- * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
- * whether the user has moved far enough from his original down touch.
- */
-
- /*
- * Locally do absolute value. mLastMotionX is set to the x value
- * of the down event.
- */
- final int xDiff = (int) Math.abs(x - mLastMotionX);
- if (xDiff > mTouchSlop) {
- mIsBeingDragged = true;
- if (mParent != null) mParent.requestDisallowInterceptTouchEvent(true);
- }
- break;
-
- case MotionEvent.ACTION_DOWN:
- /* Remember location of down touch */
- mLastMotionX = x;
-
- /*
- * If being flinged and user touches the screen, initiate drag;
- * otherwise don't. mScroller.isFinished should be false when
- * being flinged.
- */
- mIsBeingDragged = !mScroller.isFinished();
- break;
-
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- /* Release the drag */
- mIsBeingDragged = false;
- break;
- }
-
- /*
- * The only time we want to intercept motion events is if we are in the
- * drag mode.
- */
- return mIsBeingDragged;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
-
- if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) {
- // Don't handle edge touches immediately -- they may actually belong to one of our
- // descendants.
- return false;
- }
-
- if (!canScroll()) {
- return false;
- }
-
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(ev);
-
- final int action = ev.getAction();
- final float x = ev.getX();
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- /*
- * If being flinged and user touches, stop the fling. isFinished
- * will be false if being flinged.
- */
- if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
- }
-
- // Remember where the motion event started
- mLastMotionX = x;
- break;
- case MotionEvent.ACTION_MOVE:
- // Scroll to follow the motion event
- final int deltaX = (int) (mLastMotionX - x);
- mLastMotionX = x;
-
- if (deltaX < 0) {
- if (mScrollX > 0) {
- scrollBy(deltaX, 0);
- }
- } else if (deltaX > 0) {
- final int rightEdge = getWidth() - mPaddingRight;
- final int availableToScroll = getChildAt(0).getRight() - mScrollX - rightEdge;
- if (availableToScroll > 0) {
- scrollBy(Math.min(availableToScroll, deltaX), 0);
- }
- }
- break;
- case MotionEvent.ACTION_UP:
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(1000);
- int initialVelocity = (int) velocityTracker.getXVelocity();
-
- if ((Math.abs(initialVelocity) >
- ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity()) &&
- getChildCount() > 0) {
- fling(-initialVelocity);
- }
-
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- }
- return true;
- }
-
- /**
- * <p>
- * Finds the next focusable component that fits in this View's bounds
- * (excluding fading edges) pretending that this View's left is located at
- * the parameter left.
- * </p>
- *
- * @param leftFocus look for a candidate is the one at the left of the bounds
- * if leftFocus is true, or at the right of the bounds if leftFocus
- * is false
- * @param left the left offset of the bounds in which a focusable must be
- * found (the fading edge is assumed to start at this position)
- * @param preferredFocusable the View that has highest priority and will be
- * returned if it is within my bounds (null is valid)
- * @return the next focusable component in the bounds or null if none can be found
- */
- private View findFocusableViewInMyBounds(final boolean leftFocus,
- final int left, View preferredFocusable) {
- /*
- * The fading edge's transparent side should be considered for focus
- * since it's mostly visible, so we divide the actual fading edge length
- * by 2.
- */
- final int fadingEdgeLength = getHorizontalFadingEdgeLength() / 2;
- final int leftWithoutFadingEdge = left + fadingEdgeLength;
- final int rightWithoutFadingEdge = left + getWidth() - fadingEdgeLength;
-
- if ((preferredFocusable != null)
- && (preferredFocusable.getLeft() < rightWithoutFadingEdge)
- && (preferredFocusable.getRight() > leftWithoutFadingEdge)) {
- return preferredFocusable;
- }
-
- return findFocusableViewInBounds(leftFocus, leftWithoutFadingEdge,
- rightWithoutFadingEdge);
- }
-
- /**
- * <p>
- * Finds the next focusable component that fits in the specified bounds.
- * </p>
- *
- * @param leftFocus look for a candidate is the one at the left of the bounds
- * if leftFocus is true, or at the right of the bounds if
- * leftFocus is false
- * @param left the left offset of the bounds in which a focusable must be
- * found
- * @param right the right offset of the bounds in which a focusable must
- * be found
- * @return the next focusable component in the bounds or null if none can
- * be found
- */
- private View findFocusableViewInBounds(boolean leftFocus, int left, int right) {
-
- List<View> focusables = getFocusables(View.FOCUS_FORWARD);
- View focusCandidate = null;
-
- /*
- * A fully contained focusable is one where its left is below the bound's
- * left, and its right is above the bound's right. A partially
- * contained focusable is one where some part of it is within the
- * bounds, but it also has some part that is not within bounds. A fully contained
- * focusable is preferred to a partially contained focusable.
- */
- boolean foundFullyContainedFocusable = false;
-
- int count = focusables.size();
- for (int i = 0; i < count; i++) {
- View view = focusables.get(i);
- int viewLeft = view.getLeft();
- int viewRight = view.getRight();
-
- if (left < viewRight && viewLeft < right) {
- /*
- * the focusable is in the target area, it is a candidate for
- * focusing
- */
-
- final boolean viewIsFullyContained = (left < viewLeft) &&
- (viewRight < right);
-
- if (focusCandidate == null) {
- /* No candidate, take this one */
- focusCandidate = view;
- foundFullyContainedFocusable = viewIsFullyContained;
- } else {
- final boolean viewIsCloserToBoundary =
- (leftFocus && viewLeft < focusCandidate.getLeft()) ||
- (!leftFocus && viewRight > focusCandidate.getRight());
-
- if (foundFullyContainedFocusable) {
- if (viewIsFullyContained && viewIsCloserToBoundary) {
- /*
- * We're dealing with only fully contained views, so
- * it has to be closer to the boundary to beat our
- * candidate
- */
- focusCandidate = view;
- }
- } else {
- if (viewIsFullyContained) {
- /* Any fully contained view beats a partially contained view */
- focusCandidate = view;
- foundFullyContainedFocusable = true;
- } else if (viewIsCloserToBoundary) {
- /*
- * Partially contained view beats another partially
- * contained view if it's closer
- */
- focusCandidate = view;
- }
- }
- }
- }
- }
-
- return focusCandidate;
- }
-
- /**
- * <p>Handles scrolling in response to a "page up/down" shortcut press. This
- * method will scroll the view by one page left or right and give the focus
- * to the leftmost/rightmost component in the new visible area. If no
- * component is a good candidate for focus, this scrollview reclaims the
- * focus.</p>
- *
- * @param direction the scroll direction: {@link android.view.View#FOCUS_LEFT}
- * to go one page left or {@link android.view.View#FOCUS_RIGHT}
- * to go one page right
- * @return true if the key event is consumed by this method, false otherwise
- */
- public boolean pageScroll(int direction) {
- boolean right = direction == View.FOCUS_RIGHT;
- int width = getWidth();
-
- if (right) {
- mTempRect.left = getScrollX() + width;
- int count = getChildCount();
- if (count > 0) {
- View view = getChildAt(count - 1);
- if (mTempRect.left + width > view.getRight()) {
- mTempRect.left = view.getRight() - width;
- }
- }
- } else {
- mTempRect.left = getScrollX() - width;
- if (mTempRect.left < 0) {
- mTempRect.left = 0;
- }
- }
- mTempRect.right = mTempRect.left + width;
-
- return scrollAndFocus(direction, mTempRect.left, mTempRect.right);
- }
-
- /**
- * <p>Handles scrolling in response to a "home/end" shortcut press. This
- * method will scroll the view to the left or right and give the focus
- * to the leftmost/rightmost component in the new visible area. If no
- * component is a good candidate for focus, this scrollview reclaims the
- * focus.</p>
- *
- * @param direction the scroll direction: {@link android.view.View#FOCUS_LEFT}
- * to go the left of the view or {@link android.view.View#FOCUS_RIGHT}
- * to go the right
- * @return true if the key event is consumed by this method, false otherwise
- */
- public boolean fullScroll(int direction) {
- boolean right = direction == View.FOCUS_RIGHT;
- int width = getWidth();
-
- mTempRect.left = 0;
- mTempRect.right = width;
-
- if (right) {
- int count = getChildCount();
- if (count > 0) {
- View view = getChildAt(count - 1);
- mTempRect.right = view.getRight();
- mTempRect.left = mTempRect.right - width;
- }
- }
-
- return scrollAndFocus(direction, mTempRect.left, mTempRect.right);
- }
-
- /**
- * <p>Scrolls the view to make the area defined by <code>left</code> and
- * <code>right</code> visible. This method attempts to give the focus
- * to a component visible in this area. If no component can be focused in
- * the new visible area, the focus is reclaimed by this scrollview.</p>
- *
- * @param direction the scroll direction: {@link android.view.View#FOCUS_LEFT}
- * to go left {@link android.view.View#FOCUS_RIGHT} to right
- * @param left the left offset of the new area to be made visible
- * @param right the right offset of the new area to be made visible
- * @return true if the key event is consumed by this method, false otherwise
- */
- private boolean scrollAndFocus(int direction, int left, int right) {
- boolean handled = true;
-
- int width = getWidth();
- int containerLeft = getScrollX();
- int containerRight = containerLeft + width;
- boolean goLeft = direction == View.FOCUS_LEFT;
-
- View newFocused = findFocusableViewInBounds(goLeft, left, right);
- if (newFocused == null) {
- newFocused = this;
- }
-
- if (left >= containerLeft && right <= containerRight) {
- handled = false;
- } else {
- int delta = goLeft ? (left - containerLeft) : (right - containerRight);
- doScrollX(delta);
- }
-
- if (newFocused != findFocus() && newFocused.requestFocus(direction)) {
- mScrollViewMovedFocus = true;
- mScrollViewMovedFocus = false;
- }
-
- return handled;
- }
-
- /**
- * Handle scrolling in response to a left or right arrow click.
- *
- * @param direction The direction corresponding to the arrow key that was
- * pressed
- * @return True if we consumed the event, false otherwise
- */
- public boolean arrowScroll(int direction) {
-
- View currentFocused = findFocus();
- if (currentFocused == this) currentFocused = null;
-
- View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, direction);
-
- final int maxJump = getMaxScrollAmount();
-
- if (nextFocused != null && isWithinDeltaOfScreen(nextFocused, maxJump)) {
- nextFocused.getDrawingRect(mTempRect);
- offsetDescendantRectToMyCoords(nextFocused, mTempRect);
- int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
- doScrollX(scrollDelta);
- nextFocused.requestFocus(direction);
- } else {
- // no new focus
- int scrollDelta = maxJump;
-
- if (direction == View.FOCUS_LEFT && getScrollX() < scrollDelta) {
- scrollDelta = getScrollX();
- } else if (direction == View.FOCUS_RIGHT) {
-
- int daRight = getChildAt(getChildCount() - 1).getRight();
-
- int screenRight = getScrollX() + getWidth();
-
- if (daRight - screenRight < maxJump) {
- scrollDelta = daRight - screenRight;
- }
- }
- if (scrollDelta == 0) {
- return false;
- }
- doScrollX(direction == View.FOCUS_RIGHT ? scrollDelta : -scrollDelta);
- }
-
- if (currentFocused != null && currentFocused.isFocused()
- && isOffScreen(currentFocused)) {
- // previously focused item still has focus and is off screen, give
- // it up (take it back to ourselves)
- // (also, need to temporarily force FOCUS_BEFORE_DESCENDANTS so we are
- // sure to
- // get it)
- final int descendantFocusability = getDescendantFocusability(); // save
- setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
- requestFocus();
- setDescendantFocusability(descendantFocusability); // restore
- }
- return true;
- }
-
- /**
- * @return whether the descendant of this scroll view is scrolled off
- * screen.
- */
- private boolean isOffScreen(View descendant) {
- return !isWithinDeltaOfScreen(descendant, 0);
- }
-
- /**
- * @return whether the descendant of this scroll view is within delta
- * pixels of being on the screen.
- */
- private boolean isWithinDeltaOfScreen(View descendant, int delta) {
- descendant.getDrawingRect(mTempRect);
- offsetDescendantRectToMyCoords(descendant, mTempRect);
-
- return (mTempRect.right + delta) >= getScrollX()
- && (mTempRect.left - delta) <= (getScrollX() + getWidth());
- }
-
- /**
- * Smooth scroll by a X delta
- *
- * @param delta the number of pixels to scroll by on the X axis
- */
- private void doScrollX(int delta) {
- if (delta != 0) {
- if (mSmoothScrollingEnabled) {
- smoothScrollBy(delta, 0);
- } else {
- scrollBy(delta, 0);
- }
- }
- }
-
- /**
- * Like {@link View#scrollBy}, but scroll smoothly instead of immediately.
- *
- * @param dx the number of pixels to scroll by on the X axis
- * @param dy the number of pixels to scroll by on the Y axis
- */
- public final void smoothScrollBy(int dx, int dy) {
- long duration = AnimationUtils.currentAnimationTimeMillis() - mLastScroll;
- if (duration > ANIMATED_SCROLL_GAP) {
- mScroller.startScroll(mScrollX, mScrollY, dx, dy);
- invalidate();
- } else {
- if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
- }
- scrollBy(dx, dy);
- }
- mLastScroll = AnimationUtils.currentAnimationTimeMillis();
- }
-
- /**
- * Like {@link #scrollTo}, but scroll smoothly instead of immediately.
- *
- * @param x the position where to scroll on the X axis
- * @param y the position where to scroll on the Y axis
- */
- public final void smoothScrollTo(int x, int y) {
- smoothScrollBy(x - mScrollX, y - mScrollY);
- }
-
- /**
- * <p>The scroll range of a scroll view is the overall width of all of its
- * children.</p>
- */
- @Override
- protected int computeHorizontalScrollRange() {
- int count = getChildCount();
- return count == 0 ? getWidth() : getChildAt(0).getRight();
- }
-
-
- @Override
- protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) {
- ViewGroup.LayoutParams lp = child.getLayoutParams();
-
- int childWidthMeasureSpec;
- int childHeightMeasureSpec;
-
- childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, mPaddingTop
- + mPaddingBottom, lp.height);
-
- childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
-
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- }
-
- @Override
- protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,
- int parentHeightMeasureSpec, int heightUsed) {
- final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
-
- final int childHeightMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
- mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin
- + heightUsed, lp.height);
- final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
- lp.leftMargin + lp.rightMargin, MeasureSpec.UNSPECIFIED);
-
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- }
-
- @Override
- public void computeScroll() {
- if (mScroller.computeScrollOffset()) {
- // This is called at drawing time by ViewGroup. We don't want to
- // re-show the scrollbars at this point, which scrollTo will do,
- // so we replicate most of scrollTo here.
- //
- // It's a little odd to call onScrollChanged from inside the drawing.
- //
- // It is, except when you remember that computeScroll() is used to
- // animate scrolling. So unless we want to defer the onScrollChanged()
- // until the end of the animated scrolling, we don't really have a
- // choice here.
- //
- // I agree. The alternative, which I think would be worse, is to post
- // something and tell the subclasses later. This is bad because there
- // will be a window where mScrollX/Y is different from what the app
- // thinks it is.
- //
- int oldX = mScrollX;
- int oldY = mScrollY;
- int x = mScroller.getCurrX();
- int y = mScroller.getCurrY();
- if (getChildCount() > 0) {
- View child = getChildAt(0);
- mScrollX = clamp(x, getWidth() - mPaddingRight - mPaddingLeft, child.getWidth());
- mScrollY = clamp(y, getHeight() - mPaddingBottom - mPaddingTop, child.getHeight());
- } else {
- mScrollX = x;
- mScrollY = y;
- }
- if (oldX != mScrollX || oldY != mScrollY) {
- onScrollChanged(mScrollX, mScrollY, oldX, oldY);
- }
-
- // Keep on drawing until the animation has finished.
- postInvalidate();
- }
- }
-
- /**
- * Scrolls the view to the given child.
- *
- * @param child the View to scroll to
- */
- private void scrollToChild(View child) {
- child.getDrawingRect(mTempRect);
-
- /* Offset from child's local coordinates to ScrollView coordinates */
- offsetDescendantRectToMyCoords(child, mTempRect);
-
- int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
-
- if (scrollDelta != 0) {
- scrollBy(scrollDelta, 0);
- }
- }
-
- /**
- * If rect is off screen, scroll just enough to get it (or at least the
- * first screen size chunk of it) on screen.
- *
- * @param rect The rectangle.
- * @param immediate True to scroll immediately without animation
- * @return true if scrolling was performed
- */
- private boolean scrollToChildRect(Rect rect, boolean immediate) {
- final int delta = computeScrollDeltaToGetChildRectOnScreen(rect);
- final boolean scroll = delta != 0;
- if (scroll) {
- if (immediate) {
- scrollBy(delta, 0);
- } else {
- smoothScrollBy(delta, 0);
- }
- }
- return scroll;
- }
-
- /**
- * Compute the amount to scroll in the X direction in order to get
- * a rectangle completely on the screen (or, if taller than the screen,
- * at least the first screen size chunk of it).
- *
- * @param rect The rect.
- * @return The scroll delta.
- */
- protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
-
- int width = getWidth();
- int screenLeft = getScrollX();
- int screenRight = screenLeft + width;
-
- int fadingEdge = getHorizontalFadingEdgeLength();
-
- // leave room for left fading edge as long as rect isn't at very left
- if (rect.left > 0) {
- screenLeft += fadingEdge;
- }
-
- // leave room for right fading edge as long as rect isn't at very right
- if (rect.right < getChildAt(0).getWidth()) {
- screenRight -= fadingEdge;
- }
-
- int scrollXDelta = 0;
-
- if (rect.right > screenRight && rect.left > screenLeft) {
- // need to move right to get it in view: move right just enough so
- // that the entire rectangle is in view (or at least the first
- // screen size chunk).
-
- if (rect.width() > width) {
- // just enough to get screen size chunk on
- scrollXDelta += (rect.left - screenLeft);
- } else {
- // get entire rect at right of screen
- scrollXDelta += (rect.right - screenRight);
- }
-
- // make sure we aren't scrolling beyond the end of our content
- int right = getChildAt(getChildCount() - 1).getRight();
- int distanceToRight = right - screenRight;
- scrollXDelta = Math.min(scrollXDelta, distanceToRight);
-
- } else if (rect.left < screenLeft && rect.right < screenRight) {
- // need to move right to get it in view: move right just enough so that
- // entire rectangle is in view (or at least the first screen
- // size chunk of it).
-
- if (rect.width() > width) {
- // screen size chunk
- scrollXDelta -= (screenRight - rect.right);
- } else {
- // entire rect at left
- scrollXDelta -= (screenLeft - rect.left);
- }
-
- // make sure we aren't scrolling any further than the left our content
- scrollXDelta = Math.max(scrollXDelta, -getScrollX());
- }
- return scrollXDelta;
- }
-
- @Override
- public void requestChildFocus(View child, View focused) {
- if (!mScrollViewMovedFocus) {
- if (!mIsLayoutDirty) {
- scrollToChild(focused);
- } else {
- // The child may not be laid out yet, we can't compute the scroll yet
- mChildToScrollTo = focused;
- }
- }
- super.requestChildFocus(child, focused);
- }
-
-
- /**
- * When looking for focus in children of a scroll view, need to be a little
- * more careful not to give focus to something that is scrolled off screen.
- *
- * This is more expensive than the default {@link android.view.ViewGroup}
- * implementation, otherwise this behavior might have been made the default.
- */
- @Override
- protected boolean onRequestFocusInDescendants(int direction,
- Rect previouslyFocusedRect) {
-
- // convert from forward / backward notation to up / down / left / right
- // (ugh).
- if (direction == View.FOCUS_FORWARD) {
- direction = View.FOCUS_RIGHT;
- } else if (direction == View.FOCUS_BACKWARD) {
- direction = View.FOCUS_LEFT;
- }
-
- final View nextFocus = previouslyFocusedRect == null ?
- FocusFinder.getInstance().findNextFocus(this, null, direction) :
- FocusFinder.getInstance().findNextFocusFromRect(this,
- previouslyFocusedRect, direction);
-
- if (nextFocus == null) {
- return false;
- }
-
- if (isOffScreen(nextFocus)) {
- return false;
- }
-
- return nextFocus.requestFocus(direction, previouslyFocusedRect);
- }
-
- @Override
- public boolean requestChildRectangleOnScreen(View child, Rect rectangle,
- boolean immediate) {
- // offset into coordinate space of this scroll view
- rectangle.offset(child.getLeft() - child.getScrollX(),
- child.getTop() - child.getScrollY());
-
- return scrollToChildRect(rectangle, immediate);
- }
-
- @Override
- public void requestLayout() {
- mIsLayoutDirty = true;
- super.requestLayout();
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
- mIsLayoutDirty = false;
- // Give a child focus if it needs it
- if (mChildToScrollTo != null && isViewDescendantOf(mChildToScrollTo, this)) {
- scrollToChild(mChildToScrollTo);
- }
- mChildToScrollTo = null;
-
- // Calling this with the present values causes it to re-clam them
- scrollTo(mScrollX, mScrollY);
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
-
- View currentFocused = findFocus();
- if (null == currentFocused || this == currentFocused)
- return;
-
- final int maxJump = mRight - mLeft;
-
- if (isWithinDeltaOfScreen(currentFocused, maxJump)) {
- currentFocused.getDrawingRect(mTempRect);
- offsetDescendantRectToMyCoords(currentFocused, mTempRect);
- int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
- doScrollX(scrollDelta);
- }
- }
-
- /**
- * Return true if child is an descendant of parent, (or equal to the parent).
- */
- private boolean isViewDescendantOf(View child, View parent) {
- if (child == parent) {
- return true;
- }
-
- final ViewParent theParent = child.getParent();
- return (theParent instanceof ViewGroup) && isViewDescendantOf((View) theParent, parent);
- }
-
- /**
- * Fling the scroll view
- *
- * @param velocityX The initial velocity in the X direction. Positive
- * numbers mean that the finger/curor is moving down the screen,
- * which means we want to scroll towards the left.
- */
- public void fling(int velocityX) {
- int width = getWidth() - mPaddingRight - mPaddingLeft;
- int right = getChildAt(0).getWidth();
-
- mScroller.fling(mScrollX, mScrollY, velocityX, 0, 0, right - width, 0, 0);
-
- final boolean movingRight = velocityX > 0;
-
- View newFocused = findFocusableViewInMyBounds(movingRight,
- mScroller.getFinalX(), findFocus());
-
- if (newFocused == null) {
- newFocused = this;
- }
-
- if (newFocused != findFocus()
- && newFocused.requestFocus(movingRight ? View.FOCUS_RIGHT : View.FOCUS_LEFT)) {
- mScrollViewMovedFocus = true;
- mScrollViewMovedFocus = false;
- }
-
- invalidate();
- }
-
- /**
- * {@inheritDoc}
- *
- * <p>This version also clamps the scrolling to the bounds of our child.
- */
- public void scrollTo(int x, int y) {
- // we rely on the fact the View.scrollBy calls scrollTo.
- if (getChildCount() > 0) {
- View child = getChildAt(0);
- x = clamp(x, getWidth() - mPaddingRight - mPaddingLeft, child.getWidth());
- y = clamp(y, getHeight() - mPaddingBottom - mPaddingTop, child.getHeight());
- if (x != mScrollX || y != mScrollY) {
- super.scrollTo(x, y);
- }
- }
- }
-
- private int clamp(int n, int my, int child) {
- if (my >= child || n < 0) {
- return 0;
- }
- if ((my + n) > child) {
- return child - my;
- }
- return n;
- }
-}
diff --git a/core/java/android/widget/ImageButton.java b/core/java/android/widget/ImageButton.java
deleted file mode 100644
index 4c1cbf6..0000000
--- a/core/java/android/widget/ImageButton.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Message;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.widget.RemoteViews.RemoteView;
-
-import java.util.Map;
-
-/**
- * <p>
- * An image button displays an image that can be pressed, or clicked, by the
- * user.
- * </p>
- *
- * <p><strong>XML attributes</strong></p>
- * <p>
- * See {@link android.R.styleable#ImageView Button Attributes},
- * {@link android.R.styleable#View View Attributes}
- * </p>
- */
-@RemoteView
-public class ImageButton extends ImageView {
- public ImageButton(Context context) {
- this(context, null);
- }
-
- public ImageButton(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.imageButtonStyle);
- }
-
- public ImageButton(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- setFocusable(true);
- }
-
- @Override
- protected boolean onSetAlpha(int alpha) {
- return false;
- }
-}
diff --git a/core/java/android/widget/ImageSwitcher.java b/core/java/android/widget/ImageSwitcher.java
deleted file mode 100644
index bcb750a..0000000
--- a/core/java/android/widget/ImageSwitcher.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import java.util.Map;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.util.AttributeSet;
-
-
-public class ImageSwitcher extends ViewSwitcher
-{
- public ImageSwitcher(Context context)
- {
- super(context);
- }
-
- public ImageSwitcher(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public void setImageResource(int resid)
- {
- ImageView image = (ImageView)this.getNextView();
- image.setImageResource(resid);
- showNext();
- }
-
- public void setImageURI(Uri uri)
- {
- ImageView image = (ImageView)this.getNextView();
- image.setImageURI(uri);
- showNext();
- }
-
- public void setImageDrawable(Drawable drawable)
- {
- ImageView image = (ImageView)this.getNextView();
- image.setImageDrawable(drawable);
- showNext();
- }
-}
-
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
deleted file mode 100644
index 94d1bd1..0000000
--- a/core/java/android/widget/ImageView.java
+++ /dev/null
@@ -1,891 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Matrix;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.graphics.RectF;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.widget.RemoteViews.RemoteView;
-
-
-/**
- * Displays an arbitrary image, such as an icon. The ImageView class
- * can load images from various sources (such as resources or content
- * providers), takes care of computing its measurement from the image so that
- * it can be used in any layout manager, and provides various display options
- * such as scaling and tinting.
- *
- * @attr ref android.R.styleable#ImageView_adjustViewBounds
- * @attr ref android.R.styleable#ImageView_src
- * @attr ref android.R.styleable#ImageView_maxWidth
- * @attr ref android.R.styleable#ImageView_maxHeight
- * @attr ref android.R.styleable#ImageView_tint
- * @attr ref android.R.styleable#ImageView_scaleType
- * @attr ref android.R.styleable#ImageView_cropToPadding
- */
-@RemoteView
-public class ImageView extends View {
- // settable by the client
- private Uri mUri;
- private int mResource = 0;
- private Matrix mMatrix;
- private ScaleType mScaleType;
- private boolean mHaveFrame = false;
- private boolean mAdjustViewBounds = false;
- private int mMaxWidth = Integer.MAX_VALUE;
- private int mMaxHeight = Integer.MAX_VALUE;
-
- // these are applied to the drawable
- private ColorFilter mColorFilter;
- private int mAlpha = 255;
- private int mViewAlphaScale = 256;
-
- private Drawable mDrawable = null;
- private int[] mState = null;
- private boolean mMergeState = false;
- private int mLevel = 0;
- private int mDrawableWidth;
- private int mDrawableHeight;
- private Matrix mDrawMatrix = null;
-
- // Avoid allocations...
- private RectF mTempSrc = new RectF();
- private RectF mTempDst = new RectF();
-
- private boolean mCropToPadding;
-
- private boolean mBaselineAligned = false;
-
- private static final ScaleType[] sScaleTypeArray = {
- ScaleType.MATRIX,
- ScaleType.FIT_XY,
- ScaleType.FIT_START,
- ScaleType.FIT_CENTER,
- ScaleType.FIT_END,
- ScaleType.CENTER,
- ScaleType.CENTER_CROP,
- ScaleType.CENTER_INSIDE
- };
-
- public ImageView(Context context) {
- super(context);
- initImageView();
- }
-
- public ImageView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public ImageView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- initImageView();
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.ImageView, defStyle, 0);
-
- Drawable d = a.getDrawable(com.android.internal.R.styleable.ImageView_src);
- if (d != null) {
- setImageDrawable(d);
- }
-
- mBaselineAligned = a.getBoolean(
- com.android.internal.R.styleable.ImageView_baselineAlignBottom, false);
-
- setAdjustViewBounds(
- a.getBoolean(com.android.internal.R.styleable.ImageView_adjustViewBounds,
- false));
-
- setMaxWidth(a.getDimensionPixelSize(
- com.android.internal.R.styleable.ImageView_maxWidth, Integer.MAX_VALUE));
-
- setMaxHeight(a.getDimensionPixelSize(
- com.android.internal.R.styleable.ImageView_maxHeight, Integer.MAX_VALUE));
-
- int index = a.getInt(com.android.internal.R.styleable.ImageView_scaleType, -1);
- if (index >= 0) {
- setScaleType(sScaleTypeArray[index]);
- }
-
- int tint = a.getInt(com.android.internal.R.styleable.ImageView_tint, 0);
- if (tint != 0) {
- setColorFilter(tint, PorterDuff.Mode.SRC_ATOP);
- }
-
- mCropToPadding = a.getBoolean(
- com.android.internal.R.styleable.ImageView_cropToPadding, false);
-
- a.recycle();
-
- //need inflate syntax/reader for matrix
- }
-
- private void initImageView() {
- mMatrix = new Matrix();
- mScaleType = ScaleType.FIT_CENTER;
- }
-
- @Override
- protected boolean verifyDrawable(Drawable dr) {
- return mDrawable == dr || super.verifyDrawable(dr);
- }
-
- @Override
- public void invalidateDrawable(Drawable dr) {
- if (dr == mDrawable) {
- /* we invalidate the whole view in this case because it's very
- * hard to know where the drawable actually is. This is made
- * complicated because of the offsets and transformations that
- * can be applied. In theory we could get the drawable's bounds
- * and run them through the transformation and offsets, but this
- * is probably not worth the effort.
- */
- invalidate();
- } else {
- super.invalidateDrawable(dr);
- }
- }
-
- @Override
- protected boolean onSetAlpha(int alpha) {
- if (getBackground() == null) {
- int scale = alpha + (alpha >> 7);
- if (mViewAlphaScale != scale) {
- mViewAlphaScale = scale;
- applyColorMod();
- }
- return true;
- }
- return false;
- }
-
- /**
- * Set this to true if you want the ImageView to adjust its bounds
- * to preserve the aspect ratio of its drawable.
- * @param adjustViewBounds Whether to adjust the bounds of this view
- * to presrve the original aspect ratio of the drawable
- *
- * @attr ref android.R.styleable#ImageView_adjustViewBounds
- */
- @android.view.RemotableViewMethod
- public void setAdjustViewBounds(boolean adjustViewBounds) {
- mAdjustViewBounds = adjustViewBounds;
- if (adjustViewBounds) {
- setScaleType(ScaleType.FIT_CENTER);
- }
- }
-
- /**
- * An optional argument to supply a maximum width for this view. Only valid if
- * {@link #setAdjustViewBounds} has been set to true. To set an image to be a maximum of 100 x
- * 100 while preserving the original aspect ratio, do the following: 1) set adjustViewBounds to
- * true 2) set maxWidth and maxHeight to 100 3) set the height and width layout params to
- * WRAP_CONTENT.
- *
- * <p>
- * Note that this view could be still smaller than 100 x 100 using this approach if the original
- * image is small. To set an image to a fixed size, specify that size in the layout params and
- * then use {@link #setScaleType} to determine how to fit the image within the bounds.
- * </p>
- *
- * @param maxWidth maximum width for this view
- *
- * @attr ref android.R.styleable#ImageView_maxWidth
- */
- @android.view.RemotableViewMethod
- public void setMaxWidth(int maxWidth) {
- mMaxWidth = maxWidth;
- }
-
- /**
- * An optional argument to supply a maximum height for this view. Only valid if
- * {@link #setAdjustViewBounds} has been set to true. To set an image to be a maximum of 100 x
- * 100 while preserving the original aspect ratio, do the following: 1) set adjustViewBounds to
- * true 2) set maxWidth and maxHeight to 100 3) set the height and width layout params to
- * WRAP_CONTENT.
- *
- * <p>
- * Note that this view could be still smaller than 100 x 100 using this approach if the original
- * image is small. To set an image to a fixed size, specify that size in the layout params and
- * then use {@link #setScaleType} to determine how to fit the image within the bounds.
- * </p>
- *
- * @param maxHeight maximum height for this view
- *
- * @attr ref android.R.styleable#ImageView_maxHeight
- */
- @android.view.RemotableViewMethod
- public void setMaxHeight(int maxHeight) {
- mMaxHeight = maxHeight;
- }
-
- /** Return the view's drawable, or null if no drawable has been
- assigned.
- */
- public Drawable getDrawable() {
- return mDrawable;
- }
-
- /**
- * Sets a drawable as the content of this ImageView.
- *
- * @param resId the resource identifier of the the drawable
- *
- * @attr ref android.R.styleable#ImageView_src
- */
- @android.view.RemotableViewMethod
- public void setImageResource(int resId) {
- if (mUri != null || mResource != resId) {
- updateDrawable(null);
- mResource = resId;
- mUri = null;
- resolveUri();
- requestLayout();
- invalidate();
- }
- }
-
- /**
- * Sets the content of this ImageView to the specified Uri.
- *
- * @param uri The Uri of an image
- */
- @android.view.RemotableViewMethod
- public void setImageURI(Uri uri) {
- if (mResource != 0 ||
- (mUri != uri &&
- (uri == null || mUri == null || !uri.equals(mUri)))) {
- updateDrawable(null);
- mResource = 0;
- mUri = uri;
- resolveUri();
- requestLayout();
- invalidate();
- }
- }
-
-
- /**
- * Sets a drawable as the content of this ImageView.
- *
- * @param drawable The drawable to set
- */
- public void setImageDrawable(Drawable drawable) {
- if (mDrawable != drawable) {
- mResource = 0;
- mUri = null;
- updateDrawable(drawable);
- requestLayout();
- invalidate();
- }
- }
-
- /**
- * Sets a Bitmap as the content of this ImageView.
- *
- * @param bm The bitmap to set
- */
- @android.view.RemotableViewMethod
- public void setImageBitmap(Bitmap bm) {
- // if this is used frequently, may handle bitmaps explicitly
- // to reduce the intermediate drawable object
- setImageDrawable(new BitmapDrawable(bm));
- }
-
- public void setImageState(int[] state, boolean merge) {
- mState = state;
- mMergeState = merge;
- if (mDrawable != null) {
- refreshDrawableState();
- resizeFromDrawable();
- }
- }
-
- @Override
- public void setSelected(boolean selected) {
- super.setSelected(selected);
- resizeFromDrawable();
- }
-
- @android.view.RemotableViewMethod
- public void setImageLevel(int level) {
- mLevel = level;
- if (mDrawable != null) {
- mDrawable.setLevel(level);
- resizeFromDrawable();
- }
- }
-
- /**
- * Options for scaling the bounds of an image to the bounds of this view.
- */
- public enum ScaleType {
- /**
- * Scale using the image matrix when drawing. The image matrix can be set using
- * {@link ImageView#setImageMatrix(Matrix)}. From XML, use this syntax:
- * <code>android:scaleType="matrix"</code>.
- */
- MATRIX (0),
- /**
- * Scale the image using {@link Matrix.ScaleToFit#FILL}.
- * From XML, use this syntax: <code>android:scaleType="fitXY"</code>.
- */
- FIT_XY (1),
- /**
- * Scale the image using {@link Matrix.ScaleToFit#START}.
- * From XML, use this syntax: <code>android:scaleType="fitStart"</code>.
- */
- FIT_START (2),
- /**
- * Scale the image using {@link Matrix.ScaleToFit#CENTER}.
- * From XML, use this syntax:
- * <code>android:scaleType="fitCenter"</code>.
- */
- FIT_CENTER (3),
- /**
- * Scale the image using {@link Matrix.ScaleToFit#END}.
- * From XML, use this syntax: <code>android:scaleType="fitEnd"</code>.
- */
- FIT_END (4),
- /**
- * Center the image in the view, but perform no scaling.
- * From XML, use this syntax: <code>android:scaleType="center"</code>.
- */
- CENTER (5),
- /**
- * Scale the image uniformly (maintain the image's aspect ratio) so
- * that both dimensions (width and height) of the image will be equal
- * to or larger than the corresponding dimension of the view
- * (minus padding). The image is then centered in the view.
- * From XML, use this syntax: <code>android:scaleType="centerCrop"</code>.
- */
- CENTER_CROP (6),
- /**
- * Scale the image uniformly (maintain the image's aspect ratio) so
- * that both dimensions (width and height) of the image will be equal
- * to or less than the corresponding dimension of the view
- * (minus padding). The image is then centered in the view.
- * From XML, use this syntax: <code>android:scaleType="centerInside"</code>.
- */
- CENTER_INSIDE (7);
-
- ScaleType(int ni) {
- nativeInt = ni;
- }
- final int nativeInt;
- }
-
- /**
- * Controls how the image should be resized or moved to match the size
- * of this ImageView.
- *
- * @param scaleType The desired scaling mode.
- *
- * @attr ref android.R.styleable#ImageView_scaleType
- */
- public void setScaleType(ScaleType scaleType) {
- if (scaleType == null) {
- throw new NullPointerException();
- }
-
- if (mScaleType != scaleType) {
- mScaleType = scaleType;
-
- setWillNotCacheDrawing(mScaleType == ScaleType.CENTER);
-
- requestLayout();
- invalidate();
- }
- }
-
- /**
- * Return the current scale type in use by this ImageView.
- *
- * @see ImageView.ScaleType
- *
- * @attr ref android.R.styleable#ImageView_scaleType
- */
- public ScaleType getScaleType() {
- return mScaleType;
- }
-
- /** Return the view's optional matrix. This is applied to the
- view's drawable when it is drawn. If there is not matrix,
- this method will return null.
- Do not change this matrix in place. If you want a different matrix
- applied to the drawable, be sure to call setImageMatrix().
- */
- public Matrix getImageMatrix() {
- return mMatrix;
- }
-
- public void setImageMatrix(Matrix matrix) {
- // collaps null and identity to just null
- if (matrix != null && matrix.isIdentity()) {
- matrix = null;
- }
-
- // don't invalidate unless we're actually changing our matrix
- if (matrix == null && !mMatrix.isIdentity() ||
- matrix != null && !mMatrix.equals(matrix)) {
- mMatrix.set(matrix);
- invalidate();
- }
- }
-
- private void resolveUri() {
- if (mDrawable != null) {
- return;
- }
-
- Resources rsrc = getResources();
- if (rsrc == null) {
- return;
- }
-
- Drawable d = null;
-
- if (mResource != 0) {
- try {
- d = rsrc.getDrawable(mResource);
- } catch (Exception e) {
- Log.w("ImageView", "Unable to find resource: " + mResource, e);
- // Don't try again.
- mUri = null;
- }
- } else if (mUri != null) {
- if ("content".equals(mUri.getScheme())) {
- try {
- d = Drawable.createFromStream(
- mContext.getContentResolver().openInputStream(mUri),
- null);
- } catch (Exception e) {
- Log.w("ImageView", "Unable to open content: " + mUri, e);
- }
- } else {
- d = Drawable.createFromPath(mUri.toString());
- }
-
- if (d == null) {
- System.out.println("resolveUri failed on bad bitmap uri: "
- + mUri);
- // Don't try again.
- mUri = null;
- }
- } else {
- return;
- }
-
- updateDrawable(d);
- }
-
- @Override
- public int[] onCreateDrawableState(int extraSpace) {
- if (mState == null) {
- return super.onCreateDrawableState(extraSpace);
- } else if (!mMergeState) {
- return mState;
- } else {
- return mergeDrawableStates(
- super.onCreateDrawableState(extraSpace + mState.length), mState);
- }
- }
-
- private void updateDrawable(Drawable d) {
- if (mDrawable != null) {
- mDrawable.setCallback(null);
- unscheduleDrawable(mDrawable);
- }
- mDrawable = d;
- if (d != null) {
- d.setCallback(this);
- if (d.isStateful()) {
- d.setState(getDrawableState());
- }
- d.setLevel(mLevel);
- mDrawableWidth = d.getIntrinsicWidth();
- mDrawableHeight = d.getIntrinsicHeight();
- applyColorMod();
- configureBounds();
- }
- }
-
- private void resizeFromDrawable() {
- Drawable d = mDrawable;
- if (d != null) {
- int w = d.getIntrinsicWidth();
- if (w < 0) w = mDrawableWidth;
- int h = d.getIntrinsicHeight();
- if (h < 0) h = mDrawableHeight;
- if (w != mDrawableWidth || h != mDrawableHeight) {
- mDrawableWidth = w;
- mDrawableHeight = h;
- requestLayout();
- }
- }
- }
-
- private static final Matrix.ScaleToFit[] sS2FArray = {
- Matrix.ScaleToFit.FILL,
- Matrix.ScaleToFit.START,
- Matrix.ScaleToFit.CENTER,
- Matrix.ScaleToFit.END
- };
-
- private static Matrix.ScaleToFit scaleTypeToScaleToFit(ScaleType st) {
- // ScaleToFit enum to their corresponding Matrix.ScaleToFit values
- return sS2FArray[st.nativeInt - 1];
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- resolveUri();
- int w;
- int h;
-
- // Desired aspect ratio of the view's contents (not including padding)
- float desiredAspect = 0.0f;
-
- // We are allowed to change the view's width
- boolean resizeWidth = false;
-
- // We are allowed to change the view's height
- boolean resizeHeight = false;
-
- if (mDrawable == null) {
- // If no drawable, its intrinsic size is 0.
- mDrawableWidth = -1;
- mDrawableHeight = -1;
- w = h = 0;
- } else {
- w = mDrawableWidth;
- h = mDrawableHeight;
- if (w <= 0) w = 1;
- if (h <= 0) h = 1;
-
- // We are supposed to adjust view bounds to match the aspect
- // ratio of our drawable. See if that is possible.
- if (mAdjustViewBounds) {
-
- int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
- int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
-
- resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
- resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;
-
- desiredAspect = (float)w/(float)h;
- }
- }
-
- int pleft = mPaddingLeft;
- int pright = mPaddingRight;
- int ptop = mPaddingTop;
- int pbottom = mPaddingBottom;
-
- int widthSize;
- int heightSize;
-
- if (resizeWidth || resizeHeight) {
- /* If we get here, it means we want to resize to match the
- drawables aspect ratio, and we have the freedom to change at
- least one dimension.
- */
-
- // Get the max possible width given our constraints
- widthSize = resolveAdjustedSize(w + pleft + pright,
- mMaxWidth, widthMeasureSpec);
-
- // Get the max possible height given our constraints
- heightSize = resolveAdjustedSize(h + ptop + pbottom,
- mMaxHeight, heightMeasureSpec);
-
- if (desiredAspect != 0.0f) {
- // See what our actual aspect ratio is
- float actualAspect = (float)(widthSize - pleft - pright) /
- (heightSize - ptop - pbottom);
-
- if (Math.abs(actualAspect - desiredAspect) > 0.0000001) {
-
- boolean done = false;
-
- // Try adjusting width to be proportional to height
- if (resizeWidth) {
- int newWidth = (int)(desiredAspect *
- (heightSize - ptop - pbottom))
- + pleft + pright;
- if (newWidth <= widthSize) {
- widthSize = newWidth;
- done = true;
- }
- }
-
- // Try adjusting height to be proportional to width
- if (!done && resizeHeight) {
- int newHeight = (int)((widthSize - pleft - pright)
- / desiredAspect) + ptop + pbottom;
- if (newHeight <= heightSize) {
- heightSize = newHeight;
- }
- }
- }
- }
- } else {
- /* We are either don't want to preserve the drawables aspect ratio,
- or we are not allowed to change view dimensions. Just measure in
- the normal way.
- */
- w += pleft + pright;
- h += ptop + pbottom;
-
- w = Math.max(w, getSuggestedMinimumWidth());
- h = Math.max(h, getSuggestedMinimumHeight());
-
- widthSize = resolveSize(w, widthMeasureSpec);
- heightSize = resolveSize(h, heightMeasureSpec);
- }
-
- setMeasuredDimension(widthSize, heightSize);
- }
-
- private int resolveAdjustedSize(int desiredSize, int maxSize,
- int measureSpec) {
- int result = desiredSize;
- int specMode = MeasureSpec.getMode(measureSpec);
- int specSize = MeasureSpec.getSize(measureSpec);
- switch (specMode) {
- case MeasureSpec.UNSPECIFIED:
- /* Parent says we can be as big as we want. Just don't be larger
- than max size imposed on ourselves.
- */
- result = Math.min(desiredSize, maxSize);
- break;
- case MeasureSpec.AT_MOST:
- // Parent says we can be as big as we want, up to specSize.
- // Don't be larger than specSize, and don't be larger than
- // the max size imposed on ourselves.
- result = Math.min(Math.min(desiredSize, specSize), maxSize);
- break;
- case MeasureSpec.EXACTLY:
- // No choice. Do what we are told.
- result = specSize;
- break;
- }
- return result;
- }
-
- @Override
- protected boolean setFrame(int l, int t, int r, int b) {
- boolean changed = super.setFrame(l, t, r, b);
- mHaveFrame = true;
- configureBounds();
- return changed;
- }
-
- private void configureBounds() {
- if (mDrawable == null || !mHaveFrame) {
- return;
- }
-
- int dwidth = mDrawableWidth;
- int dheight = mDrawableHeight;
-
- int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
- int vheight = getHeight() - mPaddingTop - mPaddingBottom;
-
- boolean fits = (dwidth < 0 || vwidth == dwidth) &&
- (dheight < 0 || vheight == dheight);
-
- if (dwidth <= 0 || dheight <= 0 || ScaleType.FIT_XY == mScaleType) {
- /* If the drawable has no intrinsic size, or we're told to
- scaletofit, then we just fill our entire view.
- */
- mDrawable.setBounds(0, 0, vwidth, vheight);
- mDrawMatrix = null;
- } else {
- // We need to do the scaling ourself, so have the drawable
- // use its native size.
- mDrawable.setBounds(0, 0, dwidth, dheight);
-
- if (ScaleType.MATRIX == mScaleType) {
- // Use the specified matrix as-is.
- if (mMatrix.isIdentity()) {
- mDrawMatrix = null;
- } else {
- mDrawMatrix = mMatrix;
- }
- } else if (fits) {
- // The bitmap fits exactly, no transform needed.
- mDrawMatrix = null;
- } else if (ScaleType.CENTER == mScaleType) {
- // Center bitmap in view, no scaling.
- mDrawMatrix = mMatrix;
- mDrawMatrix.setTranslate((vwidth - dwidth) * 0.5f,
- (vheight - dheight) * 0.5f);
- } else if (ScaleType.CENTER_CROP == mScaleType) {
- mDrawMatrix = mMatrix;
-
- float scale;
- float dx = 0, dy = 0;
-
- if (dwidth * vheight > vwidth * dheight) {
- scale = (float) vheight / (float) dheight;
- dx = (vwidth - dwidth * scale) * 0.5f;
- } else {
- scale = (float) vwidth / (float) dwidth;
- dy = (vheight - dheight * scale) * 0.5f;
- }
-
- mDrawMatrix.setScale(scale, scale);
- mDrawMatrix.postTranslate(dx, dy);
- } else if (ScaleType.CENTER_INSIDE == mScaleType) {
- mDrawMatrix = mMatrix;
- float scale;
- float dx;
- float dy;
-
- if (dwidth <= vwidth && dheight <= vheight) {
- scale = 1.0f;
- } else {
- scale = Math.min((float) vwidth / (float) dwidth,
- (float) vheight / (float) dheight);
- }
-
- dx = (vwidth - dwidth * scale) * 0.5f;
- dy = (vheight - dheight * scale) * 0.5f;
-
- mDrawMatrix.setScale(scale, scale);
- mDrawMatrix.postTranslate(dx, dy);
- } else {
- // Generate the required transform.
- mTempSrc.set(0, 0, dwidth, dheight);
- mTempDst.set(0, 0, vwidth, vheight);
-
- mDrawMatrix = mMatrix;
- mDrawMatrix.setRectToRect(mTempSrc, mTempDst,
- scaleTypeToScaleToFit(mScaleType));
- }
- }
- }
-
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
- Drawable d = mDrawable;
- if (d != null && d.isStateful()) {
- d.setState(getDrawableState());
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- if (mDrawable == null) {
- return; // couldn't resolve the URI
- }
-
- if (mDrawableWidth == 0 || mDrawableHeight == 0) {
- return; // nothing to draw (empty bounds)
- }
-
- if (mDrawMatrix == null && mPaddingTop == 0 && mPaddingLeft == 0) {
- mDrawable.draw(canvas);
- } else {
- int saveCount = canvas.getSaveCount();
- canvas.save();
-
- if (mCropToPadding) {
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
- canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop,
- scrollX + mRight - mLeft - mPaddingRight,
- scrollY + mBottom - mTop - mPaddingBottom);
- }
-
- canvas.translate(mPaddingLeft, mPaddingTop);
-
- if (mDrawMatrix != null) {
- canvas.concat(mDrawMatrix);
- }
- mDrawable.draw(canvas);
- canvas.restoreToCount(saveCount);
- }
- }
-
- @Override
- public int getBaseline() {
- return mBaselineAligned ? getHeight() : -1;
- }
-
- /**
- * Set a tinting option for the image.
- *
- * @param color Color tint to apply.
- * @param mode How to apply the color. The standard mode is
- * {@link PorterDuff.Mode#SRC_ATOP}
- *
- * @attr ref android.R.styleable#ImageView_tint
- */
- public final void setColorFilter(int color, PorterDuff.Mode mode) {
- setColorFilter(new PorterDuffColorFilter(color, mode));
- }
-
- public final void clearColorFilter() {
- setColorFilter(null);
- }
-
- /**
- * Apply an arbitrary colorfilter to the image.
- *
- * @param cf the colorfilter to apply (may be null)
- */
- public void setColorFilter(ColorFilter cf) {
- if (mColorFilter != cf) {
- mColorFilter = cf;
- applyColorMod();
- invalidate();
- }
- }
-
- public void setAlpha(int alpha) {
- alpha &= 0xFF; // keep it legal
- if (mAlpha != alpha) {
- mAlpha = alpha;
- applyColorMod();
- invalidate();
- }
- }
-
- private void applyColorMod() {
- if (mDrawable != null) {
- mDrawable.setColorFilter(mColorFilter);
- mDrawable.setAlpha(mAlpha * mViewAlphaScale >> 8);
- }
- }
-}
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
deleted file mode 100644
index a9822f8..0000000
--- a/core/java/android/widget/LinearLayout.java
+++ /dev/null
@@ -1,1318 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewDebug;
-import android.view.ViewGroup;
-import android.widget.RemoteViews.RemoteView;
-
-import com.android.internal.R;
-
-
-/**
- * A Layout that arranges its children in a single column or a single row. The direction of
- * the row can be set by calling {@link #setOrientation(int) setOrientation()}.
- * You can also specify gravity, which specifies the alignment of all the child elements by
- * calling {@link #setGravity(int) setGravity()} or specify that specific children
- * grow to fill up any remaining space in the layout by setting the <em>weight</em> member of
- * {@link android.widget.LinearLayout.LayoutParams LinearLayout.LayoutParams}.
- * The default orientation is horizontal.
- *
- * <p>
- * Also see {@link LinearLayout.LayoutParams android.widget.LinearLayout.LayoutParams}
- * for layout attributes </p>
- */
-@RemoteView
-public class LinearLayout extends ViewGroup {
- public static final int HORIZONTAL = 0;
- public static final int VERTICAL = 1;
-
- /**
- * Whether the children of this layout are baseline aligned. Only applicable
- * if {@link #mOrientation} is horizontal.
- */
- private boolean mBaselineAligned = true;
-
- /**
- * If this layout is part of another layout that is baseline aligned,
- * use the child at this index as the baseline.
- *
- * Note: this is orthogonal to {@link #mBaselineAligned}, which is concerned
- * with whether the children of this layout are baseline aligned.
- */
- private int mBaselineAlignedChildIndex = 0;
-
- /**
- * The additional offset to the child's baseline.
- * We'll calculate the baseline of this layout as we measure vertically; for
- * horizontal linear layouts, the offset of 0 is appropriate.
- */
- private int mBaselineChildTop = 0;
-
- private int mOrientation;
- private int mGravity = Gravity.LEFT | Gravity.TOP;
- private int mTotalLength;
-
- private float mWeightSum;
-
- private int[] mMaxAscent;
- private int[] mMaxDescent;
-
- private static final int VERTICAL_GRAVITY_COUNT = 4;
-
- private static final int INDEX_CENTER_VERTICAL = 0;
- private static final int INDEX_TOP = 1;
- private static final int INDEX_BOTTOM = 2;
- private static final int INDEX_FILL = 3;
-
- public LinearLayout(Context context) {
- super(context);
- }
-
- public LinearLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a =
- context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.LinearLayout);
-
- int index = a.getInt(com.android.internal.R.styleable.LinearLayout_orientation, -1);
- if (index >= 0) {
- setOrientation(index);
- }
-
- index = a.getInt(com.android.internal.R.styleable.LinearLayout_gravity, -1);
- if (index >= 0) {
- setGravity(index);
- }
-
- boolean baselineAligned = a.getBoolean(R.styleable.LinearLayout_baselineAligned, true);
- if (!baselineAligned) {
- setBaselineAligned(baselineAligned);
- }
-
- mWeightSum = a.getFloat(R.styleable.LinearLayout_weightSum, -1.0f);
-
- mBaselineAlignedChildIndex =
- a.getInt(com.android.internal.R.styleable.LinearLayout_baselineAlignedChildIndex, -1);
-
- a.recycle();
- }
-
- /**
- * <p>Indicates whether widgets contained within this layout are aligned
- * on their baseline or not.</p>
- *
- * @return true when widgets are baseline-aligned, false otherwise
- */
- public boolean isBaselineAligned() {
- return mBaselineAligned;
- }
-
- /**
- * <p>Defines whether widgets contained in this layout are
- * baseline-aligned or not.</p>
- *
- * @param baselineAligned true to align widgets on their baseline,
- * false otherwise
- *
- * @attr ref android.R.styleable#LinearLayout_baselineAligned
- */
- @android.view.RemotableViewMethod
- public void setBaselineAligned(boolean baselineAligned) {
- mBaselineAligned = baselineAligned;
- }
-
- @Override
- public int getBaseline() {
- if (mBaselineAlignedChildIndex < 0) {
- return super.getBaseline();
- }
-
- if (getChildCount() <= mBaselineAlignedChildIndex) {
- throw new RuntimeException("mBaselineAlignedChildIndex of LinearLayout "
- + "set to an index that is out of bounds.");
- }
-
- final View child = getChildAt(mBaselineAlignedChildIndex);
- final int childBaseline = child.getBaseline();
-
- if (childBaseline == -1) {
- if (mBaselineAlignedChildIndex == 0) {
- // this is just the default case, safe to return -1
- return -1;
- }
- // the user picked an index that points to something that doesn't
- // know how to calculate its baseline.
- throw new RuntimeException("mBaselineAlignedChildIndex of LinearLayout "
- + "points to a View that doesn't know how to get its baseline.");
- }
-
- // TODO: This should try to take into account the virtual offsets
- // (See getNextLocationOffset and getLocationOffset)
- // We should add to childTop:
- // sum([getNextLocationOffset(getChildAt(i)) / i < mBaselineAlignedChildIndex])
- // and also add:
- // getLocationOffset(child)
- int childTop = mBaselineChildTop;
-
- if (mOrientation == VERTICAL) {
- final int majorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
- if (majorGravity != Gravity.TOP) {
- switch (majorGravity) {
- case Gravity.BOTTOM:
- childTop = mBottom - mTop - mPaddingBottom - mTotalLength;
- break;
-
- case Gravity.CENTER_VERTICAL:
- childTop += ((mBottom - mTop - mPaddingTop - mPaddingBottom) -
- mTotalLength) / 2;
- break;
- }
- }
- }
-
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
- return childTop + lp.topMargin + childBaseline;
- }
-
- /**
- * @return The index of the child that will be used if this layout is
- * part of a larger layout that is baseline aligned, or -1 if none has
- * been set.
- */
- public int getBaselineAlignedChildIndex() {
- return mBaselineAlignedChildIndex;
- }
-
- /**
- * @param i The index of the child that will be used if this layout is
- * part of a larger layout that is baseline aligned.
- *
- * @attr ref android.R.styleable#LinearLayout_baselineAlignedChildIndex
- */
- @android.view.RemotableViewMethod
- public void setBaselineAlignedChildIndex(int i) {
- if ((i < 0) || (i >= getChildCount())) {
- throw new IllegalArgumentException("base aligned child index out "
- + "of range (0, " + getChildCount() + ")");
- }
- mBaselineAlignedChildIndex = i;
- }
-
- /**
- * <p>Returns the view at the specified index. This method can be overriden
- * to take into account virtual children. Refer to
- * {@link android.widget.TableLayout} and {@link android.widget.TableRow}
- * for an example.</p>
- *
- * @param index the child's index
- * @return the child at the specified index
- */
- View getVirtualChildAt(int index) {
- return getChildAt(index);
- }
-
- /**
- * <p>Returns the virtual number of children. This number might be different
- * than the actual number of children if the layout can hold virtual
- * children. Refer to
- * {@link android.widget.TableLayout} and {@link android.widget.TableRow}
- * for an example.</p>
- *
- * @return the virtual number of children
- */
- int getVirtualChildCount() {
- return getChildCount();
- }
-
- /**
- * Returns the desired weights sum.
- *
- * @return A number greater than 0.0f if the weight sum is defined, or
- * a number lower than or equals to 0.0f if not weight sum is
- * to be used.
- */
- public float getWeightSum() {
- return mWeightSum;
- }
-
- /**
- * Defines the desired weights sum. If unspecified the weights sum is computed
- * at layout time by adding the layout_weight of each child.
- *
- * This can be used for instance to give a single child 50% of the total
- * available space by giving it a layout_weight of 0.5 and setting the
- * weightSum to 1.0.
- *
- * @param weightSum a number greater than 0.0f, or a number lower than or equals
- * to 0.0f if the weight sum should be computed from the children's
- * layout_weight
- */
- @android.view.RemotableViewMethod
- public void setWeightSum(float weightSum) {
- mWeightSum = Math.max(0.0f, weightSum);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (mOrientation == VERTICAL) {
- measureVertical(widthMeasureSpec, heightMeasureSpec);
- } else {
- measureHorizontal(widthMeasureSpec, heightMeasureSpec);
- }
- }
-
- /**
- * Measures the children when the orientation of this LinearLayout is set
- * to {@link #VERTICAL}.
- *
- * @param widthMeasureSpec Horizontal space requirements as imposed by the parent.
- * @param heightMeasureSpec Vertical space requirements as imposed by the parent.
- *
- * @see #getOrientation()
- * @see #setOrientation(int)
- * @see #onMeasure(int, int)
- */
- void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {
- mTotalLength = 0;
- int maxWidth = 0;
- int alternativeMaxWidth = 0;
- int weightedMaxWidth = 0;
- boolean allFillParent = true;
- float totalWeight = 0;
-
- final int count = getVirtualChildCount();
-
- final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-
- boolean matchWidth = false;
-
- final int baselineChildIndex = mBaselineAlignedChildIndex;
-
- // See how tall everyone is. Also remember max width.
- for (int i = 0; i < count; ++i) {
- final View child = getVirtualChildAt(i);
-
- if (child == null) {
- mTotalLength += measureNullChild(i);
- continue;
- }
-
- if (child.getVisibility() == View.GONE) {
- i += getChildrenSkipCount(child, i);
- continue;
- }
-
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
-
- totalWeight += lp.weight;
-
- if (heightMode == MeasureSpec.EXACTLY && lp.height == 0 && lp.weight > 0) {
- // Optimization: don't bother measuring children who are going to use
- // leftover space. These views will get measured again down below if
- // there is any leftover space.
- mTotalLength += lp.topMargin + lp.bottomMargin;
- } else {
- int oldHeight = Integer.MIN_VALUE;
-
- if (lp.height == 0 && lp.weight > 0) {
- // heightMode is either UNSPECIFIED OR AT_MOST, and this child
- // wanted to stretch to fill available space. Translate that to
- // WRAP_CONTENT so that it does not end up with a height of 0
- oldHeight = 0;
- lp.height = LayoutParams.WRAP_CONTENT;
- }
-
- // Determine how big this child would like to. If this or
- // previous children have given a weight, then we allow it to
- // use all available space (and we will shrink things later
- // if needed).
- measureChildBeforeLayout(
- child, i, widthMeasureSpec, 0, heightMeasureSpec,
- totalWeight == 0 ? mTotalLength : 0);
-
- if (oldHeight != Integer.MIN_VALUE) {
- lp.height = oldHeight;
- }
-
- mTotalLength += child.getMeasuredHeight() + lp.topMargin +
- lp.bottomMargin + getNextLocationOffset(child);
- }
-
- /**
- * If applicable, compute the additional offset to the child's baseline
- * we'll need later when asked {@link #getBaseline}.
- */
- if ((baselineChildIndex >= 0) && (baselineChildIndex == i + 1)) {
- mBaselineChildTop = mTotalLength;
- }
-
- // if we are trying to use a child index for our baseline, the above
- // book keeping only works if there are no children above it with
- // weight. fail fast to aid the developer.
- if (i < baselineChildIndex && lp.weight > 0) {
- throw new RuntimeException("A child of LinearLayout with index "
- + "less than mBaselineAlignedChildIndex has weight > 0, which "
- + "won't work. Either remove the weight, or don't set "
- + "mBaselineAlignedChildIndex.");
- }
-
- boolean matchWidthLocally = false;
- if (widthMode != MeasureSpec.EXACTLY && lp.width == LayoutParams.FILL_PARENT) {
- // The width of the linear layout will scale, and at least one
- // child said it wanted to match our width. Set a flag
- // indicating that we need to remeasure at least that view when
- // we know our width.
- matchWidth = true;
- matchWidthLocally = true;
- }
-
- final int margin = lp.leftMargin + lp.rightMargin;
- final int measuredWidth = child.getMeasuredWidth() + margin;
- maxWidth = Math.max(maxWidth, measuredWidth);
-
- allFillParent = allFillParent && lp.width == LayoutParams.FILL_PARENT;
- if (lp.weight > 0) {
- /*
- * Widths of weighted Views are bogus if we end up
- * remeasuring, so keep them separate.
- */
- weightedMaxWidth = Math.max(weightedMaxWidth,
- matchWidthLocally ? margin : measuredWidth);
- } else {
- alternativeMaxWidth = Math.max(alternativeMaxWidth,
- matchWidthLocally ? margin : measuredWidth);
- }
-
- i += getChildrenSkipCount(child, i);
- }
-
- // Add in our padding
- mTotalLength += mPaddingTop + mPaddingBottom;
-
- int heightSize = mTotalLength;
-
- // Check against our minimum height
- heightSize = Math.max(heightSize, getSuggestedMinimumHeight());
-
- // Reconcile our calculated size with the heightMeasureSpec
- heightSize = resolveSize(heightSize, heightMeasureSpec);
-
- // Either expand children with weight to take up available space or
- // shrink them if they extend beyond our current bounds
- int delta = heightSize - mTotalLength;
- if (delta != 0 && totalWeight > 0.0f) {
- float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
-
- mTotalLength = 0;
-
- for (int i = 0; i < count; ++i) {
- final View child = getVirtualChildAt(i);
-
- if (child.getVisibility() == View.GONE) {
- continue;
- }
-
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
-
- float childExtra = lp.weight;
- if (childExtra > 0) {
- // Child said it could absorb extra space -- give him his share
- int share = (int) (childExtra * delta / weightSum);
- weightSum -= childExtra;
- delta -= share;
-
- final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
- mPaddingLeft + mPaddingRight +
- lp.leftMargin + lp.rightMargin, lp.width);
-
- // TODO: Use a field like lp.isMeasured to figure out if this
- // child has been previously measured
- if ((lp.height != 0) || (heightMode != MeasureSpec.EXACTLY)) {
- // child was measured once already above...
- // base new measurement on stored values
- int childHeight = child.getMeasuredHeight() + share;
- if (childHeight < 0) {
- childHeight = 0;
- }
-
- child.measure(childWidthMeasureSpec,
- MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
- } else {
- // child was skipped in the loop above.
- // Measure for this first time here
- child.measure(childWidthMeasureSpec,
- MeasureSpec.makeMeasureSpec(share > 0 ? share : 0,
- MeasureSpec.EXACTLY));
- }
- }
-
- final int margin = lp.leftMargin + lp.rightMargin;
- final int measuredWidth = child.getMeasuredWidth() + margin;
- maxWidth = Math.max(maxWidth, measuredWidth);
-
- boolean matchWidthLocally = widthMode != MeasureSpec.EXACTLY &&
- lp.width == LayoutParams.FILL_PARENT;
-
- alternativeMaxWidth = Math.max(alternativeMaxWidth,
- matchWidthLocally ? margin : measuredWidth);
-
- allFillParent = allFillParent && lp.width == LayoutParams.FILL_PARENT;
-
- mTotalLength += child.getMeasuredHeight() + lp.topMargin +
- lp.bottomMargin + getNextLocationOffset(child);
- }
-
- // Add in our padding
- mTotalLength += mPaddingTop + mPaddingBottom;
- } else {
- alternativeMaxWidth = Math.max(alternativeMaxWidth,
- weightedMaxWidth);
- }
-
- if (!allFillParent && widthMode != MeasureSpec.EXACTLY) {
- maxWidth = alternativeMaxWidth;
- }
-
- maxWidth += mPaddingLeft + mPaddingRight;
-
- // Check against our minimum width
- maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
-
- setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec), heightSize);
-
- if (matchWidth) {
- forceUniformWidth(count, heightMeasureSpec);
- }
- }
-
- private void forceUniformWidth(int count, int heightMeasureSpec) {
- // Pretend that the linear layout has an exact size.
- int uniformMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(),
- MeasureSpec.EXACTLY);
- for (int i = 0; i< count; ++i) {
- final View child = getVirtualChildAt(i);
- if (child.getVisibility() != GONE) {
- LinearLayout.LayoutParams lp = ((LinearLayout.LayoutParams)child.getLayoutParams());
-
- if (lp.width == LayoutParams.FILL_PARENT) {
- // Temporarily force children to reuse their old measured height
- // FIXME: this may not be right for something like wrapping text?
- int oldHeight = lp.height;
- lp.height = child.getMeasuredHeight();
-
- // Remeasue with new dimensions
- measureChildWithMargins(child, uniformMeasureSpec, 0, heightMeasureSpec, 0);
- lp.height = oldHeight;
- }
- }
- }
- }
-
- /**
- * Measures the children when the orientation of this LinearLayout is set
- * to {@link #HORIZONTAL}.
- *
- * @param widthMeasureSpec Horizontal space requirements as imposed by the parent.
- * @param heightMeasureSpec Vertical space requirements as imposed by the parent.
- *
- * @see #getOrientation()
- * @see #setOrientation(int)
- * @see #onMeasure(int, int)
- */
- void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
- mTotalLength = 0;
- int maxHeight = 0;
- int alternativeMaxHeight = 0;
- int weightedMaxHeight = 0;
- boolean allFillParent = true;
- float totalWeight = 0;
-
- final int count = getVirtualChildCount();
-
- final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-
- boolean matchHeight = false;
-
- if (mMaxAscent == null || mMaxDescent == null) {
- mMaxAscent = new int[VERTICAL_GRAVITY_COUNT];
- mMaxDescent = new int[VERTICAL_GRAVITY_COUNT];
- }
-
- final int[] maxAscent = mMaxAscent;
- final int[] maxDescent = mMaxDescent;
-
- maxAscent[0] = maxAscent[1] = maxAscent[2] = maxAscent[3] = -1;
- maxDescent[0] = maxDescent[1] = maxDescent[2] = maxDescent[3] = -1;
-
- final boolean baselineAligned = mBaselineAligned;
-
- // See how wide everyone is. Also remember max height.
- for (int i = 0; i < count; ++i) {
- final View child = getVirtualChildAt(i);
-
- if (child == null) {
- mTotalLength += measureNullChild(i);
- continue;
- }
-
- if (child.getVisibility() == GONE) {
- i += getChildrenSkipCount(child, i);
- continue;
- }
-
- final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
-
- totalWeight += lp.weight;
-
- if (widthMode == MeasureSpec.EXACTLY && lp.width == 0 && lp.weight > 0) {
- // Optimization: don't bother measuring children who are going to use
- // leftover space. These views will get measured again down below if
- // there is any leftover space.
- mTotalLength += lp.leftMargin + lp.rightMargin;
-
- // Baseline alignment requires to measure widgets to obtain the
- // baseline offset (in particular for TextViews).
- // The following defeats the optimization mentioned above.
- // Allow the child to use as much space as it wants because we
- // can shrink things later (and re-measure).
- if (baselineAligned) {
- final int freeSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- child.measure(freeSpec, freeSpec);
- }
- } else {
- int oldWidth = Integer.MIN_VALUE;
-
- if (lp.width == 0 && lp.weight > 0) {
- // widthMode is either UNSPECIFIED OR AT_MOST, and this child
- // wanted to stretch to fill available space. Translate that to
- // WRAP_CONTENT so that it does not end up with a width of 0
- oldWidth = 0;
- lp.width = LayoutParams.WRAP_CONTENT;
- }
-
- // Determine how big this child would like to be. If this or
- // previous children have given a weight, then we allow it to
- // use all available space (and we will shrink things later
- // if needed).
- measureChildBeforeLayout(child, i, widthMeasureSpec,
- totalWeight == 0 ? mTotalLength : 0,
- heightMeasureSpec, 0);
-
- if (oldWidth != Integer.MIN_VALUE) {
- lp.width = oldWidth;
- }
-
- mTotalLength += child.getMeasuredWidth() + lp.leftMargin +
- lp.rightMargin + getNextLocationOffset(child);
- }
-
- boolean matchHeightLocally = false;
- if (heightMode != MeasureSpec.EXACTLY && lp.height == LayoutParams.FILL_PARENT) {
- // The height of the linear layout will scale, and at least one
- // child said it wanted to match our height. Set a flag indicating that
- // we need to remeasure at least that view when we know our height.
- matchHeight = true;
- matchHeightLocally = true;
- }
-
- final int margin = lp.topMargin + lp.bottomMargin;
- final int childHeight = child.getMeasuredHeight() + margin;
-
- if (baselineAligned) {
- final int childBaseline = child.getBaseline();
- if (childBaseline != -1) {
- // Translates the child's vertical gravity into an index
- // in the range 0..VERTICAL_GRAVITY_COUNT
- final int gravity = (lp.gravity < 0 ? mGravity : lp.gravity)
- & Gravity.VERTICAL_GRAVITY_MASK;
- final int index = ((gravity >> Gravity.AXIS_Y_SHIFT)
- & ~Gravity.AXIS_SPECIFIED) >> 1;
-
- maxAscent[index] = Math.max(maxAscent[index], childBaseline);
- maxDescent[index] = Math.max(maxDescent[index], childHeight - childBaseline);
- }
- }
-
- maxHeight = Math.max(maxHeight, childHeight);
-
- allFillParent = allFillParent && lp.height == LayoutParams.FILL_PARENT;
- if (lp.weight > 0) {
- /*
- * Heights of weighted Views are bogus if we end up
- * remeasuring, so keep them separate.
- */
- weightedMaxHeight = Math.max(weightedMaxHeight,
- matchHeightLocally ? margin : childHeight);
- } else {
- alternativeMaxHeight = Math.max(alternativeMaxHeight,
- matchHeightLocally ? margin : childHeight);
- }
-
- i += getChildrenSkipCount(child, i);
- }
-
- // Check mMaxAscent[INDEX_TOP] first because it maps to Gravity.TOP,
- // the most common case
- if (maxAscent[INDEX_TOP] != -1 ||
- maxAscent[INDEX_CENTER_VERTICAL] != -1 ||
- maxAscent[INDEX_BOTTOM] != -1 ||
- maxAscent[INDEX_FILL] != -1) {
- final int ascent = Math.max(maxAscent[INDEX_FILL],
- Math.max(maxAscent[INDEX_CENTER_VERTICAL],
- Math.max(maxAscent[INDEX_TOP], maxAscent[INDEX_BOTTOM])));
- final int descent = Math.max(maxDescent[INDEX_FILL],
- Math.max(maxDescent[INDEX_CENTER_VERTICAL],
- Math.max(maxDescent[INDEX_TOP], maxDescent[INDEX_BOTTOM])));
- maxHeight = Math.max(maxHeight, ascent + descent);
- }
-
- // Add in our padding
- mTotalLength += mPaddingLeft + mPaddingRight;
-
- int widthSize = mTotalLength;
-
- // Check against our minimum width
- widthSize = Math.max(widthSize, getSuggestedMinimumWidth());
-
- // Reconcile our calculated size with the widthMeasureSpec
- widthSize = resolveSize(widthSize, widthMeasureSpec);
-
- // Either expand children with weight to take up available space or
- // shrink them if they extend beyond our current bounds
- int delta = widthSize - mTotalLength;
- if (delta != 0 && totalWeight > 0.0f) {
- float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
-
- maxAscent[0] = maxAscent[1] = maxAscent[2] = maxAscent[3] = -1;
- maxDescent[0] = maxDescent[1] = maxDescent[2] = maxDescent[3] = -1;
- maxHeight = -1;
-
- mTotalLength = 0;
-
- for (int i = 0; i < count; ++i) {
- final View child = getVirtualChildAt(i);
-
- if (child == null || child.getVisibility() == View.GONE) {
- continue;
- }
-
- final LinearLayout.LayoutParams lp =
- (LinearLayout.LayoutParams) child.getLayoutParams();
-
- float childExtra = lp.weight;
- if (childExtra > 0) {
- // Child said it could absorb extra space -- give him his share
- int share = (int) (childExtra * delta / weightSum);
- weightSum -= childExtra;
- delta -= share;
-
- final int childHeightMeasureSpec = getChildMeasureSpec(
- heightMeasureSpec,
- mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin,
- lp.height);
-
- // TODO: Use a field like lp.isMeasured to figure out if this
- // child has been previously measured
- if ((lp.width != 0) || (widthMode != MeasureSpec.EXACTLY)) {
- // child was measured once already above ... base new measurement
- // on stored values
- int childWidth = child.getMeasuredWidth() + share;
- if (childWidth < 0) {
- childWidth = 0;
- }
-
- child.measure(
- MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
- childHeightMeasureSpec);
- } else {
- // child was skipped in the loop above. Measure for this first time here
- child.measure(MeasureSpec.makeMeasureSpec(
- share > 0 ? share : 0, MeasureSpec.EXACTLY),
- childHeightMeasureSpec);
- }
- }
-
- mTotalLength += child.getMeasuredWidth() + lp.leftMargin +
- lp.rightMargin + getNextLocationOffset(child);
-
- boolean matchHeightLocally = heightMode != MeasureSpec.EXACTLY &&
- lp.height == LayoutParams.FILL_PARENT;
-
- final int margin = lp.topMargin + lp .bottomMargin;
- int childHeight = child.getMeasuredHeight() + margin;
- maxHeight = Math.max(maxHeight, childHeight);
- alternativeMaxHeight = Math.max(alternativeMaxHeight,
- matchHeightLocally ? margin : childHeight);
-
- allFillParent = allFillParent && lp.height == LayoutParams.FILL_PARENT;
-
- if (baselineAligned) {
- final int childBaseline = child.getBaseline();
- if (childBaseline != -1) {
- // Translates the child's vertical gravity into an index in the range 0..2
- final int gravity = (lp.gravity < 0 ? mGravity : lp.gravity)
- & Gravity.VERTICAL_GRAVITY_MASK;
- final int index = ((gravity >> Gravity.AXIS_Y_SHIFT)
- & ~Gravity.AXIS_SPECIFIED) >> 1;
-
- maxAscent[index] = Math.max(maxAscent[index], childBaseline);
- maxDescent[index] = Math.max(maxDescent[index],
- childHeight - childBaseline);
- }
- }
- }
-
- // Add in our padding
- mTotalLength += mPaddingLeft + mPaddingRight;
-
- // Check mMaxAscent[INDEX_TOP] first because it maps to Gravity.TOP,
- // the most common case
- if (maxAscent[INDEX_TOP] != -1 ||
- maxAscent[INDEX_CENTER_VERTICAL] != -1 ||
- maxAscent[INDEX_BOTTOM] != -1 ||
- maxAscent[INDEX_FILL] != -1) {
- final int ascent = Math.max(maxAscent[INDEX_FILL],
- Math.max(maxAscent[INDEX_CENTER_VERTICAL],
- Math.max(maxAscent[INDEX_TOP], maxAscent[INDEX_BOTTOM])));
- final int descent = Math.max(maxDescent[INDEX_FILL],
- Math.max(maxDescent[INDEX_CENTER_VERTICAL],
- Math.max(maxDescent[INDEX_TOP], maxDescent[INDEX_BOTTOM])));
- maxHeight = Math.max(maxHeight, ascent + descent);
- }
- } else {
- alternativeMaxHeight = Math.max(alternativeMaxHeight, weightedMaxHeight);
- }
-
- if (!allFillParent && heightMode != MeasureSpec.EXACTLY) {
- maxHeight = alternativeMaxHeight;
- }
-
- maxHeight += mPaddingTop + mPaddingBottom;
-
- // Check against our minimum height
- maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
-
- setMeasuredDimension(widthSize, resolveSize(maxHeight, heightMeasureSpec));
-
- if (matchHeight) {
- forceUniformHeight(count, widthMeasureSpec);
- }
- }
-
- private void forceUniformHeight(int count, int widthMeasureSpec) {
- // Pretend that the linear layout has an exact size. This is the measured height of
- // ourselves. The measured height should be the max height of the children, changed
- // to accomodate the heightMesureSpec from the parent
- int uniformMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(),
- MeasureSpec.EXACTLY);
- for (int i = 0; i < count; ++i) {
- final View child = getVirtualChildAt(i);
- if (child.getVisibility() != GONE) {
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
-
- if (lp.height == LayoutParams.FILL_PARENT) {
- // Temporarily force children to reuse their old measured width
- // FIXME: this may not be right for something like wrapping text?
- int oldWidth = lp.width;
- lp.width = child.getMeasuredWidth();
-
- // Remeasure with new dimensions
- measureChildWithMargins(child, widthMeasureSpec, 0, uniformMeasureSpec, 0);
- lp.width = oldWidth;
- }
- }
- }
- }
-
- /**
- * <p>Returns the number of children to skip after measuring/laying out
- * the specified child.</p>
- *
- * @param child the child after which we want to skip children
- * @param index the index of the child after which we want to skip children
- * @return the number of children to skip, 0 by default
- */
- int getChildrenSkipCount(View child, int index) {
- return 0;
- }
-
- /**
- * <p>Returns the size (width or height) that should be occupied by a null
- * child.</p>
- *
- * @param childIndex the index of the null child
- * @return the width or height of the child depending on the orientation
- */
- int measureNullChild(int childIndex) {
- return 0;
- }
-
- /**
- * <p>Measure the child according to the parent's measure specs. This
- * method should be overriden by subclasses to force the sizing of
- * children. This method is called by {@link #measureVertical(int, int)} and
- * {@link #measureHorizontal(int, int)}.</p>
- *
- * @param child the child to measure
- * @param childIndex the index of the child in this view
- * @param widthMeasureSpec horizontal space requirements as imposed by the parent
- * @param totalWidth extra space that has been used up by the parent horizontally
- * @param heightMeasureSpec vertical space requirements as imposed by the parent
- * @param totalHeight extra space that has been used up by the parent vertically
- */
- void measureChildBeforeLayout(View child, int childIndex,
- int widthMeasureSpec, int totalWidth, int heightMeasureSpec,
- int totalHeight) {
- measureChildWithMargins(child, widthMeasureSpec, totalWidth,
- heightMeasureSpec, totalHeight);
- }
-
- /**
- * <p>Return the location offset of the specified child. This can be used
- * by subclasses to change the location of a given widget.</p>
- *
- * @param child the child for which to obtain the location offset
- * @return the location offset in pixels
- */
- int getLocationOffset(View child) {
- return 0;
- }
-
- /**
- * <p>Return the size offset of the next sibling of the specified child.
- * This can be used by subclasses to change the location of the widget
- * following <code>child</code>.</p>
- *
- * @param child the child whose next sibling will be moved
- * @return the location offset of the next child in pixels
- */
- int getNextLocationOffset(View child) {
- return 0;
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- if (mOrientation == VERTICAL) {
- layoutVertical();
- } else {
- layoutHorizontal();
- }
- }
-
- /**
- * Position the children during a layout pass if the orientation of this
- * LinearLayout is set to {@link #VERTICAL}.
- *
- * @see #getOrientation()
- * @see #setOrientation(int)
- * @see #onLayout(boolean, int, int, int, int)
- */
- void layoutVertical() {
- final int paddingLeft = mPaddingLeft;
-
- int childTop = mPaddingTop;
- int childLeft = paddingLeft;
-
- // Where right end of child should go
- final int width = mRight - mLeft;
- int childRight = width - mPaddingRight;
-
- // Space available for child
- int childSpace = width - paddingLeft - mPaddingRight;
-
- final int count = getVirtualChildCount();
-
- final int majorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
- final int minorGravity = mGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
-
- if (majorGravity != Gravity.TOP) {
- switch (majorGravity) {
- case Gravity.BOTTOM:
- // mTotalLength contains the padding already, we add the top
- // padding to compensate
- childTop = mBottom - mTop + mPaddingTop - mTotalLength;
- break;
-
- case Gravity.CENTER_VERTICAL:
- childTop += ((mBottom - mTop) - mTotalLength) / 2;
- break;
- }
-
- }
-
- for (int i = 0; i < count; i++) {
- final View child = getVirtualChildAt(i);
- if (child == null) {
- childTop += measureNullChild(i);
- } else if (child.getVisibility() != GONE) {
- final int childWidth = child.getMeasuredWidth();
- final int childHeight = child.getMeasuredHeight();
-
- final LinearLayout.LayoutParams lp =
- (LinearLayout.LayoutParams) child.getLayoutParams();
-
- int gravity = lp.gravity;
- if (gravity < 0) {
- gravity = minorGravity;
- }
-
- switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- childLeft = paddingLeft + lp.leftMargin;
- break;
-
- case Gravity.CENTER_HORIZONTAL:
- childLeft = paddingLeft + ((childSpace - childWidth) / 2)
- + lp.leftMargin - lp.rightMargin;
- break;
-
- case Gravity.RIGHT:
- childLeft = childRight - childWidth - lp.rightMargin;
- break;
- }
-
-
- childTop += lp.topMargin;
- setChildFrame(child, childLeft, childTop + getLocationOffset(child),
- childWidth, childHeight);
- childTop += childHeight + lp.bottomMargin + getNextLocationOffset(child);
-
- i += getChildrenSkipCount(child, i);
- }
- }
- }
-
- /**
- * Position the children during a layout pass if the orientation of this
- * LinearLayout is set to {@link #HORIZONTAL}.
- *
- * @see #getOrientation()
- * @see #setOrientation(int)
- * @see #onLayout(boolean, int, int, int, int)
- */
- void layoutHorizontal() {
- final int paddingTop = mPaddingTop;
-
- int childTop = paddingTop;
- int childLeft = mPaddingLeft;
-
- // Where bottom of child should go
- final int height = mBottom - mTop;
- int childBottom = height - mPaddingBottom;
-
- // Space available for child
- int childSpace = height - paddingTop - mPaddingBottom;
-
- final int count = getVirtualChildCount();
-
- final int majorGravity = mGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
- final int minorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
-
- final boolean baselineAligned = mBaselineAligned;
-
- final int[] maxAscent = mMaxAscent;
- final int[] maxDescent = mMaxDescent;
-
- if (majorGravity != Gravity.LEFT) {
- switch (majorGravity) {
- case Gravity.RIGHT:
- // mTotalLength contains the padding already, we add the left
- // padding to compensate
- childLeft = mRight - mLeft + mPaddingLeft - mTotalLength;
- break;
-
- case Gravity.CENTER_HORIZONTAL:
- childLeft += ((mRight - mLeft) - mTotalLength) / 2;
- break;
- }
- }
-
- for (int i = 0; i < count; i++) {
- final View child = getVirtualChildAt(i);
-
- if (child == null) {
- childLeft += measureNullChild(i);
- } else if (child.getVisibility() != GONE) {
- final int childWidth = child.getMeasuredWidth();
- final int childHeight = child.getMeasuredHeight();
- int childBaseline = -1;
-
- final LinearLayout.LayoutParams lp =
- (LinearLayout.LayoutParams) child.getLayoutParams();
-
- if (baselineAligned && lp.height != LayoutParams.FILL_PARENT) {
- childBaseline = child.getBaseline();
- }
-
- int gravity = lp.gravity;
- if (gravity < 0) {
- gravity = minorGravity;
- }
-
- switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
- case Gravity.TOP:
- childTop = paddingTop + lp.topMargin;
- if (childBaseline != -1) {
- childTop += maxAscent[INDEX_TOP] - childBaseline;
- }
- break;
-
- case Gravity.CENTER_VERTICAL:
- // Removed support for baselign alignment when layout_gravity or
- // gravity == center_vertical. See bug #1038483.
- // Keep the code around if we need to re-enable this feature
- // if (childBaseline != -1) {
- // // Align baselines vertically only if the child is smaller than us
- // if (childSpace - childHeight > 0) {
- // childTop = paddingTop + (childSpace / 2) - childBaseline;
- // } else {
- // childTop = paddingTop + (childSpace - childHeight) / 2;
- // }
- // } else {
- childTop = paddingTop + ((childSpace - childHeight) / 2)
- + lp.topMargin - lp.bottomMargin;
- break;
-
- case Gravity.BOTTOM:
- childTop = childBottom - childHeight - lp.bottomMargin;
- if (childBaseline != -1) {
- int descent = child.getMeasuredHeight() - childBaseline;
- childTop -= (maxDescent[INDEX_BOTTOM] - descent);
- }
- break;
- }
-
- childLeft += lp.leftMargin;
- setChildFrame(child, childLeft + getLocationOffset(child), childTop,
- childWidth, childHeight);
- childLeft += childWidth + lp.rightMargin +
- getNextLocationOffset(child);
-
- i += getChildrenSkipCount(child, i);
- }
- }
- }
-
- private void setChildFrame(View child, int left, int top, int width, int height) {
- child.layout(left, top, left + width, top + height);
- }
-
- /**
- * Should the layout be a column or a row.
- * @param orientation Pass HORIZONTAL or VERTICAL. Default
- * value is HORIZONTAL.
- *
- * @attr ref android.R.styleable#LinearLayout_orientation
- */
- public void setOrientation(int orientation) {
- if (mOrientation != orientation) {
- mOrientation = orientation;
- requestLayout();
- }
- }
-
- /**
- * Returns the current orientation.
- *
- * @return either {@link #HORIZONTAL} or {@link #VERTICAL}
- */
- public int getOrientation() {
- return mOrientation;
- }
-
- /**
- * Describes how the child views are positioned. Defaults to GRAVITY_TOP. If
- * this layout has a VERTICAL orientation, this controls where all the child
- * views are placed if there is extra vertical space. If this layout has a
- * HORIZONTAL orientation, this controls the alignment of the children.
- *
- * @param gravity See {@link android.view.Gravity}
- *
- * @attr ref android.R.styleable#LinearLayout_gravity
- */
- @android.view.RemotableViewMethod
- public void setGravity(int gravity) {
- if (mGravity != gravity) {
- if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
- gravity |= Gravity.LEFT;
- }
-
- if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
- gravity |= Gravity.TOP;
- }
-
- mGravity = gravity;
- requestLayout();
- }
- }
-
- @android.view.RemotableViewMethod
- public void setHorizontalGravity(int horizontalGravity) {
- final int gravity = horizontalGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
- if ((mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != gravity) {
- mGravity = (mGravity & ~Gravity.HORIZONTAL_GRAVITY_MASK) | gravity;
- requestLayout();
- }
- }
-
- @android.view.RemotableViewMethod
- public void setVerticalGravity(int verticalGravity) {
- final int gravity = verticalGravity & Gravity.VERTICAL_GRAVITY_MASK;
- if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != gravity) {
- mGravity = (mGravity & ~Gravity.VERTICAL_GRAVITY_MASK) | gravity;
- requestLayout();
- }
- }
-
- @Override
- public LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new LinearLayout.LayoutParams(getContext(), attrs);
- }
-
- /**
- * Returns a set of layout parameters with a width of
- * {@link android.view.ViewGroup.LayoutParams#FILL_PARENT}
- * and a height of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}
- * when the layout's orientation is {@link #VERTICAL}. When the orientation is
- * {@link #HORIZONTAL}, the width is set to {@link LayoutParams#WRAP_CONTENT}
- * and the height to {@link LayoutParams#WRAP_CONTENT}.
- */
- @Override
- protected LayoutParams generateDefaultLayoutParams() {
- if (mOrientation == HORIZONTAL) {
- return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- } else if (mOrientation == VERTICAL) {
- return new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
- }
- return null;
- }
-
- @Override
- protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return new LayoutParams(p);
- }
-
-
- // Override to allow type-checking of LayoutParams.
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof LinearLayout.LayoutParams;
- }
-
- /**
- * Per-child layout information associated with ViewLinearLayout.
- *
- * @attr ref android.R.styleable#LinearLayout_Layout_layout_weight
- * @attr ref android.R.styleable#LinearLayout_Layout_layout_gravity
- */
- public static class LayoutParams extends ViewGroup.MarginLayoutParams {
- /**
- * Indicates how much of the extra space in the LinearLayout will be
- * allocated to the view associated with these LayoutParams. Specify
- * 0 if the view should not be stretched. Otherwise the extra pixels
- * will be pro-rated among all views whose weight is greater than 0.
- */
- @ViewDebug.ExportedProperty
- public float weight;
-
- /**
- * Gravity for the view associated with these LayoutParams.
- *
- * @see android.view.Gravity
- */
- @ViewDebug.ExportedProperty(mapping = {
- @ViewDebug.IntToString(from = -1, to = "NONE"),
- @ViewDebug.IntToString(from = Gravity.NO_GRAVITY, to = "NONE"),
- @ViewDebug.IntToString(from = Gravity.TOP, to = "TOP"),
- @ViewDebug.IntToString(from = Gravity.BOTTOM, to = "BOTTOM"),
- @ViewDebug.IntToString(from = Gravity.LEFT, to = "LEFT"),
- @ViewDebug.IntToString(from = Gravity.RIGHT, to = "RIGHT"),
- @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL, to = "CENTER_VERTICAL"),
- @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL, to = "FILL_VERTICAL"),
- @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"),
- @ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL, to = "FILL_HORIZONTAL"),
- @ViewDebug.IntToString(from = Gravity.CENTER, to = "CENTER"),
- @ViewDebug.IntToString(from = Gravity.FILL, to = "FILL")
- })
- public int gravity = -1;
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
- TypedArray a =
- c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.LinearLayout_Layout);
-
- weight = a.getFloat(com.android.internal.R.styleable.LinearLayout_Layout_layout_weight, 0);
- gravity = a.getInt(com.android.internal.R.styleable.LinearLayout_Layout_layout_gravity, -1);
-
- a.recycle();
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(int width, int height) {
- super(width, height);
- weight = 0;
- }
-
- /**
- * Creates a new set of layout parameters with the specified width, height
- * and weight.
- *
- * @param width the width, either {@link #FILL_PARENT},
- * {@link #WRAP_CONTENT} or a fixed size in pixels
- * @param height the height, either {@link #FILL_PARENT},
- * {@link #WRAP_CONTENT} or a fixed size in pixels
- * @param weight the weight
- */
- public LayoutParams(int width, int height, float weight) {
- super(width, height);
- this.weight = weight;
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(ViewGroup.LayoutParams p) {
- super(p);
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(MarginLayoutParams source) {
- super(source);
- }
-
- @Override
- public String debug(String output) {
- return output + "LinearLayout.LayoutParams={width=" + sizeToString(width) +
- ", height=" + sizeToString(height) + " weight=" + weight + "}";
- }
- }
-}
diff --git a/core/java/android/widget/ListAdapter.java b/core/java/android/widget/ListAdapter.java
deleted file mode 100644
index a035145..0000000
--- a/core/java/android/widget/ListAdapter.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-/**
- * Extended {@link Adapter} that is the bridge between a {@link ListView}
- * and the data that backs the list. Frequently that data comes from a Cursor,
- * but that is not
- * required. The ListView can display any data provided that it is wrapped in a
- * ListAdapter.
- */
-public interface ListAdapter extends Adapter {
-
- /**
- * Are all items in this ListAdapter enabled?
- * If yes it means all items are selectable and clickable.
- *
- * @return True if all items are enabled
- */
- public boolean areAllItemsEnabled();
-
- /**
- * Returns true if the item at the specified position is not a separator.
- * (A separator is a non-selectable, non-clickable item).
- *
- * @param position Index of the item
- * @return True if the item is not a separator
- */
- boolean isEnabled(int position);
-}
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
deleted file mode 100644
index 4e5989c..0000000
--- a/core/java/android/widget/ListView.java
+++ /dev/null
@@ -1,3274 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.ColorDrawable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.util.SparseBooleanArray;
-import android.util.SparseArray;
-import android.view.FocusFinder;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewDebug;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.view.SoundEffectConstants;
-
-import com.google.android.collect.Lists;
-import com.android.internal.R;
-
-import java.util.ArrayList;
-
-/*
- * Implementation Notes:
- *
- * Some terminology:
- *
- * index - index of the items that are currently visible
- * position - index of the items in the cursor
- */
-
-
-/**
- * A view that shows items in a vertically scrolling list. The items
- * come from the {@link ListAdapter} associated with this view.
- *
- * @attr ref android.R.styleable#ListView_entries
- * @attr ref android.R.styleable#ListView_divider
- * @attr ref android.R.styleable#ListView_dividerHeight
- * @attr ref android.R.styleable#ListView_choiceMode
- * @attr ref android.R.styleable#ListView_headerDividersEnabled
- * @attr ref android.R.styleable#ListView_footerDividersEnabled
- */
-public class ListView extends AbsListView {
- /**
- * Used to indicate a no preference for a position type.
- */
- static final int NO_POSITION = -1;
-
- /**
- * Normal list that does not indicate choices
- */
- public static final int CHOICE_MODE_NONE = 0;
-
- /**
- * The list allows up to one choice
- */
- public static final int CHOICE_MODE_SINGLE = 1;
-
- /**
- * The list allows multiple choices
- */
- public static final int CHOICE_MODE_MULTIPLE = 2;
-
- /**
- * When arrow scrolling, ListView will never scroll more than this factor
- * times the height of the list.
- */
- private static final float MAX_SCROLL_FACTOR = 0.33f;
-
- /**
- * When arrow scrolling, need a certain amount of pixels to preview next
- * items. This is usually the fading edge, but if that is small enough,
- * we want to make sure we preview at least this many pixels.
- */
- private static final int MIN_SCROLL_PREVIEW_PIXELS = 2;
-
- /**
- * A class that represents a fixed view in a list, for example a header at the top
- * or a footer at the bottom.
- */
- public class FixedViewInfo {
- /** The view to add to the list */
- public View view;
- /** The data backing the view. This is returned from {@link ListAdapter#getItem(int)}. */
- public Object data;
- /** <code>true</code> if the fixed view should be selectable in the list */
- public boolean isSelectable;
- }
-
- private ArrayList<FixedViewInfo> mHeaderViewInfos = Lists.newArrayList();
- private ArrayList<FixedViewInfo> mFooterViewInfos = Lists.newArrayList();
-
- Drawable mDivider;
- int mDividerHeight;
- private boolean mClipDivider;
- private boolean mHeaderDividersEnabled;
- private boolean mFooterDividersEnabled;
-
- private boolean mAreAllItemsSelectable = true;
-
- private boolean mItemsCanFocus = false;
-
- private int mChoiceMode = CHOICE_MODE_NONE;
-
- private SparseBooleanArray mCheckStates;
-
- // used for temporary calculations.
- private Rect mTempRect = new Rect();
-
- /**
- * Used to save / restore the state of the focused child in {@link #layoutChildren()}
- */
- private SparseArray<Parcelable> mfocusRestoreChildState = new SparseArray<Parcelable>();
-
-
- // the single allocated result per list view; kinda cheesey but avoids
- // allocating these thingies too often.
- private ArrowScrollFocusResult mArrowScrollFocusResult = new ArrowScrollFocusResult();
-
- public ListView(Context context) {
- this(context, null);
- }
-
- public ListView(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.listViewStyle);
- }
-
- public ListView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.ListView, defStyle, 0);
-
- CharSequence[] entries = a.getTextArray(
- com.android.internal.R.styleable.ListView_entries);
- if (entries != null) {
- setAdapter(new ArrayAdapter<CharSequence>(context,
- com.android.internal.R.layout.simple_list_item_1, entries));
- }
-
- final Drawable d = a.getDrawable(com.android.internal.R.styleable.ListView_divider);
- if (d != null) {
- // If a divider is specified use its intrinsic height for divider height
- setDivider(d);
- }
-
- // Use the height specified, zero being the default
- final int dividerHeight = a.getDimensionPixelSize(
- com.android.internal.R.styleable.ListView_dividerHeight, 0);
- if (dividerHeight != 0) {
- setDividerHeight(dividerHeight);
- }
-
- mHeaderDividersEnabled = a.getBoolean(R.styleable.ListView_headerDividersEnabled, true);
- mFooterDividersEnabled = a.getBoolean(R.styleable.ListView_footerDividersEnabled, true);
-
- a.recycle();
- }
-
- /**
- * @return The maximum amount a list view will scroll in response to
- * an arrow event.
- */
- public int getMaxScrollAmount() {
- return (int) (MAX_SCROLL_FACTOR * (mBottom - mTop));
- }
-
- /**
- * Make sure views are touching the top or bottom edge, as appropriate for
- * our gravity
- */
- private void adjustViewsUpOrDown() {
- final int childCount = getChildCount();
- int delta;
-
- if (childCount > 0) {
- View child;
-
- if (!mStackFromBottom) {
- // Uh-oh -- we came up short. Slide all views up to make them
- // align with the top
- child = getChildAt(0);
- delta = child.getTop() - mListPadding.top;
- if (mFirstPosition != 0) {
- // It's OK to have some space above the first item if it is
- // part of the vertical spacing
- delta -= mDividerHeight;
- }
- if (delta < 0) {
- // We only are looking to see if we are too low, not too high
- delta = 0;
- }
- } else {
- // we are too high, slide all views down to align with bottom
- child = getChildAt(childCount - 1);
- delta = child.getBottom() - (getHeight() - mListPadding.bottom);
-
- if (mFirstPosition + childCount < mItemCount) {
- // It's OK to have some space below the last item if it is
- // part of the vertical spacing
- delta += mDividerHeight;
- }
-
- if (delta > 0) {
- delta = 0;
- }
- }
-
- if (delta != 0) {
- offsetChildrenTopAndBottom(-delta);
- }
- }
- }
-
- /**
- * Add a fixed view to appear at the top of the list. If addHeaderView is
- * called more than once, the views will appear in the order they were
- * added. Views added using this call can take focus if they want.
- * <p>
- * NOTE: Call this before calling setAdapter. This is so ListView can wrap
- * the supplied cursor with one that that will also account for header
- * views.
- *
- * @param v The view to add.
- * @param data Data to associate with this view
- * @param isSelectable whether the item is selectable
- */
- public void addHeaderView(View v, Object data, boolean isSelectable) {
-
- if (mAdapter != null) {
- throw new IllegalStateException(
- "Cannot add header view to list -- setAdapter has already been called.");
- }
-
- FixedViewInfo info = new FixedViewInfo();
- info.view = v;
- info.data = data;
- info.isSelectable = isSelectable;
- mHeaderViewInfos.add(info);
- }
-
- /**
- * Add a fixed view to appear at the top of the list. If addHeaderView is
- * called more than once, the views will appear in the order they were
- * added. Views added using this call can take focus if they want.
- * <p>
- * NOTE: Call this before calling setAdapter. This is so ListView can wrap
- * the supplied cursor with one that that will also account for header
- * views.
- *
- * @param v The view to add.
- */
- public void addHeaderView(View v) {
- addHeaderView(v, null, true);
- }
-
- @Override
- public int getHeaderViewsCount() {
- return mHeaderViewInfos.size();
- }
-
- /**
- * Removes a previously-added header view.
- *
- * @param v The view to remove
- * @return true if the view was removed, false if the view was not a header
- * view
- */
- public boolean removeHeaderView(View v) {
- if (mHeaderViewInfos.size() > 0) {
- boolean result = false;
- if (((HeaderViewListAdapter) mAdapter).removeHeader(v)) {
- mDataSetObserver.onChanged();
- result = true;
- }
- removeFixedViewInfo(v, mHeaderViewInfos);
- return result;
- }
- return false;
- }
-
- private void removeFixedViewInfo(View v, ArrayList<FixedViewInfo> where) {
- int len = where.size();
- for (int i = 0; i < len; ++i) {
- FixedViewInfo info = where.get(i);
- if (info.view == v) {
- where.remove(i);
- break;
- }
- }
- }
-
- /**
- * Add a fixed view to appear at the bottom of the list. If addFooterView is
- * called more than once, the views will appear in the order they were
- * added. Views added using this call can take focus if they want.
- * <p>
- * NOTE: Call this before calling setAdapter. This is so ListView can wrap
- * the supplied cursor with one that that will also account for header
- * views.
- *
- * @param v The view to add.
- * @param data Data to associate with this view
- * @param isSelectable true if the footer view can be selected
- */
- public void addFooterView(View v, Object data, boolean isSelectable) {
- FixedViewInfo info = new FixedViewInfo();
- info.view = v;
- info.data = data;
- info.isSelectable = isSelectable;
- mFooterViewInfos.add(info);
-
- // in the case of re-adding a footer view, or adding one later on,
- // we need to notify the observer
- if (mDataSetObserver != null) {
- mDataSetObserver.onChanged();
- }
- }
-
- /**
- * Add a fixed view to appear at the bottom of the list. If addFooterView is called more
- * than once, the views will appear in the order they were added. Views added using
- * this call can take focus if they want.
- * <p>NOTE: Call this before calling setAdapter. This is so ListView can wrap the supplied
- * cursor with one that that will also account for header views.
- *
- *
- * @param v The view to add.
- */
- public void addFooterView(View v) {
- addFooterView(v, null, true);
- }
-
- @Override
- public int getFooterViewsCount() {
- return mFooterViewInfos.size();
- }
-
- /**
- * Removes a previously-added footer view.
- *
- * @param v The view to remove
- * @return
- * true if the view was removed, false if the view was not a footer view
- */
- public boolean removeFooterView(View v) {
- if (mFooterViewInfos.size() > 0) {
- boolean result = false;
- if (((HeaderViewListAdapter) mAdapter).removeFooter(v)) {
- mDataSetObserver.onChanged();
- result = true;
- }
- removeFixedViewInfo(v, mFooterViewInfos);
- return result;
- }
- return false;
- }
-
- /**
- * Returns the adapter currently in use in this ListView. The returned adapter
- * might not be the same adapter passed to {@link #setAdapter(ListAdapter)} but
- * might be a {@link WrapperListAdapter}.
- *
- * @return The adapter currently used to display data in this ListView.
- *
- * @see #setAdapter(ListAdapter)
- */
- @Override
- public ListAdapter getAdapter() {
- return mAdapter;
- }
-
- /**
- * Sets the data behind this ListView.
- *
- * The adapter passed to this method may be wrapped by a {@link WrapperListAdapter},
- * depending on the ListView features currently in use. For instance, adding
- * headers and/or footers will cause the adapter to be wrapped.
- *
- * @param adapter The ListAdapter which is responsible for maintaining the
- * data backing this list and for producing a view to represent an
- * item in that data set.
- *
- * @see #getAdapter()
- */
- @Override
- public void setAdapter(ListAdapter adapter) {
- if (null != mAdapter) {
- mAdapter.unregisterDataSetObserver(mDataSetObserver);
- }
-
- resetList();
- mRecycler.clear();
-
- if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
- mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
- } else {
- mAdapter = adapter;
- }
-
- mOldSelectedPosition = INVALID_POSITION;
- mOldSelectedRowId = INVALID_ROW_ID;
- if (mAdapter != null) {
- mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
- mOldItemCount = mItemCount;
- mItemCount = mAdapter.getCount();
- checkFocus();
-
- mDataSetObserver = new AdapterDataSetObserver();
- mAdapter.registerDataSetObserver(mDataSetObserver);
-
- mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());
-
- int position;
- if (mStackFromBottom) {
- position = lookForSelectablePosition(mItemCount - 1, false);
- } else {
- position = lookForSelectablePosition(0, true);
- }
- setSelectedPositionInt(position);
- setNextSelectedPositionInt(position);
-
- if (mItemCount == 0) {
- // Nothing selected
- checkSelectionChanged();
- }
-
- } else {
- mAreAllItemsSelectable = true;
- checkFocus();
- // Nothing selected
- checkSelectionChanged();
- }
-
- if (mCheckStates != null) {
- mCheckStates.clear();
- }
-
- requestLayout();
- }
-
-
- /**
- * The list is empty. Clear everything out.
- */
- @Override
- void resetList() {
- super.resetList();
- mLayoutMode = LAYOUT_NORMAL;
- }
-
- /**
- * @return Whether the list needs to show the top fading edge
- */
- private boolean showingTopFadingEdge() {
- final int listTop = mScrollY + mListPadding.top;
- return (mFirstPosition > 0) || (getChildAt(0).getTop() > listTop);
- }
-
- /**
- * @return Whether the list needs to show the bottom fading edge
- */
- private boolean showingBottomFadingEdge() {
- final int childCount = getChildCount();
- final int bottomOfBottomChild = getChildAt(childCount - 1).getBottom();
- final int lastVisiblePosition = mFirstPosition + childCount - 1;
-
- final int listBottom = mScrollY + getHeight() - mListPadding.bottom;
-
- return (lastVisiblePosition < mItemCount - 1)
- || (bottomOfBottomChild < listBottom);
- }
-
-
- @Override
- public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) {
-
- int rectTopWithinChild = rect.top;
-
- // offset so rect is in coordinates of the this view
- rect.offset(child.getLeft(), child.getTop());
- rect.offset(-child.getScrollX(), -child.getScrollY());
-
- final int height = getHeight();
- int listUnfadedTop = getScrollY();
- int listUnfadedBottom = listUnfadedTop + height;
- final int fadingEdge = getVerticalFadingEdgeLength();
-
- if (showingTopFadingEdge()) {
- // leave room for top fading edge as long as rect isn't at very top
- if ((mSelectedPosition > 0) || (rectTopWithinChild > fadingEdge)) {
- listUnfadedTop += fadingEdge;
- }
- }
-
- int childCount = getChildCount();
- int bottomOfBottomChild = getChildAt(childCount - 1).getBottom();
-
- if (showingBottomFadingEdge()) {
- // leave room for bottom fading edge as long as rect isn't at very bottom
- if ((mSelectedPosition < mItemCount - 1)
- || (rect.bottom < (bottomOfBottomChild - fadingEdge))) {
- listUnfadedBottom -= fadingEdge;
- }
- }
-
- int scrollYDelta = 0;
-
- if (rect.bottom > listUnfadedBottom && rect.top > listUnfadedTop) {
- // need to MOVE DOWN to get it in view: move down just enough so
- // that the entire rectangle is in view (or at least the first
- // screen size chunk).
-
- if (rect.height() > height) {
- // just enough to get screen size chunk on
- scrollYDelta += (rect.top - listUnfadedTop);
- } else {
- // get entire rect at bottom of screen
- scrollYDelta += (rect.bottom - listUnfadedBottom);
- }
-
- // make sure we aren't scrolling beyond the end of our children
- int distanceToBottom = bottomOfBottomChild - listUnfadedBottom;
- scrollYDelta = Math.min(scrollYDelta, distanceToBottom);
- } else if (rect.top < listUnfadedTop && rect.bottom < listUnfadedBottom) {
- // need to MOVE UP to get it in view: move up just enough so that
- // entire rectangle is in view (or at least the first screen
- // size chunk of it).
-
- if (rect.height() > height) {
- // screen size chunk
- scrollYDelta -= (listUnfadedBottom - rect.bottom);
- } else {
- // entire rect at top
- scrollYDelta -= (listUnfadedTop - rect.top);
- }
-
- // make sure we aren't scrolling any further than the top our children
- int top = getChildAt(0).getTop();
- int deltaToTop = top - listUnfadedTop;
- scrollYDelta = Math.max(scrollYDelta, deltaToTop);
- }
-
- final boolean scroll = scrollYDelta != 0;
- if (scroll) {
- scrollListItemsBy(-scrollYDelta);
- positionSelector(child);
- mSelectedTop = child.getTop();
- invalidate();
- }
- return scroll;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- void fillGap(boolean down) {
- final int count = getChildCount();
- if (down) {
- final int startOffset = count > 0 ? getChildAt(count - 1).getBottom() + mDividerHeight :
- getListPaddingTop();
- fillDown(mFirstPosition + count, startOffset);
- correctTooHigh(getChildCount());
- } else {
- final int startOffset = count > 0 ? getChildAt(0).getTop() - mDividerHeight :
- getHeight() - getListPaddingBottom();
- fillUp(mFirstPosition - 1, startOffset);
- correctTooLow(getChildCount());
- }
- }
-
- /**
- * Fills the list from pos down to the end of the list view.
- *
- * @param pos The first position to put in the list
- *
- * @param nextTop The location where the top of the item associated with pos
- * should be drawn
- *
- * @return The view that is currently selected, if it happens to be in the
- * range that we draw.
- */
- private View fillDown(int pos, int nextTop) {
- View selectedView = null;
-
- int end = (mBottom - mTop) - mListPadding.bottom;
-
- while (nextTop < end && pos < mItemCount) {
- // is this the selected item?
- boolean selected = pos == mSelectedPosition;
- View child = makeAndAddView(pos, nextTop, true, mListPadding.left, selected);
-
- nextTop = child.getBottom() + mDividerHeight;
- if (selected) {
- selectedView = child;
- }
- pos++;
- }
-
- return selectedView;
- }
-
- /**
- * Fills the list from pos up to the top of the list view.
- *
- * @param pos The first position to put in the list
- *
- * @param nextBottom The location where the bottom of the item associated
- * with pos should be drawn
- *
- * @return The view that is currently selected
- */
- private View fillUp(int pos, int nextBottom) {
- View selectedView = null;
-
- int end = mListPadding.top;
-
- while (nextBottom > end && pos >= 0) {
- // is this the selected item?
- boolean selected = pos == mSelectedPosition;
- View child = makeAndAddView(pos, nextBottom, false, mListPadding.left, selected);
- nextBottom = child.getTop() - mDividerHeight;
- if (selected) {
- selectedView = child;
- }
- pos--;
- }
-
- mFirstPosition = pos + 1;
-
- return selectedView;
- }
-
- /**
- * Fills the list from top to bottom, starting with mFirstPosition
- *
- * @param nextTop The location where the top of the first item should be
- * drawn
- *
- * @return The view that is currently selected
- */
- private View fillFromTop(int nextTop) {
- mFirstPosition = Math.min(mFirstPosition, mSelectedPosition);
- mFirstPosition = Math.min(mFirstPosition, mItemCount - 1);
- if (mFirstPosition < 0) {
- mFirstPosition = 0;
- }
- return fillDown(mFirstPosition, nextTop);
- }
-
-
- /**
- * Put mSelectedPosition in the middle of the screen and then build up and
- * down from there. This method forces mSelectedPosition to the center.
- *
- * @param childrenTop Top of the area in which children can be drawn, as
- * measured in pixels
- * @param childrenBottom Bottom of the area in which children can be drawn,
- * as measured in pixels
- * @return Currently selected view
- */
- private View fillFromMiddle(int childrenTop, int childrenBottom) {
- int height = childrenBottom - childrenTop;
-
- int position = reconcileSelectedPosition();
-
- View sel = makeAndAddView(position, childrenTop, true,
- mListPadding.left, true);
- mFirstPosition = position;
-
- int selHeight = sel.getMeasuredHeight();
- if (selHeight <= height) {
- sel.offsetTopAndBottom((height - selHeight) / 2);
- }
-
- fillAboveAndBelow(sel, position);
-
- if (!mStackFromBottom) {
- correctTooHigh(getChildCount());
- } else {
- correctTooLow(getChildCount());
- }
-
- return sel;
- }
-
- /**
- * Once the selected view as been placed, fill up the visible area above and
- * below it.
- *
- * @param sel The selected view
- * @param position The position corresponding to sel
- */
- private void fillAboveAndBelow(View sel, int position) {
- final int dividerHeight = mDividerHeight;
- if (!mStackFromBottom) {
- fillUp(position - 1, sel.getTop() - dividerHeight);
- adjustViewsUpOrDown();
- fillDown(position + 1, sel.getBottom() + dividerHeight);
- } else {
- fillDown(position + 1, sel.getBottom() + dividerHeight);
- adjustViewsUpOrDown();
- fillUp(position - 1, sel.getTop() - dividerHeight);
- }
- }
-
-
- /**
- * Fills the grid based on positioning the new selection at a specific
- * location. The selection may be moved so that it does not intersect the
- * faded edges. The grid is then filled upwards and downwards from there.
- *
- * @param selectedTop Where the selected item should be
- * @param childrenTop Where to start drawing children
- * @param childrenBottom Last pixel where children can be drawn
- * @return The view that currently has selection
- */
- private View fillFromSelection(int selectedTop, int childrenTop, int childrenBottom) {
- int fadingEdgeLength = getVerticalFadingEdgeLength();
- final int selectedPosition = mSelectedPosition;
-
- View sel;
-
- final int topSelectionPixel = getTopSelectionPixel(childrenTop, fadingEdgeLength,
- selectedPosition);
- final int bottomSelectionPixel = getBottomSelectionPixel(childrenBottom, fadingEdgeLength,
- selectedPosition);
-
- sel = makeAndAddView(selectedPosition, selectedTop, true, mListPadding.left, true);
-
-
- // Some of the newly selected item extends below the bottom of the list
- if (sel.getBottom() > bottomSelectionPixel) {
- // Find space available above the selection into which we can scroll
- // upwards
- final int spaceAbove = sel.getTop() - topSelectionPixel;
-
- // Find space required to bring the bottom of the selected item
- // fully into view
- final int spaceBelow = sel.getBottom() - bottomSelectionPixel;
- final int offset = Math.min(spaceAbove, spaceBelow);
-
- // Now offset the selected item to get it into view
- sel.offsetTopAndBottom(-offset);
- } else if (sel.getTop() < topSelectionPixel) {
- // Find space required to bring the top of the selected item fully
- // into view
- final int spaceAbove = topSelectionPixel - sel.getTop();
-
- // Find space available below the selection into which we can scroll
- // downwards
- final int spaceBelow = bottomSelectionPixel - sel.getBottom();
- final int offset = Math.min(spaceAbove, spaceBelow);
-
- // Offset the selected item to get it into view
- sel.offsetTopAndBottom(offset);
- }
-
- // Fill in views above and below
- fillAboveAndBelow(sel, selectedPosition);
-
- if (!mStackFromBottom) {
- correctTooHigh(getChildCount());
- } else {
- correctTooLow(getChildCount());
- }
-
- return sel;
- }
-
- /**
- * Calculate the bottom-most pixel we can draw the selection into
- *
- * @param childrenBottom Bottom pixel were children can be drawn
- * @param fadingEdgeLength Length of the fading edge in pixels, if present
- * @param selectedPosition The position that will be selected
- * @return The bottom-most pixel we can draw the selection into
- */
- private int getBottomSelectionPixel(int childrenBottom, int fadingEdgeLength,
- int selectedPosition) {
- int bottomSelectionPixel = childrenBottom;
- if (selectedPosition != mItemCount - 1) {
- bottomSelectionPixel -= fadingEdgeLength;
- }
- return bottomSelectionPixel;
- }
-
- /**
- * Calculate the top-most pixel we can draw the selection into
- *
- * @param childrenTop Top pixel were children can be drawn
- * @param fadingEdgeLength Length of the fading edge in pixels, if present
- * @param selectedPosition The position that will be selected
- * @return The top-most pixel we can draw the selection into
- */
- private int getTopSelectionPixel(int childrenTop, int fadingEdgeLength, int selectedPosition) {
- // first pixel we can draw the selection into
- int topSelectionPixel = childrenTop;
- if (selectedPosition > 0) {
- topSelectionPixel += fadingEdgeLength;
- }
- return topSelectionPixel;
- }
-
-
- /**
- * Fills the list based on positioning the new selection relative to the old
- * selection. The new selection will be placed at, above, or below the
- * location of the new selection depending on how the selection is moving.
- * The selection will then be pinned to the visible part of the screen,
- * excluding the edges that are faded. The list is then filled upwards and
- * downwards from there.
- *
- * @param oldSel The old selected view. Useful for trying to put the new
- * selection in the same place
- * @param newSel The view that is to become selected. Useful for trying to
- * put the new selection in the same place
- * @param delta Which way we are moving
- * @param childrenTop Where to start drawing children
- * @param childrenBottom Last pixel where children can be drawn
- * @return The view that currently has selection
- */
- private View moveSelection(View oldSel, View newSel, int delta, int childrenTop,
- int childrenBottom) {
- int fadingEdgeLength = getVerticalFadingEdgeLength();
- final int selectedPosition = mSelectedPosition;
-
- View sel;
-
- final int topSelectionPixel = getTopSelectionPixel(childrenTop, fadingEdgeLength,
- selectedPosition);
- final int bottomSelectionPixel = getBottomSelectionPixel(childrenTop, fadingEdgeLength,
- selectedPosition);
-
- if (delta > 0) {
- /*
- * Case 1: Scrolling down.
- */
-
- /*
- * Before After
- * | | | |
- * +-------+ +-------+
- * | A | | A |
- * | 1 | => +-------+
- * +-------+ | B |
- * | B | | 2 |
- * +-------+ +-------+
- * | | | |
- *
- * Try to keep the top of the previously selected item where it was.
- * oldSel = A
- * sel = B
- */
-
- // Put oldSel (A) where it belongs
- oldSel = makeAndAddView(selectedPosition - 1, oldSel.getTop(), true,
- mListPadding.left, false);
-
- final int dividerHeight = mDividerHeight;
-
- // Now put the new selection (B) below that
- sel = makeAndAddView(selectedPosition, oldSel.getBottom() + dividerHeight, true,
- mListPadding.left, true);
-
- // Some of the newly selected item extends below the bottom of the list
- if (sel.getBottom() > bottomSelectionPixel) {
-
- // Find space available above the selection into which we can scroll upwards
- int spaceAbove = sel.getTop() - topSelectionPixel;
-
- // Find space required to bring the bottom of the selected item fully into view
- int spaceBelow = sel.getBottom() - bottomSelectionPixel;
-
- // Don't scroll more than half the height of the list
- int halfVerticalSpace = (childrenBottom - childrenTop) / 2;
- int offset = Math.min(spaceAbove, spaceBelow);
- offset = Math.min(offset, halfVerticalSpace);
-
- // We placed oldSel, so offset that item
- oldSel.offsetTopAndBottom(-offset);
- // Now offset the selected item to get it into view
- sel.offsetTopAndBottom(-offset);
- }
-
- // Fill in views above and below
- if (!mStackFromBottom) {
- fillUp(mSelectedPosition - 2, sel.getTop() - dividerHeight);
- adjustViewsUpOrDown();
- fillDown(mSelectedPosition + 1, sel.getBottom() + dividerHeight);
- } else {
- fillDown(mSelectedPosition + 1, sel.getBottom() + dividerHeight);
- adjustViewsUpOrDown();
- fillUp(mSelectedPosition - 2, sel.getTop() - dividerHeight);
- }
- } else if (delta < 0) {
- /*
- * Case 2: Scrolling up.
- */
-
- /*
- * Before After
- * | | | |
- * +-------+ +-------+
- * | A | | A |
- * +-------+ => | 1 |
- * | B | +-------+
- * | 2 | | B |
- * +-------+ +-------+
- * | | | |
- *
- * Try to keep the top of the item about to become selected where it was.
- * newSel = A
- * olSel = B
- */
-
- if (newSel != null) {
- // Try to position the top of newSel (A) where it was before it was selected
- sel = makeAndAddView(selectedPosition, newSel.getTop(), true, mListPadding.left,
- true);
- } else {
- // If (A) was not on screen and so did not have a view, position
- // it above the oldSel (B)
- sel = makeAndAddView(selectedPosition, oldSel.getTop(), false, mListPadding.left,
- true);
- }
-
- // Some of the newly selected item extends above the top of the list
- if (sel.getTop() < topSelectionPixel) {
- // Find space required to bring the top of the selected item fully into view
- int spaceAbove = topSelectionPixel - sel.getTop();
-
- // Find space available below the selection into which we can scroll downwards
- int spaceBelow = bottomSelectionPixel - sel.getBottom();
-
- // Don't scroll more than half the height of the list
- int halfVerticalSpace = (childrenBottom - childrenTop) / 2;
- int offset = Math.min(spaceAbove, spaceBelow);
- offset = Math.min(offset, halfVerticalSpace);
-
- // Offset the selected item to get it into view
- sel.offsetTopAndBottom(offset);
- }
-
- // Fill in views above and below
- fillAboveAndBelow(sel, selectedPosition);
- } else {
-
- int oldTop = oldSel.getTop();
-
- /*
- * Case 3: Staying still
- */
- sel = makeAndAddView(selectedPosition, oldTop, true, mListPadding.left, true);
-
- // We're staying still...
- if (oldTop < childrenTop) {
- // ... but the top of the old selection was off screen.
- // (This can happen if the data changes size out from under us)
- int newBottom = sel.getBottom();
- if (newBottom < childrenTop + 20) {
- // Not enough visible -- bring it onscreen
- sel.offsetTopAndBottom(childrenTop - sel.getTop());
- }
- }
-
- // Fill in views above and below
- fillAboveAndBelow(sel, selectedPosition);
- }
-
- return sel;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // Sets up mListPadding
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
- int childWidth = 0;
- int childHeight = 0;
-
- mItemCount = mAdapter == null ? 0 : mAdapter.getCount();
- if (mItemCount > 0 && (widthMode == MeasureSpec.UNSPECIFIED ||
- heightMode == MeasureSpec.UNSPECIFIED)) {
- final View child = obtainView(0);
- final int childViewType = mAdapter.getItemViewType(0);
-
- AbsListView.LayoutParams lp = (AbsListView.LayoutParams) child.getLayoutParams();
- if (lp == null) {
- lp = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT, 0);
- child.setLayoutParams(lp);
- }
- lp.viewType = childViewType;
-
- final int childWidthSpec = ViewGroup.getChildMeasureSpec(widthMeasureSpec,
- mListPadding.left + mListPadding.right, lp.width);
-
- int lpHeight = lp.height;
-
- int childHeightSpec;
- if (lpHeight > 0) {
- childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
- } else {
- childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- }
-
- child.measure(childWidthSpec, childHeightSpec);
-
- childWidth = child.getMeasuredWidth();
- childHeight = child.getMeasuredHeight();
-
- if (mRecycler.shouldRecycleViewType(childViewType)) {
- mRecycler.addScrapView(child);
- }
- }
-
- if (widthMode == MeasureSpec.UNSPECIFIED) {
- widthSize = mListPadding.left + mListPadding.right + childWidth +
- getVerticalScrollbarWidth();
- }
-
- if (heightMode == MeasureSpec.UNSPECIFIED) {
- heightSize = mListPadding.top + mListPadding.bottom + childHeight +
- getVerticalFadingEdgeLength() * 2;
- }
-
- if (heightMode == MeasureSpec.AT_MOST) {
- // TODO: after first layout we should maybe start at the first visible position, not 0
- heightSize = measureHeightOfChildren(
- MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY),
- 0, NO_POSITION, heightSize, -1);
- }
-
- setMeasuredDimension(widthSize, heightSize);
- mWidthMeasureSpec = widthMeasureSpec;
- }
-
- /**
- * Measures the height of the given range of children (inclusive) and
- * returns the height with this ListView's padding and divider heights
- * included. If maxHeight is provided, the measuring will stop when the
- * current height reaches maxHeight.
- *
- * @param widthMeasureSpec The width measure spec to be given to a child's
- * {@link View#measure(int, int)}.
- * @param startPosition The position of the first child to be shown.
- * @param endPosition The (inclusive) position of the last child to be
- * shown. Specify {@link #NO_POSITION} if the last child should be
- * the last available child from the adapter.
- * @param maxHeight The maximum height that will be returned (if all the
- * children don't fit in this value, this value will be
- * returned).
- * @param disallowPartialChildPosition In general, whether the returned
- * height should only contain entire children. This is more
- * powerful--it is the first inclusive position at which partial
- * children will not be allowed. Example: it looks nice to have
- * at least 3 completely visible children, and in portrait this
- * will most likely fit; but in landscape there could be times
- * when even 2 children can not be completely shown, so a value
- * of 2 (remember, inclusive) would be good (assuming
- * startPosition is 0).
- * @return The height of this ListView with the given children.
- */
- final int measureHeightOfChildren(final int widthMeasureSpec, final int startPosition,
- int endPosition, final int maxHeight, int disallowPartialChildPosition) {
-
- final ListAdapter adapter = mAdapter;
- if (adapter == null) {
- return mListPadding.top + mListPadding.bottom;
- }
-
- // Include the padding of the list
- int returnedHeight = mListPadding.top + mListPadding.bottom;
- final int dividerHeight = ((mDividerHeight > 0) && mDivider != null) ? mDividerHeight : 0;
- // The previous height value that was less than maxHeight and contained
- // no partial children
- int prevHeightWithoutPartialChild = 0;
- int i;
- View child;
-
- // mItemCount - 1 since endPosition parameter is inclusive
- endPosition = (endPosition == NO_POSITION) ? adapter.getCount() - 1 : endPosition;
- final AbsListView.RecycleBin recycleBin = mRecycler;
- for (i = startPosition; i <= endPosition; ++i) {
- child = obtainView(i);
- final int childViewType = adapter.getItemViewType(i);
-
- AbsListView.LayoutParams lp = (AbsListView.LayoutParams) child.getLayoutParams();
- if (lp == null) {
- lp = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT, 0);
- child.setLayoutParams(lp);
- }
- lp.viewType = childViewType;
-
- if (i > 0) {
- // Count the divider for all but one child
- returnedHeight += dividerHeight;
- }
-
- child.measure(widthMeasureSpec, lp.height >= 0
- ? MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY)
- : MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
-
- // Recycle the view before we possibly return from the method
- if (recycleBin.shouldRecycleViewType(childViewType)) {
- recycleBin.addScrapView(child);
- }
-
- returnedHeight += child.getMeasuredHeight();
-
- if (returnedHeight >= maxHeight) {
- // We went over, figure out which height to return. If returnedHeight > maxHeight,
- // then the i'th position did not fit completely.
- return (disallowPartialChildPosition >= 0) // Disallowing is enabled (> -1)
- && (i > disallowPartialChildPosition) // We've past the min pos
- && (prevHeightWithoutPartialChild > 0) // We have a prev height
- && (returnedHeight != maxHeight) // i'th child did not fit completely
- ? prevHeightWithoutPartialChild
- : maxHeight;
- }
-
- if ((disallowPartialChildPosition >= 0) && (i >= disallowPartialChildPosition)) {
- prevHeightWithoutPartialChild = returnedHeight;
- }
- }
-
- // At this point, we went through the range of children, and they each
- // completely fit, so return the returnedHeight
- return returnedHeight;
- }
-
- @Override
- int findMotionRow(int y) {
- int childCount = getChildCount();
- if (childCount > 0) {
- for (int i = 0; i < childCount; i++) {
- View v = getChildAt(i);
- if (y <= v.getBottom()) {
- return mFirstPosition + i;
- }
- }
- return mFirstPosition + childCount - 1;
- }
- return INVALID_POSITION;
- }
-
- /**
- * Put a specific item at a specific location on the screen and then build
- * up and down from there.
- *
- * @param position The reference view to use as the starting point
- * @param top Pixel offset from the top of this view to the top of the
- * reference view.
- *
- * @return The selected view, or null if the selected view is outside the
- * visible area.
- */
- private View fillSpecific(int position, int top) {
- boolean tempIsSelected = position == mSelectedPosition;
- View temp = makeAndAddView(position, top, true, mListPadding.left, tempIsSelected);
- // Possibly changed again in fillUp if we add rows above this one.
- mFirstPosition = position;
-
- View above;
- View below;
-
- final int dividerHeight = mDividerHeight;
- if (!mStackFromBottom) {
- above = fillUp(position - 1, temp.getTop() - dividerHeight);
- // This will correct for the top of the first view not touching the top of the list
- adjustViewsUpOrDown();
- below = fillDown(position + 1, temp.getBottom() + dividerHeight);
- int childCount = getChildCount();
- if (childCount > 0) {
- correctTooHigh(childCount);
- }
- } else {
- below = fillDown(position + 1, temp.getBottom() + dividerHeight);
- // This will correct for the bottom of the last view not touching the bottom of the list
- adjustViewsUpOrDown();
- above = fillUp(position - 1, temp.getTop() - dividerHeight);
- int childCount = getChildCount();
- if (childCount > 0) {
- correctTooLow(childCount);
- }
- }
-
- if (tempIsSelected) {
- return temp;
- } else if (above != null) {
- return above;
- } else {
- return below;
- }
- }
-
- /**
- * Check if we have dragged the bottom of the list too high (we have pushed the
- * top element off the top of the screen when we did not need to). Correct by sliding
- * everything back down.
- *
- * @param childCount Number of children
- */
- private void correctTooHigh(int childCount) {
- // First see if the last item is visible. If it is not, it is OK for the
- // top of the list to be pushed up.
- int lastPosition = mFirstPosition + childCount - 1;
- if (lastPosition == mItemCount - 1 && childCount > 0) {
-
- // Get the last child ...
- final View lastChild = getChildAt(childCount - 1);
-
- // ... and its bottom edge
- final int lastBottom = lastChild.getBottom();
-
- // This is bottom of our drawable area
- final int end = (mBottom - mTop) - mListPadding.bottom;
-
- // This is how far the bottom edge of the last view is from the bottom of the
- // drawable area
- int bottomOffset = end - lastBottom;
- View firstChild = getChildAt(0);
- final int firstTop = firstChild.getTop();
-
- // Make sure we are 1) Too high, and 2) Either there are more rows above the
- // first row or the first row is scrolled off the top of the drawable area
- if (bottomOffset > 0 && (mFirstPosition > 0 || firstTop < mListPadding.top)) {
- if (mFirstPosition == 0) {
- // Don't pull the top too far down
- bottomOffset = Math.min(bottomOffset, mListPadding.top - firstTop);
- }
- // Move everything down
- offsetChildrenTopAndBottom(bottomOffset);
- if (mFirstPosition > 0) {
- // Fill the gap that was opened above mFirstPosition with more rows, if
- // possible
- fillUp(mFirstPosition - 1, firstChild.getTop() - mDividerHeight);
- // Close up the remaining gap
- adjustViewsUpOrDown();
- }
-
- }
- }
- }
-
- /**
- * Check if we have dragged the bottom of the list too low (we have pushed the
- * bottom element off the bottom of the screen when we did not need to). Correct by sliding
- * everything back up.
- *
- * @param childCount Number of children
- */
- private void correctTooLow(int childCount) {
- // First see if the first item is visible. If it is not, it is OK for the
- // bottom of the list to be pushed down.
- if (mFirstPosition == 0 && childCount > 0) {
-
- // Get the first child ...
- final View firstChild = getChildAt(0);
-
- // ... and its top edge
- final int firstTop = firstChild.getTop();
-
- // This is top of our drawable area
- final int start = mListPadding.top;
-
- // This is bottom of our drawable area
- final int end = (mBottom - mTop) - mListPadding.bottom;
-
- // This is how far the top edge of the first view is from the top of the
- // drawable area
- int topOffset = firstTop - start;
- View lastChild = getChildAt(childCount - 1);
- final int lastBottom = lastChild.getBottom();
- int lastPosition = mFirstPosition + childCount - 1;
-
- // Make sure we are 1) Too low, and 2) Either there are more rows below the
- // last row or the last row is scrolled off the bottom of the drawable area
- if (topOffset > 0 && (lastPosition < mItemCount - 1 || lastBottom > end)) {
- if (lastPosition == mItemCount - 1 ) {
- // Don't pull the bottom too far up
- topOffset = Math.min(topOffset, lastBottom - end);
- }
- // Move everything up
- offsetChildrenTopAndBottom(-topOffset);
- if (lastPosition < mItemCount - 1) {
- // Fill the gap that was opened below the last position with more rows, if
- // possible
- fillDown(lastPosition + 1, lastChild.getBottom() + mDividerHeight);
- // Close up the remaining gap
- adjustViewsUpOrDown();
- }
- }
- }
- }
-
- @Override
- protected void layoutChildren() {
- final boolean blockLayoutRequests = mBlockLayoutRequests;
- if (!blockLayoutRequests) {
- mBlockLayoutRequests = true;
- }
-
- try {
- super.layoutChildren();
-
- invalidate();
-
- if (mAdapter == null) {
- resetList();
- invokeOnItemScrollListener();
- return;
- }
-
- int childrenTop = mListPadding.top;
- int childrenBottom = mBottom - mTop - mListPadding.bottom;
-
- int childCount = getChildCount();
- int index;
- int delta = 0;
-
- View sel;
- View oldSel = null;
- View oldFirst = null;
- View newSel = null;
-
- View focusLayoutRestoreView = null;
-
- // Remember stuff we will need down below
- switch (mLayoutMode) {
- case LAYOUT_SET_SELECTION:
- index = mNextSelectedPosition - mFirstPosition;
- if (index >= 0 && index < childCount) {
- newSel = getChildAt(index);
- }
- break;
- case LAYOUT_FORCE_TOP:
- case LAYOUT_FORCE_BOTTOM:
- case LAYOUT_SPECIFIC:
- case LAYOUT_SYNC:
- break;
- case LAYOUT_MOVE_SELECTION:
- default:
- // Remember the previously selected view
- index = mSelectedPosition - mFirstPosition;
- if (index >= 0 && index < childCount) {
- oldSel = getChildAt(index);
- }
-
- // Remember the previous first child
- oldFirst = getChildAt(0);
-
- if (mNextSelectedPosition >= 0) {
- delta = mNextSelectedPosition - mSelectedPosition;
- }
-
- // Caution: newSel might be null
- newSel = getChildAt(index + delta);
- }
-
-
- boolean dataChanged = mDataChanged;
- if (dataChanged) {
- handleDataChanged();
- }
-
- // Handle the empty set by removing all views that are visible
- // and calling it a day
- if (mItemCount == 0) {
- resetList();
- invokeOnItemScrollListener();
- return;
- }
-
- setSelectedPositionInt(mNextSelectedPosition);
-
- // Pull all children into the RecycleBin.
- // These views will be reused if possible
- final int firstPosition = mFirstPosition;
- final RecycleBin recycleBin = mRecycler;
-
- // reset the focus restoration
- View focusLayoutRestoreDirectChild = null;
-
-
- // Don't put header or footer views into the Recycler. Those are
- // already cached in mHeaderViews;
- if (dataChanged) {
- for (int i = 0; i < childCount; i++) {
- recycleBin.addScrapView(getChildAt(i));
- if (ViewDebug.TRACE_RECYCLER) {
- ViewDebug.trace(getChildAt(i),
- ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP, index, i);
- }
- }
- } else {
- recycleBin.fillActiveViews(childCount, firstPosition);
- }
-
- // take focus back to us temporarily to avoid the eventual
- // call to clear focus when removing the focused child below
- // from messing things up when ViewRoot assigns focus back
- // to someone else
- final View focusedChild = getFocusedChild();
- if (focusedChild != null) {
- // TODO: in some cases focusedChild.getParent() == null
-
- // we can remember the focused view to restore after relayout if the
- // data hasn't changed, or if the focused position is a header or footer
- if (!dataChanged || isDirectChildHeaderOrFooter(focusedChild)) {
- focusLayoutRestoreDirectChild = getFocusedChild();
- if (focusLayoutRestoreDirectChild != null) {
-
- // remember its state
- focusLayoutRestoreDirectChild.saveHierarchyState(mfocusRestoreChildState);
-
- // remember the specific view that had focus
- focusLayoutRestoreView = findFocus();
- }
- }
- requestFocus();
- }
-
- // Clear out old views
- //removeAllViewsInLayout();
- detachAllViewsFromParent();
-
- switch (mLayoutMode) {
- case LAYOUT_SET_SELECTION:
- if (newSel != null) {
- sel = fillFromSelection(newSel.getTop(), childrenTop, childrenBottom);
- } else {
- sel = fillFromMiddle(childrenTop, childrenBottom);
- }
- break;
- case LAYOUT_SYNC:
- sel = fillSpecific(mSyncPosition, mSpecificTop);
- break;
- case LAYOUT_FORCE_BOTTOM:
- sel = fillUp(mItemCount - 1, childrenBottom);
- adjustViewsUpOrDown();
- break;
- case LAYOUT_FORCE_TOP:
- mFirstPosition = 0;
- sel = fillFromTop(childrenTop);
- adjustViewsUpOrDown();
- break;
- case LAYOUT_SPECIFIC:
- sel = fillSpecific(reconcileSelectedPosition(), mSpecificTop);
- break;
- case LAYOUT_MOVE_SELECTION:
- sel = moveSelection(oldSel, newSel, delta, childrenTop, childrenBottom);
- break;
- default:
- if (childCount == 0) {
- if (!mStackFromBottom) {
- final int position = lookForSelectablePosition(0, true);
- setSelectedPositionInt(position);
- sel = fillFromTop(childrenTop);
- } else {
- final int position = lookForSelectablePosition(mItemCount - 1, false);
- setSelectedPositionInt(position);
- sel = fillUp(mItemCount - 1, childrenBottom);
- }
- } else {
- if (mSelectedPosition >= 0 && mSelectedPosition < mItemCount) {
- sel = fillSpecific(mSelectedPosition,
- oldSel == null ? childrenTop : oldSel.getTop());
- } else if (mFirstPosition < mItemCount) {
- sel = fillSpecific(mFirstPosition,
- oldFirst == null ? childrenTop : oldFirst.getTop());
- } else {
- sel = fillSpecific(0, childrenTop);
- }
- }
- break;
- }
-
- // Flush any cached views that did not get reused above
- recycleBin.scrapActiveViews();
-
- if (sel != null) {
- // the current selected item should get focus if items
- // are focusable
- if (mItemsCanFocus && hasFocus() && !sel.hasFocus()) {
- final boolean focusWasTaken = (sel == focusLayoutRestoreDirectChild &&
- focusLayoutRestoreView.requestFocus()) || sel.requestFocus();
- if (!focusWasTaken) {
- // selected item didn't take focus, fine, but still want
- // to make sure something else outside of the selected view
- // has focus
- final View focused = getFocusedChild();
- if (focused != null) {
- focused.clearFocus();
- }
- positionSelector(sel);
- } else {
- sel.setSelected(false);
- mSelectorRect.setEmpty();
- }
-
- if (sel == focusLayoutRestoreDirectChild) {
- focusLayoutRestoreDirectChild.restoreHierarchyState(mfocusRestoreChildState);
- }
- } else {
- positionSelector(sel);
- }
- mSelectedTop = sel.getTop();
- } else {
- mSelectedTop = 0;
- mSelectorRect.setEmpty();
-
- // even if there is not selected position, we may need to restore
- // focus (i.e. something focusable in touch mode)
- if (hasFocus() && focusLayoutRestoreView != null) {
- focusLayoutRestoreView.requestFocus();
- focusLayoutRestoreDirectChild.restoreHierarchyState(mfocusRestoreChildState);
- }
- }
-
- mLayoutMode = LAYOUT_NORMAL;
- mDataChanged = false;
- mNeedSync = false;
- setNextSelectedPositionInt(mSelectedPosition);
-
- updateScrollIndicators();
-
- if (mItemCount > 0) {
- checkSelectionChanged();
- }
-
- invokeOnItemScrollListener();
- } finally {
- if (!blockLayoutRequests) {
- mBlockLayoutRequests = false;
- }
- }
- }
-
- /**
- * @param child a direct child of this list.
- * @return Whether child is a header or footer view.
- */
- private boolean isDirectChildHeaderOrFooter(View child) {
-
- final ArrayList<FixedViewInfo> headers = mHeaderViewInfos;
- final int numHeaders = headers.size();
- for (int i = 0; i < numHeaders; i++) {
- if (child == headers.get(i).view) {
- return true;
- }
- }
- final ArrayList<FixedViewInfo> footers = mFooterViewInfos;
- final int numFooters = footers.size();
- for (int i = 0; i < numFooters; i++) {
- if (child == footers.get(i).view) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Obtain the view and add it to our list of children. The view can be made
- * fresh, converted from an unused view, or used as is if it was in the
- * recycle bin.
- *
- * @param position Logical position in the list
- * @param y Top or bottom edge of the view to add
- * @param flow If flow is true, align top edge to y. If false, align bottom
- * edge to y.
- * @param childrenLeft Left edge where children should be positioned
- * @param selected Is this position selected?
- * @return View that was added
- */
- private View makeAndAddView(int position, int y, boolean flow, int childrenLeft,
- boolean selected) {
- View child;
-
-
- if (!mDataChanged) {
- // Try to use an exsiting view for this position
- child = mRecycler.getActiveView(position);
- if (child != null) {
- if (ViewDebug.TRACE_RECYCLER) {
- ViewDebug.trace(child, ViewDebug.RecyclerTraceType.RECYCLE_FROM_ACTIVE_HEAP,
- position, getChildCount());
- }
-
- // Found it -- we're using an existing child
- // This just needs to be positioned
- setupChild(child, position, y, flow, childrenLeft, selected, true);
-
- return child;
- }
- }
-
- // Make a new view for this position, or convert an unused view if possible
- child = obtainView(position);
-
- // This needs to be positioned and measured
- setupChild(child, position, y, flow, childrenLeft, selected, false);
-
- return child;
- }
-
- /**
- * Add a view as a child and make sure it is measured (if necessary) and
- * positioned properly.
- *
- * @param child The view to add
- * @param position The position of this child
- * @param y The y position relative to which this view will be positioned
- * @param flowDown If true, align top edge to y. If false, align bottom
- * edge to y.
- * @param childrenLeft Left edge where children should be positioned
- * @param selected Is this position selected?
- * @param recycled Has this view been pulled from the recycle bin? If so it
- * does not need to be remeasured.
- */
- private void setupChild(View child, int position, int y, boolean flowDown, int childrenLeft,
- boolean selected, boolean recycled) {
- final boolean isSelected = selected && shouldShowSelector();
- final boolean updateChildSelected = isSelected != child.isSelected();
- final boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested();
-
- // Respect layout params that are already in the view. Otherwise make some up...
- // noinspection unchecked
- AbsListView.LayoutParams p = (AbsListView.LayoutParams)child.getLayoutParams();
- if (p == null) {
- p = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT, 0);
- }
- p.viewType = mAdapter.getItemViewType(position);
-
- if (recycled) {
- attachViewToParent(child, flowDown ? -1 : 0, p);
- } else {
- addViewInLayout(child, flowDown ? -1 : 0, p, true);
- }
-
- if (updateChildSelected) {
- child.setSelected(isSelected);
- }
-
- if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
- if (child instanceof Checkable) {
- ((Checkable)child).setChecked(mCheckStates.get(position));
- }
- }
-
- if (needToMeasure) {
- int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec,
- mListPadding.left + mListPadding.right, p.width);
- int lpHeight = p.height;
- int childHeightSpec;
- if (lpHeight > 0) {
- childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
- } else {
- childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- }
- child.measure(childWidthSpec, childHeightSpec);
- } else {
- cleanupLayoutState(child);
- }
-
- final int w = child.getMeasuredWidth();
- final int h = child.getMeasuredHeight();
- final int childTop = flowDown ? y : y - h;
-
- if (needToMeasure) {
- final int childRight = childrenLeft + w;
- final int childBottom = childTop + h;
- child.layout(childrenLeft, childTop, childRight, childBottom);
- } else {
- child.offsetLeftAndRight(childrenLeft - child.getLeft());
- child.offsetTopAndBottom(childTop - child.getTop());
- }
-
- if (mCachingStarted && !child.isDrawingCacheEnabled()) {
- child.setDrawingCacheEnabled(true);
- }
- }
-
- @Override
- protected boolean canAnimate() {
- return super.canAnimate() && mItemCount > 0;
- }
-
- /**
- * Sets the currently selected item. If in touch mode, the item will not be selected
- * but it will still be positioned appropriately. If the specified selection position
- * is less than 0, then the item at position 0 will be selected.
- *
- * @param position Index (starting at 0) of the data item to be selected.
- */
- @Override
- public void setSelection(int position) {
- setSelectionFromTop(position, 0);
- }
-
- /**
- * Sets the selected item and positions the selection y pixels from the top edge
- * of the ListView. (If in touch mode, the item will not be selected but it will
- * still be positioned appropriately.)
- *
- * @param position Index (starting at 0) of the data item to be selected.
- * @param y The distance from the top edge of the ListView (plus padding) that the
- * item will be positioned.
- */
- public void setSelectionFromTop(int position, int y) {
- if (mAdapter == null) {
- return;
- }
-
- if (!isInTouchMode()) {
- position = lookForSelectablePosition(position, true);
- if (position >= 0) {
- setNextSelectedPositionInt(position);
- }
- } else {
- mResurrectToPosition = position;
- }
-
- if (position >= 0) {
- mLayoutMode = LAYOUT_SPECIFIC;
- mSpecificTop = mListPadding.top + y;
-
- if (mNeedSync) {
- mSyncPosition = position;
- mSyncRowId = mAdapter.getItemId(position);
- }
-
- requestLayout();
- }
- }
-
- /**
- * Makes the item at the supplied position selected.
- *
- * @param position the position of the item to select
- */
- @Override
- void setSelectionInt(int position) {
- mBlockLayoutRequests = true;
- setNextSelectedPositionInt(position);
- layoutChildren();
- mBlockLayoutRequests = false;
- }
-
- /**
- * Find a position that can be selected (i.e., is not a separator).
- *
- * @param position The starting position to look at.
- * @param lookDown Whether to look down for other positions.
- * @return The next selectable position starting at position and then searching either up or
- * down. Returns {@link #INVALID_POSITION} if nothing can be found.
- */
- @Override
- int lookForSelectablePosition(int position, boolean lookDown) {
- final ListAdapter adapter = mAdapter;
- if (adapter == null || isInTouchMode()) {
- return INVALID_POSITION;
- }
-
- final int count = adapter.getCount();
- if (!mAreAllItemsSelectable) {
- if (lookDown) {
- position = Math.max(0, position);
- while (position < count && !adapter.isEnabled(position)) {
- position++;
- }
- } else {
- position = Math.min(position, count - 1);
- while (position >= 0 && !adapter.isEnabled(position)) {
- position--;
- }
- }
-
- if (position < 0 || position >= count) {
- return INVALID_POSITION;
- }
- return position;
- } else {
- if (position < 0 || position >= count) {
- return INVALID_POSITION;
- }
- return position;
- }
- }
-
- /**
- * setSelectionAfterHeaderView set the selection to be the first list item
- * after the header views.
- */
- public void setSelectionAfterHeaderView() {
- final int count = mHeaderViewInfos.size();
- if (count > 0) {
- mNextSelectedPosition = 0;
- return;
- }
-
- if (mAdapter != null) {
- setSelection(count);
- } else {
- mNextSelectedPosition = count;
- mLayoutMode = LAYOUT_SET_SELECTION;
- }
-
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- // Dispatch in the normal way
- boolean handled = super.dispatchKeyEvent(event);
- if (!handled) {
- // If we didn't handle it...
- View focused = getFocusedChild();
- if (focused != null && event.getAction() == KeyEvent.ACTION_DOWN) {
- // ... and our focused child didn't handle it
- // ... give it to ourselves so we can scroll if necessary
- handled = onKeyDown(event.getKeyCode(), event);
- }
- }
- return handled;
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- return commonKey(keyCode, 1, event);
- }
-
- @Override
- public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
- return commonKey(keyCode, repeatCount, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- return commonKey(keyCode, 1, event);
- }
-
- private boolean commonKey(int keyCode, int count, KeyEvent event) {
- if (mAdapter == null) {
- return false;
- }
-
- if (mDataChanged) {
- layoutChildren();
- }
-
- boolean handled = false;
- int action = event.getAction();
-
- if (action != KeyEvent.ACTION_UP) {
- if (mSelectedPosition < 0) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_SPACE:
- if (resurrectSelection()) {
- return true;
- }
- }
- }
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_UP:
- if (!event.isAltPressed()) {
- while (count > 0) {
- handled = arrowScroll(FOCUS_UP);
- count--;
- }
- } else {
- handled = fullScroll(FOCUS_UP);
- }
- break;
-
- case KeyEvent.KEYCODE_DPAD_DOWN:
- if (!event.isAltPressed()) {
- while (count > 0) {
- handled = arrowScroll(FOCUS_DOWN);
- count--;
- }
- } else {
- handled = fullScroll(FOCUS_DOWN);
- }
- break;
-
- case KeyEvent.KEYCODE_DPAD_LEFT:
- handled = handleHorizontalFocusWithinListItem(View.FOCUS_LEFT);
- break;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- handled = handleHorizontalFocusWithinListItem(View.FOCUS_RIGHT);
- break;
-
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_ENTER:
- if (mItemCount > 0 && event.getRepeatCount() == 0) {
- keyPressed();
- }
- handled = true;
- break;
-
- case KeyEvent.KEYCODE_SPACE:
- if (mPopup == null || !mPopup.isShowing()) {
- if (!event.isShiftPressed()) {
- pageScroll(FOCUS_DOWN);
- } else {
- pageScroll(FOCUS_UP);
- }
- handled = true;
- }
- break;
- }
- }
-
- if (!handled) {
- handled = sendToTextFilter(keyCode, count, event);
- }
-
- if (handled) {
- return true;
- } else {
- switch (action) {
- case KeyEvent.ACTION_DOWN:
- return super.onKeyDown(keyCode, event);
-
- case KeyEvent.ACTION_UP:
- return super.onKeyUp(keyCode, event);
-
- case KeyEvent.ACTION_MULTIPLE:
- return super.onKeyMultiple(keyCode, count, event);
-
- default: // shouldn't happen
- return false;
- }
- }
- }
-
- /**
- * Scrolls up or down by the number of items currently present on screen.
- *
- * @param direction either {@link View#FOCUS_UP} or {@link View#FOCUS_DOWN}
- * @return whether selection was moved
- */
- boolean pageScroll(int direction) {
- int nextPage = -1;
- boolean down = false;
-
- if (direction == FOCUS_UP) {
- nextPage = Math.max(0, mSelectedPosition - getChildCount() - 1);
- } else if (direction == FOCUS_DOWN) {
- nextPage = Math.min(mItemCount - 1, mSelectedPosition + getChildCount() - 1);
- down = true;
- }
-
- if (nextPage >= 0) {
- int position = lookForSelectablePosition(nextPage, down);
- if (position >= 0) {
- mLayoutMode = LAYOUT_SPECIFIC;
- mSpecificTop = mPaddingTop + getVerticalFadingEdgeLength();
-
- if (down && position > mItemCount - getChildCount()) {
- mLayoutMode = LAYOUT_FORCE_BOTTOM;
- }
-
- if (!down && position < getChildCount()) {
- mLayoutMode = LAYOUT_FORCE_TOP;
- }
-
- setSelectionInt(position);
- invokeOnItemScrollListener();
- invalidate();
-
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Go to the last or first item if possible (not worrying about panning across or navigating
- * within the internal focus of the currently selected item.)
- *
- * @param direction either {@link View#FOCUS_UP} or {@link View#FOCUS_DOWN}
- *
- * @return whether selection was moved
- */
- boolean fullScroll(int direction) {
- boolean moved = false;
- if (direction == FOCUS_UP) {
- if (mSelectedPosition != 0) {
- int position = lookForSelectablePosition(0, true);
- if (position >= 0) {
- mLayoutMode = LAYOUT_FORCE_TOP;
- setSelectionInt(position);
- invokeOnItemScrollListener();
- }
- moved = true;
- }
- } else if (direction == FOCUS_DOWN) {
- if (mSelectedPosition < mItemCount - 1) {
- int position = lookForSelectablePosition(mItemCount - 1, true);
- if (position >= 0) {
- mLayoutMode = LAYOUT_FORCE_BOTTOM;
- setSelectionInt(position);
- invokeOnItemScrollListener();
- }
- moved = true;
- }
- }
-
- if (moved) {
- invalidate();
- }
-
- return moved;
- }
-
- /**
- * To avoid horizontal focus searches changing the selected item, we
- * manually focus search within the selected item (as applicable), and
- * prevent focus from jumping to something within another item.
- * @param direction one of {View.FOCUS_LEFT, View.FOCUS_RIGHT}
- * @return Whether this consumes the key event.
- */
- private boolean handleHorizontalFocusWithinListItem(int direction) {
- if (direction != View.FOCUS_LEFT && direction != View.FOCUS_RIGHT) {
- throw new IllegalArgumentException("direction must be one of {View.FOCUS_LEFT, View.FOCUS_RIGHT}");
- }
-
- final int numChildren = getChildCount();
- if (mItemsCanFocus && numChildren > 0 && mSelectedPosition != INVALID_POSITION) {
- final View selectedView = getSelectedView();
- if (selectedView.hasFocus() && selectedView instanceof ViewGroup) {
- final View currentFocus = selectedView.findFocus();
- final View nextFocus = FocusFinder.getInstance().findNextFocus(
- (ViewGroup) selectedView,
- currentFocus,
- direction);
- if (nextFocus != null) {
- // do the math to get interesting rect in next focus' coordinates
- currentFocus.getFocusedRect(mTempRect);
- offsetDescendantRectToMyCoords(currentFocus, mTempRect);
- offsetRectIntoDescendantCoords(nextFocus, mTempRect);
- if (nextFocus.requestFocus(direction, mTempRect)) {
- return true;
- }
- }
- // we are blocking the key from being handled (by returning true)
- // if the global result is going to be some other view within this
- // list. this is to acheive the overall goal of having
- // horizontal d-pad navigation remain in the current item.
- final View globalNextFocus = FocusFinder.getInstance()
- .findNextFocus(
- (ViewGroup) getRootView(),
- currentFocus,
- direction);
- if (globalNextFocus != null) {
- return isViewAncestorOf(globalNextFocus, this);
- }
- }
- }
- return false;
- }
-
- /**
- * Scrolls to the next or previous item if possible.
- *
- * @param direction either {@link View#FOCUS_UP} or {@link View#FOCUS_DOWN}
- *
- * @return whether selection was moved
- */
- boolean arrowScroll(int direction) {
- try {
- mInLayout = true;
- final boolean handled = arrowScrollImpl(direction);
- if (handled) {
- playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
- }
- return handled;
- } finally {
- mInLayout = false;
- }
- }
-
- /**
- * Handle an arrow scroll going up or down. Take into account whether items are selectable,
- * whether there are focusable items etc.
- *
- * @param direction Either {@link android.view.View#FOCUS_UP} or {@link android.view.View#FOCUS_DOWN}.
- * @return Whether any scrolling, selection or focus change occured.
- */
- private boolean arrowScrollImpl(int direction) {
- if (getChildCount() <= 0) {
- return false;
- }
-
- View selectedView = getSelectedView();
-
- int nextSelectedPosition = lookForSelectablePositionOnScreen(direction);
- int amountToScroll = amountToScroll(direction, nextSelectedPosition);
-
- // if we are moving focus, we may OVERRIDE the default behavior
- final ArrowScrollFocusResult focusResult = mItemsCanFocus ? arrowScrollFocused(direction) : null;
- if (focusResult != null) {
- nextSelectedPosition = focusResult.getSelectedPosition();
- amountToScroll = focusResult.getAmountToScroll();
- }
-
- boolean needToRedraw = focusResult != null;
- if (nextSelectedPosition != INVALID_POSITION) {
- handleNewSelectionChange(selectedView, direction, nextSelectedPosition, focusResult != null);
- setSelectedPositionInt(nextSelectedPosition);
- setNextSelectedPositionInt(nextSelectedPosition);
- selectedView = getSelectedView();
- if (mItemsCanFocus && focusResult == null) {
- // there was no new view found to take focus, make sure we
- // don't leave focus with the old selection
- final View focused = getFocusedChild();
- if (focused != null) {
- focused.clearFocus();
- }
- }
- needToRedraw = true;
- checkSelectionChanged();
- }
-
- if (amountToScroll > 0) {
- scrollListItemsBy((direction == View.FOCUS_UP) ? amountToScroll : -amountToScroll);
- needToRedraw = true;
- }
-
- // if we didn't find a new focusable, make sure any existing focused
- // item that was panned off screen gives up focus.
- if (mItemsCanFocus && (focusResult == null)
- && selectedView != null && selectedView.hasFocus()) {
- final View focused = selectedView.findFocus();
- if (distanceToView(focused) > 0) {
- focused.clearFocus();
- }
- }
-
- // if the current selection is panned off, we need to remove the selection
- if (nextSelectedPosition == INVALID_POSITION && selectedView != null
- && !isViewAncestorOf(selectedView, this)) {
- selectedView = null;
- hideSelector();
-
- // but we don't want to set the ressurect position (that would make subsequent
- // unhandled key events bring back the item we just scrolled off!)
- mResurrectToPosition = INVALID_POSITION;
- }
-
- if (needToRedraw) {
- if (selectedView != null) {
- positionSelector(selectedView);
- mSelectedTop = selectedView.getTop();
- }
- invalidate();
- invokeOnItemScrollListener();
- return true;
- }
-
- return false;
- }
-
- /**
- * When selection changes, it is possible that the previously selected or the
- * next selected item will change its size. If so, we need to offset some folks,
- * and re-layout the items as appropriate.
- *
- * @param selectedView The currently selected view (before changing selection).
- * should be <code>null</code> if there was no previous selection.
- * @param direction Either {@link android.view.View#FOCUS_UP} or
- * {@link android.view.View#FOCUS_DOWN}.
- * @param newSelectedPosition The position of the next selection.
- * @param newFocusAssigned whether new focus was assigned. This matters because
- * when something has focus, we don't want to show selection (ugh).
- */
- private void handleNewSelectionChange(View selectedView, int direction, int newSelectedPosition,
- boolean newFocusAssigned) {
- if (newSelectedPosition == INVALID_POSITION) {
- throw new IllegalArgumentException("newSelectedPosition needs to be valid");
- }
-
- // whether or not we are moving down or up, we want to preserve the
- // top of whatever view is on top:
- // - moving down: the view that had selection
- // - moving up: the view that is getting selection
- View topView;
- View bottomView;
- int topViewIndex, bottomViewIndex;
- boolean topSelected = false;
- final int selectedIndex = mSelectedPosition - mFirstPosition;
- final int nextSelectedIndex = newSelectedPosition - mFirstPosition;
- if (direction == View.FOCUS_UP) {
- topViewIndex = nextSelectedIndex;
- bottomViewIndex = selectedIndex;
- topView = getChildAt(topViewIndex);
- bottomView = selectedView;
- topSelected = true;
- } else {
- topViewIndex = selectedIndex;
- bottomViewIndex = nextSelectedIndex;
- topView = selectedView;
- bottomView = getChildAt(bottomViewIndex);
- }
-
- final int numChildren = getChildCount();
-
- // start with top view: is it changing size?
- if (topView != null) {
- topView.setSelected(!newFocusAssigned && topSelected);
- measureAndAdjustDown(topView, topViewIndex, numChildren);
- }
-
- // is the bottom view changing size?
- if (bottomView != null) {
- bottomView.setSelected(!newFocusAssigned && !topSelected);
- measureAndAdjustDown(bottomView, bottomViewIndex, numChildren);
- }
- }
-
- /**
- * Re-measure a child, and if its height changes, lay it out preserving its
- * top, and adjust the children below it appropriately.
- * @param child The child
- * @param childIndex The view group index of the child.
- * @param numChildren The number of children in the view group.
- */
- private void measureAndAdjustDown(View child, int childIndex, int numChildren) {
- int oldHeight = child.getHeight();
- measureItem(child);
- if (child.getMeasuredHeight() != oldHeight) {
- // lay out the view, preserving its top
- relayoutMeasuredItem(child);
-
- // adjust views below appropriately
- final int heightDelta = child.getMeasuredHeight() - oldHeight;
- for (int i = childIndex + 1; i < numChildren; i++) {
- getChildAt(i).offsetTopAndBottom(heightDelta);
- }
- }
- }
-
- /**
- * Measure a particular list child.
- * TODO: unify with setUpChild.
- * @param child The child.
- */
- private void measureItem(View child) {
- ViewGroup.LayoutParams p = child.getLayoutParams();
- if (p == null) {
- p = new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- }
-
- int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec,
- mListPadding.left + mListPadding.right, p.width);
- int lpHeight = p.height;
- int childHeightSpec;
- if (lpHeight > 0) {
- childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
- } else {
- childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- }
- child.measure(childWidthSpec, childHeightSpec);
- }
-
- /**
- * Layout a child that has been measured, preserving its top position.
- * TODO: unify with setUpChild.
- * @param child The child.
- */
- private void relayoutMeasuredItem(View child) {
- final int w = child.getMeasuredWidth();
- final int h = child.getMeasuredHeight();
- final int childLeft = mListPadding.left;
- final int childRight = childLeft + w;
- final int childTop = child.getTop();
- final int childBottom = childTop + h;
- child.layout(childLeft, childTop, childRight, childBottom);
- }
-
- /**
- * @return The amount to preview next items when arrow srolling.
- */
- private int getArrowScrollPreviewLength() {
- return Math.max(MIN_SCROLL_PREVIEW_PIXELS, getVerticalFadingEdgeLength());
- }
-
- /**
- * Determine how much we need to scroll in order to get the next selected view
- * visible, with a fading edge showing below as applicable. The amount is
- * capped at {@link #getMaxScrollAmount()} .
- *
- * @param direction either {@link android.view.View#FOCUS_UP} or
- * {@link android.view.View#FOCUS_DOWN}.
- * @param nextSelectedPosition The position of the next selection, or
- * {@link #INVALID_POSITION} if there is no next selectable position
- * @return The amount to scroll. Note: this is always positive! Direction
- * needs to be taken into account when actually scrolling.
- */
- private int amountToScroll(int direction, int nextSelectedPosition) {
- final int listBottom = getHeight() - mListPadding.bottom;
- final int listTop = mListPadding.top;
-
- final int numChildren = getChildCount();
-
- if (direction == View.FOCUS_DOWN) {
- int indexToMakeVisible = numChildren - 1;
- if (nextSelectedPosition != INVALID_POSITION) {
- indexToMakeVisible = nextSelectedPosition - mFirstPosition;
- }
-
- final int positionToMakeVisible = mFirstPosition + indexToMakeVisible;
- final View viewToMakeVisible = getChildAt(indexToMakeVisible);
-
- int goalBottom = listBottom;
- if (positionToMakeVisible < mItemCount - 1) {
- goalBottom -= getArrowScrollPreviewLength();
- }
-
- if (viewToMakeVisible.getBottom() <= goalBottom) {
- // item is fully visible.
- return 0;
- }
-
- if (nextSelectedPosition != INVALID_POSITION
- && (goalBottom - viewToMakeVisible.getTop()) >= getMaxScrollAmount()) {
- // item already has enough of it visible, changing selection is good enough
- return 0;
- }
-
- int amountToScroll = (viewToMakeVisible.getBottom() - goalBottom);
-
- if ((mFirstPosition + numChildren) == mItemCount) {
- // last is last in list -> make sure we don't scroll past it
- final int max = getChildAt(numChildren - 1).getBottom() - listBottom;
- amountToScroll = Math.min(amountToScroll, max);
- }
-
- return Math.min(amountToScroll, getMaxScrollAmount());
- } else {
- int indexToMakeVisible = 0;
- if (nextSelectedPosition != INVALID_POSITION) {
- indexToMakeVisible = nextSelectedPosition - mFirstPosition;
- }
- final int positionToMakeVisible = mFirstPosition + indexToMakeVisible;
- final View viewToMakeVisible = getChildAt(indexToMakeVisible);
- int goalTop = listTop;
- if (positionToMakeVisible > 0) {
- goalTop += getArrowScrollPreviewLength();
- }
- if (viewToMakeVisible.getTop() >= goalTop) {
- // item is fully visible.
- return 0;
- }
-
- if (nextSelectedPosition != INVALID_POSITION &&
- (viewToMakeVisible.getBottom() - goalTop) >= getMaxScrollAmount()) {
- // item already has enough of it visible, changing selection is good enough
- return 0;
- }
-
- int amountToScroll = (goalTop - viewToMakeVisible.getTop());
- if (mFirstPosition == 0) {
- // first is first in list -> make sure we don't scroll past it
- final int max = listTop - getChildAt(0).getTop();
- amountToScroll = Math.min(amountToScroll, max);
- }
- return Math.min(amountToScroll, getMaxScrollAmount());
- }
- }
-
- /**
- * Holds results of focus aware arrow scrolling.
- */
- static private class ArrowScrollFocusResult {
- private int mSelectedPosition;
- private int mAmountToScroll;
-
- /**
- * How {@link android.widget.ListView#arrowScrollFocused} returns its values.
- */
- void populate(int selectedPosition, int amountToScroll) {
- mSelectedPosition = selectedPosition;
- mAmountToScroll = amountToScroll;
- }
-
- public int getSelectedPosition() {
- return mSelectedPosition;
- }
-
- public int getAmountToScroll() {
- return mAmountToScroll;
- }
- }
-
- /**
- * @param direction either {@link android.view.View#FOCUS_UP} or
- * {@link android.view.View#FOCUS_DOWN}.
- * @return The position of the next selectable position of the views that
- * are currently visible, taking into account the fact that there might
- * be no selection. Returns {@link #INVALID_POSITION} if there is no
- * selectable view on screen in the given direction.
- */
- private int lookForSelectablePositionOnScreen(int direction) {
- final int firstPosition = mFirstPosition;
- if (direction == View.FOCUS_DOWN) {
- int startPos = (mSelectedPosition != INVALID_POSITION) ?
- mSelectedPosition + 1 :
- firstPosition;
- if (startPos >= mAdapter.getCount()) {
- return INVALID_POSITION;
- }
- if (startPos < firstPosition) {
- startPos = firstPosition;
- }
-
- final int lastVisiblePos = getLastVisiblePosition();
- final ListAdapter adapter = getAdapter();
- for (int pos = startPos; pos <= lastVisiblePos; pos++) {
- if (adapter.isEnabled(pos)
- && getChildAt(pos - firstPosition).getVisibility() == View.VISIBLE) {
- return pos;
- }
- }
- } else {
- int last = firstPosition + getChildCount() - 1;
- int startPos = (mSelectedPosition != INVALID_POSITION) ?
- mSelectedPosition - 1 :
- firstPosition + getChildCount() - 1;
- if (startPos < 0) {
- return INVALID_POSITION;
- }
- if (startPos > last) {
- startPos = last;
- }
-
- final ListAdapter adapter = getAdapter();
- for (int pos = startPos; pos >= firstPosition; pos--) {
- if (adapter.isEnabled(pos)
- && getChildAt(pos - firstPosition).getVisibility() == View.VISIBLE) {
- return pos;
- }
- }
- }
- return INVALID_POSITION;
- }
-
- /**
- * Do an arrow scroll based on focus searching. If a new view is
- * given focus, return the selection delta and amount to scroll via
- * an {@link ArrowScrollFocusResult}, otherwise, return null.
- *
- * @param direction either {@link android.view.View#FOCUS_UP} or
- * {@link android.view.View#FOCUS_DOWN}.
- * @return The result if focus has changed, or <code>null</code>.
- */
- private ArrowScrollFocusResult arrowScrollFocused(final int direction) {
- final View selectedView = getSelectedView();
- View newFocus;
- if (selectedView != null && selectedView.hasFocus()) {
- View oldFocus = selectedView.findFocus();
- newFocus = FocusFinder.getInstance().findNextFocus(this, oldFocus, direction);
- } else {
- if (direction == View.FOCUS_DOWN) {
- final boolean topFadingEdgeShowing = (mFirstPosition > 0);
- final int listTop = mListPadding.top +
- (topFadingEdgeShowing ? getArrowScrollPreviewLength() : 0);
- final int ySearchPoint =
- (selectedView != null && selectedView.getTop() > listTop) ?
- selectedView.getTop() :
- listTop;
- mTempRect.set(0, ySearchPoint, 0, ySearchPoint);
- } else {
- final boolean bottomFadingEdgeShowing =
- (mFirstPosition + getChildCount() - 1) < mItemCount;
- final int listBottom = getHeight() - mListPadding.bottom -
- (bottomFadingEdgeShowing ? getArrowScrollPreviewLength() : 0);
- final int ySearchPoint =
- (selectedView != null && selectedView.getBottom() < listBottom) ?
- selectedView.getBottom() :
- listBottom;
- mTempRect.set(0, ySearchPoint, 0, ySearchPoint);
- }
- newFocus = FocusFinder.getInstance().findNextFocusFromRect(this, mTempRect, direction);
- }
-
- if (newFocus != null) {
- final int positionOfNewFocus = positionOfNewFocus(newFocus);
-
- // if the focus change is in a different new position, make sure
- // we aren't jumping over another selectable position
- if (mSelectedPosition != INVALID_POSITION && positionOfNewFocus != mSelectedPosition) {
- final int selectablePosition = lookForSelectablePositionOnScreen(direction);
- if (selectablePosition != INVALID_POSITION &&
- ((direction == View.FOCUS_DOWN && selectablePosition < positionOfNewFocus) ||
- (direction == View.FOCUS_UP && selectablePosition > positionOfNewFocus))) {
- return null;
- }
- }
-
- int focusScroll = amountToScrollToNewFocus(direction, newFocus, positionOfNewFocus);
-
- final int maxScrollAmount = getMaxScrollAmount();
- if (focusScroll < maxScrollAmount) {
- // not moving too far, safe to give next view focus
- newFocus.requestFocus(direction);
- mArrowScrollFocusResult.populate(positionOfNewFocus, focusScroll);
- return mArrowScrollFocusResult;
- } else if (distanceToView(newFocus) < maxScrollAmount){
- // Case to consider:
- // too far to get entire next focusable on screen, but by going
- // max scroll amount, we are getting it at least partially in view,
- // so give it focus and scroll the max ammount.
- newFocus.requestFocus(direction);
- mArrowScrollFocusResult.populate(positionOfNewFocus, maxScrollAmount);
- return mArrowScrollFocusResult;
- }
- }
- return null;
- }
-
- /**
- * @param newFocus The view that would have focus.
- * @return the position that contains newFocus
- */
- private int positionOfNewFocus(View newFocus) {
- final int numChildren = getChildCount();
- for (int i = 0; i < numChildren; i++) {
- final View child = getChildAt(i);
- if (isViewAncestorOf(newFocus, child)) {
- return mFirstPosition + i;
- }
- }
- throw new IllegalArgumentException("newFocus is not a child of any of the"
- + " children of the list!");
- }
-
- /**
- * Return true if child is an ancestor of parent, (or equal to the parent).
- */
- private boolean isViewAncestorOf(View child, View parent) {
- if (child == parent) {
- return true;
- }
-
- final ViewParent theParent = child.getParent();
- return (theParent instanceof ViewGroup) && isViewAncestorOf((View) theParent, parent);
- }
-
- /**
- * Determine how much we need to scroll in order to get newFocus in view.
- * @param direction either {@link android.view.View#FOCUS_UP} or
- * {@link android.view.View#FOCUS_DOWN}.
- * @param newFocus The view that would take focus.
- * @param positionOfNewFocus The position of the list item containing newFocus
- * @return The amount to scroll. Note: this is always positive! Direction
- * needs to be taken into account when actually scrolling.
- */
- private int amountToScrollToNewFocus(int direction, View newFocus, int positionOfNewFocus) {
- int amountToScroll = 0;
- newFocus.getDrawingRect(mTempRect);
- offsetDescendantRectToMyCoords(newFocus, mTempRect);
- if (direction == View.FOCUS_UP) {
- if (mTempRect.top < mListPadding.top) {
- amountToScroll = mListPadding.top - mTempRect.top;
- if (positionOfNewFocus > 0) {
- amountToScroll += getArrowScrollPreviewLength();
- }
- }
- } else {
- final int listBottom = getHeight() - mListPadding.bottom;
- if (mTempRect.bottom > listBottom) {
- amountToScroll = mTempRect.bottom - listBottom;
- if (positionOfNewFocus < mItemCount - 1) {
- amountToScroll += getArrowScrollPreviewLength();
- }
- }
- }
- return amountToScroll;
- }
-
- /**
- * Determine the distance to the nearest edge of a view in a particular
- * direciton.
- * @param descendant A descendant of this list.
- * @return The distance, or 0 if the nearest edge is already on screen.
- */
- private int distanceToView(View descendant) {
- int distance = 0;
- descendant.getDrawingRect(mTempRect);
- offsetDescendantRectToMyCoords(descendant, mTempRect);
- final int listBottom = mBottom - mTop - mListPadding.bottom;
- if (mTempRect.bottom < mListPadding.top) {
- distance = mListPadding.top - mTempRect.bottom;
- } else if (mTempRect.top > listBottom) {
- distance = mTempRect.top - listBottom;
- }
- return distance;
- }
-
-
- /**
- * Scroll the children by amount, adding a view at the end and removing
- * views that fall off as necessary.
- *
- * @param amount The amount (positive or negative) to scroll.
- */
- private void scrollListItemsBy(int amount) {
- offsetChildrenTopAndBottom(amount);
-
- final int listBottom = getHeight() - mListPadding.bottom;
- final int listTop = mListPadding.top;
-
- if (amount < 0) {
- // shifted items up
-
- // may need to pan views into the bottom space
- int numChildren = getChildCount();
- View last = getChildAt(numChildren - 1);
- while (last.getBottom() < listBottom) {
- final int lastVisiblePosition = mFirstPosition + numChildren - 1;
- if (lastVisiblePosition < mItemCount - 1) {
- last = addViewBelow(last, lastVisiblePosition);
- numChildren++;
- } else {
- break;
- }
- }
-
- // may have brought in the last child of the list that is skinnier
- // than the fading edge, thereby leaving space at the end. need
- // to shift back
- if (last.getBottom() < listBottom) {
- offsetChildrenTopAndBottom(listBottom - last.getBottom());
- }
-
- // top views may be panned off screen
- View first = getChildAt(0);
- while (first.getBottom() < listTop) {
- removeViewInLayout(first);
- mRecycler.addScrapView(first);
- first = getChildAt(0);
- mFirstPosition++;
- }
- } else {
- // shifted items down
- View first = getChildAt(0);
-
- // may need to pan views into top
- while ((first.getTop() > listTop) && (mFirstPosition > 0)) {
- first = addViewAbove(first, mFirstPosition);
- mFirstPosition--;
- }
-
- // may have brought the very first child of the list in too far and
- // need to shift it back
- if (first.getTop() > listTop) {
- offsetChildrenTopAndBottom(listTop - first.getTop());
- }
-
- int lastIndex = getChildCount() - 1;
- View last = getChildAt(lastIndex);
-
- // bottom view may be panned off screen
- while (last.getTop() > listBottom) {
- removeViewInLayout(last);
- mRecycler.addScrapView(last);
- last = getChildAt(--lastIndex);
- }
- }
- }
-
- private View addViewAbove(View theView, int position) {
- int abovePosition = position - 1;
- View view = obtainView(abovePosition);
- int edgeOfNewChild = theView.getTop() - mDividerHeight;
- setupChild(view, abovePosition, edgeOfNewChild, false, mListPadding.left, false, false);
- return view;
- }
-
- private View addViewBelow(View theView, int position) {
- int belowPosition = position + 1;
- View view = obtainView(belowPosition);
- int edgeOfNewChild = theView.getBottom() + mDividerHeight;
- setupChild(view, belowPosition, edgeOfNewChild, true, mListPadding.left, false, false);
- return view;
- }
-
- /**
- * Indicates that the views created by the ListAdapter can contain focusable
- * items.
- *
- * @param itemsCanFocus true if items can get focus, false otherwise
- */
- public void setItemsCanFocus(boolean itemsCanFocus) {
- mItemsCanFocus = itemsCanFocus;
- if (!itemsCanFocus) {
- setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
- }
- }
-
- /**
- * @return Whether the views created by the ListAdapter can contain focusable
- * items.
- */
- public boolean getItemsCanFocus() {
- return mItemsCanFocus;
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- // Draw the dividers
- final int dividerHeight = mDividerHeight;
-
- if (dividerHeight > 0 && mDivider != null) {
- // Only modify the top and bottom in the loop, we set the left and right here
- final Rect bounds = mTempRect;
- bounds.left = mPaddingLeft;
- bounds.right = mRight - mLeft - mPaddingRight;
-
- final int count = getChildCount();
- final int headerCount = mHeaderViewInfos.size();
- final int footerLimit = mItemCount - mFooterViewInfos.size() - 1;
- final boolean headerDividers = mHeaderDividersEnabled;
- final boolean footerDividers = mFooterDividersEnabled;
- final int first = mFirstPosition;
-
- if (!mStackFromBottom) {
- int bottom;
- int listBottom = mBottom - mTop - mListPadding.bottom;
-
- for (int i = 0; i < count; i++) {
- if ((headerDividers || first + i >= headerCount) &&
- (footerDividers || first + i < footerLimit)) {
- View child = getChildAt(i);
- bottom = child.getBottom();
- if (bottom < listBottom) {
- bounds.top = bottom;
- bounds.bottom = bottom + dividerHeight;
- drawDivider(canvas, bounds, i);
- }
- }
- }
- } else {
- int top;
- int listTop = mListPadding.top;
-
- for (int i = 0; i < count; i++) {
- if ((headerDividers || first + i >= headerCount) &&
- (footerDividers || first + i < footerLimit)) {
- View child = getChildAt(i);
- top = child.getTop();
- if (top > listTop) {
- bounds.top = top - dividerHeight;
- bounds.bottom = top;
- // Give the method the child ABOVE the divider, so we
- // subtract one from our child
- // position. Give -1 when there is no child above the
- // divider.
- drawDivider(canvas, bounds, i - 1);
- }
- }
- }
- }
- }
-
- // Draw the indicators (these should be drawn above the dividers) and children
- super.dispatchDraw(canvas);
- }
-
- /**
- * Draws a divider for the given child in the given bounds.
- *
- * @param canvas The canvas to draw to.
- * @param bounds The bounds of the divider.
- * @param childIndex The index of child (of the View) above the divider.
- * This will be -1 if there is no child above the divider to be
- * drawn.
- */
- void drawDivider(Canvas canvas, Rect bounds, int childIndex) {
- // This widget draws the same divider for all children
- final Drawable divider = mDivider;
- final boolean clipDivider = mClipDivider;
-
- if (!clipDivider) {
- divider.setBounds(bounds);
- } else {
- canvas.save();
- canvas.clipRect(bounds);
- }
-
- divider.draw(canvas);
-
- if (clipDivider) {
- canvas.restore();
- }
- }
-
- /**
- * Returns the drawable that will be drawn between each item in the list.
- *
- * @return the current drawable drawn between list elements
- */
- public Drawable getDivider() {
- return mDivider;
- }
-
- /**
- * Sets the drawable that will be drawn between each item in the list. If the drawable does
- * not have an intrinsic height, you should also call {@link #setDividerHeight(int)}
- *
- * @param divider The drawable to use.
- */
- public void setDivider(Drawable divider) {
- if (divider != null) {
- mDividerHeight = divider.getIntrinsicHeight();
- mClipDivider = divider instanceof ColorDrawable;
- } else {
- mDividerHeight = 0;
- mClipDivider = false;
- }
- mDivider = divider;
- requestLayoutIfNecessary();
- }
-
- /**
- * @return Returns the height of the divider that will be drawn between each item in the list.
- */
- public int getDividerHeight() {
- return mDividerHeight;
- }
-
- /**
- * Sets the height of the divider that will be drawn between each item in the list. Calling
- * this will override the intrinsic height as set by {@link #setDivider(Drawable)}
- *
- * @param height The new height of the divider in pixels.
- */
- public void setDividerHeight(int height) {
- mDividerHeight = height;
- requestLayoutIfNecessary();
- }
-
- /**
- * Enables or disables the drawing of the divider for header views.
- *
- * @param headerDividersEnabled True to draw the headers, false otherwise.
- *
- * @see #setFooterDividersEnabled(boolean)
- * @see #addHeaderView(android.view.View)
- */
- public void setHeaderDividersEnabled(boolean headerDividersEnabled) {
- mHeaderDividersEnabled = headerDividersEnabled;
- invalidate();
- }
-
- /**
- * Enables or disables the drawing of the divider for footer views.
- *
- * @param footerDividersEnabled True to draw the footers, false otherwise.
- *
- * @see #setHeaderDividersEnabled(boolean)
- * @see #addFooterView(android.view.View)
- */
- public void setFooterDividersEnabled(boolean footerDividersEnabled) {
- mFooterDividersEnabled = footerDividersEnabled;
- invalidate();
- }
-
- @Override
- protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
- super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
-
- int closetChildIndex = -1;
- if (gainFocus && previouslyFocusedRect != null) {
- previouslyFocusedRect.offset(mScrollX, mScrollY);
-
- // figure out which item should be selected based on previously
- // focused rect
- Rect otherRect = mTempRect;
- int minDistance = Integer.MAX_VALUE;
- final int childCount = getChildCount();
- final int firstPosition = mFirstPosition;
- final ListAdapter adapter = mAdapter;
-
- for (int i = 0; i < childCount; i++) {
- // only consider selectable views
- if (!adapter.isEnabled(firstPosition + i)) {
- continue;
- }
-
- View other = getChildAt(i);
- other.getDrawingRect(otherRect);
- offsetDescendantRectToMyCoords(other, otherRect);
- int distance = getDistance(previouslyFocusedRect, otherRect, direction);
-
- if (distance < minDistance) {
- minDistance = distance;
- closetChildIndex = i;
- }
- }
- }
-
- if (closetChildIndex >= 0) {
- setSelection(closetChildIndex + mFirstPosition);
- } else {
- requestLayout();
- }
- }
-
-
- /*
- * (non-Javadoc)
- *
- * Children specified in XML are assumed to be header views. After we have
- * parsed them move them out of the children list and into mHeaderViews.
- */
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- int count = getChildCount();
- if (count > 0) {
- for (int i = 0; i < count; ++i) {
- addHeaderView(getChildAt(i));
- }
- removeAllViews();
- }
- }
-
- /* (non-Javadoc)
- * @see android.view.View#findViewById(int)
- * First look in our children, then in any header and footer views that may be scrolled off.
- */
- @Override
- protected View findViewTraversal(int id) {
- View v;
- v = super.findViewTraversal(id);
- if (v == null) {
- v = findViewInHeadersOrFooters(mHeaderViewInfos, id);
- if (v != null) {
- return v;
- }
- v = findViewInHeadersOrFooters(mFooterViewInfos, id);
- if (v != null) {
- return v;
- }
- }
- return v;
- }
-
- /* (non-Javadoc)
- *
- * Look in the passed in list of headers or footers for the view.
- */
- View findViewInHeadersOrFooters(ArrayList<FixedViewInfo> where, int id) {
- if (where != null) {
- int len = where.size();
- View v;
-
- for (int i = 0; i < len; i++) {
- v = where.get(i).view;
-
- if (!v.isRootNamespace()) {
- v = v.findViewById(id);
-
- if (v != null) {
- return v;
- }
- }
- }
- }
- return null;
- }
-
- /* (non-Javadoc)
- * @see android.view.View#findViewWithTag(String)
- * First look in our children, then in any header and footer views that may be scrolled off.
- */
- @Override
- protected View findViewWithTagTraversal(Object tag) {
- View v;
- v = super.findViewWithTagTraversal(tag);
- if (v == null) {
- v = findViewTagInHeadersOrFooters(mHeaderViewInfos, tag);
- if (v != null) {
- return v;
- }
-
- v = findViewTagInHeadersOrFooters(mFooterViewInfos, tag);
- if (v != null) {
- return v;
- }
- }
- return v;
- }
-
- /* (non-Javadoc)
- *
- * Look in the passed in list of headers or footers for the view with the tag.
- */
- View findViewTagInHeadersOrFooters(ArrayList<FixedViewInfo> where, Object tag) {
- if (where != null) {
- int len = where.size();
- View v;
-
- for (int i = 0; i < len; i++) {
- v = where.get(i).view;
-
- if (!v.isRootNamespace()) {
- v = v.findViewWithTag(tag);
-
- if (v != null) {
- return v;
- }
- }
- }
- }
- return null;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- if (mItemsCanFocus && ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) {
- // Don't handle edge touches immediately -- they may actually belong to one of our
- // descendants.
- return false;
- }
- return super.onTouchEvent(ev);
- }
-
- /**
- * @see #setChoiceMode(int)
- *
- * @return The current choice mode
- */
- public int getChoiceMode() {
- return mChoiceMode;
- }
-
- /**
- * Defines the choice behavior for the List. By default, Lists do not have any choice behavior
- * ({@link #CHOICE_MODE_NONE}). By setting the choiceMode to {@link #CHOICE_MODE_SINGLE}, the
- * List allows up to one item to be in a chosen state. By setting the choiceMode to
- * {@link #CHOICE_MODE_MULTIPLE}, the list allows any number of items to be chosen.
- *
- * @param choiceMode One of {@link #CHOICE_MODE_NONE}, {@link #CHOICE_MODE_SINGLE}, or
- * {@link #CHOICE_MODE_MULTIPLE}
- */
- public void setChoiceMode(int choiceMode) {
- mChoiceMode = choiceMode;
- if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates == null) {
- mCheckStates = new SparseBooleanArray();
- }
- }
-
- @Override
- public boolean performItemClick(View view, int position, long id) {
- boolean handled = false;
-
- if (mChoiceMode != CHOICE_MODE_NONE) {
- handled = true;
-
- if (mChoiceMode == CHOICE_MODE_MULTIPLE) {
- boolean oldValue = mCheckStates.get(position, false);
- mCheckStates.put(position, !oldValue);
- } else {
- boolean oldValue = mCheckStates.get(position, false);
- if (!oldValue) {
- mCheckStates.clear();
- mCheckStates.put(position, true);
- }
- }
-
- mDataChanged = true;
- rememberSyncState();
- requestLayout();
- }
-
- handled |= super.performItemClick(view, position, id);
-
- return handled;
- }
-
- /**
- * Sets the checked state of the specified position. The is only valid if
- * the choice mode has been set to {@link #CHOICE_MODE_SINGLE} or
- * {@link #CHOICE_MODE_MULTIPLE}.
- *
- * @param position The item whose checked state is to be checked
- * @param value The new checked sate for the item
- */
- public void setItemChecked(int position, boolean value) {
- if (mChoiceMode == CHOICE_MODE_NONE) {
- return;
- }
-
- if (mChoiceMode == CHOICE_MODE_MULTIPLE) {
- mCheckStates.put(position, value);
- } else {
- boolean oldValue = mCheckStates.get(position, false);
- mCheckStates.clear();
- if (!oldValue) {
- mCheckStates.put(position, true);
- }
- }
-
- // Do not generate a data change while we are in the layout phase
- if (!mInLayout && !mBlockLayoutRequests) {
- mDataChanged = true;
- rememberSyncState();
- requestLayout();
- }
- }
-
- /**
- * Returns the checked state of the specified position. The result is only
- * valid if the choice mode has not been set to {@link #CHOICE_MODE_SINGLE}
- * or {@link #CHOICE_MODE_MULTIPLE}.
- *
- * @param position The item whose checked state to return
- * @return The item's checked state
- *
- * @see #setChoiceMode(int)
- */
- public boolean isItemChecked(int position) {
- if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
- return mCheckStates.get(position);
- }
-
- return false;
- }
-
- /**
- * Returns the currently checked item. The result is only valid if the choice
- * mode has not been set to {@link #CHOICE_MODE_SINGLE}.
- *
- * @return The position of the currently checked item or
- * {@link #INVALID_POSITION} if nothing is selected
- *
- * @see #setChoiceMode(int)
- */
- public int getCheckedItemPosition() {
- if (mChoiceMode == CHOICE_MODE_SINGLE && mCheckStates != null && mCheckStates.size() == 1) {
- return mCheckStates.keyAt(0);
- }
-
- return INVALID_POSITION;
- }
-
- /**
- * Returns the set of checked items in the list. The result is only valid if
- * the choice mode has not been set to {@link #CHOICE_MODE_SINGLE}.
- *
- * @return A SparseBooleanArray which will return true for each call to
- * get(int position) where position is a position in the list.
- */
- public SparseBooleanArray getCheckedItemPositions() {
- if (mChoiceMode != CHOICE_MODE_NONE) {
- return mCheckStates;
- }
- return null;
- }
-
- /**
- * Clear any choices previously set
- */
- public void clearChoices() {
- if (mCheckStates != null) {
- mCheckStates.clear();
- }
- }
-
- static class SavedState extends BaseSavedState {
- SparseBooleanArray checkState;
-
- /**
- * Constructor called from {@link ListView#onSaveInstanceState()}
- */
- SavedState(Parcelable superState, SparseBooleanArray checkState) {
- super(superState);
- this.checkState = checkState;
- }
-
- /**
- * Constructor called from {@link #CREATOR}
- */
- private SavedState(Parcel in) {
- super(in);
- checkState = in.readSparseBooleanArray();
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- super.writeToParcel(out, flags);
- out.writeSparseBooleanArray(checkState);
- }
-
- @Override
- public String toString() {
- return "ListView.SavedState{"
- + Integer.toHexString(System.identityHashCode(this))
- + " checkState=" + checkState + "}";
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR
- = new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
- @Override
- public Parcelable onSaveInstanceState() {
- Parcelable superState = super.onSaveInstanceState();
- return new SavedState(superState, mCheckStates);
- }
-
- @Override
- public void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
-
- super.onRestoreInstanceState(ss.getSuperState());
-
- if (ss.checkState != null) {
- mCheckStates = ss.checkState;
- }
-
- }
-}
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
deleted file mode 100644
index f2cec92..0000000
--- a/core/java/android/widget/MediaController.java
+++ /dev/null
@@ -1,552 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.graphics.PixelFormat;
-import android.media.AudioManager;
-import android.os.Handler;
-import android.os.Message;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
-import android.widget.SeekBar.OnSeekBarChangeListener;
-
-import com.android.internal.policy.PolicyManager;
-
-import java.util.Formatter;
-import java.util.Locale;
-
-/**
- * A view containing controls for a MediaPlayer. Typically contains the
- * buttons like "Play/Pause", "Rewind", "Fast Forward" and a progress
- * slider. It takes care of synchronizing the controls with the state
- * of the MediaPlayer.
- * <p>
- * The way to use this class is to instantiate it programatically.
- * The MediaController will create a default set of controls
- * and put them in a window floating above your application. Specifically,
- * the controls will float above the view specified with setAnchorView().
- * The window will disappear if left idle for three seconds and reappear
- * when the user touches the anchor view.
- * <p>
- * Functions like show() and hide() have no effect when MediaController
- * is created in an xml layout.
- *
- * MediaController will hide and
- * show the buttons according to these rules:
- * <ul>
- * <li> The "previous" and "next" buttons are hidden until setPrevNextListeners()
- * has been called
- * <li> The "previous" and "next" buttons are visible but disabled if
- * setPrevNextListeners() was called with null listeners
- * <li> The "rewind" and "fastforward" buttons are shown unless requested
- * otherwise by using the MediaController(Context, boolean) constructor
- * with the boolean set to false
- * </ul>
- */
-public class MediaController extends FrameLayout {
-
- private MediaPlayerControl mPlayer;
- private Context mContext;
- private View mAnchor;
- private View mRoot;
- private WindowManager mWindowManager;
- private Window mWindow;
- private View mDecor;
- private ProgressBar mProgress;
- private TextView mEndTime, mCurrentTime;
- private boolean mShowing;
- private boolean mDragging;
- private static final int sDefaultTimeout = 3000;
- private static final int FADE_OUT = 1;
- private static final int SHOW_PROGRESS = 2;
- private boolean mUseFastForward;
- private boolean mFromXml;
- private boolean mListenersSet;
- private View.OnClickListener mNextListener, mPrevListener;
- StringBuilder mFormatBuilder;
- Formatter mFormatter;
- private ImageButton mPauseButton;
- private ImageButton mFfwdButton;
- private ImageButton mRewButton;
- private ImageButton mNextButton;
- private ImageButton mPrevButton;
-
- public MediaController(Context context, AttributeSet attrs) {
- super(context, attrs);
- mRoot = this;
- mContext = context;
- mUseFastForward = true;
- mFromXml = true;
- }
-
- @Override
- public void onFinishInflate() {
- if (mRoot != null)
- initControllerView(mRoot);
- }
-
- public MediaController(Context context, boolean useFastForward) {
- super(context);
- mContext = context;
- mUseFastForward = useFastForward;
- initFloatingWindow();
- }
-
- public MediaController(Context context) {
- super(context);
- mContext = context;
- mUseFastForward = true;
- initFloatingWindow();
- }
-
- private void initFloatingWindow() {
- mWindowManager = (WindowManager)mContext.getSystemService("window");
- mWindow = PolicyManager.makeNewWindow(mContext);
- mWindow.setWindowManager(mWindowManager, null, null);
- mWindow.requestFeature(Window.FEATURE_NO_TITLE);
- mDecor = mWindow.getDecorView();
- mDecor.setOnTouchListener(mTouchListener);
- mWindow.setContentView(this);
- mWindow.setBackgroundDrawableResource(android.R.color.transparent);
-
- // While the media controller is up, the volume control keys should
- // affect the media stream type
- mWindow.setVolumeControlStream(AudioManager.STREAM_MUSIC);
-
- setFocusable(true);
- setFocusableInTouchMode(true);
- setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
- requestFocus();
- }
-
- private OnTouchListener mTouchListener = new OnTouchListener() {
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- if (mShowing) {
- hide();
- }
- }
- return false;
- }
- };
-
- public void setMediaPlayer(MediaPlayerControl player) {
- mPlayer = player;
- updatePausePlay();
- }
-
- /**
- * Set the view that acts as the anchor for the control view.
- * This can for example be a VideoView, or your Activity's main view.
- * @param view The view to which to anchor the controller when it is visible.
- */
- public void setAnchorView(View view) {
- mAnchor = view;
-
- FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.FILL_PARENT
- );
-
- removeAllViews();
- View v = makeControllerView();
- addView(v, frameParams);
- }
-
- /**
- * Create the view that holds the widgets that control playback.
- * Derived classes can override this to create their own.
- * @return The controller view.
- * @hide This doesn't work as advertised
- */
- protected View makeControllerView() {
- LayoutInflater inflate = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mRoot = inflate.inflate(com.android.internal.R.layout.media_controller, null);
-
- initControllerView(mRoot);
-
- return mRoot;
- }
-
- private void initControllerView(View v) {
- mPauseButton = (ImageButton) v.findViewById(com.android.internal.R.id.pause);
- if (mPauseButton != null) {
- mPauseButton.requestFocus();
- mPauseButton.setOnClickListener(mPauseListener);
- }
-
- mFfwdButton = (ImageButton) v.findViewById(com.android.internal.R.id.ffwd);
- if (mFfwdButton != null) {
- mFfwdButton.setOnClickListener(mFfwdListener);
- if (!mFromXml) {
- mFfwdButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
- }
- }
-
- mRewButton = (ImageButton) v.findViewById(com.android.internal.R.id.rew);
- if (mRewButton != null) {
- mRewButton.setOnClickListener(mRewListener);
- if (!mFromXml) {
- mRewButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
- }
- }
-
- // By default these are hidden. They will be enabled when setPrevNextListeners() is called
- mNextButton = (ImageButton) v.findViewById(com.android.internal.R.id.next);
- if (mNextButton != null && !mFromXml && !mListenersSet) {
- mNextButton.setVisibility(View.GONE);
- }
- mPrevButton = (ImageButton) v.findViewById(com.android.internal.R.id.prev);
- if (mPrevButton != null && !mFromXml && !mListenersSet) {
- mPrevButton.setVisibility(View.GONE);
- }
-
- mProgress = (ProgressBar) v.findViewById(com.android.internal.R.id.mediacontroller_progress);
- if (mProgress != null) {
- if (mProgress instanceof SeekBar) {
- SeekBar seeker = (SeekBar) mProgress;
- seeker.setOnSeekBarChangeListener(mSeekListener);
- }
- mProgress.setMax(1000);
- }
-
- mEndTime = (TextView) v.findViewById(com.android.internal.R.id.time);
- mCurrentTime = (TextView) v.findViewById(com.android.internal.R.id.time_current);
- mFormatBuilder = new StringBuilder();
- mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
-
- installPrevNextListeners();
- }
-
- /**
- * Show the controller on screen. It will go away
- * automatically after 3 seconds of inactivity.
- */
- public void show() {
- show(sDefaultTimeout);
- }
-
- /**
- * Show the controller on screen. It will go away
- * automatically after 'timeout' milliseconds of inactivity.
- * @param timeout The timeout in milliseconds. Use 0 to show
- * the controller until hide() is called.
- */
- public void show(int timeout) {
-
- if (!mShowing && mAnchor != null) {
- setProgress();
-
- int [] anchorpos = new int[2];
- mAnchor.getLocationOnScreen(anchorpos);
-
- WindowManager.LayoutParams p = new WindowManager.LayoutParams();
- p.gravity = Gravity.TOP;
- p.width = mAnchor.getWidth();
- p.height = LayoutParams.WRAP_CONTENT;
- p.x = 0;
- p.y = anchorpos[1] + mAnchor.getHeight() - p.height;
- p.format = PixelFormat.TRANSLUCENT;
- p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
- p.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- p.token = null;
- p.windowAnimations = 0; // android.R.style.DropDownAnimationDown;
- mWindowManager.addView(mDecor, p);
- mShowing = true;
- }
- updatePausePlay();
-
- // cause the progress bar to be updated even if mShowing
- // was already true. This happens, for example, if we're
- // paused with the progress bar showing the user hits play.
- mHandler.sendEmptyMessage(SHOW_PROGRESS);
-
- Message msg = mHandler.obtainMessage(FADE_OUT);
- if (timeout != 0) {
- mHandler.removeMessages(FADE_OUT);
- mHandler.sendMessageDelayed(msg, timeout);
- }
- }
-
- public boolean isShowing() {
- return mShowing;
- }
-
- /**
- * Remove the controller from the screen.
- */
- public void hide() {
- if (mAnchor == null)
- return;
-
- if (mShowing) {
- try {
- mHandler.removeMessages(SHOW_PROGRESS);
- mWindowManager.removeView(mDecor);
- } catch (IllegalArgumentException ex) {
- Log.w("MediaController", "already removed");
- }
- mShowing = false;
- }
- }
-
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- int pos;
- switch (msg.what) {
- case FADE_OUT:
- hide();
- break;
- case SHOW_PROGRESS:
- pos = setProgress();
- if (!mDragging && mShowing && mPlayer.isPlaying()) {
- msg = obtainMessage(SHOW_PROGRESS);
- sendMessageDelayed(msg, 1000 - (pos % 1000));
- }
- break;
- }
- }
- };
-
- private String stringForTime(int timeMs) {
- int totalSeconds = timeMs / 1000;
-
- int seconds = totalSeconds % 60;
- int minutes = (totalSeconds / 60) % 60;
- int hours = totalSeconds / 3600;
-
- mFormatBuilder.setLength(0);
- if (hours > 0) {
- return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
- } else {
- return mFormatter.format("%02d:%02d", minutes, seconds).toString();
- }
- }
-
- private int setProgress() {
- if (mPlayer == null || mDragging) {
- return 0;
- }
- int position = mPlayer.getCurrentPosition();
- int duration = mPlayer.getDuration();
- if (mProgress != null) {
- if (duration > 0) {
- // use long to avoid overflow
- long pos = 1000L * position / duration;
- mProgress.setProgress( (int) pos);
- }
- int percent = mPlayer.getBufferPercentage();
- mProgress.setSecondaryProgress(percent * 10);
- }
-
- if (mEndTime != null)
- mEndTime.setText(stringForTime(duration));
- if (mCurrentTime != null)
- mCurrentTime.setText(stringForTime(position));
-
- return position;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- show(sDefaultTimeout);
- return true;
- }
-
- @Override
- public boolean onTrackballEvent(MotionEvent ev) {
- show(sDefaultTimeout);
- return false;
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- int keyCode = event.getKeyCode();
- if (event.getRepeatCount() == 0 && event.isDown() && (
- keyCode == KeyEvent.KEYCODE_HEADSETHOOK ||
- keyCode == KeyEvent.KEYCODE_PLAYPAUSE ||
- keyCode == KeyEvent.KEYCODE_SPACE)) {
- doPauseResume();
- show(sDefaultTimeout);
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_STOP) {
- if (mPlayer.isPlaying()) {
- mPlayer.pause();
- updatePausePlay();
- }
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
- keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
- // don't show the controls for volume adjustment
- return super.dispatchKeyEvent(event);
- } else if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) {
- hide();
- } else {
- show(sDefaultTimeout);
- }
- return super.dispatchKeyEvent(event);
- }
-
- private View.OnClickListener mPauseListener = new View.OnClickListener() {
- public void onClick(View v) {
- doPauseResume();
- show(sDefaultTimeout);
- }
- };
-
- private void updatePausePlay() {
- if (mRoot == null)
- return;
-
- ImageButton button = (ImageButton) mRoot.findViewById(com.android.internal.R.id.pause);
- if (button == null)
- return;
-
- if (mPlayer.isPlaying()) {
- button.setImageResource(com.android.internal.R.drawable.ic_media_pause);
- } else {
- button.setImageResource(com.android.internal.R.drawable.ic_media_play);
- }
- }
-
- private void doPauseResume() {
- if (mPlayer.isPlaying()) {
- mPlayer.pause();
- } else {
- mPlayer.start();
- }
- updatePausePlay();
- }
-
- private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
- long duration;
- public void onStartTrackingTouch(SeekBar bar) {
- show(3600000);
- duration = mPlayer.getDuration();
- }
- public void onProgressChanged(SeekBar bar, int progress, boolean fromtouch) {
- if (fromtouch) {
- mDragging = true;
- long newposition = (duration * progress) / 1000L;
- mPlayer.seekTo( (int) newposition);
- if (mCurrentTime != null)
- mCurrentTime.setText(stringForTime( (int) newposition));
- }
- }
- public void onStopTrackingTouch(SeekBar bar) {
- mDragging = false;
- setProgress();
- updatePausePlay();
- show(sDefaultTimeout);
- }
- };
-
- @Override
- public void setEnabled(boolean enabled) {
- if (mPauseButton != null) {
- mPauseButton.setEnabled(enabled);
- }
- if (mFfwdButton != null) {
- mFfwdButton.setEnabled(enabled);
- }
- if (mRewButton != null) {
- mRewButton.setEnabled(enabled);
- }
- if (mNextButton != null) {
- mNextButton.setEnabled(enabled && mNextListener != null);
- }
- if (mPrevButton != null) {
- mPrevButton.setEnabled(enabled && mPrevListener != null);
- }
- if (mProgress != null) {
- mProgress.setEnabled(enabled);
- }
-
- super.setEnabled(enabled);
- }
-
- private View.OnClickListener mRewListener = new View.OnClickListener() {
- public void onClick(View v) {
- int pos = mPlayer.getCurrentPosition();
- pos -= 5000; // milliseconds
- mPlayer.seekTo(pos);
- setProgress();
-
- show(sDefaultTimeout);
- }
- };
-
- private View.OnClickListener mFfwdListener = new View.OnClickListener() {
- public void onClick(View v) {
- int pos = mPlayer.getCurrentPosition();
- pos += 15000; // milliseconds
- mPlayer.seekTo(pos);
- setProgress();
-
- show(sDefaultTimeout);
- }
- };
-
- private void installPrevNextListeners() {
- if (mNextButton != null) {
- mNextButton.setOnClickListener(mNextListener);
- mNextButton.setEnabled(mNextListener != null);
- }
-
- if (mPrevButton != null) {
- mPrevButton.setOnClickListener(mPrevListener);
- mPrevButton.setEnabled(mPrevListener != null);
- }
- }
-
- public void setPrevNextListeners(View.OnClickListener next, View.OnClickListener prev) {
- mNextListener = next;
- mPrevListener = prev;
- mListenersSet = true;
-
- if (mRoot != null) {
- installPrevNextListeners();
-
- if (mNextButton != null && !mFromXml) {
- mNextButton.setVisibility(View.VISIBLE);
- }
- if (mPrevButton != null && !mFromXml) {
- mPrevButton.setVisibility(View.VISIBLE);
- }
- }
- }
-
- public interface MediaPlayerControl {
- void start();
- void pause();
- int getDuration();
- int getCurrentPosition();
- void seekTo(int pos);
- boolean isPlaying();
- int getBufferPercentage();
- };
-}
diff --git a/core/java/android/widget/MultiAutoCompleteTextView.java b/core/java/android/widget/MultiAutoCompleteTextView.java
deleted file mode 100644
index 59a9310..0000000
--- a/core/java/android/widget/MultiAutoCompleteTextView.java
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.text.Editable;
-import android.text.Selection;
-import android.text.Spanned;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.TextUtils;
-import android.text.method.QwertyKeyListener;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.internal.R;
-
-/**
- * An editable text view, extending {@link AutoCompleteTextView}, that
- * can show completion suggestions for the substring of the text where
- * the user is typing instead of necessarily for the entire thing.
- * <p>
- * You must must provide a {@link Tokenizer} to distinguish the
- * various substrings.
- *
- * <p>The following code snippet shows how to create a text view which suggests
- * various countries names while the user is typing:</p>
- *
- * <pre class="prettyprint">
- * public class CountriesActivity extends Activity {
- * protected void onCreate(Bundle savedInstanceState) {
- * super.onCreate(savedInstanceState);
- * setContentView(R.layout.autocomplete_7);
- *
- * ArrayAdapter&lt;String&gt; adapter = new ArrayAdapter&lt;String&gt;(this,
- * android.R.layout.simple_dropdown_item_1line, COUNTRIES);
- * MultiAutoCompleteTextView textView = (MultiAutoCompleteTextView) findViewById(R.id.edit);
- * textView.setAdapter(adapter);
- * textView.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
- * }
- *
- * private static final String[] COUNTRIES = new String[] {
- * "Belgium", "France", "Italy", "Germany", "Spain"
- * };
- * }</pre>
- */
-
-public class MultiAutoCompleteTextView extends AutoCompleteTextView {
- private Tokenizer mTokenizer;
-
- public MultiAutoCompleteTextView(Context context) {
- this(context, null);
- }
-
- public MultiAutoCompleteTextView(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.autoCompleteTextViewStyle);
- }
-
- public MultiAutoCompleteTextView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- /* package */ void finishInit() { }
-
- /**
- * Sets the Tokenizer that will be used to determine the relevant
- * range of the text where the user is typing.
- */
- public void setTokenizer(Tokenizer t) {
- mTokenizer = t;
- }
-
- /**
- * Instead of filtering on the entire contents of the edit box,
- * this subclass method filters on the range from
- * {@link Tokenizer#findTokenStart} to {@link #getSelectionEnd}
- * if the length of that range meets or exceeds {@link #getThreshold}.
- */
- @Override
- protected void performFiltering(CharSequence text, int keyCode) {
- if (enoughToFilter()) {
- int end = getSelectionEnd();
- int start = mTokenizer.findTokenStart(text, end);
-
- performFiltering(text, start, end, keyCode);
- } else {
- dismissDropDown();
-
- Filter f = getFilter();
- if (f != null) {
- f.filter(null);
- }
- }
- }
-
- /**
- * Instead of filtering whenever the total length of the text
- * exceeds the threshhold, this subclass filters only when the
- * length of the range from
- * {@link Tokenizer#findTokenStart} to {@link #getSelectionEnd}
- * meets or exceeds {@link #getThreshold}.
- */
- @Override
- public boolean enoughToFilter() {
- Editable text = getText();
-
- int end = getSelectionEnd();
- if (end < 0) {
- return false;
- }
-
- int start = mTokenizer.findTokenStart(text, end);
-
- if (end - start >= getThreshold()) {
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Instead of validating the entire text, this subclass method validates
- * each token of the text individually. Empty tokens are removed.
- */
- @Override
- public void performValidation() {
- Validator v = getValidator();
-
- if (v == null) {
- return;
- }
-
- Editable e = getText();
- int i = getText().length();
- while (i > 0) {
- int start = mTokenizer.findTokenStart(e, i);
- int end = mTokenizer.findTokenEnd(e, start);
-
- CharSequence sub = e.subSequence(start, end);
- if (TextUtils.isEmpty(sub)) {
- e.replace(start, i, "");
- } else if (!v.isValid(sub)) {
- e.replace(start, i,
- mTokenizer.terminateToken(v.fixText(sub)));
- }
-
- i = start;
- }
- }
-
- /**
- * <p>Starts filtering the content of the drop down list. The filtering
- * pattern is the specified range of text from the edit box. Subclasses may
- * override this method to filter with a different pattern, for
- * instance a smaller substring of <code>text</code>.</p>
- */
- protected void performFiltering(CharSequence text, int start, int end,
- int keyCode) {
- getFilter().filter(text.subSequence(start, end), this);
- }
-
- /**
- * <p>Performs the text completion by replacing the range from
- * {@link Tokenizer#findTokenStart} to {@link #getSelectionEnd} by the
- * the result of passing <code>text</code> through
- * {@link Tokenizer#terminateToken}.
- * In addition, the replaced region will be marked as an AutoText
- * substition so that if the user immediately presses DEL, the
- * completion will be undone.
- * Subclasses may override this method to do some different
- * insertion of the content into the edit box.</p>
- *
- * @param text the selected suggestion in the drop down list
- */
- @Override
- protected void replaceText(CharSequence text) {
- int end = getSelectionEnd();
- int start = mTokenizer.findTokenStart(getText(), end);
-
- Editable editable = getText();
- String original = TextUtils.substring(editable, start, end);
-
- QwertyKeyListener.markAsReplaced(editable, start, end, original);
- editable.replace(start, end, mTokenizer.terminateToken(text));
- }
-
- public static interface Tokenizer {
- /**
- * Returns the start of the token that ends at offset
- * <code>cursor</code> within <code>text</code>.
- */
- public int findTokenStart(CharSequence text, int cursor);
-
- /**
- * Returns the end of the token (minus trailing punctuation)
- * that begins at offset <code>cursor</code> within <code>text</code>.
- */
- public int findTokenEnd(CharSequence text, int cursor);
-
- /**
- * Returns <code>text</code>, modified, if necessary, to ensure that
- * it ends with a token terminator (for example a space or comma).
- */
- public CharSequence terminateToken(CharSequence text);
- }
-
- /**
- * This simple Tokenizer can be used for lists where the items are
- * separated by a comma and one or more spaces.
- */
- public static class CommaTokenizer implements Tokenizer {
- public int findTokenStart(CharSequence text, int cursor) {
- int i = cursor;
-
- while (i > 0 && text.charAt(i - 1) != ',') {
- i--;
- }
- while (i < cursor && text.charAt(i) == ' ') {
- i++;
- }
-
- return i;
- }
-
- public int findTokenEnd(CharSequence text, int cursor) {
- int i = cursor;
- int len = text.length();
-
- while (i < len) {
- if (text.charAt(i) == ',') {
- return i;
- } else {
- i++;
- }
- }
-
- return len;
- }
-
- public CharSequence terminateToken(CharSequence text) {
- int i = text.length();
-
- while (i > 0 && text.charAt(i - 1) == ' ') {
- i--;
- }
-
- if (i > 0 && text.charAt(i - 1) == ',') {
- return text;
- } else {
- if (text instanceof Spanned) {
- SpannableString sp = new SpannableString(text + ", ");
- TextUtils.copySpansFrom((Spanned) text, 0, text.length(),
- Object.class, sp, 0);
- return sp;
- } else {
- return text + ", ";
- }
- }
- }
- }
-}
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
deleted file mode 100644
index 4a5cea1..0000000
--- a/core/java/android/widget/PopupWindow.java
+++ /dev/null
@@ -1,1218 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import com.android.internal.R;
-
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.WindowManager;
-import android.view.Gravity;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.view.ViewTreeObserver.OnScrollChangedListener;
-import android.view.View.OnTouchListener;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.IBinder;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-
-import java.lang.ref.WeakReference;
-
-/**
- * <p>A popup window that can be used to display an arbitrary view. The popup
- * windows is a floating container that appears on top of the current
- * activity.</p>
- *
- * @see android.widget.AutoCompleteTextView
- * @see android.widget.Spinner
- */
-public class PopupWindow {
- /**
- * Mode for {@link #setInputMethodMode(int): the requirements for the
- * input method should be based on the focusability of the popup. That is
- * if it is focusable than it needs to work with the input method, else
- * it doesn't.
- */
- public static final int INPUT_METHOD_FROM_FOCUSABLE = 0;
-
- /**
- * Mode for {@link #setInputMethodMode(int): this popup always needs to
- * work with an input method, regardless of whether it is focusable. This
- * means that it will always be displayed so that the user can also operate
- * the input method while it is shown.
- */
-
- public static final int INPUT_METHOD_NEEDED = 1;
-
- /**
- * Mode for {@link #setInputMethodMode(int): this popup never needs to
- * work with an input method, regardless of whether it is focusable. This
- * means that it will always be displayed to use as much space on the
- * screen as needed, regardless of whether this covers the input method.
- */
- public static final int INPUT_METHOD_NOT_NEEDED = 2;
-
- private final Context mContext;
- private final WindowManager mWindowManager;
-
- private boolean mIsShowing;
- private boolean mIsDropdown;
-
- private View mContentView;
- private View mPopupView;
- private boolean mFocusable;
- private int mInputMethodMode = INPUT_METHOD_FROM_FOCUSABLE;
- private boolean mTouchable = true;
- private boolean mOutsideTouchable = false;
- private boolean mClippingEnabled = true;
-
- private OnTouchListener mTouchInterceptor;
-
- private int mWidthMode;
- private int mWidth;
- private int mLastWidth;
- private int mHeightMode;
- private int mHeight;
- private int mLastHeight;
-
- private int mPopupWidth;
- private int mPopupHeight;
-
- private int[] mDrawingLocation = new int[2];
- private int[] mScreenLocation = new int[2];
- private Rect mTempRect = new Rect();
-
- private Drawable mBackground;
-
- private boolean mAboveAnchor;
-
- private OnDismissListener mOnDismissListener;
- private boolean mIgnoreCheekPress = false;
-
- private int mAnimationStyle = -1;
-
- private static final int[] ABOVE_ANCHOR_STATE_SET = new int[] {
- com.android.internal.R.attr.state_above_anchor
- };
-
- private WeakReference<View> mAnchor;
- private OnScrollChangedListener mOnScrollChangedListener =
- new OnScrollChangedListener() {
- public void onScrollChanged() {
- View anchor = mAnchor.get();
- if (anchor != null && mPopupView != null) {
- WindowManager.LayoutParams p = (WindowManager.LayoutParams)
- mPopupView.getLayoutParams();
-
- mAboveAnchor = findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff);
- update(p.x, p.y, -1, -1, true);
- }
- }
- };
- private int mAnchorXoff, mAnchorYoff;
-
- /**
- * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
- *
- * <p>The popup does provide a background.</p>
- */
- public PopupWindow(Context context) {
- this(context, null);
- }
-
- /**
- * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
- *
- * <p>The popup does provide a background.</p>
- */
- public PopupWindow(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.popupWindowStyle);
- }
-
- /**
- * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
- *
- * <p>The popup does provide a background.</p>
- */
- public PopupWindow(Context context, AttributeSet attrs, int defStyle) {
- mContext = context;
- mWindowManager = (WindowManager)context.getSystemService(
- Context.WINDOW_SERVICE);
-
- TypedArray a =
- context.obtainStyledAttributes(
- attrs, com.android.internal.R.styleable.PopupWindow, defStyle, 0);
-
- mBackground = a.getDrawable(R.styleable.PopupWindow_popupBackground);
-
- a.recycle();
- }
-
- /**
- * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
- *
- * <p>The popup does not provide any background. This should be handled
- * by the content view.</p>
- */
- public PopupWindow() {
- this(null, 0, 0);
- }
-
- /**
- * <p>Create a new non focusable popup window which can display the
- * <tt>contentView</tt>. The dimension of the window are (0,0).</p>
- *
- * <p>The popup does not provide any background. This should be handled
- * by the content view.</p>
- *
- * @param contentView the popup's content
- */
- public PopupWindow(View contentView) {
- this(contentView, 0, 0);
- }
-
- /**
- * <p>Create a new empty, non focusable popup window. The dimension of the
- * window must be passed to this constructor.</p>
- *
- * <p>The popup does not provide any background. This should be handled
- * by the content view.</p>
- *
- * @param width the popup's width
- * @param height the popup's height
- */
- public PopupWindow(int width, int height) {
- this(null, width, height);
- }
-
- /**
- * <p>Create a new non focusable popup window which can display the
- * <tt>contentView</tt>. The dimension of the window must be passed to
- * this constructor.</p>
- *
- * <p>The popup does not provide any background. This should be handled
- * by the content view.</p>
- *
- * @param contentView the popup's content
- * @param width the popup's width
- * @param height the popup's height
- */
- public PopupWindow(View contentView, int width, int height) {
- this(contentView, width, height, false);
- }
-
- /**
- * <p>Create a new popup window which can display the <tt>contentView</tt>.
- * The dimension of the window must be passed to this constructor.</p>
- *
- * <p>The popup does not provide any background. This should be handled
- * by the content view.</p>
- *
- * @param contentView the popup's content
- * @param width the popup's width
- * @param height the popup's height
- * @param focusable true if the popup can be focused, false otherwise
- */
- public PopupWindow(View contentView, int width, int height,
- boolean focusable) {
- mContext = contentView.getContext();
- mWindowManager = (WindowManager)mContext.getSystemService(
- Context.WINDOW_SERVICE);
- setContentView(contentView);
- setWidth(width);
- setHeight(height);
- setFocusable(focusable);
- }
-
- /**
- * <p>Return the drawable used as the popup window's background.</p>
- *
- * @return the background drawable or null
- */
- public Drawable getBackground() {
- return mBackground;
- }
-
- /**
- * <p>Change the background drawable for this popup window. The background
- * can be set to null.</p>
- *
- * @param background the popup's background
- */
- public void setBackgroundDrawable(Drawable background) {
- mBackground = background;
- }
-
- /**
- * <p>Return the animation style to use the popup appears and disappears</p>
- *
- * @return the animation style to use the popup appears and disappears
- */
- public int getAnimationStyle() {
- return mAnimationStyle;
- }
-
- /**
- * Set the flag on popup to ignore cheek press eventt; by default this flag
- * is set to false
- * which means the pop wont ignore cheek press dispatch events.
- *
- * <p>If the popup is showing, calling this method will take effect only
- * the next time the popup is shown or through a manual call to one of
- * the {@link #update()} methods.</p>
- *
- * @see #update()
- */
- public void setIgnoreCheekPress() {
- mIgnoreCheekPress = true;
- }
-
-
- /**
- * <p>Change the animation style resource for this popup.</p>
- *
- * <p>If the popup is showing, calling this method will take effect only
- * the next time the popup is shown or through a manual call to one of
- * the {@link #update()} methods.</p>
- *
- * @param animationStyle animation style to use when the popup appears
- * and disappears. Set to -1 for the default animation, 0 for no
- * animation, or a resource identifier for an explicit animation.
- *
- * @see #update()
- */
- public void setAnimationStyle(int animationStyle) {
- mAnimationStyle = animationStyle;
- }
-
- /**
- * <p>Return the view used as the content of the popup window.</p>
- *
- * @return a {@link android.view.View} representing the popup's content
- *
- * @see #setContentView(android.view.View)
- */
- public View getContentView() {
- return mContentView;
- }
-
- /**
- * <p>Change the popup's content. The content is represented by an instance
- * of {@link android.view.View}.</p>
- *
- * <p>This method has no effect if called when the popup is showing. To
- * apply it while a popup is showing, call </p>
- *
- * @param contentView the new content for the popup
- *
- * @see #getContentView()
- * @see #isShowing()
- */
- public void setContentView(View contentView) {
- if (isShowing()) {
- return;
- }
-
- mContentView = contentView;
- }
-
- /**
- * Set a callback for all touch events being dispatched to the popup
- * window.
- */
- public void setTouchInterceptor(OnTouchListener l) {
- mTouchInterceptor = l;
- }
-
- /**
- * <p>Indicate whether the popup window can grab the focus.</p>
- *
- * @return true if the popup is focusable, false otherwise
- *
- * @see #setFocusable(boolean)
- */
- public boolean isFocusable() {
- return mFocusable;
- }
-
- /**
- * <p>Changes the focusability of the popup window. When focusable, the
- * window will grab the focus from the current focused widget if the popup
- * contains a focusable {@link android.view.View}. By default a popup
- * window is not focusable.</p>
- *
- * <p>If the popup is showing, calling this method will take effect only
- * the next time the popup is shown or through a manual call to one of
- * the {@link #update()} methods.</p>
- *
- * @param focusable true if the popup should grab focus, false otherwise.
- *
- * @see #isFocusable()
- * @see #isShowing()
- * @see #update()
- */
- public void setFocusable(boolean focusable) {
- mFocusable = focusable;
- }
-
- /**
- * Return the current value in {@link #setInputMethodMode(int)}.
- *
- * @see #setInputMethodMode(int)
- */
- public int getInputMethodMode() {
- return mInputMethodMode;
-
- }
-
- /**
- * Control how the popup operates with an input method: one of
- * {@link #INPUT_METHOD_FROM_FOCUSABLE}, {@link #INPUT_METHOD_NEEDED},
- * or {@link #INPUT_METHOD_NOT_NEEDED}.
- *
- * <p>If the popup is showing, calling this method will take effect only
- * the next time the popup is shown or through a manual call to one of
- * the {@link #update()} methods.</p>
- *
- * @see #getInputMethodMode()
- * @see #update()
- */
- public void setInputMethodMode(int mode) {
- mInputMethodMode = mode;
- }
-
- /**
- * <p>Indicates whether the popup window receives touch events.</p>
- *
- * @return true if the popup is touchable, false otherwise
- *
- * @see #setTouchable(boolean)
- */
- public boolean isTouchable() {
- return mTouchable;
- }
-
- /**
- * <p>Changes the touchability of the popup window. When touchable, the
- * window will receive touch events, otherwise touch events will go to the
- * window below it. By default the window is touchable.</p>
- *
- * <p>If the popup is showing, calling this method will take effect only
- * the next time the popup is shown or through a manual call to one of
- * the {@link #update()} methods.</p>
- *
- * @param touchable true if the popup should receive touch events, false otherwise
- *
- * @see #isTouchable()
- * @see #isShowing()
- * @see #update()
- */
- public void setTouchable(boolean touchable) {
- mTouchable = touchable;
- }
-
- /**
- * <p>Indicates whether the popup window will be informed of touch events
- * outside of its window.</p>
- *
- * @return true if the popup is outside touchable, false otherwise
- *
- * @see #setOutsideTouchable(boolean)
- */
- public boolean isOutsideTouchable() {
- return mOutsideTouchable;
- }
-
- /**
- * <p>Controls whether the pop-up will be informed of touch events outside
- * of its window. This only makes sense for pop-ups that are touchable
- * but not focusable, which means touches outside of the window will
- * be delivered to the window behind. The default is false.</p>
- *
- * <p>If the popup is showing, calling this method will take effect only
- * the next time the popup is shown or through a manual call to one of
- * the {@link #update()} methods.</p>
- *
- * @param touchable true if the popup should receive outside
- * touch events, false otherwise
- *
- * @see #isOutsideTouchable()
- * @see #isShowing()
- * @see #update()
- */
- public void setOutsideTouchable(boolean touchable) {
- mOutsideTouchable = touchable;
- }
-
- /**
- * <p>Indicates whether clipping of the popup window is enabled.</p>
- *
- * @return true if the clipping is enabled, false otherwise
- *
- * @see #setClippingEnabled(boolean)
- */
- public boolean isClippingEnabled() {
- return mClippingEnabled;
- }
-
- /**
- * <p>Allows the popup window to extend beyond the bounds of the screen. By default the
- * window is clipped to the screen boundaries. Setting this to false will allow windows to be
- * accurately positioned.</p>
- *
- * <p>If the popup is showing, calling this method will take effect only
- * the next time the popup is shown or through a manual call to one of
- * the {@link #update()} methods.</p>
- *
- * @param enabled false if the window should be allowed to extend outside of the screen
- * @see #isShowing()
- * @see #isClippingEnabled()
- * @see #update()
- */
- public void setClippingEnabled(boolean enabled) {
- mClippingEnabled = enabled;
- }
-
- /**
- * <p>Change the width and height measure specs that are given to the
- * window manager by the popup. By default these are 0, meaning that
- * the current width or height is requested as an explicit size from
- * the window manager. You can supply
- * {@link ViewGroup.LayoutParams#WRAP_CONTENT} or
- * {@link ViewGroup.LayoutParams#FILL_PARENT} to have that measure
- * spec supplied instead, replacing the absolute width and height that
- * has been set in the popup.</p>
- *
- * <p>If the popup is showing, calling this method will take effect only
- * the next time the popup is shown.</p>
- *
- * @param widthSpec an explicit width measure spec mode, either
- * {@link ViewGroup.LayoutParams#WRAP_CONTENT},
- * {@link ViewGroup.LayoutParams#FILL_PARENT}, or 0 to use the absolute
- * width.
- * @param heightSpec an explicit height measure spec mode, either
- * {@link ViewGroup.LayoutParams#WRAP_CONTENT},
- * {@link ViewGroup.LayoutParams#FILL_PARENT}, or 0 to use the absolute
- * height.
- */
- public void setWindowLayoutMode(int widthSpec, int heightSpec) {
- mWidthMode = widthSpec;
- mHeightMode = heightSpec;
- }
-
- /**
- * <p>Return this popup's height MeasureSpec</p>
- *
- * @return the height MeasureSpec of the popup
- *
- * @see #setHeight(int)
- */
- public int getHeight() {
- return mHeight;
- }
-
- /**
- * <p>Change the popup's height MeasureSpec</p>
- *
- * <p>If the popup is showing, calling this method will take effect only
- * the next time the popup is shown.</p>
- *
- * @param height the height MeasureSpec of the popup
- *
- * @see #getHeight()
- * @see #isShowing()
- */
- public void setHeight(int height) {
- mHeight = height;
- }
-
- /**
- * <p>Return this popup's width MeasureSpec</p>
- *
- * @return the width MeasureSpec of the popup
- *
- * @see #setWidth(int)
- */
- public int getWidth() {
- return mWidth;
- }
-
- /**
- * <p>Change the popup's width MeasureSpec</p>
- *
- * <p>If the popup is showing, calling this method will take effect only
- * the next time the popup is shown.</p>
- *
- * @param width the width MeasureSpec of the popup
- *
- * @see #getWidth()
- * @see #isShowing()
- */
- public void setWidth(int width) {
- mWidth = width;
- }
-
- /**
- * <p>Indicate whether this popup window is showing on screen.</p>
- *
- * @return true if the popup is showing, false otherwise
- */
- public boolean isShowing() {
- return mIsShowing;
- }
-
- /**
- * <p>
- * Display the content view in a popup window at the specified location. If the popup window
- * cannot fit on screen, it will be clipped. See {@link android.view.WindowManager.LayoutParams}
- * for more information on how gravity and the x and y parameters are related. Specifying
- * a gravity of {@link android.view.Gravity#NO_GRAVITY} is similar to specifying
- * <code>Gravity.LEFT | Gravity.TOP</code>.
- * </p>
- *
- * @param parent a parent view to get the {@link android.view.View#getWindowToken()} token from
- * @param gravity the gravity which controls the placement of the popup window
- * @param x the popup's x location offset
- * @param y the popup's y location offset
- */
- public void showAtLocation(View parent, int gravity, int x, int y) {
- if (isShowing() || mContentView == null) {
- return;
- }
-
- unregisterForScrollChanged();
-
- mIsShowing = true;
- mIsDropdown = false;
-
- WindowManager.LayoutParams p = createPopupLayout(parent.getWindowToken());
- p.windowAnimations = computeAnimationResource();
-
- preparePopup(p);
- if (gravity == Gravity.NO_GRAVITY) {
- gravity = Gravity.TOP | Gravity.LEFT;
- }
- p.gravity = gravity;
- p.x = x;
- p.y = y;
- invokePopup(p);
- }
-
- /**
- * <p>Display the content view in a popup window anchored to the bottom-left
- * corner of the anchor view. If there is not enough room on screen to show
- * the popup in its entirety, this method tries to find a parent scroll
- * view to scroll. If no parent scroll view can be scrolled, the bottom-left
- * corner of the popup is pinned at the top left corner of the anchor view.</p>
- *
- * @param anchor the view on which to pin the popup window
- *
- * @see #dismiss()
- */
- public void showAsDropDown(View anchor) {
- showAsDropDown(anchor, 0, 0);
- }
-
- /**
- * <p>Display the content view in a popup window anchored to the bottom-left
- * corner of the anchor view offset by the specified x and y coordinates.
- * If there is not enough room on screen to show
- * the popup in its entirety, this method tries to find a parent scroll
- * view to scroll. If no parent scroll view can be scrolled, the bottom-left
- * corner of the popup is pinned at the top left corner of the anchor view.</p>
- * <p>If the view later scrolls to move <code>anchor</code> to a different
- * location, the popup will be moved correspondingly.</p>
- *
- * @param anchor the view on which to pin the popup window
- *
- * @see #dismiss()
- */
- public void showAsDropDown(View anchor, int xoff, int yoff) {
- if (isShowing() || mContentView == null) {
- return;
- }
-
- registerForScrollChanged(anchor, xoff, yoff);
-
- mIsShowing = true;
- mIsDropdown = true;
-
- WindowManager.LayoutParams p = createPopupLayout(anchor.getWindowToken());
- preparePopup(p);
- mAboveAnchor = findDropDownPosition(anchor, p, xoff, yoff);
-
- if (mBackground != null) {
- mPopupView.refreshDrawableState();
- }
-
- if (mHeightMode < 0) p.height = mLastHeight = mHeightMode;
- if (mWidthMode < 0) p.width = mLastWidth = mWidthMode;
-
- p.windowAnimations = computeAnimationResource();
-
- invokePopup(p);
- }
-
- /**
- * Indicates whether the popup is showing above (the y coordinate of the popup's bottom
- * is less than the y coordinate of the anchor) or below the anchor view (the y coordinate
- * of the popup is greater than y coordinate of the anchor's bottom).
- *
- * The value returned
- * by this method is meaningful only after {@link #showAsDropDown(android.view.View)}
- * or {@link #showAsDropDown(android.view.View, int, int)} was invoked.
- *
- * @return True if this popup is showing above the anchor view, false otherwise.
- */
- public boolean isAboveAnchor() {
- return mAboveAnchor;
- }
-
- /**
- * <p>Prepare the popup by embedding in into a new ViewGroup if the
- * background drawable is not null. If embedding is required, the layout
- * parameters' height is mnodified to take into account the background's
- * padding.</p>
- *
- * @param p the layout parameters of the popup's content view
- */
- private void preparePopup(WindowManager.LayoutParams p) {
- if (mBackground != null) {
- // when a background is available, we embed the content view
- // within another view that owns the background drawable
- PopupViewContainer popupViewContainer = new PopupViewContainer(mContext);
- PopupViewContainer.LayoutParams listParams = new PopupViewContainer.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.FILL_PARENT
- );
- popupViewContainer.setBackgroundDrawable(mBackground);
- popupViewContainer.addView(mContentView, listParams);
-
- mPopupView = popupViewContainer;
- } else {
- mPopupView = mContentView;
- }
- mPopupWidth = p.width;
- mPopupHeight = p.height;
- }
-
- /**
- * <p>Invoke the popup window by adding the content view to the window
- * manager.</p>
- *
- * <p>The content view must be non-null when this method is invoked.</p>
- *
- * @param p the layout parameters of the popup's content view
- */
- private void invokePopup(WindowManager.LayoutParams p) {
- mWindowManager.addView(mPopupView, p);
- }
-
- /**
- * <p>Generate the layout parameters for the popup window.</p>
- *
- * @param token the window token used to bind the popup's window
- *
- * @return the layout parameters to pass to the window manager
- */
- private WindowManager.LayoutParams createPopupLayout(IBinder token) {
- // generates the layout parameters for the drop down
- // we want a fixed size view located at the bottom left of the anchor
- WindowManager.LayoutParams p = new WindowManager.LayoutParams();
- // these gravity settings put the view at the top left corner of the
- // screen. The view is then positioned to the appropriate location
- // by setting the x and y offsets to match the anchor's bottom
- // left corner
- p.gravity = Gravity.LEFT | Gravity.TOP;
- p.width = mLastWidth = mWidth;
- p.height = mLastHeight = mHeight;
- if (mBackground != null) {
- p.format = mBackground.getOpacity();
- } else {
- p.format = PixelFormat.TRANSLUCENT;
- }
- p.flags = computeFlags(p.flags);
- p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
- p.token = token;
- p.setTitle("PopupWindow:" + Integer.toHexString(hashCode()));
-
- return p;
- }
-
- private int computeFlags(int curFlags) {
- curFlags &= ~(
- WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES |
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
- WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
- WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
- WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
- WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
- if(mIgnoreCheekPress) {
- curFlags |= WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
- }
- if (!mFocusable) {
- curFlags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- if (mInputMethodMode == INPUT_METHOD_NEEDED) {
- curFlags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- }
- } else if (mInputMethodMode == INPUT_METHOD_NOT_NEEDED) {
- curFlags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- }
- if (!mTouchable) {
- curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
- }
- if (mTouchable) {
- curFlags |= WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
- }
- if (!mClippingEnabled) {
- curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
- }
- return curFlags;
- }
-
- private int computeAnimationResource() {
- if (mAnimationStyle == -1) {
- if (mIsDropdown) {
- return mAboveAnchor
- ? com.android.internal.R.style.Animation_DropDownUp
- : com.android.internal.R.style.Animation_DropDownDown;
- }
- return 0;
- }
- return mAnimationStyle;
- }
-
- /**
- * <p>Positions the popup window on screen. When the popup window is too
- * tall to fit under the anchor, a parent scroll view is seeked and scrolled
- * up to reclaim space. If scrolling is not possible or not enough, the
- * popup window gets moved on top of the anchor.</p>
- *
- * <p>The height must have been set on the layout parameters prior to
- * calling this method.</p>
- *
- * @param anchor the view on which the popup window must be anchored
- * @param p the layout parameters used to display the drop down
- *
- * @return true if the popup is translated upwards to fit on screen
- */
- private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p,
- int xoff, int yoff) {
-
- anchor.getLocationInWindow(mDrawingLocation);
- p.x = mDrawingLocation[0] + xoff;
- p.y = mDrawingLocation[1] + anchor.getMeasuredHeight() + yoff;
-
- boolean onTop = false;
-
- p.gravity = Gravity.LEFT | Gravity.TOP;
-
- anchor.getLocationOnScreen(mScreenLocation);
- final Rect displayFrame = new Rect();
- anchor.getWindowVisibleDisplayFrame(displayFrame);
-
- final View root = anchor.getRootView();
- if (p.y + mPopupHeight > displayFrame.bottom || p.x + mPopupWidth - root.getWidth() > 0) {
- // if the drop down disappears at the bottom of the screen. we try to
- // scroll a parent scrollview or move the drop down back up on top of
- // the edit box
- int scrollX = anchor.getScrollX();
- int scrollY = anchor.getScrollY();
- Rect r = new Rect(scrollX, scrollY, scrollX + mPopupWidth,
- scrollY + mPopupHeight + anchor.getMeasuredHeight());
- anchor.requestRectangleOnScreen(r, true);
-
- // now we re-evaluate the space available, and decide from that
- // whether the pop-up will go above or below the anchor.
- anchor.getLocationInWindow(mDrawingLocation);
- p.x = mDrawingLocation[0] + xoff;
- p.y = mDrawingLocation[1] + anchor.getMeasuredHeight() + yoff;
-
- // determine whether there is more space above or below the anchor
- anchor.getLocationOnScreen(mScreenLocation);
-
- onTop = (displayFrame.bottom - mScreenLocation[1] - anchor.getMeasuredHeight() - yoff) <
- (mScreenLocation[1] - yoff - displayFrame.top);
- if (onTop) {
- p.gravity = Gravity.LEFT | Gravity.BOTTOM;
- p.y = root.getHeight() - mDrawingLocation[1] + yoff;
- } else {
- p.y = mDrawingLocation[1] + anchor.getMeasuredHeight() + yoff;
- }
- }
-
- p.gravity |= Gravity.DISPLAY_CLIP_VERTICAL;
-
- return onTop;
- }
-
- /**
- * Returns the maximum height that is available for the popup to be
- * completely shown. It is recommended that this height be the maximum for
- * the popup's height, otherwise it is possible that the popup will be
- * clipped.
- *
- * @param anchor The view on which the popup window must be anchored.
- * @return The maximum available height for the popup to be completely
- * shown.
- */
- public int getMaxAvailableHeight(View anchor) {
- return getMaxAvailableHeight(anchor, 0);
- }
-
- /**
- * Returns the maximum height that is available for the popup to be
- * completely shown. It is recommended that this height be the maximum for
- * the popup's height, otherwise it is possible that the popup will be
- * clipped.
- *
- * @param anchor The view on which the popup window must be anchored.
- * @param yOffset y offset from the view's bottom edge
- * @return The maximum available height for the popup to be completely
- * shown.
- */
- public int getMaxAvailableHeight(View anchor, int yOffset) {
- final Rect displayFrame = new Rect();
- anchor.getWindowVisibleDisplayFrame(displayFrame);
-
- final int[] anchorPos = mDrawingLocation;
- anchor.getLocationOnScreen(anchorPos);
-
- final int distanceToBottom = displayFrame.bottom -
- (anchorPos[1] + anchor.getHeight()) - yOffset;
- final int distanceToTop = anchorPos[1] - displayFrame.top + yOffset;
-
- // anchorPos[1] is distance from anchor to top of screen
- int returnedHeight = Math.max(distanceToBottom, distanceToTop);
- if (mBackground != null) {
- mBackground.getPadding(mTempRect);
- returnedHeight -= mTempRect.top + mTempRect.bottom;
- }
-
- return returnedHeight;
- }
-
- /**
- * <p>Dispose of the popup window. This method can be invoked only after
- * {@link #showAsDropDown(android.view.View)} has been executed. Failing that, calling
- * this method will have no effect.</p>
- *
- * @see #showAsDropDown(android.view.View)
- */
- public void dismiss() {
- if (isShowing() && mPopupView != null) {
- unregisterForScrollChanged();
-
- mWindowManager.removeView(mPopupView);
- if (mPopupView != mContentView && mPopupView instanceof ViewGroup) {
- ((ViewGroup) mPopupView).removeView(mContentView);
- }
- mPopupView = null;
- mIsShowing = false;
-
- if (mOnDismissListener != null) {
- mOnDismissListener.onDismiss();
- }
- }
- }
-
- /**
- * Sets the listener to be called when the window is dismissed.
- *
- * @param onDismissListener The listener.
- */
- public void setOnDismissListener(OnDismissListener onDismissListener) {
- mOnDismissListener = onDismissListener;
- }
-
- /**
- * Updates the state of the popup window, if it is currently being displayed,
- * from the currently set state. This include:
- * {@link #setClippingEnabled(boolean)}, {@link #setFocusable(boolean)},
- * {@link #setIgnoreCheekPress()}, {@link #setInputMethodMode(int)},
- * {@link #setTouchable(boolean)}, and {@link #setAnimationStyle(int)}.
- */
- public void update() {
- if (!isShowing() || mContentView == null) {
- return;
- }
-
- WindowManager.LayoutParams p = (WindowManager.LayoutParams)
- mPopupView.getLayoutParams();
-
- boolean update = false;
-
- final int newAnim = computeAnimationResource();
- if (newAnim != p.windowAnimations) {
- p.windowAnimations = newAnim;
- update = true;
- }
-
- final int newFlags = computeFlags(p.flags);
- if (newFlags != p.flags) {
- p.flags = newFlags;
- update = true;
- }
-
- if (update) {
- mWindowManager.updateViewLayout(mPopupView, p);
- }
- }
-
- /**
- * <p>Updates the position and the dimension of the popup window. Width and
- * height can be set to -1 to update location only. Calling this function
- * also updates the window with the current popup state as
- * described for {@link #update()}.</p>
- *
- * @param x the new x location
- * @param y the new y location
- * @param width the new width, can be -1 to ignore
- * @param height the new height, can be -1 to ignore
- */
- public void update(int x, int y, int width, int height) {
- update(x, y, width, height, false);
- }
-
- /**
- * <p>Updates the position and the dimension of the popup window. Width and
- * height can be set to -1 to update location only. Calling this function
- * also updates the window with the current popup state as
- * described for {@link #update()}.</p>
- *
- * @param x the new x location
- * @param y the new y location
- * @param width the new width, can be -1 to ignore
- * @param height the new height, can be -1 to ignore
- * @param force reposition the window even if the specified position
- * already seems to correspond to the LayoutParams
- *
- * @hide pending API council approval
- */
- public void update(int x, int y, int width, int height, boolean force) {
- if (width != -1) {
- mLastWidth = width;
- setWidth(width);
- }
-
- if (height != -1) {
- mLastHeight = height;
- setHeight(height);
- }
-
- if (!isShowing() || mContentView == null) {
- return;
- }
-
- WindowManager.LayoutParams p = (WindowManager.LayoutParams)
- mPopupView.getLayoutParams();
-
- boolean update = force;
-
- final int finalWidth = mWidthMode < 0 ? mWidthMode : mLastWidth;
- if (width != -1 && p.width != finalWidth) {
- p.width = mLastWidth = finalWidth;
- update = true;
- }
-
- final int finalHeight = mHeightMode < 0 ? mHeightMode : mLastHeight;
- if (height != -1 && p.height != finalHeight) {
- p.height = mLastHeight = finalHeight;
- update = true;
- }
-
- if (p.x != x) {
- p.x = x;
- update = true;
- }
-
- if (p.y != y) {
- p.y = y;
- update = true;
- }
-
- final int newAnim = computeAnimationResource();
- if (newAnim != p.windowAnimations) {
- p.windowAnimations = newAnim;
- update = true;
- }
-
- final int newFlags = computeFlags(p.flags);
- if (newFlags != p.flags) {
- p.flags = newFlags;
- update = true;
- }
-
- if (update) {
- mWindowManager.updateViewLayout(mPopupView, p);
- }
- }
-
- /**
- * <p>Updates the position and the dimension of the popup window. Width and
- * height can be set to -1 to update location only. Calling this function
- * also updates the window with the current popup state as
- * described for {@link #update()}.</p>
- *
- * @param anchor the popup's anchor view
- * @param width the new width, can be -1 to ignore
- * @param height the new height, can be -1 to ignore
- */
- public void update(View anchor, int width, int height) {
- update(anchor, 0, 0, width, height);
- }
-
- /**
- * <p>Updates the position and the dimension of the popup window. Width and
- * height can be set to -1 to update location only. Calling this function
- * also updates the window with the current popup state as
- * described for {@link #update()}.</p>
- * <p>If the view later scrolls to move <code>anchor</code> to a different
- * location, the popup will be moved correspondingly.</p>
- *
- * @param anchor the popup's anchor view
- * @param xoff x offset from the view's left edge
- * @param yoff y offset from the view's bottom edge
- * @param width the new width, can be -1 to ignore
- * @param height the new height, can be -1 to ignore
- */
- public void update(View anchor, int xoff, int yoff, int width, int height) {
- if (!isShowing() || mContentView == null) {
- return;
- }
-
- WeakReference<View> oldAnchor = mAnchor;
- if (oldAnchor == null || oldAnchor.get() != anchor ||
- mAnchorXoff != xoff || mAnchorYoff != yoff) {
- registerForScrollChanged(anchor, xoff, yoff);
- }
-
- WindowManager.LayoutParams p = (WindowManager.LayoutParams)
- mPopupView.getLayoutParams();
-
- if (width == -1) {
- width = mPopupWidth;
- } else {
- mPopupWidth = width;
- }
- if (height == -1) {
- height = mPopupHeight;
- } else {
- mPopupHeight = height;
- }
-
- mAboveAnchor = findDropDownPosition(anchor, p, xoff, yoff);
- update(p.x, p.y, width, height);
- }
-
- /**
- * Listener that is called when this popup window is dismissed.
- */
- public interface OnDismissListener {
- /**
- * Called when this popup window is dismissed.
- */
- public void onDismiss();
- }
-
- private void unregisterForScrollChanged() {
- WeakReference<View> anchorRef = mAnchor;
- View anchor = null;
- if (anchorRef != null) {
- anchor = anchorRef.get();
- }
- if (anchor != null) {
- ViewTreeObserver vto = anchor.getViewTreeObserver();
- vto.removeOnScrollChangedListener(mOnScrollChangedListener);
- }
- mAnchor = null;
- }
-
- private void registerForScrollChanged(View anchor, int xoff, int yoff) {
- unregisterForScrollChanged();
-
- mAnchor = new WeakReference<View>(anchor);
- ViewTreeObserver vto = anchor.getViewTreeObserver();
- if (vto != null) {
- vto.addOnScrollChangedListener(mOnScrollChangedListener);
- }
-
- mAnchorXoff = xoff;
- mAnchorYoff = yoff;
- }
-
- private class PopupViewContainer extends FrameLayout {
-
- public PopupViewContainer(Context context) {
- super(context);
- }
-
- @Override
- protected int[] onCreateDrawableState(int extraSpace) {
- if (mAboveAnchor) {
- // 1 more needed for the above anchor state
- final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
- View.mergeDrawableStates(drawableState, ABOVE_ANCHOR_STATE_SET);
- return drawableState;
- } else {
- return super.onCreateDrawableState(extraSpace);
- }
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
- dismiss();
- return true;
- } else {
- return super.dispatchKeyEvent(event);
- }
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- if (mTouchInterceptor != null && mTouchInterceptor.onTouch(this, ev)) {
- return true;
- }
- return super.dispatchTouchEvent(ev);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- final int x = (int) event.getX();
- final int y = (int) event.getY();
-
- if ((event.getAction() == MotionEvent.ACTION_DOWN)
- && ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) {
- dismiss();
- return true;
- } else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
- dismiss();
- return true;
- } else {
- return super.onTouchEvent(event);
- }
- }
-
- }
-
-}
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
deleted file mode 100644
index dd2570a..0000000
--- a/core/java/android/widget/ProgressBar.java
+++ /dev/null
@@ -1,918 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
-import android.graphics.Canvas;
-import android.graphics.Shader;
-import android.graphics.Rect;
-import android.graphics.drawable.AnimationDrawable;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ClipDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.StateListDrawable;
-import android.graphics.drawable.shapes.RoundRectShape;
-import android.graphics.drawable.shapes.Shape;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.View;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
-import android.view.animation.Transformation;
-import android.widget.RemoteViews.RemoteView;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.SystemClock;
-
-import com.android.internal.R;
-
-
-/**
- * <p>
- * Visual indicator of progress in some operation. Displays a bar to the user
- * representing how far the operation has progressed; the application can
- * change the amount of progress (modifying the length of the bar) as it moves
- * forward. There is also a secondary progress displayable on a progress bar
- * which is useful for displaying intermediate progress, such as the buffer
- * level during a streaming playback progress bar.
- * </p>
- *
- * <p>
- * A progress bar can also be made indeterminate. In indeterminate mode, the
- * progress bar shows a cyclic animation. This mode is used by applications
- * when the length of the task is unknown.
- * </p>
- *
- * <p>The following code example shows how a progress bar can be used from
- * a worker thread to update the user interface to notify the user of progress:
- * </p>
- *
- * <pre class="prettyprint">
- * public class MyActivity extends Activity {
- * private static final int PROGRESS = 0x1;
- *
- * private ProgressBar mProgress;
- * private int mProgressStatus = 0;
- *
- * private Handler mHandler = new Handler();
- *
- * protected void onCreate(Bundle icicle) {
- * super.onCreate(icicle);
- *
- * setContentView(R.layout.progressbar_activity);
- *
- * mProgress = (ProgressBar) findViewById(R.id.progress_bar);
- *
- * // Start lengthy operation in a background thread
- * new Thread(new Runnable() {
- * public void run() {
- * while (mProgressStatus < 100) {
- * mProgressStatus = doWork();
- *
- * // Update the progress bar
- * mHandler.post(new Runnable() {
- * public void run() {
- * mProgress.setProgress(mProgressStatus);
- * }
- * });
- * }
- * }
- * }).start();
- * }
- * }
- * </pre>
- *
- * <p><strong>XML attributes</b></strong>
- * <p>
- * See {@link android.R.styleable#ProgressBar ProgressBar Attributes},
- * {@link android.R.styleable#View View Attributes}
- * </p>
- *
- * <p><strong>Styles</b></strong>
- * <p>
- * @attr ref android.R.styleable#Theme_progressBarStyle
- * @attr ref android.R.styleable#Theme_progressBarStyleSmall
- * @attr ref android.R.styleable#Theme_progressBarStyleLarge
- * @attr ref android.R.styleable#Theme_progressBarStyleHorizontal
- * </p>
- */
-@RemoteView
-public class ProgressBar extends View {
- private static final int MAX_LEVEL = 10000;
- private static final int ANIMATION_RESOLUTION = 200;
-
- int mMinWidth;
- int mMaxWidth;
- int mMinHeight;
- int mMaxHeight;
-
- private int mProgress;
- private int mSecondaryProgress;
- private int mMax;
-
- private int mBehavior;
- private int mDuration;
- private boolean mIndeterminate;
- private boolean mOnlyIndeterminate;
- private Transformation mTransformation;
- private AlphaAnimation mAnimation;
- private Drawable mIndeterminateDrawable;
- private Drawable mProgressDrawable;
- private Drawable mCurrentDrawable;
- Bitmap mSampleTile;
- private boolean mNoInvalidate;
- private Interpolator mInterpolator;
- private RefreshProgressRunnable mRefreshProgressRunnable;
- private long mUiThreadId;
- private boolean mShouldStartAnimationDrawable;
- private long mLastDrawTime;
-
- private boolean mInDrawing;
-
- /**
- * Create a new progress bar with range 0...100 and initial progress of 0.
- * @param context the application environment
- */
- public ProgressBar(Context context) {
- this(context, null);
- }
-
- public ProgressBar(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.progressBarStyle);
- }
-
- public ProgressBar(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- mUiThreadId = Thread.currentThread().getId();
- initProgressBar();
-
- TypedArray a =
- context.obtainStyledAttributes(attrs, R.styleable.ProgressBar, defStyle, 0);
-
- mNoInvalidate = true;
-
- Drawable drawable = a.getDrawable(R.styleable.ProgressBar_progressDrawable);
- if (drawable != null) {
- drawable = tileify(drawable, false);
- setProgressDrawable(drawable);
- }
-
-
- mDuration = a.getInt(R.styleable.ProgressBar_indeterminateDuration, mDuration);
-
- mMinWidth = a.getDimensionPixelSize(R.styleable.ProgressBar_minWidth, mMinWidth);
- mMaxWidth = a.getDimensionPixelSize(R.styleable.ProgressBar_maxWidth, mMaxWidth);
- mMinHeight = a.getDimensionPixelSize(R.styleable.ProgressBar_minHeight, mMinHeight);
- mMaxHeight = a.getDimensionPixelSize(R.styleable.ProgressBar_maxHeight, mMaxHeight);
-
- mBehavior = a.getInt(R.styleable.ProgressBar_indeterminateBehavior, mBehavior);
-
- final int resID = a.getResourceId(com.android.internal.R.styleable.ProgressBar_interpolator, -1);
- if (resID > 0) {
- setInterpolator(context, resID);
- }
-
- setMax(a.getInt(R.styleable.ProgressBar_max, mMax));
-
- setProgress(a.getInt(R.styleable.ProgressBar_progress, mProgress));
-
- setSecondaryProgress(
- a.getInt(R.styleable.ProgressBar_secondaryProgress, mSecondaryProgress));
-
- drawable = a.getDrawable(R.styleable.ProgressBar_indeterminateDrawable);
- if (drawable != null) {
- drawable = tileifyIndeterminate(drawable);
- setIndeterminateDrawable(drawable);
- }
-
- mOnlyIndeterminate = a.getBoolean(
- R.styleable.ProgressBar_indeterminateOnly, mOnlyIndeterminate);
-
- mNoInvalidate = false;
-
- setIndeterminate(mOnlyIndeterminate || a.getBoolean(
- R.styleable.ProgressBar_indeterminate, mIndeterminate));
-
- a.recycle();
- }
-
- /**
- * Converts a drawable to a tiled version of itself. It will recursively
- * traverse layer and state list drawables.
- */
- private Drawable tileify(Drawable drawable, boolean clip) {
-
- if (drawable instanceof LayerDrawable) {
- LayerDrawable background = (LayerDrawable) drawable;
- final int N = background.getNumberOfLayers();
- Drawable[] outDrawables = new Drawable[N];
-
- for (int i = 0; i < N; i++) {
- int id = background.getId(i);
- outDrawables[i] = tileify(background.getDrawable(i),
- (id == R.id.progress || id == R.id.secondaryProgress));
- }
-
- LayerDrawable newBg = new LayerDrawable(outDrawables);
-
- for (int i = 0; i < N; i++) {
- newBg.setId(i, background.getId(i));
- }
-
- return newBg;
-
- } else if (drawable instanceof StateListDrawable) {
- StateListDrawable in = (StateListDrawable) drawable;
- StateListDrawable out = new StateListDrawable();
- int numStates = in.getStateCount();
- for (int i = 0; i < numStates; i++) {
- out.addState(in.getStateSet(i), tileify(in.getStateDrawable(i), clip));
- }
- return out;
-
- } else if (drawable instanceof BitmapDrawable) {
- final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap();
- if (mSampleTile == null) {
- mSampleTile = tileBitmap;
- }
-
- final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
-
- final BitmapShader bitmapShader = new BitmapShader(tileBitmap,
- Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
- shapeDrawable.getPaint().setShader(bitmapShader);
-
- return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT,
- ClipDrawable.HORIZONTAL) : shapeDrawable;
- }
-
- return drawable;
- }
-
- Shape getDrawableShape() {
- final float[] roundedCorners = new float[] { 5, 5, 5, 5, 5, 5, 5, 5 };
- return new RoundRectShape(roundedCorners, null, null);
- }
-
- /**
- * Convert a AnimationDrawable for use as a barberpole animation.
- * Each frame of the animation is wrapped in a ClipDrawable and
- * given a tiling BitmapShader.
- */
- private Drawable tileifyIndeterminate(Drawable drawable) {
- if (drawable instanceof AnimationDrawable) {
- AnimationDrawable background = (AnimationDrawable) drawable;
- final int N = background.getNumberOfFrames();
- AnimationDrawable newBg = new AnimationDrawable();
- newBg.setOneShot(background.isOneShot());
-
- for (int i = 0; i < N; i++) {
- Drawable frame = tileify(background.getFrame(i), true);
- frame.setLevel(10000);
- newBg.addFrame(frame, background.getDuration(i));
- }
- newBg.setLevel(10000);
- drawable = newBg;
- }
- return drawable;
- }
-
- /**
- * <p>
- * Initialize the progress bar's default values:
- * </p>
- * <ul>
- * <li>progress = 0</li>
- * <li>max = 100</li>
- * <li>animation duration = 4000 ms</li>
- * <li>indeterminate = false</li>
- * <li>behavior = repeat</li>
- * </ul>
- */
- private void initProgressBar() {
- mMax = 100;
- mProgress = 0;
- mSecondaryProgress = 0;
- mIndeterminate = false;
- mOnlyIndeterminate = false;
- mDuration = 4000;
- mBehavior = AlphaAnimation.RESTART;
- mMinWidth = 24;
- mMaxWidth = 48;
- mMinHeight = 24;
- mMaxHeight = 48;
- }
-
- /**
- * <p>Indicate whether this progress bar is in indeterminate mode.</p>
- *
- * @return true if the progress bar is in indeterminate mode
- */
- public synchronized boolean isIndeterminate() {
- return mIndeterminate;
- }
-
- /**
- * <p>Change the indeterminate mode for this progress bar. In indeterminate
- * mode, the progress is ignored and the progress bar shows an infinite
- * animation instead.</p>
- *
- * If this progress bar's style only supports indeterminate mode (such as the circular
- * progress bars), then this will be ignored.
- *
- * @param indeterminate true to enable the indeterminate mode
- */
- @android.view.RemotableViewMethod
- public synchronized void setIndeterminate(boolean indeterminate) {
- if ((!mOnlyIndeterminate || !mIndeterminate) && indeterminate != mIndeterminate) {
- mIndeterminate = indeterminate;
-
- if (indeterminate) {
- // swap between indeterminate and regular backgrounds
- mCurrentDrawable = mIndeterminateDrawable;
- startAnimation();
- } else {
- mCurrentDrawable = mProgressDrawable;
- stopAnimation();
- }
- }
- }
-
- /**
- * <p>Get the drawable used to draw the progress bar in
- * indeterminate mode.</p>
- *
- * @return a {@link android.graphics.drawable.Drawable} instance
- *
- * @see #setIndeterminateDrawable(android.graphics.drawable.Drawable)
- * @see #setIndeterminate(boolean)
- */
- public Drawable getIndeterminateDrawable() {
- return mIndeterminateDrawable;
- }
-
- /**
- * <p>Define the drawable used to draw the progress bar in
- * indeterminate mode.</p>
- *
- * @param d the new drawable
- *
- * @see #getIndeterminateDrawable()
- * @see #setIndeterminate(boolean)
- */
- public void setIndeterminateDrawable(Drawable d) {
- if (d != null) {
- d.setCallback(this);
- }
- mIndeterminateDrawable = d;
- if (mIndeterminate) {
- mCurrentDrawable = d;
- postInvalidate();
- }
- }
-
- /**
- * <p>Get the drawable used to draw the progress bar in
- * progress mode.</p>
- *
- * @return a {@link android.graphics.drawable.Drawable} instance
- *
- * @see #setProgressDrawable(android.graphics.drawable.Drawable)
- * @see #setIndeterminate(boolean)
- */
- public Drawable getProgressDrawable() {
- return mProgressDrawable;
- }
-
- /**
- * <p>Define the drawable used to draw the progress bar in
- * progress mode.</p>
- *
- * @param d the new drawable
- *
- * @see #getProgressDrawable()
- * @see #setIndeterminate(boolean)
- */
- public void setProgressDrawable(Drawable d) {
- if (d != null) {
- d.setCallback(this);
- }
- mProgressDrawable = d;
- if (!mIndeterminate) {
- mCurrentDrawable = d;
- postInvalidate();
- }
- }
-
- /**
- * @return The drawable currently used to draw the progress bar
- */
- Drawable getCurrentDrawable() {
- return mCurrentDrawable;
- }
-
- @Override
- protected boolean verifyDrawable(Drawable who) {
- return who == mProgressDrawable || who == mIndeterminateDrawable
- || super.verifyDrawable(who);
- }
-
- @Override
- public void postInvalidate() {
- if (!mNoInvalidate) {
- super.postInvalidate();
- }
- }
-
- private class RefreshProgressRunnable implements Runnable {
-
- private int mId;
- private int mProgress;
- private boolean mFromUser;
-
- RefreshProgressRunnable(int id, int progress, boolean fromUser) {
- mId = id;
- mProgress = progress;
- mFromUser = fromUser;
- }
-
- public void run() {
- doRefreshProgress(mId, mProgress, mFromUser);
- // Put ourselves back in the cache when we are done
- mRefreshProgressRunnable = this;
- }
-
- public void setup(int id, int progress, boolean fromUser) {
- mId = id;
- mProgress = progress;
- mFromUser = fromUser;
- }
-
- }
-
- private synchronized void doRefreshProgress(int id, int progress, boolean fromUser) {
- float scale = mMax > 0 ? (float) progress / (float) mMax : 0;
- final Drawable d = mCurrentDrawable;
- if (d != null) {
- Drawable progressDrawable = null;
-
- if (d instanceof LayerDrawable) {
- progressDrawable = ((LayerDrawable) d).findDrawableByLayerId(id);
- }
-
- final int level = (int) (scale * MAX_LEVEL);
- (progressDrawable != null ? progressDrawable : d).setLevel(level);
- } else {
- invalidate();
- }
-
- if (id == R.id.progress) {
- onProgressRefresh(scale, fromUser);
- }
- }
-
- void onProgressRefresh(float scale, boolean fromUser) {
- }
-
- private synchronized void refreshProgress(int id, int progress, boolean fromUser) {
- if (mUiThreadId == Thread.currentThread().getId()) {
- doRefreshProgress(id, progress, fromUser);
- } else {
- RefreshProgressRunnable r;
- if (mRefreshProgressRunnable != null) {
- // Use cached RefreshProgressRunnable if available
- r = mRefreshProgressRunnable;
- // Uncache it
- mRefreshProgressRunnable = null;
- r.setup(id, progress, fromUser);
- } else {
- // Make a new one
- r = new RefreshProgressRunnable(id, progress, fromUser);
- }
- post(r);
- }
- }
-
- /**
- * <p>Set the current progress to the specified value. Does not do anything
- * if the progress bar is in indeterminate mode.</p>
- *
- * @param progress the new progress, between 0 and {@link #getMax()}
- *
- * @see #setIndeterminate(boolean)
- * @see #isIndeterminate()
- * @see #getProgress()
- * @see #incrementProgressBy(int)
- */
- public synchronized void setProgress(int progress) {
- setProgress(progress, false);
- }
-
- @android.view.RemotableViewMethod
- synchronized void setProgress(int progress, boolean fromUser) {
- if (mIndeterminate) {
- return;
- }
-
- if (progress < 0) {
- progress = 0;
- }
-
- if (progress > mMax) {
- progress = mMax;
- }
-
- if (progress != mProgress) {
- mProgress = progress;
- refreshProgress(R.id.progress, mProgress, fromUser);
- }
- }
-
- /**
- * <p>
- * Set the current secondary progress to the specified value. Does not do
- * anything if the progress bar is in indeterminate mode.
- * </p>
- *
- * @param secondaryProgress the new secondary progress, between 0 and {@link #getMax()}
- * @see #setIndeterminate(boolean)
- * @see #isIndeterminate()
- * @see #getSecondaryProgress()
- * @see #incrementSecondaryProgressBy(int)
- */
- @android.view.RemotableViewMethod
- public synchronized void setSecondaryProgress(int secondaryProgress) {
- if (mIndeterminate) {
- return;
- }
-
- if (secondaryProgress < 0) {
- secondaryProgress = 0;
- }
-
- if (secondaryProgress > mMax) {
- secondaryProgress = mMax;
- }
-
- if (secondaryProgress != mSecondaryProgress) {
- mSecondaryProgress = secondaryProgress;
- refreshProgress(R.id.secondaryProgress, mSecondaryProgress, false);
- }
- }
-
- /**
- * <p>Get the progress bar's current level of progress. Return 0 when the
- * progress bar is in indeterminate mode.</p>
- *
- * @return the current progress, between 0 and {@link #getMax()}
- *
- * @see #setIndeterminate(boolean)
- * @see #isIndeterminate()
- * @see #setProgress(int)
- * @see #setMax(int)
- * @see #getMax()
- */
- public synchronized int getProgress() {
- return mIndeterminate ? 0 : mProgress;
- }
-
- /**
- * <p>Get the progress bar's current level of secondary progress. Return 0 when the
- * progress bar is in indeterminate mode.</p>
- *
- * @return the current secondary progress, between 0 and {@link #getMax()}
- *
- * @see #setIndeterminate(boolean)
- * @see #isIndeterminate()
- * @see #setSecondaryProgress(int)
- * @see #setMax(int)
- * @see #getMax()
- */
- public synchronized int getSecondaryProgress() {
- return mIndeterminate ? 0 : mSecondaryProgress;
- }
-
- /**
- * <p>Return the upper limit of this progress bar's range.</p>
- *
- * @return a positive integer
- *
- * @see #setMax(int)
- * @see #getProgress()
- * @see #getSecondaryProgress()
- */
- public synchronized int getMax() {
- return mMax;
- }
-
- /**
- * <p>Set the range of the progress bar to 0...<tt>max</tt>.</p>
- *
- * @param max the upper range of this progress bar
- *
- * @see #getMax()
- * @see #setProgress(int)
- * @see #setSecondaryProgress(int)
- */
- @android.view.RemotableViewMethod
- public synchronized void setMax(int max) {
- if (max < 0) {
- max = 0;
- }
- if (max != mMax) {
- mMax = max;
- postInvalidate();
-
- if (mProgress > max) {
- mProgress = max;
- }
- }
- }
-
- /**
- * <p>Increase the progress bar's progress by the specified amount.</p>
- *
- * @param diff the amount by which the progress must be increased
- *
- * @see #setProgress(int)
- */
- public synchronized final void incrementProgressBy(int diff) {
- setProgress(mProgress + diff);
- }
-
- /**
- * <p>Increase the progress bar's secondary progress by the specified amount.</p>
- *
- * @param diff the amount by which the secondary progress must be increased
- *
- * @see #setSecondaryProgress(int)
- */
- public synchronized final void incrementSecondaryProgressBy(int diff) {
- setSecondaryProgress(mSecondaryProgress + diff);
- }
-
- /**
- * <p>Start the indeterminate progress animation.</p>
- */
- void startAnimation() {
- int visibility = getVisibility();
- if (visibility != VISIBLE) {
- return;
- }
-
- if (mIndeterminateDrawable instanceof AnimationDrawable) {
- mShouldStartAnimationDrawable = true;
- mAnimation = null;
- } else {
- if (mInterpolator == null) {
- mInterpolator = new LinearInterpolator();
- }
-
- mTransformation = new Transformation();
- mAnimation = new AlphaAnimation(0.0f, 1.0f);
- mAnimation.setRepeatMode(mBehavior);
- mAnimation.setRepeatCount(Animation.INFINITE);
- mAnimation.setDuration(mDuration);
- mAnimation.setInterpolator(mInterpolator);
- mAnimation.setStartTime(Animation.START_ON_FIRST_FRAME);
- postInvalidate();
- }
- }
-
- /**
- * <p>Stop the indeterminate progress animation.</p>
- */
- void stopAnimation() {
- mAnimation = null;
- mTransformation = null;
- if (mIndeterminateDrawable instanceof AnimationDrawable) {
- ((AnimationDrawable) mIndeterminateDrawable).stop();
- mShouldStartAnimationDrawable = false;
- }
- }
-
- /**
- * Sets the acceleration curve for the indeterminate animation.
- * The interpolator is loaded as a resource from the specified context.
- *
- * @param context The application environment
- * @param resID The resource identifier of the interpolator to load
- */
- public void setInterpolator(Context context, int resID) {
- setInterpolator(AnimationUtils.loadInterpolator(context, resID));
- }
-
- /**
- * Sets the acceleration curve for the indeterminate animation.
- * Defaults to a linear interpolation.
- *
- * @param interpolator The interpolator which defines the acceleration curve
- */
- public void setInterpolator(Interpolator interpolator) {
- mInterpolator = interpolator;
- }
-
- /**
- * Gets the acceleration curve type for the indeterminate animation.
- *
- * @return the {@link Interpolator} associated to this animation
- */
- public Interpolator getInterpolator() {
- return mInterpolator;
- }
-
- @Override
- public void setVisibility(int v) {
- if (getVisibility() != v) {
- super.setVisibility(v);
-
- if (mIndeterminate) {
- // let's be nice with the UI thread
- if (v == GONE || v == INVISIBLE) {
- stopAnimation();
- } else if (v == VISIBLE) {
- startAnimation();
- }
- }
- }
- }
-
- @Override
- public void invalidateDrawable(Drawable dr) {
- if (!mInDrawing) {
- if (dr == mProgressDrawable || dr == mIndeterminateDrawable) {
- final Rect dirty = dr.getBounds();
- final int scrollX = mScrollX + mPaddingLeft;
- final int scrollY = mScrollY + mPaddingTop;
-
- invalidate(dirty.left + scrollX, dirty.top + scrollY,
- dirty.right + scrollX, dirty.bottom + scrollY);
- } else {
- super.invalidateDrawable(dr);
- }
- }
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- // onDraw will translate the canvas so we draw starting at 0,0
- int right = w - mPaddingRight - mPaddingLeft;
- int bottom = h - mPaddingBottom - mPaddingTop;
-
- if (mIndeterminateDrawable != null) {
- mIndeterminateDrawable.setBounds(0, 0, right, bottom);
- }
-
- if (mProgressDrawable != null) {
- mProgressDrawable.setBounds(0, 0, right, bottom);
- }
- }
-
- @Override
- protected synchronized void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- Drawable d = mCurrentDrawable;
- if (d != null) {
- // Translate canvas so a indeterminate circular progress bar with padding
- // rotates properly in its animation
- canvas.save();
- canvas.translate(mPaddingLeft, mPaddingTop);
- long time = getDrawingTime();
- if (mAnimation != null) {
- mAnimation.getTransformation(time, mTransformation);
- float scale = mTransformation.getAlpha();
- try {
- mInDrawing = true;
- d.setLevel((int) (scale * MAX_LEVEL));
- } finally {
- mInDrawing = false;
- }
- if (SystemClock.uptimeMillis() - mLastDrawTime >= ANIMATION_RESOLUTION) {
- mLastDrawTime = SystemClock.uptimeMillis();
- postInvalidateDelayed(ANIMATION_RESOLUTION);
- }
- }
- d.draw(canvas);
- canvas.restore();
- if (mShouldStartAnimationDrawable && d instanceof AnimationDrawable) {
- ((AnimationDrawable) d).start();
- mShouldStartAnimationDrawable = false;
- }
- }
- }
-
- @Override
- protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- Drawable d = mCurrentDrawable;
-
- int dw = 0;
- int dh = 0;
- if (d != null) {
- dw = Math.max(mMinWidth, Math.min(mMaxWidth, d.getIntrinsicWidth()));
- dh = Math.max(mMinHeight, Math.min(mMaxHeight, d.getIntrinsicHeight()));
- }
- dw += mPaddingLeft + mPaddingRight;
- dh += mPaddingTop + mPaddingBottom;
-
- setMeasuredDimension(resolveSize(dw, widthMeasureSpec),
- resolveSize(dh, heightMeasureSpec));
- }
-
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
-
- int[] state = getDrawableState();
-
- if (mProgressDrawable != null && mProgressDrawable.isStateful()) {
- mProgressDrawable.setState(state);
- }
-
- if (mIndeterminateDrawable != null && mIndeterminateDrawable.isStateful()) {
- mIndeterminateDrawable.setState(state);
- }
- }
-
- static class SavedState extends BaseSavedState {
- int progress;
- int secondaryProgress;
-
- /**
- * Constructor called from {@link ProgressBar#onSaveInstanceState()}
- */
- SavedState(Parcelable superState) {
- super(superState);
- }
-
- /**
- * Constructor called from {@link #CREATOR}
- */
- private SavedState(Parcel in) {
- super(in);
- progress = in.readInt();
- secondaryProgress = in.readInt();
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- super.writeToParcel(out, flags);
- out.writeInt(progress);
- out.writeInt(secondaryProgress);
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR
- = new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
- @Override
- public Parcelable onSaveInstanceState() {
- // Force our ancestor class to save its state
- Parcelable superState = super.onSaveInstanceState();
- SavedState ss = new SavedState(superState);
-
- ss.progress = mProgress;
- ss.secondaryProgress = mSecondaryProgress;
-
- return ss;
- }
-
- @Override
- public void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
- super.onRestoreInstanceState(ss.getSuperState());
-
- setProgress(ss.progress);
- setSecondaryProgress(ss.secondaryProgress);
- }
-}
diff --git a/core/java/android/widget/RadioButton.java b/core/java/android/widget/RadioButton.java
deleted file mode 100644
index 14ec8c6..0000000
--- a/core/java/android/widget/RadioButton.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-
-/**
- * <p>
- * A radio button is a two-states button that can be either checked or
- * unchecked. When the radio button is unchecked, the user can press or click it
- * to check it. However, contrary to a {@link android.widget.CheckBox}, a radio
- * button cannot be unchecked by the user once checked.
- * </p>
- *
- * <p>
- * Radio buttons are normally used together in a
- * {@link android.widget.RadioGroup}. When several radio buttons live inside
- * a radio group, checking one radio button unchecks all the others.</p>
- * </p>
- *
- * <p><strong>XML attributes</strong></p>
- * <p>
- * See {@link android.R.styleable#CompoundButton CompoundButton Attributes},
- * {@link android.R.styleable#Button Button Attributes},
- * {@link android.R.styleable#TextView TextView Attributes},
- * {@link android.R.styleable#View View Attributes}
- * </p>
- */
-public class RadioButton extends CompoundButton {
-
- public RadioButton(Context context) {
- this(context, null);
- }
-
- public RadioButton(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.radioButtonStyle);
- }
-
- public RadioButton(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- /**
- * {@inheritDoc}
- * <p>
- * If the radio button is already checked, this method will not toggle the radio button.
- */
- @Override
- public void toggle() {
- // we override to prevent toggle when the radio is already
- // checked (as opposed to check boxes widgets)
- if (!isChecked()) {
- super.toggle();
- }
- }
-}
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
deleted file mode 100644
index 393346a..0000000
--- a/core/java/android/widget/RadioGroup.java
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import com.android.internal.R;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-
-
-/**
- * <p>This class is used to create a multiple-exclusion scope for a set of radio
- * buttons. Checking one radio button that belongs to a radio group unchecks
- * any previously checked radio button within the same group.</p>
- *
- * <p>Intially, all of the radio buttons are unchecked. While it is not possible
- * to uncheck a particular radio button, the radio group can be cleared to
- * remove the checked state.</p>
- *
- * <p>The selection is identified by the unique id of the radio button as defined
- * in the XML layout file.</p>
- *
- * <p><strong>XML Attributes</strong></p>
- * <p>See {@link android.R.styleable#RadioGroup RadioGroup Attributes},
- * {@link android.R.styleable#LinearLayout LinearLayout Attributes},
- * {@link android.R.styleable#ViewGroup ViewGroup Attributes},
- * {@link android.R.styleable#View View Attributes}</p>
- * <p>Also see
- * {@link android.widget.LinearLayout.LayoutParams LinearLayout.LayoutParams}
- * for layout attributes.</p>
- *
- * @see RadioButton
- *
- */
-public class RadioGroup extends LinearLayout {
- // holds the checked id; the selection is empty by default
- private int mCheckedId = -1;
- // tracks children radio buttons checked state
- private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;
- // when true, mOnCheckedChangeListener discards events
- private boolean mProtectFromCheckedChange = false;
- private OnCheckedChangeListener mOnCheckedChangeListener;
- private PassThroughHierarchyChangeListener mPassThroughListener;
-
- /**
- * {@inheritDoc}
- */
- public RadioGroup(Context context) {
- super(context);
- setOrientation(VERTICAL);
- init();
- }
-
- /**
- * {@inheritDoc}
- */
- public RadioGroup(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- // retrieve selected radio button as requested by the user in the
- // XML layout file
- TypedArray attributes = context.obtainStyledAttributes(
- attrs, com.android.internal.R.styleable.RadioGroup, com.android.internal.R.attr.radioButtonStyle, 0);
-
- int value = attributes.getResourceId(R.styleable.RadioGroup_checkedButton, View.NO_ID);
- if (value != View.NO_ID) {
- mCheckedId = value;
- }
-
- final int index = attributes.getInt(com.android.internal.R.styleable.RadioGroup_orientation, VERTICAL);
- setOrientation(index);
-
- attributes.recycle();
- init();
- }
-
- private void init() {
- mChildOnCheckedChangeListener = new CheckedStateTracker();
- mPassThroughListener = new PassThroughHierarchyChangeListener();
- super.setOnHierarchyChangeListener(mPassThroughListener);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
- // the user listener is delegated to our pass-through listener
- mPassThroughListener.mOnHierarchyChangeListener = listener;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- // checks the appropriate radio button as requested in the XML file
- if (mCheckedId != -1) {
- mProtectFromCheckedChange = true;
- setCheckedStateForView(mCheckedId, true);
- mProtectFromCheckedChange = false;
- setCheckedId(mCheckedId);
- }
- }
-
- @Override
- public void addView(View child, int index, ViewGroup.LayoutParams params) {
- if (child instanceof RadioButton) {
- final RadioButton button = (RadioButton) child;
- if (button.isChecked()) {
- mProtectFromCheckedChange = true;
- if (mCheckedId != -1) {
- setCheckedStateForView(mCheckedId, false);
- }
- mProtectFromCheckedChange = false;
- setCheckedId(button.getId());
- }
- }
-
- super.addView(child, index, params);
- }
-
- /**
- * <p>Sets the selection to the radio button whose identifier is passed in
- * parameter. Using -1 as the selection identifier clears the selection;
- * such an operation is equivalent to invoking {@link #clearCheck()}.</p>
- *
- * @param id the unique id of the radio button to select in this group
- *
- * @see #getCheckedRadioButtonId()
- * @see #clearCheck()
- */
- public void check(int id) {
- // don't even bother
- if (id != -1 && (id == mCheckedId)) {
- return;
- }
-
- if (mCheckedId != -1) {
- setCheckedStateForView(mCheckedId, false);
- }
-
- if (id != -1) {
- setCheckedStateForView(id, true);
- }
-
- setCheckedId(id);
- }
-
- private void setCheckedId(int id) {
- mCheckedId = id;
- if (mOnCheckedChangeListener != null) {
- mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
- }
- }
-
- private void setCheckedStateForView(int viewId, boolean checked) {
- View checkedView = findViewById(viewId);
- if (checkedView != null && checkedView instanceof RadioButton) {
- ((RadioButton) checkedView).setChecked(checked);
- }
- }
-
- /**
- * <p>Returns the identifier of the selected radio button in this group.
- * Upon empty selection, the returned value is -1.</p>
- *
- * @return the unique id of the selected radio button in this group
- *
- * @see #check(int)
- * @see #clearCheck()
- */
- public int getCheckedRadioButtonId() {
- return mCheckedId;
- }
-
- /**
- * <p>Clears the selection. When the selection is cleared, no radio button
- * in this group is selected and {@link #getCheckedRadioButtonId()} returns
- * null.</p>
- *
- * @see #check(int)
- * @see #getCheckedRadioButtonId()
- */
- public void clearCheck() {
- check(-1);
- }
-
- /**
- * <p>Register a callback to be invoked when the checked radio button
- * changes in this group.</p>
- *
- * @param listener the callback to call on checked state change
- */
- public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
- mOnCheckedChangeListener = listener;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new RadioGroup.LayoutParams(getContext(), attrs);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof RadioGroup.LayoutParams;
- }
-
- @Override
- protected LinearLayout.LayoutParams generateDefaultLayoutParams() {
- return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- }
-
- /**
- * <p>This set of layout parameters defaults the width and the height of
- * the children to {@link #WRAP_CONTENT} when they are not specified in the
- * XML file. Otherwise, this class ussed the value read from the XML file.</p>
- *
- * <p>See
- * {@link android.R.styleable#LinearLayout_Layout LinearLayout Attributes}
- * for a list of all child view attributes that this class supports.</p>
- *
- */
- public static class LayoutParams extends LinearLayout.LayoutParams {
- /**
- * {@inheritDoc}
- */
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(int w, int h) {
- super(w, h);
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(int w, int h, float initWeight) {
- super(w, h, initWeight);
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(ViewGroup.LayoutParams p) {
- super(p);
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(MarginLayoutParams source) {
- super(source);
- }
-
- /**
- * <p>Fixes the child's width to
- * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and the child's
- * height to {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}
- * when not specified in the XML file.</p>
- *
- * @param a the styled attributes set
- * @param widthAttr the width attribute to fetch
- * @param heightAttr the height attribute to fetch
- */
- @Override
- protected void setBaseAttributes(TypedArray a,
- int widthAttr, int heightAttr) {
-
- if (a.hasValue(widthAttr)) {
- width = a.getLayoutDimension(widthAttr, "layout_width");
- } else {
- width = WRAP_CONTENT;
- }
-
- if (a.hasValue(heightAttr)) {
- height = a.getLayoutDimension(heightAttr, "layout_height");
- } else {
- height = WRAP_CONTENT;
- }
- }
- }
-
- /**
- * <p>Interface definition for a callback to be invoked when the checked
- * radio button changed in this group.</p>
- */
- public interface OnCheckedChangeListener {
- /**
- * <p>Called when the checked radio button has changed. When the
- * selection is cleared, checkedId is -1.</p>
- *
- * @param group the group in which the checked radio button has changed
- * @param checkedId the unique identifier of the newly checked radio button
- */
- public void onCheckedChanged(RadioGroup group, int checkedId);
- }
-
- private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- // prevents from infinite recursion
- if (mProtectFromCheckedChange) {
- return;
- }
-
- mProtectFromCheckedChange = true;
- if (mCheckedId != -1) {
- setCheckedStateForView(mCheckedId, false);
- }
- mProtectFromCheckedChange = false;
-
- int id = buttonView.getId();
- setCheckedId(id);
- }
- }
-
- /**
- * <p>A pass-through listener acts upon the events and dispatches them
- * to another listener. This allows the table layout to set its own internal
- * hierarchy change listener without preventing the user to setup his.</p>
- */
- private class PassThroughHierarchyChangeListener implements
- ViewGroup.OnHierarchyChangeListener {
- private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener;
-
- /**
- * {@inheritDoc}
- */
- public void onChildViewAdded(View parent, View child) {
- if (parent == RadioGroup.this && child instanceof RadioButton) {
- int id = child.getId();
- // generates an id if it's missing
- if (id == View.NO_ID) {
- id = child.hashCode();
- child.setId(id);
- }
- ((RadioButton) child).setOnCheckedChangeWidgetListener(
- mChildOnCheckedChangeListener);
- }
-
- if (mOnHierarchyChangeListener != null) {
- mOnHierarchyChangeListener.onChildViewAdded(parent, child);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void onChildViewRemoved(View parent, View child) {
- if (parent == RadioGroup.this && child instanceof RadioButton) {
- ((RadioButton) child).setOnCheckedChangeWidgetListener(null);
- }
-
- if (mOnHierarchyChangeListener != null) {
- mOnHierarchyChangeListener.onChildViewRemoved(parent, child);
- }
- }
- }
-}
diff --git a/core/java/android/widget/RatingBar.java b/core/java/android/widget/RatingBar.java
deleted file mode 100644
index ad5ca07..0000000
--- a/core/java/android/widget/RatingBar.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.drawable.shapes.RectShape;
-import android.graphics.drawable.shapes.Shape;
-import android.util.AttributeSet;
-
-import com.android.internal.R;
-
-/**
- * A RatingBar is an extension of SeekBar and ProgressBar that shows a rating in
- * stars. The user can touch/drag or use arrow keys to set the rating when using
- * the default size RatingBar. The smaller RatingBar style (
- * {@link android.R.attr#ratingBarStyleSmall}) and the larger indicator-only
- * style ({@link android.R.attr#ratingBarStyleIndicator}) do not support user
- * interaction and should only be used as indicators.
- * <p>
- * When using a RatingBar that supports user interaction, placing widgets to the
- * left or right of the RatingBar is discouraged.
- * <p>
- * The number of stars set (via {@link #setNumStars(int)} or in an XML layout)
- * will be shown when the layout width is set to wrap content (if another layout
- * width is set, the results may be unpredictable).
- * <p>
- * The secondary progress should not be modified by the client as it is used
- * internally as the background for a fractionally filled star.
- *
- * @attr ref android.R.styleable#RatingBar_numStars
- * @attr ref android.R.styleable#RatingBar_rating
- * @attr ref android.R.styleable#RatingBar_stepSize
- * @attr ref android.R.styleable#RatingBar_isIndicator
- */
-public class RatingBar extends AbsSeekBar {
-
- /**
- * A callback that notifies clients when the rating has been changed. This
- * includes changes that were initiated by the user through a touch gesture
- * or arrow key/trackball as well as changes that were initiated
- * programmatically.
- */
- public interface OnRatingBarChangeListener {
-
- /**
- * Notification that the rating has changed. Clients can use the
- * fromUser parameter to distinguish user-initiated changes from those
- * that occurred programmatically. This will not be called continuously
- * while the user is dragging, only when the user finalizes a rating by
- * lifting the touch.
- *
- * @param ratingBar The RatingBar whose rating has changed.
- * @param rating The current rating. This will be in the range
- * 0..numStars.
- * @param fromUser True if the rating change was initiated by a user's
- * touch gesture or arrow key/horizontal trackbell movement.
- */
- void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser);
-
- }
-
- private int mNumStars = 5;
-
- private int mProgressOnStartTracking;
-
- private OnRatingBarChangeListener mOnRatingBarChangeListener;
-
- public RatingBar(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RatingBar,
- defStyle, 0);
- final int numStars = a.getInt(R.styleable.RatingBar_numStars, mNumStars);
- setIsIndicator(a.getBoolean(R.styleable.RatingBar_isIndicator, !mIsUserSeekable));
- final float rating = a.getFloat(R.styleable.RatingBar_rating, -1);
- final float stepSize = a.getFloat(R.styleable.RatingBar_stepSize, -1);
- a.recycle();
-
- if (numStars > 0 && numStars != mNumStars) {
- setNumStars(numStars);
- }
-
- if (stepSize >= 0) {
- setStepSize(stepSize);
- } else {
- setStepSize(0.5f);
- }
-
- if (rating >= 0) {
- setRating(rating);
- }
-
- // A touch inside a star fill up to that fractional area (slightly more
- // than 1 so boundaries round up).
- mTouchProgressOffset = 1.1f;
- }
-
- public RatingBar(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.ratingBarStyle);
- }
-
- public RatingBar(Context context) {
- this(context, null);
- }
-
- /**
- * Sets the listener to be called when the rating changes.
- *
- * @param listener The listener.
- */
- public void setOnRatingBarChangeListener(OnRatingBarChangeListener listener) {
- mOnRatingBarChangeListener = listener;
- }
-
- /**
- * @return The listener (may be null) that is listening for rating change
- * events.
- */
- public OnRatingBarChangeListener getOnRatingBarChangeListener() {
- return mOnRatingBarChangeListener;
- }
-
- /**
- * Whether this rating bar should only be an indicator (thus non-changeable
- * by the user).
- *
- * @param isIndicator Whether it should be an indicator.
- */
- public void setIsIndicator(boolean isIndicator) {
- mIsUserSeekable = !isIndicator;
- setFocusable(!isIndicator);
- }
-
- /**
- * @return Whether this rating bar is only an indicator.
- */
- public boolean isIndicator() {
- return !mIsUserSeekable;
- }
-
- /**
- * Sets the number of stars to show. In order for these to be shown
- * properly, it is recommended the layout width of this widget be wrap
- * content.
- *
- * @param numStars The number of stars.
- */
- public void setNumStars(final int numStars) {
- if (numStars <= 0) {
- return;
- }
-
- mNumStars = numStars;
-
- // This causes the width to change, so re-layout
- requestLayout();
- }
-
- /**
- * Returns the number of stars shown.
- * @return The number of stars shown.
- */
- public int getNumStars() {
- return mNumStars;
- }
-
- /**
- * Sets the rating (the number of stars filled).
- *
- * @param rating The rating to set.
- */
- public void setRating(float rating) {
- setProgress(Math.round(rating * getProgressPerStar()));
- }
-
- /**
- * Gets the current rating (number of stars filled).
- *
- * @return The current rating.
- */
- public float getRating() {
- return getProgress() / getProgressPerStar();
- }
-
- /**
- * Sets the step size (granularity) of this rating bar.
- *
- * @param stepSize The step size of this rating bar. For example, if
- * half-star granularity is wanted, this would be 0.5.
- */
- public void setStepSize(float stepSize) {
- if (stepSize <= 0) {
- return;
- }
-
- final float newMax = mNumStars / stepSize;
- final int newProgress = (int) (newMax / getMax() * getProgress());
- setMax((int) newMax);
- setProgress(newProgress);
- }
-
- /**
- * Gets the step size of this rating bar.
- *
- * @return The step size.
- */
- public float getStepSize() {
- return (float) getNumStars() / getMax();
- }
-
- /**
- * @return The amount of progress that fits into a star
- */
- private float getProgressPerStar() {
- if (mNumStars > 0) {
- return 1f * getMax() / mNumStars;
- } else {
- return 1;
- }
- }
-
- @Override
- Shape getDrawableShape() {
- // TODO: Once ProgressBar's TODOs are fixed, this won't be needed
- return new RectShape();
- }
-
- @Override
- void onProgressRefresh(float scale, boolean fromUser) {
- super.onProgressRefresh(scale, fromUser);
-
- // Keep secondary progress in sync with primary
- updateSecondaryProgress(getProgress());
-
- if (!fromUser) {
- // Callback for non-user rating changes
- dispatchRatingChange(false);
- }
- }
-
- /**
- * The secondary progress is used to differentiate the background of a
- * partially filled star. This method keeps the secondary progress in sync
- * with the progress.
- *
- * @param progress The primary progress level.
- */
- private void updateSecondaryProgress(int progress) {
- final float ratio = getProgressPerStar();
- if (ratio > 0) {
- final float progressInStars = progress / ratio;
- final int secondaryProgress = (int) (Math.ceil(progressInStars) * ratio);
- setSecondaryProgress(secondaryProgress);
- }
- }
-
- @Override
- protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
- if (mSampleTile != null) {
- // TODO: Once ProgressBar's TODOs are gone, this can be done more
- // cleanly than mSampleTile
- final int width = mSampleTile.getWidth() * mNumStars;
- setMeasuredDimension(resolveSize(width, widthMeasureSpec), mMeasuredHeight);
- }
- }
-
- @Override
- void onStartTrackingTouch() {
- mProgressOnStartTracking = getProgress();
-
- super.onStartTrackingTouch();
- }
-
- @Override
- void onStopTrackingTouch() {
- super.onStopTrackingTouch();
-
- if (getProgress() != mProgressOnStartTracking) {
- dispatchRatingChange(true);
- }
- }
-
- void dispatchRatingChange(boolean fromUser) {
- if (mOnRatingBarChangeListener != null) {
- mOnRatingBarChangeListener.onRatingChanged(this, getRating(),
- fromUser);
- }
- }
-
- @Override
- public synchronized void setMax(int max) {
- // Disallow max progress = 0
- if (max <= 0) {
- return;
- }
-
- super.setMax(max);
- }
-
-}
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
deleted file mode 100644
index ba63ec3..0000000
--- a/core/java/android/widget/RelativeLayout.java
+++ /dev/null
@@ -1,954 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Gravity;
-import android.widget.RemoteViews.RemoteView;
-import android.graphics.Rect;
-import com.android.internal.R;
-
-
-/**
- * A Layout where the positions of the children can be described in relation to each other or to the
- * parent. For the sake of efficiency, the relations between views are evaluated in one pass, so if
- * view Y is dependent on the position of view X, make sure the view X comes first in the layout.
- *
- * <p>
- * Note that you cannot have a circular dependency between the size of the RelativeLayout and the
- * position of its children. For example, you cannot have a RelativeLayout whose height is set to
- * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT WRAP_CONTENT} and a child set to
- * {@link #ALIGN_PARENT_BOTTOM}.
- * </p>
- *
- * <p>
- * Also see {@link android.widget.RelativeLayout.LayoutParams RelativeLayout.LayoutParams} for
- * layout attributes
- * </p>
- *
- * @attr ref android.R.styleable#RelativeLayout_gravity
- * @attr ref android.R.styleable#RelativeLayout_ignoreGravity
- */
-@RemoteView
-public class RelativeLayout extends ViewGroup {
- public static final int TRUE = -1;
-
- /**
- * Rule that aligns a child's right edge with another child's left edge.
- */
- public static final int LEFT_OF = 0;
- /**
- * Rule that aligns a child's left edge with another child's right edge.
- */
- public static final int RIGHT_OF = 1;
- /**
- * Rule that aligns a child's bottom edge with another child's top edge.
- */
- public static final int ABOVE = 2;
- /**
- * Rule that aligns a child's top edge with another child's bottom edge.
- */
- public static final int BELOW = 3;
-
- /**
- * Rule that aligns a child's baseline with another child's baseline.
- */
- public static final int ALIGN_BASELINE = 4;
- /**
- * Rule that aligns a child's left edge with another child's left edge.
- */
- public static final int ALIGN_LEFT = 5;
- /**
- * Rule that aligns a child's top edge with another child's top edge.
- */
- public static final int ALIGN_TOP = 6;
- /**
- * Rule that aligns a child's right edge with another child's right edge.
- */
- public static final int ALIGN_RIGHT = 7;
- /**
- * Rule that aligns a child's bottom edge with another child's bottom edge.
- */
- public static final int ALIGN_BOTTOM = 8;
-
- /**
- * Rule that aligns the child's left edge with its RelativeLayout
- * parent's left edge.
- */
- public static final int ALIGN_PARENT_LEFT = 9;
- /**
- * Rule that aligns the child's top edge with its RelativeLayout
- * parent's top edge.
- */
- public static final int ALIGN_PARENT_TOP = 10;
- /**
- * Rule that aligns the child's right edge with its RelativeLayout
- * parent's right edge.
- */
- public static final int ALIGN_PARENT_RIGHT = 11;
- /**
- * Rule that aligns the child's bottom edge with its RelativeLayout
- * parent's bottom edge.
- */
- public static final int ALIGN_PARENT_BOTTOM = 12;
-
- /**
- * Rule that centers the child with respect to the bounds of its
- * RelativeLayout parent.
- */
- public static final int CENTER_IN_PARENT = 13;
- /**
- * Rule that centers the child horizontally with respect to the
- * bounds of its RelativeLayout parent.
- */
- public static final int CENTER_HORIZONTAL = 14;
- /**
- * Rule that centers the child vertically with respect to the
- * bounds of its RelativeLayout parent.
- */
- public static final int CENTER_VERTICAL = 15;
-
- private static final int VERB_COUNT = 16;
-
- private View mBaselineView = null;
- private boolean mHasBaselineAlignedChild;
-
- private int mGravity = Gravity.LEFT | Gravity.TOP;
- private final Rect mContentBounds = new Rect();
- private final Rect mSelfBounds = new Rect();
- private int mIgnoreGravity;
-
- public RelativeLayout(Context context) {
- super(context);
- }
-
- public RelativeLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- initFromAttributes(context, attrs);
- }
-
- public RelativeLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- initFromAttributes(context, attrs);
- }
-
- private void initFromAttributes(Context context, AttributeSet attrs) {
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RelativeLayout);
- mIgnoreGravity = a.getResourceId(R.styleable.RelativeLayout_ignoreGravity, View.NO_ID);
- mGravity = a.getInt(R.styleable.RelativeLayout_gravity, mGravity);
- a.recycle();
- }
-
- /**
- * Defines which View is ignored when the gravity is applied. This setting has no
- * effect if the gravity is <code>Gravity.LEFT | Gravity.TOP</code>.
- *
- * @param viewId The id of the View to be ignored by gravity, or 0 if no View
- * should be ignored.
- *
- * @see #setGravity(int)
- *
- * @attr ref android.R.styleable#RelativeLayout_ignoreGravity
- */
- @android.view.RemotableViewMethod
- public void setIgnoreGravity(int viewId) {
- mIgnoreGravity = viewId;
- }
-
- /**
- * Describes how the child views are positioned. Defaults to
- * <code>Gravity.LEFT | Gravity.TOP</code>.
- *
- * @param gravity See {@link android.view.Gravity}
- *
- * @see #setHorizontalGravity(int)
- * @see #setVerticalGravity(int)
- *
- * @attr ref android.R.styleable#RelativeLayout_gravity
- */
- @android.view.RemotableViewMethod
- public void setGravity(int gravity) {
- if (mGravity != gravity) {
- if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
- gravity |= Gravity.LEFT;
- }
-
- if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
- gravity |= Gravity.TOP;
- }
-
- mGravity = gravity;
- requestLayout();
- }
- }
-
- @android.view.RemotableViewMethod
- public void setHorizontalGravity(int horizontalGravity) {
- final int gravity = horizontalGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
- if ((mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != gravity) {
- mGravity = (mGravity & ~Gravity.HORIZONTAL_GRAVITY_MASK) | gravity;
- requestLayout();
- }
- }
-
- @android.view.RemotableViewMethod
- public void setVerticalGravity(int verticalGravity) {
- final int gravity = verticalGravity & Gravity.VERTICAL_GRAVITY_MASK;
- if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != gravity) {
- mGravity = (mGravity & ~Gravity.VERTICAL_GRAVITY_MASK) | gravity;
- requestLayout();
- }
- }
-
- @Override
- public int getBaseline() {
- return mBaselineView != null ? mBaselineView.getBaseline() : super.getBaseline();
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int myWidth = -1;
- int myHeight = -1;
-
- int width = 0;
- int height = 0;
-
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
- // Record our dimensions if they are known;
- if (widthMode != MeasureSpec.UNSPECIFIED) {
- myWidth = widthSize;
- }
-
- if (heightMode != MeasureSpec.UNSPECIFIED) {
- myHeight = heightSize;
- }
-
- if (widthMode == MeasureSpec.EXACTLY) {
- width = myWidth;
- }
-
- if (heightMode == MeasureSpec.EXACTLY) {
- height = myHeight;
- }
-
- int len = this.getChildCount();
- mHasBaselineAlignedChild = false;
-
- View ignore = null;
- int gravity = mGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
- final boolean horizontalGravity = gravity != Gravity.LEFT && gravity != 0;
- gravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
- final boolean verticalGravity = gravity != Gravity.TOP && gravity != 0;
-
- int left = Integer.MAX_VALUE;
- int top = Integer.MAX_VALUE;
- int right = Integer.MIN_VALUE;
- int bottom = Integer.MIN_VALUE;
-
- if ((horizontalGravity || verticalGravity) && mIgnoreGravity != View.NO_ID) {
- ignore = findViewById(mIgnoreGravity);
- }
-
- for (int i = 0; i < len; i++) {
- View child = getChildAt(i);
- if (child.getVisibility() != GONE) {
- LayoutParams params = (LayoutParams) child.getLayoutParams();
- applySizeRules(params, myWidth, myHeight);
- measureChild(child, params, myWidth, myHeight);
- positionChild(child, params, myWidth, myHeight);
-
- if (widthMode != MeasureSpec.EXACTLY) {
- width = Math.max(width, params.mRight);
- }
- if (heightMode != MeasureSpec.EXACTLY) {
- height = Math.max(height, params.mBottom);
- }
-
- if (child != ignore || verticalGravity) {
- left = Math.min(left, params.mLeft - params.leftMargin);
- top = Math.min(top, params.mTop - params.topMargin);
- }
-
- if (child != ignore || horizontalGravity) {
- right = Math.max(right, params.mRight + params.rightMargin);
- bottom = Math.max(bottom, params.mBottom + params.bottomMargin);
- }
- }
- }
-
- if (mHasBaselineAlignedChild) {
- for (int i = 0; i < len; i++) {
- View child = getChildAt(i);
- if (child.getVisibility() != GONE) {
- LayoutParams params = (LayoutParams) child.getLayoutParams();
- alignBaseline(child, params);
-
- if (child != ignore || verticalGravity) {
- left = Math.min(left, params.mLeft - params.leftMargin);
- top = Math.min(top, params.mTop - params.topMargin);
- }
-
- if (child != ignore || horizontalGravity) {
- right = Math.max(right, params.mRight + params.rightMargin);
- bottom = Math.max(bottom, params.mBottom + params.bottomMargin);
- }
- }
- }
- }
-
- if (widthMode != MeasureSpec.EXACTLY) {
- // Width already has left padding in it since it was calculated by looking at
- // the right of each child view
- width += mPaddingRight;
-
- if (mLayoutParams.width >= 0) {
- width = Math.max(width, mLayoutParams.width);
- }
-
- width = Math.max(width, getSuggestedMinimumWidth());
- width = resolveSize(width, widthMeasureSpec);
- }
- if (heightMode != MeasureSpec.EXACTLY) {
- // Height already has top padding in it since it was calculated by looking at
- // the bottom of each child view
- height += mPaddingBottom;
-
- if (mLayoutParams.height >= 0) {
- height = Math.max(height, mLayoutParams.height);
- }
-
- height = Math.max(height, getSuggestedMinimumHeight());
- height = resolveSize(height, heightMeasureSpec);
- }
-
- if (horizontalGravity || verticalGravity) {
- final Rect selfBounds = mSelfBounds;
- selfBounds.set(mPaddingLeft, mPaddingTop, width - mPaddingRight,
- height - mPaddingBottom);
-
- final Rect contentBounds = mContentBounds;
- Gravity.apply(mGravity, right - left, bottom - top, selfBounds, contentBounds);
-
- final int horizontalOffset = contentBounds.left - left;
- final int verticalOffset = contentBounds.top - top;
- if (horizontalOffset != 0 || verticalOffset != 0) {
- for (int i = 0; i < len; i++) {
- View child = getChildAt(i);
- if (child.getVisibility() != GONE && child != ignore) {
- LayoutParams params = (LayoutParams) child.getLayoutParams();
- params.mLeft += horizontalOffset;
- params.mRight += horizontalOffset;
- params.mTop += verticalOffset;
- params.mBottom += verticalOffset;
- }
- }
- }
- }
-
- setMeasuredDimension(width, height);
- }
-
- private void alignBaseline(View child, LayoutParams params) {
- int[] rules = params.getRules();
- int anchorBaseline = getRelatedViewBaseline(rules, ALIGN_BASELINE);
-
- if (anchorBaseline != -1) {
- LayoutParams anchorParams = getRelatedViewParams(rules, ALIGN_BASELINE);
- if (anchorParams != null) {
- int offset = anchorParams.mTop + anchorBaseline;
- int baseline = child.getBaseline();
- if (baseline != -1) {
- offset -= baseline;
- }
- int height = params.mBottom - params.mTop;
- params.mTop = offset;
- params.mBottom = params.mTop + height;
- }
- }
-
- if (mBaselineView == null) {
- mBaselineView = child;
- } else {
- LayoutParams lp = (LayoutParams) mBaselineView.getLayoutParams();
- if (params.mTop < lp.mTop || (params.mTop == lp.mTop && params.mLeft < lp.mLeft)) {
- mBaselineView = child;
- }
- }
- }
-
- /**
- * Measure a child. The child should have left, top, right and bottom information
- * stored in its LayoutParams. If any of these values is -1 it means that the view
- * can extend up to the corresponding edge.
- *
- * @param child Child to measure
- * @param params LayoutParams associated with child
- * @param myWidth Width of the the RelativeLayout
- * @param myHeight Height of the RelativeLayout
- */
- private void measureChild(View child, LayoutParams params, int myWidth,
- int myHeight) {
-
- int childWidthMeasureSpec = getChildMeasureSpec(params.mLeft,
- params.mRight, params.width,
- params.leftMargin, params.rightMargin,
- mPaddingLeft, mPaddingRight,
- myWidth);
- int childHeightMeasureSpec = getChildMeasureSpec(params.mTop,
- params.mBottom, params.height,
- params.topMargin, params.bottomMargin,
- mPaddingTop, mPaddingBottom,
- myHeight);
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- }
-
- /**
- * Get a measure spec that accounts for all of the constraints on this view.
- * This includes size contstraints imposed by the RelativeLayout as well as
- * the View's desired dimension.
- *
- * @param childStart The left or top field of the child's layout params
- * @param childEnd The right or bottom field of the child's layout params
- * @param childSize The child's desired size (the width or height field of
- * the child's layout params)
- * @param startMargin The left or top margin
- * @param endMargin The right or bottom margin
- * @param startPadding mPaddingLeft or mPaddingTop
- * @param endPadding mPaddingRight or mPaddingBottom
- * @param mySize The width or height of this view (the RelativeLayout)
- * @return MeasureSpec for the child
- */
- private int getChildMeasureSpec(int childStart, int childEnd,
- int childSize, int startMargin, int endMargin, int startPadding,
- int endPadding, int mySize) {
- int childSpecMode = 0;
- int childSpecSize = 0;
-
- // Figure out start and end bounds.
- int tempStart = childStart;
- int tempEnd = childEnd;
-
- // If the view did not express a layout constraint for an edge, use
- // view's margins and our padding
- if (tempStart < 0) {
- tempStart = startPadding + startMargin;
- }
- if (tempEnd < 0) {
- tempEnd = mySize - endPadding - endMargin;
- }
-
- // Figure out maximum size available to this view
- int maxAvailable = tempEnd - tempStart;
-
- if (childStart >= 0 && childEnd >= 0) {
- // Constraints fixed both edges, so child must be an exact size
- childSpecMode = MeasureSpec.EXACTLY;
- childSpecSize = maxAvailable;
- } else {
- if (childSize >= 0) {
- // Child wanted an exact size. Give as much as possible
- childSpecMode = MeasureSpec.EXACTLY;
-
- if (maxAvailable >= 0) {
- // We have a maxmum size in this dimension.
- childSpecSize = Math.min(maxAvailable, childSize);
- } else {
- // We can grow in this dimension.
- childSpecSize = childSize;
- }
- } else if (childSize == LayoutParams.FILL_PARENT) {
- // Child wanted to be as big as possible. Give all availble
- // space
- childSpecMode = MeasureSpec.EXACTLY;
- childSpecSize = maxAvailable;
- } else if (childSize == LayoutParams.WRAP_CONTENT) {
- // Child wants to wrap content. Use AT_MOST
- // to communicate available space if we know
- // our max size
- if (maxAvailable >= 0) {
- // We have a maxmum size in this dimension.
- childSpecMode = MeasureSpec.AT_MOST;
- childSpecSize = maxAvailable;
- } else {
- // We can grow in this dimension. Child can be as big as it
- // wants
- childSpecMode = MeasureSpec.UNSPECIFIED;
- childSpecSize = 0;
- }
- }
- }
-
- return MeasureSpec.makeMeasureSpec(childSpecSize, childSpecMode);
- }
-
- /**
- * After the child has been measured, assign it a position. Some views may
- * already have final values for l,t,r,b. Others may have one or both edges
- * unfixed (i.e. set to -1) in each dimension. These will get positioned
- * based on which edge is fixed, the view's desired dimension, and whether
- * or not it is centered.
- *
- * @param child Child to position
- * @param params LayoutParams associated with child
- * @param myWidth Width of the the RelativeLayout
- * @param myHeight Height of the RelativeLayout
- */
- private void positionChild(View child, LayoutParams params, int myWidth, int myHeight) {
- int[] rules = params.getRules();
-
- if (params.mLeft < 0 && params.mRight >= 0) {
- // Right is fixed, but left varies
- params.mLeft = params.mRight - child.getMeasuredWidth();
- } else if (params.mLeft >= 0 && params.mRight < 0) {
- // Left is fixed, but right varies
- params.mRight = params.mLeft + child.getMeasuredWidth();
- } else if (params.mLeft < 0 && params.mRight < 0) {
- // Both left and right vary
- if (0 != rules[CENTER_IN_PARENT] || 0 != rules[CENTER_HORIZONTAL]) {
- centerHorizontal(child, params, myWidth);
- } else {
- params.mLeft = mPaddingLeft + params.leftMargin;
- params.mRight = params.mLeft + child.getMeasuredWidth();
- }
- }
-
- if (params.mTop < 0 && params.mBottom >= 0) {
- // Bottom is fixed, but top varies
- params.mTop = params.mBottom - child.getMeasuredHeight();
- } else if (params.mTop >= 0 && params.mBottom < 0) {
- // Top is fixed, but bottom varies
- params.mBottom = params.mTop + child.getMeasuredHeight();
- } else if (params.mTop < 0 && params.mBottom < 0) {
- // Both top and bottom vary
- if (0 != rules[CENTER_IN_PARENT] || 0 != rules[CENTER_VERTICAL]) {
- centerVertical(child, params, myHeight);
- } else {
- params.mTop = mPaddingTop + params.topMargin;
- params.mBottom = params.mTop + child.getMeasuredHeight();
- }
- }
- }
-
- /**
- * Set l,t,r,b values in the LayoutParams for one view based on its layout rules.
- * Big assumption #1: All antecedents of this view have been sized & positioned
- * Big assumption #2: The dimensions of the parent view (the RelativeLayout)
- * are already known if they are needed.
- *
- * @param childParams LayoutParams for the view being positioned
- * @param myWidth Width of the the RelativeLayout
- * @param myHeight Height of the RelativeLayout
- */
- private void applySizeRules(LayoutParams childParams, int myWidth, int myHeight) {
- int[] rules = childParams.getRules();
- RelativeLayout.LayoutParams anchorParams;
-
- // -1 indicated a "soft requirement" in that direction. For example:
- // left=10, right=-1 means the view must start at 10, but can go as far as it wants to the right
- // left =-1, right=10 means the view must end at 10, but can go as far as it wants to the left
- // left=10, right=20 means the left and right ends are both fixed
- childParams.mLeft = -1;
- childParams.mRight = -1;
-
- anchorParams = getRelatedViewParams(rules, LEFT_OF);
- if (anchorParams != null) {
- childParams.mRight = anchorParams.mLeft - (anchorParams.leftMargin +
- childParams.rightMargin);
- } else if (childParams.alignWithParent && rules[LEFT_OF] != 0) {
- if (myWidth >= 0) {
- childParams.mRight = myWidth - mPaddingRight - childParams.rightMargin;
- } else {
- // FIXME uh oh...
- }
- }
-
- anchorParams = getRelatedViewParams(rules, RIGHT_OF);
- if (anchorParams != null) {
- childParams.mLeft = anchorParams.mRight + (anchorParams.rightMargin +
- childParams.leftMargin);
- } else if (childParams.alignWithParent && rules[RIGHT_OF] != 0) {
- childParams.mLeft = mPaddingLeft + childParams.leftMargin;
- }
-
- anchorParams = getRelatedViewParams(rules, ALIGN_LEFT);
- if (anchorParams != null) {
- childParams.mLeft = anchorParams.mLeft + childParams.leftMargin;
- } else if (childParams.alignWithParent && rules[ALIGN_LEFT] != 0) {
- childParams.mLeft = mPaddingLeft + childParams.leftMargin;
- }
-
- anchorParams = getRelatedViewParams(rules, ALIGN_RIGHT);
- if (anchorParams != null) {
- childParams.mRight = anchorParams.mRight - childParams.rightMargin;
- } else if (childParams.alignWithParent && rules[ALIGN_RIGHT] != 0) {
- if (myWidth >= 0) {
- childParams.mRight = myWidth - mPaddingRight - childParams.rightMargin;
- } else {
- // FIXME uh oh...
- }
- }
-
- if (0 != rules[ALIGN_PARENT_LEFT]) {
- childParams.mLeft = mPaddingLeft + childParams.leftMargin;
- }
-
- if (0 != rules[ALIGN_PARENT_RIGHT]) {
- if (myWidth >= 0) {
- childParams.mRight = myWidth - mPaddingRight - childParams.rightMargin;
- } else {
- // FIXME uh oh...
- }
- }
-
- childParams.mTop = -1;
- childParams.mBottom = -1;
-
- anchorParams = getRelatedViewParams(rules, ABOVE);
- if (anchorParams != null) {
- childParams.mBottom = anchorParams.mTop - (anchorParams.topMargin +
- childParams.bottomMargin);
- } else if (childParams.alignWithParent && rules[ABOVE] != 0) {
- if (myHeight >= 0) {
- childParams.mBottom = myHeight - mPaddingBottom - childParams.bottomMargin;
- } else {
- // FIXME uh oh...
- }
- }
-
- anchorParams = getRelatedViewParams(rules, BELOW);
- if (anchorParams != null) {
- childParams.mTop = anchorParams.mBottom + (anchorParams.bottomMargin +
- childParams.topMargin);
- } else if (childParams.alignWithParent && rules[BELOW] != 0) {
- childParams.mTop = mPaddingTop + childParams.topMargin;
- }
-
- anchorParams = getRelatedViewParams(rules, ALIGN_TOP);
- if (anchorParams != null) {
- childParams.mTop = anchorParams.mTop + childParams.topMargin;
- } else if (childParams.alignWithParent && rules[ALIGN_TOP] != 0) {
- childParams.mTop = mPaddingTop + childParams.topMargin;
- }
-
- anchorParams = getRelatedViewParams(rules, ALIGN_BOTTOM);
- if (anchorParams != null) {
- childParams.mBottom = anchorParams.mBottom - childParams.bottomMargin;
- } else if (childParams.alignWithParent && rules[ALIGN_BOTTOM] != 0) {
- if (myHeight >= 0) {
- childParams.mBottom = myHeight - mPaddingBottom - childParams.bottomMargin;
- } else {
- // FIXME uh oh...
- }
- }
-
- if (0 != rules[ALIGN_PARENT_TOP]) {
- childParams.mTop = mPaddingTop + childParams.topMargin;
- }
-
- if (0 != rules[ALIGN_PARENT_BOTTOM]) {
- if (myHeight >= 0) {
- childParams.mBottom = myHeight - mPaddingBottom - childParams.bottomMargin;
- } else {
- // FIXME uh oh...
- }
- }
-
- if (rules[ALIGN_BASELINE] != 0) {
- mHasBaselineAlignedChild = true;
- }
- }
-
- private View getRelatedView(int[] rules, int relation) {
- int id = rules[relation];
- if (id != 0) {
- View v = findViewById(id);
- if (v == null) {
- return null;
- }
-
- // Find the first non-GONE view up the chain
- while (v.getVisibility() == View.GONE) {
- rules = ((LayoutParams) v.getLayoutParams()).getRules();
- v = v.findViewById(rules[relation]);
- if (v == null) {
- return null;
- }
- }
-
- return v;
- }
-
- return null;
- }
-
- private LayoutParams getRelatedViewParams(int[] rules, int relation) {
- View v = getRelatedView(rules, relation);
- if (v != null) {
- ViewGroup.LayoutParams params = v.getLayoutParams();
- if (params instanceof LayoutParams) {
- return (LayoutParams) v.getLayoutParams();
- }
- }
- return null;
- }
-
- private int getRelatedViewBaseline(int[] rules, int relation) {
- View v = getRelatedView(rules, relation);
- if (v != null) {
- return v.getBaseline();
- }
- return -1;
- }
-
- private void centerHorizontal(View child, LayoutParams params, int myWidth) {
- int childWidth = child.getMeasuredWidth();
- int left = (myWidth - childWidth) / 2;
-
- params.mLeft = left;
- params.mRight = left + childWidth;
- }
-
- private void centerVertical(View child, LayoutParams params, int myHeight) {
- int childHeight = child.getMeasuredHeight();
- int top = (myHeight - childHeight) / 2;
-
- params.mTop = top;
- params.mBottom = top + childHeight;
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- // The layout has actually already been performed and the positions
- // cached. Apply the cached values to the children.
- int count = getChildCount();
-
- for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
- if (child.getVisibility() != GONE) {
- RelativeLayout.LayoutParams st =
- (RelativeLayout.LayoutParams) child.getLayoutParams();
- child.layout(st.mLeft, st.mTop, st.mRight, st.mBottom);
-
- }
- }
- }
-
- @Override
- public LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new RelativeLayout.LayoutParams(getContext(), attrs);
- }
-
- /**
- * Returns a set of layout parameters with a width of
- * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT},
- * a height of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and no spanning.
- */
- @Override
- protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
- return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- }
-
- // Override to allow type-checking of LayoutParams.
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof RelativeLayout.LayoutParams;
- }
-
- @Override
- protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return new LayoutParams(p);
- }
-
- /**
- * Per-child layout information associated with RelativeLayout.
- *
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignWithParentIfMissing
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_toLeftOf
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_toRightOf
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_above
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_below
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignBaseline
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignLeft
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignTop
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignRight
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignBottom
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentLeft
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentTop
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentRight
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignParentBottom
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerInParent
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerHorizontal
- * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerVertical
- */
- public static class LayoutParams extends ViewGroup.MarginLayoutParams {
- private int[] mRules = new int[VERB_COUNT];
- private int mLeft, mTop, mRight, mBottom;
-
- /**
- * When true, uses the parent as the anchor if the anchor doesn't exist or if
- * the anchor's visibility is GONE.
- */
- public boolean alignWithParent;
-
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
-
- TypedArray a = c.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.RelativeLayout_Layout);
-
- final int[] rules = mRules;
-
- final int N = a.getIndexCount();
- for (int i = 0; i < N; i++) {
- int attr = a.getIndex(i);
- switch (attr) {
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignWithParentIfMissing:
- alignWithParent = a.getBoolean(attr, false);
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toLeftOf:
- rules[LEFT_OF] = a.getResourceId(attr, 0);
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toRightOf:
- rules[RIGHT_OF] = a.getResourceId(attr, 0);
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_above:
- rules[ABOVE] = a.getResourceId(attr, 0);
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_below:
- rules[BELOW] = a.getResourceId(attr, 0);
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignBaseline:
- rules[ALIGN_BASELINE] = a.getResourceId(attr, 0);
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignLeft:
- rules[ALIGN_LEFT] = a.getResourceId(attr, 0);
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignTop:
- rules[ALIGN_TOP] = a.getResourceId(attr, 0);
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignRight:
- rules[ALIGN_RIGHT] = a.getResourceId(attr, 0);
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignBottom:
- rules[ALIGN_BOTTOM] = a.getResourceId(attr, 0);
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentLeft:
- rules[ALIGN_PARENT_LEFT] = a.getBoolean(attr, false) ? TRUE : 0;
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentTop:
- rules[ALIGN_PARENT_TOP] = a.getBoolean(attr, false) ? TRUE : 0;
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentRight:
- rules[ALIGN_PARENT_RIGHT] = a.getBoolean(attr, false) ? TRUE : 0;
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentBottom:
- rules[ALIGN_PARENT_BOTTOM] = a.getBoolean(attr, false) ? TRUE : 0;
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerInParent:
- rules[CENTER_IN_PARENT] = a.getBoolean(attr, false) ? TRUE : 0;
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerHorizontal:
- rules[CENTER_HORIZONTAL] = a.getBoolean(attr, false) ? TRUE : 0;
- break;
- case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerVertical:
- rules[CENTER_VERTICAL] = a.getBoolean(attr, false) ? TRUE : 0;
- break;
- }
- }
-
- a.recycle();
- }
-
- public LayoutParams(int w, int h) {
- super(w, h);
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(ViewGroup.LayoutParams source) {
- super(source);
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(ViewGroup.MarginLayoutParams source) {
- super(source);
- }
-
- @Override
- public String debug(String output) {
- return output + "ViewGroup.LayoutParams={ width=" + sizeToString(width) +
- ", height=" + sizeToString(height) + " }";
- }
-
- /**
- * Adds a layout rule to be interpreted by the RelativeLayout. This
- * method should only be used for constraints that don't refer to another sibling
- * (e.g., CENTER_IN_PARENT) or take a boolean value ({@link RelativeLayout#TRUE}
- * for true or - for false). To specify a verb that takes a subject, use
- * {@link #addRule(int, int)} instead.
- *
- * @param verb One of the verbs defined by
- * {@link android.widget.RelativeLayout RelativeLayout}, such as
- * ALIGN_WITH_PARENT_LEFT.
- * @see #addRule(int, int)
- */
- public void addRule(int verb) {
- mRules[verb] = TRUE;
- }
-
- /**
- * Adds a layout rule to be interpreted by the RelativeLayout. Use this for
- * verbs that take a target, such as a sibling (ALIGN_RIGHT) or a boolean
- * value (VISIBLE).
- *
- * @param verb One of the verbs defined by
- * {@link android.widget.RelativeLayout RelativeLayout}, such as
- * ALIGN_WITH_PARENT_LEFT.
- * @param anchor The id of another view to use as an anchor,
- * or a boolean value(represented as {@link RelativeLayout#TRUE})
- * for true or 0 for false). For verbs that don't refer to another sibling
- * (for example, ALIGN_WITH_PARENT_BOTTOM) just use -1.
- * @see #addRule(int)
- */
- public void addRule(int verb, int anchor) {
- mRules[verb] = anchor;
- }
-
- /**
- * Retrieves a complete list of all supported rules, where the index is the rule
- * verb, and the element value is the value specified, or "false" if it was never
- * set.
- *
- * @return the supported rules
- * @see #addRule(int, int)
- */
- public int[] getRules() {
- return mRules;
- }
- }
-}
diff --git a/core/java/android/widget/RemoteViews.aidl b/core/java/android/widget/RemoteViews.aidl
deleted file mode 100644
index ec86410..0000000
--- a/core/java/android/widget/RemoteViews.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2007, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-parcelable RemoteViews;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
deleted file mode 100644
index e000d2e..0000000
--- a/core/java/android/widget/RemoteViews.java
+++ /dev/null
@@ -1,834 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.app.PendingIntent;
-import android.app.PendingIntent.CanceledException;
-import android.content.Context;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.RemotableViewMethod;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.LayoutInflater.Filter;
-import android.view.View.OnClickListener;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-
-import java.lang.Class;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-
-
-/**
- * A class that describes a view hierarchy that can be displayed in
- * another process. The hierarchy is inflated from a layout resource
- * file, and this class provides some basic operations for modifying
- * the content of the inflated hierarchy.
- */
-public class RemoteViews implements Parcelable, Filter {
-
- private static final String LOG_TAG = "RemoteViews";
-
- /**
- * The package name of the package containing the layout
- * resource. (Added to the parcel)
- */
- private String mPackage;
-
- /**
- * The resource ID of the layout file. (Added to the parcel)
- */
- private int mLayoutId;
-
- /**
- * The Context object used to inflate the layout file. Also may
- * be used by actions if they need access to the senders resources.
- */
- private Context mContext;
-
- /**
- * An array of actions to perform on the view tree once it has been
- * inflated
- */
- private ArrayList<Action> mActions;
-
-
- /**
- * This annotation indicates that a subclass of View is alllowed to be used
- * with the {@link android.widget.RemoteViews} mechanism.
- */
- @Target({ ElementType.TYPE })
- @Retention(RetentionPolicy.RUNTIME)
- public @interface RemoteView {
- }
-
- /**
- * Exception to send when something goes wrong executing an action
- *
- */
- public static class ActionException extends RuntimeException {
- public ActionException(Exception ex) {
- super(ex);
- }
- public ActionException(String message) {
- super(message);
- }
- }
-
- /**
- * Base class for all actions that can be performed on an
- * inflated view.
- *
- */
- private abstract static class Action implements Parcelable {
- public abstract void apply(View root) throws ActionException;
-
- public int describeContents() {
- return 0;
- }
- };
-
- /**
- * Equivalent to calling
- * {@link android.view.View#setOnClickListener(android.view.View.OnClickListener)}
- * to launch the provided {@link PendingIntent}.
- */
- private class SetOnClickPendingIntent extends Action {
- public SetOnClickPendingIntent(int id, PendingIntent pendingIntent) {
- this.viewId = id;
- this.pendingIntent = pendingIntent;
- }
-
- public SetOnClickPendingIntent(Parcel parcel) {
- viewId = parcel.readInt();
- pendingIntent = PendingIntent.readPendingIntentOrNullFromParcel(parcel);
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(TAG);
- dest.writeInt(viewId);
- pendingIntent.writeToParcel(dest, 0 /* no flags */);
- }
-
- @Override
- public void apply(View root) {
- final View target = root.findViewById(viewId);
- if (target != null && pendingIntent != null) {
- OnClickListener listener = new OnClickListener() {
- public void onClick(View v) {
- try {
- // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
- pendingIntent.send();
- } catch (CanceledException e) {
- throw new ActionException(e.toString());
- }
- }
- };
- target.setOnClickListener(listener);
- }
- }
-
- int viewId;
- PendingIntent pendingIntent;
-
- public final static int TAG = 1;
- }
-
- /**
- * Equivalent to calling a combination of {@link Drawable#setAlpha(int)},
- * {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)},
- * and/or {@link Drawable#setLevel(int)} on the {@link Drawable} of a given view.
- * <p>
- * These operations will be performed on the {@link Drawable} returned by the
- * target {@link View#getBackground()} by default. If targetBackground is false,
- * we assume the target is an {@link ImageView} and try applying the operations
- * to {@link ImageView#getDrawable()}.
- * <p>
- * You can omit specific calls by marking their values with null or -1.
- */
- private class SetDrawableParameters extends Action {
- public SetDrawableParameters(int id, boolean targetBackground, int alpha,
- int colorFilter, PorterDuff.Mode mode, int level) {
- this.viewId = id;
- this.targetBackground = targetBackground;
- this.alpha = alpha;
- this.colorFilter = colorFilter;
- this.filterMode = mode;
- this.level = level;
- }
-
- public SetDrawableParameters(Parcel parcel) {
- viewId = parcel.readInt();
- targetBackground = parcel.readInt() != 0;
- alpha = parcel.readInt();
- colorFilter = parcel.readInt();
- boolean hasMode = parcel.readInt() != 0;
- if (hasMode) {
- filterMode = PorterDuff.Mode.valueOf(parcel.readString());
- } else {
- filterMode = null;
- }
- level = parcel.readInt();
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(TAG);
- dest.writeInt(viewId);
- dest.writeInt(targetBackground ? 1 : 0);
- dest.writeInt(alpha);
- dest.writeInt(colorFilter);
- if (filterMode != null) {
- dest.writeInt(1);
- dest.writeString(filterMode.toString());
- } else {
- dest.writeInt(0);
- }
- dest.writeInt(level);
- }
-
- @Override
- public void apply(View root) {
- final View target = root.findViewById(viewId);
- if (target == null) {
- return;
- }
-
- // Pick the correct drawable to modify for this view
- Drawable targetDrawable = null;
- if (targetBackground) {
- targetDrawable = target.getBackground();
- } else if (target instanceof ImageView) {
- ImageView imageView = (ImageView) target;
- targetDrawable = imageView.getDrawable();
- }
-
- // Perform modifications only if values are set correctly
- if (alpha != -1) {
- targetDrawable.setAlpha(alpha);
- }
- if (colorFilter != -1 && filterMode != null) {
- targetDrawable.setColorFilter(colorFilter, filterMode);
- }
- if (level != -1) {
- targetDrawable.setLevel(level);
- }
- }
-
- int viewId;
- boolean targetBackground;
- int alpha;
- int colorFilter;
- PorterDuff.Mode filterMode;
- int level;
-
- public final static int TAG = 3;
- }
-
- /**
- * Base class for the reflection actions.
- */
- private class ReflectionAction extends Action {
- static final int TAG = 2;
-
- static final int BOOLEAN = 1;
- static final int BYTE = 2;
- static final int SHORT = 3;
- static final int INT = 4;
- static final int LONG = 5;
- static final int FLOAT = 6;
- static final int DOUBLE = 7;
- static final int CHAR = 8;
- static final int STRING = 9;
- static final int CHAR_SEQUENCE = 10;
- static final int URI = 11;
- static final int BITMAP = 12;
-
- int viewId;
- String methodName;
- int type;
- Object value;
-
- ReflectionAction(int viewId, String methodName, int type, Object value) {
- this.viewId = viewId;
- this.methodName = methodName;
- this.type = type;
- this.value = value;
- }
-
- ReflectionAction(Parcel in) {
- this.viewId = in.readInt();
- this.methodName = in.readString();
- this.type = in.readInt();
- if (false) {
- Log.d("RemoteViews", "read viewId=0x" + Integer.toHexString(this.viewId)
- + " methodName=" + this.methodName + " type=" + this.type);
- }
- switch (this.type) {
- case BOOLEAN:
- this.value = in.readInt() != 0;
- break;
- case BYTE:
- this.value = in.readByte();
- break;
- case SHORT:
- this.value = (short)in.readInt();
- break;
- case INT:
- this.value = in.readInt();
- break;
- case LONG:
- this.value = in.readLong();
- break;
- case FLOAT:
- this.value = in.readFloat();
- break;
- case DOUBLE:
- this.value = in.readDouble();
- break;
- case CHAR:
- this.value = (char)in.readInt();
- break;
- case STRING:
- this.value = in.readString();
- break;
- case CHAR_SEQUENCE:
- this.value = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
- break;
- case URI:
- this.value = Uri.CREATOR.createFromParcel(in);
- break;
- case BITMAP:
- this.value = Bitmap.CREATOR.createFromParcel(in);
- break;
- default:
- break;
- }
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(TAG);
- out.writeInt(this.viewId);
- out.writeString(this.methodName);
- out.writeInt(this.type);
- if (false) {
- Log.d("RemoteViews", "write viewId=0x" + Integer.toHexString(this.viewId)
- + " methodName=" + this.methodName + " type=" + this.type);
- }
- switch (this.type) {
- case BOOLEAN:
- out.writeInt(((Boolean)this.value).booleanValue() ? 1 : 0);
- break;
- case BYTE:
- out.writeByte(((Byte)this.value).byteValue());
- break;
- case SHORT:
- out.writeInt(((Short)this.value).shortValue());
- break;
- case INT:
- out.writeInt(((Integer)this.value).intValue());
- break;
- case LONG:
- out.writeLong(((Long)this.value).longValue());
- break;
- case FLOAT:
- out.writeFloat(((Float)this.value).floatValue());
- break;
- case DOUBLE:
- out.writeDouble(((Double)this.value).doubleValue());
- break;
- case CHAR:
- out.writeInt((int)((Character)this.value).charValue());
- break;
- case STRING:
- out.writeString((String)this.value);
- break;
- case CHAR_SEQUENCE:
- TextUtils.writeToParcel((CharSequence)this.value, out, flags);
- break;
- case URI:
- ((Uri)this.value).writeToParcel(out, flags);
- break;
- case BITMAP:
- ((Bitmap)this.value).writeToParcel(out, flags);
- break;
- default:
- break;
- }
- }
-
- private Class getParameterType() {
- switch (this.type) {
- case BOOLEAN:
- return boolean.class;
- case BYTE:
- return byte.class;
- case SHORT:
- return short.class;
- case INT:
- return int.class;
- case LONG:
- return long.class;
- case FLOAT:
- return float.class;
- case DOUBLE:
- return double.class;
- case CHAR:
- return char.class;
- case STRING:
- return String.class;
- case CHAR_SEQUENCE:
- return CharSequence.class;
- case URI:
- return Uri.class;
- case BITMAP:
- return Bitmap.class;
- default:
- return null;
- }
- }
-
- @Override
- public void apply(View root) {
- final View view = root.findViewById(viewId);
- if (view == null) {
- throw new ActionException("can't find view: 0x" + Integer.toHexString(viewId));
- }
-
- Class param = getParameterType();
- if (param == null) {
- throw new ActionException("bad type: " + this.type);
- }
-
- Class klass = view.getClass();
- Method method = null;
- try {
- method = klass.getMethod(this.methodName, getParameterType());
- }
- catch (NoSuchMethodException ex) {
- throw new ActionException("view: " + klass.getName() + " doesn't have method: "
- + this.methodName + "(" + param.getName() + ")");
- }
-
- if (!method.isAnnotationPresent(RemotableViewMethod.class)) {
- throw new ActionException("view: " + klass.getName()
- + " can't use method with RemoteViews: "
- + this.methodName + "(" + param.getName() + ")");
- }
-
- try {
- if (false) {
- Log.d("RemoteViews", "view: " + klass.getName() + " calling method: "
- + this.methodName + "(" + param.getName() + ") with "
- + (this.value == null ? "null" : this.value.getClass().getName()));
- }
- method.invoke(view, this.value);
- }
- catch (Exception ex) {
- throw new ActionException(ex);
- }
- }
- }
-
-
- /**
- * Create a new RemoteViews object that will display the views contained
- * in the specified layout file.
- *
- * @param packageName Name of the package that contains the layout resource
- * @param layoutId The id of the layout resource
- */
- public RemoteViews(String packageName, int layoutId) {
- mPackage = packageName;
- mLayoutId = layoutId;
- }
-
- /**
- * Reads a RemoteViews object from a parcel.
- *
- * @param parcel
- */
- public RemoteViews(Parcel parcel) {
- mPackage = parcel.readString();
- mLayoutId = parcel.readInt();
- int count = parcel.readInt();
- if (count > 0) {
- mActions = new ArrayList<Action>(count);
- for (int i=0; i<count; i++) {
- int tag = parcel.readInt();
- switch (tag) {
- case SetOnClickPendingIntent.TAG:
- mActions.add(new SetOnClickPendingIntent(parcel));
- break;
- case SetDrawableParameters.TAG:
- mActions.add(new SetDrawableParameters(parcel));
- break;
- case ReflectionAction.TAG:
- mActions.add(new ReflectionAction(parcel));
- break;
- default:
- throw new ActionException("Tag " + tag + " not found");
- }
- }
- }
- }
-
- public String getPackage() {
- return mPackage;
- }
-
- public int getLayoutId() {
- return mLayoutId;
- }
-
- /**
- * Add an action to be executed on the remote side when apply is called.
- *
- * @param a The action to add
- */
- private void addAction(Action a) {
- if (mActions == null) {
- mActions = new ArrayList<Action>();
- }
- mActions.add(a);
- }
-
- /**
- * Equivalent to calling View.setVisibility
- *
- * @param viewId The id of the view whose visibility should change
- * @param visibility The new visibility for the view
- */
- public void setViewVisibility(int viewId, int visibility) {
- setInt(viewId, "setVisibility", visibility);
- }
-
- /**
- * Equivalent to calling TextView.setText
- *
- * @param viewId The id of the view whose text should change
- * @param text The new text for the view
- */
- public void setTextViewText(int viewId, CharSequence text) {
- setCharSequence(viewId, "setText", text);
- }
-
- /**
- * Equivalent to calling ImageView.setImageResource
- *
- * @param viewId The id of the view whose drawable should change
- * @param srcId The new resource id for the drawable
- */
- public void setImageViewResource(int viewId, int srcId) {
- setInt(viewId, "setImageResource", srcId);
- }
-
- /**
- * Equivalent to calling ImageView.setImageURI
- *
- * @param viewId The id of the view whose drawable should change
- * @param uri The Uri for the image
- */
- public void setImageViewUri(int viewId, Uri uri) {
- setUri(viewId, "setImageURI", uri);
- }
-
- /**
- * Equivalent to calling ImageView.setImageBitmap
- *
- * @param viewId The id of the view whose drawable should change
- * @param bitmap The new Bitmap for the drawable
- */
- public void setImageViewBitmap(int viewId, Bitmap bitmap) {
- setBitmap(viewId, "setImageBitmap", bitmap);
- }
-
- /**
- * Equivalent to calling {@link Chronometer#setBase Chronometer.setBase},
- * {@link Chronometer#setFormat Chronometer.setFormat},
- * and {@link Chronometer#start Chronometer.start()} or
- * {@link Chronometer#stop Chronometer.stop()}.
- *
- * @param viewId The id of the view whose text should change
- * @param base The time at which the timer would have read 0:00. This
- * time should be based off of
- * {@link android.os.SystemClock#elapsedRealtime SystemClock.elapsedRealtime()}.
- * @param format The Chronometer format string, or null to
- * simply display the timer value.
- * @param started True if you want the clock to be started, false if not.
- */
- public void setChronometer(int viewId, long base, String format, boolean started) {
- setLong(viewId, "setBase", base);
- setString(viewId, "setFormat", format);
- setBoolean(viewId, "setStarted", started);
- }
-
- /**
- * Equivalent to calling {@link ProgressBar#setMax ProgressBar.setMax},
- * {@link ProgressBar#setProgress ProgressBar.setProgress}, and
- * {@link ProgressBar#setIndeterminate ProgressBar.setIndeterminate}
- *
- * If indeterminate is true, then the values for max and progress are ignored.
- *
- * @param viewId The id of the view whose text should change
- * @param max The 100% value for the progress bar
- * @param progress The current value of the progress bar.
- * @param indeterminate True if the progress bar is indeterminate,
- * false if not.
- */
- public void setProgressBar(int viewId, int max, int progress,
- boolean indeterminate) {
- setBoolean(viewId, "setIndeterminate", indeterminate);
- if (!indeterminate) {
- setInt(viewId, "setMax", max);
- setInt(viewId, "setProgress", progress);
- }
- }
-
- /**
- * Equivalent to calling
- * {@link android.view.View#setOnClickListener(android.view.View.OnClickListener)}
- * to launch the provided {@link PendingIntent}.
- *
- * @param viewId The id of the view that will trigger the {@link PendingIntent} when clicked
- * @param pendingIntent The {@link PendingIntent} to send when user clicks
- */
- public void setOnClickPendingIntent(int viewId, PendingIntent pendingIntent) {
- addAction(new SetOnClickPendingIntent(viewId, pendingIntent));
- }
-
- /**
- * @hide
- * Equivalent to calling a combination of {@link Drawable#setAlpha(int)},
- * {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)},
- * and/or {@link Drawable#setLevel(int)} on the {@link Drawable} of a given
- * view.
- * <p>
- * You can omit specific calls by marking their values with null or -1.
- *
- * @param viewId The id of the view that contains the target
- * {@link Drawable}
- * @param targetBackground If true, apply these parameters to the
- * {@link Drawable} returned by
- * {@link android.view.View#getBackground()}. Otherwise, assume
- * the target view is an {@link ImageView} and apply them to
- * {@link ImageView#getDrawable()}.
- * @param alpha Specify an alpha value for the drawable, or -1 to leave
- * unchanged.
- * @param colorFilter Specify a color for a
- * {@link android.graphics.ColorFilter} for this drawable, or -1
- * to leave unchanged.
- * @param mode Specify a PorterDuff mode for this drawable, or null to leave
- * unchanged.
- * @param level Specify the level for the drawable, or -1 to leave
- * unchanged.
- */
- public void setDrawableParameters(int viewId, boolean targetBackground, int alpha,
- int colorFilter, PorterDuff.Mode mode, int level) {
- addAction(new SetDrawableParameters(viewId, targetBackground, alpha,
- colorFilter, mode, level));
- }
-
- /**
- * Equivalent to calling {@link android.widget.TextView#setTextColor(int)}.
- *
- * @param viewId The id of the view whose text should change
- * @param color Sets the text color for all the states (normal, selected,
- * focused) to be this color.
- */
- public void setTextColor(int viewId, int color) {
- setInt(viewId, "setTextColor", color);
- }
-
- public void setBoolean(int viewId, String methodName, boolean value) {
- addAction(new ReflectionAction(viewId, methodName, ReflectionAction.BOOLEAN, value));
- }
-
- public void setByte(int viewId, String methodName, byte value) {
- addAction(new ReflectionAction(viewId, methodName, ReflectionAction.BYTE, value));
- }
-
- public void setShort(int viewId, String methodName, short value) {
- addAction(new ReflectionAction(viewId, methodName, ReflectionAction.SHORT, value));
- }
-
- public void setInt(int viewId, String methodName, int value) {
- addAction(new ReflectionAction(viewId, methodName, ReflectionAction.INT, value));
- }
-
- public void setLong(int viewId, String methodName, long value) {
- addAction(new ReflectionAction(viewId, methodName, ReflectionAction.LONG, value));
- }
-
- public void setFloat(int viewId, String methodName, float value) {
- addAction(new ReflectionAction(viewId, methodName, ReflectionAction.FLOAT, value));
- }
-
- public void setDouble(int viewId, String methodName, double value) {
- addAction(new ReflectionAction(viewId, methodName, ReflectionAction.DOUBLE, value));
- }
-
- public void setChar(int viewId, String methodName, char value) {
- addAction(new ReflectionAction(viewId, methodName, ReflectionAction.CHAR, value));
- }
-
- public void setString(int viewId, String methodName, String value) {
- addAction(new ReflectionAction(viewId, methodName, ReflectionAction.STRING, value));
- }
-
- public void setCharSequence(int viewId, String methodName, CharSequence value) {
- addAction(new ReflectionAction(viewId, methodName, ReflectionAction.CHAR_SEQUENCE, value));
- }
-
- public void setUri(int viewId, String methodName, Uri value) {
- addAction(new ReflectionAction(viewId, methodName, ReflectionAction.URI, value));
- }
-
- public void setBitmap(int viewId, String methodName, Bitmap value) {
- addAction(new ReflectionAction(viewId, methodName, ReflectionAction.BITMAP, value));
- }
-
- /**
- * Inflates the view hierarchy represented by this object and applies
- * all of the actions.
- *
- * <p><strong>Caller beware: this may throw</strong>
- *
- * @param context Default context to use
- * @param parent Parent that the resulting view hierarchy will be attached to. This method
- * does <strong>not</strong> attach the hierarchy. The caller should do so when appropriate.
- * @return The inflated view hierarchy
- */
- public View apply(Context context, ViewGroup parent) {
- View result = null;
-
- Context c = prepareContext(context);
-
- Resources r = c.getResources();
- LayoutInflater inflater = (LayoutInflater) c
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- inflater = inflater.cloneInContext(c);
- inflater.setFilter(this);
-
- result = inflater.inflate(mLayoutId, parent, false);
-
- performApply(result);
-
- return result;
- }
-
- /**
- * Applies all of the actions to the provided view.
- *
- * <p><strong>Caller beware: this may throw</strong>
- *
- * @param v The view to apply the actions to. This should be the result of
- * the {@link #apply(Context,ViewGroup)} call.
- */
- public void reapply(Context context, View v) {
- prepareContext(context);
- performApply(v);
- }
-
- private void performApply(View v) {
- if (mActions != null) {
- final int count = mActions.size();
- for (int i = 0; i < count; i++) {
- Action a = mActions.get(i);
- a.apply(v);
- }
- }
- }
-
- private Context prepareContext(Context context) {
- Context c = null;
- String packageName = mPackage;
-
- if (packageName != null) {
- try {
- c = context.createPackageContext(packageName, 0);
- } catch (NameNotFoundException e) {
- Log.e(LOG_TAG, "Package name " + packageName + " not found");
- c = context;
- }
- } else {
- c = context;
- }
-
- mContext = c;
-
- return c;
- }
-
- /* (non-Javadoc)
- * Used to restrict the views which can be inflated
- *
- * @see android.view.LayoutInflater.Filter#onLoadClass(java.lang.Class)
- */
- public boolean onLoadClass(Class clazz) {
- return clazz.isAnnotationPresent(RemoteView.class);
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mPackage);
- dest.writeInt(mLayoutId);
- int count;
- if (mActions != null) {
- count = mActions.size();
- } else {
- count = 0;
- }
- dest.writeInt(count);
- for (int i=0; i<count; i++) {
- Action a = mActions.get(i);
- a.writeToParcel(dest, 0);
- }
- }
-
- /**
- * Parcelable.Creator that instantiates RemoteViews objects
- */
- public static final Parcelable.Creator<RemoteViews> CREATOR = new Parcelable.Creator<RemoteViews>() {
- public RemoteViews createFromParcel(Parcel parcel) {
- return new RemoteViews(parcel);
- }
-
- public RemoteViews[] newArray(int size) {
- return new RemoteViews[size];
- }
- };
-}
diff --git a/core/java/android/widget/ResourceCursorAdapter.java b/core/java/android/widget/ResourceCursorAdapter.java
deleted file mode 100644
index 9052ae3..0000000
--- a/core/java/android/widget/ResourceCursorAdapter.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.LayoutInflater;
-
-
-/**
- * An easy adapter that creates views defined in an XML file. You can specify
- * the XML file that defines the appearance of the views.
- */
-public abstract class ResourceCursorAdapter extends CursorAdapter {
- private int mLayout;
-
- private int mDropDownLayout;
-
- private LayoutInflater mInflater;
-
- /**
- * Constructor.
- *
- * @param context The context where the ListView associated with this
- * SimpleListItemFactory is running
- * @param layout resource identifier of a layout file that defines the views
- * for this list item. Unless you override them later, this will
- * define both the item views and the drop down views.
- */
- public ResourceCursorAdapter(Context context, int layout, Cursor c) {
- super(context, c);
- mLayout = mDropDownLayout = layout;
- mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
-
- /**
- * Inflates view(s) from the specified XML file.
- *
- * @see android.widget.CursorAdapter#newView(android.content.Context,
- * android.database.Cursor, ViewGroup)
- */
- @Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- return mInflater.inflate(mLayout, parent, false);
- }
-
- @Override
- public View newDropDownView(Context context, Cursor cursor, ViewGroup parent) {
- return mInflater.inflate(mDropDownLayout, parent, false);
- }
-
- /**
- * <p>Sets the layout resource of the item views.</p>
- *
- * @param layout the layout resources used to create item views
- */
- public void setViewResource(int layout) {
- mLayout = layout;
- }
-
- /**
- * <p>Sets the layout resource of the drop down views.</p>
- *
- * @param dropDownLayout the layout resources used to create drop down views
- */
- public void setDropDownViewResource(int dropDownLayout) {
- mDropDownLayout = dropDownLayout;
- }
-}
diff --git a/core/java/android/widget/ResourceCursorTreeAdapter.java b/core/java/android/widget/ResourceCursorTreeAdapter.java
deleted file mode 100644
index ddce515..0000000
--- a/core/java/android/widget/ResourceCursorTreeAdapter.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.LayoutInflater;
-
-/**
- * A fairly simple ExpandableListAdapter that creates views defined in an XML
- * file. You can specify the XML file that defines the appearance of the views.
- */
-public abstract class ResourceCursorTreeAdapter extends CursorTreeAdapter {
- private int mCollapsedGroupLayout;
- private int mExpandedGroupLayout;
- private int mChildLayout;
- private int mLastChildLayout;
- private LayoutInflater mInflater;
-
- /**
- * Constructor.
- *
- * @param context The context where the ListView associated with this
- * SimpleListItemFactory is running
- * @param cursor The database cursor
- * @param collapsedGroupLayout resource identifier of a layout file that
- * defines the views for collapsed groups.
- * @param expandedGroupLayout resource identifier of a layout file that
- * defines the views for expanded groups.
- * @param childLayout resource identifier of a layout file that defines the
- * views for all children but the last..
- * @param lastChildLayout resource identifier of a layout file that defines
- * the views for the last child of a group.
- */
- public ResourceCursorTreeAdapter(Context context, Cursor cursor, int collapsedGroupLayout,
- int expandedGroupLayout, int childLayout, int lastChildLayout) {
- super(cursor, context);
-
- mCollapsedGroupLayout = collapsedGroupLayout;
- mExpandedGroupLayout = expandedGroupLayout;
- mChildLayout = childLayout;
- mLastChildLayout = lastChildLayout;
-
- mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
-
- /**
- * Constructor.
- *
- * @param context The context where the ListView associated with this
- * SimpleListItemFactory is running
- * @param cursor The database cursor
- * @param collapsedGroupLayout resource identifier of a layout file that
- * defines the views for collapsed groups.
- * @param expandedGroupLayout resource identifier of a layout file that
- * defines the views for expanded groups.
- * @param childLayout resource identifier of a layout file that defines the
- * views for all children.
- */
- public ResourceCursorTreeAdapter(Context context, Cursor cursor, int collapsedGroupLayout,
- int expandedGroupLayout, int childLayout) {
- this(context, cursor, collapsedGroupLayout, expandedGroupLayout, childLayout, childLayout);
- }
-
- /**
- * Constructor.
- *
- * @param context The context where the ListView associated with this
- * SimpleListItemFactory is running
- * @param cursor The database cursor
- * @param groupLayout resource identifier of a layout file that defines the
- * views for all groups.
- * @param childLayout resource identifier of a layout file that defines the
- * views for all children.
- */
- public ResourceCursorTreeAdapter(Context context, Cursor cursor, int groupLayout,
- int childLayout) {
- this(context, cursor, groupLayout, groupLayout, childLayout, childLayout);
- }
-
- @Override
- public View newChildView(Context context, Cursor cursor, boolean isLastChild,
- ViewGroup parent) {
- return mInflater.inflate((isLastChild) ? mLastChildLayout : mChildLayout, parent, false);
- }
-
- @Override
- public View newGroupView(Context context, Cursor cursor, boolean isExpanded, ViewGroup parent) {
- return mInflater.inflate((isExpanded) ? mExpandedGroupLayout : mCollapsedGroupLayout,
- parent, false);
- }
-
-}
diff --git a/core/java/android/widget/ScrollBarDrawable.java b/core/java/android/widget/ScrollBarDrawable.java
deleted file mode 100644
index 3b113ae..0000000
--- a/core/java/android/widget/ScrollBarDrawable.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-
-/**
- * This is only used by View for displaying its scroll bars. It should probably
- * be moved in to the view package since it is used in that lower-level layer.
- * For now, we'll hide it so it can be cleaned up later.
- * {@hide}
- */
-public class ScrollBarDrawable extends Drawable {
- private Drawable mVerticalTrack;
- private Drawable mHorizontalTrack;
- private Drawable mVerticalThumb;
- private Drawable mHorizontalThumb;
- private int mRange;
- private int mOffset;
- private int mExtent;
- private boolean mVertical;
- private boolean mChanged;
- private boolean mRangeChanged;
- private final Rect mTempBounds = new Rect();
- private boolean mAlwaysDrawHorizontalTrack;
- private boolean mAlwaysDrawVerticalTrack;
-
- public ScrollBarDrawable() {
- }
-
- /**
- * Indicate whether the horizontal scrollbar track should always be drawn regardless of the
- * extent. Defaults to false.
- *
- * @param alwaysDrawTrack Set to true if the track should always be drawn
- */
- public void setAlwaysDrawHorizontalTrack(boolean alwaysDrawTrack) {
- mAlwaysDrawHorizontalTrack = alwaysDrawTrack;
- }
-
- /**
- * Indicate whether the vertical scrollbar track should always be drawn regardless of the
- * extent. Defaults to false.
- *
- * @param alwaysDrawTrack Set to true if the track should always be drawn
- */
- public void setAlwaysDrawVerticalTrack(boolean alwaysDrawTrack) {
- mAlwaysDrawVerticalTrack = alwaysDrawTrack;
- }
-
- /**
- * Indicates whether the vertical scrollbar track should always be drawn regardless of the
- * extent.
- */
- public boolean getAlwaysDrawVerticalTrack() {
- return mAlwaysDrawVerticalTrack;
- }
-
- /**
- * Indicates whether the horizontal scrollbar track should always be drawn regardless of the
- * extent.
- */
- public boolean getAlwaysDrawHorizontalTrack() {
- return mAlwaysDrawHorizontalTrack;
- }
-
- public void setParameters(int range, int offset, int extent, boolean vertical) {
- if (mVertical != vertical) {
- mChanged = true;
- }
-
- if (mRange != range || mOffset != offset || mExtent != extent) {
- mRangeChanged = true;
- }
-
- mRange = range;
- mOffset = offset;
- mExtent = extent;
- mVertical = vertical;
- }
-
- @Override
- public void draw(Canvas canvas) {
- final boolean vertical = mVertical;
- final int extent = mExtent;
- final int range = mRange;
-
- boolean drawTrack = true;
- boolean drawThumb = true;
- if (extent <= 0 || range <= extent) {
- drawTrack = vertical ? mAlwaysDrawVerticalTrack : mAlwaysDrawHorizontalTrack;
- drawThumb = false;
- }
-
- Rect r = getBounds();
- if (canvas.quickReject(r.left, r.top, r.right, r.bottom,
- Canvas.EdgeType.AA)) {
- return;
- }
- if (drawTrack) {
- drawTrack(canvas, r, vertical);
- }
-
- if (drawThumb) {
- int size = vertical ? r.height() : r.width();
- int thickness = vertical ? r.width() : r.height();
- int length = Math.round((float) size * extent / range);
- int offset = Math.round((float) (size - length) * mOffset / (range - extent));
-
- // avoid the tiny thumb
- int minLength = thickness * 2;
- if (length < minLength) {
- length = minLength;
- }
- // avoid the too-big thumb
- if (offset + length > size) {
- offset = size - length;
- }
-
- drawThumb(canvas, r, offset, length, vertical);
- }
- }
-
- @Override
- protected void onBoundsChange(Rect bounds) {
- super.onBoundsChange(bounds);
- mChanged = true;
- }
-
- protected void drawTrack(Canvas canvas, Rect bounds, boolean vertical) {
- Drawable track;
- if (vertical) {
- track = mVerticalTrack;
- } else {
- track = mHorizontalTrack;
- }
- if (track != null) {
- if (mChanged) {
- track.setBounds(bounds);
- }
- track.draw(canvas);
- }
- }
-
- protected void drawThumb(Canvas canvas, Rect bounds, int offset, int length, boolean vertical) {
- final Rect thumbRect = mTempBounds;
- final boolean changed = mRangeChanged || mChanged;
- if (changed) {
- if (vertical) {
- thumbRect.set(bounds.left, bounds.top + offset,
- bounds.right, bounds.top + offset + length);
- } else {
- thumbRect.set(bounds.left + offset, bounds.top,
- bounds.left + offset + length, bounds.bottom);
- }
- }
-
- if (vertical) {
- final Drawable thumb = mVerticalThumb;
- if (changed) thumb.setBounds(thumbRect);
- thumb.draw(canvas);
- } else {
- final Drawable thumb = mHorizontalThumb;
- if (changed) thumb.setBounds(thumbRect);
- thumb.draw(canvas);
- }
- }
-
- public void setVerticalThumbDrawable(Drawable thumb) {
- if (thumb != null) {
- mVerticalThumb = thumb;
- }
- }
-
- public void setVerticalTrackDrawable(Drawable track) {
- mVerticalTrack = track;
- }
-
- public void setHorizontalThumbDrawable(Drawable thumb) {
- if (thumb != null) {
- mHorizontalThumb = thumb;
- }
- }
-
- public void setHorizontalTrackDrawable(Drawable track) {
- mHorizontalTrack = track;
- }
-
- public int getSize(boolean vertical) {
- if (vertical) {
- return (mVerticalTrack != null ?
- mVerticalTrack : mVerticalThumb).getIntrinsicWidth();
- } else {
- return (mHorizontalTrack != null ?
- mHorizontalTrack : mHorizontalThumb).getIntrinsicHeight();
- }
- }
-
- @Override
- public void setAlpha(int alpha) {
- if (mVerticalTrack != null) {
- mVerticalTrack.setAlpha(alpha);
- }
- mVerticalThumb.setAlpha(alpha);
- if (mHorizontalTrack != null) {
- mHorizontalTrack.setAlpha(alpha);
- }
- mHorizontalThumb.setAlpha(alpha);
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- if (mVerticalTrack != null) {
- mVerticalTrack.setColorFilter(cf);
- }
- mVerticalThumb.setColorFilter(cf);
- if (mHorizontalTrack != null) {
- mHorizontalTrack.setColorFilter(cf);
- }
- mHorizontalThumb.setColorFilter(cf);
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
-
- @Override
- public String toString() {
- return "ScrollBarDrawable: range=" + mRange + " offset=" + mOffset +
- " extent=" + mExtent + (mVertical ? " V" : " H");
- }
-}
-
-
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
deleted file mode 100644
index c9b3751..0000000
--- a/core/java/android/widget/ScrollView.java
+++ /dev/null
@@ -1,1232 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.util.Config;
-import android.util.Log;
-import android.view.FocusFinder;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.view.animation.AnimationUtils;
-
-import com.android.internal.R;
-
-import java.util.List;
-
-/**
- * Layout container for a view hierarchy that can be scrolled by the user,
- * allowing it to be larger than the physical display. A ScrollView
- * is a {@link FrameLayout}, meaning you should place one child in it
- * containing the entire contents to scroll; this child may itself be a layout
- * manager with a complex hierarchy of objects. A child that is often used
- * is a {@link LinearLayout} in a vertical orientation, presenting a vertical
- * array of top-level items that the user can scroll through.
- *
- * <p>The {@link TextView} class also
- * takes care of its own scrolling, so does not require a ScrollView, but
- * using the two together is possible to achieve the effect of a text view
- * within a larger container.
- *
- * <p>ScrollView only supports vertical scrolling.
- */
-public class ScrollView extends FrameLayout {
- static final String TAG = "ScrollView";
- static final boolean localLOGV = false || Config.LOGV;
-
- static final int ANIMATED_SCROLL_GAP = 250;
-
- static final float MAX_SCROLL_FACTOR = 0.5f;
-
-
- private long mLastScroll;
-
- private final Rect mTempRect = new Rect();
- private Scroller mScroller;
-
- /**
- * Flag to indicate that we are moving focus ourselves. This is so the
- * code that watches for focus changes initiated outside this ScrollView
- * knows that it does not have to do anything.
- */
- private boolean mScrollViewMovedFocus;
-
- /**
- * Position of the last motion event.
- */
- private float mLastMotionY;
-
- /**
- * True when the layout has changed but the traversal has not come through yet.
- * Ideally the view hierarchy would keep track of this for us.
- */
- private boolean mIsLayoutDirty = true;
-
- /**
- * The child to give focus to in the event that a child has requested focus while the
- * layout is dirty. This prevents the scroll from being wrong if the child has not been
- * laid out before requesting focus.
- */
- private View mChildToScrollTo = null;
-
- /**
- * True if the user is currently dragging this ScrollView around. This is
- * not the same as 'is being flinged', which can be checked by
- * mScroller.isFinished() (flinging begins when the user lifts his finger).
- */
- private boolean mIsBeingDragged = false;
-
- /**
- * Determines speed during touch scrolling
- */
- private VelocityTracker mVelocityTracker;
-
- /**
- * When set to true, the scroll view measure its child to make it fill the currently
- * visible area.
- */
- private boolean mFillViewport;
-
- /**
- * Whether arrow scrolling is animated.
- */
- private boolean mSmoothScrollingEnabled = true;
-
- private int mTouchSlop;
-
- public ScrollView(Context context) {
- this(context, null);
- }
-
- public ScrollView(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.scrollViewStyle);
- }
-
- public ScrollView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- initScrollView();
-
- TypedArray a =
- context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ScrollView, defStyle, 0);
-
- setFillViewport(a.getBoolean(R.styleable.ScrollView_fillViewport, false));
-
- a.recycle();
- }
-
- @Override
- protected float getTopFadingEdgeStrength() {
- if (getChildCount() == 0) {
- return 0.0f;
- }
-
- final int length = getVerticalFadingEdgeLength();
- if (mScrollY < length) {
- return mScrollY / (float) length;
- }
-
- return 1.0f;
- }
-
- @Override
- protected float getBottomFadingEdgeStrength() {
- if (getChildCount() == 0) {
- return 0.0f;
- }
-
- final int length = getVerticalFadingEdgeLength();
- final int bottomEdge = getHeight() - mPaddingBottom;
- final int span = getChildAt(0).getBottom() - mScrollY - bottomEdge;
- if (span < length) {
- return span / (float) length;
- }
-
- return 1.0f;
- }
-
- /**
- * @return The maximum amount this scroll view will scroll in response to
- * an arrow event.
- */
- public int getMaxScrollAmount() {
- return (int) (MAX_SCROLL_FACTOR * (mBottom - mTop));
- }
-
-
- private void initScrollView() {
- mScroller = new Scroller(getContext());
- setFocusable(true);
- setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
- setWillNotDraw(false);
- mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- }
-
- @Override
- public void addView(View child) {
- if (getChildCount() > 0) {
- throw new IllegalStateException("ScrollView can host only one direct child");
- }
-
- super.addView(child);
- }
-
- @Override
- public void addView(View child, int index) {
- if (getChildCount() > 0) {
- throw new IllegalStateException("ScrollView can host only one direct child");
- }
-
- super.addView(child, index);
- }
-
- @Override
- public void addView(View child, ViewGroup.LayoutParams params) {
- if (getChildCount() > 0) {
- throw new IllegalStateException("ScrollView can host only one direct child");
- }
-
- super.addView(child, params);
- }
-
- @Override
- public void addView(View child, int index, ViewGroup.LayoutParams params) {
- if (getChildCount() > 0) {
- throw new IllegalStateException("ScrollView can host only one direct child");
- }
-
- super.addView(child, index, params);
- }
-
- /**
- * @return Returns true this ScrollView can be scrolled
- */
- private boolean canScroll() {
- View child = getChildAt(0);
- if (child != null) {
- int childHeight = child.getHeight();
- return getHeight() < childHeight + mPaddingTop + mPaddingBottom;
- }
- return false;
- }
-
- /**
- * Indicates whether this ScrollView's content is stretched to fill the viewport.
- *
- * @return True if the content fills the viewport, false otherwise.
- */
- public boolean isFillViewport() {
- return mFillViewport;
- }
-
- /**
- * Indicates this ScrollView whether it should stretch its content height to fill
- * the viewport or not.
- *
- * @param fillViewport True to stretch the content's height to the viewport's
- * boundaries, false otherwise.
- */
- public void setFillViewport(boolean fillViewport) {
- if (fillViewport != mFillViewport) {
- mFillViewport = fillViewport;
- requestLayout();
- }
- }
-
- /**
- * @return Whether arrow scrolling will animate its transition.
- */
- public boolean isSmoothScrollingEnabled() {
- return mSmoothScrollingEnabled;
- }
-
- /**
- * Set whether arrow scrolling will animate its transition.
- * @param smoothScrollingEnabled whether arrow scrolling will animate its transition
- */
- public void setSmoothScrollingEnabled(boolean smoothScrollingEnabled) {
- mSmoothScrollingEnabled = smoothScrollingEnabled;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
- if (!mFillViewport) {
- return;
- }
-
- final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- if (heightMode == MeasureSpec.UNSPECIFIED) {
- return;
- }
-
- final View child = getChildAt(0);
- int height = getMeasuredHeight();
- if (child.getMeasuredHeight() < height) {
- final FrameLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
- int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, mPaddingLeft
- + mPaddingRight, lp.width);
- height -= mPaddingTop;
- height -= mPaddingBottom;
- int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
-
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- }
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- // Let the focused view and/or our descendants get the key first
- boolean handled = super.dispatchKeyEvent(event);
- if (handled) {
- return true;
- }
- return executeKeyEvent(event);
- }
-
- /**
- * You can call this function yourself to have the scroll view perform
- * scrolling from a key event, just as if the event had been dispatched to
- * it by the view hierarchy.
- *
- * @param event The key event to execute.
- * @return Return true if the event was handled, else false.
- */
- public boolean executeKeyEvent(KeyEvent event) {
- mTempRect.setEmpty();
-
- if (!canScroll()) {
- if (isFocused()) {
- View currentFocused = findFocus();
- if (currentFocused == this) currentFocused = null;
- View nextFocused = FocusFinder.getInstance().findNextFocus(this,
- currentFocused, View.FOCUS_DOWN);
- return nextFocused != null
- && nextFocused != this
- && nextFocused.requestFocus(View.FOCUS_DOWN);
- }
- return false;
- }
-
- boolean handled = false;
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- switch (event.getKeyCode()) {
- case KeyEvent.KEYCODE_DPAD_UP:
- if (!event.isAltPressed()) {
- handled = arrowScroll(View.FOCUS_UP);
- } else {
- handled = fullScroll(View.FOCUS_UP);
- }
- break;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- if (!event.isAltPressed()) {
- handled = arrowScroll(View.FOCUS_DOWN);
- } else {
- handled = fullScroll(View.FOCUS_DOWN);
- }
- break;
- case KeyEvent.KEYCODE_SPACE:
- pageScroll(event.isShiftPressed() ? View.FOCUS_UP : View.FOCUS_DOWN);
- break;
- }
- }
-
- return handled;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- /*
- * This method JUST determines whether we want to intercept the motion.
- * If we return true, onMotionEvent will be called and we do the actual
- * scrolling there.
- */
-
- /*
- * Shortcut the most recurring case: the user is in the dragging
- * state and he is moving his finger. We want to intercept this
- * motion.
- */
- final int action = ev.getAction();
- if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) {
- return true;
- }
-
- if (!canScroll()) {
- mIsBeingDragged = false;
- return false;
- }
-
- final float y = ev.getY();
-
- switch (action) {
- case MotionEvent.ACTION_MOVE:
- /*
- * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
- * whether the user has moved far enough from his original down touch.
- */
-
- /*
- * Locally do absolute value. mLastMotionY is set to the y value
- * of the down event.
- */
- final int yDiff = (int) Math.abs(y - mLastMotionY);
- if (yDiff > mTouchSlop) {
- mIsBeingDragged = true;
- }
- break;
-
- case MotionEvent.ACTION_DOWN:
- /* Remember location of down touch */
- mLastMotionY = y;
-
- /*
- * If being flinged and user touches the screen, initiate drag;
- * otherwise don't. mScroller.isFinished should be false when
- * being flinged.
- */
- mIsBeingDragged = !mScroller.isFinished();
- break;
-
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- /* Release the drag */
- mIsBeingDragged = false;
- break;
- }
-
- /*
- * The only time we want to intercept motion events is if we are in the
- * drag mode.
- */
- return mIsBeingDragged;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
-
- if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) {
- // Don't handle edge touches immediately -- they may actually belong to one of our
- // descendants.
- return false;
- }
-
- if (!canScroll()) {
- return false;
- }
-
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(ev);
-
- final int action = ev.getAction();
- final float y = ev.getY();
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- /*
- * If being flinged and user touches, stop the fling. isFinished
- * will be false if being flinged.
- */
- if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
- }
-
- // Remember where the motion event started
- mLastMotionY = y;
- break;
- case MotionEvent.ACTION_MOVE:
- // Scroll to follow the motion event
- final int deltaY = (int) (mLastMotionY - y);
- mLastMotionY = y;
-
- if (deltaY < 0) {
- if (mScrollY > 0) {
- scrollBy(0, deltaY);
- }
- } else if (deltaY > 0) {
- final int bottomEdge = getHeight() - mPaddingBottom;
- final int availableToScroll = getChildAt(0).getBottom() - mScrollY - bottomEdge;
- if (availableToScroll > 0) {
- scrollBy(0, Math.min(availableToScroll, deltaY));
- }
- }
- break;
- case MotionEvent.ACTION_UP:
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(1000);
- int initialVelocity = (int) velocityTracker.getYVelocity();
-
- if ((Math.abs(initialVelocity) >
- ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity()) &&
- getChildCount() > 0) {
- fling(-initialVelocity);
- }
-
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- }
- return true;
- }
-
- /**
- * <p>
- * Finds the next focusable component that fits in this View's bounds
- * (excluding fading edges) pretending that this View's top is located at
- * the parameter top.
- * </p>
- *
- * @param topFocus look for a candidate is the one at the top of the bounds
- * if topFocus is true, or at the bottom of the bounds if topFocus is
- * false
- * @param top the top offset of the bounds in which a focusable must be
- * found (the fading edge is assumed to start at this position)
- * @param preferredFocusable the View that has highest priority and will be
- * returned if it is within my bounds (null is valid)
- * @return the next focusable component in the bounds or null if none can be
- * found
- */
- private View findFocusableViewInMyBounds(final boolean topFocus,
- final int top, View preferredFocusable) {
- /*
- * The fading edge's transparent side should be considered for focus
- * since it's mostly visible, so we divide the actual fading edge length
- * by 2.
- */
- final int fadingEdgeLength = getVerticalFadingEdgeLength() / 2;
- final int topWithoutFadingEdge = top + fadingEdgeLength;
- final int bottomWithoutFadingEdge = top + getHeight() - fadingEdgeLength;
-
- if ((preferredFocusable != null)
- && (preferredFocusable.getTop() < bottomWithoutFadingEdge)
- && (preferredFocusable.getBottom() > topWithoutFadingEdge)) {
- return preferredFocusable;
- }
-
- return findFocusableViewInBounds(topFocus, topWithoutFadingEdge,
- bottomWithoutFadingEdge);
- }
-
- /**
- * <p>
- * Finds the next focusable component that fits in the specified bounds.
- * </p>
- *
- * @param topFocus look for a candidate is the one at the top of the bounds
- * if topFocus is true, or at the bottom of the bounds if topFocus is
- * false
- * @param top the top offset of the bounds in which a focusable must be
- * found
- * @param bottom the bottom offset of the bounds in which a focusable must
- * be found
- * @return the next focusable component in the bounds or null if none can
- * be found
- */
- private View findFocusableViewInBounds(boolean topFocus, int top, int bottom) {
-
- List<View> focusables = getFocusables(View.FOCUS_FORWARD);
- View focusCandidate = null;
-
- /*
- * A fully contained focusable is one where its top is below the bound's
- * top, and its bottom is above the bound's bottom. A partially
- * contained focusable is one where some part of it is within the
- * bounds, but it also has some part that is not within bounds. A fully contained
- * focusable is preferred to a partially contained focusable.
- */
- boolean foundFullyContainedFocusable = false;
-
- int count = focusables.size();
- for (int i = 0; i < count; i++) {
- View view = focusables.get(i);
- int viewTop = view.getTop();
- int viewBottom = view.getBottom();
-
- if (top < viewBottom && viewTop < bottom) {
- /*
- * the focusable is in the target area, it is a candidate for
- * focusing
- */
-
- final boolean viewIsFullyContained = (top < viewTop) &&
- (viewBottom < bottom);
-
- if (focusCandidate == null) {
- /* No candidate, take this one */
- focusCandidate = view;
- foundFullyContainedFocusable = viewIsFullyContained;
- } else {
- final boolean viewIsCloserToBoundary =
- (topFocus && viewTop < focusCandidate.getTop()) ||
- (!topFocus && viewBottom > focusCandidate
- .getBottom());
-
- if (foundFullyContainedFocusable) {
- if (viewIsFullyContained && viewIsCloserToBoundary) {
- /*
- * We're dealing with only fully contained views, so
- * it has to be closer to the boundary to beat our
- * candidate
- */
- focusCandidate = view;
- }
- } else {
- if (viewIsFullyContained) {
- /* Any fully contained view beats a partially contained view */
- focusCandidate = view;
- foundFullyContainedFocusable = true;
- } else if (viewIsCloserToBoundary) {
- /*
- * Partially contained view beats another partially
- * contained view if it's closer
- */
- focusCandidate = view;
- }
- }
- }
- }
- }
-
- return focusCandidate;
- }
-
- /**
- * <p>Handles scrolling in response to a "page up/down" shortcut press. This
- * method will scroll the view by one page up or down and give the focus
- * to the topmost/bottommost component in the new visible area. If no
- * component is a good candidate for focus, this scrollview reclaims the
- * focus.</p>
- *
- * @param direction the scroll direction: {@link android.view.View#FOCUS_UP}
- * to go one page up or
- * {@link android.view.View#FOCUS_DOWN} to go one page down
- * @return true if the key event is consumed by this method, false otherwise
- */
- public boolean pageScroll(int direction) {
- boolean down = direction == View.FOCUS_DOWN;
- int height = getHeight();
-
- if (down) {
- mTempRect.top = getScrollY() + height;
- int count = getChildCount();
- if (count > 0) {
- View view = getChildAt(count - 1);
- if (mTempRect.top + height > view.getBottom()) {
- mTempRect.top = view.getBottom() - height;
- }
- }
- } else {
- mTempRect.top = getScrollY() - height;
- if (mTempRect.top < 0) {
- mTempRect.top = 0;
- }
- }
- mTempRect.bottom = mTempRect.top + height;
-
- return scrollAndFocus(direction, mTempRect.top, mTempRect.bottom);
- }
-
- /**
- * <p>Handles scrolling in response to a "home/end" shortcut press. This
- * method will scroll the view to the top or bottom and give the focus
- * to the topmost/bottommost component in the new visible area. If no
- * component is a good candidate for focus, this scrollview reclaims the
- * focus.</p>
- *
- * @param direction the scroll direction: {@link android.view.View#FOCUS_UP}
- * to go the top of the view or
- * {@link android.view.View#FOCUS_DOWN} to go the bottom
- * @return true if the key event is consumed by this method, false otherwise
- */
- public boolean fullScroll(int direction) {
- boolean down = direction == View.FOCUS_DOWN;
- int height = getHeight();
-
- mTempRect.top = 0;
- mTempRect.bottom = height;
-
- if (down) {
- int count = getChildCount();
- if (count > 0) {
- View view = getChildAt(count - 1);
- mTempRect.bottom = view.getBottom();
- mTempRect.top = mTempRect.bottom - height;
- }
- }
-
- return scrollAndFocus(direction, mTempRect.top, mTempRect.bottom);
- }
-
- /**
- * <p>Scrolls the view to make the area defined by <code>top</code> and
- * <code>bottom</code> visible. This method attempts to give the focus
- * to a component visible in this area. If no component can be focused in
- * the new visible area, the focus is reclaimed by this scrollview.</p>
- *
- * @param direction the scroll direction: {@link android.view.View#FOCUS_UP}
- * to go upward
- * {@link android.view.View#FOCUS_DOWN} to downward
- * @param top the top offset of the new area to be made visible
- * @param bottom the bottom offset of the new area to be made visible
- * @return true if the key event is consumed by this method, false otherwise
- */
- private boolean scrollAndFocus(int direction, int top, int bottom) {
- boolean handled = true;
-
- int height = getHeight();
- int containerTop = getScrollY();
- int containerBottom = containerTop + height;
- boolean up = direction == View.FOCUS_UP;
-
- View newFocused = findFocusableViewInBounds(up, top, bottom);
- if (newFocused == null) {
- newFocused = this;
- }
-
- if (top >= containerTop && bottom <= containerBottom) {
- handled = false;
- } else {
- int delta = up ? (top - containerTop) : (bottom - containerBottom);
- doScrollY(delta);
- }
-
- if (newFocused != findFocus() && newFocused.requestFocus(direction)) {
- mScrollViewMovedFocus = true;
- mScrollViewMovedFocus = false;
- }
-
- return handled;
- }
-
- /**
- * Handle scrolling in response to an up or down arrow click.
- *
- * @param direction The direction corresponding to the arrow key that was
- * pressed
- * @return True if we consumed the event, false otherwise
- */
- public boolean arrowScroll(int direction) {
-
- View currentFocused = findFocus();
- if (currentFocused == this) currentFocused = null;
-
- View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, direction);
-
- final int maxJump = getMaxScrollAmount();
-
- if (nextFocused != null && isWithinDeltaOfScreen(nextFocused, maxJump)) {
- nextFocused.getDrawingRect(mTempRect);
- offsetDescendantRectToMyCoords(nextFocused, mTempRect);
- int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
- doScrollY(scrollDelta);
- nextFocused.requestFocus(direction);
- } else {
- // no new focus
- int scrollDelta = maxJump;
-
- if (direction == View.FOCUS_UP && getScrollY() < scrollDelta) {
- scrollDelta = getScrollY();
- } else if (direction == View.FOCUS_DOWN) {
-
- int daBottom = getChildAt(getChildCount() - 1).getBottom();
-
- int screenBottom = getScrollY() + getHeight();
-
- if (daBottom - screenBottom < maxJump) {
- scrollDelta = daBottom - screenBottom;
- }
- }
- if (scrollDelta == 0) {
- return false;
- }
- doScrollY(direction == View.FOCUS_DOWN ? scrollDelta : -scrollDelta);
- }
-
- if (currentFocused != null && currentFocused.isFocused()
- && isOffScreen(currentFocused)) {
- // previously focused item still has focus and is off screen, give
- // it up (take it back to ourselves)
- // (also, need to temporarily force FOCUS_BEFORE_DESCENDANTS so we are
- // sure to
- // get it)
- final int descendantFocusability = getDescendantFocusability(); // save
- setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
- requestFocus();
- setDescendantFocusability(descendantFocusability); // restore
- }
- return true;
- }
-
- /**
- * @return whether the descendant of this scroll view is scrolled off
- * screen.
- */
- private boolean isOffScreen(View descendant) {
- return !isWithinDeltaOfScreen(descendant, 0);
- }
-
- /**
- * @return whether the descendant of this scroll view is within delta
- * pixels of being on the screen.
- */
- private boolean isWithinDeltaOfScreen(View descendant, int delta) {
- descendant.getDrawingRect(mTempRect);
- offsetDescendantRectToMyCoords(descendant, mTempRect);
-
- return (mTempRect.bottom + delta) >= getScrollY()
- && (mTempRect.top - delta) <= (getScrollY() + getHeight());
- }
-
- /**
- * Smooth scroll by a Y delta
- *
- * @param delta the number of pixels to scroll by on the Y axis
- */
- private void doScrollY(int delta) {
- if (delta != 0) {
- if (mSmoothScrollingEnabled) {
- smoothScrollBy(0, delta);
- } else {
- scrollBy(0, delta);
- }
- }
- }
-
- /**
- * Like {@link View#scrollBy}, but scroll smoothly instead of immediately.
- *
- * @param dx the number of pixels to scroll by on the X axis
- * @param dy the number of pixels to scroll by on the Y axis
- */
- public final void smoothScrollBy(int dx, int dy) {
- long duration = AnimationUtils.currentAnimationTimeMillis() - mLastScroll;
- if (duration > ANIMATED_SCROLL_GAP) {
- if (localLOGV) Log.v(TAG, "Smooth scroll: mScrollY=" + mScrollY
- + " dy=" + dy);
- mScroller.startScroll(mScrollX, mScrollY, dx, dy);
- invalidate();
- } else {
- if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
- }
- if (localLOGV) Log.v(TAG, "Immediate scroll: mScrollY=" + mScrollY
- + " dy=" + dy);
- scrollBy(dx, dy);
- }
- mLastScroll = AnimationUtils.currentAnimationTimeMillis();
- }
-
- /**
- * Like {@link #scrollTo}, but scroll smoothly instead of immediately.
- *
- * @param x the position where to scroll on the X axis
- * @param y the position where to scroll on the Y axis
- */
- public final void smoothScrollTo(int x, int y) {
- smoothScrollBy(x - mScrollX, y - mScrollY);
- }
-
- /**
- * <p>The scroll range of a scroll view is the overall height of all of its
- * children.</p>
- */
- @Override
- protected int computeVerticalScrollRange() {
- int count = getChildCount();
- return count == 0 ? getHeight() : (getChildAt(0)).getBottom();
- }
-
-
- @Override
- protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) {
- ViewGroup.LayoutParams lp = child.getLayoutParams();
-
- int childWidthMeasureSpec;
- int childHeightMeasureSpec;
-
- childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft
- + mPaddingRight, lp.width);
-
- childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
-
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- }
-
- @Override
- protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,
- int parentHeightMeasureSpec, int heightUsed) {
- final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
-
- final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
- mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
- + widthUsed, lp.width);
- final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
- lp.topMargin + lp.bottomMargin, MeasureSpec.UNSPECIFIED);
-
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- }
-
- @Override
- public void computeScroll() {
- if (mScroller.computeScrollOffset()) {
- // This is called at drawing time by ViewGroup. We don't want to
- // re-show the scrollbars at this point, which scrollTo will do,
- // so we replicate most of scrollTo here.
- //
- // It's a little odd to call onScrollChanged from inside the drawing.
- //
- // It is, except when you remember that computeScroll() is used to
- // animate scrolling. So unless we want to defer the onScrollChanged()
- // until the end of the animated scrolling, we don't really have a
- // choice here.
- //
- // I agree. The alternative, which I think would be worse, is to post
- // something and tell the subclasses later. This is bad because there
- // will be a window where mScrollX/Y is different from what the app
- // thinks it is.
- //
- int oldX = mScrollX;
- int oldY = mScrollY;
- int x = mScroller.getCurrX();
- int y = mScroller.getCurrY();
- if (getChildCount() > 0) {
- View child = getChildAt(0);
- mScrollX = clamp(x, getWidth() - mPaddingRight - mPaddingLeft, child.getWidth());
- mScrollY = clamp(y, getHeight() - mPaddingBottom - mPaddingTop, child.getHeight());
- if (localLOGV) Log.v(TAG, "mScrollY=" + mScrollY + " y=" + y
- + " height=" + this.getHeight()
- + " child height=" + child.getHeight());
- } else {
- mScrollX = x;
- mScrollY = y;
- }
- if (oldX != mScrollX || oldY != mScrollY) {
- onScrollChanged(mScrollX, mScrollY, oldX, oldY);
- }
-
- // Keep on drawing until the animation has finished.
- postInvalidate();
- }
- }
-
- /**
- * Scrolls the view to the given child.
- *
- * @param child the View to scroll to
- */
- private void scrollToChild(View child) {
- child.getDrawingRect(mTempRect);
-
- /* Offset from child's local coordinates to ScrollView coordinates */
- offsetDescendantRectToMyCoords(child, mTempRect);
-
- int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
-
- if (scrollDelta != 0) {
- scrollBy(0, scrollDelta);
- }
- }
-
- /**
- * If rect is off screen, scroll just enough to get it (or at least the
- * first screen size chunk of it) on screen.
- *
- * @param rect The rectangle.
- * @param immediate True to scroll immediately without animation
- * @return true if scrolling was performed
- */
- private boolean scrollToChildRect(Rect rect, boolean immediate) {
- final int delta = computeScrollDeltaToGetChildRectOnScreen(rect);
- final boolean scroll = delta != 0;
- if (scroll) {
- if (immediate) {
- scrollBy(0, delta);
- } else {
- smoothScrollBy(0, delta);
- }
- }
- return scroll;
- }
-
- /**
- * Compute the amount to scroll in the Y direction in order to get
- * a rectangle completely on the screen (or, if taller than the screen,
- * at least the first screen size chunk of it).
- *
- * @param rect The rect.
- * @return The scroll delta.
- */
- protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
-
- int height = getHeight();
- int screenTop = getScrollY();
- int screenBottom = screenTop + height;
-
- int fadingEdge = getVerticalFadingEdgeLength();
-
- // leave room for top fading edge as long as rect isn't at very top
- if (rect.top > 0) {
- screenTop += fadingEdge;
- }
-
- // leave room for bottom fading edge as long as rect isn't at very bottom
- if (rect.bottom < getChildAt(0).getHeight()) {
- screenBottom -= fadingEdge;
- }
-
- int scrollYDelta = 0;
-
- if (localLOGV) Log.v(TAG, "child=" + rect.toShortString()
- + " screenTop=" + screenTop + " screenBottom=" + screenBottom
- + " height=" + height);
- if (rect.bottom > screenBottom && rect.top > screenTop) {
- // need to move down to get it in view: move down just enough so
- // that the entire rectangle is in view (or at least the first
- // screen size chunk).
-
- if (rect.height() > height) {
- // just enough to get screen size chunk on
- scrollYDelta += (rect.top - screenTop);
- } else {
- // get entire rect at bottom of screen
- scrollYDelta += (rect.bottom - screenBottom);
- }
-
- // make sure we aren't scrolling beyond the end of our content
- int bottom = getChildAt(getChildCount() - 1).getBottom();
- int distanceToBottom = bottom - screenBottom;
- if (localLOGV) Log.v(TAG, "scrollYDelta=" + scrollYDelta
- + " distanceToBottom=" + distanceToBottom);
- scrollYDelta = Math.min(scrollYDelta, distanceToBottom);
-
- } else if (rect.top < screenTop && rect.bottom < screenBottom) {
- // need to move up to get it in view: move up just enough so that
- // entire rectangle is in view (or at least the first screen
- // size chunk of it).
-
- if (rect.height() > height) {
- // screen size chunk
- scrollYDelta -= (screenBottom - rect.bottom);
- } else {
- // entire rect at top
- scrollYDelta -= (screenTop - rect.top);
- }
-
- // make sure we aren't scrolling any further than the top our content
- scrollYDelta = Math.max(scrollYDelta, -getScrollY());
- }
- return scrollYDelta;
- }
-
- @Override
- public void requestChildFocus(View child, View focused) {
- if (!mScrollViewMovedFocus) {
- if (!mIsLayoutDirty) {
- scrollToChild(focused);
- } else {
- // The child may not be laid out yet, we can't compute the scroll yet
- mChildToScrollTo = focused;
- }
- }
- super.requestChildFocus(child, focused);
- }
-
-
- /**
- * When looking for focus in children of a scroll view, need to be a little
- * more careful not to give focus to something that is scrolled off screen.
- *
- * This is more expensive than the default {@link android.view.ViewGroup}
- * implementation, otherwise this behavior might have been made the default.
- */
- @Override
- protected boolean onRequestFocusInDescendants(int direction,
- Rect previouslyFocusedRect) {
-
- // convert from forward / backward notation to up / down / left / right
- // (ugh).
- if (direction == View.FOCUS_FORWARD) {
- direction = View.FOCUS_DOWN;
- } else if (direction == View.FOCUS_BACKWARD) {
- direction = View.FOCUS_UP;
- }
-
- final View nextFocus = previouslyFocusedRect == null ?
- FocusFinder.getInstance().findNextFocus(this, null, direction) :
- FocusFinder.getInstance().findNextFocusFromRect(this,
- previouslyFocusedRect, direction);
-
- if (nextFocus == null) {
- return false;
- }
-
- if (isOffScreen(nextFocus)) {
- return false;
- }
-
- return nextFocus.requestFocus(direction, previouslyFocusedRect);
- }
-
- @Override
- public boolean requestChildRectangleOnScreen(View child, Rect rectangle,
- boolean immediate) {
- // offset into coordinate space of this scroll view
- rectangle.offset(child.getLeft() - child.getScrollX(),
- child.getTop() - child.getScrollY());
-
- return scrollToChildRect(rectangle, immediate);
- }
-
- @Override
- public void requestLayout() {
- mIsLayoutDirty = true;
- super.requestLayout();
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
- mIsLayoutDirty = false;
- // Give a child focus if it needs it
- if (mChildToScrollTo != null && isViewDescendantOf(mChildToScrollTo, this)) {
- scrollToChild(mChildToScrollTo);
- }
- mChildToScrollTo = null;
-
- // Calling this with the present values causes it to re-clam them
- scrollTo(mScrollX, mScrollY);
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
-
- View currentFocused = findFocus();
- if (null == currentFocused || this == currentFocused)
- return;
-
- final int maxJump = mBottom - mTop;
-
- if (isWithinDeltaOfScreen(currentFocused, maxJump)) {
- currentFocused.getDrawingRect(mTempRect);
- offsetDescendantRectToMyCoords(currentFocused, mTempRect);
- int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
- doScrollY(scrollDelta);
- }
- }
-
- /**
- * Return true if child is an descendant of parent, (or equal to the parent).
- */
- private boolean isViewDescendantOf(View child, View parent) {
- if (child == parent) {
- return true;
- }
-
- final ViewParent theParent = child.getParent();
- return (theParent instanceof ViewGroup) && isViewDescendantOf((View) theParent, parent);
- }
-
- /**
- * Fling the scroll view
- *
- * @param velocityY The initial velocity in the Y direction. Positive
- * numbers mean that the finger/curor is moving down the screen,
- * which means we want to scroll towards the top.
- */
- public void fling(int velocityY) {
- int height = getHeight() - mPaddingBottom - mPaddingTop;
- int bottom = getChildAt(0).getHeight();
-
- mScroller.fling(mScrollX, mScrollY, 0, velocityY, 0, 0, 0, bottom - height);
-
- final boolean movingDown = velocityY > 0;
-
- View newFocused =
- findFocusableViewInMyBounds(movingDown, mScroller.getFinalY(), findFocus());
- if (newFocused == null) {
- newFocused = this;
- }
-
- if (newFocused != findFocus()
- && newFocused.requestFocus(movingDown ? View.FOCUS_DOWN : View.FOCUS_UP)) {
- mScrollViewMovedFocus = true;
- mScrollViewMovedFocus = false;
- }
-
- invalidate();
- }
-
- /**
- * {@inheritDoc}
- *
- * <p>This version also clamps the scrolling to the bounds of our child.
- */
- public void scrollTo(int x, int y) {
- // we rely on the fact the View.scrollBy calls scrollTo.
- if (getChildCount() > 0) {
- View child = getChildAt(0);
- x = clamp(x, getWidth() - mPaddingRight - mPaddingLeft, child.getWidth());
- y = clamp(y, getHeight() - mPaddingBottom - mPaddingTop, child.getHeight());
- if (x != mScrollX || y != mScrollY) {
- super.scrollTo(x, y);
- }
- }
- }
-
- private int clamp(int n, int my, int child) {
- if (my >= child || n < 0) {
- /* my >= child is this case:
- * |--------------- me ---------------|
- * |------ child ------|
- * or
- * |--------------- me ---------------|
- * |------ child ------|
- * or
- * |--------------- me ---------------|
- * |------ child ------|
- *
- * n < 0 is this case:
- * |------ me ------|
- * |-------- child --------|
- * |-- mScrollX --|
- */
- return 0;
- }
- if ((my+n) > child) {
- /* this case:
- * |------ me ------|
- * |------ child ------|
- * |-- mScrollX --|
- */
- return child-my;
- }
- return n;
- }
-}
diff --git a/core/java/android/widget/Scroller.java b/core/java/android/widget/Scroller.java
deleted file mode 100644
index febc956..0000000
--- a/core/java/android/widget/Scroller.java
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.view.ViewConfiguration;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
-
-
-/**
- * This class encapsulates scrolling. The duration of the scroll
- * can be passed in the constructor and specifies the maximum time that
- * the scrolling animation should take. Past this time, the scrolling is
- * automatically moved to its final stage and computeScrollOffset()
- * will always return false to indicate that scrolling is over.
- */
-public class Scroller {
- private int mMode;
-
- private int mStartX;
- private int mStartY;
- private int mFinalX;
- private int mFinalY;
-
- private int mMinX;
- private int mMaxX;
- private int mMinY;
- private int mMaxY;
-
- private int mCurrX;
- private int mCurrY;
- private long mStartTime;
- private int mDuration;
- private float mDurationReciprocal;
- private float mDeltaX;
- private float mDeltaY;
- private float mViscousFluidScale;
- private float mViscousFluidNormalize;
- private boolean mFinished;
- private Interpolator mInterpolator;
-
- private float mCoeffX = 0.0f;
- private float mCoeffY = 1.0f;
- private float mVelocity;
-
- private static final int DEFAULT_DURATION = 250;
- private static final int SCROLL_MODE = 0;
- private static final int FLING_MODE = 1;
-
- private final float mDeceleration;
-
- /**
- * Create a Scroller with the default duration and interpolator.
- */
- public Scroller(Context context) {
- this(context, null);
- }
-
- /**
- * Create a Scroller with the specified interpolator. If the interpolator is
- * null, the default (viscous) interpolator will be used.
- */
- public Scroller(Context context, Interpolator interpolator) {
- mFinished = true;
- mInterpolator = interpolator;
- float ppi = context.getResources().getDisplayMetrics().density * 160.0f;
- mDeceleration = 9.8f // g (m/s^2)
- * 39.37f // inch/meter
- * ppi // pixels per inch
- * ViewConfiguration.getScrollFriction();
- }
-
- /**
- *
- * Returns whether the scroller has finished scrolling.
- *
- * @return True if the scroller has finished scrolling, false otherwise.
- */
- public final boolean isFinished() {
- return mFinished;
- }
-
- /**
- * Force the finished field to a particular value.
- *
- * @param finished The new finished value.
- */
- public final void forceFinished(boolean finished) {
- mFinished = finished;
- }
-
- /**
- * Returns how long the scroll event will take, in milliseconds.
- *
- * @return The duration of the scroll in milliseconds.
- */
- public final int getDuration() {
- return mDuration;
- }
-
- /**
- * Returns the current X offset in the scroll.
- *
- * @return The new X offset as an absolute distance from the origin.
- */
- public final int getCurrX() {
- return mCurrX;
- }
-
- /**
- * Returns the current Y offset in the scroll.
- *
- * @return The new Y offset as an absolute distance from the origin.
- */
- public final int getCurrY() {
- return mCurrY;
- }
-
- /**
- * Returns the start X offset in the scroll.
- *
- * @return The start X offset as an absolute distance from the origin.
- * @hide pending API council
- */
- public final int getStartX() {
- return mStartX;
- }
-
- /**
- * Returns the start Y offset in the scroll.
- *
- * @return The start Y offset as an absolute distance from the origin.
- * @hide pending API council
- */
- public final int getStartY() {
- return mStartY;
- }
-
- /**
- * Returns where the scroll will end. Valid only for "fling" scrolls.
- *
- * @return The final X offset as an absolute distance from the origin.
- */
- public final int getFinalX() {
- return mFinalX;
- }
-
- /**
- * Returns where the scroll will end. Valid only for "fling" scrolls.
- *
- * @return The final Y offset as an absolute distance from the origin.
- */
- public final int getFinalY() {
- return mFinalY;
- }
-
- /**
- * Call this when you want to know the new location. If it returns true,
- * the animation is not yet finished. loc will be altered to provide the
- * new location.
- */
- public boolean computeScrollOffset() {
- if (mFinished) {
- return false;
- }
-
- int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
-
- if (timePassed < mDuration) {
- switch (mMode) {
- case SCROLL_MODE:
- float x = (float)timePassed * mDurationReciprocal;
-
- if (mInterpolator == null)
- x = viscousFluid(x);
- else
- x = mInterpolator.getInterpolation(x);
-
- mCurrX = mStartX + Math.round(x * mDeltaX);
- mCurrY = mStartY + Math.round(x * mDeltaY);
- if ((mCurrX == mFinalX) && (mCurrY == mFinalY)) {
- mFinished = true;
- }
- break;
- case FLING_MODE:
- float timePassedSeconds = timePassed / 1000.0f;
- float distance = (mVelocity * timePassedSeconds)
- - (mDeceleration * timePassedSeconds * timePassedSeconds / 2.0f);
-
- mCurrX = mStartX + Math.round(distance * mCoeffX);
- // Pin to mMinX <= mCurrX <= mMaxX
- mCurrX = Math.min(mCurrX, mMaxX);
- mCurrX = Math.max(mCurrX, mMinX);
-
- mCurrY = mStartY + Math.round(distance * mCoeffY);
- // Pin to mMinY <= mCurrY <= mMaxY
- mCurrY = Math.min(mCurrY, mMaxY);
- mCurrY = Math.max(mCurrY, mMinY);
-
- if (mCurrX == mFinalX && mCurrY == mFinalY) {
- mFinished = true;
- }
-
- break;
- }
- }
- else {
- mCurrX = mFinalX;
- mCurrY = mFinalY;
- mFinished = true;
- }
- return true;
- }
-
- /**
- * Start scrolling by providing a starting point and the distance to travel.
- * The scroll will use the default value of 250 milliseconds for the
- * duration.
- *
- * @param startX Starting horizontal scroll offset in pixels. Positive
- * numbers will scroll the content to the left.
- * @param startY Starting vertical scroll offset in pixels. Positive numbers
- * will scroll the content up.
- * @param dx Horizontal distance to travel. Positive numbers will scroll the
- * content to the left.
- * @param dy Vertical distance to travel. Positive numbers will scroll the
- * content up.
- */
- public void startScroll(int startX, int startY, int dx, int dy) {
- startScroll(startX, startY, dx, dy, DEFAULT_DURATION);
- }
-
- /**
- * Start scrolling by providing a starting point and the distance to travel.
- *
- * @param startX Starting horizontal scroll offset in pixels. Positive
- * numbers will scroll the content to the left.
- * @param startY Starting vertical scroll offset in pixels. Positive numbers
- * will scroll the content up.
- * @param dx Horizontal distance to travel. Positive numbers will scroll the
- * content to the left.
- * @param dy Vertical distance to travel. Positive numbers will scroll the
- * content up.
- * @param duration Duration of the scroll in milliseconds.
- */
- public void startScroll(int startX, int startY, int dx, int dy, int duration) {
- mMode = SCROLL_MODE;
- mFinished = false;
- mDuration = duration;
- mStartTime = AnimationUtils.currentAnimationTimeMillis();
- mStartX = startX;
- mStartY = startY;
- mFinalX = startX + dx;
- mFinalY = startY + dy;
- mDeltaX = dx;
- mDeltaY = dy;
- mDurationReciprocal = 1.0f / (float) mDuration;
- // This controls the viscous fluid effect (how much of it)
- mViscousFluidScale = 8.0f;
- // must be set to 1.0 (used in viscousFluid())
- mViscousFluidNormalize = 1.0f;
- mViscousFluidNormalize = 1.0f / viscousFluid(1.0f);
- }
-
- /**
- * Start scrolling based on a fling gesture. The distance travelled will
- * depend on the initial velocity of the fling.
- *
- * @param startX Starting point of the scroll (X)
- * @param startY Starting point of the scroll (Y)
- * @param velocityX Initial velocity of the fling (X) measured in pixels per
- * second.
- * @param velocityY Initial velocity of the fling (Y) measured in pixels per
- * second
- * @param minX Minimum X value. The scroller will not scroll past this
- * point.
- * @param maxX Maximum X value. The scroller will not scroll past this
- * point.
- * @param minY Minimum Y value. The scroller will not scroll past this
- * point.
- * @param maxY Maximum Y value. The scroller will not scroll past this
- * point.
- */
- public void fling(int startX, int startY, int velocityX, int velocityY,
- int minX, int maxX, int minY, int maxY) {
- mMode = FLING_MODE;
- mFinished = false;
-
- float velocity = (float)Math.hypot(velocityX, velocityY);
-
- mVelocity = velocity;
- mDuration = (int) (1000 * velocity / mDeceleration); // Duration is in
- // milliseconds
- mStartTime = AnimationUtils.currentAnimationTimeMillis();
- mStartX = startX;
- mStartY = startY;
-
- mCoeffX = velocity == 0 ? 1.0f : velocityX / velocity;
- mCoeffY = velocity == 0 ? 1.0f : velocityY / velocity;
-
- int totalDistance = (int) ((velocity * velocity) / (2 * mDeceleration));
-
- mMinX = minX;
- mMaxX = maxX;
- mMinY = minY;
- mMaxY = maxY;
-
-
- mFinalX = startX + Math.round(totalDistance * mCoeffX);
- // Pin to mMinX <= mFinalX <= mMaxX
- mFinalX = Math.min(mFinalX, mMaxX);
- mFinalX = Math.max(mFinalX, mMinX);
-
- mFinalY = startY + Math.round(totalDistance * mCoeffY);
- // Pin to mMinY <= mFinalY <= mMaxY
- mFinalY = Math.min(mFinalY, mMaxY);
- mFinalY = Math.max(mFinalY, mMinY);
- }
-
-
-
- private float viscousFluid(float x)
- {
- x *= mViscousFluidScale;
- if (x < 1.0f) {
- x -= (1.0f - (float)Math.exp(-x));
- } else {
- float start = 0.36787944117f; // 1/e == exp(-1)
- x = 1.0f - (float)Math.exp(1.0f - x);
- x = start + x * (1.0f - start);
- }
- x *= mViscousFluidNormalize;
- return x;
- }
-
- /**
- *
- */
- public void abortAnimation() {
- mCurrX = mFinalX;
- mCurrY = mFinalY;
- mFinished = true;
- }
-
- /**
- * Extend the scroll animation. This allows a running animation to
- * scroll further and longer, when used with setFinalX() or setFinalY().
- *
- * @param extend Additional time to scroll in milliseconds.
- */
- public void extendDuration(int extend) {
- int passed = timePassed();
- mDuration = passed + extend;
- mDurationReciprocal = 1.0f / (float)mDuration;
- mFinished = false;
- }
-
- public int timePassed() {
- return (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
- }
-
- public void setFinalX(int newX) {
- mFinalX = newX;
- mDeltaX = mFinalX - mStartX;
- mFinished = false;
- }
-
- public void setFinalY(int newY) {
- mFinalY = newY;
- mDeltaY = mFinalY - mStartY;
- mFinished = false;
- }
-}
diff --git a/core/java/android/widget/SectionIndexer.java b/core/java/android/widget/SectionIndexer.java
deleted file mode 100644
index 24f894c..0000000
--- a/core/java/android/widget/SectionIndexer.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-/**
- * Interface that should be implemented on Adapters to enable fast scrolling
- * in an {@link AbsListView} between sections of the list. A section is a group of list items
- * to jump to that have something in common. For example, they may begin with the
- * same letter or they may be songs from the same artist.
- */
-public interface SectionIndexer {
- /**
- * This provides the list view with an array of section objects. In the simplest
- * case these are Strings, each containing one letter of the alphabet.
- * They could be more complex objects that indicate the grouping for the adapter's
- * consumption. The list view will call toString() on the objects to get the
- * preview letter to display while scrolling.
- * @return the array of objects that indicate the different sections of the list.
- */
- Object[] getSections();
-
- /**
- * Provides the starting index in the list for a given section.
- * @param section the index of the section to jump to.
- * @return the starting position of that section. If the section is out of bounds, the
- * position must be clipped to fall within the size of the list.
- */
- int getPositionForSection(int section);
-
- /**
- * This is a reverse mapping to fetch the section index for a given position
- * in the list.
- * @param position the position for which to return the section
- * @return the section index. If the position is out of bounds, the section index
- * must be clipped to fall within the size of the section array.
- */
- int getSectionForPosition(int position);
-}
diff --git a/core/java/android/widget/SeekBar.java b/core/java/android/widget/SeekBar.java
deleted file mode 100644
index dfee29b..0000000
--- a/core/java/android/widget/SeekBar.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-
-
-/**
- * A SeekBar is an extension of ProgressBar that adds a draggable thumb. The user can touch
- * the thumb and drag left or right to set the current progress level or use the arrow keys.
- * Placing focusable widgets to the left or right of a SeekBar is discouraged.
- * <p>
- * Clients of the SeekBar can attach a {@link SeekBar.OnSeekBarChangeListener} to
- * be notified of the user's actions.
- *
- * @attr ref android.R.styleable#SeekBar_thumb
- */
-public class SeekBar extends AbsSeekBar {
-
- /**
- * A callback that notifies clients when the progress level has been
- * changed. This includes changes that were initiated by the user through a
- * touch gesture or arrow key/trackball as well as changes that were initiated
- * programmatically.
- */
- public interface OnSeekBarChangeListener {
-
- /**
- * Notification that the progress level has changed. Clients can use the fromUser parameter
- * to distinguish user-initiated changes from those that occurred programmatically.
- *
- * @param seekBar The SeekBar whose progress has changed
- * @param progress The current progress level. This will be in the range 0..max where max
- * was set by {@link ProgressBar#setMax(int)}. (The default value for max is 100.)
- * @param fromUser True if the progress change was initiated by the user.
- */
- void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser);
-
- /**
- * Notification that the user has started a touch gesture. Clients may want to use this
- * to disable advancing the seekbar.
- * @param seekBar The SeekBar in which the touch gesture began
- */
- void onStartTrackingTouch(SeekBar seekBar);
-
- /**
- * Notification that the user has finished a touch gesture. Clients may want to use this
- * to re-enable advancing the seekbar.
- * @param seekBar The SeekBar in which the touch gesture began
- */
- void onStopTrackingTouch(SeekBar seekBar);
- }
-
- private OnSeekBarChangeListener mOnSeekBarChangeListener;
-
- public SeekBar(Context context) {
- this(context, null);
- }
-
- public SeekBar(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.seekBarStyle);
- }
-
- public SeekBar(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- void onProgressRefresh(float scale, boolean fromUser) {
- super.onProgressRefresh(scale, fromUser);
-
- if (mOnSeekBarChangeListener != null) {
- mOnSeekBarChangeListener.onProgressChanged(this, getProgress(), fromUser);
- }
- }
-
- /**
- * Sets a listener to receive notifications of changes to the SeekBar's progress level. Also
- * provides notifications of when the user starts and stops a touch gesture within the SeekBar.
- *
- * @param l The seek bar notification listener
- *
- * @see SeekBar.OnSeekBarChangeListener
- */
- public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) {
- mOnSeekBarChangeListener = l;
- }
-
- @Override
- void onStartTrackingTouch() {
- if (mOnSeekBarChangeListener != null) {
- mOnSeekBarChangeListener.onStartTrackingTouch(this);
- }
- }
-
- @Override
- void onStopTrackingTouch() {
- if (mOnSeekBarChangeListener != null) {
- mOnSeekBarChangeListener.onStopTrackingTouch(this);
- }
- }
-
-}
diff --git a/core/java/android/widget/SimpleAdapter.java b/core/java/android/widget/SimpleAdapter.java
deleted file mode 100644
index 093c24e..0000000
--- a/core/java/android/widget/SimpleAdapter.java
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.LayoutInflater;
-import android.net.Uri;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * An easy adapter to map static data to views defined in an XML file. You can specify the data
- * backing the list as an ArrayList of Maps. Each entry in the ArrayList corresponds to one row
- * in the list. The Maps contain the data for each row. You also specify an XML file that
- * defines the views used to display the row, and a mapping from keys in the Map to specific
- * views.
- *
- * Binding data to views occurs in two phases. First, if a
- * {@link android.widget.SimpleAdapter.ViewBinder} is available,
- * {@link ViewBinder#setViewValue(android.view.View, Object, String)}
- * is invoked. If the returned value is true, binding has occurred.
- * If the returned value is false, the following views are then tried in order:
- * <ul>
- * <li> A view that implements Checkable (e.g. CheckBox). The expected bind value is a boolean.
- * <li> TextView. The expected bind value is a string and {@link #setViewText(TextView, String)}
- * is invoked.
- * <li> ImageView. The expected bind value is a resource id or a string and
- * {@link #setViewImage(ImageView, int)} or {@link #setViewImage(ImageView, String)} is invoked.
- * </ul>
- * If no appropriate binding can be found, an {@link IllegalStateException} is thrown.
- */
-public class SimpleAdapter extends BaseAdapter implements Filterable {
- private int[] mTo;
- private String[] mFrom;
- private ViewBinder mViewBinder;
-
- private List<? extends Map<String, ?>> mData;
-
- private int mResource;
- private int mDropDownResource;
- private LayoutInflater mInflater;
-
- private SimpleFilter mFilter;
- private ArrayList<Map<String, ?>> mUnfilteredData;
-
- /**
- * Constructor
- *
- * @param context The context where the View associated with this SimpleAdapter is running
- * @param data A List of Maps. Each entry in the List corresponds to one row in the list. The
- * Maps contain the data for each row, and should include all the entries specified in
- * "from"
- * @param resource Resource identifier of a view layout that defines the views for this list
- * item. The layout file should include at least those named views defined in "to"
- * @param from A list of column names that will be added to the Map associated with each
- * item.
- * @param to The views that should display column in the "from" parameter. These should all be
- * TextViews. The first N views in this list are given the values of the first N columns
- * in the from parameter.
- */
- public SimpleAdapter(Context context, List<? extends Map<String, ?>> data,
- int resource, String[] from, int[] to) {
- mData = data;
- mResource = mDropDownResource = resource;
- mFrom = from;
- mTo = to;
- mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
-
-
- /**
- * @see android.widget.Adapter#getCount()
- */
- public int getCount() {
- return mData.size();
- }
-
- /**
- * @see android.widget.Adapter#getItem(int)
- */
- public Object getItem(int position) {
- return mData.get(position);
- }
-
- /**
- * @see android.widget.Adapter#getItemId(int)
- */
- public long getItemId(int position) {
- return position;
- }
-
- /**
- * @see android.widget.Adapter#getView(int, View, ViewGroup)
- */
- public View getView(int position, View convertView, ViewGroup parent) {
- return createViewFromResource(position, convertView, parent, mResource);
- }
-
- private View createViewFromResource(int position, View convertView,
- ViewGroup parent, int resource) {
- View v;
- if (convertView == null) {
- v = mInflater.inflate(resource, parent, false);
-
- final int[] to = mTo;
- final int count = to.length;
- final View[] holder = new View[count];
-
- for (int i = 0; i < count; i++) {
- holder[i] = v.findViewById(to[i]);
- }
-
- v.setTag(holder);
- } else {
- v = convertView;
- }
-
- bindView(position, v);
-
- return v;
- }
-
- /**
- * <p>Sets the layout resource to create the drop down views.</p>
- *
- * @param resource the layout resource defining the drop down views
- * @see #getDropDownView(int, android.view.View, android.view.ViewGroup)
- */
- public void setDropDownViewResource(int resource) {
- this.mDropDownResource = resource;
- }
-
- @Override
- public View getDropDownView(int position, View convertView, ViewGroup parent) {
- return createViewFromResource(position, convertView, parent, mDropDownResource);
- }
-
- private void bindView(int position, View view) {
- final Map dataSet = mData.get(position);
- if (dataSet == null) {
- return;
- }
-
- final ViewBinder binder = mViewBinder;
- final View[] holder = (View[]) view.getTag();
- final String[] from = mFrom;
- final int[] to = mTo;
- final int count = to.length;
-
- for (int i = 0; i < count; i++) {
- final View v = holder[i];
- if (v != null) {
- final Object data = dataSet.get(from[i]);
- String text = data == null ? "" : data.toString();
- if (text == null) {
- text = "";
- }
-
- boolean bound = false;
- if (binder != null) {
- bound = binder.setViewValue(v, data, text);
- }
-
- if (!bound) {
- if (v instanceof Checkable) {
- if (data instanceof Boolean) {
- ((Checkable) v).setChecked((Boolean) data);
- } else {
- throw new IllegalStateException(v.getClass().getName() +
- " should be bound to a Boolean, not a " + data.getClass());
- }
- } else if (v instanceof TextView) {
- // Note: keep the instanceof TextView check at the bottom of these
- // ifs since a lot of views are TextViews (e.g. CheckBoxes).
- setViewText((TextView) v, text);
- } else if (v instanceof ImageView) {
- if (data instanceof Integer) {
- setViewImage((ImageView) v, (Integer) data);
- } else {
- setViewImage((ImageView) v, text);
- }
- } else {
- throw new IllegalStateException(v.getClass().getName() + " is not a " +
- " view that can be bounds by this SimpleAdapter");
- }
- }
- }
- }
- }
-
- /**
- * Returns the {@link ViewBinder} used to bind data to views.
- *
- * @return a ViewBinder or null if the binder does not exist
- *
- * @see #setViewBinder(android.widget.SimpleAdapter.ViewBinder)
- */
- public ViewBinder getViewBinder() {
- return mViewBinder;
- }
-
- /**
- * Sets the binder used to bind data to views.
- *
- * @param viewBinder the binder used to bind data to views, can be null to
- * remove the existing binder
- *
- * @see #getViewBinder()
- */
- public void setViewBinder(ViewBinder viewBinder) {
- mViewBinder = viewBinder;
- }
-
- /**
- * Called by bindView() to set the image for an ImageView but only if
- * there is no existing ViewBinder or if the existing ViewBinder cannot
- * handle binding to an ImageView.
- *
- * This method is called instead of {@link #setViewImage(ImageView, String)}
- * if the supplied data is an int or Integer.
- *
- * @param v ImageView to receive an image
- * @param value the value retrieved from the data set
- *
- * @see #setViewImage(ImageView, String)
- */
- public void setViewImage(ImageView v, int value) {
- v.setImageResource(value);
- }
-
- /**
- * Called by bindView() to set the image for an ImageView but only if
- * there is no existing ViewBinder or if the existing ViewBinder cannot
- * handle binding to an ImageView.
- *
- * By default, the value will be treated as an image resource. If the
- * value cannot be used as an image resource, the value is used as an
- * image Uri.
- *
- * This method is called instead of {@link #setViewImage(ImageView, int)}
- * if the supplied data is not an int or Integer.
- *
- * @param v ImageView to receive an image
- * @param value the value retrieved from the data set
- *
- * @see #setViewImage(ImageView, int)
- */
- public void setViewImage(ImageView v, String value) {
- try {
- v.setImageResource(Integer.parseInt(value));
- } catch (NumberFormatException nfe) {
- v.setImageURI(Uri.parse(value));
- }
- }
-
- /**
- * Called by bindView() to set the text for a TextView but only if
- * there is no existing ViewBinder or if the existing ViewBinder cannot
- * handle binding to an TextView.
- *
- * @param v TextView to receive text
- * @param text the text to be set for the TextView
- */
- public void setViewText(TextView v, String text) {
- v.setText(text);
- }
-
- public Filter getFilter() {
- if (mFilter == null) {
- mFilter = new SimpleFilter();
- }
- return mFilter;
- }
-
- /**
- * This class can be used by external clients of SimpleAdapter to bind
- * values to views.
- *
- * You should use this class to bind values to views that are not
- * directly supported by SimpleAdapter or to change the way binding
- * occurs for views supported by SimpleAdapter.
- *
- * @see SimpleAdapter#setViewImage(ImageView, int)
- * @see SimpleAdapter#setViewImage(ImageView, String)
- * @see SimpleAdapter#setViewText(TextView, String)
- */
- public static interface ViewBinder {
- /**
- * Binds the specified data to the specified view.
- *
- * When binding is handled by this ViewBinder, this method must return true.
- * If this method returns false, SimpleAdapter will attempts to handle
- * the binding on its own.
- *
- * @param view the view to bind the data to
- * @param data the data to bind to the view
- * @param textRepresentation a safe String representation of the supplied data:
- * it is either the result of data.toString() or an empty String but it
- * is never null
- *
- * @return true if the data was bound to the view, false otherwise
- */
- boolean setViewValue(View view, Object data, String textRepresentation);
- }
-
- /**
- * <p>An array filters constrains the content of the array adapter with
- * a prefix. Each item that does not start with the supplied prefix
- * is removed from the list.</p>
- */
- private class SimpleFilter extends Filter {
-
- @Override
- protected FilterResults performFiltering(CharSequence prefix) {
- FilterResults results = new FilterResults();
-
- if (mUnfilteredData == null) {
- mUnfilteredData = new ArrayList<Map<String, ?>>(mData);
- }
-
- if (prefix == null || prefix.length() == 0) {
- ArrayList<Map<String, ?>> list = mUnfilteredData;
- results.values = list;
- results.count = list.size();
- } else {
- String prefixString = prefix.toString().toLowerCase();
-
- ArrayList<Map<String, ?>> unfilteredValues = mUnfilteredData;
- int count = unfilteredValues.size();
-
- ArrayList<Map<String, ?>> newValues = new ArrayList<Map<String, ?>>(count);
-
- for (int i = 0; i < count; i++) {
- Map<String, ?> h = unfilteredValues.get(i);
- if (h != null) {
-
- int len = mTo.length;
-
- for (int j=0; j<len; j++) {
- String str = (String)h.get(mFrom[j]);
-
- String[] words = str.split(" ");
- int wordCount = words.length;
-
- for (int k = 0; k < wordCount; k++) {
- String word = words[k];
-
- if (word.toLowerCase().startsWith(prefixString)) {
- newValues.add(h);
- break;
- }
- }
- }
- }
- }
-
- results.values = newValues;
- results.count = newValues.size();
- }
-
- return results;
- }
-
- @Override
- protected void publishResults(CharSequence constraint, FilterResults results) {
- //noinspection unchecked
- mData = (List<Map<String, ?>>) results.values;
- if (results.count > 0) {
- notifyDataSetChanged();
- } else {
- notifyDataSetInvalidated();
- }
- }
- }
-}
diff --git a/core/java/android/widget/SimpleCursorAdapter.java b/core/java/android/widget/SimpleCursorAdapter.java
deleted file mode 100644
index c1595ea..0000000
--- a/core/java/android/widget/SimpleCursorAdapter.java
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * An easy adapter to map columns from a cursor to TextViews or ImageViews
- * defined in an XML file. You can specify which columns you want, which
- * views you want to display the columns, and the XML file that defines
- * the appearance of these views.
- *
- * Binding occurs in two phases. First, if a
- * {@link android.widget.SimpleCursorAdapter.ViewBinder} is available,
- * {@link ViewBinder#setViewValue(android.view.View, android.database.Cursor, int)}
- * is invoked. If the returned value is true, binding has occured. If the
- * returned value is false and the view to bind is a TextView,
- * {@link #setViewText(TextView, String)} is invoked. If the returned value
- * is false and the view to bind is an ImageView,
- * {@link #setViewImage(ImageView, String)} is invoked. If no appropriate
- * binding can be found, an {@link IllegalStateException} is thrown.
- *
- * If this adapter is used with filtering, for instance in an
- * {@link android.widget.AutoCompleteTextView}, you can use the
- * {@link android.widget.SimpleCursorAdapter.CursorToStringConverter} and the
- * {@link android.widget.FilterQueryProvider} interfaces
- * to get control over the filtering process. You can refer to
- * {@link #convertToString(android.database.Cursor)} and
- * {@link #runQueryOnBackgroundThread(CharSequence)} for more information.
- */
-public class SimpleCursorAdapter extends ResourceCursorAdapter {
- /**
- * A list of columns containing the data to bind to the UI.
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected int[] mFrom;
- /**
- * A list of View ids representing the views to which the data must be bound.
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected int[] mTo;
-
- private int mStringConversionColumn = -1;
- private CursorToStringConverter mCursorToStringConverter;
- private ViewBinder mViewBinder;
- private String[] mOriginalFrom;
-
- /**
- * Constructor.
- *
- * @param context The context where the ListView associated with this
- * SimpleListItemFactory is running
- * @param layout resource identifier of a layout file that defines the views
- * for this list item. Thelayout file should include at least
- * those named views defined in "to"
- * @param c The database cursor. Can be null if the cursor is not available yet.
- * @param from A list of column names representing the data to bind to the UI. Can be null
- * if the cursor is not available yet.
- * @param to The views that should display column in the "from" parameter.
- * These should all be TextViews. The first N views in this list
- * are given the values of the first N columns in the from
- * parameter. Can be null if the cursor is not available yet.
- */
- public SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
- super(context, layout, c);
- mTo = to;
- mOriginalFrom = from;
- findColumns(from);
- }
-
- @Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- return generateViewHolder(super.newView(context, cursor, parent));
- }
-
- @Override
- public View newDropDownView(Context context, Cursor cursor, ViewGroup parent) {
- return generateViewHolder(super.newDropDownView(context, cursor, parent));
- }
-
- private View generateViewHolder(View v) {
- final int[] to = mTo;
- final int count = to.length;
- final View[] holder = new View[count];
-
- for (int i = 0; i < count; i++) {
- holder[i] = v.findViewById(to[i]);
- }
- v.setTag(holder);
-
- return v;
- }
-
- /**
- * Binds all of the field names passed into the "to" parameter of the
- * constructor with their corresponding cursor columns as specified in the
- * "from" parameter.
- *
- * Binding occurs in two phases. First, if a
- * {@link android.widget.SimpleCursorAdapter.ViewBinder} is available,
- * {@link ViewBinder#setViewValue(android.view.View, android.database.Cursor, int)}
- * is invoked. If the returned value is true, binding has occured. If the
- * returned value is false and the view to bind is a TextView,
- * {@link #setViewText(TextView, String)} is invoked. If the returned value is
- * false and the view to bind is an ImageView,
- * {@link #setViewImage(ImageView, String)} is invoked. If no appropriate
- * binding can be found, an {@link IllegalStateException} is thrown.
- *
- * @throws IllegalStateException if binding cannot occur
- *
- * @see android.widget.CursorAdapter#bindView(android.view.View,
- * android.content.Context, android.database.Cursor)
- * @see #getViewBinder()
- * @see #setViewBinder(android.widget.SimpleCursorAdapter.ViewBinder)
- * @see #setViewImage(ImageView, String)
- * @see #setViewText(TextView, String)
- */
- @Override
- public void bindView(View view, Context context, Cursor cursor) {
- final View[] holder = (View[]) view.getTag();
- final ViewBinder binder = mViewBinder;
- final int count = mTo.length;
- final int[] from = mFrom;
-
- for (int i = 0; i < count; i++) {
- final View v = holder[i];
- if (v != null) {
- String text = cursor.getString(from[i]);
- if (text == null) {
- text = "";
- }
-
- boolean bound = false;
- if (binder != null) {
- bound = binder.setViewValue(v, cursor, from[i]);
- }
-
- if (!bound) {
- if (v instanceof TextView) {
- setViewText((TextView) v, text);
- } else if (v instanceof ImageView) {
- setViewImage((ImageView) v, text);
- } else {
- throw new IllegalStateException(v.getClass().getName() + " is not a " +
- " view that can be bounds by this SimpleCursorAdapter");
- }
- }
- }
- }
- }
-
- /**
- * Returns the {@link ViewBinder} used to bind data to views.
- *
- * @return a ViewBinder or null if the binder does not exist
- *
- * @see #bindView(android.view.View, android.content.Context, android.database.Cursor)
- * @see #setViewBinder(android.widget.SimpleCursorAdapter.ViewBinder)
- */
- public ViewBinder getViewBinder() {
- return mViewBinder;
- }
-
- /**
- * Sets the binder used to bind data to views.
- *
- * @param viewBinder the binder used to bind data to views, can be null to
- * remove the existing binder
- *
- * @see #bindView(android.view.View, android.content.Context, android.database.Cursor)
- * @see #getViewBinder()
- */
- public void setViewBinder(ViewBinder viewBinder) {
- mViewBinder = viewBinder;
- }
-
- /**
- * Called by bindView() to set the image for an ImageView but only if
- * there is no existing ViewBinder or if the existing ViewBinder cannot
- * handle binding to an ImageView.
- *
- * By default, the value will be treated as an image resource. If the
- * value cannot be used as an image resource, the value is used as an
- * image Uri.
- *
- * Intended to be overridden by Adapters that need to filter strings
- * retrieved from the database.
- *
- * @param v ImageView to receive an image
- * @param value the value retrieved from the cursor
- */
- public void setViewImage(ImageView v, String value) {
- try {
- v.setImageResource(Integer.parseInt(value));
- } catch (NumberFormatException nfe) {
- v.setImageURI(Uri.parse(value));
- }
- }
-
- /**
- * Called by bindView() to set the text for a TextView but only if
- * there is no existing ViewBinder or if the existing ViewBinder cannot
- * handle binding to an TextView.
- *
- * Intended to be overridden by Adapters that need to filter strings
- * retrieved from the database.
- *
- * @param v TextView to receive text
- * @param text the text to be set for the TextView
- */
- public void setViewText(TextView v, String text) {
- v.setText(text);
- }
-
- /**
- * Return the index of the column used to get a String representation
- * of the Cursor.
- *
- * @return a valid index in the current Cursor or -1
- *
- * @see android.widget.CursorAdapter#convertToString(android.database.Cursor)
- * @see #setStringConversionColumn(int)
- * @see #setCursorToStringConverter(android.widget.SimpleCursorAdapter.CursorToStringConverter)
- * @see #getCursorToStringConverter()
- */
- public int getStringConversionColumn() {
- return mStringConversionColumn;
- }
-
- /**
- * Defines the index of the column in the Cursor used to get a String
- * representation of that Cursor. The column is used to convert the
- * Cursor to a String only when the current CursorToStringConverter
- * is null.
- *
- * @param stringConversionColumn a valid index in the current Cursor or -1 to use the default
- * conversion mechanism
- *
- * @see android.widget.CursorAdapter#convertToString(android.database.Cursor)
- * @see #getStringConversionColumn()
- * @see #setCursorToStringConverter(android.widget.SimpleCursorAdapter.CursorToStringConverter)
- * @see #getCursorToStringConverter()
- */
- public void setStringConversionColumn(int stringConversionColumn) {
- mStringConversionColumn = stringConversionColumn;
- }
-
- /**
- * Returns the converter used to convert the filtering Cursor
- * into a String.
- *
- * @return null if the converter does not exist or an instance of
- * {@link android.widget.SimpleCursorAdapter.CursorToStringConverter}
- *
- * @see #setCursorToStringConverter(android.widget.SimpleCursorAdapter.CursorToStringConverter)
- * @see #getStringConversionColumn()
- * @see #setStringConversionColumn(int)
- * @see android.widget.CursorAdapter#convertToString(android.database.Cursor)
- */
- public CursorToStringConverter getCursorToStringConverter() {
- return mCursorToStringConverter;
- }
-
- /**
- * Sets the converter used to convert the filtering Cursor
- * into a String.
- *
- * @param cursorToStringConverter the Cursor to String converter, or
- * null to remove the converter
- *
- * @see #setCursorToStringConverter(android.widget.SimpleCursorAdapter.CursorToStringConverter)
- * @see #getStringConversionColumn()
- * @see #setStringConversionColumn(int)
- * @see android.widget.CursorAdapter#convertToString(android.database.Cursor)
- */
- public void setCursorToStringConverter(CursorToStringConverter cursorToStringConverter) {
- mCursorToStringConverter = cursorToStringConverter;
- }
-
- /**
- * Returns a CharSequence representation of the specified Cursor as defined
- * by the current CursorToStringConverter. If no CursorToStringConverter
- * has been set, the String conversion column is used instead. If the
- * conversion column is -1, the returned String is empty if the cursor
- * is null or Cursor.toString().
- *
- * @param cursor the Cursor to convert to a CharSequence
- *
- * @return a non-null CharSequence representing the cursor
- */
- @Override
- public CharSequence convertToString(Cursor cursor) {
- if (mCursorToStringConverter != null) {
- return mCursorToStringConverter.convertToString(cursor);
- } else if (mStringConversionColumn > -1) {
- return cursor.getString(mStringConversionColumn);
- }
-
- return super.convertToString(cursor);
- }
-
- /**
- * Create a map from an array of strings to an array of column-id integers in mCursor.
- * If mCursor is null, the array will be discarded.
- *
- * @param from the Strings naming the columns of interest
- */
- private void findColumns(String[] from) {
- if (mCursor != null) {
- int i;
- int count = from.length;
- if (mFrom == null || mFrom.length != count) {
- mFrom = new int[count];
- }
- for (i = 0; i < count; i++) {
- mFrom[i] = mCursor.getColumnIndexOrThrow(from[i]);
- }
- } else {
- mFrom = null;
- }
- }
-
- @Override
- public void changeCursor(Cursor c) {
- super.changeCursor(c);
- // rescan columns in case cursor layout is different
- findColumns(mOriginalFrom);
- }
-
- /**
- * Change the cursor and change the column-to-view mappings at the same time.
- *
- * @param c The database cursor. Can be null if the cursor is not available yet.
- * @param from A list of column names representing the data to bind to the UI. Can be null
- * if the cursor is not available yet.
- * @param to The views that should display column in the "from" parameter.
- * These should all be TextViews. The first N views in this list
- * are given the values of the first N columns in the from
- * parameter. Can be null if the cursor is not available yet.
- */
- public void changeCursorAndColumns(Cursor c, String[] from, int[] to) {
- mOriginalFrom = from;
- mTo = to;
- super.changeCursor(c);
- findColumns(mOriginalFrom);
- }
-
- /**
- * This class can be used by external clients of SimpleCursorAdapter
- * to bind values fom the Cursor to views.
- *
- * You should use this class to bind values from the Cursor to views
- * that are not directly supported by SimpleCursorAdapter or to
- * change the way binding occurs for views supported by
- * SimpleCursorAdapter.
- *
- * @see SimpleCursorAdapter#bindView(android.view.View, android.content.Context, android.database.Cursor)
- * @see SimpleCursorAdapter#setViewImage(ImageView, String)
- * @see SimpleCursorAdapter#setViewText(TextView, String)
- */
- public static interface ViewBinder {
- /**
- * Binds the Cursor column defined by the specified index to the specified view.
- *
- * When binding is handled by this ViewBinder, this method must return true.
- * If this method returns false, SimpleCursorAdapter will attempts to handle
- * the binding on its own.
- *
- * @param view the view to bind the data to
- * @param cursor the cursor to get the data from
- * @param columnIndex the column at which the data can be found in the cursor
- *
- * @return true if the data was bound to the view, false otherwise
- */
- boolean setViewValue(View view, Cursor cursor, int columnIndex);
- }
-
- /**
- * This class can be used by external clients of SimpleCursorAdapter
- * to define how the Cursor should be converted to a String.
- *
- * @see android.widget.CursorAdapter#convertToString(android.database.Cursor)
- */
- public static interface CursorToStringConverter {
- /**
- * Returns a CharSequence representing the specified Cursor.
- *
- * @param cursor the cursor for which a CharSequence representation
- * is requested
- *
- * @return a non-null CharSequence representing the cursor
- */
- CharSequence convertToString(Cursor cursor);
- }
-
-}
diff --git a/core/java/android/widget/SimpleCursorTreeAdapter.java b/core/java/android/widget/SimpleCursorTreeAdapter.java
deleted file mode 100644
index c456f56..0000000
--- a/core/java/android/widget/SimpleCursorTreeAdapter.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.view.View;
-
-/**
- * An easy adapter to map columns from a cursor to TextViews or ImageViews
- * defined in an XML file. You can specify which columns you want, which views
- * you want to display the columns, and the XML file that defines the appearance
- * of these views. Separate XML files for child and groups are possible.
- * TextViews bind the values to their text property (see
- * {@link TextView#setText(CharSequence)}). ImageViews bind the values to their
- * image's Uri property (see {@link ImageView#setImageURI(android.net.Uri)}).
- */
-public abstract class SimpleCursorTreeAdapter extends ResourceCursorTreeAdapter {
- /** The indices of columns that contain data to display for a group. */
- private int[] mGroupFrom;
- /**
- * The View IDs that will display a group's data fetched from the
- * corresponding column.
- */
- private int[] mGroupTo;
-
- /** The indices of columns that contain data to display for a child. */
- private int[] mChildFrom;
- /**
- * The View IDs that will display a child's data fetched from the
- * corresponding column.
- */
- private int[] mChildTo;
-
- /**
- * Constructor.
- *
- * @param context The context where the {@link ExpandableListView}
- * associated with this {@link SimpleCursorTreeAdapter} is
- * running
- * @param cursor The database cursor
- * @param collapsedGroupLayout The resource identifier of a layout file that
- * defines the views for a collapsed group. The layout file
- * should include at least those named views defined in groupTo.
- * @param expandedGroupLayout The resource identifier of a layout file that
- * defines the views for an expanded group. The layout file
- * should include at least those named views defined in groupTo.
- * @param groupFrom A list of column names that will be used to display the
- * data for a group.
- * @param groupTo The group views (from the group layouts) that should
- * display column in the "from" parameter. These should all be
- * TextViews or ImageViews. The first N views in this list are
- * given the values of the first N columns in the from parameter.
- * @param childLayout The resource identifier of a layout file that defines
- * the views for a child (except the last). The layout file
- * should include at least those named views defined in childTo.
- * @param lastChildLayout The resource identifier of a layout file that
- * defines the views for the last child within a group. The
- * layout file should include at least those named views defined
- * in childTo.
- * @param childFrom A list of column names that will be used to display the
- * data for a child.
- * @param childTo The child views (from the child layouts) that should
- * display column in the "from" parameter. These should all be
- * TextViews or ImageViews. The first N views in this list are
- * given the values of the first N columns in the from parameter.
- */
- public SimpleCursorTreeAdapter(Context context, Cursor cursor, int collapsedGroupLayout,
- int expandedGroupLayout, String[] groupFrom, int[] groupTo, int childLayout,
- int lastChildLayout, String[] childFrom, int[] childTo) {
- super(context, cursor, collapsedGroupLayout, expandedGroupLayout, childLayout,
- lastChildLayout);
- init(groupFrom, groupTo, childFrom, childTo);
- }
-
- /**
- * Constructor.
- *
- * @param context The context where the {@link ExpandableListView}
- * associated with this {@link SimpleCursorTreeAdapter} is
- * running
- * @param cursor The database cursor
- * @param collapsedGroupLayout The resource identifier of a layout file that
- * defines the views for a collapsed group. The layout file
- * should include at least those named views defined in groupTo.
- * @param expandedGroupLayout The resource identifier of a layout file that
- * defines the views for an expanded group. The layout file
- * should include at least those named views defined in groupTo.
- * @param groupFrom A list of column names that will be used to display the
- * data for a group.
- * @param groupTo The group views (from the group layouts) that should
- * display column in the "from" parameter. These should all be
- * TextViews or ImageViews. The first N views in this list are
- * given the values of the first N columns in the from parameter.
- * @param childLayout The resource identifier of a layout file that defines
- * the views for a child. The layout file
- * should include at least those named views defined in childTo.
- * @param childFrom A list of column names that will be used to display the
- * data for a child.
- * @param childTo The child views (from the child layouts) that should
- * display column in the "from" parameter. These should all be
- * TextViews or ImageViews. The first N views in this list are
- * given the values of the first N columns in the from parameter.
- */
- public SimpleCursorTreeAdapter(Context context, Cursor cursor, int collapsedGroupLayout,
- int expandedGroupLayout, String[] groupFrom, int[] groupTo,
- int childLayout, String[] childFrom, int[] childTo) {
- super(context, cursor, collapsedGroupLayout, expandedGroupLayout, childLayout);
- init(groupFrom, groupTo, childFrom, childTo);
- }
-
- /**
- * Constructor.
- *
- * @param context The context where the {@link ExpandableListView}
- * associated with this {@link SimpleCursorTreeAdapter} is
- * running
- * @param cursor The database cursor
- * @param groupLayout The resource identifier of a layout file that defines
- * the views for a group. The layout file should include at least
- * those named views defined in groupTo.
- * @param groupFrom A list of column names that will be used to display the
- * data for a group.
- * @param groupTo The group views (from the group layouts) that should
- * display column in the "from" parameter. These should all be
- * TextViews or ImageViews. The first N views in this list are
- * given the values of the first N columns in the from parameter.
- * @param childLayout The resource identifier of a layout file that defines
- * the views for a child. The layout file should include at least
- * those named views defined in childTo.
- * @param childFrom A list of column names that will be used to display the
- * data for a child.
- * @param childTo The child views (from the child layouts) that should
- * display column in the "from" parameter. These should all be
- * TextViews or ImageViews. The first N views in this list are
- * given the values of the first N columns in the from parameter.
- */
- public SimpleCursorTreeAdapter(Context context, Cursor cursor, int groupLayout,
- String[] groupFrom, int[] groupTo, int childLayout, String[] childFrom,
- int[] childTo) {
- super(context, cursor, groupLayout, childLayout);
- init(groupFrom, groupTo, childFrom, childTo);
- }
-
- private void init(String[] groupFromNames, int[] groupTo, String[] childFromNames,
- int[] childTo) {
- mGroupTo = groupTo;
-
- mChildTo = childTo;
-
- // Get the group cursor column indices, the child cursor column indices will come
- // when needed
- initGroupFromColumns(groupFromNames);
-
- // Get a temporary child cursor to init the column indices
- if (getGroupCount() > 0) {
- MyCursorHelper tmpCursorHelper = getChildrenCursorHelper(0, true);
- if (tmpCursorHelper != null) {
- initChildrenFromColumns(childFromNames, tmpCursorHelper.getCursor());
- deactivateChildrenCursorHelper(0);
- }
- }
- }
-
- private void initFromColumns(Cursor cursor, String[] fromColumnNames, int[] fromColumns) {
- for (int i = fromColumnNames.length - 1; i >= 0; i--) {
- fromColumns[i] = cursor.getColumnIndexOrThrow(fromColumnNames[i]);
- }
- }
-
- private void initGroupFromColumns(String[] groupFromNames) {
- mGroupFrom = new int[groupFromNames.length];
- initFromColumns(mGroupCursorHelper.getCursor(), groupFromNames, mGroupFrom);
- }
-
- private void initChildrenFromColumns(String[] childFromNames, Cursor childCursor) {
- mChildFrom = new int[childFromNames.length];
- initFromColumns(childCursor, childFromNames, mChildFrom);
- }
-
- private void bindView(View view, Context context, Cursor cursor, int[] from, int[] to) {
- for (int i = 0; i < to.length; i++) {
- View v = view.findViewById(to[i]);
- if (v != null) {
- String text = cursor.getString(from[i]);
- if (text == null) {
- text = "";
- }
- if (v instanceof TextView) {
- ((TextView) v).setText(text);
- } else if (v instanceof ImageView) {
- setViewImage((ImageView) v, text);
- } else {
- throw new IllegalStateException("SimpleCursorAdapter can bind values only to" +
- " TextView and ImageView!");
- }
- }
- }
- }
-
- @Override
- protected void bindChildView(View view, Context context, Cursor cursor, boolean isLastChild) {
- bindView(view, context, cursor, mChildFrom, mChildTo);
- }
-
- @Override
- protected void bindGroupView(View view, Context context, Cursor cursor, boolean isExpanded) {
- bindView(view, context, cursor, mGroupFrom, mGroupTo);
- }
-
- /**
- * Called by bindView() to set the image for an ImageView. By default, the
- * value will be treated as a Uri. Intended to be overridden by Adapters
- * that need to filter strings retrieved from the database.
- *
- * @param v ImageView to receive an image
- * @param value the value retrieved from the cursor
- */
- protected void setViewImage(ImageView v, String value) {
- try {
- v.setImageResource(Integer.parseInt(value));
- } catch (NumberFormatException nfe) {
- v.setImageURI(Uri.parse(value));
- }
- }
-}
diff --git a/core/java/android/widget/SimpleExpandableListAdapter.java b/core/java/android/widget/SimpleExpandableListAdapter.java
deleted file mode 100644
index 015c169..0000000
--- a/core/java/android/widget/SimpleExpandableListAdapter.java
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.LayoutInflater;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * An easy adapter to map static data to group and child views defined in an XML
- * file. You can separately specify the data backing the group as a List of
- * Maps. Each entry in the ArrayList corresponds to one group in the expandable
- * list. The Maps contain the data for each row. You also specify an XML file
- * that defines the views used to display a group, and a mapping from keys in
- * the Map to specific views. This process is similar for a child, except it is
- * one-level deeper so the data backing is specified as a List<List<Map>>,
- * where the first List corresponds to the group of the child, the second List
- * corresponds to the position of the child within the group, and finally the
- * Map holds the data for that particular child.
- */
-public class SimpleExpandableListAdapter extends BaseExpandableListAdapter {
- private List<? extends Map<String, ?>> mGroupData;
- private int mExpandedGroupLayout;
- private int mCollapsedGroupLayout;
- private String[] mGroupFrom;
- private int[] mGroupTo;
-
- private List<? extends List<? extends Map<String, ?>>> mChildData;
- private int mChildLayout;
- private int mLastChildLayout;
- private String[] mChildFrom;
- private int[] mChildTo;
-
- private LayoutInflater mInflater;
-
- /**
- * Constructor
- *
- * @param context The context where the {@link ExpandableListView}
- * associated with this {@link SimpleExpandableListAdapter} is
- * running
- * @param groupData A List of Maps. Each entry in the List corresponds to
- * one group in the list. The Maps contain the data for each
- * group, and should include all the entries specified in
- * "groupFrom"
- * @param groupFrom A list of keys that will be fetched from the Map
- * associated with each group.
- * @param groupTo The group views that should display column in the
- * "groupFrom" parameter. These should all be TextViews. The
- * first N views in this list are given the values of the first N
- * columns in the groupFrom parameter.
- * @param groupLayout resource identifier of a view layout that defines the
- * views for a group. The layout file should include at least
- * those named views defined in "groupTo"
- * @param childData A List of List of Maps. Each entry in the outer List
- * corresponds to a group (index by group position), each entry
- * in the inner List corresponds to a child within the group
- * (index by child position), and the Map corresponds to the data
- * for a child (index by values in the childFrom array). The Map
- * contains the data for each child, and should include all the
- * entries specified in "childFrom"
- * @param childFrom A list of keys that will be fetched from the Map
- * associated with each child.
- * @param childTo The child views that should display column in the
- * "childFrom" parameter. These should all be TextViews. The
- * first N views in this list are given the values of the first N
- * columns in the childFrom parameter.
- * @param childLayout resource identifier of a view layout that defines the
- * views for a child. The layout file should include at least
- * those named views defined in "childTo"
- */
- public SimpleExpandableListAdapter(Context context,
- List<? extends Map<String, ?>> groupData, int groupLayout,
- String[] groupFrom, int[] groupTo,
- List<? extends List<? extends Map<String, ?>>> childData,
- int childLayout, String[] childFrom, int[] childTo) {
- this(context, groupData, groupLayout, groupLayout, groupFrom, groupTo, childData,
- childLayout, childLayout, childFrom, childTo);
- }
-
- /**
- * Constructor
- *
- * @param context The context where the {@link ExpandableListView}
- * associated with this {@link SimpleExpandableListAdapter} is
- * running
- * @param groupData A List of Maps. Each entry in the List corresponds to
- * one group in the list. The Maps contain the data for each
- * group, and should include all the entries specified in
- * "groupFrom"
- * @param groupFrom A list of keys that will be fetched from the Map
- * associated with each group.
- * @param groupTo The group views that should display column in the
- * "groupFrom" parameter. These should all be TextViews. The
- * first N views in this list are given the values of the first N
- * columns in the groupFrom parameter.
- * @param expandedGroupLayout resource identifier of a view layout that
- * defines the views for an expanded group. The layout file
- * should include at least those named views defined in "groupTo"
- * @param collapsedGroupLayout resource identifier of a view layout that
- * defines the views for a collapsed group. The layout file
- * should include at least those named views defined in "groupTo"
- * @param childData A List of List of Maps. Each entry in the outer List
- * corresponds to a group (index by group position), each entry
- * in the inner List corresponds to a child within the group
- * (index by child position), and the Map corresponds to the data
- * for a child (index by values in the childFrom array). The Map
- * contains the data for each child, and should include all the
- * entries specified in "childFrom"
- * @param childFrom A list of keys that will be fetched from the Map
- * associated with each child.
- * @param childTo The child views that should display column in the
- * "childFrom" parameter. These should all be TextViews. The
- * first N views in this list are given the values of the first N
- * columns in the childFrom parameter.
- * @param childLayout resource identifier of a view layout that defines the
- * views for a child. The layout file should include at least
- * those named views defined in "childTo"
- */
- public SimpleExpandableListAdapter(Context context,
- List<? extends Map<String, ?>> groupData, int expandedGroupLayout,
- int collapsedGroupLayout, String[] groupFrom, int[] groupTo,
- List<? extends List<? extends Map<String, ?>>> childData,
- int childLayout, String[] childFrom, int[] childTo) {
- this(context, groupData, expandedGroupLayout, collapsedGroupLayout,
- groupFrom, groupTo, childData, childLayout, childLayout,
- childFrom, childTo);
- }
-
- /**
- * Constructor
- *
- * @param context The context where the {@link ExpandableListView}
- * associated with this {@link SimpleExpandableListAdapter} is
- * running
- * @param groupData A List of Maps. Each entry in the List corresponds to
- * one group in the list. The Maps contain the data for each
- * group, and should include all the entries specified in
- * "groupFrom"
- * @param groupFrom A list of keys that will be fetched from the Map
- * associated with each group.
- * @param groupTo The group views that should display column in the
- * "groupFrom" parameter. These should all be TextViews. The
- * first N views in this list are given the values of the first N
- * columns in the groupFrom parameter.
- * @param expandedGroupLayout resource identifier of a view layout that
- * defines the views for an expanded group. The layout file
- * should include at least those named views defined in "groupTo"
- * @param collapsedGroupLayout resource identifier of a view layout that
- * defines the views for a collapsed group. The layout file
- * should include at least those named views defined in "groupTo"
- * @param childData A List of List of Maps. Each entry in the outer List
- * corresponds to a group (index by group position), each entry
- * in the inner List corresponds to a child within the group
- * (index by child position), and the Map corresponds to the data
- * for a child (index by values in the childFrom array). The Map
- * contains the data for each child, and should include all the
- * entries specified in "childFrom"
- * @param childFrom A list of keys that will be fetched from the Map
- * associated with each child.
- * @param childTo The child views that should display column in the
- * "childFrom" parameter. These should all be TextViews. The
- * first N views in this list are given the values of the first N
- * columns in the childFrom parameter.
- * @param childLayout resource identifier of a view layout that defines the
- * views for a child (unless it is the last child within a group,
- * in which case the lastChildLayout is used). The layout file
- * should include at least those named views defined in "childTo"
- * @param lastChildLayout resource identifier of a view layout that defines
- * the views for the last child within each group. The layout
- * file should include at least those named views defined in
- * "childTo"
- */
- public SimpleExpandableListAdapter(Context context,
- List<? extends Map<String, ?>> groupData, int expandedGroupLayout,
- int collapsedGroupLayout, String[] groupFrom, int[] groupTo,
- List<? extends List<? extends Map<String, ?>>> childData,
- int childLayout, int lastChildLayout, String[] childFrom,
- int[] childTo) {
- mGroupData = groupData;
- mExpandedGroupLayout = expandedGroupLayout;
- mCollapsedGroupLayout = collapsedGroupLayout;
- mGroupFrom = groupFrom;
- mGroupTo = groupTo;
-
- mChildData = childData;
- mChildLayout = childLayout;
- mLastChildLayout = lastChildLayout;
- mChildFrom = childFrom;
- mChildTo = childTo;
-
- mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
-
- public Object getChild(int groupPosition, int childPosition) {
- return mChildData.get(groupPosition).get(childPosition);
- }
-
- public long getChildId(int groupPosition, int childPosition) {
- return childPosition;
- }
-
- public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
- View convertView, ViewGroup parent) {
- View v;
- if (convertView == null) {
- v = newChildView(isLastChild, parent);
- } else {
- v = convertView;
- }
- bindView(v, mChildData.get(groupPosition).get(childPosition), mChildFrom, mChildTo);
- return v;
- }
-
- /**
- * Instantiates a new View for a child.
- * @param isLastChild Whether the child is the last child within its group.
- * @param parent The eventual parent of this new View.
- * @return A new child View
- */
- public View newChildView(boolean isLastChild, ViewGroup parent) {
- return mInflater.inflate((isLastChild) ? mLastChildLayout : mChildLayout, parent, false);
- }
-
- private void bindView(View view, Map<String, ?> data, String[] from, int[] to) {
- int len = to.length;
-
- for (int i = 0; i < len; i++) {
- TextView v = (TextView)view.findViewById(to[i]);
- if (v != null) {
- v.setText((String)data.get(from[i]));
- }
- }
- }
-
- public int getChildrenCount(int groupPosition) {
- return mChildData.get(groupPosition).size();
- }
-
- public Object getGroup(int groupPosition) {
- return mGroupData.get(groupPosition);
- }
-
- public int getGroupCount() {
- return mGroupData.size();
- }
-
- public long getGroupId(int groupPosition) {
- return groupPosition;
- }
-
- public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
- ViewGroup parent) {
- View v;
- if (convertView == null) {
- v = newGroupView(isExpanded, parent);
- } else {
- v = convertView;
- }
- bindView(v, mGroupData.get(groupPosition), mGroupFrom, mGroupTo);
- return v;
- }
-
- /**
- * Instantiates a new View for a group.
- * @param isExpanded Whether the group is currently expanded.
- * @param parent The eventual parent of this new View.
- * @return A new group View
- */
- public View newGroupView(boolean isExpanded, ViewGroup parent) {
- return mInflater.inflate((isExpanded) ? mExpandedGroupLayout : mCollapsedGroupLayout,
- parent, false);
- }
-
- public boolean isChildSelectable(int groupPosition, int childPosition) {
- return true;
- }
-
- public boolean hasStableIds() {
- return true;
- }
-
-}
diff --git a/core/java/android/widget/SlidingDrawer.java b/core/java/android/widget/SlidingDrawer.java
deleted file mode 100644
index e77c4ca..0000000
--- a/core/java/android/widget/SlidingDrawer.java
+++ /dev/null
@@ -1,938 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.view.ViewGroup;
-import android.view.View;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.SoundEffectConstants;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.Bitmap;
-import android.os.SystemClock;
-import android.os.Handler;
-import android.os.Message;
-import android.R;
-
-/**
- * SlidingDrawer hides content out of the screen and allows the user to drag a handle
- * to bring the content on screen. SlidingDrawer can be used vertically or horizontally.
- *
- * A special widget composed of two children views: the handle, that the users drags,
- * and the content, attached to the handle and dragged with it.
- *
- * SlidingDrawer should be used as an overlay inside layouts. This means SlidingDrawer
- * should only be used inside of a FrameLayout or a RelativeLayout for instance. The
- * size of the SlidingDrawer defines how much space the content will occupy once slid
- * out so SlidingDrawer should usually use fill_parent for both its dimensions.
- *
- * Inside an XML layout, SlidingDrawer must define the id of the handle and of the
- * content:
- *
- * <pre class="prettyprint">
- * &lt;SlidingDrawer
- * android:id="@+id/drawer"
- * android:layout_width="fill_parent"
- * android:layout_height="fill_parent"
- *
- * android:handle="@+id/handle"
- * android:content="@+id/content"&gt;
- *
- * &lt;ImageView
- * android:id="@id/handle"
- * android:layout_width="88dip"
- * android:layout_height="44dip" /&gt;
- *
- * &lt;GridView
- * android:id="@id/content"
- * android:layout_width="fill_parent"
- * android:layout_height="fill_parent" /&gt;
- *
- * &lt;/SlidingDrawer&gt;
- * </pre>
- *
- * @attr ref android.R.styleable#SlidingDrawer_content
- * @attr ref android.R.styleable#SlidingDrawer_handle
- * @attr ref android.R.styleable#SlidingDrawer_topOffset
- * @attr ref android.R.styleable#SlidingDrawer_bottomOffset
- * @attr ref android.R.styleable#SlidingDrawer_orientation
- * @attr ref android.R.styleable#SlidingDrawer_allowSingleTap
- * @attr ref android.R.styleable#SlidingDrawer_animateOnClick
- */
-public class SlidingDrawer extends ViewGroup {
- public static final int ORIENTATION_HORIZONTAL = 0;
- public static final int ORIENTATION_VERTICAL = 1;
-
- private static final int TAP_THRESHOLD = 6;
- private static final float MAXIMUM_TAP_VELOCITY = 100.0f;
- private static final float MAXIMUM_MINOR_VELOCITY = 150.0f;
- private static final float MAXIMUM_MAJOR_VELOCITY = 200.0f;
- private static final float MAXIMUM_ACCELERATION = 2000.0f;
- private static final int VELOCITY_UNITS = 1000;
- private static final int MSG_ANIMATE = 1000;
- private static final int ANIMATION_FRAME_DURATION = 1000 / 60;
-
- private static final int EXPANDED_FULL_OPEN = -10001;
- private static final int COLLAPSED_FULL_CLOSED = -10002;
-
- private final int mHandleId;
- private final int mContentId;
-
- private View mHandle;
- private View mContent;
-
- private final Rect mFrame = new Rect();
- private final Rect mInvalidate = new Rect();
- private boolean mTracking;
- private boolean mLocked;
-
- private VelocityTracker mVelocityTracker;
-
- private boolean mVertical;
- private boolean mExpanded;
- private int mBottomOffset;
- private int mTopOffset;
- private int mHandleHeight;
- private int mHandleWidth;
-
- private OnDrawerOpenListener mOnDrawerOpenListener;
- private OnDrawerCloseListener mOnDrawerCloseListener;
- private OnDrawerScrollListener mOnDrawerScrollListener;
-
- private final Handler mHandler = new SlidingHandler();
- private float mAnimatedAcceleration;
- private float mAnimatedVelocity;
- private float mAnimationPosition;
- private long mAnimationLastTime;
- private long mCurrentAnimationTime;
- private int mTouchDelta;
- private boolean mAnimating;
- private boolean mAllowSingleTap;
- private boolean mAnimateOnClick;
-
- private final int mTapThreshold;
- private final int mMaximumTapVelocity;
- private final int mMaximumMinorVelocity;
- private final int mMaximumMajorVelocity;
- private final int mMaximumAcceleration;
- private final int mVelocityUnits;
-
- /**
- * Callback invoked when the drawer is opened.
- */
- public static interface OnDrawerOpenListener {
- /**
- * Invoked when the drawer becomes fully open.
- */
- public void onDrawerOpened();
- }
-
- /**
- * Callback invoked when the drawer is closed.
- */
- public static interface OnDrawerCloseListener {
- /**
- * Invoked when the drawer becomes fully closed.
- */
- public void onDrawerClosed();
- }
-
- /**
- * Callback invoked when the drawer is scrolled.
- */
- public static interface OnDrawerScrollListener {
- /**
- * Invoked when the user starts dragging/flinging the drawer's handle.
- */
- public void onScrollStarted();
-
- /**
- * Invoked when the user stops dragging/flinging the drawer's handle.
- */
- public void onScrollEnded();
- }
-
- /**
- * Creates a new SlidingDrawer from a specified set of attributes defined in XML.
- *
- * @param context The application's environment.
- * @param attrs The attributes defined in XML.
- */
- public SlidingDrawer(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- /**
- * Creates a new SlidingDrawer from a specified set of attributes defined in XML.
- *
- * @param context The application's environment.
- * @param attrs The attributes defined in XML.
- * @param defStyle The style to apply to this widget.
- */
- public SlidingDrawer(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlidingDrawer, defStyle, 0);
-
- int orientation = a.getInt(R.styleable.SlidingDrawer_orientation, ORIENTATION_VERTICAL);
- mVertical = orientation == ORIENTATION_VERTICAL;
- mBottomOffset = (int) a.getDimension(R.styleable.SlidingDrawer_bottomOffset, 0.0f);
- mTopOffset = (int) a.getDimension(R.styleable.SlidingDrawer_topOffset, 0.0f);
- mAllowSingleTap = a.getBoolean(R.styleable.SlidingDrawer_allowSingleTap, true);
- mAnimateOnClick = a.getBoolean(R.styleable.SlidingDrawer_animateOnClick, true);
-
- int handleId = a.getResourceId(R.styleable.SlidingDrawer_handle, 0);
- if (handleId == 0) {
- throw new IllegalArgumentException("The handle attribute is required and must refer "
- + "to a valid child.");
- }
-
- int contentId = a.getResourceId(R.styleable.SlidingDrawer_content, 0);
- if (contentId == 0) {
- throw new IllegalArgumentException("The handle attribute is required and must refer "
- + "to a valid child.");
- }
-
- mHandleId = handleId;
- mContentId = contentId;
-
- final float density = getResources().getDisplayMetrics().density;
- mTapThreshold = (int) (TAP_THRESHOLD * density + 0.5f);
- mMaximumTapVelocity = (int) (MAXIMUM_TAP_VELOCITY * density + 0.5f);
- mMaximumMinorVelocity = (int) (MAXIMUM_MINOR_VELOCITY * density + 0.5f);
- mMaximumMajorVelocity = (int) (MAXIMUM_MAJOR_VELOCITY * density + 0.5f);
- mMaximumAcceleration = (int) (MAXIMUM_ACCELERATION * density + 0.5f);
- mVelocityUnits = (int) (VELOCITY_UNITS * density + 0.5f);
-
- a.recycle();
-
- setAlwaysDrawnWithCacheEnabled(false);
- }
-
- @Override
- protected void onFinishInflate() {
- mHandle = findViewById(mHandleId);
- if (mHandle == null) {
- throw new IllegalArgumentException("The handle attribute is must refer to an"
- + " existing child.");
- }
- mHandle.setOnClickListener(new DrawerToggler());
-
- mContent = findViewById(mContentId);
- if (mContent == null) {
- throw new IllegalArgumentException("The content attribute is must refer to an"
- + " existing child.");
- }
- mContent.setVisibility(View.GONE);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
- int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
-
- int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
- int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
-
- if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) {
- throw new RuntimeException("SlidingDrawer cannot have UNSPECIFIED dimensions");
- }
-
- final View handle = mHandle;
- measureChild(handle, widthMeasureSpec, heightMeasureSpec);
-
- if (mVertical) {
- int height = heightSpecSize - handle.getMeasuredHeight() - mTopOffset;
- mContent.measure(MeasureSpec.makeMeasureSpec(widthSpecSize, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
- } else {
- int width = widthSpecSize - handle.getMeasuredWidth() - mTopOffset;
- mContent.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(heightSpecSize, MeasureSpec.EXACTLY));
- }
-
- setMeasuredDimension(widthSpecSize, heightSpecSize);
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- final long drawingTime = getDrawingTime();
- final View handle = mHandle;
- final boolean isVertical = mVertical;
-
- drawChild(canvas, handle, drawingTime);
-
- if (mTracking || mAnimating) {
- final Bitmap cache = mContent.getDrawingCache();
- if (cache != null) {
- if (isVertical) {
- canvas.drawBitmap(cache, 0, handle.getBottom(), null);
- } else {
- canvas.drawBitmap(cache, handle.getRight(), 0, null);
- }
- } else {
- canvas.save();
- canvas.translate(isVertical ? 0 : handle.getLeft() - mTopOffset,
- isVertical ? handle.getTop() - mTopOffset : 0);
- drawChild(canvas, mContent, drawingTime);
- canvas.restore();
- }
- } else if (mExpanded) {
- drawChild(canvas, mContent, drawingTime);
- }
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- if (mTracking) {
- return;
- }
-
- final int width = r - l;
- final int height = b - t;
-
- final View handle = mHandle;
-
- int childWidth = handle.getMeasuredWidth();
- int childHeight = handle.getMeasuredHeight();
-
- int childLeft;
- int childTop;
-
- final View content = mContent;
-
- if (mVertical) {
- childLeft = (width - childWidth) / 2;
- childTop = mExpanded ? mTopOffset : height - childHeight + mBottomOffset;
-
- content.layout(0, mTopOffset + childHeight, content.getMeasuredWidth(),
- mTopOffset + childHeight + content.getMeasuredHeight());
- } else {
- childLeft = mExpanded ? mTopOffset : width - childWidth + mBottomOffset;
- childTop = (height - childHeight) / 2;
-
- content.layout(mTopOffset + childWidth, 0,
- mTopOffset + childWidth + content.getMeasuredWidth(),
- content.getMeasuredHeight());
- }
-
- handle.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
- mHandleHeight = handle.getHeight();
- mHandleWidth = handle.getWidth();
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent event) {
- if (mLocked) {
- return false;
- }
-
- final int action = event.getAction();
-
- float x = event.getX();
- float y = event.getY();
-
- final Rect frame = mFrame;
- final View handle = mHandle;
-
- handle.getHitRect(frame);
- if (!mTracking && !frame.contains((int) x, (int) y)) {
- return false;
- }
-
- if (action == MotionEvent.ACTION_DOWN) {
- if (mOnDrawerScrollListener != null) {
- mOnDrawerScrollListener.onScrollStarted();
- }
- mTracking = true;
-
- handle.setPressed(true);
- // Must be called before prepareTracking()
- prepareContent();
-
- if (mVertical) {
- final int top = mHandle.getTop();
- mTouchDelta = (int) y - top;
- prepareTracking(top);
- } else {
- final int left = mHandle.getLeft();
- mTouchDelta = (int) x - left;
- prepareTracking(left);
- }
- mVelocityTracker.addMovement(event);
- }
-
- return true;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (mLocked) {
- return true;
- }
-
- if (mTracking) {
- mVelocityTracker.addMovement(event);
- final int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_MOVE:
- moveHandle((int) (mVertical ? event.getY() : event.getX()) - mTouchDelta);
- break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL: {
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(mVelocityUnits);
-
- float yVelocity = velocityTracker.getYVelocity();
- float xVelocity = velocityTracker.getXVelocity();
- boolean negative;
-
- final boolean vertical = mVertical;
- if (vertical) {
- negative = yVelocity < 0;
- if (xVelocity < 0) {
- xVelocity = -xVelocity;
- }
- if (xVelocity > mMaximumMinorVelocity) {
- xVelocity = mMaximumMinorVelocity;
- }
- } else {
- negative = xVelocity < 0;
- if (yVelocity < 0) {
- yVelocity = -yVelocity;
- }
- if (yVelocity > mMaximumMinorVelocity) {
- yVelocity = mMaximumMinorVelocity;
- }
- }
-
- float velocity = (float) Math.hypot(xVelocity, yVelocity);
- if (negative) {
- velocity = -velocity;
- }
-
- final int top = mHandle.getTop();
- final int left = mHandle.getLeft();
-
- if (Math.abs(velocity) < mMaximumTapVelocity) {
- if (vertical ? (mExpanded && top < mTapThreshold + mTopOffset) ||
- (!mExpanded && top > mBottomOffset + mBottom - mTop -
- mHandleHeight - mTapThreshold) :
- (mExpanded && left < mTapThreshold + mTopOffset) ||
- (!mExpanded && left > mBottomOffset + mRight - mLeft -
- mHandleWidth - mTapThreshold)) {
-
- if (mAllowSingleTap) {
- playSoundEffect(SoundEffectConstants.CLICK);
-
- if (mExpanded) {
- animateClose(vertical ? top : left);
- } else {
- animateOpen(vertical ? top : left);
- }
- }
-
- } else {
- performFling(vertical ? top : left, velocity, false);
- }
- } else {
- performFling(vertical ? top : left, velocity, false);
- }
- }
- break;
- }
- }
-
- return mTracking || mAnimating || super.onTouchEvent(event);
- }
-
- private void animateClose(int position) {
- prepareTracking(position);
- performFling(position, mMaximumAcceleration, true);
- }
-
- private void animateOpen(int position) {
- prepareTracking(position);
- performFling(position, -mMaximumAcceleration, true);
- }
-
- private void performFling(int position, float velocity, boolean always) {
- mAnimationPosition = position;
- mAnimatedVelocity = velocity;
-
- if (mExpanded) {
- if (always || (velocity > mMaximumMajorVelocity ||
- (position > mTopOffset + (mVertical ? mHandleHeight : mHandleWidth) &&
- velocity > -mMaximumMajorVelocity))) {
- // We are expanded, but they didn't move sufficiently to cause
- // us to retract. Animate back to the expanded position.
- mAnimatedAcceleration = mMaximumAcceleration;
- if (velocity < 0) {
- mAnimatedVelocity = 0;
- }
- } else {
- // We are expanded and are now going to animate away.
- mAnimatedAcceleration = -mMaximumAcceleration;
- if (velocity > 0) {
- mAnimatedVelocity = 0;
- }
- }
- } else {
- if (!always && (velocity > mMaximumMajorVelocity ||
- (position > (mVertical ? getHeight() : getWidth()) / 2 &&
- velocity > -mMaximumMajorVelocity))) {
- // We are collapsed, and they moved enough to allow us to expand.
- mAnimatedAcceleration = mMaximumAcceleration;
- if (velocity < 0) {
- mAnimatedVelocity = 0;
- }
- } else {
- // We are collapsed, but they didn't move sufficiently to cause
- // us to retract. Animate back to the collapsed position.
- mAnimatedAcceleration = -mMaximumAcceleration;
- if (velocity > 0) {
- mAnimatedVelocity = 0;
- }
- }
- }
-
- long now = SystemClock.uptimeMillis();
- mAnimationLastTime = now;
- mCurrentAnimationTime = now + ANIMATION_FRAME_DURATION;
- mAnimating = true;
- mHandler.removeMessages(MSG_ANIMATE);
- mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE), mCurrentAnimationTime);
- stopTracking();
- }
-
- private void prepareTracking(int position) {
- mTracking = true;
- mVelocityTracker = VelocityTracker.obtain();
- boolean opening = !mExpanded;
- if (opening) {
- mAnimatedAcceleration = mMaximumAcceleration;
- mAnimatedVelocity = mMaximumMajorVelocity;
- mAnimationPosition = mBottomOffset +
- (mVertical ? getHeight() - mHandleHeight : getWidth() - mHandleWidth);
- moveHandle((int) mAnimationPosition);
- mAnimating = true;
- mHandler.removeMessages(MSG_ANIMATE);
- long now = SystemClock.uptimeMillis();
- mAnimationLastTime = now;
- mCurrentAnimationTime = now + ANIMATION_FRAME_DURATION;
- mAnimating = true;
- } else {
- if (mAnimating) {
- mAnimating = false;
- mHandler.removeMessages(MSG_ANIMATE);
- }
- moveHandle(position);
- }
- }
-
- private void moveHandle(int position) {
- final View handle = mHandle;
-
- if (mVertical) {
- if (position == EXPANDED_FULL_OPEN) {
- handle.offsetTopAndBottom(mTopOffset - handle.getTop());
- invalidate();
- } else if (position == COLLAPSED_FULL_CLOSED) {
- handle.offsetTopAndBottom(mBottomOffset + mBottom - mTop -
- mHandleHeight - handle.getTop());
- invalidate();
- } else {
- final int top = handle.getTop();
- int deltaY = position - top;
- if (position < mTopOffset) {
- deltaY = mTopOffset - top;
- } else if (deltaY > mBottomOffset + mBottom - mTop - mHandleHeight - top) {
- deltaY = mBottomOffset + mBottom - mTop - mHandleHeight - top;
- }
- handle.offsetTopAndBottom(deltaY);
-
- final Rect frame = mFrame;
- final Rect region = mInvalidate;
-
- handle.getHitRect(frame);
- region.set(frame);
-
- region.union(frame.left, frame.top - deltaY, frame.right, frame.bottom - deltaY);
- region.union(0, frame.bottom - deltaY, getWidth(),
- frame.bottom - deltaY + mContent.getHeight());
-
- invalidate(region);
- }
- } else {
- if (position == EXPANDED_FULL_OPEN) {
- handle.offsetLeftAndRight(mTopOffset - handle.getLeft());
- invalidate();
- } else if (position == COLLAPSED_FULL_CLOSED) {
- handle.offsetLeftAndRight(mBottomOffset + mRight - mLeft -
- mHandleWidth - handle.getLeft());
- invalidate();
- } else {
- final int left = handle.getLeft();
- int deltaX = position - left;
- if (position < mTopOffset) {
- deltaX = mTopOffset - left;
- } else if (deltaX > mBottomOffset + mRight - mLeft - mHandleWidth - left) {
- deltaX = mBottomOffset + mRight - mLeft - mHandleWidth - left;
- }
- handle.offsetLeftAndRight(deltaX);
-
- final Rect frame = mFrame;
- final Rect region = mInvalidate;
-
- handle.getHitRect(frame);
- region.set(frame);
-
- region.union(frame.left - deltaX, frame.top, frame.right - deltaX, frame.bottom);
- region.union(frame.right - deltaX, 0,
- frame.right - deltaX + mContent.getWidth(), getHeight());
-
- invalidate(region);
- }
- }
- }
-
- private void prepareContent() {
- if (mAnimating) {
- return;
- }
-
- // Something changed in the content, we need to honor the layout request
- // before creating the cached bitmap
- final View content = mContent;
- if (content.isLayoutRequested()) {
- if (mVertical) {
- final int childHeight = mHandleHeight;
- int height = mBottom - mTop - childHeight - mTopOffset;
- content.measure(MeasureSpec.makeMeasureSpec(mRight - mLeft, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
- content.layout(0, mTopOffset + childHeight, content.getMeasuredWidth(),
- mTopOffset + childHeight + content.getMeasuredHeight());
- } else {
- final int childWidth = mHandle.getWidth();
- int width = mRight - mLeft - childWidth - mTopOffset;
- content.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(mBottom - mTop, MeasureSpec.EXACTLY));
- content.layout(childWidth + mTopOffset, 0,
- mTopOffset + childWidth + content.getMeasuredWidth(),
- content.getMeasuredHeight());
- }
- }
- // Try only once... we should really loop but it's not a big deal
- // if the draw was cancelled, it will only be temporary anyway
- content.getViewTreeObserver().dispatchOnPreDraw();
- content.buildDrawingCache();
-
- content.setVisibility(View.GONE);
- }
-
- private void stopTracking() {
- mHandle.setPressed(false);
- mTracking = false;
-
- if (mOnDrawerScrollListener != null) {
- mOnDrawerScrollListener.onScrollEnded();
- }
-
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- }
-
- private void doAnimation() {
- if (mAnimating) {
- incrementAnimation();
- if (mAnimationPosition >= mBottomOffset + (mVertical ? getHeight() : getWidth()) - 1) {
- mAnimating = false;
- closeDrawer();
- } else if (mAnimationPosition < mTopOffset) {
- mAnimating = false;
- openDrawer();
- } else {
- moveHandle((int) mAnimationPosition);
- mCurrentAnimationTime += ANIMATION_FRAME_DURATION;
- mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE),
- mCurrentAnimationTime);
- }
- }
- }
-
- private void incrementAnimation() {
- long now = SystemClock.uptimeMillis();
- float t = (now - mAnimationLastTime) / 1000.0f; // ms -> s
- final float position = mAnimationPosition;
- final float v = mAnimatedVelocity; // px/s
- final float a = mAnimatedAcceleration; // px/s/s
- mAnimationPosition = position + (v * t) + (0.5f * a * t * t); // px
- mAnimatedVelocity = v + (a * t); // px/s
- mAnimationLastTime = now; // ms
- }
-
- /**
- * Toggles the drawer open and close. Takes effect immediately.
- *
- * @see #open()
- * @see #close()
- * @see #animateClose()
- * @see #animateOpen()
- * @see #animateToggle()
- */
- public void toggle() {
- if (!mExpanded) {
- openDrawer();
- } else {
- closeDrawer();
- }
- invalidate();
- requestLayout();
- }
-
- /**
- * Toggles the drawer open and close with an animation.
- *
- * @see #open()
- * @see #close()
- * @see #animateClose()
- * @see #animateOpen()
- * @see #toggle()
- */
- public void animateToggle() {
- if (!mExpanded) {
- animateOpen();
- } else {
- animateClose();
- }
- }
-
- /**
- * Opens the drawer immediately.
- *
- * @see #toggle()
- * @see #close()
- * @see #animateOpen()
- */
- public void open() {
- openDrawer();
- invalidate();
- requestLayout();
- }
-
- /**
- * Closes the drawer immediately.
- *
- * @see #toggle()
- * @see #open()
- * @see #animateClose()
- */
- public void close() {
- closeDrawer();
- invalidate();
- requestLayout();
- }
-
- /**
- * Closes the drawer with an animation.
- *
- * @see #close()
- * @see #open()
- * @see #animateOpen()
- * @see #animateToggle()
- * @see #toggle()
- */
- public void animateClose() {
- final OnDrawerScrollListener scrollListener = mOnDrawerScrollListener;
- if (scrollListener != null) {
- scrollListener.onScrollStarted();
- }
- prepareContent();
- animateClose(mVertical ? mHandle.getTop() : mHandle.getLeft());
- if (scrollListener != null) {
- scrollListener.onScrollEnded();
- }
- }
-
- /**
- * Opens the drawer with an animation.
- *
- * @see #close()
- * @see #open()
- * @see #animateClose()
- * @see #animateToggle()
- * @see #toggle()
- */
- public void animateOpen() {
- final OnDrawerScrollListener scrollListener = mOnDrawerScrollListener;
- if (scrollListener != null) {
- scrollListener.onScrollStarted();
- }
- prepareContent();
- animateOpen(mVertical ? mHandle.getTop() : mHandle.getLeft());
- if (scrollListener != null) {
- scrollListener.onScrollEnded();
- }
- }
-
- private void closeDrawer() {
- moveHandle(COLLAPSED_FULL_CLOSED);
- mContent.setVisibility(View.GONE);
- mContent.destroyDrawingCache();
-
- if (!mExpanded) {
- return;
- }
-
- mExpanded = false;
- if (mOnDrawerCloseListener != null) {
- mOnDrawerCloseListener.onDrawerClosed();
- }
- }
-
- private void openDrawer() {
- moveHandle(EXPANDED_FULL_OPEN);
- mContent.setVisibility(View.VISIBLE);
-
- if (mExpanded) {
- return;
- }
-
- mExpanded = true;
- if (mOnDrawerOpenListener != null) {
- mOnDrawerOpenListener.onDrawerOpened();
- }
- }
-
- /**
- * Sets the listener that receives a notification when the drawer becomes open.
- *
- * @param onDrawerOpenListener The listener to be notified when the drawer is opened.
- */
- public void setOnDrawerOpenListener(OnDrawerOpenListener onDrawerOpenListener) {
- mOnDrawerOpenListener = onDrawerOpenListener;
- }
-
- /**
- * Sets the listener that receives a notification when the drawer becomes close.
- *
- * @param onDrawerCloseListener The listener to be notified when the drawer is closed.
- */
- public void setOnDrawerCloseListener(OnDrawerCloseListener onDrawerCloseListener) {
- mOnDrawerCloseListener = onDrawerCloseListener;
- }
-
- /**
- * Sets the listener that receives a notification when the drawer starts or ends
- * a scroll. A fling is considered as a scroll. A fling will also trigger a
- * drawer opened or drawer closed event.
- *
- * @param onDrawerScrollListener The listener to be notified when scrolling
- * starts or stops.
- */
- public void setOnDrawerScrollListener(OnDrawerScrollListener onDrawerScrollListener) {
- mOnDrawerScrollListener = onDrawerScrollListener;
- }
-
- /**
- * Returns the handle of the drawer.
- *
- * @return The View reprenseting the handle of the drawer, identified by
- * the "handle" id in XML.
- */
- public View getHandle() {
- return mHandle;
- }
-
- /**
- * Returns the content of the drawer.
- *
- * @return The View reprenseting the content of the drawer, identified by
- * the "content" id in XML.
- */
- public View getContent() {
- return mContent;
- }
-
- /**
- * Unlocks the SlidingDrawer so that touch events are processed.
- *
- * @see #lock()
- */
- public void unlock() {
- mLocked = false;
- }
-
- /**
- * Locks the SlidingDrawer so that touch events are ignores.
- *
- * @see #unlock()
- */
- public void lock() {
- mLocked = true;
- }
-
- /**
- * Indicates whether the drawer is currently fully opened.
- *
- * @return True if the drawer is opened, false otherwise.
- */
- public boolean isOpened() {
- return mExpanded;
- }
-
- /**
- * Indicates whether the drawer is scrolling or flinging.
- *
- * @return True if the drawer is scroller or flinging, false otherwise.
- */
- public boolean isMoving() {
- return mTracking || mAnimating;
- }
-
- private class DrawerToggler implements OnClickListener {
- public void onClick(View v) {
- if (mLocked) {
- return;
- }
- // mAllowSingleTap isn't relevant here; you're *always*
- // allowed to open/close the drawer by clicking with the
- // trackball.
-
- if (mAnimateOnClick) {
- animateToggle();
- } else {
- toggle();
- }
- }
- }
-
- private class SlidingHandler extends Handler {
- public void handleMessage(Message m) {
- switch (m.what) {
- case MSG_ANIMATE:
- doAnimation();
- break;
- }
- }
- }
-}
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
deleted file mode 100644
index 80d688e..0000000
--- a/core/java/android/widget/Spinner.java
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.annotation.Widget;
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.content.res.TypedArray;
-import android.database.DataSetObserver;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewGroup;
-
-
-/**
- * A view that displays one child at a time and lets the user pick among them.
- * The items in the Spinner come from the {@link Adapter} associated with
- * this view.
- *
- * @attr ref android.R.styleable#Spinner_prompt
- */
-@Widget
-public class Spinner extends AbsSpinner implements OnClickListener {
-
- private CharSequence mPrompt;
-
- public Spinner(Context context) {
- this(context, null);
- }
-
- public Spinner(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.spinnerStyle);
- }
-
- public Spinner(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.Spinner, defStyle, 0);
-
- mPrompt = a.getString(com.android.internal.R.styleable.Spinner_prompt);
-
- a.recycle();
- }
-
- @Override
- public int getBaseline() {
- View child = null;
-
- if (getChildCount() > 0) {
- child = getChildAt(0);
- } else if (mAdapter != null && mAdapter.getCount() > 0) {
- child = makeAndAddView(0);
- // TODO: We should probably put the child in the recycler
- }
-
- if (child != null) {
- return child.getTop() + child.getBaseline();
- } else {
- return -1;
- }
- }
-
- /**
- * <p>A spinner does not support item click events. Calling this method
- * will raise an exception.</p>
- *
- * @param l this listener will be ignored
- */
- @Override
- public void setOnItemClickListener(OnItemClickListener l) {
- throw new RuntimeException("setOnItemClickListener cannot be used with a spinner.");
- }
-
- /**
- * @see android.view.View#onLayout(boolean,int,int,int,int)
- *
- * Creates and positions all views
- *
- */
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
- mInLayout = true;
- layout(0, false);
- mInLayout = false;
- }
-
- /**
- * Creates and positions all views for this Spinner.
- *
- * @param delta Change in the selected position. +1 moves selection is moving to the right,
- * so views are scrolling to the left. -1 means selection is moving to the left.
- */
- @Override
- void layout(int delta, boolean animate) {
- int childrenLeft = mSpinnerPadding.left;
- int childrenWidth = mRight - mLeft - mSpinnerPadding.left - mSpinnerPadding.right;
-
- if (mDataChanged) {
- handleDataChanged();
- }
-
- // Handle the empty set by removing all views
- if (mItemCount == 0) {
- resetList();
- return;
- }
-
- if (mNextSelectedPosition >= 0) {
- setSelectedPositionInt(mNextSelectedPosition);
- }
-
- recycleAllViews();
-
- // Clear out old views
- removeAllViewsInLayout();
-
- // Make selected view and center it
- mFirstPosition = mSelectedPosition;
- View sel = makeAndAddView(mSelectedPosition);
- int width = sel.getMeasuredWidth();
- int selectedOffset = childrenLeft + (childrenWidth / 2) - (width / 2);
- sel.offsetLeftAndRight(selectedOffset);
-
- // Flush any cached views that did not get reused above
- mRecycler.clear();
-
- invalidate();
-
- checkSelectionChanged();
-
- mDataChanged = false;
- mNeedSync = false;
- setNextSelectedPositionInt(mSelectedPosition);
- }
-
- /**
- * Obtain a view, either by pulling an existing view from the recycler or
- * by getting a new one from the adapter. If we are animating, make sure
- * there is enough information in the view's layout parameters to animate
- * from the old to new positions.
- *
- * @param position Position in the spinner for the view to obtain
- * @return A view that has been added to the spinner
- */
- private View makeAndAddView(int position) {
-
- View child;
-
- if (!mDataChanged) {
- child = mRecycler.get(position);
- if (child != null) {
- // Position the view
- setUpChild(child);
-
- return child;
- }
- }
-
- // Nothing found in the recycler -- ask the adapter for a view
- child = mAdapter.getView(position, null, this);
-
- // Position the view
- setUpChild(child);
-
- return child;
- }
-
-
-
- /**
- * Helper for makeAndAddView to set the position of a view
- * and fill out its layout paramters.
- *
- * @param child The view to position
- */
- private void setUpChild(View child) {
-
- // Respect layout params that are already in the view. Otherwise
- // make some up...
- ViewGroup.LayoutParams lp = child.getLayoutParams();
- if (lp == null) {
- lp = generateDefaultLayoutParams();
- }
-
- addViewInLayout(child, 0, lp);
-
- child.setSelected(hasFocus());
-
- // Get measure specs
- int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec,
- mSpinnerPadding.top + mSpinnerPadding.bottom, lp.height);
- int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec,
- mSpinnerPadding.left + mSpinnerPadding.right, lp.width);
-
- // Measure child
- child.measure(childWidthSpec, childHeightSpec);
-
- int childLeft;
- int childRight;
-
- // Position vertically based on gravity setting
- int childTop = mSpinnerPadding.top
- + ((mMeasuredHeight - mSpinnerPadding.bottom -
- mSpinnerPadding.top - child.getMeasuredHeight()) / 2);
- int childBottom = childTop + child.getMeasuredHeight();
-
- int width = child.getMeasuredWidth();
- childLeft = 0;
- childRight = childLeft + width;
-
- child.layout(childLeft, childTop, childRight, childBottom);
- }
-
- @Override
- public boolean performClick() {
- boolean handled = super.performClick();
-
- if (!handled) {
- handled = true;
- Context context = getContext();
-
- final DropDownAdapter adapter = new DropDownAdapter(getAdapter());
-
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- if (mPrompt != null) {
- builder.setTitle(mPrompt);
- }
- builder.setSingleChoiceItems(adapter, getSelectedItemPosition(), this).show();
- }
-
- return handled;
- }
-
- public void onClick(DialogInterface dialog, int which) {
- setSelection(which);
- dialog.dismiss();
- }
-
- /**
- * Sets the prompt to display when the dialog is shown.
- * @param prompt the prompt to set
- */
- public void setPrompt(CharSequence prompt) {
- mPrompt = prompt;
- }
-
- /**
- * Sets the prompt to display when the dialog is shown.
- * @param promptId the resource ID of the prompt to display when the dialog is shown
- */
- public void setPromptId(int promptId) {
- mPrompt = getContext().getText(promptId);
- }
-
- /**
- * @return The prompt to display when the dialog is shown
- */
- public CharSequence getPrompt() {
- return mPrompt;
- }
-
- /**
- * <p>Wrapper class for an Adapter. Transforms the embedded Adapter instance
- * into a ListAdapter.</p>
- */
- private static class DropDownAdapter implements ListAdapter, SpinnerAdapter {
- private SpinnerAdapter mAdapter;
-
- /**
- * <p>Creates a new ListAddapter wrapper for the specified adapter.</p>
- *
- * @param adapter the Adapter to transform into a ListAdapter
- */
- public DropDownAdapter(SpinnerAdapter adapter) {
- this.mAdapter = adapter;
- }
-
- public int getCount() {
- return mAdapter == null ? 0 : mAdapter.getCount();
- }
-
- public Object getItem(int position) {
- return mAdapter == null ? null : mAdapter.getItem(position);
- }
-
- public long getItemId(int position) {
- return mAdapter == null ? -1 : mAdapter.getItemId(position);
- }
-
- public View getView(int position, View convertView, ViewGroup parent) {
- return getDropDownView(position, convertView, parent);
- }
-
- public View getDropDownView(int position, View convertView, ViewGroup parent) {
- return mAdapter == null ? null :
- mAdapter.getDropDownView(position, convertView, parent);
- }
-
- public boolean hasStableIds() {
- return mAdapter != null && mAdapter.hasStableIds();
- }
-
- public void registerDataSetObserver(DataSetObserver observer) {
- if (mAdapter != null) {
- mAdapter.registerDataSetObserver(observer);
- }
- }
-
- public void unregisterDataSetObserver(DataSetObserver observer) {
- if (mAdapter != null) {
- mAdapter.unregisterDataSetObserver(observer);
- }
- }
-
- /**
- * <p>Always returns false.</p>
- *
- * @return false
- */
- public boolean areAllItemsEnabled() {
- return true;
- }
-
- /**
- * <p>Always returns false.</p>
- *
- * @return false
- */
- public boolean isEnabled(int position) {
- return true;
- }
-
- public int getItemViewType(int position) {
- return 0;
- }
-
- public int getViewTypeCount() {
- return 1;
- }
-
- public boolean isEmpty() {
- return getCount() == 0;
- }
- }
-}
diff --git a/core/java/android/widget/SpinnerAdapter.java b/core/java/android/widget/SpinnerAdapter.java
deleted file mode 100644
index 91504cf..0000000
--- a/core/java/android/widget/SpinnerAdapter.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * Extended {@link Adapter} that is the bridge between a
- * {@link android.widget.Spinner} and its data. A spinner adapter allows to
- * define two different views: one that shows the data in the spinner itself and
- * one that shows the data in the drop down list when the spinner is pressed.</p>
- */
-public interface SpinnerAdapter extends Adapter {
- /**
- * <p>Get a {@link android.view.View} that displays in the drop down popup
- * the data at the specified position in the data set.</p>
- *
- * @param position index of the item whose view we want.
- * @param convertView the old view to reuse, if possible. Note: You should
- * check that this view is non-null and of an appropriate type before
- * using. If it is not possible to convert this view to display the
- * correct data, this method can create a new view.
- * @param parent the parent that this view will eventually be attached to
- * @return a {@link android.view.View} corresponding to the data at the
- * specified position.
- */
- public View getDropDownView(int position, View convertView, ViewGroup parent);
-}
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
deleted file mode 100644
index dc2c70d..0000000
--- a/core/java/android/widget/TabHost.java
+++ /dev/null
@@ -1,632 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.app.LocalActivityManager;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.SoundEffectConstants;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.view.Window;
-import com.android.internal.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Container for a tabbed window view. This object holds two children: a set of tab labels that the
- * user clicks to select a specific tab, and a FrameLayout object that displays the contents of that
- * page. The individual elements are typically controlled using this container object, rather than
- * setting values on the child elements themselves.
- */
-public class TabHost extends FrameLayout implements ViewTreeObserver.OnTouchModeChangeListener {
-
- private TabWidget mTabWidget;
- private FrameLayout mTabContent;
- private List<TabSpec> mTabSpecs = new ArrayList<TabSpec>(2);
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected int mCurrentTab = -1;
- private View mCurrentView = null;
- /**
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected LocalActivityManager mLocalActivityManager = null;
- private OnTabChangeListener mOnTabChangeListener;
- private OnKeyListener mTabKeyListener;
-
- public TabHost(Context context) {
- super(context);
- initTabHost();
- }
-
- public TabHost(Context context, AttributeSet attrs) {
- super(context, attrs);
- initTabHost();
- }
-
- private final void initTabHost() {
- setFocusableInTouchMode(true);
- setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
-
- mCurrentTab = -1;
- mCurrentView = null;
- }
-
- /**
- * Get a new {@link TabSpec} associated with this tab host.
- * @param tag required tag of tab.
- */
- public TabSpec newTabSpec(String tag) {
- return new TabSpec(tag);
- }
-
-
-
- /**
- * <p>Call setup() before adding tabs if loading TabHost using findViewById(). <i><b>However</i></b>: You do
- * not need to call setup() after getTabHost() in {@link android.app.TabActivity TabActivity}.
- * Example:</p>
-<pre>mTabHost = (TabHost)findViewById(R.id.tabhost);
-mTabHost.setup();
-mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
- */
- public void setup() {
- mTabWidget = (TabWidget) findViewById(com.android.internal.R.id.tabs);
- if (mTabWidget == null) {
- throw new RuntimeException(
- "Your TabHost must have a TabWidget whose id attribute is 'android.R.id.tabs'");
- }
-
- // KeyListener to attach to all tabs. Detects non-navigation keys
- // and relays them to the tab content.
- mTabKeyListener = new OnKeyListener() {
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- case KeyEvent.KEYCODE_ENTER:
- return false;
-
- }
- mTabContent.requestFocus(View.FOCUS_FORWARD);
- return mTabContent.dispatchKeyEvent(event);
- }
-
- };
-
- mTabWidget.setTabSelectionListener(new TabWidget.OnTabSelectionChanged() {
- public void onTabSelectionChanged(int tabIndex, boolean clicked) {
- setCurrentTab(tabIndex);
- if (clicked) {
- mTabContent.requestFocus(View.FOCUS_FORWARD);
- }
- }
- });
-
- mTabContent = (FrameLayout) findViewById(com.android.internal.R.id.tabcontent);
- if (mTabContent == null) {
- throw new RuntimeException(
- "Your TabHost must have a FrameLayout whose id attribute is 'android.R.id.tabcontent'");
- }
- }
-
- /**
- * If you are using {@link TabSpec#setContent(android.content.Intent)}, this
- * must be called since the activityGroup is needed to launch the local activity.
- *
- * This is done for you if you extend {@link android.app.TabActivity}.
- * @param activityGroup Used to launch activities for tab content.
- */
- public void setup(LocalActivityManager activityGroup) {
- setup();
- mLocalActivityManager = activityGroup;
- }
-
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- final ViewTreeObserver treeObserver = getViewTreeObserver();
- if (treeObserver != null) {
- treeObserver.addOnTouchModeChangeListener(this);
- }
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- final ViewTreeObserver treeObserver = getViewTreeObserver();
- if (treeObserver != null) {
- treeObserver.removeOnTouchModeChangeListener(this);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void onTouchModeChanged(boolean isInTouchMode) {
- if (!isInTouchMode) {
- // leaving touch mode.. if nothing has focus, let's give it to
- // the indicator of the current tab
- if (!mCurrentView.hasFocus() || mCurrentView.isFocused()) {
- mTabWidget.getChildAt(mCurrentTab).requestFocus();
- }
- }
- }
-
- /**
- * Add a tab.
- * @param tabSpec Specifies how to create the indicator and content.
- */
- public void addTab(TabSpec tabSpec) {
-
- if (tabSpec.mIndicatorStrategy == null) {
- throw new IllegalArgumentException("you must specify a way to create the tab indicator.");
- }
-
- if (tabSpec.mContentStrategy == null) {
- throw new IllegalArgumentException("you must specify a way to create the tab content");
- }
- View tabIndicator = tabSpec.mIndicatorStrategy.createIndicatorView();
- tabIndicator.setOnKeyListener(mTabKeyListener);
- mTabWidget.addView(tabIndicator);
- mTabSpecs.add(tabSpec);
-
- if (mCurrentTab == -1) {
- setCurrentTab(0);
- }
- }
-
-
- /**
- * Removes all tabs from the tab widget associated with this tab host.
- */
- public void clearAllTabs() {
- mTabWidget.removeAllViews();
- initTabHost();
- mTabContent.removeAllViews();
- mTabSpecs.clear();
- requestLayout();
- invalidate();
- }
-
- public TabWidget getTabWidget() {
- return mTabWidget;
- }
-
- public int getCurrentTab() {
- return mCurrentTab;
- }
-
- public String getCurrentTabTag() {
- if (mCurrentTab >= 0 && mCurrentTab < mTabSpecs.size()) {
- return mTabSpecs.get(mCurrentTab).getTag();
- }
- return null;
- }
-
- public View getCurrentTabView() {
- if (mCurrentTab >= 0 && mCurrentTab < mTabSpecs.size()) {
- return mTabWidget.getChildAt(mCurrentTab);
- }
- return null;
- }
-
- public View getCurrentView() {
- return mCurrentView;
- }
-
- public void setCurrentTabByTag(String tag) {
- int i;
- for (i = 0; i < mTabSpecs.size(); i++) {
- if (mTabSpecs.get(i).getTag().equals(tag)) {
- setCurrentTab(i);
- break;
- }
- }
- }
-
- /**
- * Get the FrameLayout which holds tab content
- */
- public FrameLayout getTabContentView() {
- return mTabContent;
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- final boolean handled = super.dispatchKeyEvent(event);
-
- // unhandled key ups change focus to tab indicator for embedded activities
- // when there is nothing that will take focus from default focus searching
- if (!handled
- && (event.getAction() == KeyEvent.ACTION_DOWN)
- && (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP)
- && (mCurrentView.isRootNamespace())
- && (mCurrentView.hasFocus())
- && (mCurrentView.findFocus().focusSearch(View.FOCUS_UP) == null)) {
- mTabWidget.getChildAt(mCurrentTab).requestFocus();
- playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
- return true;
- }
- return handled;
- }
-
-
- @Override
- public void dispatchWindowFocusChanged(boolean hasFocus) {
- mCurrentView.dispatchWindowFocusChanged(hasFocus);
- }
-
- public void setCurrentTab(int index) {
- if (index < 0 || index >= mTabSpecs.size()) {
- return;
- }
-
- if (index == mCurrentTab) {
- return;
- }
-
- // notify old tab content
- if (mCurrentTab != -1) {
- mTabSpecs.get(mCurrentTab).mContentStrategy.tabClosed();
- }
-
- mCurrentTab = index;
- final TabHost.TabSpec spec = mTabSpecs.get(index);
-
- // Call the tab widget's focusCurrentTab(), instead of just
- // selecting the tab.
- mTabWidget.focusCurrentTab(mCurrentTab);
-
- // tab content
- mCurrentView = spec.mContentStrategy.getContentView();
-
- if (mCurrentView.getParent() == null) {
- mTabContent
- .addView(
- mCurrentView,
- new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.FILL_PARENT));
- }
-
- if (!mTabWidget.hasFocus()) {
- // if the tab widget didn't take focus (likely because we're in touch mode)
- // give the current tab content view a shot
- mCurrentView.requestFocus();
- }
-
- //mTabContent.requestFocus(View.FOCUS_FORWARD);
- invokeOnTabChangeListener();
- }
-
- /**
- * Register a callback to be invoked when the selected state of any of the items
- * in this list changes
- * @param l
- * The callback that will run
- */
- public void setOnTabChangedListener(OnTabChangeListener l) {
- mOnTabChangeListener = l;
- }
-
- private void invokeOnTabChangeListener() {
- if (mOnTabChangeListener != null) {
- mOnTabChangeListener.onTabChanged(getCurrentTabTag());
- }
- }
-
- /**
- * Interface definition for a callback to be invoked when tab changed
- */
- public interface OnTabChangeListener {
- void onTabChanged(String tabId);
- }
-
-
- /**
- * Makes the content of a tab when it is selected. Use this if your tab
- * content needs to be created on demand, i.e. you are not showing an
- * existing view or starting an activity.
- */
- public interface TabContentFactory {
- /**
- * Callback to make the tab contents
- *
- * @param tag
- * Which tab was selected.
- * @return The view to distplay the contents of the selected tab.
- */
- View createTabContent(String tag);
- }
-
-
- /**
- * A tab has a tab indictor, content, and a tag that is used to keep
- * track of it. This builder helps choose among these options.
- *
- * For the tab indicator, your choices are:
- * 1) set a label
- * 2) set a label and an icon
- *
- * For the tab content, your choices are:
- * 1) the id of a {@link View}
- * 2) a {@link TabContentFactory} that creates the {@link View} content.
- * 3) an {@link Intent} that launches an {@link android.app.Activity}.
- */
- public class TabSpec {
-
- private String mTag;
-
- private IndicatorStrategy mIndicatorStrategy;
- private ContentStrategy mContentStrategy;
-
- private TabSpec(String tag) {
- mTag = tag;
- }
-
- /**
- * Specify a label as the tab indicator.
- */
- public TabSpec setIndicator(CharSequence label) {
- mIndicatorStrategy = new LabelIndicatorStrategy(label);
- return this;
- }
-
- /**
- * Specify a label and icon as the tab indicator.
- */
- public TabSpec setIndicator(CharSequence label, Drawable icon) {
- mIndicatorStrategy = new LabelAndIconIndicatorStrategy(label, icon);
- return this;
- }
-
- /**
- * Specify the id of the view that should be used as the content
- * of the tab.
- */
- public TabSpec setContent(int viewId) {
- mContentStrategy = new ViewIdContentStrategy(viewId);
- return this;
- }
-
- /**
- * Specify a {@link android.widget.TabHost.TabContentFactory} to use to
- * create the content of the tab.
- */
- public TabSpec setContent(TabContentFactory contentFactory) {
- mContentStrategy = new FactoryContentStrategy(mTag, contentFactory);
- return this;
- }
-
- /**
- * Specify an intent to use to launch an activity as the tab content.
- */
- public TabSpec setContent(Intent intent) {
- mContentStrategy = new IntentContentStrategy(mTag, intent);
- return this;
- }
-
-
- String getTag() {
- return mTag;
- }
- }
-
- /**
- * Specifies what you do to create a tab indicator.
- */
- private static interface IndicatorStrategy {
-
- /**
- * Return the view for the indicator.
- */
- View createIndicatorView();
- }
-
- /**
- * Specifies what you do to manage the tab content.
- */
- private static interface ContentStrategy {
-
- /**
- * Return the content view. The view should may be cached locally.
- */
- View getContentView();
-
- /**
- * Perhaps do something when the tab associated with this content has
- * been closed (i.e make it invisible, or remove it).
- */
- void tabClosed();
- }
-
- /**
- * How to create a tab indicator that just has a label.
- */
- private class LabelIndicatorStrategy implements IndicatorStrategy {
-
- private final CharSequence mLabel;
-
- private LabelIndicatorStrategy(CharSequence label) {
- mLabel = label;
- }
-
- public View createIndicatorView() {
- LayoutInflater inflater =
- (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View tabIndicator = inflater.inflate(R.layout.tab_indicator,
- mTabWidget, // tab widget is the parent
- false); // no inflate params
-
- final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
- tv.setText(mLabel);
-
- return tabIndicator;
- }
- }
-
- /**
- * How we create a tab indicator that has a label and an icon
- */
- private class LabelAndIconIndicatorStrategy implements IndicatorStrategy {
-
- private final CharSequence mLabel;
- private final Drawable mIcon;
-
- private LabelAndIconIndicatorStrategy(CharSequence label, Drawable icon) {
- mLabel = label;
- mIcon = icon;
- }
-
- public View createIndicatorView() {
- LayoutInflater inflater =
- (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View tabIndicator = inflater.inflate(R.layout.tab_indicator,
- mTabWidget, // tab widget is the parent
- false); // no inflate params
-
- final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
- tv.setText(mLabel);
-
- final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.icon);
- iconView.setImageDrawable(mIcon);
-
- return tabIndicator;
- }
- }
-
- /**
- * How to create the tab content via a view id.
- */
- private class ViewIdContentStrategy implements ContentStrategy {
-
- private final View mView;
-
- private ViewIdContentStrategy(int viewId) {
- mView = mTabContent.findViewById(viewId);
- if (mView != null) {
- mView.setVisibility(View.GONE);
- } else {
- throw new RuntimeException("Could not create tab content because " +
- "could not find view with id " + viewId);
- }
- }
-
- public View getContentView() {
- mView.setVisibility(View.VISIBLE);
- return mView;
- }
-
- public void tabClosed() {
- mView.setVisibility(View.GONE);
- }
- }
-
- /**
- * How tab content is managed using {@link TabContentFactory}.
- */
- private class FactoryContentStrategy implements ContentStrategy {
- private View mTabContent;
- private final CharSequence mTag;
- private TabContentFactory mFactory;
-
- public FactoryContentStrategy(CharSequence tag, TabContentFactory factory) {
- mTag = tag;
- mFactory = factory;
- }
-
- public View getContentView() {
- if (mTabContent == null) {
- mTabContent = mFactory.createTabContent(mTag.toString());
- }
- mTabContent.setVisibility(View.VISIBLE);
- return mTabContent;
- }
-
- public void tabClosed() {
- mTabContent.setVisibility(View.INVISIBLE);
- }
- }
-
- /**
- * How tab content is managed via an {@link Intent}: the content view is the
- * decorview of the launched activity.
- */
- private class IntentContentStrategy implements ContentStrategy {
-
- private final String mTag;
- private final Intent mIntent;
-
- private View mLaunchedView;
-
- private IntentContentStrategy(String tag, Intent intent) {
- mTag = tag;
- mIntent = intent;
- }
-
- public View getContentView() {
- if (mLocalActivityManager == null) {
- throw new IllegalStateException("Did you forget to call 'public void setup(LocalActivityManager activityGroup)'?");
- }
- final Window w = mLocalActivityManager.startActivity(
- mTag, mIntent);
- final View wd = w != null ? w.getDecorView() : null;
- if (mLaunchedView != wd && mLaunchedView != null) {
- if (mLaunchedView.getParent() != null) {
- mTabContent.removeView(mLaunchedView);
- }
- }
- mLaunchedView = wd;
-
- // XXX Set FOCUS_AFTER_DESCENDANTS on embedded activies for now so they can get
- // focus if none of their children have it. They need focus to be able to
- // display menu items.
- //
- // Replace this with something better when Bug 628886 is fixed...
- //
- if (mLaunchedView != null) {
- mLaunchedView.setVisibility(View.VISIBLE);
- mLaunchedView.setFocusableInTouchMode(true);
- ((ViewGroup) mLaunchedView).setDescendantFocusability(
- FOCUS_AFTER_DESCENDANTS);
- }
- return mLaunchedView;
- }
-
- public void tabClosed() {
- if (mLaunchedView != null) {
- mLaunchedView.setVisibility(View.GONE);
- }
- }
- }
-
-}
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
deleted file mode 100644
index 20cddcb..0000000
--- a/core/java/android/widget/TabWidget.java
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.View.OnFocusChangeListener;
-
-
-
-/**
- *
- * Displays a list of tab labels representing each page in the parent's tab
- * collection. The container object for this widget is
- * {@link android.widget.TabHost TabHost}. When the user selects a tab, this
- * object sends a message to the parent container, TabHost, to tell it to switch
- * the displayed page. You typically won't use many methods directly on this
- * object. The container TabHost is used to add labels, add the callback
- * handler, and manage callbacks. You might call this object to iterate the list
- * of tabs, or to tweak the layout of the tab list, but most methods should be
- * called on the containing TabHost object.
- */
-public class TabWidget extends LinearLayout implements OnFocusChangeListener {
-
-
- private OnTabSelectionChanged mSelectionChangedListener;
- private int mSelectedTab = 0;
- private Drawable mBottomLeftStrip;
- private Drawable mBottomRightStrip;
- private boolean mStripMoved;
-
- public TabWidget(Context context) {
- this(context, null);
- }
-
- public TabWidget(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.tabWidgetStyle);
- }
-
- public TabWidget(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs);
- initTabWidget();
-
- TypedArray a =
- context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.TabWidget,
- defStyle, 0);
-
- a.recycle();
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- mStripMoved = true;
- super.onSizeChanged(w, h, oldw, oldh);
- }
-
- private void initTabWidget() {
- setOrientation(LinearLayout.HORIZONTAL);
- mBottomLeftStrip = mContext.getResources().getDrawable(
- com.android.internal.R.drawable.tab_bottom_left);
- mBottomRightStrip = mContext.getResources().getDrawable(
- com.android.internal.R.drawable.tab_bottom_right);
- // Deal with focus, as we don't want the focus to go by default
- // to a tab other than the current tab
- setFocusable(true);
- setOnFocusChangeListener(this);
- }
-
- @Override
- public void childDrawableStateChanged(View child) {
- if (child == getChildAt(mSelectedTab)) {
- // To make sure that the bottom strip is redrawn
- invalidate();
- }
- super.childDrawableStateChanged(child);
- }
-
- @Override
- public void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
-
- View selectedChild = getChildAt(mSelectedTab);
-
- mBottomLeftStrip.setState(selectedChild.getDrawableState());
- mBottomRightStrip.setState(selectedChild.getDrawableState());
-
- if (mStripMoved) {
- Rect selBounds = new Rect(); // Bounds of the selected tab indicator
- selBounds.left = selectedChild.getLeft();
- selBounds.right = selectedChild.getRight();
- final int myHeight = getHeight();
- mBottomLeftStrip.setBounds(
- Math.min(0, selBounds.left
- - mBottomLeftStrip.getIntrinsicWidth()),
- myHeight - mBottomLeftStrip.getIntrinsicHeight(),
- selBounds.left,
- getHeight());
- mBottomRightStrip.setBounds(
- selBounds.right,
- myHeight - mBottomRightStrip.getIntrinsicHeight(),
- Math.max(getWidth(),
- selBounds.right + mBottomRightStrip.getIntrinsicWidth()),
- myHeight);
- mStripMoved = false;
- }
-
- mBottomLeftStrip.draw(canvas);
- mBottomRightStrip.draw(canvas);
- }
-
- /**
- * Sets the current tab.
- * This method is used to bring a tab to the front of the Widget,
- * and is used to post to the rest of the UI that a different tab
- * has been brought to the foreground.
- *
- * Note, this is separate from the traditional "focus" that is
- * employed from the view logic.
- *
- * For instance, if we have a list in a tabbed view, a user may be
- * navigating up and down the list, moving the UI focus (orange
- * highlighting) through the list items. The cursor movement does
- * not effect the "selected" tab though, because what is being
- * scrolled through is all on the same tab. The selected tab only
- * changes when we navigate between tabs (moving from the list view
- * to the next tabbed view, in this example).
- *
- * To move both the focus AND the selected tab at once, please use
- * {@link #setCurrentTab}. Normally, the view logic takes care of
- * adjusting the focus, so unless you're circumventing the UI,
- * you'll probably just focus your interest here.
- *
- * @param index The tab that you want to indicate as the selected
- * tab (tab brought to the front of the widget)
- *
- * @see #focusCurrentTab
- */
- public void setCurrentTab(int index) {
- if (index < 0 || index >= getChildCount()) {
- return;
- }
-
- getChildAt(mSelectedTab).setSelected(false);
- mSelectedTab = index;
- getChildAt(mSelectedTab).setSelected(true);
- mStripMoved = true;
- }
-
- /**
- * Sets the current tab and focuses the UI on it.
- * This method makes sure that the focused tab matches the selected
- * tab, normally at {@link #setCurrentTab}. Normally this would not
- * be an issue if we go through the UI, since the UI is responsible
- * for calling TabWidget.onFocusChanged(), but in the case where we
- * are selecting the tab programmatically, we'll need to make sure
- * focus keeps up.
- *
- * @param index The tab that you want focused (highlighted in orange)
- * and selected (tab brought to the front of the widget)
- *
- * @see #setCurrentTab
- */
- public void focusCurrentTab(int index) {
- final int oldTab = mSelectedTab;
-
- // set the tab
- setCurrentTab(index);
-
- // change the focus if applicable.
- if (oldTab != index) {
- getChildAt(index).requestFocus();
- }
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- super.setEnabled(enabled);
- int count = getChildCount();
-
- for (int i=0; i<count; i++) {
- View child = getChildAt(i);
- child.setEnabled(enabled);
- }
- }
-
- @Override
- public void addView(View child) {
- if (child.getLayoutParams() == null) {
- final LinearLayout.LayoutParams lp = new LayoutParams(
- 0,
- ViewGroup.LayoutParams.WRAP_CONTENT, 1);
- lp.setMargins(0, 0, 0, 0);
- child.setLayoutParams(lp);
- }
-
- // Ensure you can navigate to the tab with the keyboard, and you can touch it
- child.setFocusable(true);
- child.setClickable(true);
-
- super.addView(child);
-
- // TODO: detect this via geometry with a tabwidget listener rather
- // than potentially interfere with the view's listener
- child.setOnClickListener(new TabClickListener(getChildCount() - 1));
- child.setOnFocusChangeListener(this);
- }
-
-
-
-
- /**
- * Provides a way for {@link TabHost} to be notified that the user clicked on a tab indicator.
- */
- void setTabSelectionListener(OnTabSelectionChanged listener) {
- mSelectionChangedListener = listener;
- }
-
- public void onFocusChange(View v, boolean hasFocus) {
- if (v == this && hasFocus) {
- getChildAt(mSelectedTab).requestFocus();
- return;
- }
-
- if (hasFocus) {
- int i = 0;
- while (i < getChildCount()) {
- if (getChildAt(i) == v) {
- setCurrentTab(i);
- mSelectionChangedListener.onTabSelectionChanged(i, false);
- break;
- }
- i++;
- }
- }
- }
-
- // registered with each tab indicator so we can notify tab host
- private class TabClickListener implements OnClickListener {
-
- private final int mTabIndex;
-
- private TabClickListener(int tabIndex) {
- mTabIndex = tabIndex;
- }
-
- public void onClick(View v) {
- mSelectionChangedListener.onTabSelectionChanged(mTabIndex, true);
- }
- }
-
- /**
- * Let {@link TabHost} know that the user clicked on a tab indicator.
- */
- static interface OnTabSelectionChanged {
- /**
- * Informs the TabHost which tab was selected. It also indicates
- * if the tab was clicked/pressed or just focused into.
- *
- * @param tabIndex index of the tab that was selected
- * @param clicked whether the selection changed due to a touch/click
- * or due to focus entering the tab through navigation. Pass true
- * if it was due to a press/click and false otherwise.
- */
- void onTabSelectionChanged(int tabIndex, boolean clicked);
- }
-
-}
-
diff --git a/core/java/android/widget/TableLayout.java b/core/java/android/widget/TableLayout.java
deleted file mode 100644
index afa2f3b..0000000
--- a/core/java/android/widget/TableLayout.java
+++ /dev/null
@@ -1,751 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import com.android.internal.R;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.util.SparseBooleanArray;
-import android.view.View;
-import android.view.ViewGroup;
-
-import java.util.regex.Pattern;
-
-/**
- * <p>A layout that arranges its children into rows and columns.
- * A TableLayout consists of a number of {@link android.widget.TableRow} objects,
- * each defining a row (actually, you can have other children, which will be
- * explained below). TableLayout containers do not display border lines for
- * their rows, columns, or cells. Each row has zero or more cells; each cell can
- * hold one {@link android.view.View View} object. The table has as many columns
- * as the row with the most cells. A table can leave cells empty. Cells can span
- * columns, as they can in HTML.</p>
- *
- * <p>The width of a column is defined by the row with the widest cell in that
- * column. However, a TableLayout can specify certain columns as shrinkable or
- * stretchable by calling
- * {@link #setColumnShrinkable(int, boolean) setColumnShrinkable()}
- * or {@link #setColumnStretchable(int, boolean) setColumnStretchable()}. If
- * marked as shrinkable, the column width can be shrunk to fit the table into
- * its parent object. If marked as stretchable, it can expand in width to fit
- * any extra space. The total width of the table is defined by its parent
- * container. It is important to remember that a column can be both shrinkable
- * and stretchable. In such a situation, the column will change its size to
- * always use up the available space, but never more. Finally, you can hide a
- * column by calling
- * {@link #setColumnCollapsed(int,boolean) setColumnCollapsed()}.</p>
- *
- * <p>The children of a TableLayout cannot specify the <code>layout_width</code>
- * attribute. Width is always <code>FILL_PARENT</code>. However, the
- * <code>layout_height</code> attribute can be defined by a child; default value
- * is {@link android.widget.TableLayout.LayoutParams#WRAP_CONTENT}. If the child
- * is a {@link android.widget.TableRow}, then the height is always
- * {@link android.widget.TableLayout.LayoutParams#WRAP_CONTENT}.</p>
- *
- * <p> Cells must be added to a row in increasing column order, both in code and
- * XML. Column numbers are zero-based. If you don't specify a column number for
- * a child cell, it will autoincrement to the next available column. If you skip
- * a column number, it will be considered an empty cell in that row. See the
- * TableLayout examples in ApiDemos for examples of creating tables in XML.</p>
- *
- * <p>Although the typical child of a TableLayout is a TableRow, you can
- * actually use any View subclass as a direct child of TableLayout. The View
- * will be displayed as a single row that spans all the table columns.</p>
- */
-public class TableLayout extends LinearLayout {
- private int[] mMaxWidths;
- private SparseBooleanArray mStretchableColumns;
- private SparseBooleanArray mShrinkableColumns;
- private SparseBooleanArray mCollapsedColumns;
-
- private boolean mShrinkAllColumns;
- private boolean mStretchAllColumns;
-
- private TableLayout.PassThroughHierarchyChangeListener mPassThroughListener;
-
- private boolean mInitialized;
-
- /**
- * <p>Creates a new TableLayout for the given context.</p>
- *
- * @param context the application environment
- */
- public TableLayout(Context context) {
- super(context);
- initTableLayout();
- }
-
- /**
- * <p>Creates a new TableLayout for the given context and with the
- * specified set attributes.</p>
- *
- * @param context the application environment
- * @param attrs a collection of attributes
- */
- public TableLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TableLayout);
-
- String stretchedColumns = a.getString(R.styleable.TableLayout_stretchColumns);
- if (stretchedColumns != null) {
- if (stretchedColumns.charAt(0) == '*') {
- mStretchAllColumns = true;
- } else {
- mStretchableColumns = parseColumns(stretchedColumns);
- }
- }
-
- String shrinkedColumns = a.getString(R.styleable.TableLayout_shrinkColumns);
- if (shrinkedColumns != null) {
- if (shrinkedColumns.charAt(0) == '*') {
- mShrinkAllColumns = true;
- } else {
- mShrinkableColumns = parseColumns(shrinkedColumns);
- }
- }
-
- String collapsedColumns = a.getString(R.styleable.TableLayout_collapseColumns);
- if (collapsedColumns != null) {
- mCollapsedColumns = parseColumns(collapsedColumns);
- }
-
- a.recycle();
- initTableLayout();
- }
-
- /**
- * <p>Parses a sequence of columns ids defined in a CharSequence with the
- * following pattern (regex): \d+(\s*,\s*\d+)*</p>
- *
- * <p>Examples: "1" or "13, 7, 6" or "".</p>
- *
- * <p>The result of the parsing is stored in a sparse boolean array. The
- * parsed column ids are used as the keys of the sparse array. The values
- * are always true.</p>
- *
- * @param sequence a sequence of column ids, can be empty but not null
- * @return a sparse array of boolean mapping column indexes to the columns
- * collapse state
- */
- private static SparseBooleanArray parseColumns(String sequence) {
- SparseBooleanArray columns = new SparseBooleanArray();
- Pattern pattern = Pattern.compile("\\s*,\\s*");
- String[] columnDefs = pattern.split(sequence);
-
- for (String columnIdentifier : columnDefs) {
- try {
- int columnIndex = Integer.parseInt(columnIdentifier);
- // only valid, i.e. positive, columns indexes are handled
- if (columnIndex >= 0) {
- // putting true in this sparse array indicates that the
- // column index was defined in the XML file
- columns.put(columnIndex, true);
- }
- } catch (NumberFormatException e) {
- // we just ignore columns that don't exist
- }
- }
-
- return columns;
- }
-
- /**
- * <p>Performs initialization common to prorgrammatic use and XML use of
- * this widget.</p>
- */
- private void initTableLayout() {
- if (mCollapsedColumns == null) {
- mCollapsedColumns = new SparseBooleanArray();
- }
- if (mStretchableColumns == null) {
- mStretchableColumns = new SparseBooleanArray();
- }
- if (mShrinkableColumns == null) {
- mShrinkableColumns = new SparseBooleanArray();
- }
-
- mPassThroughListener = new PassThroughHierarchyChangeListener();
- // make sure to call the parent class method to avoid potential
- // infinite loops
- super.setOnHierarchyChangeListener(mPassThroughListener);
-
- mInitialized = true;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setOnHierarchyChangeListener(
- OnHierarchyChangeListener listener) {
- // the user listener is delegated to our pass-through listener
- mPassThroughListener.mOnHierarchyChangeListener = listener;
- }
-
- private void requestRowsLayout() {
- if (mInitialized) {
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- getChildAt(i).requestLayout();
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void requestLayout() {
- if (mInitialized) {
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- getChildAt(i).forceLayout();
- }
- }
-
- super.requestLayout();
- }
-
- /**
- * <p>Indicates whether all columns are shrinkable or not.</p>
- *
- * @return true if all columns are shrinkable, false otherwise
- */
- public boolean isShrinkAllColumns() {
- return mShrinkAllColumns;
- }
-
- /**
- * <p>Convenience method to mark all columns as shrinkable.</p>
- *
- * @param shrinkAllColumns true to mark all columns shrinkable
- *
- * @attr ref android.R.styleable#TableLayout_shrinkColumns
- */
- public void setShrinkAllColumns(boolean shrinkAllColumns) {
- mShrinkAllColumns = shrinkAllColumns;
- }
-
- /**
- * <p>Indicates whether all columns are stretchable or not.</p>
- *
- * @return true if all columns are stretchable, false otherwise
- */
- public boolean isStretchAllColumns() {
- return mStretchAllColumns;
- }
-
- /**
- * <p>Convenience method to mark all columns as stretchable.</p>
- *
- * @param stretchAllColumns true to mark all columns stretchable
- *
- * @attr ref android.R.styleable#TableLayout_stretchColumns
- */
- public void setStretchAllColumns(boolean stretchAllColumns) {
- mStretchAllColumns = stretchAllColumns;
- }
-
- /**
- * <p>Collapses or restores a given column. When collapsed, a column
- * does not appear on screen and the extra space is reclaimed by the
- * other columns. A column is collapsed/restored only when it belongs to
- * a {@link android.widget.TableRow}.</p>
- *
- * <p>Calling this method requests a layout operation.</p>
- *
- * @param columnIndex the index of the column
- * @param isCollapsed true if the column must be collapsed, false otherwise
- *
- * @attr ref android.R.styleable#TableLayout_collapseColumns
- */
- public void setColumnCollapsed(int columnIndex, boolean isCollapsed) {
- // update the collapse status of the column
- mCollapsedColumns.put(columnIndex, isCollapsed);
-
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View view = getChildAt(i);
- if (view instanceof TableRow) {
- ((TableRow) view).setColumnCollapsed(columnIndex, isCollapsed);
- }
- }
-
- requestRowsLayout();
- }
-
- /**
- * <p>Returns the collapsed state of the specified column.</p>
- *
- * @param columnIndex the index of the column
- * @return true if the column is collapsed, false otherwise
- */
- public boolean isColumnCollapsed(int columnIndex) {
- return mCollapsedColumns.get(columnIndex);
- }
-
- /**
- * <p>Makes the given column stretchable or not. When stretchable, a column
- * takes up as much as available space as possible in its row.</p>
- *
- * <p>Calling this method requests a layout operation.</p>
- *
- * @param columnIndex the index of the column
- * @param isStretchable true if the column must be stretchable,
- * false otherwise. Default is false.
- *
- * @attr ref android.R.styleable#TableLayout_stretchColumns
- */
- public void setColumnStretchable(int columnIndex, boolean isStretchable) {
- mStretchableColumns.put(columnIndex, isStretchable);
- requestRowsLayout();
- }
-
- /**
- * <p>Returns whether the specified column is stretchable or not.</p>
- *
- * @param columnIndex the index of the column
- * @return true if the column is stretchable, false otherwise
- */
- public boolean isColumnStretchable(int columnIndex) {
- return mStretchAllColumns || mStretchableColumns.get(columnIndex);
- }
-
- /**
- * <p>Makes the given column shrinkable or not. When a row is too wide, the
- * table can reclaim extra space from shrinkable columns.</p>
- *
- * <p>Calling this method requests a layout operation.</p>
- *
- * @param columnIndex the index of the column
- * @param isShrinkable true if the column must be shrinkable,
- * false otherwise. Default is false.
- *
- * @attr ref android.R.styleable#TableLayout_shrinkColumns
- */
- public void setColumnShrinkable(int columnIndex, boolean isShrinkable) {
- mShrinkableColumns.put(columnIndex, isShrinkable);
- requestRowsLayout();
- }
-
- /**
- * <p>Returns whether the specified column is shrinkable or not.</p>
- *
- * @param columnIndex the index of the column
- * @return true if the column is shrinkable, false otherwise. Default is false.
- */
- public boolean isColumnShrinkable(int columnIndex) {
- return mShrinkAllColumns || mShrinkableColumns.get(columnIndex);
- }
-
- /**
- * <p>Applies the columns collapse status to a new row added to this
- * table. This method is invoked by PassThroughHierarchyChangeListener
- * upon child insertion.</p>
- *
- * <p>This method only applies to {@link android.widget.TableRow}
- * instances.</p>
- *
- * @param child the newly added child
- */
- private void trackCollapsedColumns(View child) {
- if (child instanceof TableRow) {
- final TableRow row = (TableRow) child;
- final SparseBooleanArray collapsedColumns = mCollapsedColumns;
- final int count = collapsedColumns.size();
- for (int i = 0; i < count; i++) {
- int columnIndex = collapsedColumns.keyAt(i);
- boolean isCollapsed = collapsedColumns.valueAt(i);
- // the collapse status is set only when the column should be
- // collapsed; otherwise, this might affect the default
- // visibility of the row's children
- if (isCollapsed) {
- row.setColumnCollapsed(columnIndex, isCollapsed);
- }
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void addView(View child) {
- super.addView(child);
- requestRowsLayout();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void addView(View child, int index) {
- super.addView(child, index);
- requestRowsLayout();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void addView(View child, ViewGroup.LayoutParams params) {
- super.addView(child, params);
- requestRowsLayout();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void addView(View child, int index, ViewGroup.LayoutParams params) {
- super.addView(child, index, params);
- requestRowsLayout();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // enforce vertical layout
- measureVertical(widthMeasureSpec, heightMeasureSpec);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- // enforce vertical layout
- layoutVertical();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- void measureChildBeforeLayout(View child, int childIndex,
- int widthMeasureSpec, int totalWidth,
- int heightMeasureSpec, int totalHeight) {
- // when the measured child is a table row, we force the width of its
- // children with the widths computed in findLargestCells()
- if (child instanceof TableRow) {
- ((TableRow) child).setColumnsWidthConstraints(mMaxWidths);
- }
-
- super.measureChildBeforeLayout(child, childIndex,
- widthMeasureSpec, totalWidth, heightMeasureSpec, totalHeight);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {
- findLargestCells(widthMeasureSpec);
- shrinkAndStretchColumns(widthMeasureSpec);
-
- super.measureVertical(widthMeasureSpec, heightMeasureSpec);
- }
-
- /**
- * <p>Finds the largest cell in each column. For each column, the width of
- * the largest cell is applied to all the other cells.</p>
- *
- * @param widthMeasureSpec the measure constraint imposed by our parent
- */
- private void findLargestCells(int widthMeasureSpec) {
- boolean firstRow = true;
-
- // find the maximum width for each column
- // the total number of columns is dynamically changed if we find
- // wider rows as we go through the children
- // the array is reused for each layout operation; the array can grow
- // but never shrinks. Unused extra cells in the array are just ignored
- // this behavior avoids to unnecessary grow the array after the first
- // layout operation
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.getVisibility() == GONE) {
- continue;
- }
-
- if (child instanceof TableRow) {
- final TableRow row = (TableRow) child;
- // forces the row's height
- final ViewGroup.LayoutParams layoutParams = row.getLayoutParams();
- layoutParams.height = LayoutParams.WRAP_CONTENT;
-
- final int[] widths = row.getColumnsWidths(widthMeasureSpec);
- final int newLength = widths.length;
- // this is the first row, we just need to copy the values
- if (firstRow) {
- if (mMaxWidths == null || mMaxWidths.length != newLength) {
- mMaxWidths = new int[newLength];
- }
- System.arraycopy(widths, 0, mMaxWidths, 0, newLength);
- firstRow = false;
- } else {
- int length = mMaxWidths.length;
- final int difference = newLength - length;
- // the current row is wider than the previous rows, so
- // we just grow the array and copy the values
- if (difference > 0) {
- final int[] oldMaxWidths = mMaxWidths;
- mMaxWidths = new int[newLength];
- System.arraycopy(oldMaxWidths, 0, mMaxWidths, 0,
- oldMaxWidths.length);
- System.arraycopy(widths, oldMaxWidths.length,
- mMaxWidths, oldMaxWidths.length, difference);
- }
-
- // the row is narrower or of the same width as the previous
- // rows, so we find the maximum width for each column
- // if the row is narrower than the previous ones,
- // difference will be negative
- final int[] maxWidths = mMaxWidths;
- length = Math.min(length, newLength);
- for (int j = 0; j < length; j++) {
- maxWidths[j] = Math.max(maxWidths[j], widths[j]);
- }
- }
- }
- }
- }
-
- /**
- * <p>Shrinks the columns if their total width is greater than the
- * width allocated by widthMeasureSpec. When the total width is less
- * than the allocated width, this method attempts to stretch columns
- * to fill the remaining space.</p>
- *
- * @param widthMeasureSpec the width measure specification as indicated
- * by this widget's parent
- */
- private void shrinkAndStretchColumns(int widthMeasureSpec) {
- // when we have no row, mMaxWidths is not initialized and the loop
- // below could cause a NPE
- if (mMaxWidths == null) {
- return;
- }
-
- // should we honor AT_MOST, EXACTLY and UNSPECIFIED?
- int totalWidth = 0;
- for (int width : mMaxWidths) {
- totalWidth += width;
- }
-
- int size = MeasureSpec.getSize(widthMeasureSpec) - mPaddingLeft - mPaddingRight;
-
- if ((totalWidth > size) && (mShrinkAllColumns || mShrinkableColumns.size() > 0)) {
- // oops, the largest columns are wider than the row itself
- // fairly redistribute the row's widh among the columns
- mutateColumnsWidth(mShrinkableColumns, mShrinkAllColumns, size, totalWidth);
- } else if ((totalWidth < size) && (mStretchAllColumns || mStretchableColumns.size() > 0)) {
- // if we have some space left, we distribute it among the
- // expandable columns
- mutateColumnsWidth(mStretchableColumns, mStretchAllColumns, size, totalWidth);
- }
- }
-
- private void mutateColumnsWidth(SparseBooleanArray columns,
- boolean allColumns, int size, int totalWidth) {
- int skipped = 0;
- final int[] maxWidths = mMaxWidths;
- final int length = maxWidths.length;
- final int count = allColumns ? length : columns.size();
- final int totalExtraSpace = size - totalWidth;
- int extraSpace = totalExtraSpace / count;
-
- if (!allColumns) {
- for (int i = 0; i < count; i++) {
- int column = columns.keyAt(i);
- if (columns.valueAt(i)) {
- if (column < length) {
- maxWidths[column] += extraSpace;
- } else {
- skipped++;
- }
- }
- }
- } else {
- for (int i = 0; i < count; i++) {
- maxWidths[i] += extraSpace;
- }
-
- // we don't skip any column so we can return right away
- return;
- }
-
- if (skipped > 0 && skipped < count) {
- // reclaim any extra space we left to columns that don't exist
- extraSpace = skipped * extraSpace / (count - skipped);
- for (int i = 0; i < count; i++) {
- int column = columns.keyAt(i);
- if (columns.valueAt(i) && column < length) {
- if (extraSpace > maxWidths[column]) {
- maxWidths[column] = 0;
- } else {
- maxWidths[column] += extraSpace;
- }
- }
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new TableLayout.LayoutParams(getContext(), attrs);
- }
-
- /**
- * Returns a set of layout parameters with a width of
- * {@link android.view.ViewGroup.LayoutParams#FILL_PARENT},
- * and a height of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}.
- */
- @Override
- protected LinearLayout.LayoutParams generateDefaultLayoutParams() {
- return new LayoutParams();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof TableLayout.LayoutParams;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected LinearLayout.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return new LayoutParams(p);
- }
-
- /**
- * <p>This set of layout parameters enforces the width of each child to be
- * {@link #FILL_PARENT} and the height of each child to be
- * {@link #WRAP_CONTENT}, but only if the height is not specified.</p>
- */
- @SuppressWarnings({"UnusedDeclaration"})
- public static class LayoutParams extends LinearLayout.LayoutParams {
- /**
- * {@inheritDoc}
- */
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(int w, int h) {
- super(FILL_PARENT, h);
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(int w, int h, float initWeight) {
- super(FILL_PARENT, h, initWeight);
- }
-
- /**
- * <p>Sets the child width to
- * {@link android.view.ViewGroup.LayoutParams} and the child height to
- * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}.</p>
- */
- public LayoutParams() {
- super(FILL_PARENT, WRAP_CONTENT);
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(ViewGroup.LayoutParams p) {
- super(p);
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(MarginLayoutParams source) {
- super(source);
- }
-
- /**
- * <p>Fixes the row's width to
- * {@link android.view.ViewGroup.LayoutParams#FILL_PARENT}; the row's
- * height is fixed to
- * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} if no layout
- * height is specified.</p>
- *
- * @param a the styled attributes set
- * @param widthAttr the width attribute to fetch
- * @param heightAttr the height attribute to fetch
- */
- @Override
- protected void setBaseAttributes(TypedArray a,
- int widthAttr, int heightAttr) {
- this.width = FILL_PARENT;
- if (a.hasValue(heightAttr)) {
- this.height = a.getLayoutDimension(heightAttr, "layout_height");
- } else {
- this.height = WRAP_CONTENT;
- }
- }
- }
-
- /**
- * <p>A pass-through listener acts upon the events and dispatches them
- * to another listener. This allows the table layout to set its own internal
- * hierarchy change listener without preventing the user to setup his.</p>
- */
- private class PassThroughHierarchyChangeListener implements
- OnHierarchyChangeListener {
- private OnHierarchyChangeListener mOnHierarchyChangeListener;
-
- /**
- * {@inheritDoc}
- */
- public void onChildViewAdded(View parent, View child) {
- trackCollapsedColumns(child);
-
- if (mOnHierarchyChangeListener != null) {
- mOnHierarchyChangeListener.onChildViewAdded(parent, child);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void onChildViewRemoved(View parent, View child) {
- if (mOnHierarchyChangeListener != null) {
- mOnHierarchyChangeListener.onChildViewRemoved(parent, child);
- }
- }
- }
-}
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
deleted file mode 100644
index 5628cab..0000000
--- a/core/java/android/widget/TableRow.java
+++ /dev/null
@@ -1,531 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.util.SparseIntArray;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewDebug;
-
-
-/**
- * <p>A layout that arranges its children horizontally. A TableRow should
- * always be used as a child of a {@link android.widget.TableLayout}. If a
- * TableRow's parent is not a TableLayout, the TableRow will behave as
- * an horizontal {@link android.widget.LinearLayout}.</p>
- *
- * <p>The children of a TableRow do not need to specify the
- * <code>layout_width</code> and <code>layout_height</code> attributes in the
- * XML file. TableRow always enforces those values to be respectively
- * {@link android.widget.TableLayout.LayoutParams#FILL_PARENT} and
- * {@link android.widget.TableLayout.LayoutParams#WRAP_CONTENT}.</p>
- *
- * <p>
- * Also see {@link TableRow.LayoutParams android.widget.TableRow.LayoutParams}
- * for layout attributes </p>
- */
-public class TableRow extends LinearLayout {
- private int mNumColumns = 0;
- private int[] mColumnWidths;
- private int[] mConstrainedColumnWidths;
- private SparseIntArray mColumnToChildIndex;
-
- private ChildrenTracker mChildrenTracker;
-
- /**
- * <p>Creates a new TableRow for the given context.</p>
- *
- * @param context the application environment
- */
- public TableRow(Context context) {
- super(context);
- initTableRow();
- }
-
- /**
- * <p>Creates a new TableRow for the given context and with the
- * specified set attributes.</p>
- *
- * @param context the application environment
- * @param attrs a collection of attributes
- */
- public TableRow(Context context, AttributeSet attrs) {
- super(context, attrs);
- initTableRow();
- }
-
- private void initTableRow() {
- OnHierarchyChangeListener oldListener = mOnHierarchyChangeListener;
- mChildrenTracker = new ChildrenTracker();
- if (oldListener != null) {
- mChildrenTracker.setOnHierarchyChangeListener(oldListener);
- }
- super.setOnHierarchyChangeListener(mChildrenTracker);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
- mChildrenTracker.setOnHierarchyChangeListener(listener);
- }
-
- /**
- * <p>Collapses or restores a given column.</p>
- *
- * @param columnIndex the index of the column
- * @param collapsed true if the column must be collapsed, false otherwise
- * {@hide}
- */
- void setColumnCollapsed(int columnIndex, boolean collapsed) {
- View child = getVirtualChildAt(columnIndex);
- if (child != null) {
- child.setVisibility(collapsed ? GONE : VISIBLE);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // enforce horizontal layout
- measureHorizontal(widthMeasureSpec, heightMeasureSpec);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- // enforce horizontal layout
- layoutHorizontal();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public View getVirtualChildAt(int i) {
- if (mColumnToChildIndex == null) {
- mapIndexAndColumns();
- }
-
- final int deflectedIndex = mColumnToChildIndex.get(i, -1);
- if (deflectedIndex != -1) {
- return getChildAt(deflectedIndex);
- }
-
- return null;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int getVirtualChildCount() {
- if (mColumnToChildIndex == null) {
- mapIndexAndColumns();
- }
- return mNumColumns;
- }
-
- private void mapIndexAndColumns() {
- if (mColumnToChildIndex == null) {
- int virtualCount = 0;
- final int count = getChildCount();
-
- mColumnToChildIndex = new SparseIntArray();
- final SparseIntArray columnToChild = mColumnToChildIndex;
-
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- final LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
-
- if (layoutParams.column >= virtualCount) {
- virtualCount = layoutParams.column;
- }
-
- for (int j = 0; j < layoutParams.span; j++) {
- columnToChild.put(virtualCount++, i);
- }
- }
-
- mNumColumns = virtualCount;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- int measureNullChild(int childIndex) {
- return mConstrainedColumnWidths[childIndex];
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- void measureChildBeforeLayout(View child, int childIndex,
- int widthMeasureSpec, int totalWidth,
- int heightMeasureSpec, int totalHeight) {
- if (mConstrainedColumnWidths != null) {
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
- int measureMode = MeasureSpec.EXACTLY;
- int columnWidth = 0;
-
- final int span = lp.span;
- final int[] constrainedColumnWidths = mConstrainedColumnWidths;
- for (int i = 0; i < span; i++) {
- columnWidth += constrainedColumnWidths[childIndex + i];
- }
-
- final int gravity = lp.gravity;
- final boolean isHorizontalGravity = Gravity.isHorizontal(gravity);
-
- if (isHorizontalGravity) {
- measureMode = MeasureSpec.AT_MOST;
- }
-
- // no need to care about padding here,
- // ViewGroup.getChildMeasureSpec() would get rid of it anyway
- // because of the EXACTLY measure spec we use
- int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
- Math.max(0, columnWidth - lp.leftMargin - lp.rightMargin), measureMode
- );
- int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
- mPaddingTop + mPaddingBottom + lp.topMargin +
- lp .bottomMargin + totalHeight, lp.height);
-
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
-
- if (isHorizontalGravity) {
- final int childWidth = child.getMeasuredWidth();
- lp.mOffset[LayoutParams.LOCATION_NEXT] = columnWidth - childWidth;
-
- switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- // don't offset on X axis
- break;
- case Gravity.RIGHT:
- lp.mOffset[LayoutParams.LOCATION] = lp.mOffset[LayoutParams.LOCATION_NEXT];
- break;
- case Gravity.CENTER_HORIZONTAL:
- lp.mOffset[LayoutParams.LOCATION] = lp.mOffset[LayoutParams.LOCATION_NEXT] / 2;
- break;
- }
- } else {
- lp.mOffset[LayoutParams.LOCATION] = lp.mOffset[LayoutParams.LOCATION_NEXT] = 0;
- }
- } else {
- // fail silently when column widths are not available
- super.measureChildBeforeLayout(child, childIndex, widthMeasureSpec,
- totalWidth, heightMeasureSpec, totalHeight);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- int getChildrenSkipCount(View child, int index) {
- LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
-
- // when the span is 1 (default), we need to skip 0 child
- return layoutParams.span - 1;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- int getLocationOffset(View child) {
- return ((TableRow.LayoutParams) child.getLayoutParams()).mOffset[LayoutParams.LOCATION];
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- int getNextLocationOffset(View child) {
- return ((TableRow.LayoutParams) child.getLayoutParams()).mOffset[LayoutParams.LOCATION_NEXT];
- }
-
- /**
- * <p>Measures the preferred width of each child, including its margins.</p>
- *
- * @param widthMeasureSpec the width constraint imposed by our parent
- *
- * @return an array of integers corresponding to the width of each cell, or
- * column, in this row
- * {@hide}
- */
- int[] getColumnsWidths(int widthMeasureSpec) {
- final int numColumns = getVirtualChildCount();
- if (mColumnWidths == null || numColumns != mColumnWidths.length) {
- mColumnWidths = new int[numColumns];
- }
-
- final int[] columnWidths = mColumnWidths;
-
- for (int i = 0; i < numColumns; i++) {
- final View child = getVirtualChildAt(i);
- if (child != null && child.getVisibility() != GONE) {
- final LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
- if (layoutParams.span == 1) {
- int spec;
- switch (layoutParams.width) {
- case LayoutParams.WRAP_CONTENT:
- spec = getChildMeasureSpec(widthMeasureSpec, 0, LayoutParams.WRAP_CONTENT);
- break;
- case LayoutParams.FILL_PARENT:
- spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- break;
- default:
- spec = MeasureSpec.makeMeasureSpec(layoutParams.width, MeasureSpec.EXACTLY);
- }
- child.measure(spec, spec);
-
- final int width = child.getMeasuredWidth() + layoutParams.leftMargin +
- layoutParams.rightMargin;
- columnWidths[i] = width;
- } else {
- columnWidths[i] = 0;
- }
- } else {
- columnWidths[i] = 0;
- }
- }
-
- return columnWidths;
- }
-
- /**
- * <p>Sets the width of all of the columns in this row. At layout time,
- * this row sets a fixed width, as defined by <code>columnWidths</code>,
- * on each child (or cell, or column.)</p>
- *
- * @param columnWidths the fixed width of each column that this row must
- * honor
- * @throws IllegalArgumentException when columnWidths' length is smaller
- * than the number of children in this row
- * {@hide}
- */
- void setColumnsWidthConstraints(int[] columnWidths) {
- if (columnWidths == null || columnWidths.length < getVirtualChildCount()) {
- throw new IllegalArgumentException(
- "columnWidths should be >= getVirtualChildCount()");
- }
-
- mConstrainedColumnWidths = columnWidths;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new TableRow.LayoutParams(getContext(), attrs);
- }
-
- /**
- * Returns a set of layout parameters with a width of
- * {@link android.view.ViewGroup.LayoutParams#FILL_PARENT},
- * a height of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and no spanning.
- */
- @Override
- protected LinearLayout.LayoutParams generateDefaultLayoutParams() {
- return new LayoutParams();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof TableRow.LayoutParams;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected LinearLayout.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return new LayoutParams(p);
- }
-
- /**
- * <p>Set of layout parameters used in table rows.</p>
- *
- * @see android.widget.TableLayout.LayoutParams
- *
- * @attr ref android.R.styleable#TableRow_Cell_layout_column
- * @attr ref android.R.styleable#TableRow_Cell_layout_span
- */
- public static class LayoutParams extends LinearLayout.LayoutParams {
- /**
- * <p>The column index of the cell represented by the widget.</p>
- */
- @ViewDebug.ExportedProperty
- public int column;
-
- /**
- * <p>The number of columns the widgets spans over.</p>
- */
- @ViewDebug.ExportedProperty
- public int span;
-
- private static final int LOCATION = 0;
- private static final int LOCATION_NEXT = 1;
-
- private int[] mOffset = new int[2];
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
-
- TypedArray a =
- c.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.TableRow_Cell);
-
- column = a.getInt(com.android.internal.R.styleable.TableRow_Cell_layout_column, -1);
- span = a.getInt(com.android.internal.R.styleable.TableRow_Cell_layout_span, 1);
- if (span <= 1) {
- span = 1;
- }
-
- a.recycle();
- }
-
- /**
- * <p>Sets the child width and the child height.</p>
- *
- * @param w the desired width
- * @param h the desired height
- */
- public LayoutParams(int w, int h) {
- super(w, h);
- column = -1;
- span = 1;
- }
-
- /**
- * <p>Sets the child width, height and weight.</p>
- *
- * @param w the desired width
- * @param h the desired height
- * @param initWeight the desired weight
- */
- public LayoutParams(int w, int h, float initWeight) {
- super(w, h, initWeight);
- column = -1;
- span = 1;
- }
-
- /**
- * <p>Sets the child width to {@link android.view.ViewGroup.LayoutParams}
- * and the child height to
- * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}.</p>
- */
- public LayoutParams() {
- super(FILL_PARENT, WRAP_CONTENT);
- column = -1;
- span = 1;
- }
-
- /**
- * <p>Puts the view in the specified column.</p>
- *
- * <p>Sets the child width to {@link android.view.ViewGroup.LayoutParams#FILL_PARENT}
- * and the child height to
- * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}.</p>
- *
- * @param column the column index for the view
- */
- public LayoutParams(int column) {
- this();
- this.column = column;
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(ViewGroup.LayoutParams p) {
- super(p);
- }
-
- /**
- * {@inheritDoc}
- */
- public LayoutParams(MarginLayoutParams source) {
- super(source);
- }
-
- @Override
- protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
- // We don't want to force users to specify a layout_width
- if (a.hasValue(widthAttr)) {
- width = a.getLayoutDimension(widthAttr, "layout_width");
- } else {
- width = FILL_PARENT;
- }
-
- // We don't want to force users to specify a layout_height
- if (a.hasValue(heightAttr)) {
- height = a.getLayoutDimension(heightAttr, "layout_height");
- } else {
- height = WRAP_CONTENT;
- }
- }
- }
-
- // special transparent hierarchy change listener
- private class ChildrenTracker implements OnHierarchyChangeListener {
- private OnHierarchyChangeListener listener;
-
- private void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
- this.listener = listener;
- }
-
- public void onChildViewAdded(View parent, View child) {
- // dirties the index to column map
- mColumnToChildIndex = null;
-
- if (this.listener != null) {
- this.listener.onChildViewAdded(parent, child);
- }
- }
-
- public void onChildViewRemoved(View parent, View child) {
- // dirties the index to column map
- mColumnToChildIndex = null;
-
- if (this.listener != null) {
- this.listener.onChildViewRemoved(parent, child);
- }
- }
- }
-}
diff --git a/core/java/android/widget/TextSwitcher.java b/core/java/android/widget/TextSwitcher.java
deleted file mode 100644
index a8794a3..0000000
--- a/core/java/android/widget/TextSwitcher.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * Specialized {@link android.widget.ViewSwitcher} that contains
- * only children of type {@link android.widget.TextView}.
- *
- * A TextSwitcher is useful to animate a label on screen. Whenever
- * {@link #setText(CharSequence)} is called, TextSwitcher animates the current text
- * out and animates the new text in.
- */
-public class TextSwitcher extends ViewSwitcher {
- /**
- * Creates a new empty TextSwitcher.
- *
- * @param context the application's environment
- */
- public TextSwitcher(Context context) {
- super(context);
- }
-
- /**
- * Creates a new empty TextSwitcher for the given context and with the
- * specified set attributes.
- *
- * @param context the application environment
- * @param attrs a collection of attributes
- */
- public TextSwitcher(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws IllegalArgumentException if child is not an instance of
- * {@link android.widget.TextView}
- */
- @Override
- public void addView(View child, int index, ViewGroup.LayoutParams params) {
- if (!(child instanceof TextView)) {
- throw new IllegalArgumentException(
- "TextSwitcher children must be instances of TextView");
- }
-
- super.addView(child, index, params);
- }
-
- /**
- * Sets the text of the next view and switches to the next view. This can
- * be used to animate the old text out and animate the next text in.
- *
- * @param text the new text to display
- */
- public void setText(CharSequence text) {
- final TextView t = (TextView) getNextView();
- t.setText(text);
- showNext();
- }
-
- /**
- * Sets the text of the text view that is currently showing. This does
- * not perform the animations.
- *
- * @param text the new text to display
- */
- public void setCurrentText(CharSequence text) {
- ((TextView)getCurrentView()).setText(text);
- }
-}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
deleted file mode 100644
index c852be5..0000000
--- a/core/java/android/widget/TextView.java
+++ /dev/null
@@ -1,6507 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.SystemClock;
-import android.os.Message;
-import android.text.BoringLayout;
-import android.text.DynamicLayout;
-import android.text.Editable;
-import android.text.GetChars;
-import android.text.GraphicsOperations;
-import android.text.ClipboardManager;
-import android.text.InputFilter;
-import android.text.Layout;
-import android.text.ParcelableSpan;
-import android.text.Selection;
-import android.text.SpanWatcher;
-import android.text.Spannable;
-import android.text.Spanned;
-import android.text.SpannedString;
-import android.text.SpannableString;
-import android.text.StaticLayout;
-import android.text.TextPaint;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.text.method.DateKeyListener;
-import android.text.method.DateTimeKeyListener;
-import android.text.method.DialerKeyListener;
-import android.text.method.DigitsKeyListener;
-import android.text.method.KeyListener;
-import android.text.method.LinkMovementMethod;
-import android.text.method.MetaKeyKeyListener;
-import android.text.method.MovementMethod;
-import android.text.method.TimeKeyListener;
-
-import android.text.method.PasswordTransformationMethod;
-import android.text.method.SingleLineTransformationMethod;
-import android.text.method.TextKeyListener;
-import android.text.method.TransformationMethod;
-import android.text.style.ParagraphStyle;
-import android.text.style.URLSpan;
-import android.text.style.UpdateAppearance;
-import android.text.util.Linkify;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.FloatMath;
-import android.util.TypedValue;
-import android.view.ContextMenu;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewDebug;
-import android.view.ViewTreeObserver;
-import android.view.ViewGroup.LayoutParams;
-import android.view.animation.AnimationUtils;
-import android.view.inputmethod.BaseInputConnection;
-import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.ExtractedText;
-import android.view.inputmethod.ExtractedTextRequest;
-import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.EditorInfo;
-import android.widget.RemoteViews.RemoteView;
-
-import java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-
-import com.android.internal.util.FastMath;
-import com.android.internal.widget.EditableInputConnection;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-/**
- * Displays text to the user and optionally allows them to edit it. A TextView
- * is a complete text editor, however the basic class is configured to not
- * allow editing; see {@link EditText} for a subclass that configures the text
- * view for editing.
- *
- * <p>
- * <b>XML attributes</b>
- * <p>
- * See {@link android.R.styleable#TextView TextView Attributes},
- * {@link android.R.styleable#View View Attributes}
- *
- * @attr ref android.R.styleable#TextView_text
- * @attr ref android.R.styleable#TextView_bufferType
- * @attr ref android.R.styleable#TextView_hint
- * @attr ref android.R.styleable#TextView_textColor
- * @attr ref android.R.styleable#TextView_textColorHighlight
- * @attr ref android.R.styleable#TextView_textColorHint
- * @attr ref android.R.styleable#TextView_textSize
- * @attr ref android.R.styleable#TextView_textScaleX
- * @attr ref android.R.styleable#TextView_typeface
- * @attr ref android.R.styleable#TextView_textStyle
- * @attr ref android.R.styleable#TextView_cursorVisible
- * @attr ref android.R.styleable#TextView_maxLines
- * @attr ref android.R.styleable#TextView_maxHeight
- * @attr ref android.R.styleable#TextView_lines
- * @attr ref android.R.styleable#TextView_height
- * @attr ref android.R.styleable#TextView_minLines
- * @attr ref android.R.styleable#TextView_minHeight
- * @attr ref android.R.styleable#TextView_maxEms
- * @attr ref android.R.styleable#TextView_maxWidth
- * @attr ref android.R.styleable#TextView_ems
- * @attr ref android.R.styleable#TextView_width
- * @attr ref android.R.styleable#TextView_minEms
- * @attr ref android.R.styleable#TextView_minWidth
- * @attr ref android.R.styleable#TextView_gravity
- * @attr ref android.R.styleable#TextView_scrollHorizontally
- * @attr ref android.R.styleable#TextView_password
- * @attr ref android.R.styleable#TextView_singleLine
- * @attr ref android.R.styleable#TextView_selectAllOnFocus
- * @attr ref android.R.styleable#TextView_includeFontPadding
- * @attr ref android.R.styleable#TextView_maxLength
- * @attr ref android.R.styleable#TextView_shadowColor
- * @attr ref android.R.styleable#TextView_shadowDx
- * @attr ref android.R.styleable#TextView_shadowDy
- * @attr ref android.R.styleable#TextView_shadowRadius
- * @attr ref android.R.styleable#TextView_autoLink
- * @attr ref android.R.styleable#TextView_linksClickable
- * @attr ref android.R.styleable#TextView_numeric
- * @attr ref android.R.styleable#TextView_digits
- * @attr ref android.R.styleable#TextView_phoneNumber
- * @attr ref android.R.styleable#TextView_inputMethod
- * @attr ref android.R.styleable#TextView_capitalize
- * @attr ref android.R.styleable#TextView_autoText
- * @attr ref android.R.styleable#TextView_editable
- * @attr ref android.R.styleable#TextView_drawableTop
- * @attr ref android.R.styleable#TextView_drawableBottom
- * @attr ref android.R.styleable#TextView_drawableRight
- * @attr ref android.R.styleable#TextView_drawableLeft
- * @attr ref android.R.styleable#TextView_lineSpacingExtra
- * @attr ref android.R.styleable#TextView_lineSpacingMultiplier
- * @attr ref android.R.styleable#TextView_marqueeRepeatLimit
- */
-@RemoteView
-public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
- static final String TAG = "TextView";
- static final boolean DEBUG_EXTRACT = false;
-
- private static int PRIORITY = 100;
-
- private ColorStateList mTextColor;
- private int mCurTextColor;
- private ColorStateList mHintTextColor;
- private ColorStateList mLinkTextColor;
- private int mCurHintTextColor;
- private boolean mFreezesText;
- private boolean mFrozenWithFocus;
-
- private boolean mEatTouchRelease = false;
- private boolean mScrolled = false;
-
- private Editable.Factory mEditableFactory = Editable.Factory.getInstance();
- private Spannable.Factory mSpannableFactory = Spannable.Factory.getInstance();
-
- private float mShadowRadius, mShadowDx, mShadowDy;
-
- private static final int PREDRAW_NOT_REGISTERED = 0;
- private static final int PREDRAW_PENDING = 1;
- private static final int PREDRAW_DONE = 2;
- private int mPreDrawState = PREDRAW_NOT_REGISTERED;
-
- private TextUtils.TruncateAt mEllipsize = null;
-
- // Enum for the "typeface" XML parameter.
- // TODO: How can we get this from the XML instead of hardcoding it here?
- private static final int SANS = 1;
- private static final int SERIF = 2;
- private static final int MONOSPACE = 3;
-
- // Bitfield for the "numeric" XML parameter.
- // TODO: How can we get this from the XML instead of hardcoding it here?
- private static final int SIGNED = 2;
- private static final int DECIMAL = 4;
-
- class Drawables {
- final Rect mCompoundRect = new Rect();
- Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight;
- int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight;
- int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight;
- int mDrawablePadding;
- };
- private Drawables mDrawables;
-
- private CharSequence mError;
- private boolean mErrorWasChanged;
- private PopupWindow mPopup;
- /**
- * This flag is set if the TextView tries to display an error before it
- * is attached to the window (so its position is still unknown).
- * It causes the error to be shown later, when onAttachedToWindow()
- * is called.
- */
- private boolean mShowErrorAfterAttach;
-
- private CharWrapper mCharWrapper = null;
-
- private boolean mSelectionMoved = false;
-
- private Marquee mMarquee;
- private boolean mRestartMarquee;
-
- private int mMarqueeRepeatLimit = 3;
-
- class InputContentType {
- String privateContentType;
- Bundle extras;
- }
- InputContentType mInputContentType;
-
- class InputMethodState {
- Rect mCursorRectInWindow = new Rect();
- RectF mTmpRectF = new RectF();
- float[] mTmpOffset = new float[2];
- ExtractedTextRequest mExtracting;
- final ExtractedText mTmpExtracted = new ExtractedText();
- int mBatchEditNesting;
- boolean mCursorChanged;
- boolean mContentChanged;
- int mChangedStart, mChangedEnd, mChangedDelta;
- }
- InputMethodState mInputMethodState;
-
- /*
- * Kick-start the font cache for the zygote process (to pay the cost of
- * initializing freetype for our default font only once).
- */
- static {
- Paint p = new Paint();
- p.setAntiAlias(true);
- // We don't care about the result, just the side-effect of measuring.
- p.measureText("H");
- }
-
- public TextView(Context context) {
- this(context, null);
- }
-
- public TextView(Context context,
- AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.textViewStyle);
- }
-
- public TextView(Context context,
- AttributeSet attrs,
- int defStyle) {
- super(context, attrs, defStyle);
- mText = "";
-
- mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
- // If we get the paint from the skin, we should set it to left, since
- // the layout always wants it to be left.
- // mTextPaint.setTextAlign(Paint.Align.LEFT);
-
- mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-
- mMovement = getDefaultMovementMethod();
- mTransformation = null;
-
- TypedArray a =
- context.obtainStyledAttributes(
- attrs, com.android.internal.R.styleable.TextView, defStyle, 0);
-
- int textColorHighlight = 0;
- ColorStateList textColor = null;
- ColorStateList textColorHint = null;
- ColorStateList textColorLink = null;
- int textSize = 15;
- int typefaceIndex = -1;
- int styleIndex = -1;
-
- /*
- * Look the appearance up without checking first if it exists because
- * almost every TextView has one and it greatly simplifies the logic
- * to be able to parse the appearance first and then let specific tags
- * for this View override it.
- */
- TypedArray appearance = null;
- int ap = a.getResourceId(com.android.internal.R.styleable.TextView_textAppearance, -1);
- if (ap != -1) {
- appearance = context.obtainStyledAttributes(ap,
- com.android.internal.R.styleable.
- TextAppearance);
- }
- if (appearance != null) {
- int n = appearance.getIndexCount();
- for (int i = 0; i < n; i++) {
- int attr = appearance.getIndex(i);
-
- switch (attr) {
- case com.android.internal.R.styleable.TextAppearance_textColorHighlight:
- textColorHighlight = appearance.getColor(attr, textColorHighlight);
- break;
-
- case com.android.internal.R.styleable.TextAppearance_textColor:
- textColor = appearance.getColorStateList(attr);
- break;
-
- case com.android.internal.R.styleable.TextAppearance_textColorHint:
- textColorHint = appearance.getColorStateList(attr);
- break;
-
- case com.android.internal.R.styleable.TextAppearance_textColorLink:
- textColorLink = appearance.getColorStateList(attr);
- break;
-
- case com.android.internal.R.styleable.TextAppearance_textSize:
- textSize = appearance.getDimensionPixelSize(attr, textSize);
- break;
-
- case com.android.internal.R.styleable.TextAppearance_typeface:
- typefaceIndex = appearance.getInt(attr, -1);
- break;
-
- case com.android.internal.R.styleable.TextAppearance_textStyle:
- styleIndex = appearance.getInt(attr, -1);
- break;
- }
- }
-
- appearance.recycle();
- }
-
- boolean editable = getDefaultEditable();
- CharSequence inputMethod = null;
- int numeric = 0;
- CharSequence digits = null;
- boolean phone = false;
- boolean autotext = false;
- int autocap = -1;
- int buffertype = 0;
- boolean selectallonfocus = false;
- Drawable drawableLeft = null, drawableTop = null, drawableRight = null,
- drawableBottom = null;
- int drawablePadding = 0;
- int ellipsize = -1;
- boolean singleLine = false;
- int maxlength = -1;
- CharSequence text = "";
- int shadowcolor = 0;
- float dx = 0, dy = 0, r = 0;
- boolean password = false;
- int contentType = EditorInfo.TYPE_NULL;
-
- int n = a.getIndexCount();
- for (int i = 0; i < n; i++) {
- int attr = a.getIndex(i);
-
- switch (attr) {
- case com.android.internal.R.styleable.TextView_editable:
- editable = a.getBoolean(attr, editable);
- break;
-
- case com.android.internal.R.styleable.TextView_inputMethod:
- inputMethod = a.getText(attr);
- break;
-
- case com.android.internal.R.styleable.TextView_numeric:
- numeric = a.getInt(attr, numeric);
- break;
-
- case com.android.internal.R.styleable.TextView_digits:
- digits = a.getText(attr);
- break;
-
- case com.android.internal.R.styleable.TextView_phoneNumber:
- phone = a.getBoolean(attr, phone);
- break;
-
- case com.android.internal.R.styleable.TextView_autoText:
- autotext = a.getBoolean(attr, autotext);
- break;
-
- case com.android.internal.R.styleable.TextView_capitalize:
- autocap = a.getInt(attr, autocap);
- break;
-
- case com.android.internal.R.styleable.TextView_bufferType:
- buffertype = a.getInt(attr, buffertype);
- break;
-
- case com.android.internal.R.styleable.TextView_selectAllOnFocus:
- selectallonfocus = a.getBoolean(attr, selectallonfocus);
- break;
-
- case com.android.internal.R.styleable.TextView_autoLink:
- mAutoLinkMask = a.getInt(attr, 0);
- break;
-
- case com.android.internal.R.styleable.TextView_linksClickable:
- mLinksClickable = a.getBoolean(attr, true);
- break;
-
- case com.android.internal.R.styleable.TextView_drawableLeft:
- drawableLeft = a.getDrawable(attr);
- break;
-
- case com.android.internal.R.styleable.TextView_drawableTop:
- drawableTop = a.getDrawable(attr);
- break;
-
- case com.android.internal.R.styleable.TextView_drawableRight:
- drawableRight = a.getDrawable(attr);
- break;
-
- case com.android.internal.R.styleable.TextView_drawableBottom:
- drawableBottom = a.getDrawable(attr);
- break;
-
- case com.android.internal.R.styleable.TextView_drawablePadding:
- drawablePadding = a.getDimensionPixelSize(attr, drawablePadding);
- break;
-
- case com.android.internal.R.styleable.TextView_maxLines:
- setMaxLines(a.getInt(attr, -1));
- break;
-
- case com.android.internal.R.styleable.TextView_maxHeight:
- setMaxHeight(a.getDimensionPixelSize(attr, -1));
- break;
-
- case com.android.internal.R.styleable.TextView_lines:
- setLines(a.getInt(attr, -1));
- break;
-
- case com.android.internal.R.styleable.TextView_height:
- setHeight(a.getDimensionPixelSize(attr, -1));
- break;
-
- case com.android.internal.R.styleable.TextView_minLines:
- setMinLines(a.getInt(attr, -1));
- break;
-
- case com.android.internal.R.styleable.TextView_minHeight:
- setMinHeight(a.getDimensionPixelSize(attr, -1));
- break;
-
- case com.android.internal.R.styleable.TextView_maxEms:
- setMaxEms(a.getInt(attr, -1));
- break;
-
- case com.android.internal.R.styleable.TextView_maxWidth:
- setMaxWidth(a.getDimensionPixelSize(attr, -1));
- break;
-
- case com.android.internal.R.styleable.TextView_ems:
- setEms(a.getInt(attr, -1));
- break;
-
- case com.android.internal.R.styleable.TextView_width:
- setWidth(a.getDimensionPixelSize(attr, -1));
- break;
-
- case com.android.internal.R.styleable.TextView_minEms:
- setMinEms(a.getInt(attr, -1));
- break;
-
- case com.android.internal.R.styleable.TextView_minWidth:
- setMinWidth(a.getDimensionPixelSize(attr, -1));
- break;
-
- case com.android.internal.R.styleable.TextView_gravity:
- setGravity(a.getInt(attr, -1));
- break;
-
- case com.android.internal.R.styleable.TextView_hint:
- setHint(a.getText(attr));
- break;
-
- case com.android.internal.R.styleable.TextView_text:
- text = a.getText(attr);
- break;
-
- case com.android.internal.R.styleable.TextView_scrollHorizontally:
- if (a.getBoolean(attr, false)) {
- setHorizontallyScrolling(true);
- }
- break;
-
- case com.android.internal.R.styleable.TextView_singleLine:
- singleLine = a.getBoolean(attr, singleLine);
- break;
-
- case com.android.internal.R.styleable.TextView_ellipsize:
- ellipsize = a.getInt(attr, ellipsize);
- break;
-
- case com.android.internal.R.styleable.TextView_marqueeRepeatLimit:
- setMarqueeRepeatLimit(a.getInt(attr, mMarqueeRepeatLimit));
- break;
-
- case com.android.internal.R.styleable.TextView_includeFontPadding:
- if (!a.getBoolean(attr, true)) {
- setIncludeFontPadding(false);
- }
- break;
-
- case com.android.internal.R.styleable.TextView_cursorVisible:
- if (!a.getBoolean(attr, true)) {
- setCursorVisible(false);
- }
- break;
-
- case com.android.internal.R.styleable.TextView_maxLength:
- maxlength = a.getInt(attr, -1);
- break;
-
- case com.android.internal.R.styleable.TextView_textScaleX:
- setTextScaleX(a.getFloat(attr, 1.0f));
- break;
-
- case com.android.internal.R.styleable.TextView_freezesText:
- mFreezesText = a.getBoolean(attr, false);
- break;
-
- case com.android.internal.R.styleable.TextView_shadowColor:
- shadowcolor = a.getInt(attr, 0);
- break;
-
- case com.android.internal.R.styleable.TextView_shadowDx:
- dx = a.getFloat(attr, 0);
- break;
-
- case com.android.internal.R.styleable.TextView_shadowDy:
- dy = a.getFloat(attr, 0);
- break;
-
- case com.android.internal.R.styleable.TextView_shadowRadius:
- r = a.getFloat(attr, 0);
- break;
-
- case com.android.internal.R.styleable.TextView_enabled:
- setEnabled(a.getBoolean(attr, isEnabled()));
- break;
-
- case com.android.internal.R.styleable.TextView_textColorHighlight:
- textColorHighlight = a.getColor(attr, textColorHighlight);
- break;
-
- case com.android.internal.R.styleable.TextView_textColor:
- textColor = a.getColorStateList(attr);
- break;
-
- case com.android.internal.R.styleable.TextView_textColorHint:
- textColorHint = a.getColorStateList(attr);
- break;
-
- case com.android.internal.R.styleable.TextView_textColorLink:
- textColorLink = a.getColorStateList(attr);
- break;
-
- case com.android.internal.R.styleable.TextView_textSize:
- textSize = a.getDimensionPixelSize(attr, textSize);
- break;
-
- case com.android.internal.R.styleable.TextView_typeface:
- typefaceIndex = a.getInt(attr, typefaceIndex);
- break;
-
- case com.android.internal.R.styleable.TextView_textStyle:
- styleIndex = a.getInt(attr, styleIndex);
- break;
-
- case com.android.internal.R.styleable.TextView_password:
- password = a.getBoolean(attr, password);
- break;
-
- case com.android.internal.R.styleable.TextView_lineSpacingExtra:
- mSpacingAdd = a.getDimensionPixelSize(attr, (int) mSpacingAdd);
- break;
-
- case com.android.internal.R.styleable.TextView_lineSpacingMultiplier:
- mSpacingMult = a.getFloat(attr, mSpacingMult);
- break;
-
- case com.android.internal.R.styleable.TextView_inputType:
- contentType = a.getInt(attr, mInputType);
- break;
-
- case com.android.internal.R.styleable.TextView_editorPrivateContentType:
- setPrivateContentType(a.getString(attr));
- break;
-
- case com.android.internal.R.styleable.TextView_editorExtras:
- try {
- setInputExtras(a.getResourceId(attr, 0));
- } catch (XmlPullParserException e) {
- Log.w("TextView", "Failure reading input extras", e);
- } catch (IOException e) {
- Log.w("TextView", "Failure reading input extras", e);
- }
- break;
- }
- }
- a.recycle();
-
- BufferType bufferType = BufferType.EDITABLE;
-
- if ((contentType&(EditorInfo.TYPE_MASK_CLASS
- |EditorInfo.TYPE_MASK_VARIATION))
- == (EditorInfo.TYPE_CLASS_TEXT
- |EditorInfo.TYPE_TEXT_VARIATION_PASSWORD)) {
- password = true;
- }
-
- if (inputMethod != null) {
- Class c;
-
- try {
- c = Class.forName(inputMethod.toString());
- } catch (ClassNotFoundException ex) {
- throw new RuntimeException(ex);
- }
-
- try {
- mInput = (KeyListener) c.newInstance();
- } catch (InstantiationException ex) {
- throw new RuntimeException(ex);
- } catch (IllegalAccessException ex) {
- throw new RuntimeException(ex);
- }
- try {
- mInputType = contentType != EditorInfo.TYPE_NULL
- ? contentType
- : mInput.getInputType();
- } catch (IncompatibleClassChangeError e) {
- mInputType = EditorInfo.TYPE_CLASS_TEXT;
- }
- } else if (digits != null) {
- mInput = DigitsKeyListener.getInstance(digits.toString());
- mInputType = contentType;
- } else if (contentType != EditorInfo.TYPE_NULL) {
- setInputType(contentType, true);
- singleLine = (contentType&(EditorInfo.TYPE_MASK_CLASS
- | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE)) !=
- (EditorInfo.TYPE_CLASS_TEXT
- | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE);
- } else if (phone) {
- mInput = DialerKeyListener.getInstance();
- contentType = EditorInfo.TYPE_CLASS_PHONE;
- } else if (numeric != 0) {
- mInput = DigitsKeyListener.getInstance((numeric & SIGNED) != 0,
- (numeric & DECIMAL) != 0);
- contentType = EditorInfo.TYPE_CLASS_NUMBER;
- if ((numeric & SIGNED) != 0) {
- contentType |= EditorInfo.TYPE_NUMBER_FLAG_SIGNED;
- }
- if ((numeric & DECIMAL) != 0) {
- contentType |= EditorInfo.TYPE_NUMBER_FLAG_DECIMAL;
- }
- mInputType = contentType;
- } else if (autotext || autocap != -1) {
- TextKeyListener.Capitalize cap;
-
- contentType = EditorInfo.TYPE_CLASS_TEXT;
- if (!singleLine) {
- contentType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
- }
-
- switch (autocap) {
- case 1:
- cap = TextKeyListener.Capitalize.SENTENCES;
- contentType |= EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES;
- break;
-
- case 2:
- cap = TextKeyListener.Capitalize.WORDS;
- contentType |= EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS;
- break;
-
- case 3:
- cap = TextKeyListener.Capitalize.CHARACTERS;
- contentType |= EditorInfo.TYPE_TEXT_FLAG_CAP_CHARACTERS;
- break;
-
- default:
- cap = TextKeyListener.Capitalize.NONE;
- break;
- }
-
- mInput = TextKeyListener.getInstance(autotext, cap);
- mInputType = contentType;
- } else if (editable) {
- mInput = TextKeyListener.getInstance();
- mInputType = EditorInfo.TYPE_CLASS_TEXT;
- } else {
- mInput = null;
-
- switch (buffertype) {
- case 0:
- bufferType = BufferType.NORMAL;
- break;
- case 1:
- bufferType = BufferType.SPANNABLE;
- break;
- case 2:
- bufferType = BufferType.EDITABLE;
- break;
- }
- }
-
- if (password && (mInputType&EditorInfo.TYPE_MASK_CLASS)
- == EditorInfo.TYPE_CLASS_TEXT) {
- mInputType = (mInputType & ~(EditorInfo.TYPE_MASK_VARIATION))
- | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD;
- }
-
- if (selectallonfocus) {
- mSelectAllOnFocus = true;
-
- if (bufferType == BufferType.NORMAL)
- bufferType = BufferType.SPANNABLE;
- }
-
- setCompoundDrawablesWithIntrinsicBounds(
- drawableLeft, drawableTop, drawableRight, drawableBottom);
- setCompoundDrawablePadding(drawablePadding);
-
- if (singleLine) {
- setSingleLine();
-
- if (mInput == null && ellipsize < 0) {
- ellipsize = 3; // END
- }
- }
-
- switch (ellipsize) {
- case 1:
- setEllipsize(TextUtils.TruncateAt.START);
- break;
- case 2:
- setEllipsize(TextUtils.TruncateAt.MIDDLE);
- break;
- case 3:
- setEllipsize(TextUtils.TruncateAt.END);
- break;
- case 4:
- setHorizontalFadingEdgeEnabled(true);
- setEllipsize(TextUtils.TruncateAt.MARQUEE);
- break;
- }
-
- setTextColor(textColor != null ? textColor : ColorStateList.valueOf(0xFF000000));
- setHintTextColor(textColorHint);
- setLinkTextColor(textColorLink);
- if (textColorHighlight != 0) {
- setHighlightColor(textColorHighlight);
- }
- setRawTextSize(textSize);
-
- if (password) {
- setTransformationMethod(PasswordTransformationMethod.getInstance());
- typefaceIndex = MONOSPACE;
- }
-
- setTypefaceByIndex(typefaceIndex, styleIndex);
-
- if (shadowcolor != 0) {
- setShadowLayer(r, dx, dy, shadowcolor);
- }
-
- if (maxlength >= 0) {
- setFilters(new InputFilter[] { new InputFilter.LengthFilter(maxlength) });
- } else {
- setFilters(NO_FILTERS);
- }
-
- setText(text, bufferType);
-
- /*
- * Views are not normally focusable unless specified to be.
- * However, TextViews that have input or movement methods *are*
- * focusable by default.
- */
- a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.View,
- defStyle, 0);
-
- boolean focusable = mMovement != null || mInput != null;
- boolean clickable = focusable;
- boolean longClickable = focusable;
-
- n = a.getIndexCount();
- for (int i = 0; i < n; i++) {
- int attr = a.getIndex(i);
-
- switch (attr) {
- case com.android.internal.R.styleable.View_focusable:
- focusable = a.getBoolean(attr, focusable);
- break;
-
- case com.android.internal.R.styleable.View_clickable:
- clickable = a.getBoolean(attr, clickable);
- break;
-
- case com.android.internal.R.styleable.View_longClickable:
- longClickable = a.getBoolean(attr, longClickable);
- break;
- }
- }
- a.recycle();
-
- setFocusable(focusable);
- setClickable(clickable);
- setLongClickable(longClickable);
- }
-
- private void setTypefaceByIndex(int typefaceIndex, int styleIndex) {
- Typeface tf = null;
- switch (typefaceIndex) {
- case SANS:
- tf = Typeface.SANS_SERIF;
- break;
-
- case SERIF:
- tf = Typeface.SERIF;
- break;
-
- case MONOSPACE:
- tf = Typeface.MONOSPACE;
- break;
- }
-
- setTypeface(tf, styleIndex);
- }
-
- /**
- * Sets the typeface and style in which the text should be displayed,
- * and turns on the fake bold and italic bits in the Paint if the
- * Typeface that you provided does not have all the bits in the
- * style that you specified.
- *
- * @attr ref android.R.styleable#TextView_typeface
- * @attr ref android.R.styleable#TextView_textStyle
- */
- public void setTypeface(Typeface tf, int style) {
- if (style > 0) {
- if (tf == null) {
- tf = Typeface.defaultFromStyle(style);
- } else {
- tf = Typeface.create(tf, style);
- }
-
- setTypeface(tf);
- // now compute what (if any) algorithmic styling is needed
- int typefaceStyle = tf != null ? tf.getStyle() : 0;
- int need = style & ~typefaceStyle;
- mTextPaint.setFakeBoldText((need & Typeface.BOLD) != 0);
- mTextPaint.setTextSkewX((need & Typeface.ITALIC) != 0 ? -0.25f : 0);
- } else {
- mTextPaint.setFakeBoldText(false);
- mTextPaint.setTextSkewX(0);
- setTypeface(tf);
- }
- }
-
- /**
- * Subclasses override this to specify that they have a KeyListener
- * by default even if not specifically called for in the XML options.
- */
- protected boolean getDefaultEditable() {
- return false;
- }
-
- /**
- * Subclasses override this to specify a default movement method.
- */
- protected MovementMethod getDefaultMovementMethod() {
- return null;
- }
-
- /**
- * Return the text the TextView is displaying. If setText() was called with
- * an argument of BufferType.SPANNABLE or BufferType.EDITABLE, you can cast
- * the return value from this method to Spannable or Editable, respectively.
- *
- * Note: The content of the return value should not be modified. If you want
- * a modifiable one, you should make your own copy first.
- */
- @ViewDebug.CapturedViewProperty
- public CharSequence getText() {
- return mText;
- }
-
- /**
- * Returns the length, in characters, of the text managed by this TextView
- */
- public int length() {
- return mText.length();
- }
-
- /**
- * Return the text the TextView is displaying as an Editable object. If
- * the text is not editable, null is returned.
- *
- * @see #getText
- */
- public Editable getEditableText() {
- return (mText instanceof Editable) ? (Editable)mText : null;
- }
-
- /**
- * @return the height of one standard line in pixels. Note that markup
- * within the text can cause individual lines to be taller or shorter
- * than this height, and the layout may contain additional first-
- * or last-line padding.
- */
- public int getLineHeight() {
- return FastMath.round(mTextPaint.getFontMetricsInt(null) * mSpacingMult
- + mSpacingAdd);
- }
-
- /**
- * @return the Layout that is currently being used to display the text.
- * This can be null if the text or width has recently changes.
- */
- public final Layout getLayout() {
- return mLayout;
- }
-
- /**
- * @return the current key listener for this TextView.
- * This will frequently be null for non-EditText TextViews.
- */
- public final KeyListener getKeyListener() {
- return mInput;
- }
-
- /**
- * Sets the key listener to be used with this TextView. This can be null
- * to disallow user input. Note that this method has significant and
- * subtle interactions with soft keyboards and other input method:
- * see {@link KeyListener#getInputType() KeyListener.getContentType()}
- * for important details. Calling this method will replace the current
- * content type of the text view with the content type returned by the
- * key listener.
- * <p>
- * Be warned that if you want a TextView with a key listener or movement
- * method not to be focusable, or if you want a TextView without a
- * key listener or movement method to be focusable, you must call
- * {@link #setFocusable} again after calling this to get the focusability
- * back the way you want it.
- *
- * @attr ref android.R.styleable#TextView_numeric
- * @attr ref android.R.styleable#TextView_digits
- * @attr ref android.R.styleable#TextView_phoneNumber
- * @attr ref android.R.styleable#TextView_inputMethod
- * @attr ref android.R.styleable#TextView_capitalize
- * @attr ref android.R.styleable#TextView_autoText
- */
- public void setKeyListener(KeyListener input) {
- setKeyListenerOnly(input);
- fixFocusableAndClickableSettings();
-
- if (input != null) {
- try {
- mInputType = mInput.getInputType();
- } catch (IncompatibleClassChangeError e) {
- mInputType = EditorInfo.TYPE_CLASS_TEXT;
- }
- if ((mInputType&EditorInfo.TYPE_MASK_CLASS)
- == EditorInfo.TYPE_CLASS_TEXT) {
- if (mSingleLine) {
- mInputType &= ~EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
- } else {
- mInputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
- }
- }
- } else {
- mInputType = EditorInfo.TYPE_NULL;
- }
-
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) imm.restartInput(this);
- }
-
- private void setKeyListenerOnly(KeyListener input) {
- mInput = input;
- if (mInput != null && !(mText instanceof Editable))
- setText(mText);
-
- setFilters((Editable) mText, mFilters);
- }
-
- /**
- * @return the movement method being used for this TextView.
- * This will frequently be null for non-EditText TextViews.
- */
- public final MovementMethod getMovementMethod() {
- return mMovement;
- }
-
- /**
- * Sets the movement method (arrow key handler) to be used for
- * this TextView. This can be null to disallow using the arrow keys
- * to move the cursor or scroll the view.
- * <p>
- * Be warned that if you want a TextView with a key listener or movement
- * method not to be focusable, or if you want a TextView without a
- * key listener or movement method to be focusable, you must call
- * {@link #setFocusable} again after calling this to get the focusability
- * back the way you want it.
- */
- public final void setMovementMethod(MovementMethod movement) {
- mMovement = movement;
-
- if (mMovement != null && !(mText instanceof Spannable))
- setText(mText);
-
- fixFocusableAndClickableSettings();
- }
-
- private void fixFocusableAndClickableSettings() {
- if ((mMovement != null) || mInput != null) {
- setFocusable(true);
- setClickable(true);
- setLongClickable(true);
- } else {
- setFocusable(false);
- setClickable(false);
- setLongClickable(false);
- }
- }
-
- /**
- * @return the current transformation method for this TextView.
- * This will frequently be null except for single-line and password
- * fields.
- */
- public final TransformationMethod getTransformationMethod() {
- return mTransformation;
- }
-
- /**
- * Sets the transformation that is applied to the text that this
- * TextView is displaying.
- *
- * @attr ref android.R.styleable#TextView_password
- * @attr ref android.R.styleable#TextView_singleLine
- */
- public final void setTransformationMethod(TransformationMethod method) {
- if (mTransformation != null) {
- if (mText instanceof Spannable) {
- ((Spannable) mText).removeSpan(mTransformation);
- }
- }
-
- mTransformation = method;
-
- setText(mText);
- }
-
- /**
- * Returns the top padding of the view, plus space for the top
- * Drawable if any.
- */
- public int getCompoundPaddingTop() {
- final Drawables dr = mDrawables;
- if (dr == null || dr.mDrawableTop == null) {
- return mPaddingTop;
- } else {
- return mPaddingTop + dr.mDrawablePadding + dr.mDrawableSizeTop;
- }
- }
-
- /**
- * Returns the bottom padding of the view, plus space for the bottom
- * Drawable if any.
- */
- public int getCompoundPaddingBottom() {
- final Drawables dr = mDrawables;
- if (dr == null || dr.mDrawableBottom == null) {
- return mPaddingBottom;
- } else {
- return mPaddingBottom + dr.mDrawablePadding + dr.mDrawableSizeBottom;
- }
- }
-
- /**
- * Returns the left padding of the view, plus space for the left
- * Drawable if any.
- */
- public int getCompoundPaddingLeft() {
- final Drawables dr = mDrawables;
- if (dr == null || dr.mDrawableLeft == null) {
- return mPaddingLeft;
- } else {
- return mPaddingLeft + dr.mDrawablePadding + dr.mDrawableSizeLeft;
- }
- }
-
- /**
- * Returns the right padding of the view, plus space for the right
- * Drawable if any.
- */
- public int getCompoundPaddingRight() {
- final Drawables dr = mDrawables;
- if (dr == null || dr.mDrawableRight == null) {
- return mPaddingRight;
- } else {
- return mPaddingRight + dr.mDrawablePadding + dr.mDrawableSizeRight;
- }
- }
-
- /**
- * Returns the extended top padding of the view, including both the
- * top Drawable if any and any extra space to keep more than maxLines
- * of text from showing. It is only valid to call this after measuring.
- */
- public int getExtendedPaddingTop() {
- if (mMaxMode != LINES) {
- return getCompoundPaddingTop();
- }
-
- if (mLayout.getLineCount() <= mMaximum) {
- return getCompoundPaddingTop();
- }
-
- int top = getCompoundPaddingTop();
- int bottom = getCompoundPaddingBottom();
- int viewht = getHeight() - top - bottom;
- int layoutht = mLayout.getLineTop(mMaximum);
-
- if (layoutht >= viewht) {
- return top;
- }
-
- final int gravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
- if (gravity == Gravity.TOP) {
- return top;
- } else if (gravity == Gravity.BOTTOM) {
- return top + viewht - layoutht;
- } else { // (gravity == Gravity.CENTER_VERTICAL)
- return top + (viewht - layoutht) / 2;
- }
- }
-
- /**
- * Returns the extended bottom padding of the view, including both the
- * bottom Drawable if any and any extra space to keep more than maxLines
- * of text from showing. It is only valid to call this after measuring.
- */
- public int getExtendedPaddingBottom() {
- if (mMaxMode != LINES) {
- return getCompoundPaddingBottom();
- }
-
- if (mLayout.getLineCount() <= mMaximum) {
- return getCompoundPaddingBottom();
- }
-
- int top = getCompoundPaddingTop();
- int bottom = getCompoundPaddingBottom();
- int viewht = getHeight() - top - bottom;
- int layoutht = mLayout.getLineTop(mMaximum);
-
- if (layoutht >= viewht) {
- return bottom;
- }
-
- final int gravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
- if (gravity == Gravity.TOP) {
- return bottom + viewht - layoutht;
- } else if (gravity == Gravity.BOTTOM) {
- return bottom;
- } else { // (gravity == Gravity.CENTER_VERTICAL)
- return bottom + (viewht - layoutht) / 2;
- }
- }
-
- /**
- * Returns the total left padding of the view, including the left
- * Drawable if any.
- */
- public int getTotalPaddingLeft() {
- return getCompoundPaddingLeft();
- }
-
- /**
- * Returns the total right padding of the view, including the right
- * Drawable if any.
- */
- public int getTotalPaddingRight() {
- return getCompoundPaddingRight();
- }
-
- /**
- * Returns the total top padding of the view, including the top
- * Drawable if any, the extra space to keep more than maxLines
- * from showing, and the vertical offset for gravity, if any.
- */
- public int getTotalPaddingTop() {
- return getExtendedPaddingTop() + getVerticalOffset(true);
- }
-
- /**
- * Returns the total bottom padding of the view, including the bottom
- * Drawable if any, the extra space to keep more than maxLines
- * from showing, and the vertical offset for gravity, if any.
- */
- public int getTotalPaddingBottom() {
- return getExtendedPaddingBottom() + getBottomVerticalOffset(true);
- }
-
- /**
- * Sets the Drawables (if any) to appear to the left of, above,
- * to the right of, and below the text. Use null if you do not
- * want a Drawable there. The Drawables must already have had
- * {@link Drawable#setBounds} called.
- *
- * @attr ref android.R.styleable#TextView_drawableLeft
- * @attr ref android.R.styleable#TextView_drawableTop
- * @attr ref android.R.styleable#TextView_drawableRight
- * @attr ref android.R.styleable#TextView_drawableBottom
- */
- public void setCompoundDrawables(Drawable left, Drawable top,
- Drawable right, Drawable bottom) {
- Drawables dr = mDrawables;
-
- final boolean drawables = left != null || top != null
- || right != null || bottom != null;
-
- if (!drawables) {
- // Clearing drawables... can we free the data structure?
- if (dr != null) {
- if (dr.mDrawablePadding == 0) {
- mDrawables = null;
- } else {
- // We need to retain the last set padding, so just clear
- // out all of the fields in the existing structure.
- dr.mDrawableLeft = null;
- dr.mDrawableTop = null;
- dr.mDrawableRight = null;
- dr.mDrawableBottom = null;
- dr.mDrawableSizeLeft = dr.mDrawableHeightLeft = 0;
- dr.mDrawableSizeRight = dr.mDrawableHeightRight = 0;
- dr.mDrawableSizeTop = dr.mDrawableWidthTop = 0;
- dr.mDrawableSizeBottom = dr.mDrawableWidthBottom = 0;
- }
- }
- } else {
- if (dr == null) {
- mDrawables = dr = new Drawables();
- }
-
- dr.mDrawableLeft = left;
- dr.mDrawableTop = top;
- dr.mDrawableRight = right;
- dr.mDrawableBottom = bottom;
-
- final Rect compoundRect = dr.mCompoundRect;
- int[] state = null;
-
- state = getDrawableState();
-
- if (left != null) {
- left.setState(state);
- left.copyBounds(compoundRect);
- dr.mDrawableSizeLeft = compoundRect.width();
- dr.mDrawableHeightLeft = compoundRect.height();
- } else {
- dr.mDrawableSizeLeft = dr.mDrawableHeightLeft = 0;
- }
-
- if (right != null) {
- right.setState(state);
- right.copyBounds(compoundRect);
- dr.mDrawableSizeRight = compoundRect.width();
- dr.mDrawableHeightRight = compoundRect.height();
- } else {
- dr.mDrawableSizeRight = dr.mDrawableHeightRight = 0;
- }
-
- if (top != null) {
- top.setState(state);
- top.copyBounds(compoundRect);
- dr.mDrawableSizeTop = compoundRect.height();
- dr.mDrawableWidthTop = compoundRect.width();
- } else {
- dr.mDrawableSizeTop = dr.mDrawableWidthTop = 0;
- }
-
- if (bottom != null) {
- bottom.setState(state);
- bottom.copyBounds(compoundRect);
- dr.mDrawableSizeBottom = compoundRect.height();
- dr.mDrawableWidthBottom = compoundRect.width();
- } else {
- dr.mDrawableSizeBottom = dr.mDrawableWidthBottom = 0;
- }
- }
-
- invalidate();
- requestLayout();
- }
-
- /**
- * Sets the Drawables (if any) to appear to the left of, above,
- * to the right of, and below the text. Use 0 if you do not
- * want a Drawable there. The Drawables' bounds will be set to
- * their intrinsic bounds.
- *
- * @param left Resource identifier of the left Drawable.
- * @param top Resource identifier of the top Drawable.
- * @param right Resource identifier of the right Drawable.
- * @param bottom Resource identifier of the bottom Drawable.
- *
- * @attr ref android.R.styleable#TextView_drawableLeft
- * @attr ref android.R.styleable#TextView_drawableTop
- * @attr ref android.R.styleable#TextView_drawableRight
- * @attr ref android.R.styleable#TextView_drawableBottom
- */
- public void setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom) {
- final Resources resources = getContext().getResources();
- setCompoundDrawables(left != 0 ? resources.getDrawable(left) : null,
- top != 0 ? resources.getDrawable(top) : null,
- right != 0 ? resources.getDrawable(right) : null,
- bottom != 0 ? resources.getDrawable(bottom) : null);
- }
-
- /**
- * Sets the Drawables (if any) to appear to the left of, above,
- * to the right of, and below the text. Use null if you do not
- * want a Drawable there. The Drawables' bounds will be set to
- * their intrinsic bounds.
- *
- * @attr ref android.R.styleable#TextView_drawableLeft
- * @attr ref android.R.styleable#TextView_drawableTop
- * @attr ref android.R.styleable#TextView_drawableRight
- * @attr ref android.R.styleable#TextView_drawableBottom
- */
- public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top,
- Drawable right, Drawable bottom) {
-
- if (left != null) {
- left.setBounds(0, 0, left.getIntrinsicWidth(), left.getIntrinsicHeight());
- }
- if (right != null) {
- right.setBounds(0, 0, right.getIntrinsicWidth(), right.getIntrinsicHeight());
- }
- if (top != null) {
- top.setBounds(0, 0, top.getIntrinsicWidth(), top.getIntrinsicHeight());
- }
- if (bottom != null) {
- bottom.setBounds(0, 0, bottom.getIntrinsicWidth(), bottom.getIntrinsicHeight());
- }
- setCompoundDrawables(left, top, right, bottom);
- }
-
- /**
- * Returns drawables for the left, top, right, and bottom borders.
- */
- public Drawable[] getCompoundDrawables() {
- final Drawables dr = mDrawables;
- if (dr != null) {
- return new Drawable[] {
- dr.mDrawableLeft, dr.mDrawableTop, dr.mDrawableRight, dr.mDrawableBottom
- };
- } else {
- return new Drawable[] { null, null, null, null };
- }
- }
-
- /**
- * Sets the size of the padding between the compound drawables and
- * the text.
- *
- * @attr ref android.R.styleable#TextView_drawablePadding
- */
- public void setCompoundDrawablePadding(int pad) {
- Drawables dr = mDrawables;
- if (pad == 0) {
- if (dr != null) {
- dr.mDrawablePadding = pad;
- }
- } else {
- if (dr == null) {
- mDrawables = dr = new Drawables();
- }
- dr.mDrawablePadding = pad;
- }
-
- invalidate();
- requestLayout();
- }
-
- /**
- * Returns the padding between the compound drawables and the text.
- */
- public int getCompoundDrawablePadding() {
- final Drawables dr = mDrawables;
- return dr != null ? dr.mDrawablePadding : 0;
- }
-
- @Override
- public void setPadding(int left, int top, int right, int bottom) {
- if (left != getPaddingLeft() ||
- right != getPaddingRight() ||
- top != getPaddingTop() ||
- bottom != getPaddingBottom()) {
- nullLayouts();
- }
-
- // the super call will requestLayout()
- super.setPadding(left, top, right, bottom);
- invalidate();
- }
-
- /**
- * Gets the autolink mask of the text. See {@link
- * android.text.util.Linkify#ALL Linkify.ALL} and peers for
- * possible values.
- *
- * @attr ref android.R.styleable#TextView_autoLink
- */
- public final int getAutoLinkMask() {
- return mAutoLinkMask;
- }
-
- /**
- * Sets the text color, size, style, hint color, and highlight color
- * from the specified TextAppearance resource.
- */
- public void setTextAppearance(Context context, int resid) {
- TypedArray appearance =
- context.obtainStyledAttributes(resid,
- com.android.internal.R.styleable.TextAppearance);
-
- int color;
- ColorStateList colors;
- int ts;
-
- color = appearance.getColor(com.android.internal.R.styleable.TextAppearance_textColorHighlight, 0);
- if (color != 0) {
- setHighlightColor(color);
- }
-
- colors = appearance.getColorStateList(com.android.internal.R.styleable.
- TextAppearance_textColor);
- if (colors != null) {
- setTextColor(colors);
- }
-
- ts = appearance.getDimensionPixelSize(com.android.internal.R.styleable.
- TextAppearance_textSize, 0);
- if (ts != 0) {
- setRawTextSize(ts);
- }
-
- colors = appearance.getColorStateList(com.android.internal.R.styleable.
- TextAppearance_textColorHint);
- if (colors != null) {
- setHintTextColor(colors);
- }
-
- colors = appearance.getColorStateList(com.android.internal.R.styleable.
- TextAppearance_textColorLink);
- if (colors != null) {
- setLinkTextColor(colors);
- }
-
- int typefaceIndex, styleIndex;
-
- typefaceIndex = appearance.getInt(com.android.internal.R.styleable.
- TextAppearance_typeface, -1);
- styleIndex = appearance.getInt(com.android.internal.R.styleable.
- TextAppearance_textStyle, -1);
-
- setTypefaceByIndex(typefaceIndex, styleIndex);
- appearance.recycle();
- }
-
- /**
- * @return the size (in pixels) of the default text size in this TextView.
- */
- public float getTextSize() {
- return mTextPaint.getTextSize();
- }
-
- /**
- * Set the default text size to the given value, interpreted as "scaled
- * pixel" units. This size is adjusted based on the current density and
- * user font size preference.
- *
- * @param size The scaled pixel size.
- *
- * @attr ref android.R.styleable#TextView_textSize
- */
- @android.view.RemotableViewMethod
- public void setTextSize(float size) {
- setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
- }
-
- /**
- * Set the default text size to a given unit and value. See {@link
- * TypedValue} for the possible dimension units.
- *
- * @param unit The desired dimension unit.
- * @param size The desired size in the given units.
- *
- * @attr ref android.R.styleable#TextView_textSize
- */
- public void setTextSize(int unit, float size) {
- Context c = getContext();
- Resources r;
-
- if (c == null)
- r = Resources.getSystem();
- else
- r = c.getResources();
-
- setRawTextSize(TypedValue.applyDimension(
- unit, size, r.getDisplayMetrics()));
- }
-
- private void setRawTextSize(float size) {
- if (size != mTextPaint.getTextSize()) {
- mTextPaint.setTextSize(size);
-
- if (mLayout != null) {
- nullLayouts();
- requestLayout();
- invalidate();
- }
- }
- }
-
- /**
- * @return the extent by which text is currently being stretched
- * horizontally. This will usually be 1.
- */
- public float getTextScaleX() {
- return mTextPaint.getTextScaleX();
- }
-
- /**
- * Sets the extent by which text should be stretched horizontally.
- *
- * @attr ref android.R.styleable#TextView_textScaleX
- */
- @android.view.RemotableViewMethod
- public void setTextScaleX(float size) {
- if (size != mTextPaint.getTextScaleX()) {
- mTextPaint.setTextScaleX(size);
-
- if (mLayout != null) {
- nullLayouts();
- requestLayout();
- invalidate();
- }
- }
- }
-
- /**
- * Sets the typeface and style in which the text should be displayed.
- * Note that not all Typeface families actually have bold and italic
- * variants, so you may need to use
- * {@link #setTypeface(Typeface, int)} to get the appearance
- * that you actually want.
- *
- * @attr ref android.R.styleable#TextView_typeface
- * @attr ref android.R.styleable#TextView_textStyle
- */
- public void setTypeface(Typeface tf) {
- if (mTextPaint.getTypeface() != tf) {
- mTextPaint.setTypeface(tf);
-
- if (mLayout != null) {
- nullLayouts();
- requestLayout();
- invalidate();
- }
- }
- }
-
- /**
- * @return the current typeface and style in which the text is being
- * displayed.
- */
- public Typeface getTypeface() {
- return mTextPaint.getTypeface();
- }
-
- /**
- * Sets the text color for all the states (normal, selected,
- * focused) to be this color.
- *
- * @attr ref android.R.styleable#TextView_textColor
- */
- @android.view.RemotableViewMethod
- public void setTextColor(int color) {
- mTextColor = ColorStateList.valueOf(color);
- updateTextColors();
- }
-
- /**
- * Sets the text color.
- *
- * @attr ref android.R.styleable#TextView_textColor
- */
- public void setTextColor(ColorStateList colors) {
- if (colors == null) {
- throw new NullPointerException();
- }
-
- mTextColor = colors;
- updateTextColors();
- }
-
- /**
- * Return the set of text colors.
- *
- * @return Returns the set of text colors.
- */
- public final ColorStateList getTextColors() {
- return mTextColor;
- }
-
- /**
- * <p>Return the current color selected for normal text.</p>
- *
- * @return Returns the current text color.
- */
- public final int getCurrentTextColor() {
- return mCurTextColor;
- }
-
- /**
- * Sets the color used to display the selection highlight.
- *
- * @attr ref android.R.styleable#TextView_textColorHighlight
- */
- @android.view.RemotableViewMethod
- public void setHighlightColor(int color) {
- if (mHighlightColor != color) {
- mHighlightColor = color;
- invalidate();
- }
- }
-
- /**
- * Gives the text a shadow of the specified radius and color, the specified
- * distance from its normal position.
- *
- * @attr ref android.R.styleable#TextView_shadowColor
- * @attr ref android.R.styleable#TextView_shadowDx
- * @attr ref android.R.styleable#TextView_shadowDy
- * @attr ref android.R.styleable#TextView_shadowRadius
- */
- public void setShadowLayer(float radius, float dx, float dy, int color) {
- mTextPaint.setShadowLayer(radius, dx, dy, color);
-
- mShadowRadius = radius;
- mShadowDx = dx;
- mShadowDy = dy;
-
- invalidate();
- }
-
- /**
- * @return the base paint used for the text. Please use this only to
- * consult the Paint's properties and not to change them.
- */
- public TextPaint getPaint() {
- return mTextPaint;
- }
-
- /**
- * Sets the autolink mask of the text. See {@link
- * android.text.util.Linkify#ALL Linkify.ALL} and peers for
- * possible values.
- *
- * @attr ref android.R.styleable#TextView_autoLink
- */
- @android.view.RemotableViewMethod
- public final void setAutoLinkMask(int mask) {
- mAutoLinkMask = mask;
- }
-
- /**
- * Sets whether the movement method will automatically be set to
- * {@link LinkMovementMethod} if {@link #setAutoLinkMask} has been
- * set to nonzero and links are detected in {@link #setText}.
- * The default is true.
- *
- * @attr ref android.R.styleable#TextView_linksClickable
- */
- @android.view.RemotableViewMethod
- public final void setLinksClickable(boolean whether) {
- mLinksClickable = whether;
- }
-
- /**
- * Returns whether the movement method will automatically be set to
- * {@link LinkMovementMethod} if {@link #setAutoLinkMask} has been
- * set to nonzero and links are detected in {@link #setText}.
- * The default is true.
- *
- * @attr ref android.R.styleable#TextView_linksClickable
- */
- public final boolean getLinksClickable() {
- return mLinksClickable;
- }
-
- /**
- * Returns the list of URLSpans attached to the text
- * (by {@link Linkify} or otherwise) if any. You can call
- * {@link URLSpan#getURL} on them to find where they link to
- * or use {@link Spanned#getSpanStart} and {@link Spanned#getSpanEnd}
- * to find the region of the text they are attached to.
- */
- public URLSpan[] getUrls() {
- if (mText instanceof Spanned) {
- return ((Spanned) mText).getSpans(0, mText.length(), URLSpan.class);
- } else {
- return new URLSpan[0];
- }
- }
-
- /**
- * Sets the color of the hint text.
- *
- * @attr ref android.R.styleable#TextView_textColorHint
- */
- @android.view.RemotableViewMethod
- public final void setHintTextColor(int color) {
- mHintTextColor = ColorStateList.valueOf(color);
- updateTextColors();
- }
-
- /**
- * Sets the color of the hint text.
- *
- * @attr ref android.R.styleable#TextView_textColorHint
- */
- public final void setHintTextColor(ColorStateList colors) {
- mHintTextColor = colors;
- updateTextColors();
- }
-
- /**
- * <p>Return the color used to paint the hint text.</p>
- *
- * @return Returns the list of hint text colors.
- */
- public final ColorStateList getHintTextColors() {
- return mHintTextColor;
- }
-
- /**
- * <p>Return the current color selected to paint the hint text.</p>
- *
- * @return Returns the current hint text color.
- */
- public final int getCurrentHintTextColor() {
- return mHintTextColor != null ? mCurHintTextColor : mCurTextColor;
- }
-
- /**
- * Sets the color of links in the text.
- *
- * @attr ref android.R.styleable#TextView_textColorLink
- */
- @android.view.RemotableViewMethod
- public final void setLinkTextColor(int color) {
- mLinkTextColor = ColorStateList.valueOf(color);
- updateTextColors();
- }
-
- /**
- * Sets the color of links in the text.
- *
- * @attr ref android.R.styleable#TextView_textColorLink
- */
- public final void setLinkTextColor(ColorStateList colors) {
- mLinkTextColor = colors;
- updateTextColors();
- }
-
- /**
- * <p>Returns the color used to paint links in the text.</p>
- *
- * @return Returns the list of link text colors.
- */
- public final ColorStateList getLinkTextColors() {
- return mLinkTextColor;
- }
-
- /**
- * Sets the horizontal alignment of the text and the
- * vertical gravity that will be used when there is extra space
- * in the TextView beyond what is required for the text itself.
- *
- * @see android.view.Gravity
- * @attr ref android.R.styleable#TextView_gravity
- */
- public void setGravity(int gravity) {
- if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
- gravity |= Gravity.LEFT;
- }
- if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
- gravity |= Gravity.TOP;
- }
-
- boolean newLayout = false;
-
- if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) !=
- (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK)) {
- newLayout = true;
- }
-
- if (gravity != mGravity) {
- invalidate();
- }
-
- mGravity = gravity;
-
- if (mLayout != null && newLayout) {
- // XXX this is heavy-handed because no actual content changes.
- int want = mLayout.getWidth();
- int hintWant = mHintLayout == null ? 0 : mHintLayout.getWidth();
-
- makeNewLayout(want, hintWant, UNKNOWN_BORING, UNKNOWN_BORING,
- mRight - mLeft - getCompoundPaddingLeft() -
- getCompoundPaddingRight(), true);
- }
- }
-
- /**
- * Returns the horizontal and vertical alignment of this TextView.
- *
- * @see android.view.Gravity
- * @attr ref android.R.styleable#TextView_gravity
- */
- public int getGravity() {
- return mGravity;
- }
-
- /**
- * @return the flags on the Paint being used to display the text.
- * @see Paint#getFlags
- */
- public int getPaintFlags() {
- return mTextPaint.getFlags();
- }
-
- /**
- * Sets flags on the Paint being used to display the text and
- * reflows the text if they are different from the old flags.
- * @see Paint#setFlags
- */
- @android.view.RemotableViewMethod
- public void setPaintFlags(int flags) {
- if (mTextPaint.getFlags() != flags) {
- mTextPaint.setFlags(flags);
-
- if (mLayout != null) {
- nullLayouts();
- requestLayout();
- invalidate();
- }
- }
- }
-
- /**
- * Sets whether the text should be allowed to be wider than the
- * View is. If false, it will be wrapped to the width of the View.
- *
- * @attr ref android.R.styleable#TextView_scrollHorizontally
- */
- public void setHorizontallyScrolling(boolean whether) {
- mHorizontallyScrolling = whether;
-
- if (mLayout != null) {
- nullLayouts();
- requestLayout();
- invalidate();
- }
- }
-
- /**
- * Makes the TextView at least this many lines tall
- *
- * @attr ref android.R.styleable#TextView_minLines
- */
- @android.view.RemotableViewMethod
- public void setMinLines(int minlines) {
- mMinimum = minlines;
- mMinMode = LINES;
-
- requestLayout();
- invalidate();
- }
-
- /**
- * Makes the TextView at least this many pixels tall
- *
- * @attr ref android.R.styleable#TextView_minHeight
- */
- @android.view.RemotableViewMethod
- public void setMinHeight(int minHeight) {
- mMinimum = minHeight;
- mMinMode = PIXELS;
-
- requestLayout();
- invalidate();
- }
-
- /**
- * Makes the TextView at most this many lines tall
- *
- * @attr ref android.R.styleable#TextView_maxLines
- */
- @android.view.RemotableViewMethod
- public void setMaxLines(int maxlines) {
- mMaximum = maxlines;
- mMaxMode = LINES;
-
- requestLayout();
- invalidate();
- }
-
- /**
- * Makes the TextView at most this many pixels tall
- *
- * @attr ref android.R.styleable#TextView_maxHeight
- */
- @android.view.RemotableViewMethod
- public void setMaxHeight(int maxHeight) {
- mMaximum = maxHeight;
- mMaxMode = PIXELS;
-
- requestLayout();
- invalidate();
- }
-
- /**
- * Makes the TextView exactly this many lines tall
- *
- * @attr ref android.R.styleable#TextView_lines
- */
- @android.view.RemotableViewMethod
- public void setLines(int lines) {
- mMaximum = mMinimum = lines;
- mMaxMode = mMinMode = LINES;
-
- requestLayout();
- invalidate();
- }
-
- /**
- * Makes the TextView exactly this many pixels tall.
- * You could do the same thing by specifying this number in the
- * LayoutParams.
- *
- * @attr ref android.R.styleable#TextView_height
- */
- @android.view.RemotableViewMethod
- public void setHeight(int pixels) {
- mMaximum = mMinimum = pixels;
- mMaxMode = mMinMode = PIXELS;
-
- requestLayout();
- invalidate();
- }
-
- /**
- * Makes the TextView at least this many ems wide
- *
- * @attr ref android.R.styleable#TextView_minEms
- */
- @android.view.RemotableViewMethod
- public void setMinEms(int minems) {
- mMinWidth = minems;
- mMinWidthMode = EMS;
-
- requestLayout();
- invalidate();
- }
-
- /**
- * Makes the TextView at least this many pixels wide
- *
- * @attr ref android.R.styleable#TextView_minWidth
- */
- @android.view.RemotableViewMethod
- public void setMinWidth(int minpixels) {
- mMinWidth = minpixels;
- mMinWidthMode = PIXELS;
-
- requestLayout();
- invalidate();
- }
-
- /**
- * Makes the TextView at most this many ems wide
- *
- * @attr ref android.R.styleable#TextView_maxEms
- */
- @android.view.RemotableViewMethod
- public void setMaxEms(int maxems) {
- mMaxWidth = maxems;
- mMaxWidthMode = EMS;
-
- requestLayout();
- invalidate();
- }
-
- /**
- * Makes the TextView at most this many pixels wide
- *
- * @attr ref android.R.styleable#TextView_maxWidth
- */
- @android.view.RemotableViewMethod
- public void setMaxWidth(int maxpixels) {
- mMaxWidth = maxpixels;
- mMaxWidthMode = PIXELS;
-
- requestLayout();
- invalidate();
- }
-
- /**
- * Makes the TextView exactly this many ems wide
- *
- * @attr ref android.R.styleable#TextView_ems
- */
- @android.view.RemotableViewMethod
- public void setEms(int ems) {
- mMaxWidth = mMinWidth = ems;
- mMaxWidthMode = mMinWidthMode = EMS;
-
- requestLayout();
- invalidate();
- }
-
- /**
- * Makes the TextView exactly this many pixels wide.
- * You could do the same thing by specifying this number in the
- * LayoutParams.
- *
- * @attr ref android.R.styleable#TextView_width
- */
- @android.view.RemotableViewMethod
- public void setWidth(int pixels) {
- mMaxWidth = mMinWidth = pixels;
- mMaxWidthMode = mMinWidthMode = PIXELS;
-
- requestLayout();
- invalidate();
- }
-
-
- /**
- * Sets line spacing for this TextView. Each line will have its height
- * multiplied by <code>mult</code> and have <code>add</code> added to it.
- *
- * @attr ref android.R.styleable#TextView_lineSpacingExtra
- * @attr ref android.R.styleable#TextView_lineSpacingMultiplier
- */
- public void setLineSpacing(float add, float mult) {
- mSpacingMult = mult;
- mSpacingAdd = add;
-
- if (mLayout != null) {
- nullLayouts();
- requestLayout();
- invalidate();
- }
- }
-
- /**
- * Convenience method: Append the specified text to the TextView's
- * display buffer, upgrading it to BufferType.EDITABLE if it was
- * not already editable.
- */
- public final void append(CharSequence text) {
- append(text, 0, text.length());
- }
-
- /**
- * Convenience method: Append the specified text slice to the TextView's
- * display buffer, upgrading it to BufferType.EDITABLE if it was
- * not already editable.
- */
- public void append(CharSequence text, int start, int end) {
- if (!(mText instanceof Editable)) {
- setText(mText, BufferType.EDITABLE);
- }
-
- ((Editable) mText).append(text, start, end);
- }
-
- private void updateTextColors() {
- boolean inval = false;
- int color = mTextColor.getColorForState(getDrawableState(), 0);
- if (color != mCurTextColor) {
- mCurTextColor = color;
- inval = true;
- }
- if (mLinkTextColor != null) {
- color = mLinkTextColor.getColorForState(getDrawableState(), 0);
- if (color != mTextPaint.linkColor) {
- mTextPaint.linkColor = color;
- inval = true;
- }
- }
- if (mHintTextColor != null) {
- color = mHintTextColor.getColorForState(getDrawableState(), 0);
- if (color != mCurHintTextColor && mText.length() == 0) {
- mCurHintTextColor = color;
- inval = true;
- }
- }
- if (inval) {
- invalidate();
- }
- }
-
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
- if (mTextColor != null && mTextColor.isStateful()
- || (mHintTextColor != null && mHintTextColor.isStateful())
- || (mLinkTextColor != null && mLinkTextColor.isStateful())) {
- updateTextColors();
- }
-
- final Drawables dr = mDrawables;
- if (dr != null) {
- int[] state = getDrawableState();
- if (dr.mDrawableTop != null && dr.mDrawableTop.isStateful()) {
- dr.mDrawableTop.setState(state);
- }
- if (dr.mDrawableBottom != null && dr.mDrawableBottom.isStateful()) {
- dr.mDrawableBottom.setState(state);
- }
- if (dr.mDrawableLeft != null && dr.mDrawableLeft.isStateful()) {
- dr.mDrawableLeft.setState(state);
- }
- if (dr.mDrawableRight != null && dr.mDrawableRight.isStateful()) {
- dr.mDrawableRight.setState(state);
- }
- }
- }
-
- /**
- * User interface state that is stored by TextView for implementing
- * {@link View#onSaveInstanceState}.
- */
- public static class SavedState extends BaseSavedState {
- int selStart;
- int selEnd;
- CharSequence text;
- boolean frozenWithFocus;
-
- SavedState(Parcelable superState) {
- super(superState);
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- super.writeToParcel(out, flags);
- out.writeInt(selStart);
- out.writeInt(selEnd);
- out.writeInt(frozenWithFocus ? 1 : 0);
- TextUtils.writeToParcel(text, out, flags);
- }
-
- @Override
- public String toString() {
- String str = "TextView.SavedState{"
- + Integer.toHexString(System.identityHashCode(this))
- + " start=" + selStart + " end=" + selEnd;
- if (text != null) {
- str += " text=" + text;
- }
- return str + "}";
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR
- = new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
-
- private SavedState(Parcel in) {
- super(in);
- selStart = in.readInt();
- selEnd = in.readInt();
- frozenWithFocus = (in.readInt() != 0);
- text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
- }
- }
-
- @Override
- public Parcelable onSaveInstanceState() {
- Parcelable superState = super.onSaveInstanceState();
-
- // Save state if we are forced to
- boolean save = mFreezesText;
- int start = 0;
- int end = 0;
-
- if (mText != null) {
- start = Selection.getSelectionStart(mText);
- end = Selection.getSelectionEnd(mText);
- if (start >= 0 || end >= 0) {
- // Or save state if there is a selection
- save = true;
- }
- }
-
- if (save) {
- SavedState ss = new SavedState(superState);
- // XXX Should also save the current scroll position!
- ss.selStart = start;
- ss.selEnd = end;
-
- if (mText instanceof Spanned) {
- /*
- * Calling setText() strips off any ChangeWatchers;
- * strip them now to avoid leaking references.
- * But do it to a copy so that if there are any
- * further changes to the text of this view, it
- * won't get into an inconsistent state.
- */
-
- Spannable sp = new SpannableString(mText);
-
- for (ChangeWatcher cw :
- sp.getSpans(0, sp.length(), ChangeWatcher.class)) {
- sp.removeSpan(cw);
- }
-
- ss.text = sp;
- } else {
- ss.text = mText.toString();
- }
-
- if (isFocused() && start >= 0 && end >= 0) {
- ss.frozenWithFocus = true;
- }
-
- return ss;
- }
-
- return superState;
- }
-
- @Override
- public void onRestoreInstanceState(Parcelable state) {
- if (!(state instanceof SavedState)) {
- super.onRestoreInstanceState(state);
- return;
- }
-
- SavedState ss = (SavedState)state;
- super.onRestoreInstanceState(ss.getSuperState());
-
- // XXX restore buffer type too, as well as lots of other stuff
- if (ss.text != null) {
- setText(ss.text);
- }
-
- if (ss.selStart >= 0 && ss.selEnd >= 0) {
- if (mText instanceof Spannable) {
- int len = mText.length();
-
- if (ss.selStart > len || ss.selEnd > len) {
- String restored = "";
-
- if (ss.text != null) {
- restored = "(restored) ";
- }
-
- Log.e("TextView", "Saved cursor position " + ss.selStart +
- "/" + ss.selEnd + " out of range for " + restored +
- "text " + mText);
- } else {
- Selection.setSelection((Spannable) mText, ss.selStart,
- ss.selEnd);
-
- if (ss.frozenWithFocus) {
- mFrozenWithFocus = true;
- }
- }
- }
- }
- }
-
- /**
- * Control whether this text view saves its entire text contents when
- * freezing to an icicle, in addition to dynamic state such as cursor
- * position. By default this is false, not saving the text. Set to true
- * if the text in the text view is not being saved somewhere else in
- * persistent storage (such as in a content provider) so that if the
- * view is later thawed the user will not lose their data.
- *
- * @param freezesText Controls whether a frozen icicle should include the
- * entire text data: true to include it, false to not.
- *
- * @attr ref android.R.styleable#TextView_freezesText
- */
- @android.view.RemotableViewMethod
- public void setFreezesText(boolean freezesText) {
- mFreezesText = freezesText;
- }
-
- /**
- * Return whether this text view is including its entire text contents
- * in frozen icicles.
- *
- * @return Returns true if text is included, false if it isn't.
- *
- * @see #setFreezesText
- */
- public boolean getFreezesText() {
- return mFreezesText;
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- /**
- * Sets the Factory used to create new Editables.
- */
- public final void setEditableFactory(Editable.Factory factory) {
- mEditableFactory = factory;
- setText(mText);
- }
-
- /**
- * Sets the Factory used to create new Spannables.
- */
- public final void setSpannableFactory(Spannable.Factory factory) {
- mSpannableFactory = factory;
- setText(mText);
- }
-
- /**
- * Sets the string value of the TextView. TextView <em>does not</em> accept
- * HTML-like formatting, which you can do with text strings in XML resource files.
- * To style your strings, attach android.text.style.* objects to a
- * {@link android.text.SpannableString SpannableString}, or see the
- * <a href="{@docRoot}guide/topics/resources/available-resources.html#stringresources">
- * Available Resource Types</a> documentation for an example of setting
- * formatted text in the XML resource file.
- *
- * @attr ref android.R.styleable#TextView_text
- */
- @android.view.RemotableViewMethod
- public final void setText(CharSequence text) {
- setText(text, mBufferType);
- }
-
- /**
- * Like {@link #setText(CharSequence)},
- * except that the cursor position (if any) is retained in the new text.
- *
- * @param text The new text to place in the text view.
- *
- * @see #setText(CharSequence)
- */
- @android.view.RemotableViewMethod
- public final void setTextKeepState(CharSequence text) {
- setTextKeepState(text, mBufferType);
- }
-
- /**
- * Sets the text that this TextView is to display (see
- * {@link #setText(CharSequence)}) and also sets whether it is stored
- * in a styleable/spannable buffer and whether it is editable.
- *
- * @attr ref android.R.styleable#TextView_text
- * @attr ref android.R.styleable#TextView_bufferType
- */
- public void setText(CharSequence text, BufferType type) {
- setText(text, type, true, 0);
-
- if (mCharWrapper != null) {
- mCharWrapper.mChars = null;
- }
- }
-
- private void setText(CharSequence text, BufferType type,
- boolean notifyBefore, int oldlen) {
- if (text == null) {
- text = "";
- }
-
- if (text instanceof Spanned &&
- ((Spanned) text).getSpanStart(TextUtils.TruncateAt.MARQUEE) >= 0) {
- setHorizontalFadingEdgeEnabled(true);
- setEllipsize(TextUtils.TruncateAt.MARQUEE);
- }
-
- int n = mFilters.length;
- for (int i = 0; i < n; i++) {
- CharSequence out = mFilters[i].filter(text, 0, text.length(),
- EMPTY_SPANNED, 0, 0);
- if (out != null) {
- text = out;
- }
- }
-
- if (notifyBefore) {
- if (mText != null) {
- oldlen = mText.length();
- sendBeforeTextChanged(mText, 0, oldlen, text.length());
- } else {
- sendBeforeTextChanged("", 0, 0, text.length());
- }
- }
-
- boolean needEditableForNotification = false;
-
- if (mListeners != null && mListeners.size() != 0) {
- needEditableForNotification = true;
- }
-
- if (type == BufferType.EDITABLE || mInput != null ||
- needEditableForNotification) {
- Editable t = mEditableFactory.newEditable(text);
- text = t;
- setFilters(t, mFilters);
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) imm.restartInput(this);
- } else if (type == BufferType.SPANNABLE || mMovement != null) {
- text = mSpannableFactory.newSpannable(text);
- } else if (!(text instanceof CharWrapper)) {
- text = TextUtils.stringOrSpannedString(text);
- }
-
- if (mAutoLinkMask != 0) {
- Spannable s2;
-
- if (type == BufferType.EDITABLE || text instanceof Spannable) {
- s2 = (Spannable) text;
- } else {
- s2 = mSpannableFactory.newSpannable(text);
- }
-
- if (Linkify.addLinks(s2, mAutoLinkMask)) {
- text = s2;
- type = (type == BufferType.EDITABLE) ? BufferType.EDITABLE : BufferType.SPANNABLE;
-
- /*
- * We must go ahead and set the text before changing the
- * movement method, because setMovementMethod() may call
- * setText() again to try to upgrade the buffer type.
- */
- mText = text;
-
- if (mLinksClickable) {
- setMovementMethod(LinkMovementMethod.getInstance());
- }
- }
- }
-
- mBufferType = type;
- mText = text;
-
- if (mTransformation == null)
- mTransformed = text;
- else
- mTransformed = mTransformation.getTransformation(text, this);
-
- final int textLength = text.length();
-
- if (text instanceof Spannable) {
- Spannable sp = (Spannable) text;
-
- // Remove any ChangeWatchers that might have come
- // from other TextViews.
- final ChangeWatcher[] watchers = sp.getSpans(0, sp.length(), ChangeWatcher.class);
- final int count = watchers.length;
- for (int i = 0; i < count; i++)
- sp.removeSpan(watchers[i]);
-
- if (mChangeWatcher == null)
- mChangeWatcher = new ChangeWatcher();
-
- sp.setSpan(mChangeWatcher, 0, textLength, Spanned.SPAN_INCLUSIVE_INCLUSIVE |
- (PRIORITY << Spanned.SPAN_PRIORITY_SHIFT));
-
- if (mInput != null) {
- sp.setSpan(mInput, 0, textLength, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- }
-
- if (mTransformation != null) {
- sp.setSpan(mTransformation, 0, textLength, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
-
- }
-
- if (mMovement != null) {
- mMovement.initialize(this, (Spannable) text);
-
- /*
- * Initializing the movement method will have set the
- * selection, so reset mSelectionMoved to keep that from
- * interfering with the normal on-focus selection-setting.
- */
- mSelectionMoved = false;
- }
- }
-
- if (mLayout != null) {
- checkForRelayout();
- }
-
- sendOnTextChanged(text, 0, oldlen, textLength);
- onTextChanged(text, 0, oldlen, textLength);
-
- if (needEditableForNotification) {
- sendAfterTextChanged((Editable) text);
- }
- }
-
- /**
- * Sets the TextView to display the specified slice of the specified
- * char array. You must promise that you will not change the contents
- * of the array except for right before another call to setText(),
- * since the TextView has no way to know that the text
- * has changed and that it needs to invalidate and re-layout.
- */
- public final void setText(char[] text, int start, int len) {
- int oldlen = 0;
-
- if (start < 0 || len < 0 || start + len > text.length) {
- throw new IndexOutOfBoundsException(start + ", " + len);
- }
-
- /*
- * We must do the before-notification here ourselves because if
- * the old text is a CharWrapper we destroy it before calling
- * into the normal path.
- */
- if (mText != null) {
- oldlen = mText.length();
- sendBeforeTextChanged(mText, 0, oldlen, len);
- } else {
- sendBeforeTextChanged("", 0, 0, len);
- }
-
- if (mCharWrapper == null) {
- mCharWrapper = new CharWrapper(text, start, len);
- } else {
- mCharWrapper.set(text, start, len);
- }
-
- setText(mCharWrapper, mBufferType, false, oldlen);
- }
-
- private static class CharWrapper
- implements CharSequence, GetChars, GraphicsOperations {
- private char[] mChars;
- private int mStart, mLength;
-
- public CharWrapper(char[] chars, int start, int len) {
- mChars = chars;
- mStart = start;
- mLength = len;
- }
-
- /* package */ void set(char[] chars, int start, int len) {
- mChars = chars;
- mStart = start;
- mLength = len;
- }
-
- public int length() {
- return mLength;
- }
-
- public char charAt(int off) {
- return mChars[off + mStart];
- }
-
- public String toString() {
- return new String(mChars, mStart, mLength);
- }
-
- public CharSequence subSequence(int start, int end) {
- if (start < 0 || end < 0 || start > mLength || end > mLength) {
- throw new IndexOutOfBoundsException(start + ", " + end);
- }
-
- return new String(mChars, start + mStart, end - start);
- }
-
- public void getChars(int start, int end, char[] buf, int off) {
- if (start < 0 || end < 0 || start > mLength || end > mLength) {
- throw new IndexOutOfBoundsException(start + ", " + end);
- }
-
- System.arraycopy(mChars, start + mStart, buf, off, end - start);
- }
-
- public void drawText(Canvas c, int start, int end,
- float x, float y, Paint p) {
- c.drawText(mChars, start + mStart, end - start, x, y, p);
- }
-
- public float measureText(int start, int end, Paint p) {
- return p.measureText(mChars, start + mStart, end - start);
- }
-
- public int getTextWidths(int start, int end, float[] widths, Paint p) {
- return p.getTextWidths(mChars, start + mStart, end - start, widths);
- }
- }
-
- /**
- * Like {@link #setText(CharSequence, android.widget.TextView.BufferType)},
- * except that the cursor position (if any) is retained in the new text.
- *
- * @see #setText(CharSequence, android.widget.TextView.BufferType)
- */
- public final void setTextKeepState(CharSequence text, BufferType type) {
- int start = getSelectionStart();
- int end = getSelectionEnd();
- int len = text.length();
-
- setText(text, type);
-
- if (start >= 0 || end >= 0) {
- if (mText instanceof Spannable) {
- Selection.setSelection((Spannable) mText,
- Math.max(0, Math.min(start, len)),
- Math.max(0, Math.min(end, len)));
- }
- }
- }
-
- @android.view.RemotableViewMethod
- public final void setText(int resid) {
- setText(getContext().getResources().getText(resid));
- }
-
- public final void setText(int resid, BufferType type) {
- setText(getContext().getResources().getText(resid), type);
- }
-
- /**
- * Sets the text to be displayed when the text of the TextView is empty.
- * Null means to use the normal empty text. The hint does not currently
- * participate in determining the size of the view.
- *
- * This method is deprecated. Use {link #setHint(int, String)} or
- * {link #setHint(CharSequence, String)} instead.
- *
- * @attr ref android.R.styleable#TextView_hint
- */
- @android.view.RemotableViewMethod
- public final void setHint(CharSequence hint) {
- mHint = TextUtils.stringOrSpannedString(hint);
-
- if (mLayout != null) {
- checkForRelayout();
- }
-
- if (mText.length() == 0)
- invalidate();
- }
-
- /**
- * Sets the text to be displayed when the text of the TextView is empty,
- * from a resource.
- *
- * This method is deprecated. Use {link #setHint(int, String)} or
- * {link #setHint(CharSequence, String)} instead.
- *
- * @attr ref android.R.styleable#TextView_hint
- */
- @android.view.RemotableViewMethod
- public final void setHint(int resid) {
- setHint(getContext().getResources().getText(resid));
- }
-
- /**
- * Returns the hint that is displayed when the text of the TextView
- * is empty.
- *
- * @attr ref android.R.styleable#TextView_hint
- */
- @ViewDebug.CapturedViewProperty
- public CharSequence getHint() {
- return mHint;
- }
-
- /**
- * Set the type of the content with a constant as defined for
- * {@link EditorInfo#inputType}. This will take care of changing
- * the key listener, by calling {@link #setKeyListener(KeyListener)}, to
- * match the given content type. If the given content type is
- * {@link EditorInfo#TYPE_NULL} then a soft keyboard will
- * not be displayed for this text view.
- *
- * @see #getInputType()
- * @see #setRawInputType(int)
- * @see android.text.InputType
- * @attr ref android.R.styleable#TextView_inputType
- */
- public void setInputType(int type) {
- setInputType(type, false);
- final boolean isPassword = (type&(EditorInfo.TYPE_MASK_CLASS
- |EditorInfo.TYPE_MASK_VARIATION))
- == (EditorInfo.TYPE_CLASS_TEXT
- |EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
- boolean forceUpdate = false;
- if (isPassword) {
- setTransformationMethod(PasswordTransformationMethod.getInstance());
- setTypefaceByIndex(MONOSPACE, 0);
- } else if (mTransformation == PasswordTransformationMethod.getInstance()) {
- // We need to clean up if we were previously in password mode.
- setTypefaceByIndex(-1, -1);
- forceUpdate = true;
- }
-
- boolean multiLine = (type&(EditorInfo.TYPE_MASK_CLASS
- | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE)) ==
- (EditorInfo.TYPE_CLASS_TEXT
- | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE);
-
- // We need to update the single line mode if it has changed or we
- // were previously in password mode.
- if (mSingleLine == multiLine || forceUpdate) {
- // Change single line mode, but only change the transformation if
- // we are not in password mode.
- applySingleLine(!multiLine, !isPassword);
- }
-
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) imm.restartInput(this);
- }
-
- /**
- * Directly change the content type integer of the text view, without
- * modifying any other state.
- * @see #setContentType
- * @see android.text.InputType
- * @attr ref android.R.styleable#TextView_inputType
- */
- public void setRawInputType(int type) {
- mInputType = type;
- }
-
- private void setInputType(int type, boolean direct) {
- final int cls = type & EditorInfo.TYPE_MASK_CLASS;
- KeyListener input;
- if (cls == EditorInfo.TYPE_CLASS_TEXT) {
- boolean autotext = (type & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT)
- != 0;
- TextKeyListener.Capitalize cap;
- if ((type & EditorInfo.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) {
- cap = TextKeyListener.Capitalize.CHARACTERS;
- } else if ((type & EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS) != 0) {
- cap = TextKeyListener.Capitalize.WORDS;
- } else if ((type & EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES) != 0) {
- cap = TextKeyListener.Capitalize.SENTENCES;
- } else {
- cap = TextKeyListener.Capitalize.NONE;
- }
- input = TextKeyListener.getInstance(autotext, cap);
- } else if (cls == EditorInfo.TYPE_CLASS_NUMBER) {
- input = DigitsKeyListener.getInstance(
- (type & EditorInfo.TYPE_NUMBER_FLAG_SIGNED) != 0,
- (type & EditorInfo.TYPE_NUMBER_FLAG_DECIMAL) != 0);
- } else if (cls == EditorInfo.TYPE_CLASS_DATETIME) {
- switch (type & EditorInfo.TYPE_MASK_VARIATION) {
- case EditorInfo.TYPE_DATETIME_VARIATION_DATE:
- input = DateKeyListener.getInstance();
- break;
- case EditorInfo.TYPE_DATETIME_VARIATION_TIME:
- input = TimeKeyListener.getInstance();
- break;
- default:
- input = DateTimeKeyListener.getInstance();
- break;
- }
- } else if (cls == EditorInfo.TYPE_CLASS_PHONE) {
- input = DialerKeyListener.getInstance();
- } else {
- input = TextKeyListener.getInstance();
- }
- mInputType = type;
- if (direct) mInput = input;
- else {
- setKeyListenerOnly(input);
- }
- }
-
- /**
- * Get the type of the content.
- *
- * @see #setInputType(int)
- * @see android.text.InputType
- */
- public int getInputType() {
- return mInputType;
- }
-
- /**
- * Set the private content type of the text, which is the
- * {@link EditorInfo#privateContentType TextBoxAttribute.privateContentType}
- * field that will be filled in when creating an input connection.
- *
- * @see #getPrivateContentType()
- * @see EditorInfo#privateContentType
- * @attr ref android.R.styleable#TextView_editorPrivateContentType
- */
- public void setPrivateContentType(String type) {
- if (mInputContentType == null) mInputContentType = new InputContentType();
- mInputContentType.privateContentType = type;
- }
-
- /**
- * Get the private type of the content.
- *
- * @see #setPrivateContentType(String)
- * @see EditorInfo#privateContentType
- */
- public String getPrivateContentType() {
- return mInputContentType != null
- ? mInputContentType.privateContentType : null;
- }
-
- /**
- * Set the extra input data of the text, which is the
- * {@link EditorInfo#extras TextBoxAttribute.extras}
- * Bundle that will be filled in when creating an input connection. The
- * given integer is the resource ID of an XML resource holding an
- * {@link android.R.styleable#InputExtras &lt;input-extras&gt;} XML tree.
- *
- * @see #getInputExtras(boolean)
- * @see EditorInfo#extras
- * @attr ref android.R.styleable#TextView_editorExtras
- */
- public void setInputExtras(int xmlResId)
- throws XmlPullParserException, IOException {
- XmlResourceParser parser = getResources().getXml(xmlResId);
- if (mInputContentType == null) mInputContentType = new InputContentType();
- mInputContentType.extras = new Bundle();
- getResources().parseBundleExtras(parser, mInputContentType.extras);
- }
-
- /**
- * Retrieve the input extras currently associated with the text view, which
- * can be viewed as well as modified.
- *
- * @param create If true, the extras will be created if they don't already
- * exist. Otherwise, null will be returned if none have been created.
- * @see #setInputExtras(int)View
- * @see EditorInfo#extras
- * @attr ref android.R.styleable#TextView_editorExtras
- */
- public Bundle getInputExtras(boolean create) {
- if (mInputContentType == null) {
- if (!create) return null;
- mInputContentType = new InputContentType();
- }
- if (mInputContentType.extras == null) {
- if (!create) return null;
- mInputContentType.extras = new Bundle();
- }
- return mInputContentType.extras;
- }
-
- /**
- * Returns the error message that was set to be displayed with
- * {@link #setError}, or <code>null</code> if no error was set
- * or if it the error was cleared by the widget after user input.
- */
- public CharSequence getError() {
- return mError;
- }
-
- /**
- * Sets the right-hand compound drawable of the TextView to the "error"
- * icon and sets an error message that will be displayed in a popup when
- * the TextView has focus. The icon and error message will be reset to
- * null when any key events cause changes to the TextView's text. If the
- * <code>error</code> is <code>null</code>, the error message and icon
- * will be cleared.
- */
- @android.view.RemotableViewMethod
- public void setError(CharSequence error) {
- if (error == null) {
- setError(null, null);
- } else {
- Drawable dr = getContext().getResources().
- getDrawable(com.android.internal.R.drawable.
- indicator_input_error);
-
- dr.setBounds(0, 0, dr.getIntrinsicWidth(), dr.getIntrinsicHeight());
- setError(error, dr);
- }
- }
-
- /**
- * Sets the right-hand compound drawable of the TextView to the specified
- * icon and sets an error message that will be displayed in a popup when
- * the TextView has focus. The icon and error message will be reset to
- * null when any key events cause changes to the TextView's text. The
- * drawable must already have had {@link Drawable#setBounds} set on it.
- * If the <code>error</code> is <code>null</code>, the error message will
- * be cleared (and you should provide a <code>null</code> icon as well).
- */
- public void setError(CharSequence error, Drawable icon) {
- error = TextUtils.stringOrSpannedString(error);
-
- mError = error;
- mErrorWasChanged = true;
- final Drawables dr = mDrawables;
- if (dr != null) {
- setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop,
- icon, dr.mDrawableBottom);
- } else {
- setCompoundDrawables(null, null, icon, null);
- }
-
- if (error == null) {
- if (mPopup != null) {
- if (mPopup.isShowing()) {
- mPopup.dismiss();
- }
-
- mPopup = null;
- }
- } else {
- if (isFocused()) {
- showError();
- }
- }
- }
-
- private void showError() {
- if (getWindowToken() == null) {
- mShowErrorAfterAttach = true;
- return;
- }
-
- if (mPopup == null) {
- LayoutInflater inflater = LayoutInflater.from(getContext());
- final TextView err = (TextView) inflater.inflate(com.android.internal.R.layout.textview_hint,
- null);
-
- mPopup = new PopupWindow(err, 200, 50) {
- private boolean mAbove = false;
-
- @Override
- public void update(int x, int y, int w, int h, boolean force) {
- super.update(x, y, w, h, force);
-
- boolean above = isAboveAnchor();
- if (above != mAbove) {
- mAbove = above;
-
- if (above) {
- err.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error_above);
- } else {
- err.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error);
- }
- }
- }
- };
- mPopup.setFocusable(false);
- }
-
- TextView tv = (TextView) mPopup.getContentView();
- chooseSize(mPopup, mError, tv);
- tv.setText(mError);
-
- mPopup.showAsDropDown(this, getErrorX(), getErrorY());
- }
-
- /**
- * Returns the Y offset to make the pointy top of the error point
- * at the middle of the error icon.
- */
- private int getErrorX() {
- /*
- * The "25" is the distance between the point and the right edge
- * of the background
- */
-
- final Drawables dr = mDrawables;
- return getWidth() - mPopup.getWidth()
- - getPaddingRight()
- - (dr != null ? dr.mDrawableSizeRight : 0) / 2 + 25;
- }
-
- /**
- * Returns the Y offset to make the pointy top of the error point
- * at the bottom of the error icon.
- */
- private int getErrorY() {
- /*
- * Compound, not extended, because the icon is not clipped
- * if the text height is smaller.
- */
- int vspace = mBottom - mTop -
- getCompoundPaddingBottom() - getCompoundPaddingTop();
-
- final Drawables dr = mDrawables;
- int icontop = getCompoundPaddingTop()
- + (vspace - (dr != null ? dr.mDrawableHeightRight : 0)) / 2;
-
- /*
- * The "2" is the distance between the point and the top edge
- * of the background.
- */
-
- return icontop + (dr != null ? dr.mDrawableHeightRight : 0)
- - getHeight() - 2;
- }
-
- private void hideError() {
- if (mPopup != null) {
- if (mPopup.isShowing()) {
- mPopup.dismiss();
- }
- }
-
- mShowErrorAfterAttach = false;
- }
-
- private void chooseSize(PopupWindow pop, CharSequence text, TextView tv) {
- int wid = tv.getPaddingLeft() + tv.getPaddingRight();
- int ht = tv.getPaddingTop() + tv.getPaddingBottom();
-
- /*
- * Figure out how big the text would be if we laid it out to the
- * full width of this view minus the border.
- */
- int cap = getWidth() - wid;
- if (cap < 0) {
- cap = 200; // We must not be measured yet -- setFrame() will fix it.
- }
-
- Layout l = new StaticLayout(text, tv.getPaint(), cap,
- Layout.Alignment.ALIGN_NORMAL, 1, 0, true);
- float max = 0;
- for (int i = 0; i < l.getLineCount(); i++) {
- max = Math.max(max, l.getLineWidth(i));
- }
-
- /*
- * Now set the popup size to be big enough for the text plus the border.
- */
- pop.setWidth(wid + (int) Math.ceil(max));
- pop.setHeight(ht + l.getHeight());
- }
-
-
- @Override
- protected boolean setFrame(int l, int t, int r, int b) {
- boolean result = super.setFrame(l, t, r, b);
-
- if (mPopup != null) {
- TextView tv = (TextView) mPopup.getContentView();
- chooseSize(mPopup, mError, tv);
- mPopup.update(this, getErrorX(), getErrorY(), -1, -1);
- }
-
- if (mRestartMarquee && mEllipsize == TextUtils.TruncateAt.MARQUEE) {
- mRestartMarquee = false;
- startMarquee();
- }
-
- return result;
- }
-
- /**
- * Sets the list of input filters that will be used if the buffer is
- * Editable. Has no effect otherwise.
- *
- * @attr ref android.R.styleable#TextView_maxLength
- */
- public void setFilters(InputFilter[] filters) {
- if (filters == null) {
- throw new IllegalArgumentException();
- }
-
- mFilters = filters;
-
- if (mText instanceof Editable) {
- setFilters((Editable) mText, filters);
- }
- }
-
- /**
- * Sets the list of input filters on the specified Editable,
- * and includes mInput in the list if it is an InputFilter.
- */
- private void setFilters(Editable e, InputFilter[] filters) {
- if (mInput instanceof InputFilter) {
- InputFilter[] nf = new InputFilter[filters.length + 1];
-
- System.arraycopy(filters, 0, nf, 0, filters.length);
- nf[filters.length] = (InputFilter) mInput;
-
- e.setFilters(nf);
- } else {
- e.setFilters(filters);
- }
- }
-
- /**
- * Returns the current list of input filters.
- */
- public InputFilter[] getFilters() {
- return mFilters;
- }
-
- /////////////////////////////////////////////////////////////////////////
-
- private int getVerticalOffset(boolean forceNormal) {
- int voffset = 0;
- final int gravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
-
- Layout l = mLayout;
- if (!forceNormal && mText.length() == 0 && mHintLayout != null) {
- l = mHintLayout;
- }
-
- if (gravity != Gravity.TOP) {
- int boxht;
-
- if (l == mHintLayout) {
- boxht = getMeasuredHeight() - getCompoundPaddingTop() -
- getCompoundPaddingBottom();
- } else {
- boxht = getMeasuredHeight() - getExtendedPaddingTop() -
- getExtendedPaddingBottom();
- }
- int textht = l.getHeight();
-
- if (textht < boxht) {
- if (gravity == Gravity.BOTTOM)
- voffset = boxht - textht;
- else // (gravity == Gravity.CENTER_VERTICAL)
- voffset = (boxht - textht) >> 1;
- }
- }
- return voffset;
- }
-
- private int getBottomVerticalOffset(boolean forceNormal) {
- int voffset = 0;
- final int gravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
-
- Layout l = mLayout;
- if (!forceNormal && mText.length() == 0 && mHintLayout != null) {
- l = mHintLayout;
- }
-
- if (gravity != Gravity.BOTTOM) {
- int boxht;
-
- if (l == mHintLayout) {
- boxht = getMeasuredHeight() - getCompoundPaddingTop() -
- getCompoundPaddingBottom();
- } else {
- boxht = getMeasuredHeight() - getExtendedPaddingTop() -
- getExtendedPaddingBottom();
- }
- int textht = l.getHeight();
-
- if (textht < boxht) {
- if (gravity == Gravity.TOP)
- voffset = boxht - textht;
- else // (gravity == Gravity.CENTER_VERTICAL)
- voffset = (boxht - textht) >> 1;
- }
- }
- return voffset;
- }
-
- private void invalidateCursorPath() {
- if (mHighlightPathBogus) {
- invalidateCursor();
- } else {
- synchronized (sTempRect) {
- /*
- * The reason for this concern about the thickness of the
- * cursor and doing the floor/ceil on the coordinates is that
- * some EditTexts (notably textfields in the Browser) have
- * anti-aliased text where not all the characters are
- * necessarily at integer-multiple locations. This should
- * make sure the entire cursor gets invalidated instead of
- * sometimes missing half a pixel.
- */
-
- float thick = FloatMath.ceil(mTextPaint.getStrokeWidth());
- if (thick < 1.0f) {
- thick = 1.0f;
- }
-
- thick /= 2;
-
- mHighlightPath.computeBounds(sTempRect, false);
-
- int left = getCompoundPaddingLeft();
- int top = getExtendedPaddingTop() + getVerticalOffset(true);
-
- invalidate((int) FloatMath.floor(left + sTempRect.left - thick),
- (int) FloatMath.floor(top + sTempRect.top - thick),
- (int) FloatMath.ceil(left + sTempRect.right + thick),
- (int) FloatMath.ceil(top + sTempRect.bottom + thick));
- }
- }
- }
-
- private void invalidateCursor() {
- int where = Selection.getSelectionEnd(mText);
-
- invalidateCursor(where, where, where);
- }
-
- private void invalidateCursor(int a, int b, int c) {
- if (mLayout == null) {
- invalidate();
- } else {
- if (a >= 0 || b >= 0 || c >= 0) {
- int first = Math.min(Math.min(a, b), c);
- int last = Math.max(Math.max(a, b), c);
-
- int line = mLayout.getLineForOffset(first);
- int top = mLayout.getLineTop(line);
-
- // This is ridiculous, but the descent from the line above
- // can hang down into the line we really want to redraw,
- // so we have to invalidate part of the line above to make
- // sure everything that needs to be redrawn really is.
- // (But not the whole line above, because that would cause
- // the same problem with the descenders on the line above it!)
- if (line > 0) {
- top -= mLayout.getLineDescent(line - 1);
- }
-
- int line2;
-
- if (first == last)
- line2 = line;
- else
- line2 = mLayout.getLineForOffset(last);
-
- int bottom = mLayout.getLineTop(line2 + 1);
- int voffset = getVerticalOffset(true);
-
- int left = getCompoundPaddingLeft() + mScrollX;
- invalidate(left, top + voffset + getExtendedPaddingTop(),
- left + getWidth() - getCompoundPaddingLeft() -
- getCompoundPaddingRight(),
- bottom + voffset + getExtendedPaddingTop());
- }
- }
- }
-
- private void registerForPreDraw() {
- final ViewTreeObserver observer = getViewTreeObserver();
- if (observer == null) {
- return;
- }
-
- if (mPreDrawState == PREDRAW_NOT_REGISTERED) {
- observer.addOnPreDrawListener(this);
- mPreDrawState = PREDRAW_PENDING;
- } else if (mPreDrawState == PREDRAW_DONE) {
- mPreDrawState = PREDRAW_PENDING;
- }
-
- // else state is PREDRAW_PENDING, so keep waiting.
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean onPreDraw() {
- if (mPreDrawState != PREDRAW_PENDING) {
- return true;
- }
-
- if (mLayout == null) {
- assumeLayout();
- }
-
- boolean changed = false;
-
- if (mMovement != null) {
- int curs = Selection.getSelectionEnd(mText);
-
- /*
- * TODO: This should really only keep the end in view if
- * it already was before the text changed. I'm not sure
- * of a good way to tell from here if it was.
- */
- if (curs < 0 &&
- (mGravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
- curs = mText.length();
- }
-
- if (curs >= 0) {
- changed = bringPointIntoView(curs);
- }
- } else {
- changed = bringTextIntoView();
- }
-
- mPreDrawState = PREDRAW_DONE;
- return !changed;
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- if (mShowErrorAfterAttach) {
- showError();
- mShowErrorAfterAttach = false;
- }
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
- if (mPreDrawState != PREDRAW_NOT_REGISTERED) {
- final ViewTreeObserver observer = getViewTreeObserver();
- if (observer != null) {
- observer.removeOnPreDrawListener(this);
- mPreDrawState = PREDRAW_NOT_REGISTERED;
- }
- }
-
- if (mError != null) {
- hideError();
- }
- }
-
- @Override
- protected boolean isPaddingOffsetRequired() {
- return mShadowRadius != 0;
- }
-
- @Override
- protected int getLeftPaddingOffset() {
- return (int) Math.min(0, mShadowDx - mShadowRadius);
- }
-
- @Override
- protected int getTopPaddingOffset() {
- return (int) Math.min(0, mShadowDy - mShadowRadius);
- }
-
- @Override
- protected int getBottomPaddingOffset() {
- return (int) Math.max(0, mShadowDy + mShadowRadius);
- }
-
- @Override
- protected int getRightPaddingOffset() {
- return (int) Math.max(0, mShadowDx + mShadowRadius);
- }
-
- @Override
- protected boolean verifyDrawable(Drawable who) {
- final boolean verified = super.verifyDrawable(who);
- if (!verified && mDrawables != null) {
- return who == mDrawables.mDrawableLeft || who == mDrawables.mDrawableTop ||
- who == mDrawables.mDrawableRight || who == mDrawables.mDrawableBottom;
- }
- return verified;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- // Draw the background for this view
- super.onDraw(canvas);
-
- final int compoundPaddingLeft = getCompoundPaddingLeft();
- final int compoundPaddingTop = getCompoundPaddingTop();
- final int compoundPaddingRight = getCompoundPaddingRight();
- final int compoundPaddingBottom = getCompoundPaddingBottom();
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
- final int right = mRight;
- final int left = mLeft;
- final int bottom = mBottom;
- final int top = mTop;
-
- final Drawables dr = mDrawables;
- if (dr != null) {
- /*
- * Compound, not extended, because the icon is not clipped
- * if the text height is smaller.
- */
-
- int vspace = bottom - top - compoundPaddingBottom - compoundPaddingTop;
- int hspace = right - left - compoundPaddingRight - compoundPaddingLeft;
-
- if (dr.mDrawableLeft != null) {
- canvas.save();
- canvas.translate(scrollX + mPaddingLeft,
- scrollY + compoundPaddingTop +
- (vspace - dr.mDrawableHeightLeft) / 2);
- dr.mDrawableLeft.draw(canvas);
- canvas.restore();
- }
-
- if (dr.mDrawableRight != null) {
- canvas.save();
- canvas.translate(scrollX + right - left - mPaddingRight - dr.mDrawableSizeRight,
- scrollY + compoundPaddingTop + (vspace - dr.mDrawableHeightRight) / 2);
- dr.mDrawableRight.draw(canvas);
- canvas.restore();
- }
-
- if (dr.mDrawableTop != null) {
- canvas.save();
- canvas.translate(scrollX + compoundPaddingLeft + (hspace - dr.mDrawableWidthTop) / 2,
- scrollY + mPaddingTop);
- dr.mDrawableTop.draw(canvas);
- canvas.restore();
- }
-
- if (dr.mDrawableBottom != null) {
- canvas.save();
- canvas.translate(scrollX + compoundPaddingLeft +
- (hspace - dr.mDrawableWidthBottom) / 2,
- scrollY + bottom - top - mPaddingBottom - dr.mDrawableSizeBottom);
- dr.mDrawableBottom.draw(canvas);
- canvas.restore();
- }
- }
-
- if (mPreDrawState == PREDRAW_DONE) {
- final ViewTreeObserver observer = getViewTreeObserver();
- if (observer != null) {
- observer.removeOnPreDrawListener(this);
- mPreDrawState = PREDRAW_NOT_REGISTERED;
- }
- }
-
- int color = mCurTextColor;
-
- if (mLayout == null) {
- assumeLayout();
- }
-
- Layout layout = mLayout;
- int cursorcolor = color;
-
- if (mHint != null && mText.length() == 0) {
- if (mHintTextColor != null) {
- color = mCurHintTextColor;
- }
-
- layout = mHintLayout;
- }
-
- mTextPaint.setColor(color);
- mTextPaint.drawableState = getDrawableState();
-
- canvas.save();
- /* Would be faster if we didn't have to do this. Can we chop the
- (displayable) text so that we don't need to do this ever?
- */
-
- int extendedPaddingTop = getExtendedPaddingTop();
- int extendedPaddingBottom = getExtendedPaddingBottom();
-
- float clipLeft = compoundPaddingLeft + scrollX;
- float clipTop = extendedPaddingTop + scrollY;
- float clipRight = right - left - compoundPaddingRight + scrollX;
- float clipBottom = bottom - top - extendedPaddingBottom + scrollY;
-
- if (mShadowRadius != 0) {
- clipLeft += Math.min(0, mShadowDx - mShadowRadius);
- clipRight += Math.max(0, mShadowDx + mShadowRadius);
-
- clipTop += Math.min(0, mShadowDy - mShadowRadius);
- clipBottom += Math.max(0, mShadowDy + mShadowRadius);
- }
-
- canvas.clipRect(clipLeft, clipTop, clipRight, clipBottom);
-
- int voffsetText = 0;
- int voffsetCursor = 0;
-
- // translate in by our padding
- {
- /* shortcircuit calling getVerticaOffset() */
- if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
- voffsetText = getVerticalOffset(false);
- voffsetCursor = getVerticalOffset(true);
- }
- canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText);
- }
-
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
- if (!mSingleLine && getLineCount() == 1 && canMarquee() &&
- (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) {
- canvas.translate(mLayout.getLineRight(0) - (mRight - mLeft -
- getCompoundPaddingLeft() - getCompoundPaddingRight()), 0.0f);
- }
-
- if (mMarquee != null && mMarquee.isRunning()) {
- canvas.translate(-mMarquee.mScroll, 0.0f);
- }
- }
-
- Path highlight = null;
- int selStart = -1, selEnd = -1;
-
- // If there is no movement method, then there can be no selection.
- // Check that first and attempt to skip everything having to do with
- // the cursor.
- // XXX This is not strictly true -- a program could set the
- // selection manually if it really wanted to.
- if (mMovement != null && (isFocused() || isPressed())) {
- selStart = Selection.getSelectionStart(mText);
- selEnd = Selection.getSelectionEnd(mText);
-
- if (mCursorVisible && selStart >= 0 && isEnabled()) {
- if (mHighlightPath == null)
- mHighlightPath = new Path();
-
- if (selStart == selEnd) {
- if ((SystemClock.uptimeMillis() - mShowCursor) % (2 * BLINK)
- < BLINK) {
- if (mHighlightPathBogus) {
- mHighlightPath.reset();
- mLayout.getCursorPath(selStart, mHighlightPath, mText);
- mHighlightPathBogus = false;
- }
-
- // XXX should pass to skin instead of drawing directly
- mHighlightPaint.setColor(cursorcolor);
- mHighlightPaint.setStyle(Paint.Style.STROKE);
-
- highlight = mHighlightPath;
- }
- } else {
- if (mHighlightPathBogus) {
- mHighlightPath.reset();
- mLayout.getSelectionPath(selStart, selEnd, mHighlightPath);
- mHighlightPathBogus = false;
- }
-
- // XXX should pass to skin instead of drawing directly
- mHighlightPaint.setColor(mHighlightColor);
- mHighlightPaint.setStyle(Paint.Style.FILL);
-
- highlight = mHighlightPath;
- }
- }
- }
-
- /* Comment out until we decide what to do about animations
- boolean isLinearTextOn = false;
- if (currentTransformation != null) {
- isLinearTextOn = mTextPaint.isLinearTextOn();
- Matrix m = currentTransformation.getMatrix();
- if (!m.isIdentity()) {
- // mTextPaint.setLinearTextOn(true);
- }
- }
- */
-
- final InputMethodState ims = mInputMethodState;
- if (ims != null && ims.mBatchEditNesting == 0) {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) {
- if (imm.isActive(this)) {
- boolean reported = false;
- if (ims.mContentChanged) {
- // We are in extract mode and the content has changed
- // in some way... just report complete new text to the
- // input method.
- reported = reportExtractedText();
- }
- if (!reported && highlight != null) {
- int candStart = -1;
- int candEnd = -1;
- if (mText instanceof Spannable) {
- Spannable sp = (Spannable)mText;
- candStart = EditableInputConnection.getComposingSpanStart(sp);
- candEnd = EditableInputConnection.getComposingSpanEnd(sp);
- }
- imm.updateSelection(this, selStart, selEnd, candStart, candEnd);
- }
- }
-
- if (imm.isWatchingCursor(this) && highlight != null) {
- highlight.computeBounds(ims.mTmpRectF, true);
- ims.mTmpOffset[0] = ims.mTmpOffset[1] = 0;
-
- canvas.getMatrix().mapPoints(ims.mTmpOffset);
- ims.mTmpRectF.offset(ims.mTmpOffset[0], ims.mTmpOffset[1]);
-
- ims.mTmpRectF.offset(0, voffsetCursor - voffsetText);
-
- ims.mCursorRectInWindow.set((int)(ims.mTmpRectF.left + 0.5),
- (int)(ims.mTmpRectF.top + 0.5),
- (int)(ims.mTmpRectF.right + 0.5),
- (int)(ims.mTmpRectF.bottom + 0.5));
-
- imm.updateCursor(this,
- ims.mCursorRectInWindow.left, ims.mCursorRectInWindow.top,
- ims.mCursorRectInWindow.right, ims.mCursorRectInWindow.bottom);
- }
- }
- }
-
- layout.draw(canvas, highlight, mHighlightPaint, voffsetCursor - voffsetText);
-
- /* Comment out until we decide what to do about animations
- if (currentTransformation != null) {
- mTextPaint.setLinearTextOn(isLinearTextOn);
- }
- */
-
- canvas.restore();
- }
-
- @Override
- public void getFocusedRect(Rect r) {
- if (mLayout == null) {
- super.getFocusedRect(r);
- return;
- }
-
- int sel = getSelectionEnd();
- if (sel < 0) {
- super.getFocusedRect(r);
- return;
- }
-
- int line = mLayout.getLineForOffset(sel);
- r.top = mLayout.getLineTop(line);
- r.bottom = mLayout.getLineBottom(line);
-
- r.left = (int) mLayout.getPrimaryHorizontal(sel);
- r.right = r.left + 1;
-
- // Adjust for padding and gravity.
- int paddingLeft = getCompoundPaddingLeft();
- int paddingTop = getExtendedPaddingTop();
- if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
- paddingTop += getVerticalOffset(false);
- }
- r.offset(paddingLeft, paddingTop);
- }
-
- /**
- * Return the number of lines of text, or 0 if the internal Layout has not
- * been built.
- */
- public int getLineCount() {
- return mLayout != null ? mLayout.getLineCount() : 0;
- }
-
- /**
- * Return the baseline for the specified line (0...getLineCount() - 1)
- * If bounds is not null, return the top, left, right, bottom extents
- * of the specified line in it. If the internal Layout has not been built,
- * return 0 and set bounds to (0, 0, 0, 0)
- * @param line which line to examine (0..getLineCount() - 1)
- * @param bounds Optional. If not null, it returns the extent of the line
- * @return the Y-coordinate of the baseline
- */
- public int getLineBounds(int line, Rect bounds) {
- if (mLayout == null) {
- if (bounds != null) {
- bounds.set(0, 0, 0, 0);
- }
- return 0;
- }
- else {
- int baseline = mLayout.getLineBounds(line, bounds);
-
- int voffset = getExtendedPaddingTop();
- if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
- voffset += getVerticalOffset(true);
- }
- if (bounds != null) {
- bounds.offset(getCompoundPaddingLeft(), voffset);
- }
- return baseline + voffset;
- }
- }
-
- @Override
- public int getBaseline() {
- if (mLayout == null) {
- return super.getBaseline();
- }
-
- int voffset = 0;
- if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
- voffset = getVerticalOffset(true);
- }
-
- return getExtendedPaddingTop() + voffset + mLayout.getLineBaseline(0);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- int which = doKeyDown(keyCode, event, null);
- if (which == 0) {
- // Go through default dispatching.
- return super.onKeyDown(keyCode, event);
- }
-
- return true;
- }
-
- @Override
- public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
- KeyEvent down = new KeyEvent(event, KeyEvent.ACTION_DOWN);
-
- int which = doKeyDown(keyCode, down, event);
- if (which == 0) {
- // Go through default dispatching.
- return super.onKeyMultiple(keyCode, repeatCount, event);
- }
- if (which == -1) {
- // Consumed the whole thing.
- return true;
- }
-
- repeatCount--;
-
- // We are going to dispatch the remaining events to either the input
- // or movement method. To do this, we will just send a repeated stream
- // of down and up events until we have done the complete repeatCount.
- // It would be nice if those interfaces had an onKeyMultiple() method,
- // but adding that is a more complicated change.
- KeyEvent up = new KeyEvent(event, KeyEvent.ACTION_UP);
- if (which == 1) {
- mInput.onKeyUp(this, (Editable)mText, keyCode, up);
- while (--repeatCount > 0) {
- mInput.onKeyDown(this, (Editable)mText, keyCode, down);
- mInput.onKeyUp(this, (Editable)mText, keyCode, up);
- }
- if (mError != null && !mErrorWasChanged) {
- setError(null, null);
- }
-
- } else if (which == 2) {
- mMovement.onKeyUp(this, (Spannable)mText, keyCode, up);
- while (--repeatCount > 0) {
- mMovement.onKeyDown(this, (Spannable)mText, keyCode, down);
- mMovement.onKeyUp(this, (Spannable)mText, keyCode, up);
- }
- }
-
- return true;
- }
-
- /**
- * Returns true if pressing ENTER in this field advances focus instead
- * of inserting the character. This is true mostly in single-line fields,
- * but also in mail addresses and subjects which will display on multiple
- * lines but where it doesn't make sense to insert newlines.
- */
- private boolean advanceFocusOnEnter() {
- if (mInput == null) {
- return false;
- }
-
- if (mSingleLine) {
- return true;
- }
-
- if ((mInputType & EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT) {
- int variation = mInputType & EditorInfo.TYPE_MASK_VARIATION;
-
- if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS ||
- variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_SUBJECT) {
- return true;
- }
- }
-
- return false;
- }
-
- private int doKeyDown(int keyCode, KeyEvent event, KeyEvent otherEvent) {
- if (!isEnabled()) {
- return 0;
- }
-
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_ENTER:
- if (advanceFocusOnEnter()) {
- return 0;
- }
- }
-
- if (mInput != null) {
- /*
- * Keep track of what the error was before doing the input
- * so that if an input filter changed the error, we leave
- * that error showing. Otherwise, we take down whatever
- * error was showing when the user types something.
- */
- mErrorWasChanged = false;
-
- boolean doDown = true;
- if (otherEvent != null) {
- try {
- beginBatchEdit();
- boolean handled = mInput.onKeyOther(this, (Editable) mText,
- otherEvent);
- if (mError != null && !mErrorWasChanged) {
- setError(null, null);
- }
- doDown = false;
- if (handled) {
- return -1;
- }
- } catch (AbstractMethodError e) {
- // onKeyOther was added after 1.0, so if it isn't
- // implemented we need to try to dispatch as a regular down.
- } finally {
- endBatchEdit();
- }
- }
-
- if (doDown) {
- beginBatchEdit();
- if (mInput.onKeyDown(this, (Editable) mText, keyCode, event)) {
- endBatchEdit();
- if (mError != null && !mErrorWasChanged) {
- setError(null, null);
- }
- return 1;
- }
- endBatchEdit();
- }
- }
-
- // bug 650865: sometimes we get a key event before a layout.
- // don't try to move around if we don't know the layout.
-
- if (mMovement != null && mLayout != null) {
- boolean doDown = true;
- if (otherEvent != null) {
- try {
- boolean handled = mMovement.onKeyOther(this, (Spannable) mText,
- otherEvent);
- doDown = false;
- if (handled) {
- return -1;
- }
- } catch (AbstractMethodError e) {
- // onKeyOther was added after 1.0, so if it isn't
- // implemented we need to try to dispatch as a regular down.
- }
- }
- if (doDown) {
- if (mMovement.onKeyDown(this, (Spannable)mText, keyCode, event))
- return 2;
- }
- }
-
- return 0;
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (!isEnabled()) {
- return super.onKeyUp(keyCode, event);
- }
-
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- /*
- * If there is a click listener, just call through to
- * super, which will invoke it.
- *
- * If there isn't a click listener, try to show the soft
- * input method. (It will also
- * call performClick(), but that won't do anything in
- * this case.)
- */
- if (mOnClickListener == null) {
- if (mMovement != null && mText instanceof Editable
- && mLayout != null && onCheckIsTextEditor()) {
- InputMethodManager imm = (InputMethodManager)
- getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(this, 0);
- }
- }
- return super.onKeyUp(keyCode, event);
-
- case KeyEvent.KEYCODE_ENTER:
- if (advanceFocusOnEnter()) {
- /*
- * If there is a click listener, just call through to
- * super, which will invoke it.
- *
- * If there isn't a click listener, try to advance focus,
- * but still call through to super, which will reset the
- * pressed state and longpress state. (It will also
- * call performClick(), but that won't do anything in
- * this case.)
- */
- if (mOnClickListener == null) {
- View v = focusSearch(FOCUS_DOWN);
-
- if (v != null) {
- if (!v.requestFocus(FOCUS_DOWN)) {
- throw new IllegalStateException("focus search returned a view " +
- "that wasn't able to take focus!");
- }
-
- /*
- * Return true because we handled the key; super
- * will return false because there was no click
- * listener.
- */
- super.onKeyUp(keyCode, event);
- return true;
- }
- }
-
- return super.onKeyUp(keyCode, event);
- }
- }
-
- if (mInput != null)
- if (mInput.onKeyUp(this, (Editable) mText, keyCode, event))
- return true;
-
- if (mMovement != null && mLayout != null)
- if (mMovement.onKeyUp(this, (Spannable) mText, keyCode, event))
- return true;
-
- return super.onKeyUp(keyCode, event);
- }
-
- @Override public boolean onCheckIsTextEditor() {
- return mInputType != EditorInfo.TYPE_NULL;
- }
-
- @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
- if (onCheckIsTextEditor()) {
- if (mInputMethodState == null) {
- mInputMethodState = new InputMethodState();
- }
- outAttrs.inputType = mInputType;
- outAttrs.hintText = mHint;
- if (mInputContentType != null) {
- outAttrs.privateContentType = mInputContentType.privateContentType;
- outAttrs.extras = mInputContentType.extras;
- }
- if (mText instanceof Editable) {
- InputConnection ic = new EditableInputConnection(this);
- outAttrs.initialSelStart = Selection.getSelectionStart(mText);
- outAttrs.initialSelEnd = Selection.getSelectionEnd(mText);
- outAttrs.initialCapsMode = ic.getCursorCapsMode(mInputType);
- return ic;
- }
- }
- return null;
- }
-
- /**
- * If this TextView contains editable content, extract a portion of it
- * based on the information in <var>request</var> in to <var>outText</var>.
- * @return Returns true if the text was successfully extracted, else false.
- */
- public boolean extractText(ExtractedTextRequest request,
- ExtractedText outText) {
- return extractTextInternal(request, -1, -1, -1, outText);
- }
-
- boolean extractTextInternal(ExtractedTextRequest request,
- int partialStartOffset, int partialEndOffset, int delta,
- ExtractedText outText) {
- final CharSequence content = mText;
- if (content != null) {
- final int N = content.length();
- if (partialStartOffset < 0) {
- outText.partialStartOffset = outText.partialEndOffset = -1;
- partialStartOffset = 0;
- partialEndOffset = N;
- } else {
- // Adjust offsets to ensure we contain full spans.
- if (content instanceof Spanned) {
- Spanned spanned = (Spanned)content;
- Object[] spans = spanned.getSpans(partialStartOffset,
- partialEndOffset, ParcelableSpan.class);
- int i = spans.length;
- while (i > 0) {
- i--;
- int j = spanned.getSpanStart(spans[i]);
- if (j < partialStartOffset) partialStartOffset = j;
- j = spanned.getSpanEnd(spans[i]);
- if (j > partialEndOffset) partialEndOffset = j;
- }
- }
- outText.partialStartOffset = partialStartOffset;
- outText.partialEndOffset = partialEndOffset;
- // Now use the delta to determine the actual amount of text
- // we need.
- partialEndOffset += delta;
- if (partialEndOffset > N) {
- partialEndOffset = N;
- } else if (partialEndOffset < 0) {
- partialEndOffset = 0;
- }
- }
- if ((request.flags&InputConnection.GET_TEXT_WITH_STYLES) != 0) {
- outText.text = content.subSequence(partialStartOffset,
- partialEndOffset);
- } else {
- outText.text = TextUtils.substring(content, partialStartOffset,
- partialEndOffset);
- }
- outText.startOffset = 0;
- outText.selectionStart = Selection.getSelectionStart(content);
- outText.selectionEnd = Selection.getSelectionEnd(content);
- return true;
- }
- return false;
- }
-
- boolean reportExtractedText() {
- final InputMethodState ims = mInputMethodState;
- if (ims != null && ims.mContentChanged) {
- ims.mContentChanged = false;
- final ExtractedTextRequest req = mInputMethodState.mExtracting;
- if (req != null) {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) {
- if (DEBUG_EXTRACT) Log.v(TAG, "Retrieving extracted start="
- + ims.mChangedStart + " end=" + ims.mChangedEnd
- + " delta=" + ims.mChangedDelta);
- if (extractTextInternal(req, ims.mChangedStart, ims.mChangedEnd,
- ims.mChangedDelta, ims.mTmpExtracted)) {
- if (DEBUG_EXTRACT) Log.v(TAG, "Reporting extracted start="
- + ims.mTmpExtracted.partialStartOffset
- + " end=" + ims.mTmpExtracted.partialEndOffset
- + ": " + ims.mTmpExtracted.text);
- imm.updateExtractedText(this, req.token,
- mInputMethodState.mTmpExtracted);
- return true;
- }
- }
- }
- }
- return false;
- }
-
- /**
- * This is used to remove all style-impacting spans from text before new
- * extracted text is being replaced into it, so that we don't have any
- * lingering spans applied during the replace.
- */
- static void removeParcelableSpans(Spannable spannable, int start, int end) {
- Object[] spans = spannable.getSpans(start, end, ParcelableSpan.class);
- int i = spans.length;
- while (i > 0) {
- i--;
- spannable.removeSpan(spans[i]);
- }
- }
-
- /**
- * Apply to this text view the given extracted text, as previously
- * returned by {@link #extractText(ExtractedTextRequest, ExtractedText)}.
- */
- public void setExtractedText(ExtractedText text) {
- Editable content = getEditableText();
- if (content == null) {
- setText(text.text, TextView.BufferType.EDITABLE);
- } else if (text.partialStartOffset < 0) {
- removeParcelableSpans(content, 0, content.length());
- content.replace(0, content.length(), text.text);
- } else {
- final int N = content.length();
- int start = text.partialStartOffset;
- if (start > N) start = N;
- int end = text.partialEndOffset;
- if (end > N) end = N;
- removeParcelableSpans(content, start, end);
- content.replace(start, end, text.text);
- }
-
- // Now set the selection position... make sure it is in range, to
- // avoid crashes. If this is a partial update, it is possible that
- // the underlying text may have changed, causing us problems here.
- // Also we just don't want to trust clients to do the right thing.
- Spannable sp = (Spannable)getText();
- final int N = sp.length();
- int start = text.selectionStart;
- if (start < 0) start = 0;
- else if (start > N) start = N;
- int end = text.selectionEnd;
- if (end < 0) end = 0;
- else if (end > N) end = N;
- Selection.setSelection(sp, start, end);
- }
-
- /**
- * @hide
- */
- public void setExtracting(ExtractedTextRequest req) {
- if (mInputMethodState != null) {
- mInputMethodState.mExtracting = req;
- }
- }
-
- /**
- * Called by the framework in response to a text completion from
- * the current input method, provided by it calling
- * {@link InputConnection#commitCompletion
- * InputConnection.commitCompletion()}. The default implementation does
- * nothing; text views that are supporting auto-completion should override
- * this to do their desired behavior.
- *
- * @param text The auto complete text the user has selected.
- */
- public void onCommitCompletion(CompletionInfo text) {
- }
-
- public void beginBatchEdit() {
- final InputMethodState ims = mInputMethodState;
- if (ims != null) {
- int nesting = ++ims.mBatchEditNesting;
- if (nesting == 1) {
- ims.mCursorChanged = false;
- ims.mChangedDelta = 0;
- if (ims.mContentChanged) {
- // We already have a pending change from somewhere else,
- // so turn this into a full update.
- ims.mChangedStart = 0;
- ims.mChangedEnd = mText.length();
- } else {
- ims.mChangedStart = -1;
- ims.mChangedEnd = -1;
- ims.mContentChanged = false;
- }
- onBeginBatchEdit();
- }
- }
- }
-
- public void endBatchEdit() {
- final InputMethodState ims = mInputMethodState;
- if (ims != null) {
- int nesting = --ims.mBatchEditNesting;
- if (nesting == 0) {
- finishBatchEdit(ims);
- }
- }
- }
-
- void ensureEndedBatchEdit() {
- final InputMethodState ims = mInputMethodState;
- if (ims != null && ims.mBatchEditNesting != 0) {
- ims.mBatchEditNesting = 0;
- finishBatchEdit(ims);
- }
- }
-
- void finishBatchEdit(final InputMethodState ims) {
- onEndBatchEdit();
-
- if (ims.mContentChanged) {
- updateAfterEdit();
- reportExtractedText();
- } else if (ims.mCursorChanged) {
- // Cheezy way to get us to report the current cursor location.
- invalidateCursor();
- }
- }
-
- void updateAfterEdit() {
- invalidate();
- int curs = Selection.getSelectionStart(mText);
-
- if (curs >= 0 || (mGravity & Gravity.VERTICAL_GRAVITY_MASK) ==
- Gravity.BOTTOM) {
- registerForPreDraw();
- }
-
- if (curs >= 0) {
- mHighlightPathBogus = true;
-
- if (isFocused()) {
- mShowCursor = SystemClock.uptimeMillis();
- makeBlink();
- }
- }
-
- checkForResize();
- }
-
- /**
- * Called by the framework in response to a request to begin a batch
- * of edit operations through a call to link {@link #beginBatchEdit()}.
- */
- public void onBeginBatchEdit() {
- }
-
- /**
- * Called by the framework in response to a request to end a batch
- * of edit operations through a call to link {@link #endBatchEdit}.
- */
- public void onEndBatchEdit() {
- }
-
- /**
- * Called by the framework in response to a private command from the
- * current method, provided by it calling
- * {@link InputConnection#performPrivateCommand
- * InputConnection.performPrivateCommand()}.
- *
- * @param action The action name of the command.
- * @param data Any additional data for the command. This may be null.
- * @return Return true if you handled the command, else false.
- */
- public boolean onPrivateIMECommand(String action, Bundle data) {
- return false;
- }
-
- private void nullLayouts() {
- if (mLayout instanceof BoringLayout && mSavedLayout == null) {
- mSavedLayout = (BoringLayout) mLayout;
- }
- if (mHintLayout instanceof BoringLayout && mSavedHintLayout == null) {
- mSavedHintLayout = (BoringLayout) mHintLayout;
- }
-
- mLayout = mHintLayout = null;
- }
-
- /**
- * Make a new Layout based on the already-measured size of the view,
- * on the assumption that it was measured correctly at some point.
- */
- private void assumeLayout() {
- int width = mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight();
-
- if (width < 1) {
- width = 0;
- }
-
- int physicalWidth = width;
-
- if (mHorizontallyScrolling) {
- width = VERY_WIDE;
- }
-
- makeNewLayout(width, physicalWidth, UNKNOWN_BORING, UNKNOWN_BORING,
- physicalWidth, false);
- }
-
- /**
- * The width passed in is now the desired layout width,
- * not the full view width with padding.
- * {@hide}
- */
- protected void makeNewLayout(int w, int hintWidth,
- BoringLayout.Metrics boring,
- BoringLayout.Metrics hintBoring,
- int ellipsisWidth, boolean bringIntoView) {
- stopMarquee();
-
- mHighlightPathBogus = true;
-
- if (w < 0) {
- w = 0;
- }
- if (hintWidth < 0) {
- hintWidth = 0;
- }
-
- Layout.Alignment alignment;
- switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.CENTER_HORIZONTAL:
- alignment = Layout.Alignment.ALIGN_CENTER;
- break;
-
- case Gravity.RIGHT:
- alignment = Layout.Alignment.ALIGN_OPPOSITE;
- break;
-
- default:
- alignment = Layout.Alignment.ALIGN_NORMAL;
- }
-
- if (mText instanceof Spannable) {
- mLayout = new DynamicLayout(mText, mTransformed, mTextPaint, w,
- alignment, mSpacingMult,
- mSpacingAdd, mIncludePad, mEllipsize,
- ellipsisWidth);
- } else {
- if (boring == UNKNOWN_BORING) {
- boring = BoringLayout.isBoring(mTransformed, mTextPaint,
- mBoring);
- if (boring != null) {
- mBoring = boring;
- }
- }
-
- if (boring != null) {
- if (boring.width <= w &&
- (mEllipsize == null || boring.width <= ellipsisWidth)) {
- if (mSavedLayout != null) {
- mLayout = mSavedLayout.
- replaceOrMake(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
- boring, mIncludePad);
- } else {
- mLayout = BoringLayout.make(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
- boring, mIncludePad);
- }
- // Log.e("aaa", "Boring: " + mTransformed);
-
- mSavedLayout = (BoringLayout) mLayout;
- } else if (mEllipsize != null && boring.width <= w) {
- if (mSavedLayout != null) {
- mLayout = mSavedLayout.
- replaceOrMake(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
- boring, mIncludePad, mEllipsize,
- ellipsisWidth);
- } else {
- mLayout = BoringLayout.make(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
- boring, mIncludePad, mEllipsize,
- ellipsisWidth);
- }
- } else if (mEllipsize != null) {
- mLayout = new StaticLayout(mTransformed,
- 0, mTransformed.length(),
- mTextPaint, w, alignment, mSpacingMult,
- mSpacingAdd, mIncludePad, mEllipsize,
- ellipsisWidth);
- } else {
- mLayout = new StaticLayout(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
- mIncludePad);
- // Log.e("aaa", "Boring but wide: " + mTransformed);
- }
- } else if (mEllipsize != null) {
- mLayout = new StaticLayout(mTransformed,
- 0, mTransformed.length(),
- mTextPaint, w, alignment, mSpacingMult,
- mSpacingAdd, mIncludePad, mEllipsize,
- ellipsisWidth);
- } else {
- mLayout = new StaticLayout(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
- mIncludePad);
- }
- }
-
- mHintLayout = null;
-
- if (mHint != null) {
- if (hintBoring == UNKNOWN_BORING) {
- hintBoring = BoringLayout.isBoring(mHint, mTextPaint,
- mHintBoring);
- if (hintBoring != null) {
- mHintBoring = hintBoring;
- }
- }
-
- if (hintBoring != null) {
- if (hintBoring.width <= hintWidth) {
- if (mSavedHintLayout != null) {
- mHintLayout = mSavedHintLayout.
- replaceOrMake(mHint, mTextPaint,
- hintWidth, alignment, mSpacingMult,
- mSpacingAdd, hintBoring, mIncludePad);
- } else {
- mHintLayout = BoringLayout.make(mHint, mTextPaint,
- hintWidth, alignment, mSpacingMult,
- mSpacingAdd, hintBoring, mIncludePad);
- }
-
- mSavedHintLayout = (BoringLayout) mHintLayout;
- } else {
- mHintLayout = new StaticLayout(mHint, mTextPaint,
- hintWidth, alignment, mSpacingMult, mSpacingAdd,
- mIncludePad);
- }
- } else {
- mHintLayout = new StaticLayout(mHint, mTextPaint,
- hintWidth, alignment, mSpacingMult, mSpacingAdd,
- mIncludePad);
- }
- }
-
- if (bringIntoView) {
- registerForPreDraw();
- }
-
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
- final int height = mLayoutParams.height;
- // If the size of the view does not depend on the size of the text, try to
- // start the marquee immediately
- if (height != LayoutParams.WRAP_CONTENT && height != LayoutParams.FILL_PARENT) {
- startMarquee();
- } else {
- // Defer the start of the marquee until we know our width (see setFrame())
- mRestartMarquee = true;
- }
- }
- }
-
- private static int desired(Layout layout) {
- int n = layout.getLineCount();
- CharSequence text = layout.getText();
- float max = 0;
-
- // if any line was wrapped, we can't use it.
- // but it's ok for the last line not to have a newline
-
- for (int i = 0; i < n - 1; i++) {
- if (text.charAt(layout.getLineEnd(i) - 1) != '\n')
- return -1;
- }
-
- for (int i = 0; i < n; i++) {
- max = Math.max(max, layout.getLineWidth(i));
- }
-
- return (int) FloatMath.ceil(max);
- }
-
- /**
- * Set whether the TextView includes extra top and bottom padding to make
- * room for accents that go above the normal ascent and descent.
- * The default is true.
- *
- * @attr ref android.R.styleable#TextView_includeFontPadding
- */
- public void setIncludeFontPadding(boolean includepad) {
- mIncludePad = includepad;
-
- if (mLayout != null) {
- nullLayouts();
- requestLayout();
- invalidate();
- }
- }
-
- private static final BoringLayout.Metrics UNKNOWN_BORING =
- new BoringLayout.Metrics();
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
- int width;
- int height;
-
- BoringLayout.Metrics boring = UNKNOWN_BORING;
- BoringLayout.Metrics hintBoring = UNKNOWN_BORING;
-
- int des = -1;
- boolean fromexisting = false;
-
- if (widthMode == MeasureSpec.EXACTLY) {
- // Parent has told us how big to be. So be it.
- width = widthSize;
- } else {
- if (mLayout != null && mEllipsize == null) {
- des = desired(mLayout);
- }
-
- if (des < 0) {
- boring = BoringLayout.isBoring(mTransformed, mTextPaint,
- mBoring);
- if (boring != null) {
- mBoring = boring;
- }
- } else {
- fromexisting = true;
- }
-
- if (boring == null || boring == UNKNOWN_BORING) {
- if (des < 0) {
- des = (int) FloatMath.ceil(Layout.
- getDesiredWidth(mTransformed, mTextPaint));
- }
-
- width = des;
- } else {
- width = boring.width;
- }
-
- final Drawables dr = mDrawables;
- if (dr != null) {
- width = Math.max(width, dr.mDrawableWidthTop);
- width = Math.max(width, dr.mDrawableWidthBottom);
- }
-
- if (mHint != null) {
- int hintDes = -1;
- int hintWidth;
-
- if (mHintLayout != null) {
- hintDes = desired(mHintLayout);
- }
-
- if (hintDes < 0) {
- hintBoring = BoringLayout.isBoring(mHint, mTextPaint,
- mHintBoring);
- if (hintBoring != null) {
- mHintBoring = hintBoring;
- }
- }
-
- if (hintBoring == null || hintBoring == UNKNOWN_BORING) {
- if (hintDes < 0) {
- hintDes = (int) FloatMath.ceil(Layout.
- getDesiredWidth(mHint, mTextPaint));
- }
-
- hintWidth = hintDes;
- } else {
- hintWidth = hintBoring.width;
- }
-
- if (hintWidth > width) {
- width = hintWidth;
- }
- }
-
- width += getCompoundPaddingLeft() + getCompoundPaddingRight();
-
- if (mMaxWidthMode == EMS) {
- width = Math.min(width, mMaxWidth * getLineHeight());
- } else {
- width = Math.min(width, mMaxWidth);
- }
-
- if (mMinWidthMode == EMS) {
- width = Math.max(width, mMinWidth * getLineHeight());
- } else {
- width = Math.max(width, mMinWidth);
- }
-
- // Check against our minimum width
- width = Math.max(width, getSuggestedMinimumWidth());
-
- if (widthMode == MeasureSpec.AT_MOST) {
- width = Math.min(widthSize, width);
- }
- }
-
- int want = width - getCompoundPaddingLeft() - getCompoundPaddingRight();
- int unpaddedWidth = want;
- int hintWant = want;
-
- if (mHorizontallyScrolling)
- want = VERY_WIDE;
-
- int hintWidth = mHintLayout == null ? hintWant : mHintLayout.getWidth();
-
- if (mLayout == null) {
- makeNewLayout(want, hintWant, boring, hintBoring,
- width - getCompoundPaddingLeft() - getCompoundPaddingRight(),
- false);
- } else if ((mLayout.getWidth() != want) || (hintWidth != hintWant) ||
- (mLayout.getEllipsizedWidth() !=
- width - getCompoundPaddingLeft() - getCompoundPaddingRight())) {
- if (mHint == null && mEllipsize == null &&
- want > mLayout.getWidth() &&
- (mLayout instanceof BoringLayout ||
- (fromexisting && des >= 0 && des <= want))) {
- mLayout.increaseWidthTo(want);
- } else {
- makeNewLayout(want, hintWant, boring, hintBoring,
- width - getCompoundPaddingLeft() - getCompoundPaddingRight(),
- false);
- }
- } else {
- // Width has not changed.
- }
-
- if (heightMode == MeasureSpec.EXACTLY) {
- // Parent has told us how big to be. So be it.
- height = heightSize;
- mDesiredHeightAtMeasure = -1;
- } else {
- int desired = getDesiredHeight();
-
- height = desired;
- mDesiredHeightAtMeasure = desired;
-
- if (heightMode == MeasureSpec.AT_MOST) {
- height = Math.min(desired, height);
- }
- }
-
- int unpaddedHeight = height - getCompoundPaddingTop() -
- getCompoundPaddingBottom();
- if (mMaxMode == LINES && mLayout.getLineCount() > mMaximum) {
- unpaddedHeight = Math.min(unpaddedHeight,
- mLayout.getLineTop(mMaximum));
- }
-
- /*
- * We didn't let makeNewLayout() register to bring the cursor into view,
- * so do it here if there is any possibility that it is needed.
- */
- if (mMovement != null ||
- mLayout.getWidth() > unpaddedWidth ||
- mLayout.getHeight() > unpaddedHeight) {
- registerForPreDraw();
- } else {
- scrollTo(0, 0);
- }
-
- setMeasuredDimension(width, height);
- }
-
- private int getDesiredHeight() {
- return Math.max(getDesiredHeight(mLayout, true),
- getDesiredHeight(mHintLayout, false));
- }
-
- private int getDesiredHeight(Layout layout, boolean cap) {
- if (layout == null) {
- return 0;
- }
-
- int linecount = layout.getLineCount();
- int pad = getCompoundPaddingTop() + getCompoundPaddingBottom();
- int desired = layout.getLineTop(linecount);
-
- final Drawables dr = mDrawables;
- if (dr != null) {
- desired = Math.max(desired, dr.mDrawableHeightLeft);
- desired = Math.max(desired, dr.mDrawableHeightRight);
- }
-
- desired += pad;
-
- if (mMaxMode == LINES) {
- /*
- * Don't cap the hint to a certain number of lines.
- * (Do cap it, though, if we have a maximum pixel height.)
- */
- if (cap) {
- if (linecount > mMaximum) {
- desired = layout.getLineTop(mMaximum) +
- layout.getBottomPadding();
-
- if (dr != null) {
- desired = Math.max(desired, dr.mDrawableHeightLeft);
- desired = Math.max(desired, dr.mDrawableHeightRight);
- }
-
- desired += pad;
- linecount = mMaximum;
- }
- }
- } else {
- desired = Math.min(desired, mMaximum);
- }
-
- if (mMinMode == LINES) {
- if (linecount < mMinimum) {
- desired += getLineHeight() * (mMinimum - linecount);
- }
- } else {
- desired = Math.max(desired, mMinimum);
- }
-
- // Check against our minimum height
- desired = Math.max(desired, getSuggestedMinimumHeight());
-
- return desired;
- }
-
- /**
- * Check whether a change to the existing text layout requires a
- * new view layout.
- */
- private void checkForResize() {
- boolean sizeChanged = false;
-
- if (mLayout != null) {
- // Check if our width changed
- if (mLayoutParams.width == LayoutParams.WRAP_CONTENT) {
- sizeChanged = true;
- invalidate();
- }
-
- // Check if our height changed
- if (mLayoutParams.height == LayoutParams.WRAP_CONTENT) {
- int desiredHeight = getDesiredHeight();
-
- if (desiredHeight != this.getHeight()) {
- sizeChanged = true;
- }
- } else if (mLayoutParams.height == LayoutParams.FILL_PARENT) {
- if (mDesiredHeightAtMeasure >= 0) {
- int desiredHeight = getDesiredHeight();
-
- if (desiredHeight != mDesiredHeightAtMeasure) {
- sizeChanged = true;
- }
- }
- }
- }
-
- if (sizeChanged) {
- requestLayout();
- // caller will have already invalidated
- }
- }
-
- /**
- * Check whether entirely new text requires a new view layout
- * or merely a new text layout.
- */
- private void checkForRelayout() {
- // If we have a fixed width, we can just swap in a new text layout
- // if the text height stays the same or if the view height is fixed.
-
- if ((mLayoutParams.width != LayoutParams.WRAP_CONTENT ||
- (mMaxWidthMode == mMinWidthMode && mMaxWidth == mMinWidth)) &&
- (mHint == null || mHintLayout != null) &&
- (mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight() > 0)) {
- // Static width, so try making a new text layout.
-
- int oldht = mLayout.getHeight();
- int want = mLayout.getWidth();
- int hintWant = mHintLayout == null ? 0 : mHintLayout.getWidth();
-
- /*
- * No need to bring the text into view, since the size is not
- * changing (unless we do the requestLayout(), in which case it
- * will happen at measure).
- */
- makeNewLayout(want, hintWant, UNKNOWN_BORING, UNKNOWN_BORING,
- mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(), false);
-
- // In a fixed-height view, so use our new text layout.
- if (mLayoutParams.height != LayoutParams.WRAP_CONTENT &&
- mLayoutParams.height != LayoutParams.FILL_PARENT) {
- invalidate();
- return;
- }
-
- // Dynamic height, but height has stayed the same,
- // so use our new text layout.
- if (mLayout.getHeight() == oldht &&
- (mHintLayout == null || mHintLayout.getHeight() == oldht)) {
- invalidate();
- return;
- }
-
- // We lose: the height has changed and we have a dynamic height.
- // Request a new view layout using our new text layout.
- requestLayout();
- invalidate();
- } else {
- // Dynamic width, so we have no choice but to request a new
- // view layout with a new text layout.
-
- nullLayouts();
- requestLayout();
- invalidate();
- }
- }
-
- /**
- * Returns true if anything changed.
- */
- private boolean bringTextIntoView() {
- int line = 0;
- if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
- line = mLayout.getLineCount() - 1;
- }
-
- Layout.Alignment a = mLayout.getParagraphAlignment(line);
- int dir = mLayout.getParagraphDirection(line);
- int hspace = mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight();
- int vspace = mBottom - mTop - getExtendedPaddingTop() - getExtendedPaddingBottom();
- int ht = mLayout.getHeight();
-
- int scrollx, scrolly;
-
- if (a == Layout.Alignment.ALIGN_CENTER) {
- /*
- * Keep centered if possible, or, if it is too wide to fit,
- * keep leading edge in view.
- */
-
- int left = (int) FloatMath.floor(mLayout.getLineLeft(line));
- int right = (int) FloatMath.ceil(mLayout.getLineRight(line));
-
- if (right - left < hspace) {
- scrollx = (right + left) / 2 - hspace / 2;
- } else {
- if (dir < 0) {
- scrollx = right - hspace;
- } else {
- scrollx = left;
- }
- }
- } else if (a == Layout.Alignment.ALIGN_NORMAL) {
- /*
- * Keep leading edge in view.
- */
-
- if (dir < 0) {
- int right = (int) FloatMath.ceil(mLayout.getLineRight(line));
- scrollx = right - hspace;
- } else {
- scrollx = (int) FloatMath.floor(mLayout.getLineLeft(line));
- }
- } else /* a == Layout.Alignment.ALIGN_OPPOSITE */ {
- /*
- * Keep trailing edge in view.
- */
-
- if (dir < 0) {
- scrollx = (int) FloatMath.floor(mLayout.getLineLeft(line));
- } else {
- int right = (int) FloatMath.ceil(mLayout.getLineRight(line));
- scrollx = right - hspace;
- }
- }
-
- if (ht < vspace) {
- scrolly = 0;
- } else {
- if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
- scrolly = ht - vspace;
- } else {
- scrolly = 0;
- }
- }
-
- if (scrollx != mScrollX || scrolly != mScrollY) {
- scrollTo(scrollx, scrolly);
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Move the point, specified by the offset, into the view if it is needed.
- * This has to be called after layout. Returns true if anything changed.
- */
- public boolean bringPointIntoView(int offset) {
- boolean changed = false;
-
- int line = mLayout.getLineForOffset(offset);
-
- // FIXME: Is it okay to truncate this, or should we round?
- final int x = (int)mLayout.getPrimaryHorizontal(offset);
- final int top = mLayout.getLineTop(line);
- final int bottom = mLayout.getLineTop(line+1);
-
- int left = (int) FloatMath.floor(mLayout.getLineLeft(line));
- int right = (int) FloatMath.ceil(mLayout.getLineRight(line));
- int ht = mLayout.getHeight();
-
- int grav;
-
- switch (mLayout.getParagraphAlignment(line)) {
- case ALIGN_NORMAL:
- grav = 1;
- break;
-
- case ALIGN_OPPOSITE:
- grav = -1;
- break;
-
- default:
- grav = 0;
- }
-
- grav *= mLayout.getParagraphDirection(line);
-
- int hspace = mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight();
- int vspace = mBottom - mTop - getExtendedPaddingTop() - getExtendedPaddingBottom();
-
- int hslack = (bottom - top) / 2;
- int vslack = hslack;
-
- if (vslack > vspace / 4)
- vslack = vspace / 4;
- if (hslack > hspace / 4)
- hslack = hspace / 4;
-
- int hs = mScrollX;
- int vs = mScrollY;
-
- if (top - vs < vslack)
- vs = top - vslack;
- if (bottom - vs > vspace - vslack)
- vs = bottom - (vspace - vslack);
- if (ht - vs < vspace)
- vs = ht - vspace;
- if (0 - vs > 0)
- vs = 0;
-
- if (grav != 0) {
- if (x - hs < hslack) {
- hs = x - hslack;
- }
- if (x - hs > hspace - hslack) {
- hs = x - (hspace - hslack);
- }
- }
-
- if (grav < 0) {
- if (left - hs > 0)
- hs = left;
- if (right - hs < hspace)
- hs = right - hspace;
- } else if (grav > 0) {
- if (right - hs < hspace)
- hs = right - hspace;
- if (left - hs > 0)
- hs = left;
- } else /* grav == 0 */ {
- if (right - left <= hspace) {
- /*
- * If the entire text fits, center it exactly.
- */
- hs = left - (hspace - (right - left)) / 2;
- } else if (x > right - hslack) {
- /*
- * If we are near the right edge, keep the right edge
- * at the edge of the view.
- */
- hs = right - hspace;
- } else if (x < left + hslack) {
- /*
- * If we are near the left edge, keep the left edge
- * at the edge of the view.
- */
- hs = left;
- } else if (left > hs) {
- /*
- * Is there whitespace visible at the left? Fix it if so.
- */
- hs = left;
- } else if (right < hs + hspace) {
- /*
- * Is there whitespace visible at the right? Fix it if so.
- */
- hs = right - hspace;
- } else {
- /*
- * Otherwise, float as needed.
- */
- if (x - hs < hslack) {
- hs = x - hslack;
- }
- if (x - hs > hspace - hslack) {
- hs = x - (hspace - hslack);
- }
- }
- }
-
- if (hs != mScrollX || vs != mScrollY) {
- if (mScroller == null) {
- scrollTo(hs, vs);
- } else {
- long duration = AnimationUtils.currentAnimationTimeMillis() - mLastScroll;
- int dx = hs - mScrollX;
- int dy = vs - mScrollY;
-
- if (duration > ANIMATED_SCROLL_GAP) {
- mScroller.startScroll(mScrollX, mScrollY, dx, dy);
- invalidate();
- } else {
- if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
- }
-
- scrollBy(dx, dy);
- }
-
- mLastScroll = AnimationUtils.currentAnimationTimeMillis();
- }
-
- changed = true;
- }
-
- if (isFocused()) {
- // This offsets because getInterestingRect() is in terms of
- // viewport coordinates, but requestRectangleOnScreen()
- // is in terms of content coordinates.
-
- Rect r = new Rect();
- getInterestingRect(r, x, top, bottom, line);
- r.offset(mScrollX, mScrollY);
-
- if (requestRectangleOnScreen(r)) {
- changed = true;
- }
- }
-
- return changed;
- }
-
- @Override
- public void computeScroll() {
- if (mScroller != null) {
- if (mScroller.computeScrollOffset()) {
- mScrollX = mScroller.getCurrX();
- mScrollY = mScroller.getCurrY();
- postInvalidate(); // So we draw again
- }
- }
- }
-
- private void getInterestingRect(Rect r, int h, int top, int bottom,
- int line) {
- int paddingTop = getExtendedPaddingTop();
- if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
- paddingTop += getVerticalOffset(false);
- }
- top += paddingTop;
- bottom += paddingTop;
- h += getCompoundPaddingLeft();
-
- if (line == 0)
- top -= getExtendedPaddingTop();
- if (line == mLayout.getLineCount() - 1)
- bottom += getExtendedPaddingBottom();
-
- r.set(h, top, h+1, bottom);
- r.offset(-mScrollX, -mScrollY);
- }
-
- @Override
- public void debug(int depth) {
- super.debug(depth);
-
- String output = debugIndent(depth);
- output += "frame={" + mLeft + ", " + mTop + ", " + mRight
- + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
- + "} ";
-
- if (mText != null) {
-
- output += "mText=\"" + mText + "\" ";
- if (mLayout != null) {
- output += "mLayout width=" + mLayout.getWidth()
- + " height=" + mLayout.getHeight();
- }
- } else {
- output += "mText=NULL";
- }
- Log.d(VIEW_LOG_TAG, output);
- }
-
- /**
- * Convenience for {@link Selection#getSelectionStart}.
- */
- public int getSelectionStart() {
- return Selection.getSelectionStart(getText());
- }
-
- /**
- * Convenience for {@link Selection#getSelectionEnd}.
- */
- public int getSelectionEnd() {
- return Selection.getSelectionEnd(getText());
- }
-
- /**
- * Return true iff there is a selection inside this text view.
- */
- public boolean hasSelection() {
- return getSelectionStart() != getSelectionEnd();
- }
-
- /**
- * Sets the properties of this field (lines, horizontally scrolling,
- * transformation method) to be for a single-line input.
- *
- * @attr ref android.R.styleable#TextView_singleLine
- */
- public void setSingleLine() {
- setSingleLine(true);
- }
-
- /**
- * If true, sets the properties of this field (lines, horizontally
- * scrolling, transformation method) to be for a single-line input;
- * if false, restores these to the default conditions.
- * Note that calling this with false restores default conditions,
- * not necessarily those that were in effect prior to calling
- * it with true.
- *
- * @attr ref android.R.styleable#TextView_singleLine
- */
- @android.view.RemotableViewMethod
- public void setSingleLine(boolean singleLine) {
- if ((mInputType&EditorInfo.TYPE_MASK_CLASS)
- == EditorInfo.TYPE_CLASS_TEXT) {
- if (singleLine) {
- mInputType &= ~EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
- } else {
- mInputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
- }
- }
- applySingleLine(singleLine, true);
- }
-
- private void applySingleLine(boolean singleLine, boolean applyTransformation) {
- mSingleLine = singleLine;
- if (singleLine) {
- setLines(1);
- setHorizontallyScrolling(true);
- if (applyTransformation) {
- setTransformationMethod(SingleLineTransformationMethod.
- getInstance());
- }
- } else {
- setMaxLines(Integer.MAX_VALUE);
- setHorizontallyScrolling(false);
- if (applyTransformation) {
- setTransformationMethod(null);
- }
- }
- }
-
- /**
- * Causes words in the text that are longer than the view is wide
- * to be ellipsized instead of broken in the middle. You may also
- * want to {@link #setSingleLine} or {@link #setHorizontallyScrolling}
- * to constrain the text toa single line. Use <code>null</code>
- * to turn off ellipsizing.
- *
- * @attr ref android.R.styleable#TextView_ellipsize
- */
- public void setEllipsize(TextUtils.TruncateAt where) {
- mEllipsize = where;
-
- if (mLayout != null) {
- nullLayouts();
- requestLayout();
- invalidate();
- }
- }
-
- /**
- * Sets how many times to repeat the marquee animation. Only applied if the
- * TextView has marquee enabled. Set to -1 to repeat indefinitely.
- *
- * @attr ref android.R.styleable#TextView_marqueeRepeatLimit
- */
- public void setMarqueeRepeatLimit(int marqueeLimit) {
- mMarqueeRepeatLimit = marqueeLimit;
- }
-
- /**
- * Returns where, if anywhere, words that are longer than the view
- * is wide should be ellipsized.
- */
- @ViewDebug.ExportedProperty
- public TextUtils.TruncateAt getEllipsize() {
- return mEllipsize;
- }
-
- /**
- * Set the TextView so that when it takes focus, all the text is
- * selected.
- *
- * @attr ref android.R.styleable#TextView_selectAllOnFocus
- */
- @android.view.RemotableViewMethod
- public void setSelectAllOnFocus(boolean selectAllOnFocus) {
- mSelectAllOnFocus = selectAllOnFocus;
-
- if (selectAllOnFocus && !(mText instanceof Spannable)) {
- setText(mText, BufferType.SPANNABLE);
- }
- }
-
- /**
- * Set whether the cursor is visible. The default is true.
- *
- * @attr ref android.R.styleable#TextView_cursorVisible
- */
- @android.view.RemotableViewMethod
- public void setCursorVisible(boolean visible) {
- mCursorVisible = visible;
- invalidate();
-
- if (visible) {
- makeBlink();
- } else if (mBlink != null) {
- mBlink.removeCallbacks(mBlink);
- }
- }
-
- private boolean canMarquee() {
- int width = (mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight());
- return width > 0 && mLayout.getLineWidth(0) > width;
- }
-
- private void startMarquee() {
- if ((mMarquee == null || mMarquee.isStopped()) && (isFocused() || isSelected()) &&
- getLineCount() == 1 && canMarquee()) {
- if (mMarquee == null) mMarquee = new Marquee(this);
- mMarquee.start(mMarqueeRepeatLimit);
- }
- }
-
- private void stopMarquee() {
- if (mMarquee != null && !mMarquee.isStopped()) {
- mMarquee.stop();
- }
- }
-
- private void startStopMarquee(boolean start) {
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
- if (start) {
- startMarquee();
- } else {
- stopMarquee();
- }
- }
- }
-
- private static final class Marquee extends Handler {
- // TODO: Add an option to configure this
- private static final int MARQUEE_DELAY = 1200;
- private static final int MARQUEE_RESTART_DELAY = 1200;
- private static final int MARQUEE_RESOLUTION = 1000 / 30;
- private static final int MARQUEE_PIXELS_PER_SECOND = 30;
-
- private static final byte MARQUEE_STOPPED = 0x0;
- private static final byte MARQUEE_STARTING = 0x1;
- private static final byte MARQUEE_RUNNING = 0x2;
-
- private static final int MESSAGE_START = 0x1;
- private static final int MESSAGE_TICK = 0x2;
- private static final int MESSAGE_RESTART = 0x3;
-
- private final WeakReference<TextView> mView;
-
- private byte mStatus = MARQUEE_STOPPED;
- private float mScrollUnit;
- private float mMaxScroll;
- private int mRepeatLimit;
-
- float mScroll;
-
- Marquee(TextView v) {
- final float density = v.getContext().getResources().getDisplayMetrics().density;
- mScrollUnit = (MARQUEE_PIXELS_PER_SECOND * density) / (float) MARQUEE_RESOLUTION;
- mView = new WeakReference<TextView>(v);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MESSAGE_START:
- mStatus = MARQUEE_RUNNING;
- tick();
- break;
- case MESSAGE_TICK:
- tick();
- break;
- case MESSAGE_RESTART:
- if (mStatus == MARQUEE_RUNNING) {
- if (mRepeatLimit >= 0) {
- mRepeatLimit--;
- }
- start(mRepeatLimit);
- }
- break;
- }
- }
-
- void tick() {
- if (mStatus != MARQUEE_RUNNING) {
- return;
- }
-
- removeMessages(MESSAGE_TICK);
-
- final TextView textView = mView.get();
- if (textView != null && (textView.isFocused() || textView.isSelected())) {
- mScroll += mScrollUnit;
- if (mScroll > mMaxScroll) {
- mScroll = mMaxScroll;
- sendEmptyMessageDelayed(MESSAGE_RESTART, MARQUEE_RESTART_DELAY);
- } else {
- sendEmptyMessageDelayed(MESSAGE_TICK, MARQUEE_RESOLUTION);
- }
- textView.invalidate();
- }
- }
-
- void stop() {
- mStatus = MARQUEE_STOPPED;
- removeMessages(MESSAGE_START);
- removeMessages(MESSAGE_RESTART);
- removeMessages(MESSAGE_TICK);
- resetScroll();
- }
-
- private void resetScroll() {
- mScroll = 0.0f;
- final TextView textView = mView.get();
- if (textView != null) textView.invalidate();
- }
-
- void start(int repeatLimit) {
- if (repeatLimit == 0) {
- stop();
- return;
- }
- mRepeatLimit = repeatLimit;
- final TextView textView = mView.get();
- if (textView != null && textView.mLayout != null) {
- mStatus = MARQUEE_STARTING;
- mScroll = 0.0f;
- mMaxScroll = textView.mLayout.getLineWidth(0) - (textView.getWidth() -
- textView.getCompoundPaddingLeft() - textView.getCompoundPaddingRight());
- textView.invalidate();
- sendEmptyMessageDelayed(MESSAGE_START, MARQUEE_DELAY);
- }
- }
-
- boolean isRunning() {
- return mStatus == MARQUEE_RUNNING;
- }
-
- boolean isStopped() {
- return mStatus == MARQUEE_STOPPED;
- }
- }
-
- /**
- * This method is called when the text is changed, in case any
- * subclasses would like to know.
- *
- * @param text The text the TextView is displaying.
- * @param start The offset of the start of the range of the text
- * that was modified.
- * @param before The offset of the former end of the range of the
- * text that was modified. If text was simply inserted,
- * this will be the same as <code>start</code>.
- * If text was replaced with new text or deleted, the
- * length of the old text was <code>before-start</code>.
- * @param after The offset of the end of the range of the text
- * that was modified. If text was simply deleted,
- * this will be the same as <code>start</code>.
- * If text was replaced with new text or inserted,
- * the length of the new text is <code>after-start</code>.
- */
- protected void onTextChanged(CharSequence text,
- int start, int before, int after) {
- }
-
- /**
- * This method is called when the selection has changed, in case any
- * subclasses would like to know.
- *
- * @param selStart The new selection start location.
- * @param selEnd The new selection end location.
- */
- protected void onSelectionChanged(int selStart, int selEnd) {
- }
-
- /**
- * Adds a TextWatcher to the list of those whose methods are called
- * whenever this TextView's text changes.
- * <p>
- * In 1.0, the {@link TextWatcher#afterTextChanged} method was erroneously
- * not called after {@link #setText} calls. Now, doing {@link #setText}
- * if there are any text changed listeners forces the buffer type to
- * Editable if it would not otherwise be and does call this method.
- */
- public void addTextChangedListener(TextWatcher watcher) {
- if (mListeners == null) {
- mListeners = new ArrayList<TextWatcher>();
- }
-
- mListeners.add(watcher);
- }
-
- /**
- * Removes the specified TextWatcher from the list of those whose
- * methods are called
- * whenever this TextView's text changes.
- */
- public void removeTextChangedListener(TextWatcher watcher) {
- if (mListeners != null) {
- int i = mListeners.indexOf(watcher);
-
- if (i >= 0) {
- mListeners.remove(i);
- }
- }
- }
-
- private void sendBeforeTextChanged(CharSequence text, int start, int before,
- int after) {
- if (mListeners != null) {
- final ArrayList<TextWatcher> list = mListeners;
- final int count = list.size();
- for (int i = 0; i < count; i++) {
- list.get(i).beforeTextChanged(text, start, before, after);
- }
- }
- }
-
- /**
- * Not private so it can be called from an inner class without going
- * through a thunk.
- */
- void sendOnTextChanged(CharSequence text, int start, int before,
- int after) {
- if (mListeners != null) {
- final ArrayList<TextWatcher> list = mListeners;
- final int count = list.size();
- for (int i = 0; i < count; i++) {
- list.get(i).onTextChanged(text, start, before, after);
- }
- }
- }
-
- /**
- * Not private so it can be called from an inner class without going
- * through a thunk.
- */
- void sendAfterTextChanged(Editable text) {
- if (mListeners != null) {
- final ArrayList<TextWatcher> list = mListeners;
- final int count = list.size();
- for (int i = 0; i < count; i++) {
- list.get(i).afterTextChanged(text);
- }
- }
- }
-
- /**
- * Not private so it can be called from an inner class without going
- * through a thunk.
- */
- void handleTextChanged(CharSequence buffer, int start,
- int before, int after) {
- final InputMethodState ims = mInputMethodState;
- if (ims == null || ims.mBatchEditNesting == 0) {
- updateAfterEdit();
- }
- if (ims != null) {
- ims.mContentChanged = true;
- if (ims.mChangedStart < 0) {
- ims.mChangedStart = start;
- ims.mChangedEnd = start+before;
- } else {
- if (ims.mChangedStart > start) ims.mChangedStart = start;
- if (ims.mChangedEnd < (start+before)) ims.mChangedEnd = start+before;
- }
- ims.mChangedDelta += after-before;
- }
-
- sendOnTextChanged(buffer, start, before, after);
- onTextChanged(buffer, start, before, after);
- }
-
- /**
- * Not private so it can be called from an inner class without going
- * through a thunk.
- */
- void spanChange(Spanned buf, Object what, int oldStart, int newStart,
- int oldEnd, int newEnd) {
- // XXX Make the start and end move together if this ends up
- // spending too much time invalidating.
-
- boolean selChanged = false;
- int newSelStart=-1, newSelEnd=-1;
-
- final InputMethodState ims = mInputMethodState;
-
- if (what == Selection.SELECTION_END) {
- mHighlightPathBogus = true;
- selChanged = true;
- newSelEnd = newStart;
-
- if (!isFocused()) {
- mSelectionMoved = true;
- }
-
- if (oldStart >= 0 || newStart >= 0) {
- invalidateCursor(Selection.getSelectionStart(buf), oldStart, newStart);
- registerForPreDraw();
-
- if (isFocused()) {
- mShowCursor = SystemClock.uptimeMillis();
- makeBlink();
- }
- }
- }
-
- if (what == Selection.SELECTION_START) {
- mHighlightPathBogus = true;
- selChanged = true;
- newSelStart = newStart;
-
- if (!isFocused()) {
- mSelectionMoved = true;
- }
-
- if (oldStart >= 0 || newStart >= 0) {
- int end = Selection.getSelectionEnd(buf);
- invalidateCursor(end, oldStart, newStart);
- }
- }
-
- if (selChanged) {
- if ((buf.getSpanFlags(what)&Spanned.SPAN_INTERMEDIATE) == 0) {
- if (newSelStart < 0) {
- newSelStart = Selection.getSelectionStart(buf);
- }
- if (newSelEnd < 0) {
- newSelEnd = Selection.getSelectionEnd(buf);
- }
- onSelectionChanged(newSelStart, newSelEnd);
- }
- }
-
- if (what instanceof UpdateAppearance ||
- what instanceof ParagraphStyle) {
- if (ims == null || ims.mBatchEditNesting == 0) {
- invalidate();
- mHighlightPathBogus = true;
- checkForResize();
- } else {
- ims.mContentChanged = true;
- }
- }
-
- if (MetaKeyKeyListener.isMetaTracker(buf, what)) {
- mHighlightPathBogus = true;
-
- if (Selection.getSelectionStart(buf) >= 0) {
- if (ims == null || ims.mBatchEditNesting == 0) {
- invalidateCursor();
- } else {
- ims.mCursorChanged = true;
- }
- }
- }
-
- if (what instanceof ParcelableSpan) {
- // If this is a span that can be sent to a remote process,
- // the current extract editor would be interested in it.
- if (ims != null && ims.mExtracting != null) {
- if (ims.mBatchEditNesting != 0) {
- if (oldStart >= 0) {
- if (ims.mChangedStart > oldStart) {
- ims.mChangedStart = oldStart;
- }
- if (ims.mChangedStart > oldEnd) {
- ims.mChangedStart = oldEnd;
- }
- }
- if (newStart >= 0) {
- if (ims.mChangedStart > newStart) {
- ims.mChangedStart = newStart;
- }
- if (ims.mChangedStart > newEnd) {
- ims.mChangedStart = newEnd;
- }
- }
- } else {
- if (DEBUG_EXTRACT) Log.v(TAG, "Span change outside of batch: "
- + oldStart + "-" + oldEnd + ","
- + newStart + "-" + newEnd + what);
- ims.mContentChanged = true;
- }
- }
- }
- }
-
- private class ChangeWatcher
- implements TextWatcher, SpanWatcher {
- public void beforeTextChanged(CharSequence buffer, int start,
- int before, int after) {
- if (DEBUG_EXTRACT) Log.v(TAG, "beforeTextChanged start=" + start
- + " before=" + before + " after=" + after + ": " + buffer);
- TextView.this.sendBeforeTextChanged(buffer, start, before, after);
- }
-
- public void onTextChanged(CharSequence buffer, int start,
- int before, int after) {
- if (DEBUG_EXTRACT) Log.v(TAG, "onTextChanged start=" + start
- + " before=" + before + " after=" + after + ": " + buffer);
- TextView.this.handleTextChanged(buffer, start, before, after);
- }
-
- public void afterTextChanged(Editable buffer) {
- if (DEBUG_EXTRACT) Log.v(TAG, "afterTextChanged: " + buffer);
- TextView.this.sendAfterTextChanged(buffer);
-
- if (MetaKeyKeyListener.getMetaState(buffer,
- MetaKeyKeyListener.META_SELECTING) != 0) {
- MetaKeyKeyListener.stopSelecting(TextView.this, buffer);
- }
- }
-
- public void onSpanChanged(Spannable buf,
- Object what, int s, int e, int st, int en) {
- if (DEBUG_EXTRACT) Log.v(TAG, "onSpanChanged s=" + s + " e=" + e
- + " st=" + st + " en=" + en + " what=" + what + ": " + buf);
- TextView.this.spanChange(buf, what, s, st, e, en);
- }
-
- public void onSpanAdded(Spannable buf, Object what, int s, int e) {
- if (DEBUG_EXTRACT) Log.v(TAG, "onSpanAdded s=" + s + " e=" + e
- + " what=" + what + ": " + buf);
- TextView.this.spanChange(buf, what, -1, s, -1, e);
- }
-
- public void onSpanRemoved(Spannable buf, Object what, int s, int e) {
- if (DEBUG_EXTRACT) Log.v(TAG, "onSpanRemoved s=" + s + " e=" + e
- + " what=" + what + ": " + buf);
- TextView.this.spanChange(buf, what, s, -1, e, -1);
- }
- }
-
- private void makeBlink() {
- if (!mCursorVisible) {
- if (mBlink != null) {
- mBlink.removeCallbacks(mBlink);
- }
-
- return;
- }
-
- if (mBlink == null)
- mBlink = new Blink(this);
-
- mBlink.removeCallbacks(mBlink);
- mBlink.postAtTime(mBlink, mShowCursor + BLINK);
- }
-
- @Override
- protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
- mShowCursor = SystemClock.uptimeMillis();
-
- ensureEndedBatchEdit();
-
- if (focused) {
- int selStart = getSelectionStart();
- int selEnd = getSelectionEnd();
-
- if (!mFrozenWithFocus || (selStart < 0 || selEnd < 0)) {
- boolean selMoved = mSelectionMoved;
-
- if (mMovement != null) {
- mMovement.onTakeFocus(this, (Spannable) mText, direction);
- }
-
- if (mSelectAllOnFocus) {
- Selection.setSelection((Spannable) mText, 0, mText.length());
- }
-
- if (selMoved && selStart >= 0 && selEnd >= 0) {
- /*
- * Someone intentionally set the selection, so let them
- * do whatever it is that they wanted to do instead of
- * the default on-focus behavior. We reset the selection
- * here instead of just skipping the onTakeFocus() call
- * because some movement methods do something other than
- * just setting the selection in theirs and we still
- * need to go through that path.
- */
-
- Selection.setSelection((Spannable) mText, selStart, selEnd);
- }
- }
-
- mFrozenWithFocus = false;
- mSelectionMoved = false;
-
- if (mText instanceof Spannable) {
- Spannable sp = (Spannable) mText;
- MetaKeyKeyListener.resetMetaState(sp);
- }
-
- makeBlink();
-
- if (mError != null) {
- showError();
- }
- } else {
- if (mError != null) {
- hideError();
- }
- // Don't leave us in the middle of a batch edit.
- onEndBatchEdit();
- }
-
- startStopMarquee(focused);
-
- if (mTransformation != null) {
- mTransformation.onFocusChanged(this, mText, focused, direction,
- previouslyFocusedRect);
- }
-
- super.onFocusChanged(focused, direction, previouslyFocusedRect);
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasWindowFocus) {
- super.onWindowFocusChanged(hasWindowFocus);
-
- if (hasWindowFocus) {
- if (mBlink != null) {
- mBlink.uncancel();
-
- if (isFocused()) {
- mShowCursor = SystemClock.uptimeMillis();
- makeBlink();
- }
- }
- } else {
- if (mBlink != null) {
- mBlink.cancel();
- }
- // Don't leave us in the middle of a batch edit.
- onEndBatchEdit();
- }
-
- startStopMarquee(hasWindowFocus);
- }
-
- /**
- * Use {@link BaseInputConnection#removeComposingSpans
- * BaseInputConnection.removeComposingSpans()} to remove any IME composing
- * state from this text view.
- */
- public void clearComposingText() {
- if (mText instanceof Spannable) {
- BaseInputConnection.removeComposingSpans((Spannable)mText);
- }
- }
-
- @Override
- public void setSelected(boolean selected) {
- boolean wasSelected = isSelected();
-
- super.setSelected(selected);
-
- if (selected != wasSelected && mEllipsize == TextUtils.TruncateAt.MARQUEE) {
- if (selected) {
- startMarquee();
- } else {
- stopMarquee();
- }
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- final boolean superResult = super.onTouchEvent(event);
-
- final int action = event.getAction();
-
- /*
- * Don't handle the release after a long press, because it will
- * move the selection away from whatever the menu action was
- * trying to affect.
- */
- if (mEatTouchRelease && action == MotionEvent.ACTION_UP) {
- mEatTouchRelease = false;
- return superResult;
- }
-
- if (mMovement != null && mText instanceof Spannable && mLayout != null) {
-
- if (action == MotionEvent.ACTION_DOWN) {
- mScrolled = false;
- }
-
- boolean moved = mMovement.onTouchEvent(this, (Spannable) mText, event);
-
- if (mText instanceof Editable && onCheckIsTextEditor()) {
- if (action == MotionEvent.ACTION_UP && isFocused() && !mScrolled) {
- InputMethodManager imm = (InputMethodManager)
- getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(this, 0);
- }
- }
-
- if (moved) {
- return true;
- }
- }
-
- return superResult;
- }
-
- @Override
- public void cancelLongPress() {
- super.cancelLongPress();
- mScrolled = true;
- }
-
- @Override
- public boolean onTrackballEvent(MotionEvent event) {
- if (mMovement != null && mText instanceof Spannable &&
- mLayout != null) {
- if (mMovement.onTrackballEvent(this, (Spannable) mText, event)) {
- return true;
- }
- }
-
- return super.onTrackballEvent(event);
- }
-
- public void setScroller(Scroller s) {
- mScroller = s;
- }
-
- private static class Blink extends Handler
- implements Runnable {
- private WeakReference<TextView> mView;
- private boolean mCancelled;
-
- public Blink(TextView v) {
- mView = new WeakReference<TextView>(v);
- }
-
- public void run() {
- if (mCancelled) {
- return;
- }
-
- removeCallbacks(Blink.this);
-
- TextView tv = mView.get();
-
- if (tv != null && tv.isFocused()) {
- int st = Selection.getSelectionStart(tv.mText);
- int en = Selection.getSelectionEnd(tv.mText);
-
- if (st == en && st >= 0 && en >= 0) {
- if (tv.mLayout != null) {
- tv.invalidateCursorPath();
- }
-
- postAtTime(this, SystemClock.uptimeMillis() + BLINK);
- }
- }
- }
-
- void cancel() {
- if (!mCancelled) {
- removeCallbacks(Blink.this);
- mCancelled = true;
- }
- }
-
- void uncancel() {
- mCancelled = false;
- }
- }
-
- @Override
- protected float getLeftFadingEdgeStrength() {
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
- if (mMarquee != null && !mMarquee.isStopped()) {
- final Marquee marquee = mMarquee;
- return marquee.mScroll / getHorizontalFadingEdgeLength();
- } else if (getLineCount() == 1) {
- switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- return 0.0f;
- case Gravity.RIGHT:
- return (mLayout.getLineRight(0) - (mRight - mLeft) -
- getCompoundPaddingLeft() - getCompoundPaddingRight() -
- mLayout.getLineLeft(0)) / getHorizontalFadingEdgeLength();
- case Gravity.CENTER_HORIZONTAL:
- return 0.0f;
- }
- }
- }
- return super.getLeftFadingEdgeStrength();
- }
-
- @Override
- protected float getRightFadingEdgeStrength() {
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
- if (mMarquee != null && !mMarquee.isStopped()) {
- final Marquee marquee = mMarquee;
- return (marquee.mMaxScroll - marquee.mScroll) / getHorizontalFadingEdgeLength();
- } else if (getLineCount() == 1) {
- switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- return (mLayout.getLineRight(0) - mScrollX - (mRight - mLeft) -
- getCompoundPaddingLeft() - getCompoundPaddingRight()) /
- getHorizontalFadingEdgeLength();
- case Gravity.RIGHT:
- return 0.0f;
- case Gravity.CENTER_HORIZONTAL:
- return (mLayout.getLineWidth(0) - ((mRight - mLeft) -
- getCompoundPaddingLeft() - getCompoundPaddingRight())) /
- getHorizontalFadingEdgeLength();
- }
- }
- }
- return super.getRightFadingEdgeStrength();
- }
-
- @Override
- protected int computeHorizontalScrollRange() {
- if (mLayout != null)
- return mLayout.getWidth();
-
- return super.computeHorizontalScrollRange();
- }
-
- @Override
- protected int computeVerticalScrollRange() {
- if (mLayout != null)
- return mLayout.getHeight();
-
- return super.computeVerticalScrollRange();
- }
-
- public enum BufferType {
- NORMAL, SPANNABLE, EDITABLE,
- }
-
- /**
- * Returns the TextView_textColor attribute from the
- * Resources.StyledAttributes, if set, or the TextAppearance_textColor
- * from the TextView_textAppearance attribute, if TextView_textColor
- * was not set directly.
- */
- public static ColorStateList getTextColors(Context context, TypedArray attrs) {
- ColorStateList colors;
- colors = attrs.getColorStateList(com.android.internal.R.styleable.
- TextView_textColor);
-
- if (colors == null) {
- int ap = attrs.getResourceId(com.android.internal.R.styleable.
- TextView_textAppearance, -1);
- if (ap != -1) {
- TypedArray appearance;
- appearance = context.obtainStyledAttributes(ap,
- com.android.internal.R.styleable.TextAppearance);
- colors = appearance.getColorStateList(com.android.internal.R.styleable.
- TextAppearance_textColor);
- appearance.recycle();
- }
- }
-
- return colors;
- }
-
- /**
- * Returns the default color from the TextView_textColor attribute
- * from the AttributeSet, if set, or the default color from the
- * TextAppearance_textColor from the TextView_textAppearance attribute,
- * if TextView_textColor was not set directly.
- */
- public static int getTextColor(Context context,
- TypedArray attrs,
- int def) {
- ColorStateList colors = getTextColors(context, attrs);
-
- if (colors == null) {
- return def;
- } else {
- return colors.getDefaultColor();
- }
- }
-
- @Override
- public boolean onKeyShortcut(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_A:
- if (canSelectAll()) {
- return onTextContextMenuItem(ID_SELECT_ALL);
- }
-
- break;
-
- case KeyEvent.KEYCODE_X:
- if (canCut()) {
- return onTextContextMenuItem(ID_CUT);
- }
-
- break;
-
- case KeyEvent.KEYCODE_C:
- if (canCopy()) {
- return onTextContextMenuItem(ID_COPY);
- }
-
- break;
-
- case KeyEvent.KEYCODE_V:
- if (canPaste()) {
- return onTextContextMenuItem(ID_PASTE);
- }
-
- break;
- }
-
- return super.onKeyShortcut(keyCode, event);
- }
-
- private boolean canSelectAll() {
- if (mText instanceof Spannable && mText.length() != 0 &&
- mMovement != null && mMovement.canSelectArbitrarily()) {
- return true;
- }
-
- return false;
- }
-
- private boolean canSelectText() {
- if (mText instanceof Spannable && mText.length() != 0 &&
- mMovement != null && mMovement.canSelectArbitrarily()) {
- return true;
- }
-
- return false;
- }
-
- private boolean canCut() {
- if (mTransformation instanceof PasswordTransformationMethod) {
- return false;
- }
-
- if (mText.length() > 0 && getSelectionStart() >= 0) {
- if (mText instanceof Editable && mInput != null) {
- return true;
- }
- }
-
- return false;
- }
-
- private boolean canCopy() {
- if (mTransformation instanceof PasswordTransformationMethod) {
- return false;
- }
-
- if (mText.length() > 0 && getSelectionStart() >= 0) {
- return true;
- }
-
- return false;
- }
-
- private boolean canPaste() {
- if (mText instanceof Editable && mInput != null &&
- getSelectionStart() >= 0 && getSelectionEnd() >= 0) {
- ClipboardManager clip = (ClipboardManager)getContext()
- .getSystemService(Context.CLIPBOARD_SERVICE);
- if (clip.hasText()) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Returns a word to add to the dictionary from the context menu,
- * or null if there is no cursor or no word at the cursor.
- */
- private String getWordForDictionary() {
- int end = getSelectionEnd();
-
- if (end < 0) {
- return null;
- }
-
- int start = end;
- char c;
- int len = mText.length();
-
- while (start > 0 && (((c = mTransformed.charAt(start - 1)) == '\'') ||
- (Character.isLetterOrDigit(c)))) {
- start--;
- }
-
- while (end < len && (((c = mTransformed.charAt(end)) == '\'') ||
- (Character.isLetterOrDigit(c)))) {
- end++;
- }
-
- if (start == end) {
- return null;
- }
-
- return TextUtils.substring(mTransformed, start, end);
- }
-
- @Override
- protected void onCreateContextMenu(ContextMenu menu) {
- super.onCreateContextMenu(menu);
- boolean added = false;
-
- if (!isFocused()) {
- if (isFocusable() && mInput != null) {
- if (canCopy()) {
- MenuHandler handler = new MenuHandler();
- int name = com.android.internal.R.string.copyAll;
-
- menu.add(0, ID_COPY, 0, name).
- setOnMenuItemClickListener(handler).
- setAlphabeticShortcut('c');
- menu.setHeaderTitle(com.android.internal.R.string.
- editTextMenuTitle);
- }
- }
-
- return;
- }
-
- MenuHandler handler = new MenuHandler();
-
- if (canSelectAll()) {
- menu.add(0, ID_SELECT_ALL, 0,
- com.android.internal.R.string.selectAll).
- setOnMenuItemClickListener(handler).
- setAlphabeticShortcut('a');
- added = true;
- }
-
- boolean selection = getSelectionStart() != getSelectionEnd();
-
- if (canSelectText()) {
- if (MetaKeyKeyListener.getMetaState(mText, MetaKeyKeyListener.META_SELECTING) != 0) {
- menu.add(0, ID_STOP_SELECTING_TEXT, 0,
- com.android.internal.R.string.stopSelectingText).
- setOnMenuItemClickListener(handler);
- added = true;
- } else {
- menu.add(0, ID_START_SELECTING_TEXT, 0,
- com.android.internal.R.string.selectText).
- setOnMenuItemClickListener(handler);
- added = true;
- }
- }
-
- if (canCut()) {
- int name;
- if (selection) {
- name = com.android.internal.R.string.cut;
- } else {
- name = com.android.internal.R.string.cutAll;
- }
-
- menu.add(0, ID_CUT, 0, name).
- setOnMenuItemClickListener(handler).
- setAlphabeticShortcut('x');
- added = true;
- }
-
- if (canCopy()) {
- int name;
- if (selection) {
- name = com.android.internal.R.string.copy;
- } else {
- name = com.android.internal.R.string.copyAll;
- }
-
- menu.add(0, ID_COPY, 0, name).
- setOnMenuItemClickListener(handler).
- setAlphabeticShortcut('c');
- added = true;
- }
-
- if (canPaste()) {
- menu.add(0, ID_PASTE, 0, com.android.internal.R.string.paste).
- setOnMenuItemClickListener(handler).
- setAlphabeticShortcut('v');
- added = true;
- }
-
- if (mText instanceof Spanned) {
- int selStart = getSelectionStart();
- int selEnd = getSelectionEnd();
-
- int min = Math.min(selStart, selEnd);
- int max = Math.max(selStart, selEnd);
-
- URLSpan[] urls = ((Spanned) mText).getSpans(min, max,
- URLSpan.class);
- if (urls.length == 1) {
- menu.add(0, ID_COPY_URL, 0,
- com.android.internal.R.string.copyUrl).
- setOnMenuItemClickListener(handler);
- added = true;
- }
- }
-
- if (isInputMethodTarget()) {
- menu.add(1, ID_SWITCH_INPUT_METHOD, 0, com.android.internal.R.string.inputMethod).
- setOnMenuItemClickListener(handler);
- added = true;
- }
-
- String word = getWordForDictionary();
- if (word != null) {
- menu.add(1, ID_ADD_TO_DICTIONARY, 0,
- getContext().getString(com.android.internal.R.string.addToDictionary, word)).
- setOnMenuItemClickListener(handler);
- added = true;
-
- }
-
- if (added) {
- menu.setHeaderTitle(com.android.internal.R.string.editTextMenuTitle);
- }
- }
-
- /**
- * Returns whether this text view is a current input method target. The
- * default implementation just checks with {@link InputMethodManager}.
- */
- public boolean isInputMethodTarget() {
- InputMethodManager imm = InputMethodManager.peekInstance();
- return imm != null && imm.isActive(this);
- }
-
- private static final int ID_SELECT_ALL = android.R.id.selectAll;
- private static final int ID_START_SELECTING_TEXT = android.R.id.startSelectingText;
- private static final int ID_STOP_SELECTING_TEXT = android.R.id.stopSelectingText;
- private static final int ID_CUT = android.R.id.cut;
- private static final int ID_COPY = android.R.id.copy;
- private static final int ID_PASTE = android.R.id.paste;
- private static final int ID_COPY_URL = android.R.id.copyUrl;
- private static final int ID_SWITCH_INPUT_METHOD = android.R.id.switchInputMethod;
- private static final int ID_ADD_TO_DICTIONARY = android.R.id.addToDictionary;
-
- private class MenuHandler implements MenuItem.OnMenuItemClickListener {
- public boolean onMenuItemClick(MenuItem item) {
- return onTextContextMenuItem(item.getItemId());
- }
- }
-
- /**
- * Called when a context menu option for the text view is selected. Currently
- * this will be one of: {@link android.R.id#selectAll},
- * {@link android.R.id#startSelectingText}, {@link android.R.id#stopSelectingText},
- * {@link android.R.id#cut}, {@link android.R.id#copy},
- * {@link android.R.id#paste}, {@link android.R.id#copyUrl},
- * or {@link android.R.id#switchInputMethod}.
- */
- public boolean onTextContextMenuItem(int id) {
- int selStart = getSelectionStart();
- int selEnd = getSelectionEnd();
-
- if (!isFocused()) {
- selStart = 0;
- selEnd = mText.length();
- }
-
- int min = Math.min(selStart, selEnd);
- int max = Math.max(selStart, selEnd);
-
- if (min < 0) {
- min = 0;
- }
- if (max < 0) {
- max = 0;
- }
-
- ClipboardManager clip = (ClipboardManager)getContext()
- .getSystemService(Context.CLIPBOARD_SERVICE);
-
- switch (id) {
- case ID_SELECT_ALL:
- Selection.setSelection((Spannable) mText, 0,
- mText.length());
- return true;
-
- case ID_START_SELECTING_TEXT:
- MetaKeyKeyListener.startSelecting(this, (Spannable) mText);
- return true;
-
- case ID_STOP_SELECTING_TEXT:
- MetaKeyKeyListener.stopSelecting(this, (Spannable) mText);
- Selection.setSelection((Spannable) mText, getSelectionEnd());
- return true;
-
- case ID_CUT:
- MetaKeyKeyListener.stopSelecting(this, (Spannable) mText);
-
- if (min == max) {
- min = 0;
- max = mText.length();
- }
-
- clip.setText(mTransformed.subSequence(min, max));
- ((Editable) mText).delete(min, max);
- return true;
-
- case ID_COPY:
- MetaKeyKeyListener.stopSelecting(this, (Spannable) mText);
-
- if (min == max) {
- min = 0;
- max = mText.length();
- }
-
- clip.setText(mTransformed.subSequence(min, max));
- return true;
-
- case ID_PASTE:
- MetaKeyKeyListener.stopSelecting(this, (Spannable) mText);
-
- CharSequence paste = clip.getText();
-
- if (paste != null) {
- Selection.setSelection((Spannable) mText, max);
- ((Editable) mText).replace(min, max, paste);
- }
-
- return true;
-
- case ID_COPY_URL:
- MetaKeyKeyListener.stopSelecting(this, (Spannable) mText);
-
- URLSpan[] urls = ((Spanned) mText).getSpans(min, max,
- URLSpan.class);
- if (urls.length == 1) {
- clip.setText(urls[0].getURL());
- }
-
- return true;
-
- case ID_SWITCH_INPUT_METHOD:
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) {
- imm.showInputMethodPicker();
- }
- return true;
-
- case ID_ADD_TO_DICTIONARY:
- String word = getWordForDictionary();
-
- if (word != null) {
- Intent i = new Intent("com.android.settings.USER_DICTIONARY_INSERT");
- i.putExtra("word", word);
- getContext().startActivity(i);
- }
-
- return true;
- }
-
- return false;
- }
-
- public boolean performLongClick() {
- if (super.performLongClick()) {
- mEatTouchRelease = true;
- return true;
- }
-
- return false;
- }
-
- @ViewDebug.ExportedProperty
- private CharSequence mText;
- private CharSequence mTransformed;
- private BufferType mBufferType = BufferType.NORMAL;
-
- private int mInputType = EditorInfo.TYPE_NULL;
- private CharSequence mHint;
- private Layout mHintLayout;
-
- private KeyListener mInput;
-
- private MovementMethod mMovement;
- private TransformationMethod mTransformation;
- private ChangeWatcher mChangeWatcher;
-
- private ArrayList<TextWatcher> mListeners = null;
-
- // display attributes
- private TextPaint mTextPaint;
- private Paint mHighlightPaint;
- private int mHighlightColor = 0xFFBBDDFF;
- private Layout mLayout;
-
- private long mShowCursor;
- private Blink mBlink;
- private boolean mCursorVisible = true;
-
- private boolean mSelectAllOnFocus = false;
-
- private int mGravity = Gravity.TOP | Gravity.LEFT;
- private boolean mHorizontallyScrolling;
-
- private int mAutoLinkMask;
- private boolean mLinksClickable = true;
-
- private float mSpacingMult = 1;
- private float mSpacingAdd = 0;
-
- private static final int LINES = 1;
- private static final int EMS = LINES;
- private static final int PIXELS = 2;
-
- private int mMaximum = Integer.MAX_VALUE;
- private int mMaxMode = LINES;
- private int mMinimum = 0;
- private int mMinMode = LINES;
-
- private int mMaxWidth = Integer.MAX_VALUE;
- private int mMaxWidthMode = PIXELS;
- private int mMinWidth = 0;
- private int mMinWidthMode = PIXELS;
-
- private boolean mSingleLine;
- private int mDesiredHeightAtMeasure = -1;
- private boolean mIncludePad = true;
-
- // tmp primitives, so we don't alloc them on each draw
- private Path mHighlightPath;
- private boolean mHighlightPathBogus = true;
- private static final RectF sTempRect = new RectF();
-
- // XXX should be much larger
- private static final int VERY_WIDE = 16384;
-
- private static final int BLINK = 500;
-
- private static final int ANIMATED_SCROLL_GAP = 250;
- private long mLastScroll;
- private Scroller mScroller = null;
-
- private BoringLayout.Metrics mBoring;
- private BoringLayout.Metrics mHintBoring;
-
- private BoringLayout mSavedLayout, mSavedHintLayout;
-
- private static final InputFilter[] NO_FILTERS = new InputFilter[0];
- private InputFilter[] mFilters = NO_FILTERS;
- private static final Spanned EMPTY_SPANNED = new SpannedString("");
-}
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
deleted file mode 100644
index ab4edc5..0000000
--- a/core/java/android/widget/TimePicker.java
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.annotation.Widget;
-import android.content.Context;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import com.android.internal.R;
-import com.android.internal.widget.NumberPicker;
-
-import java.text.DateFormatSymbols;
-import java.util.Calendar;
-
-/**
- * A view for selecting the time of day, in either 24 hour or AM/PM mode.
- *
- * The hour, each minute digit, and AM/PM (if applicable) can be conrolled by
- * vertical spinners.
- *
- * The hour can be entered by keyboard input. Entering in two digit hours
- * can be accomplished by hitting two digits within a timeout of about a
- * second (e.g. '1' then '2' to select 12).
- *
- * The minutes can be entered by entering single digits.
- *
- * Under AM/PM mode, the user can hit 'a', 'A", 'p' or 'P' to pick.
- *
- * For a dialog using this view, see {@link android.app.TimePickerDialog}.
- */
-@Widget
-public class TimePicker extends FrameLayout {
-
- /**
- * A no-op callback used in the constructor to avoid null checks
- * later in the code.
- */
- private static final OnTimeChangedListener NO_OP_CHANGE_LISTENER = new OnTimeChangedListener() {
- public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
- }
- };
-
- // state
- private int mCurrentHour = 0; // 0-23
- private int mCurrentMinute = 0; // 0-59
- private Boolean mIs24HourView = false;
- private boolean mIsAm;
-
- // ui components
- private final NumberPicker mHourPicker;
- private final NumberPicker mMinutePicker;
- private final Button mAmPmButton;
- private final String mAmText;
- private final String mPmText;
-
- // callbacks
- private OnTimeChangedListener mOnTimeChangedListener;
-
- /**
- * The callback interface used to indicate the time has been adjusted.
- */
- public interface OnTimeChangedListener {
-
- /**
- * @param view The view associated with this listener.
- * @param hourOfDay The current hour.
- * @param minute The current minute.
- */
- void onTimeChanged(TimePicker view, int hourOfDay, int minute);
- }
-
- public TimePicker(Context context) {
- this(context, null);
- }
-
- public TimePicker(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public TimePicker(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- LayoutInflater inflater =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(R.layout.time_picker,
- this, // we are the parent
- true);
-
- // hour
- mHourPicker = (NumberPicker) findViewById(R.id.hour);
- mHourPicker.setOnChangeListener(new NumberPicker.OnChangedListener() {
- public void onChanged(NumberPicker spinner, int oldVal, int newVal) {
- mCurrentHour = newVal;
- if (!mIs24HourView) {
- // adjust from [1-12] to [0-11] internally, with the times
- // written "12:xx" being the start of the half-day
- if (mCurrentHour == 12) {
- mCurrentHour = 0;
- }
- if (!mIsAm) {
- // PM means 12 hours later than nominal
- mCurrentHour += 12;
- }
- }
- onTimeChanged();
- }
- });
-
- // digits of minute
- mMinutePicker = (NumberPicker) findViewById(R.id.minute);
- mMinutePicker.setRange(0, 59);
- mMinutePicker.setSpeed(100);
- mMinutePicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
- mMinutePicker.setOnChangeListener(new NumberPicker.OnChangedListener() {
- public void onChanged(NumberPicker spinner, int oldVal, int newVal) {
- mCurrentMinute = newVal;
- onTimeChanged();
- }
- });
-
- // am/pm
- mAmPmButton = (Button) findViewById(R.id.amPm);
-
- // now that the hour/minute picker objects have been initialized, set
- // the hour range properly based on the 12/24 hour display mode.
- configurePickerRanges();
-
- // initialize to current time
- Calendar cal = Calendar.getInstance();
- setOnTimeChangedListener(NO_OP_CHANGE_LISTENER);
-
- // by default we're not in 24 hour mode
- setCurrentHour(cal.get(Calendar.HOUR_OF_DAY));
- setCurrentMinute(cal.get(Calendar.MINUTE));
-
- mIsAm = (mCurrentHour < 12);
-
- /* Get the localized am/pm strings and use them in the spinner */
- DateFormatSymbols dfs = new DateFormatSymbols();
- String[] dfsAmPm = dfs.getAmPmStrings();
- mAmText = dfsAmPm[Calendar.AM];
- mPmText = dfsAmPm[Calendar.PM];
- mAmPmButton.setText(mIsAm ? mAmText : mPmText);
- mAmPmButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- requestFocus();
- if (mIsAm) {
-
- // Currently AM switching to PM
- if (mCurrentHour < 12) {
- mCurrentHour += 12;
- }
- } else {
-
- // Currently PM switching to AM
- if (mCurrentHour >= 12) {
- mCurrentHour -= 12;
- }
- }
- mIsAm = !mIsAm;
- mAmPmButton.setText(mIsAm ? mAmText : mPmText);
- onTimeChanged();
- }
- });
-
- if (!isEnabled()) {
- setEnabled(false);
- }
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- super.setEnabled(enabled);
- mMinutePicker.setEnabled(enabled);
- mHourPicker.setEnabled(enabled);
- mAmPmButton.setEnabled(enabled);
- }
-
- /**
- * Used to save / restore state of time picker
- */
- private static class SavedState extends BaseSavedState {
-
- private final int mHour;
- private final int mMinute;
-
- private SavedState(Parcelable superState, int hour, int minute) {
- super(superState);
- mHour = hour;
- mMinute = minute;
- }
-
- private SavedState(Parcel in) {
- super(in);
- mHour = in.readInt();
- mMinute = in.readInt();
- }
-
- public int getHour() {
- return mHour;
- }
-
- public int getMinute() {
- return mMinute;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(mHour);
- dest.writeInt(mMinute);
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR
- = new Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
- @Override
- protected Parcelable onSaveInstanceState() {
- Parcelable superState = super.onSaveInstanceState();
- return new SavedState(superState, mCurrentHour, mCurrentMinute);
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
- super.onRestoreInstanceState(ss.getSuperState());
- setCurrentHour(ss.getHour());
- setCurrentMinute(ss.getMinute());
- }
-
- /**
- * Set the callback that indicates the time has been adjusted by the user.
- * @param onTimeChangedListener the callback, should not be null.
- */
- public void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener) {
- mOnTimeChangedListener = onTimeChangedListener;
- }
-
- /**
- * @return The current hour (0-23).
- */
- public Integer getCurrentHour() {
- return mCurrentHour;
- }
-
- /**
- * Set the current hour.
- */
- public void setCurrentHour(Integer currentHour) {
- this.mCurrentHour = currentHour;
- updateHourDisplay();
- }
-
- /**
- * Set whether in 24 hour or AM/PM mode.
- * @param is24HourView True = 24 hour mode. False = AM/PM.
- */
- public void setIs24HourView(Boolean is24HourView) {
- if (mIs24HourView != is24HourView) {
- mIs24HourView = is24HourView;
- configurePickerRanges();
- updateHourDisplay();
- }
- }
-
- /**
- * @return true if this is in 24 hour view else false.
- */
- public boolean is24HourView() {
- return mIs24HourView;
- }
-
- /**
- * @return The current minute.
- */
- public Integer getCurrentMinute() {
- return mCurrentMinute;
- }
-
- /**
- * Set the current minute (0-59).
- */
- public void setCurrentMinute(Integer currentMinute) {
- this.mCurrentMinute = currentMinute;
- updateMinuteDisplay();
- }
-
- @Override
- public int getBaseline() {
- return mHourPicker.getBaseline();
- }
-
- /**
- * Set the state of the spinners appropriate to the current hour.
- */
- private void updateHourDisplay() {
- int currentHour = mCurrentHour;
- if (!mIs24HourView) {
- // convert [0,23] ordinal to wall clock display
- if (currentHour > 12) currentHour -= 12;
- else if (currentHour == 0) currentHour = 12;
- }
- mHourPicker.setCurrent(currentHour);
- mIsAm = mCurrentHour < 12;
- mAmPmButton.setText(mIsAm ? mAmText : mPmText);
- onTimeChanged();
- }
-
- private void configurePickerRanges() {
- if (mIs24HourView) {
- mHourPicker.setRange(0, 23);
- mHourPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
- mAmPmButton.setVisibility(View.GONE);
- } else {
- mHourPicker.setRange(1, 12);
- mHourPicker.setFormatter(null);
- mAmPmButton.setVisibility(View.VISIBLE);
- }
- }
-
- private void onTimeChanged() {
- mOnTimeChangedListener.onTimeChanged(this, getCurrentHour(), getCurrentMinute());
- }
-
- /**
- * Set the state of the spinners appropriate to the current minute.
- */
- private void updateMinuteDisplay() {
- mMinutePicker.setCurrent(mCurrentMinute);
- mOnTimeChangedListener.onTimeChanged(this, getCurrentHour(), getCurrentMinute());
- }
-}
-
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
deleted file mode 100644
index ff74787..0000000
--- a/core/java/android/widget/Toast.java
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.app.INotificationManager;
-import android.app.ITransientNotification;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.PixelFormat;
-import android.os.RemoteException;
-import android.os.Handler;
-import android.os.ServiceManager;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.WindowManager;
-import android.view.WindowManagerImpl;
-
-/**
- * A toast is a view containing a quick little message for the user. The toast class
- * helps you create and show those.
- * {@more}
- *
- * <p>
- * When the view is shown to the user, appears as a floating view over the
- * application. It will never receive focus. The user will probably be in the
- * middle of typing something else. The idea is to be as unobtrusive as
- * possible, while still showing the user the information you want them to see.
- * Two examples are the volume control, and the brief message saying that your
- * settings have been saved.
- * <p>
- * The easiest way to use this class is to call one of the static methods that constructs
- * everything you need and returns a new Toast object.
- */
-public class Toast {
- static final String TAG = "Toast";
- static final boolean localLOGV = false;
-
- /**
- * Show the view or text notification for a short period of time. This time
- * could be user-definable. This is the default.
- * @see #setDuration
- */
- public static final int LENGTH_SHORT = 0;
-
- /**
- * Show the view or text notification for a long period of time. This time
- * could be user-definable.
- * @see #setDuration
- */
- public static final int LENGTH_LONG = 1;
-
- final Context mContext;
- final TN mTN;
- int mDuration;
- int mGravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
- int mX, mY;
- float mHorizontalMargin;
- float mVerticalMargin;
- View mView;
- View mNextView;
-
- /**
- * Construct an empty Toast object. You must call {@link #setView} before you
- * can call {@link #show}.
- *
- * @param context The context to use. Usually your {@link android.app.Application}
- * or {@link android.app.Activity} object.
- */
- public Toast(Context context) {
- mContext = context;
- mTN = new TN(context);
- mY = context.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.toast_y_offset);
- }
-
- /**
- * Show the view for the specified duration.
- */
- public void show() {
- if (mNextView == null) {
- throw new RuntimeException("setView must have been called");
- }
-
- INotificationManager service = getService();
-
- String pkg = mContext.getPackageName();
-
- TN tn = mTN;
-
- try {
- service.enqueueToast(pkg, tn, mDuration);
- } catch (RemoteException e) {
- // Empty
- }
- }
-
- /**
- * Close the view if it's showing, or don't show it if it isn't showing yet.
- * You do not normally have to call this. Normally view will disappear on its own
- * after the appropriate duration.
- */
- public void cancel() {
- mTN.hide();
- // TODO this still needs to cancel the inflight notification if any
- }
-
- /**
- * Set the view to show.
- * @see #getView
- */
- public void setView(View view) {
- mNextView = view;
- }
-
- /**
- * Return the view.
- * @see #setView
- */
- public View getView() {
- return mNextView;
- }
-
- /**
- * Set how long to show the view for.
- * @see #LENGTH_SHORT
- * @see #LENGTH_LONG
- */
- public void setDuration(int duration) {
- mDuration = duration;
- }
-
- /**
- * Return the duration.
- * @see #setDuration
- */
- public int getDuration() {
- return mDuration;
- }
-
- /**
- * Set the margins of the view.
- *
- * @param horizontalMargin The horizontal margin, in percentage of the
- * container width, between the container's edges and the
- * notification
- * @param verticalMargin The vertical margin, in percentage of the
- * container height, between the container's edges and the
- * notification
- */
- public void setMargin(float horizontalMargin, float verticalMargin) {
- mHorizontalMargin = horizontalMargin;
- mVerticalMargin = verticalMargin;
- }
-
- /**
- * Return the horizontal margin.
- */
- public float getHorizontalMargin() {
- return mHorizontalMargin;
- }
-
- /**
- * Return the vertical margin.
- */
- public float getVerticalMargin() {
- return mVerticalMargin;
- }
-
- /**
- * Set the location at which the notification should appear on the screen.
- * @see android.view.Gravity
- * @see #getGravity
- */
- public void setGravity(int gravity, int xOffset, int yOffset) {
- mGravity = gravity;
- mX = xOffset;
- mY = yOffset;
- }
-
- /**
- * Get the location at which the notification should appear on the screen.
- * @see android.view.Gravity
- * @see #getGravity
- */
- public int getGravity() {
- return mGravity;
- }
-
- /**
- * Return the X offset in pixels to apply to the gravity's location.
- */
- public int getXOffset() {
- return mX;
- }
-
- /**
- * Return the Y offset in pixels to apply to the gravity's location.
- */
- public int getYOffset() {
- return mY;
- }
-
- /**
- * Make a standard toast that just contains a text view.
- *
- * @param context The context to use. Usually your {@link android.app.Application}
- * or {@link android.app.Activity} object.
- * @param text The text to show. Can be formatted text.
- * @param duration How long to display the message. Either {@link #LENGTH_SHORT} or
- * {@link #LENGTH_LONG}
- *
- */
- public static Toast makeText(Context context, CharSequence text, int duration) {
- Toast result = new Toast(context);
-
- LayoutInflater inflate = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
- TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);
- tv.setText(text);
-
- result.mNextView = v;
- result.mDuration = duration;
-
- return result;
- }
-
- /**
- * Make a standard toast that just contains a text view with the text from a resource.
- *
- * @param context The context to use. Usually your {@link android.app.Application}
- * or {@link android.app.Activity} object.
- * @param resId The resource id of the string resource to use. Can be formatted text.
- * @param duration How long to display the message. Either {@link #LENGTH_SHORT} or
- * {@link #LENGTH_LONG}
- *
- * @throws Resources.NotFoundException if the resource can't be found.
- */
- public static Toast makeText(Context context, int resId, int duration)
- throws Resources.NotFoundException {
- return makeText(context, context.getResources().getText(resId), duration);
- }
-
- /**
- * Update the text in a Toast that was previously created using one of the makeText() methods.
- * @param resId The new text for the Toast.
- */
- public void setText(int resId) {
- setText(mContext.getText(resId));
- }
-
- /**
- * Update the text in a Toast that was previously created using one of the makeText() methods.
- * @param s The new text for the Toast.
- */
- public void setText(CharSequence s) {
- if (mNextView == null) {
- throw new RuntimeException("This Toast was not created with Toast.makeText()");
- }
- TextView tv = (TextView) mNextView.findViewById(com.android.internal.R.id.message);
- if (tv == null) {
- throw new RuntimeException("This Toast was not created with Toast.makeText()");
- }
- tv.setText(s);
- }
-
- // =======================================================================================
- // All the gunk below is the interaction with the Notification Service, which handles
- // the proper ordering of these system-wide.
- // =======================================================================================
-
- private static INotificationManager sService;
-
- static private INotificationManager getService()
- {
- if (sService != null) {
- return sService;
- }
- sService = INotificationManager.Stub.asInterface(ServiceManager.getService("notification"));
- return sService;
- }
-
- private class TN extends ITransientNotification.Stub
- {
- TN(Context context)
- {
- // XXX This should be changed to use a Dialog, with a Theme.Toast
- // defined that sets up the layout params appropriately.
- mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
- mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
- mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
- mParams.format = PixelFormat.TRANSLUCENT;
- mParams.windowAnimations = com.android.internal.R.style.Animation_Toast;
- mParams.type = WindowManager.LayoutParams.TYPE_TOAST;
- mParams.setTitle("Toast");
- }
-
- /**
- * schedule handleShow into the right thread
- */
- public void show()
- {
- if (localLOGV) Log.v(TAG, "SHOW: " + this);
- mHandler.post(mShow);
- }
-
- /**
- * schedule handleHide into the right thread
- */
- public void hide()
- {
- if (localLOGV) Log.v(TAG, "HIDE: " + this);
- mHandler.post(mHide);
- }
-
- public void handleShow()
- {
- if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
- + " mNextView=" + mNextView);
- if (mView != mNextView) {
- // remove the old view if necessary
- handleHide();
- mView = mNextView;
- mWM = WindowManagerImpl.getDefault();
- final int gravity = mGravity;
- mParams.gravity = gravity;
- if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
- mParams.horizontalWeight = 1.0f;
- }
- if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) {
- mParams.verticalWeight = 1.0f;
- }
- mParams.x = mX;
- mParams.y = mY;
- mParams.verticalMargin = mVerticalMargin;
- mParams.horizontalMargin = mHorizontalMargin;
- if (mView.getParent() != null) {
- if (localLOGV) Log.v(
- TAG, "REMOVE! " + mView + " in " + this);
- mWM.removeView(mView);
- }
- if (localLOGV) Log.v(TAG, "ADD! " + mView + " in " + this);
- mWM.addView(mView, mParams);
- }
- }
-
- public void handleHide()
- {
- if (localLOGV) Log.v(TAG, "HANDLE HIDE: " + this + " mView=" + mView);
- if (mView != null) {
- // note: checking parent() just to make sure the view has
- // been added... i have seen cases where we get here when
- // the view isn't yet added, so let's try not to crash.
- if (mView.getParent() != null) {
- if (localLOGV) Log.v(
- TAG, "REMOVE! " + mView + " in " + this);
- mWM.removeView(mView);
- }
- mView = null;
- }
- }
-
- Runnable mShow = new Runnable() {
- public void run() {
- handleShow();
- }
- };
-
- Runnable mHide = new Runnable() {
- public void run() {
- handleHide();
- }
- };
-
- private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
-
- WindowManagerImpl mWM;
- }
-
- final Handler mHandler = new Handler();
-}
-
diff --git a/core/java/android/widget/ToggleButton.java b/core/java/android/widget/ToggleButton.java
deleted file mode 100644
index dc791e3..0000000
--- a/core/java/android/widget/ToggleButton.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.util.AttributeSet;
-
-/**
- * Displays checked/unchecked states as a button
- * with a "light" indicator and by default accompanied with the text "ON" or "OFF".
- *
- * @attr ref android.R.styleable#ToggleButton_textOn
- * @attr ref android.R.styleable#ToggleButton_textOff
- * @attr ref android.R.styleable#ToggleButton_disabledAlpha
- */
-public class ToggleButton extends CompoundButton {
- private CharSequence mTextOn;
- private CharSequence mTextOff;
-
- private Drawable mIndicatorDrawable;
-
- private static final int NO_ALPHA = 0xFF;
- private float mDisabledAlpha;
-
- public ToggleButton(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a =
- context.obtainStyledAttributes(
- attrs, com.android.internal.R.styleable.ToggleButton, defStyle, 0);
- mTextOn = a.getText(com.android.internal.R.styleable.ToggleButton_textOn);
- mTextOff = a.getText(com.android.internal.R.styleable.ToggleButton_textOff);
- mDisabledAlpha = a.getFloat(com.android.internal.R.styleable.ToggleButton_disabledAlpha, 0.5f);
- syncTextState();
- a.recycle();
- }
-
- public ToggleButton(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.buttonStyleToggle);
- }
-
- public ToggleButton(Context context) {
- this(context, null);
- }
-
- @Override
- public void setChecked(boolean checked) {
- super.setChecked(checked);
-
- syncTextState();
- }
-
- private void syncTextState() {
- boolean checked = isChecked();
- if (checked && mTextOn != null) {
- setText(mTextOn);
- } else if (!checked && mTextOff != null) {
- setText(mTextOff);
- }
- }
-
- /**
- * Returns the text for when the button is in the checked state.
- *
- * @return The text.
- */
- public CharSequence getTextOn() {
- return mTextOn;
- }
-
- /**
- * Sets the text for when the button is in the checked state.
- *
- * @param textOn The text.
- */
- public void setTextOn(CharSequence textOn) {
- mTextOn = textOn;
- }
-
- /**
- * Returns the text for when the button is not in the checked state.
- *
- * @return The text.
- */
- public CharSequence getTextOff() {
- return mTextOff;
- }
-
- /**
- * Sets the text for when the button is not in the checked state.
- *
- * @param textOff The text.
- */
- public void setTextOff(CharSequence textOff) {
- mTextOff = textOff;
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- updateReferenceToIndicatorDrawable(getBackground());
- }
-
- @Override
- public void setBackgroundDrawable(Drawable d) {
- super.setBackgroundDrawable(d);
-
- updateReferenceToIndicatorDrawable(d);
- }
-
- private void updateReferenceToIndicatorDrawable(Drawable backgroundDrawable) {
- if (backgroundDrawable instanceof LayerDrawable) {
- LayerDrawable layerDrawable = (LayerDrawable) backgroundDrawable;
- mIndicatorDrawable =
- layerDrawable.findDrawableByLayerId(com.android.internal.R.id.toggle);
- }
- }
-
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
-
- if (mIndicatorDrawable != null) {
- mIndicatorDrawable.setAlpha(isEnabled() ? NO_ALPHA : (int) (NO_ALPHA * mDisabledAlpha));
- }
- }
-
-}
diff --git a/core/java/android/widget/TwoLineListItem.java b/core/java/android/widget/TwoLineListItem.java
deleted file mode 100644
index 77ea645..0000000
--- a/core/java/android/widget/TwoLineListItem.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import com.android.internal.R;
-
-
-import android.annotation.Widget;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.RelativeLayout;
-
-/**
- * <p>A view group with two children, intended for use in ListViews. This item has two
- * {@link android.widget.TextView TextViews} elements (or subclasses) with the ID values
- * {@link android.R.id#text1 text1}
- * and {@link android.R.id#text2 text2}. There is an optional third View element with the
- * ID {@link android.R.id#selectedIcon selectedIcon}, which can be any View subclass
- * (though it is typically a graphic View, such as {@link android.widget.ImageView ImageView})
- * that can be displayed when a TwoLineListItem has focus. Android supplies a
- * {@link android.R.layout#two_line_list_item standard layout resource for TwoLineListView}
- * (which does not include a selected item icon), but you can design your own custom XML
- * layout for this object as shown here:</p>
- * {@sample packages/apps/Phone/res/layout/dialer_list_item.xml}
- *
- * @attr ref android.R.styleable#TwoLineListItem_mode
- */
-@Widget
-public class TwoLineListItem extends RelativeLayout {
-
- private TextView mText1;
- private TextView mText2;
-
- public TwoLineListItem(Context context) {
- this(context, null, 0);
- }
-
- public TwoLineListItem(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public TwoLineListItem(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.TwoLineListItem, defStyle, 0);
-
- a.recycle();
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- mText1 = (TextView) findViewById(com.android.internal.R.id.text1);
- mText2 = (TextView) findViewById(com.android.internal.R.id.text2);
- }
-
- /**
- * Returns a handle to the item with ID text1.
- * @return A handle to the item with ID text1.
- */
- public TextView getText1() {
- return mText1;
- }
-
- /**
- * Returns a handle to the item with ID text2.
- * @return A handle to the item with ID text2.
- */
- public TextView getText2() {
- return mText2;
- }
-}
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
deleted file mode 100644
index 1227afd..0000000
--- a/core/java/android/widget/VideoView.java
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.media.AudioManager;
-import android.media.MediaPlayer;
-import android.media.MediaPlayer.OnCompletionListener;
-import android.media.MediaPlayer.OnErrorListener;
-import android.net.Uri;
-import android.os.PowerManager;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.View;
-import android.widget.MediaController.MediaPlayerControl;
-
-import java.io.IOException;
-
-/**
- * Displays a video file. The VideoView class
- * can load images from various sources (such as resources or content
- * providers), takes care of computing its measurement from the video so that
- * it can be used in any layout manager, and provides various display options
- * such as scaling and tinting.
- */
-public class VideoView extends SurfaceView implements MediaPlayerControl {
- // settable by the client
- private Uri mUri;
-
- // All the stuff we need for playing and showing a video
- private SurfaceHolder mSurfaceHolder = null;
- private MediaPlayer mMediaPlayer = null;
- private boolean mIsPrepared;
- private int mVideoWidth;
- private int mVideoHeight;
- private int mSurfaceWidth;
- private int mSurfaceHeight;
- private MediaController mMediaController;
- private OnCompletionListener mOnCompletionListener;
- private MediaPlayer.OnPreparedListener mOnPreparedListener;
- private int mCurrentBufferPercentage;
- private OnErrorListener mOnErrorListener;
- private boolean mStartWhenPrepared;
- private int mSeekWhenPrepared;
-
- public VideoView(Context context) {
- super(context);
- initVideoView();
- }
-
- public VideoView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- initVideoView();
- }
-
- public VideoView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- initVideoView();
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- //Log.i("@@@@", "onMeasure");
- int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
- int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
- if (mVideoWidth > 0 && mVideoHeight > 0) {
- if ( mVideoWidth * height > width * mVideoHeight ) {
- //Log.i("@@@", "image too tall, correcting");
- height = width * mVideoHeight / mVideoWidth;
- } else if ( mVideoWidth * height < width * mVideoHeight ) {
- //Log.i("@@@", "image too wide, correcting");
- width = height * mVideoWidth / mVideoHeight;
- } else {
- //Log.i("@@@", "aspect ratio is correct: " +
- //width+"/"+height+"="+
- //mVideoWidth+"/"+mVideoHeight);
- }
- }
- //Log.i("@@@@@@@@@@", "setting size: " + width + 'x' + height);
- setMeasuredDimension(width, height);
- }
-
- public int resolveAdjustedSize(int desiredSize, int measureSpec) {
- int result = desiredSize;
- int specMode = MeasureSpec.getMode(measureSpec);
- int specSize = MeasureSpec.getSize(measureSpec);
-
- switch (specMode) {
- case MeasureSpec.UNSPECIFIED:
- /* Parent says we can be as big as we want. Just don't be larger
- * than max size imposed on ourselves.
- */
- result = desiredSize;
- break;
-
- case MeasureSpec.AT_MOST:
- /* Parent says we can be as big as we want, up to specSize.
- * Don't be larger than specSize, and don't be larger than
- * the max size imposed on ourselves.
- */
- result = Math.min(desiredSize, specSize);
- break;
-
- case MeasureSpec.EXACTLY:
- // No choice. Do what we are told.
- result = specSize;
- break;
- }
- return result;
-}
-
- private void initVideoView() {
- mVideoWidth = 0;
- mVideoHeight = 0;
- getHolder().addCallback(mSHCallback);
- getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- setFocusable(true);
- setFocusableInTouchMode(true);
- requestFocus();
- }
-
- public void setVideoPath(String path) {
- setVideoURI(Uri.parse(path));
- }
-
- public void setVideoURI(Uri uri) {
- mUri = uri;
- mStartWhenPrepared = false;
- mSeekWhenPrepared = 0;
- openVideo();
- requestLayout();
- invalidate();
- }
-
- public void stopPlayback() {
- if (mMediaPlayer != null) {
- mMediaPlayer.stop();
- mMediaPlayer.release();
- mMediaPlayer = null;
- }
- }
-
- private void openVideo() {
- if (mUri == null || mSurfaceHolder == null) {
- // not ready for playback just yet, will try again later
- return;
- }
- // Tell the music playback service to pause
- // TODO: these constants need to be published somewhere in the framework.
- Intent i = new Intent("com.android.music.musicservicecommand");
- i.putExtra("command", "pause");
- mContext.sendBroadcast(i);
-
- if (mMediaPlayer != null) {
- mMediaPlayer.reset();
- mMediaPlayer.release();
- mMediaPlayer = null;
- }
- try {
- mMediaPlayer = new MediaPlayer();
- mMediaPlayer.setOnPreparedListener(mPreparedListener);
- mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
- mIsPrepared = false;
- mMediaPlayer.setOnCompletionListener(mCompletionListener);
- mMediaPlayer.setOnErrorListener(mErrorListener);
- mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
- mCurrentBufferPercentage = 0;
- mMediaPlayer.setDataSource(mContext, mUri);
- mMediaPlayer.setDisplay(mSurfaceHolder);
- mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
- mMediaPlayer.setScreenOnWhilePlaying(true);
- mMediaPlayer.prepareAsync();
- attachMediaController();
- } catch (IOException ex) {
- Log.w("VideoView", "Unable to open content: " + mUri, ex);
- return;
- } catch (IllegalArgumentException ex) {
- Log.w("VideoView", "Unable to open content: " + mUri, ex);
- return;
- }
- }
-
- public void setMediaController(MediaController controller) {
- if (mMediaController != null) {
- mMediaController.hide();
- }
- mMediaController = controller;
- attachMediaController();
- }
-
- private void attachMediaController() {
- if (mMediaPlayer != null && mMediaController != null) {
- mMediaController.setMediaPlayer(this);
- View anchorView = this.getParent() instanceof View ?
- (View)this.getParent() : this;
- mMediaController.setAnchorView(anchorView);
- mMediaController.setEnabled(mIsPrepared);
- }
- }
-
- MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener =
- new MediaPlayer.OnVideoSizeChangedListener() {
- public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
- mVideoWidth = mp.getVideoWidth();
- mVideoHeight = mp.getVideoHeight();
- if (mVideoWidth != 0 && mVideoHeight != 0) {
- getHolder().setFixedSize(mVideoWidth, mVideoHeight);
- }
- }
- };
-
- MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
- public void onPrepared(MediaPlayer mp) {
- // briefly show the mediacontroller
- mIsPrepared = true;
- if (mOnPreparedListener != null) {
- mOnPreparedListener.onPrepared(mMediaPlayer);
- }
- if (mMediaController != null) {
- mMediaController.setEnabled(true);
- }
- mVideoWidth = mp.getVideoWidth();
- mVideoHeight = mp.getVideoHeight();
- if (mVideoWidth != 0 && mVideoHeight != 0) {
- //Log.i("@@@@", "video size: " + mVideoWidth +"/"+ mVideoHeight);
- getHolder().setFixedSize(mVideoWidth, mVideoHeight);
- if (mSurfaceWidth == mVideoWidth && mSurfaceHeight == mVideoHeight) {
- // We didn't actually change the size (it was already at the size
- // we need), so we won't get a "surface changed" callback, so
- // start the video here instead of in the callback.
- if (mSeekWhenPrepared != 0) {
- mMediaPlayer.seekTo(mSeekWhenPrepared);
- mSeekWhenPrepared = 0;
- }
- if (mStartWhenPrepared) {
- mMediaPlayer.start();
- mStartWhenPrepared = false;
- if (mMediaController != null) {
- mMediaController.show();
- }
- } else if (!isPlaying() &&
- (mSeekWhenPrepared != 0 || getCurrentPosition() > 0)) {
- if (mMediaController != null) {
- // Show the media controls when we're paused into a video and make 'em stick.
- mMediaController.show(0);
- }
- }
- }
- } else {
- // We don't know the video size yet, but should start anyway.
- // The video size might be reported to us later.
- if (mSeekWhenPrepared != 0) {
- mMediaPlayer.seekTo(mSeekWhenPrepared);
- mSeekWhenPrepared = 0;
- }
- if (mStartWhenPrepared) {
- mMediaPlayer.start();
- mStartWhenPrepared = false;
- }
- }
- }
- };
-
- private MediaPlayer.OnCompletionListener mCompletionListener =
- new MediaPlayer.OnCompletionListener() {
- public void onCompletion(MediaPlayer mp) {
- if (mMediaController != null) {
- mMediaController.hide();
- }
- if (mOnCompletionListener != null) {
- mOnCompletionListener.onCompletion(mMediaPlayer);
- }
- }
- };
-
- private MediaPlayer.OnErrorListener mErrorListener =
- new MediaPlayer.OnErrorListener() {
- public boolean onError(MediaPlayer mp, int a, int b) {
- Log.d("VideoView", "Error: " + a + "," + b);
- if (mMediaController != null) {
- mMediaController.hide();
- }
-
- /* If an error handler has been supplied, use it and finish. */
- if (mOnErrorListener != null) {
- if (mOnErrorListener.onError(mMediaPlayer, a, b)) {
- return true;
- }
- }
-
- /* Otherwise, pop up an error dialog so the user knows that
- * something bad has happened. Only try and pop up the dialog
- * if we're attached to a window. When we're going away and no
- * longer have a window, don't bother showing the user an error.
- */
- if (getWindowToken() != null) {
- Resources r = mContext.getResources();
- new AlertDialog.Builder(mContext)
- .setTitle(com.android.internal.R.string.VideoView_error_title)
- .setMessage(com.android.internal.R.string.VideoView_error_text_unknown)
- .setPositiveButton(com.android.internal.R.string.VideoView_error_button,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- /* If we get here, there is no onError listener, so
- * at least inform them that the video is over.
- */
- if (mOnCompletionListener != null) {
- mOnCompletionListener.onCompletion(mMediaPlayer);
- }
- }
- })
- .setCancelable(false)
- .show();
- }
- return true;
- }
- };
-
- private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener =
- new MediaPlayer.OnBufferingUpdateListener() {
- public void onBufferingUpdate(MediaPlayer mp, int percent) {
- mCurrentBufferPercentage = percent;
- }
- };
-
- /**
- * Register a callback to be invoked when the media file
- * is loaded and ready to go.
- *
- * @param l The callback that will be run
- */
- public void setOnPreparedListener(MediaPlayer.OnPreparedListener l)
- {
- mOnPreparedListener = l;
- }
-
- /**
- * Register a callback to be invoked when the end of a media file
- * has been reached during playback.
- *
- * @param l The callback that will be run
- */
- public void setOnCompletionListener(OnCompletionListener l)
- {
- mOnCompletionListener = l;
- }
-
- /**
- * Register a callback to be invoked when an error occurs
- * during playback or setup. If no listener is specified,
- * or if the listener returned false, VideoView will inform
- * the user of any errors.
- *
- * @param l The callback that will be run
- */
- public void setOnErrorListener(OnErrorListener l)
- {
- mOnErrorListener = l;
- }
-
- SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback()
- {
- public void surfaceChanged(SurfaceHolder holder, int format,
- int w, int h)
- {
- mSurfaceWidth = w;
- mSurfaceHeight = h;
- if (mMediaPlayer != null && mIsPrepared && mVideoWidth == w && mVideoHeight == h) {
- if (mSeekWhenPrepared != 0) {
- mMediaPlayer.seekTo(mSeekWhenPrepared);
- mSeekWhenPrepared = 0;
- }
- mMediaPlayer.start();
- if (mMediaController != null) {
- mMediaController.show();
- }
- }
- }
-
- public void surfaceCreated(SurfaceHolder holder)
- {
- mSurfaceHolder = holder;
- openVideo();
- }
-
- public void surfaceDestroyed(SurfaceHolder holder)
- {
- // after we return from this we can't use the surface any more
- mSurfaceHolder = null;
- if (mMediaController != null) mMediaController.hide();
- if (mMediaPlayer != null) {
- mMediaPlayer.reset();
- mMediaPlayer.release();
- mMediaPlayer = null;
- }
- }
- };
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- if (mIsPrepared && mMediaPlayer != null && mMediaController != null) {
- toggleMediaControlsVisiblity();
- }
- return false;
- }
-
- @Override
- public boolean onTrackballEvent(MotionEvent ev) {
- if (mIsPrepared && mMediaPlayer != null && mMediaController != null) {
- toggleMediaControlsVisiblity();
- }
- return false;
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event)
- {
- if (mIsPrepared &&
- keyCode != KeyEvent.KEYCODE_BACK &&
- keyCode != KeyEvent.KEYCODE_VOLUME_UP &&
- keyCode != KeyEvent.KEYCODE_VOLUME_DOWN &&
- keyCode != KeyEvent.KEYCODE_MENU &&
- keyCode != KeyEvent.KEYCODE_CALL &&
- keyCode != KeyEvent.KEYCODE_ENDCALL &&
- mMediaPlayer != null &&
- mMediaController != null) {
- if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK ||
- keyCode == KeyEvent.KEYCODE_PLAYPAUSE) {
- if (mMediaPlayer.isPlaying()) {
- pause();
- mMediaController.show();
- } else {
- start();
- mMediaController.hide();
- }
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_STOP
- && mMediaPlayer.isPlaying()) {
- pause();
- mMediaController.show();
- } else {
- toggleMediaControlsVisiblity();
- }
- }
-
- return super.onKeyDown(keyCode, event);
- }
-
- private void toggleMediaControlsVisiblity() {
- if (mMediaController.isShowing()) {
- mMediaController.hide();
- } else {
- mMediaController.show();
- }
- }
-
- public void start() {
- if (mMediaPlayer != null && mIsPrepared) {
- mMediaPlayer.start();
- mStartWhenPrepared = false;
- } else {
- mStartWhenPrepared = true;
- }
- }
-
- public void pause() {
- if (mMediaPlayer != null && mIsPrepared) {
- if (mMediaPlayer.isPlaying()) {
- mMediaPlayer.pause();
- }
- }
- mStartWhenPrepared = false;
- }
-
- public int getDuration() {
- if (mMediaPlayer != null && mIsPrepared) {
- return mMediaPlayer.getDuration();
- }
- return -1;
- }
-
- public int getCurrentPosition() {
- if (mMediaPlayer != null && mIsPrepared) {
- return mMediaPlayer.getCurrentPosition();
- }
- return 0;
- }
-
- public void seekTo(int msec) {
- if (mMediaPlayer != null && mIsPrepared) {
- mMediaPlayer.seekTo(msec);
- } else {
- mSeekWhenPrepared = msec;
- }
- }
-
- public boolean isPlaying() {
- if (mMediaPlayer != null && mIsPrepared) {
- return mMediaPlayer.isPlaying();
- }
- return false;
- }
-
- public int getBufferPercentage() {
- if (mMediaPlayer != null) {
- return mCurrentBufferPercentage;
- }
- return 0;
- }
-}
diff --git a/core/java/android/widget/ViewAnimator.java b/core/java/android/widget/ViewAnimator.java
deleted file mode 100644
index fa8935e..0000000
--- a/core/java/android/widget/ViewAnimator.java
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-
-/**
- * Base class for a {@link FrameLayout} container that will perform animations
- * when switching between its views.
- *
- * @attr ref android.R.styleable#ViewAnimator_inAnimation
- * @attr ref android.R.styleable#ViewAnimator_outAnimation
- */
-public class ViewAnimator extends FrameLayout {
-
- int mWhichChild = 0;
- boolean mFirstTime = true;
- boolean mAnimateFirstTime = true;
-
- Animation mInAnimation;
- Animation mOutAnimation;
-
- public ViewAnimator(Context context) {
- super(context);
- initViewAnimator();
- }
-
- public ViewAnimator(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ViewAnimator);
- int resource = a.getResourceId(com.android.internal.R.styleable.ViewAnimator_inAnimation, 0);
- if (resource > 0) {
- setInAnimation(context, resource);
- }
-
- resource = a.getResourceId(com.android.internal.R.styleable.ViewAnimator_outAnimation, 0);
- if (resource > 0) {
- setOutAnimation(context, resource);
- }
- a.recycle();
-
- initViewAnimator();
- }
-
- private void initViewAnimator() {
- mMeasureAllChildren = true;
- }
-
- /**
- * Sets which child view will be displayed.
- *
- * @param whichChild the index of the child view to display
- */
- public void setDisplayedChild(int whichChild) {
- mWhichChild = whichChild;
- if (whichChild >= getChildCount()) {
- mWhichChild = 0;
- } else if (whichChild < 0) {
- mWhichChild = getChildCount() - 1;
- }
- boolean hasFocus = getFocusedChild() != null;
- // This will clear old focus if we had it
- showOnly(mWhichChild);
- if (hasFocus) {
- // Try to retake focus if we had it
- requestFocus(FOCUS_FORWARD);
- }
- }
-
- /**
- * Returns the index of the currently displayed child view.
- */
- public int getDisplayedChild() {
- return mWhichChild;
- }
-
- /**
- * Manually shows the next child.
- */
- public void showNext() {
- setDisplayedChild(mWhichChild + 1);
- }
-
- /**
- * Manually shows the previous child.
- */
- public void showPrevious() {
- setDisplayedChild(mWhichChild - 1);
- }
-
- /**
- * Shows only the specified child. The other displays Views exit the screen
- * with the {@link #getOutAnimation() out animation} and the specified child
- * enters the screen with the {@link #getInAnimation() in animation}.
- *
- * @param childIndex The index of the child to be shown.
- */
- void showOnly(int childIndex) {
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (i == childIndex) {
- if ((!mFirstTime || mAnimateFirstTime) && mInAnimation != null) {
- child.startAnimation(mInAnimation);
- }
- child.setVisibility(View.VISIBLE);
- mFirstTime = false;
- } else {
- if (mOutAnimation != null && child.getVisibility() == View.VISIBLE) {
- child.startAnimation(mOutAnimation);
- } else if (child.getAnimation() == mInAnimation)
- child.clearAnimation();
- child.setVisibility(View.GONE);
- }
- }
- }
-
- @Override
- public void addView(View child, int index, ViewGroup.LayoutParams params) {
- super.addView(child, index, params);
- if (getChildCount() == 1) {
- child.setVisibility(View.VISIBLE);
- } else {
- child.setVisibility(View.GONE);
- }
- }
-
- @Override
- public void removeAllViews() {
- super.removeAllViews();
- mWhichChild = 0;
- mFirstTime = true;
- }
-
- @Override
- public void removeView(View view) {
- final int index = indexOfChild(view);
- if (index >= 0) {
- removeViewAt(index);
- }
- }
-
- @Override
- public void removeViewAt(int index) {
- super.removeViewAt(index);
- final int childCount = getChildCount();
- if (childCount == 0) {
- mWhichChild = 0;
- mFirstTime = true;
- } else if (mWhichChild >= childCount) {
- // Displayed is above child count, so float down to top of stack
- setDisplayedChild(childCount - 1);
- } else if (mWhichChild == index) {
- // Displayed was removed, so show the new child living in its place
- setDisplayedChild(mWhichChild);
- }
- }
-
- public void removeViewInLayout(View view) {
- removeView(view);
- }
-
- public void removeViews(int start, int count) {
- super.removeViews(start, count);
- if (getChildCount() == 0) {
- mWhichChild = 0;
- mFirstTime = true;
- } else if (mWhichChild >= start && mWhichChild < start + count) {
- // Try showing new displayed child, wrapping if needed
- setDisplayedChild(mWhichChild);
- }
- }
-
- public void removeViewsInLayout(int start, int count) {
- removeViews(start, count);
- }
-
- /**
- * Returns the View corresponding to the currently displayed child.
- *
- * @return The View currently displayed.
- *
- * @see #getDisplayedChild()
- */
- public View getCurrentView() {
- return getChildAt(mWhichChild);
- }
-
- /**
- * Returns the current animation used to animate a View that enters the screen.
- *
- * @return An Animation or null if none is set.
- *
- * @see #setInAnimation(android.view.animation.Animation)
- * @see #setInAnimation(android.content.Context, int)
- */
- public Animation getInAnimation() {
- return mInAnimation;
- }
-
- /**
- * Specifies the animation used to animate a View that enters the screen.
- *
- * @param inAnimation The animation started when a View enters the screen.
- *
- * @see #getInAnimation()
- * @see #setInAnimation(android.content.Context, int)
- */
- public void setInAnimation(Animation inAnimation) {
- mInAnimation = inAnimation;
- }
-
- /**
- * Returns the current animation used to animate a View that exits the screen.
- *
- * @return An Animation or null if none is set.
- *
- * @see #setOutAnimation(android.view.animation.Animation)
- * @see #setOutAnimation(android.content.Context, int)
- */
- public Animation getOutAnimation() {
- return mOutAnimation;
- }
-
- /**
- * Specifies the animation used to animate a View that exit the screen.
- *
- * @param outAnimation The animation started when a View exit the screen.
- *
- * @see #getOutAnimation()
- * @see #setOutAnimation(android.content.Context, int)
- */
- public void setOutAnimation(Animation outAnimation) {
- mOutAnimation = outAnimation;
- }
-
- /**
- * Specifies the animation used to animate a View that enters the screen.
- *
- * @param context The application's environment.
- * @param resourceID The resource id of the animation.
- *
- * @see #getInAnimation()
- * @see #setInAnimation(android.view.animation.Animation)
- */
- public void setInAnimation(Context context, int resourceID) {
- setInAnimation(AnimationUtils.loadAnimation(context, resourceID));
- }
-
- /**
- * Specifies the animation used to animate a View that exit the screen.
- *
- * @param context The application's environment.
- * @param resourceID The resource id of the animation.
- *
- * @see #getOutAnimation()
- * @see #setOutAnimation(android.view.animation.Animation)
- */
- public void setOutAnimation(Context context, int resourceID) {
- setOutAnimation(AnimationUtils.loadAnimation(context, resourceID));
- }
-
- /**
- * Indicates whether the current View should be animated the first time
- * the ViewAnimation is displayed.
- *
- * @param animate True to animate the current View the first time it is displayed,
- * false otherwise.
- */
- public void setAnimateFirstView(boolean animate) {
- mAnimateFirstTime = animate;
- }
-
- @Override
- public int getBaseline() {
- return (getCurrentView() != null) ? getCurrentView().getBaseline() : super.getBaseline();
- }
-}
diff --git a/core/java/android/widget/ViewFlipper.java b/core/java/android/widget/ViewFlipper.java
deleted file mode 100644
index 8a7946b..0000000
--- a/core/java/android/widget/ViewFlipper.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.os.Handler;
-import android.os.Message;
-import android.util.AttributeSet;
-import android.widget.RemoteViews.RemoteView;
-
-/**
- * Simple {@link ViewAnimator} that will animate between two or more views
- * that have been added to it. Only one child is shown at a time. If
- * requested, can automatically flip between each child at a regular interval.
- *
- * @attr ref android.R.styleable#ViewFlipper_flipInterval
- */
-public class ViewFlipper extends ViewAnimator {
- private int mFlipInterval = 3000;
- private boolean mKeepFlipping = false;
-
- public ViewFlipper(Context context) {
- super(context);
- }
-
- public ViewFlipper(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.ViewFlipper);
- mFlipInterval = a.getInt(com.android.internal.R.styleable.ViewFlipper_flipInterval,
- 3000);
- a.recycle();
- }
-
- /**
- * How long to wait before flipping to the next view
- *
- * @param milliseconds
- * time in milliseconds
- */
- @android.view.RemotableViewMethod
- public void setFlipInterval(int milliseconds) {
- mFlipInterval = milliseconds;
- }
-
- /**
- * Start a timer to cycle through child views
- */
- public void startFlipping() {
- if (!mKeepFlipping) {
- mKeepFlipping = true;
- showOnly(mWhichChild);
- Message msg = mHandler.obtainMessage(FLIP_MSG);
- mHandler.sendMessageDelayed(msg, mFlipInterval);
- }
- }
-
- /**
- * No more flips
- */
- public void stopFlipping() {
- mKeepFlipping = false;
- }
-
- /**
- * Returns true if the child views are flipping.
- */
- public boolean isFlipping() {
- return mKeepFlipping;
- }
-
- private final int FLIP_MSG = 1;
-
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == FLIP_MSG) {
- if (mKeepFlipping) {
- showNext();
- msg = obtainMessage(FLIP_MSG);
- sendMessageDelayed(msg, mFlipInterval);
- }
- }
- }
- };
-}
diff --git a/core/java/android/widget/ViewSwitcher.java b/core/java/android/widget/ViewSwitcher.java
deleted file mode 100644
index f4f23a8..0000000
--- a/core/java/android/widget/ViewSwitcher.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import java.util.Map;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * {@link ViewAnimator} that switches between two views, and has a factory
- * from which these views are created. You can either use the factory to
- * create the views, or add them yourself. A ViewSwitcher can only have two
- * child views, of which only one is shown at a time.
- */
-public class ViewSwitcher extends ViewAnimator {
- /**
- * The factory used to create the two children.
- */
- ViewFactory mFactory;
-
- /**
- * Creates a new empty ViewSwitcher.
- *
- * @param context the application's environment
- */
- public ViewSwitcher(Context context) {
- super(context);
- }
-
- /**
- * Creates a new empty ViewSwitcher for the given context and with the
- * specified set attributes.
- *
- * @param context the application environment
- * @param attrs a collection of attributes
- */
- public ViewSwitcher(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws IllegalStateException if this switcher already contains two children
- */
- @Override
- public void addView(View child, int index, ViewGroup.LayoutParams params) {
- if (getChildCount() >= 2) {
- throw new IllegalStateException("Can't add more than 2 views to a ViewSwitcher");
- }
- super.addView(child, index, params);
- }
-
- /**
- * Returns the next view to be displayed.
- *
- * @return the view that will be displayed after the next views flip.
- */
- public View getNextView() {
- int which = mWhichChild == 0 ? 1 : 0;
- return getChildAt(which);
- }
-
- private View obtainView() {
- View child = mFactory.makeView();
- LayoutParams lp = (LayoutParams) child.getLayoutParams();
- if (lp == null) {
- lp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
- }
- addView(child, lp);
- return child;
- }
-
- /**
- * Sets the factory used to create the two views between which the
- * ViewSwitcher will flip. Instead of using a factory, you can call
- * {@link #addView(android.view.View, int, android.view.ViewGroup.LayoutParams)}
- * twice.
- *
- * @param factory the view factory used to generate the switcher's content
- */
- public void setFactory(ViewFactory factory) {
- mFactory = factory;
- obtainView();
- obtainView();
- }
-
- /**
- * Reset the ViewSwitcher to hide all of the existing views and to make it
- * think that the first time animation has not yet played.
- */
- public void reset() {
- mFirstTime = true;
- View v;
- v = getChildAt(0);
- if (v != null) {
- v.setVisibility(View.GONE);
- }
- v = getChildAt(1);
- if (v != null) {
- v.setVisibility(View.GONE);
- }
- }
-
- /**
- * Creates views in a ViewSwitcher.
- */
- public interface ViewFactory {
- /**
- * Creates a new {@link android.view.View} to be added in a
- * {@link android.widget.ViewSwitcher}.
- *
- * @return a {@link android.view.View}
- */
- View makeView();
- }
-}
-
diff --git a/core/java/android/widget/WrapperListAdapter.java b/core/java/android/widget/WrapperListAdapter.java
deleted file mode 100644
index 7fe12ae..0000000
--- a/core/java/android/widget/WrapperListAdapter.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-/**
- * List adapter that wraps another list adapter. The wrapped adapter can be retrieved
- * by calling {@link #getWrappedAdapter()}.
- *
- * @see ListView
- */
-public interface WrapperListAdapter extends ListAdapter {
- /**
- * Returns the adapter wrapped by this list adapter.
- *
- * @return The {@link android.widget.ListAdapter} wrapped by this adapter.
- */
- public ListAdapter getWrappedAdapter();
-}
diff --git a/core/java/android/widget/ZoomButton.java b/core/java/android/widget/ZoomButton.java
deleted file mode 100644
index 0df919d..0000000
--- a/core/java/android/widget/ZoomButton.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-import android.os.Handler;
-import android.util.AttributeSet;
-import android.view.GestureDetector;
-import android.view.HapticFeedbackConstants;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.GestureDetector.SimpleOnGestureListener;
-import android.view.View.OnLongClickListener;
-
-
-public class ZoomButton extends ImageButton implements OnLongClickListener {
-
- private final Handler mHandler;
- private final Runnable mRunnable = new Runnable() {
- public void run() {
- if ((mOnClickListener != null) && mIsInLongpress && isEnabled()) {
- mOnClickListener.onClick(ZoomButton.this);
- mHandler.postDelayed(this, mZoomSpeed);
- }
- }
- };
- private final GestureDetector mGestureDetector;
-
- private long mZoomSpeed = 1000;
- private boolean mIsInLongpress;
-
- public ZoomButton(Context context) {
- this(context, null);
- }
-
- public ZoomButton(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public ZoomButton(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- mHandler = new Handler();
- mGestureDetector = new GestureDetector(context, new SimpleOnGestureListener() {
- @Override
- public void onLongPress(MotionEvent e) {
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- onLongClick(ZoomButton.this);
- }
- });
- setOnLongClickListener(this);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- mGestureDetector.onTouchEvent(event);
- if ((event.getAction() == MotionEvent.ACTION_CANCEL)
- || (event.getAction() == MotionEvent.ACTION_UP)) {
- mIsInLongpress = false;
- }
- return super.onTouchEvent(event);
- }
-
- public void setZoomSpeed(long speed) {
- mZoomSpeed = speed;
- }
-
- public boolean onLongClick(View v) {
- mIsInLongpress = true;
- mHandler.post(mRunnable);
- return true;
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- mIsInLongpress = false;
- return super.onKeyUp(keyCode, event);
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- if (!enabled) {
-
- /* If we're being disabled reset the state back to unpressed
- * as disabled views don't get events and therefore we won't
- * get the up event to reset the state.
- */
- setPressed(false);
- }
- super.setEnabled(enabled);
- }
-
- @Override
- public boolean dispatchUnhandledMove(View focused, int direction) {
- clearFocus();
- return super.dispatchUnhandledMove(focused, direction);
- }
-}
diff --git a/core/java/android/widget/ZoomControls.java b/core/java/android/widget/ZoomControls.java
deleted file mode 100644
index fdc05b6..0000000
--- a/core/java/android/widget/ZoomControls.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.annotation.Widget;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.animation.AlphaAnimation;
-
-import com.android.internal.R;
-
-
-/**
- * The {@code ZoomControls} class displays a simple set of controls used for zooming and
- * provides callbacks to register for events.
- */
-@Widget
-public class ZoomControls extends LinearLayout {
-
- private final ZoomButton mZoomIn;
- private final ZoomButton mZoomOut;
-
- public ZoomControls(Context context) {
- this(context, null);
- }
-
- public ZoomControls(Context context, AttributeSet attrs) {
- super(context, attrs);
- setFocusable(false);
-
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(R.layout.zoom_controls, this, // we are the parent
- true);
-
- mZoomIn = (ZoomButton) findViewById(R.id.zoomIn);
- mZoomOut = (ZoomButton) findViewById(R.id.zoomOut);
- }
-
- public void setOnZoomInClickListener(OnClickListener listener) {
- mZoomIn.setOnClickListener(listener);
- }
-
- public void setOnZoomOutClickListener(OnClickListener listener) {
- mZoomOut.setOnClickListener(listener);
- }
-
- /*
- * Sets how fast you get zoom events when the user holds down the
- * zoom in/out buttons.
- */
- public void setZoomSpeed(long speed) {
- mZoomIn.setZoomSpeed(speed);
- mZoomOut.setZoomSpeed(speed);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
-
- /* Consume all touch events so they don't get dispatched to the view
- * beneath this view.
- */
- return true;
- }
-
- public void show() {
- if (ZoomRingController.useOldZoom(mContext)) {
- fade(View.VISIBLE, 0.0f, 1.0f);
- }
- }
-
- public void hide() {
- fade(View.GONE, 1.0f, 0.0f);
- }
-
- private void fade(int visibility, float startAlpha, float endAlpha) {
- AlphaAnimation anim = new AlphaAnimation(startAlpha, endAlpha);
- anim.setDuration(500);
- startAnimation(anim);
- setVisibility(visibility);
- }
-
- public void setIsZoomInEnabled(boolean isEnabled) {
- mZoomIn.setEnabled(isEnabled);
- }
-
- public void setIsZoomOutEnabled(boolean isEnabled) {
- mZoomOut.setEnabled(isEnabled);
- }
-
- @Override
- public boolean hasFocus() {
- return mZoomIn.hasFocus() || mZoomOut.hasFocus();
- }
-}
diff --git a/core/java/android/widget/ZoomRing.java b/core/java/android/widget/ZoomRing.java
deleted file mode 100644
index a29e1a0..0000000
--- a/core/java/android/widget/ZoomRing.java
+++ /dev/null
@@ -1,960 +0,0 @@
-package android.widget;
-
-import com.android.internal.R;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.RotateDrawable;
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemClock;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.HapticFeedbackConstants;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-
-/**
- * @hide
- */
-public class ZoomRing extends View {
-
- // TODO: move to ViewConfiguration?
- static final int DOUBLE_TAP_DISMISS_TIMEOUT = ViewConfiguration.getDoubleTapTimeout();
- // TODO: get from theme
- private static final String TAG = "ZoomRing";
-
- // TODO: Temporary until the trail is done
- private static final boolean DRAW_TRAIL = false;
-
- // TODO: xml
- private static final int THUMB_DISTANCE = 63;
-
- /** To avoid floating point calculations, we multiply radians by this value. */
- public static final int RADIAN_INT_MULTIPLIER = 10000;
- public static final int RADIAN_INT_ERROR = 100;
- /** PI using our multiplier. */
- public static final int PI_INT_MULTIPLIED = (int) (Math.PI * RADIAN_INT_MULTIPLIER);
- public static final int TWO_PI_INT_MULTIPLIED = PI_INT_MULTIPLIED * 2;
- /** PI/2 using our multiplier. */
- private static final int HALF_PI_INT_MULTIPLIED = PI_INT_MULTIPLIED / 2;
-
- private int mZeroAngle = HALF_PI_INT_MULTIPLIED * 3;
-
- private static final int THUMB_GRAB_SLOP = PI_INT_MULTIPLIED / 8;
- private static final int THUMB_DRAG_SLOP = PI_INT_MULTIPLIED / 12;
-
- /**
- * Includes error because we compare this to the result of
- * getDelta(getClosestTickeAngle(..), oldAngle) which ends up having some
- * rounding error.
- */
- private static final int MAX_ABS_JUMP_DELTA_ANGLE = (2 * PI_INT_MULTIPLIED / 3) +
- RADIAN_INT_ERROR;
-
- /** The cached X of our center. */
- private int mCenterX;
- /** The cached Y of our center. */
- private int mCenterY;
-
- /** The angle of the thumb (in int radians) */
- private int mThumbAngle;
- private int mThumbHalfWidth;
- private int mThumbHalfHeight;
-
- private int mThumbCwBound = Integer.MIN_VALUE;
- private int mThumbCcwBound = Integer.MIN_VALUE;
- private boolean mEnforceMaxAbsJump = true;
-
- /** The inner radius of the track. */
- private int mBoundInnerRadiusSquared = 0;
- /** The outer radius of the track. */
- private int mBoundOuterRadiusSquared = Integer.MAX_VALUE;
-
- private int mPreviousWidgetDragX;
- private int mPreviousWidgetDragY;
-
- private boolean mDrawThumb = true;
- private Drawable mThumbDrawable;
-
- /** Shown beneath the thumb if we can still zoom in. */
- private Drawable mThumbPlusArrowDrawable;
- /** Shown beneath the thumb if we can still zoom out. */
- private Drawable mThumbMinusArrowDrawable;
- private static final int THUMB_ARROW_PLUS = 1 << 0;
- private static final int THUMB_ARROW_MINUS = 1 << 1;
- /** Bitwise-OR of {@link #THUMB_ARROW_MINUS} and {@link #THUMB_ARROW_PLUS} */
- private int mThumbArrowsToDraw;
- private static final int THUMB_ARROWS_FADE_DURATION = 300;
- private long mThumbArrowsFadeStartTime;
- private int mThumbArrowsAlpha = 255;
-
- private static final int MODE_IDLE = 0;
-
- /**
- * User has his finger down somewhere on the ring (besides the thumb) and we
- * are waiting for him to move the slop amount before considering him in the
- * drag thumb state.
- */
- private static final int MODE_WAITING_FOR_DRAG_THUMB = 5;
- private static final int MODE_DRAG_THUMB = 1;
- /**
- * User has his finger down, but we are waiting for him to pass the touch
- * slop before going into the #MODE_MOVE_ZOOM_RING. This is a good time to
- * show the movable hint.
- */
- private static final int MODE_WAITING_FOR_MOVE_ZOOM_RING = 4;
- private static final int MODE_MOVE_ZOOM_RING = 2;
- private static final int MODE_TAP_DRAG = 3;
- /** Ignore the touch interaction. Reset to MODE_IDLE after up/cancel. */
- private static final int MODE_IGNORE_UNTIL_UP = 6;
- private int mMode;
-
- private long mPreviousUpTime;
- private int mPreviousDownX;
- private int mPreviousDownY;
-
- private int mWaitingForDragThumbDownAngle;
-
- private OnZoomRingCallback mCallback;
- private int mPreviousCallbackAngle;
- private int mCallbackThreshold = Integer.MAX_VALUE;
-
- private boolean mResetThumbAutomatically = true;
- private int mThumbDragStartAngle;
-
- private final int mTouchSlop;
-
- private Drawable mTrail;
- private double mAcculumalatedTrailAngle;
-
- private Scroller mThumbScroller;
-
- private static final int MSG_THUMB_SCROLLER_TICK = 1;
- private static final int MSG_THUMB_ARROWS_FADE_TICK = 2;
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_THUMB_SCROLLER_TICK:
- onThumbScrollerTick();
- break;
-
- case MSG_THUMB_ARROWS_FADE_TICK:
- onThumbArrowsFadeTick();
- break;
- }
- }
- };
-
- public ZoomRing(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
- mTouchSlop = viewConfiguration.getScaledTouchSlop();
-
- // TODO get drawables from style instead
- Resources res = context.getResources();
- mThumbDrawable = res.getDrawable(R.drawable.zoom_ring_thumb);
- mThumbPlusArrowDrawable = res.getDrawable(R.drawable.zoom_ring_thumb_plus_arrow_rotatable).
- mutate();
- mThumbMinusArrowDrawable = res.getDrawable(R.drawable.zoom_ring_thumb_minus_arrow_rotatable).
- mutate();
- if (DRAW_TRAIL) {
- mTrail = res.getDrawable(R.drawable.zoom_ring_trail).mutate();
- }
-
- // TODO: add padding to drawable
- setBackgroundResource(R.drawable.zoom_ring_track);
- // TODO get from style
- setRingBounds(43, Integer.MAX_VALUE);
-
- mThumbHalfHeight = mThumbDrawable.getIntrinsicHeight() / 2;
- mThumbHalfWidth = mThumbDrawable.getIntrinsicWidth() / 2;
-
- mCallbackThreshold = PI_INT_MULTIPLIED / 6;
- }
-
- public ZoomRing(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public ZoomRing(Context context) {
- this(context, null);
- }
-
- public void setCallback(OnZoomRingCallback callback) {
- mCallback = callback;
- }
-
- // TODO: rename
- public void setCallbackThreshold(int callbackThreshold) {
- mCallbackThreshold = callbackThreshold;
- }
-
- // TODO: from XML too
- public void setRingBounds(int innerRadius, int outerRadius) {
- mBoundInnerRadiusSquared = innerRadius * innerRadius;
- if (mBoundInnerRadiusSquared < innerRadius) {
- // Prevent overflow
- mBoundInnerRadiusSquared = Integer.MAX_VALUE;
- }
-
- mBoundOuterRadiusSquared = outerRadius * outerRadius;
- if (mBoundOuterRadiusSquared < outerRadius) {
- // Prevent overflow
- mBoundOuterRadiusSquared = Integer.MAX_VALUE;
- }
- }
-
- public void setThumbClockwiseBound(int angle) {
- if (angle < 0) {
- mThumbCwBound = Integer.MIN_VALUE;
- } else {
- mThumbCwBound = getClosestTickAngle(angle);
- }
- setEnforceMaxAbsJump();
- }
-
- public void setThumbCounterclockwiseBound(int angle) {
- if (angle < 0) {
- mThumbCcwBound = Integer.MIN_VALUE;
- } else {
- mThumbCcwBound = getClosestTickAngle(angle);
- }
- setEnforceMaxAbsJump();
- }
-
- private void setEnforceMaxAbsJump() {
- // If there are bounds in both direction, there is no reason to restrict
- // the amount that a user can absolute jump to
- mEnforceMaxAbsJump =
- mThumbCcwBound == Integer.MIN_VALUE || mThumbCwBound == Integer.MIN_VALUE;
- }
-
- public int getThumbAngle() {
- return mThumbAngle;
- }
-
- public void setThumbAngle(int angle) {
- angle = getValidAngle(angle);
- mPreviousCallbackAngle = getClosestTickAngle(angle);
- setThumbAngleAuto(angle, false, false);
- }
-
- /**
- * Sets the thumb angle. If already animating, will continue the animation,
- * otherwise it will do a direct jump.
- *
- * @param angle
- * @param useDirection Whether to use the ccw parameter
- * @param ccw Whether going counterclockwise (only used if useDirection is true)
- */
- private void setThumbAngleAuto(int angle, boolean useDirection, boolean ccw) {
- if (mThumbScroller == null
- || mThumbScroller.isFinished()
- || Math.abs(getDelta(angle, getThumbScrollerAngle())) < THUMB_GRAB_SLOP) {
- setThumbAngleInt(angle);
- } else {
- if (useDirection) {
- setThumbAngleAnimated(angle, 0, ccw);
- } else {
- setThumbAngleAnimated(angle, 0);
- }
- }
- }
-
- private void setThumbAngleInt(int angle) {
- mThumbAngle = angle;
- int unoffsetAngle = angle + mZeroAngle;
- int thumbCenterX = (int) (Math.cos(1f * unoffsetAngle / RADIAN_INT_MULTIPLIER) *
- THUMB_DISTANCE) + mCenterX;
- int thumbCenterY = (int) (Math.sin(1f * unoffsetAngle / RADIAN_INT_MULTIPLIER) *
- THUMB_DISTANCE) * -1 + mCenterY;
-
- mThumbDrawable.setBounds(thumbCenterX - mThumbHalfWidth,
- thumbCenterY - mThumbHalfHeight,
- thumbCenterX + mThumbHalfWidth,
- thumbCenterY + mThumbHalfHeight);
-
- if (mThumbArrowsToDraw > 0) {
- setThumbArrowsAngle(angle);
- }
-
- if (DRAW_TRAIL) {
- double degrees;
- degrees = Math.min(359.0, Math.abs(mAcculumalatedTrailAngle));
- int level = (int) (10000.0 * degrees / 360.0);
-
- mTrail.setLevel((int) (10000.0 *
- (-Math.toDegrees(angle / (double) RADIAN_INT_MULTIPLIER) -
- degrees + 90) / 360.0));
- ((RotateDrawable) mTrail).getDrawable().setLevel(level);
- }
-
- invalidate();
- }
-
- /**
- *
- * @param angle
- * @param duration The animation duration, or 0 for the default duration.
- */
- public void setThumbAngleAnimated(int angle, int duration) {
- // The angle when going from the current angle to the new angle
- int deltaAngle = getDelta(mThumbAngle, angle);
- // Counter clockwise if the new angle is more the current angle
- boolean counterClockwise = deltaAngle > 0;
-
- if (deltaAngle > PI_INT_MULTIPLIED || deltaAngle < -PI_INT_MULTIPLIED) {
- // It's quicker to go the other direction
- counterClockwise = !counterClockwise;
- }
-
- setThumbAngleAnimated(angle, duration, counterClockwise);
- }
-
- public void setThumbAngleAnimated(int angle, int duration, boolean counterClockwise) {
- if (mThumbScroller == null) {
- mThumbScroller = new Scroller(mContext);
- }
-
- int startAngle = mThumbAngle;
- int endAngle = getValidAngle(angle);
- int deltaAngle = getDelta(startAngle, endAngle, counterClockwise);
- if (startAngle + deltaAngle < 0) {
- // Keep our angles positive
- startAngle += TWO_PI_INT_MULTIPLIED;
- }
-
- if (!mThumbScroller.isFinished()) {
- duration = mThumbScroller.getDuration() - mThumbScroller.timePassed();
- } else if (duration == 0) {
- duration = getAnimationDuration(deltaAngle);
- }
- mThumbScroller.startScroll(startAngle, 0, deltaAngle, 0, duration);
- onThumbScrollerTick();
- }
-
- private int getAnimationDuration(int deltaAngle) {
- if (deltaAngle < 0) deltaAngle *= -1;
- return 300 + deltaAngle * 300 / RADIAN_INT_MULTIPLIER;
- }
-
- private void onThumbScrollerTick() {
- if (!mThumbScroller.computeScrollOffset()) return;
- setThumbAngleInt(getThumbScrollerAngle());
- mHandler.sendEmptyMessage(MSG_THUMB_SCROLLER_TICK);
- }
-
- private int getThumbScrollerAngle() {
- return mThumbScroller.getCurrX() % TWO_PI_INT_MULTIPLIED;
- }
-
- public void resetThumbAngle(int angle) {
- mPreviousCallbackAngle = angle;
- setThumbAngleInt(angle);
- }
-
- public void resetThumbAngle() {
- if (mResetThumbAutomatically) {
- resetThumbAngle(0);
- }
- }
-
- public void setResetThumbAutomatically(boolean resetThumbAutomatically) {
- mResetThumbAutomatically = resetThumbAutomatically;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- setMeasuredDimension(resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec),
- resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec));
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right,
- int bottom) {
- super.onLayout(changed, left, top, right, bottom);
-
- // Cache the center point
- mCenterX = (right - left) / 2;
- mCenterY = (bottom - top) / 2;
-
- // Done here since we now have center, which is needed to calculate some
- // aux info for thumb angle
- if (mThumbAngle == Integer.MIN_VALUE) {
- resetThumbAngle();
- }
-
- if (DRAW_TRAIL) {
- mTrail.setBounds(0, 0, right - left, bottom - top);
- }
-
- mThumbPlusArrowDrawable.setBounds(0, 0, right - left, bottom - top);
- mThumbMinusArrowDrawable.setBounds(0, 0, right - left, bottom - top);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- return handleTouch(event.getAction(), event.getEventTime(),
- (int) event.getX(), (int) event.getY(), (int) event.getRawX(),
- (int) event.getRawY());
- }
-
- private void resetState() {
- mMode = MODE_IDLE;
- mPreviousWidgetDragX = mPreviousWidgetDragY = Integer.MIN_VALUE;
- mAcculumalatedTrailAngle = 0.0;
- }
-
- public void setTapDragMode(boolean tapDragMode, int x, int y) {
- resetState();
- mMode = tapDragMode ? MODE_TAP_DRAG : MODE_IDLE;
-
- if (tapDragMode) {
- onThumbDragStarted(getAngle(x - mCenterX, y - mCenterY));
- }
- }
-
- public boolean handleTouch(int action, long time, int x, int y, int rawX, int rawY) {
- switch (action) {
-
- case MotionEvent.ACTION_DOWN:
- if (time - mPreviousUpTime <= DOUBLE_TAP_DISMISS_TIMEOUT) {
- mCallback.onZoomRingDismissed(true);
- onTouchUp(time);
-
- // Dismissing, so halt here
- return true;
- }
-
- mCallback.onUserInteractionStarted();
- mPreviousDownX = x;
- mPreviousDownY = y;
- resetState();
- // Fall through to code below switch (since the down is used for
- // jumping to the touched tick)
- break;
-
- case MotionEvent.ACTION_MOVE:
- if (mMode == MODE_IGNORE_UNTIL_UP) return true;
-
- // Fall through to code below switch
- break;
-
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- onTouchUp(time);
- return true;
-
- default:
- return false;
- }
-
- // local{X,Y} will be where the center of the widget is (0,0)
- int localX = x - mCenterX;
- int localY = y - mCenterY;
- boolean isTouchingThumb = true;
- boolean isInRingBounds = true;
-
- int touchAngle = getAngle(localX, localY);
- int radiusSquared = localX * localX + localY * localY;
- if (radiusSquared < mBoundInnerRadiusSquared ||
- radiusSquared > mBoundOuterRadiusSquared) {
- // Out-of-bounds
- isTouchingThumb = false;
- isInRingBounds = false;
- }
-
- int deltaThumbAndTouch = getDelta(mThumbAngle, touchAngle);
- int absoluteDeltaThumbAndTouch = deltaThumbAndTouch >= 0 ?
- deltaThumbAndTouch : -deltaThumbAndTouch;
- if (isTouchingThumb &&
- absoluteDeltaThumbAndTouch > THUMB_GRAB_SLOP) {
- // Didn't grab close enough to the thumb
- isTouchingThumb = false;
- }
-
- if (mMode == MODE_IDLE) {
- if (isTouchingThumb) {
- // They grabbed the thumb
- mMode = MODE_DRAG_THUMB;
- onThumbDragStarted(touchAngle);
-
- } else if (isInRingBounds) {
- // They tapped somewhere else on the ring
- int tickAngle = getClosestTickAngle(touchAngle);
-
- int deltaThumbAndTick = getDelta(mThumbAngle, tickAngle);
- int boundAngle = getBoundIfExceeds(mThumbAngle, deltaThumbAndTick);
-
- if (mEnforceMaxAbsJump) {
- // Enforcing the max jump
- if (deltaThumbAndTick > MAX_ABS_JUMP_DELTA_ANGLE ||
- deltaThumbAndTick < -MAX_ABS_JUMP_DELTA_ANGLE) {
- // Trying to jump too far, ignore this touch interaction
- mMode = MODE_IGNORE_UNTIL_UP;
- return true;
- }
-
- // Make sure we only let them jump within bounds
- if (boundAngle != Integer.MIN_VALUE) {
- tickAngle = boundAngle;
- }
- } else {
- // Not enforcing the max jump, but we have to make sure
- // we're getting to the tapped angle by going through the
- // in-bounds region
- if (boundAngle != Integer.MIN_VALUE) {
- // Going this direction hits a bound, let's go the opposite direction
- boolean oldDirectionIsCcw = deltaThumbAndTick > 0;
- deltaThumbAndTick = getDelta(mThumbAngle, tickAngle, !oldDirectionIsCcw);
- boundAngle = getBoundIfExceeds(mThumbAngle, deltaThumbAndTick);
- if (boundAngle != Integer.MIN_VALUE) {
- // Not allowed to be here, it is between two bounds
- mMode = MODE_IGNORE_UNTIL_UP;
- return true;
- }
- }
- }
-
- mMode = MODE_WAITING_FOR_DRAG_THUMB;
- mWaitingForDragThumbDownAngle = touchAngle;
- boolean ccw = deltaThumbAndTick > 0;
- setThumbAngleAnimated(tickAngle, 0, ccw);
-
- // Our thumb scrolling animation takes us from mThumbAngle to tickAngle
- onThumbDragStarted(mThumbAngle);
- onThumbDragged(tickAngle, true, ccw);
-
- } else {
- // They tapped somewhere else
- mMode = MODE_WAITING_FOR_MOVE_ZOOM_RING;
- mCallback.onZoomRingSetMovableHintVisible(true);
- }
-
- } else if (mMode == MODE_WAITING_FOR_DRAG_THUMB) {
- int deltaDownAngle = getDelta(mWaitingForDragThumbDownAngle, touchAngle);
- if ((deltaDownAngle < -THUMB_DRAG_SLOP || deltaDownAngle > THUMB_DRAG_SLOP) &&
- isDeltaInBounds(mWaitingForDragThumbDownAngle, deltaDownAngle)) {
- mMode = MODE_DRAG_THUMB;
- }
-
- } else if (mMode == MODE_WAITING_FOR_MOVE_ZOOM_RING) {
- if (Math.abs(x - mPreviousDownX) > mTouchSlop ||
- Math.abs(y - mPreviousDownY) > mTouchSlop) {
- /* Make sure the user has moved the slop amount before going into that mode. */
- mMode = MODE_MOVE_ZOOM_RING;
- mCallback.onZoomRingMovingStarted();
- }
- }
-
- // Purposefully not an "else if"
- if (mMode == MODE_DRAG_THUMB || mMode == MODE_TAP_DRAG) {
- if (isInRingBounds) {
- onThumbDragged(touchAngle, false, false);
- }
- } else if (mMode == MODE_MOVE_ZOOM_RING) {
- onZoomRingMoved(rawX, rawY);
- }
-
- return true;
- }
-
- private void onTouchUp(long time) {
- if (mMode == MODE_MOVE_ZOOM_RING || mMode == MODE_WAITING_FOR_MOVE_ZOOM_RING) {
- mCallback.onZoomRingSetMovableHintVisible(false);
- if (mMode == MODE_MOVE_ZOOM_RING) {
- mCallback.onZoomRingMovingStopped();
- }
- } else if (mMode == MODE_DRAG_THUMB || mMode == MODE_TAP_DRAG ||
- mMode == MODE_WAITING_FOR_DRAG_THUMB) {
- onThumbDragStopped();
-
- if (mMode == MODE_DRAG_THUMB) {
- // Animate back to a tick
- setThumbAngleAnimated(mPreviousCallbackAngle, 0);
- }
- }
-
- mPreviousUpTime = time;
- mCallback.onUserInteractionStopped();
- }
-
- private boolean isDeltaInBounds(int startAngle, int deltaAngle) {
- return getBoundIfExceeds(startAngle, deltaAngle) == Integer.MIN_VALUE;
- }
-
- private int getBoundIfExceeds(int startAngle, int deltaAngle) {
- if (deltaAngle > 0) {
- // Counterclockwise movement
- if (mThumbCcwBound != Integer.MIN_VALUE &&
- getDelta(startAngle, mThumbCcwBound, true) < deltaAngle) {
- return mThumbCcwBound;
- }
- } else if (deltaAngle < 0) {
- // Clockwise movement, both of these will be negative
- int deltaThumbAndBound = getDelta(startAngle, mThumbCwBound, false);
- if (mThumbCwBound != Integer.MIN_VALUE &&
- deltaThumbAndBound > deltaAngle) {
- // Tapped outside of the bound in that direction
- return mThumbCwBound;
- }
- }
-
- return Integer.MIN_VALUE;
- }
-
- private int getDelta(int startAngle, int endAngle, boolean useDirection, boolean ccw) {
- return useDirection ? getDelta(startAngle, endAngle, ccw) : getDelta(startAngle, endAngle);
- }
-
- /**
- * Gets the smallest delta between two angles, and infers the direction
- * based on the shortest path between the two angles. If going from
- * startAngle to endAngle is counterclockwise, the result will be positive.
- * If it is clockwise, the result will be negative.
- *
- * @param startAngle The start angle.
- * @param endAngle The end angle.
- * @return The difference in angles.
- */
- private int getDelta(int startAngle, int endAngle) {
- int largerAngle, smallerAngle;
- if (endAngle > startAngle) {
- largerAngle = endAngle;
- smallerAngle = startAngle;
- } else {
- largerAngle = startAngle;
- smallerAngle = endAngle;
- }
-
- int delta = largerAngle - smallerAngle;
- if (delta <= PI_INT_MULTIPLIED) {
- // If going clockwise, negate the delta
- return startAngle == largerAngle ? -delta : delta;
- } else {
- // The other direction is the delta we want (it includes the
- // discontinuous 0-2PI angle)
- delta = TWO_PI_INT_MULTIPLIED - delta;
- // If going clockwise, negate the delta
- return startAngle == smallerAngle ? -delta : delta;
- }
- }
-
- /**
- * Gets the delta between two angles in the direction specified.
- *
- * @param startAngle The start angle.
- * @param endAngle The end angle.
- * @param counterClockwise The direction to take when computing the delta.
- * @return The difference in angles in the given direction.
- */
- private int getDelta(int startAngle, int endAngle, boolean counterClockwise) {
- int delta = endAngle - startAngle;
-
- if (!counterClockwise && delta > 0) {
- // Crossed the discontinuous 0/2PI angle, take the leftover slice of
- // the pie and negate it
- return -TWO_PI_INT_MULTIPLIED + delta;
- } else if (counterClockwise && delta < 0) {
- // Crossed the discontinuous 0/2PI angle, take the leftover slice of
- // the pie (and ensure it is positive)
- return TWO_PI_INT_MULTIPLIED + delta;
- } else {
- return delta;
- }
- }
-
- private void onThumbDragStarted(int startAngle) {
- setThumbArrowsVisible(false);
- mThumbDragStartAngle = startAngle;
- mCallback.onZoomRingThumbDraggingStarted();
- }
-
- private void onThumbDragged(int touchAngle, boolean useDirection, boolean ccw) {
- boolean animateThumbToNewAngle = false;
-
- int totalDeltaAngle;
- totalDeltaAngle = getDelta(mPreviousCallbackAngle, touchAngle, useDirection, ccw);
- int fuzzyCallbackThreshold = (int) (mCallbackThreshold * 0.65f);
- if (totalDeltaAngle >= fuzzyCallbackThreshold
- || totalDeltaAngle <= -fuzzyCallbackThreshold) {
-
- if (!useDirection) {
- // Set ccw to match the direction found by getDelta
- ccw = totalDeltaAngle > 0;
- }
-
- /*
- * When the user slides the thumb through the tick that corresponds
- * to a zoom bound, we don't want to abruptly stop there. Instead,
- * let the user slide it to the next tick, and then animate it back
- * to the original zoom bound tick. Because of this, we make sure
- * the delta from the bound is more than halfway to the next tick.
- * We make sure the bound is between the touch and the previous
- * callback to ensure we just passed the bound.
- */
- int oldTouchAngle = touchAngle;
- if (ccw && mThumbCcwBound != Integer.MIN_VALUE) {
- int deltaCcwBoundAndTouch =
- getDelta(mThumbCcwBound, touchAngle, useDirection, true);
- if (deltaCcwBoundAndTouch >= mCallbackThreshold / 2) {
- // The touch has past a bound
- int deltaPreviousCbAndTouch = getDelta(mPreviousCallbackAngle,
- touchAngle, useDirection, true);
- if (deltaPreviousCbAndTouch >= deltaCcwBoundAndTouch) {
- // The bound is between the previous callback angle and the touch
- touchAngle = mThumbCcwBound;
- // We're moving the touch BACK to the bound, so opposite direction
- ccw = false;
- }
- }
- } else if (!ccw && mThumbCwBound != Integer.MIN_VALUE) {
- // See block above for general comments
- int deltaCwBoundAndTouch =
- getDelta(mThumbCwBound, touchAngle, useDirection, false);
- if (deltaCwBoundAndTouch <= -mCallbackThreshold / 2) {
- int deltaPreviousCbAndTouch = getDelta(mPreviousCallbackAngle,
- touchAngle, useDirection, false);
- /*
- * Both of these will be negative since we got delta in
- * clockwise direction, and we want the magnitude of
- * deltaPreviousCbAndTouch to be greater than the magnitude
- * of deltaCwBoundAndTouch
- */
- if (deltaPreviousCbAndTouch <= deltaCwBoundAndTouch) {
- touchAngle = mThumbCwBound;
- ccw = true;
- }
- }
- }
- if (touchAngle != oldTouchAngle) {
- // We bounded the touch angle
- totalDeltaAngle = getDelta(mPreviousCallbackAngle, touchAngle, useDirection, ccw);
- animateThumbToNewAngle = true;
- mMode = MODE_IGNORE_UNTIL_UP;
- }
-
-
- // Prevent it from jumping too far
- if (mEnforceMaxAbsJump) {
- if (totalDeltaAngle <= -MAX_ABS_JUMP_DELTA_ANGLE) {
- totalDeltaAngle = -MAX_ABS_JUMP_DELTA_ANGLE;
- animateThumbToNewAngle = true;
- } else if (totalDeltaAngle >= MAX_ABS_JUMP_DELTA_ANGLE) {
- totalDeltaAngle = MAX_ABS_JUMP_DELTA_ANGLE;
- animateThumbToNewAngle = true;
- }
- }
-
- /*
- * We need to cover the edge case of a user grabbing the thumb,
- * going into the center of the widget, and then coming out from the
- * center to an angle that's slightly below the angle he's trying to
- * hit. If we do int division, we'll end up with one level lower
- * than the one he was going for.
- */
- int deltaLevels = Math.round((float) totalDeltaAngle / mCallbackThreshold);
- if (deltaLevels != 0) {
- boolean canStillZoom = mCallback.onZoomRingThumbDragged(
- deltaLevels, mThumbDragStartAngle, touchAngle);
-
- // TODO: we're trying the haptics to see how it goes with
- // users, so we're ignoring the settings (for now)
- performHapticFeedback(HapticFeedbackConstants.ZOOM_RING_TICK,
- HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING |
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
-
- // Set the callback angle to the actual angle based on how many delta levels we gave
- mPreviousCallbackAngle = getValidAngle(
- mPreviousCallbackAngle + (deltaLevels * mCallbackThreshold));
- }
- }
-
- if (DRAW_TRAIL) {
- int deltaAngle = getDelta(mThumbAngle, touchAngle, useDirection, ccw);
- mAcculumalatedTrailAngle += Math.toDegrees(deltaAngle / (double) RADIAN_INT_MULTIPLIER);
- }
-
- if (animateThumbToNewAngle) {
- if (useDirection) {
- setThumbAngleAnimated(touchAngle, 0, ccw);
- } else {
- setThumbAngleAnimated(touchAngle, 0);
- }
- } else {
- setThumbAngleAuto(touchAngle, useDirection, ccw);
- }
- }
-
- private int getValidAngle(int invalidAngle) {
- if (invalidAngle < 0) {
- return (invalidAngle % TWO_PI_INT_MULTIPLIED) + TWO_PI_INT_MULTIPLIED;
- } else if (invalidAngle >= TWO_PI_INT_MULTIPLIED) {
- return invalidAngle % TWO_PI_INT_MULTIPLIED;
- } else {
- return invalidAngle;
- }
- }
-
- private int getClosestTickAngle(int angle) {
- int smallerAngleDistance = angle % mCallbackThreshold;
- int smallerAngle = angle - smallerAngleDistance;
- if (smallerAngleDistance < mCallbackThreshold / 2) {
- // Closer to the smaller angle
- return smallerAngle;
- } else {
- // Closer to the bigger angle (premodding)
- return (smallerAngle + mCallbackThreshold) % TWO_PI_INT_MULTIPLIED;
- }
- }
-
- private void onThumbDragStopped() {
- mCallback.onZoomRingThumbDraggingStopped();
- }
-
- private void onZoomRingMoved(int x, int y) {
- if (mPreviousWidgetDragX != Integer.MIN_VALUE) {
- int deltaX = x - mPreviousWidgetDragX;
- int deltaY = y - mPreviousWidgetDragY;
-
- mCallback.onZoomRingMoved(deltaX, deltaY);
- }
-
- mPreviousWidgetDragX = x;
- mPreviousWidgetDragY = y;
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasWindowFocus) {
- super.onWindowFocusChanged(hasWindowFocus);
-
- if (!hasWindowFocus) {
- mCallback.onZoomRingDismissed(true);
- }
- }
-
- private int getAngle(int localX, int localY) {
- int radians = (int) (Math.atan2(localY, localX) * RADIAN_INT_MULTIPLIER);
-
- // Convert from [-pi,pi] to {0,2pi]
- if (radians < 0) {
- radians = -radians;
- } else if (radians > 0) {
- radians = 2 * PI_INT_MULTIPLIED - radians;
- } else {
- radians = 0;
- }
-
- radians = radians - mZeroAngle;
- return radians >= 0 ? radians : radians + 2 * PI_INT_MULTIPLIED;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- if (mDrawThumb) {
- if (DRAW_TRAIL) {
- mTrail.draw(canvas);
- }
- if ((mThumbArrowsToDraw & THUMB_ARROW_PLUS) != 0) {
- mThumbPlusArrowDrawable.draw(canvas);
- }
- if ((mThumbArrowsToDraw & THUMB_ARROW_MINUS) != 0) {
- mThumbMinusArrowDrawable.draw(canvas);
- }
- mThumbDrawable.draw(canvas);
- }
- }
-
- private void setThumbArrowsAngle(int angle) {
- int level = -angle * 10000 / ZoomRing.TWO_PI_INT_MULTIPLIED;
- mThumbPlusArrowDrawable.setLevel(level);
- mThumbMinusArrowDrawable.setLevel(level);
- }
-
- public void setThumbArrowsVisible(boolean visible) {
- if (visible) {
- mThumbArrowsAlpha = 255;
- int callbackAngle = mPreviousCallbackAngle;
- if (callbackAngle < mThumbCwBound - RADIAN_INT_ERROR ||
- callbackAngle > mThumbCwBound + RADIAN_INT_ERROR) {
- mThumbPlusArrowDrawable.setAlpha(255);
- mThumbArrowsToDraw |= THUMB_ARROW_PLUS;
- } else {
- mThumbArrowsToDraw &= ~THUMB_ARROW_PLUS;
- }
- if (callbackAngle < mThumbCcwBound - RADIAN_INT_ERROR ||
- callbackAngle > mThumbCcwBound + RADIAN_INT_ERROR) {
- mThumbMinusArrowDrawable.setAlpha(255);
- mThumbArrowsToDraw |= THUMB_ARROW_MINUS;
- } else {
- mThumbArrowsToDraw &= ~THUMB_ARROW_MINUS;
- }
- invalidate();
- } else if (mThumbArrowsAlpha == 255) {
- // Only start fade if we're fully visible (otherwise another fade is happening already)
- mThumbArrowsFadeStartTime = SystemClock.elapsedRealtime();
- onThumbArrowsFadeTick();
- }
- }
-
- private void onThumbArrowsFadeTick() {
- if (mThumbArrowsAlpha <= 0) {
- mThumbArrowsToDraw = 0;
- return;
- }
-
- mThumbArrowsAlpha = (int)
- (255 - (255 * (SystemClock.elapsedRealtime() - mThumbArrowsFadeStartTime)
- / THUMB_ARROWS_FADE_DURATION));
- if (mThumbArrowsAlpha < 0) mThumbArrowsAlpha = 0;
- if ((mThumbArrowsToDraw & THUMB_ARROW_PLUS) != 0) {
- mThumbPlusArrowDrawable.setAlpha(mThumbArrowsAlpha);
- invalidateDrawable(mThumbPlusArrowDrawable);
- }
- if ((mThumbArrowsToDraw & THUMB_ARROW_MINUS) != 0) {
- mThumbMinusArrowDrawable.setAlpha(mThumbArrowsAlpha);
- invalidateDrawable(mThumbMinusArrowDrawable);
- }
-
- if (!mHandler.hasMessages(MSG_THUMB_ARROWS_FADE_TICK)) {
- mHandler.sendEmptyMessage(MSG_THUMB_ARROWS_FADE_TICK);
- }
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- setThumbArrowsAngle(mThumbAngle);
- setThumbArrowsVisible(true);
- }
-
- public interface OnZoomRingCallback {
- void onZoomRingSetMovableHintVisible(boolean visible);
-
- void onZoomRingMovingStarted();
- boolean onZoomRingMoved(int deltaX, int deltaY);
- void onZoomRingMovingStopped();
-
- void onZoomRingThumbDraggingStarted();
- boolean onZoomRingThumbDragged(int numLevels, int startAngle, int curAngle);
- void onZoomRingThumbDraggingStopped();
-
- void onZoomRingDismissed(boolean dismissImmediately);
-
- void onUserInteractionStarted();
- void onUserInteractionStopped();
- }
-
- private static void printAngle(String angleName, int angle) {
- Log.d(TAG, angleName + ": " + (long) angle * 180 / PI_INT_MULTIPLIED);
- }
-}
diff --git a/core/java/android/widget/ZoomRingController.java b/core/java/android/widget/ZoomRingController.java
deleted file mode 100644
index 2e97fda..0000000
--- a/core/java/android/widget/ZoomRingController.java
+++ /dev/null
@@ -1,1100 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-import android.view.animation.DecelerateInterpolator;
-
-// TODO: make sure no px values exist, only dip (scale if necessary from Viewconfiguration)
-
-/**
- * TODO: Docs
- *
- * If you are using this with a custom View, please call
- * {@link #setVisible(boolean) setVisible(false)} from the
- * {@link View#onDetachedFromWindow}.
- *
- * @hide
- */
-public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
- View.OnTouchListener, View.OnKeyListener {
-
- private static final int ZOOM_RING_RADIUS_INSET = 24;
-
- private static final int ZOOM_RING_RECENTERING_DURATION = 500;
-
- private static final String TAG = "ZoomRing";
-
- public static final boolean USE_OLD_ZOOM = false;
- public static boolean useOldZoom(Context context) {
- return Settings.System.getInt(context.getContentResolver(), "zoom", 1) == 0;
- }
-
- private static final int ZOOM_CONTROLS_TIMEOUT =
- (int) ViewConfiguration.getZoomControlsTimeout();
-
- // TODO: move these to ViewConfiguration or re-use existing ones
- // TODO: scale px values based on latest from ViewConfiguration
- private static final int SECOND_TAP_TIMEOUT = 500;
- private static final int ZOOM_RING_DISMISS_DELAY = SECOND_TAP_TIMEOUT / 2;
- // TODO: view config? at least scaled
- private static final int MAX_PAN_GAP = 20;
- private static final int MAX_INITIATE_PAN_GAP = 10;
- // TODO view config
- private static final int INITIATE_PAN_DELAY = 300;
-
- private static final String SETTING_NAME_SHOWN_TOAST = "shown_zoom_ring_toast";
-
- private Context mContext;
- private WindowManager mWindowManager;
-
- /**
- * The view that is being zoomed by this zoom ring.
- */
- private View mOwnerView;
-
- /**
- * The bounds of the owner view in global coordinates. This is recalculated
- * each time the zoom ring is shown.
- */
- private Rect mOwnerViewBounds = new Rect();
-
- /**
- * The container that is added as a window.
- */
- private FrameLayout mContainer;
- private LayoutParams mContainerLayoutParams;
-
- /**
- * The view (or null) that should receive touch events. This will get set if
- * the touch down hits the container. It will be reset on the touch up.
- */
- private View mTouchTargetView;
- /**
- * The {@link #mTouchTargetView}'s location in window, set on touch down.
- */
- private int[] mTouchTargetLocationInWindow = new int[2];
- /**
- * If the zoom ring is dismissed but the user is still in a touch
- * interaction, we set this to true. This will ignore all touch events until
- * up/cancel, and then set the owner's touch listener to null.
- */
- private boolean mReleaseTouchListenerOnUp;
-
-
- /*
- * Tap-drag is an interaction where the user first taps and then (quickly)
- * does the clockwise or counter-clockwise drag. In reality, this is: (down,
- * up, down, move in circles, up). This differs from the usual events of:
- * (down, up, down, up, down, move in circles, up). While the only
- * difference is the omission of an (up, down), for power-users this is a
- * pretty big improvement as it now only requires them to focus on the
- * screen once (for the first tap down) instead of twice (for the first tap
- * down and then to grab the thumb).
- */
- private int mTapDragStartX;
- private int mTapDragStartY;
-
- private static final int TOUCH_MODE_IDLE = 0;
- private static final int TOUCH_MODE_WAITING_FOR_SECOND_TAP = 1;
- private static final int TOUCH_MODE_WAITING_FOR_TAP_DRAG_MOVEMENT = 2;
- private static final int TOUCH_MODE_FORWARDING_FOR_TAP_DRAG = 3;
- private int mTouchMode;
-
- private boolean mIsZoomRingVisible;
-
- private ZoomRing mZoomRing;
- private int mZoomRingWidth;
- private int mZoomRingHeight;
-
- /** Invokes panning of owner view if the zoom ring is touching an edge. */
- private Panner mPanner;
- private long mTouchingEdgeStartTime;
- private boolean mPanningEnabledForThisInteraction;
-
- private ImageView mPanningArrows;
- private Animation mPanningArrowsEnterAnimation;
- private Animation mPanningArrowsExitAnimation;
-
- private Rect mTempRect = new Rect();
-
- private OnZoomListener mCallback;
-
- private ViewConfiguration mViewConfig;
-
- /**
- * When the zoom ring is centered on screen, this will be the x value used
- * for the container's layout params.
- */
- private int mCenteredContainerX = Integer.MIN_VALUE;
-
- /**
- * When the zoom ring is centered on screen, this will be the y value used
- * for the container's layout params.
- */
- private int mCenteredContainerY = Integer.MIN_VALUE;
-
- /**
- * Scroller used to re-center the zoom ring if the user had dragged it to a
- * corner and then double-taps any point on the owner view (the owner view
- * will center the double-tapped point, but we should re-center the zoom
- * ring).
- * <p>
- * The (x,y) of the scroller is the (x,y) of the container's layout params.
- */
- private Scroller mScroller;
-
- /**
- * When showing the zoom ring, we add the view as a new window. However,
- * there is logic that needs to know the size of the zoom ring which is
- * determined after it's laid out. Therefore, we must post this logic onto
- * the UI thread so it will be exceuted AFTER the layout. This is the logic.
- */
- private Runnable mPostedVisibleInitializer;
-
- /**
- * Only touch from the main thread.
- */
- private static Dialog sTutorialDialog;
- private static long sTutorialShowTime;
- private static final int TUTORIAL_MIN_DISPLAY_TIME = 2000;
-
- private IntentFilter mConfigurationChangedFilter =
- new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED);
-
- private BroadcastReceiver mConfigurationChangedReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (!mIsZoomRingVisible) return;
-
- mHandler.removeMessages(MSG_POST_CONFIGURATION_CHANGED);
- mHandler.sendEmptyMessage(MSG_POST_CONFIGURATION_CHANGED);
- }
- };
-
- /** Keeps the scroller going (or starts it). */
- private static final int MSG_SCROLLER_TICK = 1;
- /** When configuration changes, this is called after the UI thread is idle. */
- private static final int MSG_POST_CONFIGURATION_CHANGED = 2;
- /** Used to delay the zoom ring dismissal. */
- private static final int MSG_DISMISS_ZOOM_RING = 3;
-
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_SCROLLER_TICK:
- onScrollerTick();
- break;
-
- case MSG_POST_CONFIGURATION_CHANGED:
- onPostConfigurationChanged();
- break;
-
- case MSG_DISMISS_ZOOM_RING:
- setVisible(false);
- break;
- }
-
- }
- };
-
- public ZoomRingController(Context context, View ownerView) {
- mContext = context;
- mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
-
- mPanner = new Panner();
- mOwnerView = ownerView;
-
- mZoomRing = new ZoomRing(context);
- mZoomRing.setId(com.android.internal.R.id.zoomControls);
- mZoomRing.setLayoutParams(new FrameLayout.LayoutParams(
- FrameLayout.LayoutParams.WRAP_CONTENT,
- FrameLayout.LayoutParams.WRAP_CONTENT,
- Gravity.CENTER));
- mZoomRing.setCallback(this);
-
- createPanningArrows();
-
- mContainerLayoutParams = new LayoutParams();
- mContainerLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
- mContainerLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCHABLE |
- LayoutParams.FLAG_NOT_FOCUSABLE |
- LayoutParams.FLAG_LAYOUT_NO_LIMITS;
- mContainerLayoutParams.height = LayoutParams.WRAP_CONTENT;
- mContainerLayoutParams.width = LayoutParams.WRAP_CONTENT;
- mContainerLayoutParams.type = LayoutParams.TYPE_APPLICATION_PANEL;
- mContainerLayoutParams.format = PixelFormat.TRANSPARENT;
- // TODO: make a new animation for this
- mContainerLayoutParams.windowAnimations = com.android.internal.R.style.Animation_Dialog;
-
- mContainer = new FrameLayout(context);
- mContainer.setLayoutParams(mContainerLayoutParams);
- mContainer.setMeasureAllChildren(true);
-
- mContainer.addView(mZoomRing);
- mContainer.addView(mPanningArrows);
-
- mScroller = new Scroller(context, new DecelerateInterpolator());
-
- mViewConfig = ViewConfiguration.get(context);
- }
-
- private void createPanningArrows() {
- // TODO: style
- mPanningArrows = new ImageView(mContext);
- mPanningArrows.setImageResource(com.android.internal.R.drawable.zoom_ring_arrows);
- mPanningArrows.setLayoutParams(new FrameLayout.LayoutParams(
- FrameLayout.LayoutParams.WRAP_CONTENT,
- FrameLayout.LayoutParams.WRAP_CONTENT,
- Gravity.CENTER));
- mPanningArrows.setVisibility(View.INVISIBLE);
-
- mPanningArrowsEnterAnimation = AnimationUtils.loadAnimation(mContext,
- com.android.internal.R.anim.fade_in);
- mPanningArrowsExitAnimation = AnimationUtils.loadAnimation(mContext,
- com.android.internal.R.anim.fade_out);
- }
-
- /**
- * Sets the angle (in radians) a user must travel in order for the client to
- * get a callback. Once there is a callback, the accumulator resets. For
- * example, if you set this to PI/6, it will give a callback every time the
- * user moves PI/6 amount on the ring.
- *
- * @param callbackThreshold The angle for the callback threshold, in radians
- */
- public void setZoomCallbackThreshold(float callbackThreshold) {
- mZoomRing.setCallbackThreshold((int) (callbackThreshold * ZoomRing.RADIAN_INT_MULTIPLIER));
- }
-
- /**
- * Sets a drawable for the zoom ring track.
- *
- * @param drawable The drawable to use for the track.
- * @hide Need a better way of doing this, but this one-off for browser so it
- * can have its final look for the usability study
- */
- public void setZoomRingTrack(int drawable) {
- mZoomRing.setBackgroundResource(drawable);
- }
-
- public void setCallback(OnZoomListener callback) {
- mCallback = callback;
- }
-
- public void setThumbAngle(float angle) {
- mZoomRing.setThumbAngle((int) (angle * ZoomRing.RADIAN_INT_MULTIPLIER));
- }
-
- public void setThumbAngleAnimated(float angle) {
- mZoomRing.setThumbAngleAnimated((int) (angle * ZoomRing.RADIAN_INT_MULTIPLIER), 0);
- }
-
- public void setResetThumbAutomatically(boolean resetThumbAutomatically) {
- mZoomRing.setResetThumbAutomatically(resetThumbAutomatically);
- }
-
- public void setThumbClockwiseBound(float angle) {
- mZoomRing.setThumbClockwiseBound(angle >= 0 ?
- (int) (angle * ZoomRing.RADIAN_INT_MULTIPLIER) :
- Integer.MIN_VALUE);
- }
-
- public void setThumbCounterclockwiseBound(float angle) {
- mZoomRing.setThumbCounterclockwiseBound(angle >= 0 ?
- (int) (angle * ZoomRing.RADIAN_INT_MULTIPLIER) :
- Integer.MIN_VALUE);
- }
-
- public boolean isVisible() {
- return mIsZoomRingVisible;
- }
-
- public void setVisible(boolean visible) {
-
- if (useOldZoom(mContext)) return;
-
- if (visible) {
- dismissZoomRingDelayed(ZOOM_CONTROLS_TIMEOUT);
- } else {
- mPanner.stop();
- }
-
- if (mIsZoomRingVisible == visible) {
- return;
- }
- mIsZoomRingVisible = visible;
-
- if (visible) {
- if (mContainerLayoutParams.token == null) {
- mContainerLayoutParams.token = mOwnerView.getWindowToken();
- }
-
- mWindowManager.addView(mContainer, mContainerLayoutParams);
-
- if (mPostedVisibleInitializer == null) {
- mPostedVisibleInitializer = new Runnable() {
- public void run() {
- refreshPositioningVariables();
- resetZoomRing();
-
- // TODO: remove this 'update' and just center zoom ring before the
- // 'add', but need to make sure we have the width and height (which
- // probably can only be retrieved after it's measured, which happens
- // after it's added).
- mWindowManager.updateViewLayout(mContainer, mContainerLayoutParams);
-
- if (mCallback != null) {
- mCallback.onVisibilityChanged(true);
- }
- }
- };
- }
-
- mPanningArrows.setAnimation(null);
-
- mHandler.post(mPostedVisibleInitializer);
-
- // Handle configuration changes when visible
- mContext.registerReceiver(mConfigurationChangedReceiver, mConfigurationChangedFilter);
-
- // Steal key/touches events from the owner
- mOwnerView.setOnKeyListener(this);
- mOwnerView.setOnTouchListener(this);
- mReleaseTouchListenerOnUp = false;
-
- } else {
- // Don't want to steal any more keys/touches
- mOwnerView.setOnKeyListener(null);
- if (mTouchTargetView != null) {
- // We are still stealing the touch events for this touch
- // sequence, so release the touch listener later
- mReleaseTouchListenerOnUp = true;
- } else {
- mOwnerView.setOnTouchListener(null);
- }
-
- // No longer care about configuration changes
- mContext.unregisterReceiver(mConfigurationChangedReceiver);
-
- mWindowManager.removeView(mContainer);
- mHandler.removeCallbacks(mPostedVisibleInitializer);
-
- if (mCallback != null) {
- mCallback.onVisibilityChanged(false);
- }
- }
-
- }
-
- /**
- * TODO: docs
- *
- * Notes:
- * - Touch dispatching is different. Only direct children who are clickable are eligble for touch events.
- * - Please ensure you set your View to INVISIBLE not GONE when hiding it.
- *
- * @return
- */
- public FrameLayout getContainer() {
- return mContainer;
- }
-
- public int getZoomRingId() {
- return mZoomRing.getId();
- }
-
- private void dismissZoomRingDelayed(int delay) {
- mHandler.removeMessages(MSG_DISMISS_ZOOM_RING);
- mHandler.sendEmptyMessageDelayed(MSG_DISMISS_ZOOM_RING, delay);
- }
-
- private void resetZoomRing() {
- mScroller.abortAnimation();
-
- mContainerLayoutParams.x = mCenteredContainerX;
- mContainerLayoutParams.y = mCenteredContainerY;
-
- // Reset the thumb
- mZoomRing.resetThumbAngle();
- }
-
- /**
- * Should be called by the client for each event belonging to the second tap
- * (the down, move, up, and cancel events).
- *
- * @param event The event belonging to the second tap.
- * @return Whether the event was consumed.
- */
- public boolean handleDoubleTapEvent(MotionEvent event) {
- int action = event.getAction();
-
- // TODO: make sure this works well with the
- // ownerView.setOnTouchListener(this) instead of window receiving
- // touches
- if (action == MotionEvent.ACTION_DOWN) {
- mTouchMode = TOUCH_MODE_WAITING_FOR_TAP_DRAG_MOVEMENT;
- int x = (int) event.getX();
- int y = (int) event.getY();
-
- refreshPositioningVariables();
- setVisible(true);
- centerPoint(x, y);
- ensureZoomRingIsCentered();
-
- // Tap drag mode stuff
- mTapDragStartX = x;
- mTapDragStartY = y;
-
- } else if (action == MotionEvent.ACTION_CANCEL) {
- mTouchMode = TOUCH_MODE_IDLE;
-
- } else { // action is move or up
- switch (mTouchMode) {
- case TOUCH_MODE_WAITING_FOR_TAP_DRAG_MOVEMENT: {
- switch (action) {
- case MotionEvent.ACTION_MOVE:
- int x = (int) event.getX();
- int y = (int) event.getY();
- if (Math.abs(x - mTapDragStartX) > mViewConfig.getScaledTouchSlop() ||
- Math.abs(y - mTapDragStartY) >
- mViewConfig.getScaledTouchSlop()) {
- mZoomRing.setTapDragMode(true, x, y);
- mTouchMode = TOUCH_MODE_FORWARDING_FOR_TAP_DRAG;
- setTouchTargetView(mZoomRing);
- }
- return true;
-
- case MotionEvent.ACTION_UP:
- mTouchMode = TOUCH_MODE_IDLE;
- break;
- }
- break;
- }
-
- case TOUCH_MODE_FORWARDING_FOR_TAP_DRAG: {
- switch (action) {
- case MotionEvent.ACTION_MOVE:
- giveTouchToZoomRing(event);
- return true;
-
- case MotionEvent.ACTION_UP:
- mTouchMode = TOUCH_MODE_IDLE;
-
- /*
- * This is a power-user feature that only shows the
- * zoom while the user is performing the tap-drag.
- * That means once it is released, the zoom ring
- * should disappear.
- */
- mZoomRing.setTapDragMode(false, (int) event.getX(), (int) event.getY());
- dismissZoomRingDelayed(0);
- break;
- }
- break;
- }
- }
- }
-
- return true;
- }
-
- private void ensureZoomRingIsCentered() {
- LayoutParams lp = mContainerLayoutParams;
-
- if (lp.x != mCenteredContainerX || lp.y != mCenteredContainerY) {
- int width = mContainer.getWidth();
- int height = mContainer.getHeight();
- mScroller.startScroll(lp.x, lp.y, mCenteredContainerX - lp.x,
- mCenteredContainerY - lp.y, ZOOM_RING_RECENTERING_DURATION);
- mHandler.sendEmptyMessage(MSG_SCROLLER_TICK);
- }
- }
-
- private void refreshPositioningVariables() {
- mZoomRingWidth = mZoomRing.getWidth();
- mZoomRingHeight = mZoomRing.getHeight();
-
- // Calculate the owner view's bounds
- mOwnerView.getGlobalVisibleRect(mOwnerViewBounds);
-
- // Get the center
- Gravity.apply(Gravity.CENTER, mContainer.getWidth(), mContainer.getHeight(),
- mOwnerViewBounds, mTempRect);
- mCenteredContainerX = mTempRect.left;
- mCenteredContainerY = mTempRect.top;
- }
-
- /**
- * Centers the point (in owner view's coordinates).
- */
- private void centerPoint(int x, int y) {
- if (mCallback != null) {
- mCallback.onCenter(x, y);
- }
- }
-
- private void giveTouchToZoomRing(MotionEvent event) {
- int rawX = (int) event.getRawX();
- int rawY = (int) event.getRawY();
- int x = rawX - mContainerLayoutParams.x - mZoomRing.getLeft();
- int y = rawY - mContainerLayoutParams.y - mZoomRing.getTop();
- mZoomRing.handleTouch(event.getAction(), event.getEventTime(), x, y, rawX, rawY);
- }
-
- public void onZoomRingSetMovableHintVisible(boolean visible) {
- setPanningArrowsVisible(visible);
- }
-
- public void onUserInteractionStarted() {
- mHandler.removeMessages(MSG_DISMISS_ZOOM_RING);
- }
-
- public void onUserInteractionStopped() {
- dismissZoomRingDelayed(ZOOM_CONTROLS_TIMEOUT);
- }
-
- public void onZoomRingMovingStarted() {
- mScroller.abortAnimation();
- mTouchingEdgeStartTime = 0;
- if (mCallback != null) {
- mCallback.onBeginPan();
- }
- }
-
- private void setPanningArrowsVisible(boolean visible) {
- mPanningArrows.startAnimation(visible ? mPanningArrowsEnterAnimation
- : mPanningArrowsExitAnimation);
- mPanningArrows.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
- }
-
- public boolean onZoomRingMoved(int deltaX, int deltaY) {
- WindowManager.LayoutParams lp = mContainerLayoutParams;
- Rect ownerBounds = mOwnerViewBounds;
-
- int zoomRingLeft = mZoomRing.getLeft();
- int zoomRingTop = mZoomRing.getTop();
-
- int newX = lp.x + deltaX;
- int newZoomRingX = newX + zoomRingLeft;
- newZoomRingX = (newZoomRingX <= ownerBounds.left) ? ownerBounds.left :
- (newZoomRingX + mZoomRingWidth > ownerBounds.right) ?
- ownerBounds.right - mZoomRingWidth : newZoomRingX;
- lp.x = newZoomRingX - zoomRingLeft;
-
- int newY = lp.y + deltaY;
- int newZoomRingY = newY + zoomRingTop;
- newZoomRingY = (newZoomRingY <= ownerBounds.top) ? ownerBounds.top :
- (newZoomRingY + mZoomRingHeight > ownerBounds.bottom) ?
- ownerBounds.bottom - mZoomRingHeight : newZoomRingY;
- lp.y = newZoomRingY - zoomRingTop;
-
- mWindowManager.updateViewLayout(mContainer, lp);
-
- // Check for pan
- boolean horizontalPanning = true;
- int leftGap = newZoomRingX - ownerBounds.left;
- if (leftGap < MAX_PAN_GAP) {
- if (shouldPan(leftGap)) {
- mPanner.setHorizontalStrength(-getStrengthFromGap(leftGap));
- }
- } else {
- int rightGap = ownerBounds.right - (lp.x + mZoomRingWidth + zoomRingLeft);
- if (rightGap < MAX_PAN_GAP) {
- if (shouldPan(rightGap)) {
- mPanner.setHorizontalStrength(getStrengthFromGap(rightGap));
- }
- } else {
- mPanner.setHorizontalStrength(0);
- horizontalPanning = false;
- }
- }
-
- int topGap = newZoomRingY - ownerBounds.top;
- if (topGap < MAX_PAN_GAP) {
- if (shouldPan(topGap)) {
- mPanner.setVerticalStrength(-getStrengthFromGap(topGap));
- }
- } else {
- int bottomGap = ownerBounds.bottom - (lp.y + mZoomRingHeight + zoomRingTop);
- if (bottomGap < MAX_PAN_GAP) {
- if (shouldPan(bottomGap)) {
- mPanner.setVerticalStrength(getStrengthFromGap(bottomGap));
- }
- } else {
- mPanner.setVerticalStrength(0);
- if (!horizontalPanning) {
- // Neither are panning, reset any timer to start pan mode
- mTouchingEdgeStartTime = 0;
- mPanningEnabledForThisInteraction = false;
- mPanner.stop();
- }
- }
- }
-
- return true;
- }
-
- private boolean shouldPan(int gap) {
- if (mPanningEnabledForThisInteraction) return true;
-
- if (gap < MAX_INITIATE_PAN_GAP) {
- long time = SystemClock.elapsedRealtime();
- if (mTouchingEdgeStartTime != 0 &&
- mTouchingEdgeStartTime + INITIATE_PAN_DELAY < time) {
- mPanningEnabledForThisInteraction = true;
- return true;
- } else if (mTouchingEdgeStartTime == 0) {
- mTouchingEdgeStartTime = time;
- } else {
- }
- } else {
- // Moved away from the initiate pan gap, so reset the timer
- mTouchingEdgeStartTime = 0;
- }
- return false;
- }
-
- public void onZoomRingMovingStopped() {
- mPanner.stop();
- setPanningArrowsVisible(false);
- if (mCallback != null) {
- mCallback.onEndPan();
- }
- }
-
- private int getStrengthFromGap(int gap) {
- return gap > MAX_PAN_GAP ? 0 :
- (MAX_PAN_GAP - gap) * 100 / MAX_PAN_GAP;
- }
-
- public void onZoomRingThumbDraggingStarted() {
- if (mCallback != null) {
- mCallback.onBeginDrag();
- }
- }
-
- public boolean onZoomRingThumbDragged(int numLevels, int startAngle, int curAngle) {
- if (mCallback != null) {
- int deltaZoomLevel = -numLevels;
- int globalZoomCenterX = mContainerLayoutParams.x + mZoomRing.getLeft() +
- mZoomRingWidth / 2;
- int globalZoomCenterY = mContainerLayoutParams.y + mZoomRing.getTop() +
- mZoomRingHeight / 2;
-
- return mCallback.onDragZoom(deltaZoomLevel,
- globalZoomCenterX - mOwnerViewBounds.left,
- globalZoomCenterY - mOwnerViewBounds.top,
- (float) startAngle / ZoomRing.RADIAN_INT_MULTIPLIER,
- (float) curAngle / ZoomRing.RADIAN_INT_MULTIPLIER);
- }
-
- return false;
- }
-
- public void onZoomRingThumbDraggingStopped() {
- if (mCallback != null) {
- mCallback.onEndDrag();
- }
- }
-
- public void onZoomRingDismissed(boolean dismissImmediately) {
- if (dismissImmediately) {
- mHandler.removeMessages(MSG_DISMISS_ZOOM_RING);
- setVisible(false);
- } else {
- dismissZoomRingDelayed(ZOOM_RING_DISMISS_DELAY);
- }
- }
-
- public void onRingDown(int tickAngle, int touchAngle) {
- }
-
- public boolean onTouch(View v, MotionEvent event) {
- if (sTutorialDialog != null && sTutorialDialog.isShowing() &&
- SystemClock.elapsedRealtime() - sTutorialShowTime >= TUTORIAL_MIN_DISPLAY_TIME) {
- finishZoomTutorial();
- }
-
- int action = event.getAction();
-
- if (mReleaseTouchListenerOnUp) {
- // The ring was dismissed but we need to throw away all events until the up
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
- mOwnerView.setOnTouchListener(null);
- setTouchTargetView(null);
- mReleaseTouchListenerOnUp = false;
- }
-
- // Eat this event
- return true;
- }
-
- View targetView = mTouchTargetView;
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- targetView = getViewForTouch((int) event.getRawX(), (int) event.getRawY());
- setTouchTargetView(targetView);
- break;
-
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- setTouchTargetView(null);
- break;
- }
-
- if (targetView != null) {
- // The upperleft corner of the target view in raw coordinates
- int targetViewRawX = mContainerLayoutParams.x + mTouchTargetLocationInWindow[0];
- int targetViewRawY = mContainerLayoutParams.y + mTouchTargetLocationInWindow[1];
-
- MotionEvent containerEvent = MotionEvent.obtain(event);
- // Convert the motion event into the target view's coordinates (from
- // owner view's coordinates)
- containerEvent.offsetLocation(mOwnerViewBounds.left - targetViewRawX,
- mOwnerViewBounds.top - targetViewRawY);
- boolean retValue = targetView.dispatchTouchEvent(containerEvent);
- containerEvent.recycle();
- return retValue;
-
- } else {
- if (action == MotionEvent.ACTION_DOWN) {
- dismissZoomRingDelayed(ZOOM_RING_DISMISS_DELAY);
- }
-
- return false;
- }
- }
-
- private void setTouchTargetView(View view) {
- mTouchTargetView = view;
- if (view != null) {
- view.getLocationInWindow(mTouchTargetLocationInWindow);
- }
- }
-
- /**
- * Returns the View that should receive a touch at the given coordinates.
- *
- * @param rawX The raw X.
- * @param rawY The raw Y.
- * @return The view that should receive the touches, or null if there is not one.
- */
- private View getViewForTouch(int rawX, int rawY) {
- // Check to see if it is touching the ring
- int containerCenterX = mContainerLayoutParams.x + mContainer.getWidth() / 2;
- int containerCenterY = mContainerLayoutParams.y + mContainer.getHeight() / 2;
- int distanceFromCenterX = rawX - containerCenterX;
- int distanceFromCenterY = rawY - containerCenterY;
- int zoomRingRadius = mZoomRingWidth / 2 - ZOOM_RING_RADIUS_INSET;
- if (distanceFromCenterX * distanceFromCenterX +
- distanceFromCenterY * distanceFromCenterY <=
- zoomRingRadius * zoomRingRadius) {
- return mZoomRing;
- }
-
- // Check to see if it is touching any other clickable View.
- // Reverse order so the child drawn on top gets first dibs.
- int containerCoordsX = rawX - mContainerLayoutParams.x;
- int containerCoordsY = rawY - mContainerLayoutParams.y;
- Rect frame = mTempRect;
- for (int i = mContainer.getChildCount() - 1; i >= 0; i--) {
- View child = mContainer.getChildAt(i);
- if (child == mZoomRing || child.getVisibility() != View.VISIBLE ||
- !child.isClickable()) {
- continue;
- }
-
- child.getHitRect(frame);
- if (frame.contains(containerCoordsX, containerCoordsY)) {
- return child;
- }
- }
-
- return null;
- }
-
- /** Steals key events from the owner view. */
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- // Eat these
- return true;
-
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- // Keep the zoom alive a little longer
- dismissZoomRingDelayed(ZOOM_CONTROLS_TIMEOUT);
- // They started zooming, hide the thumb arrows
- mZoomRing.setThumbArrowsVisible(false);
-
- if (mCallback != null && event.getAction() == KeyEvent.ACTION_DOWN) {
- mCallback.onSimpleZoom(keyCode == KeyEvent.KEYCODE_DPAD_UP);
- }
-
- return true;
- }
-
- return false;
- }
-
- private void onScrollerTick() {
- if (!mScroller.computeScrollOffset() || !mIsZoomRingVisible) return;
-
- mContainerLayoutParams.x = mScroller.getCurrX();
- mContainerLayoutParams.y = mScroller.getCurrY();
- mWindowManager.updateViewLayout(mContainer, mContainerLayoutParams);
-
- mHandler.sendEmptyMessage(MSG_SCROLLER_TICK);
- }
-
- private void onPostConfigurationChanged() {
- dismissZoomRingDelayed(ZOOM_CONTROLS_TIMEOUT);
- refreshPositioningVariables();
- ensureZoomRingIsCentered();
- }
-
- /*
- * This is static so Activities can call this instead of the Views
- * (Activities usually do not have a reference to the ZoomRingController
- * instance.)
- */
- /**
- * Shows a "tutorial" (some text) to the user teaching her the new zoom
- * invocation method. Must call from the main thread.
- * <p>
- * It checks the global system setting to ensure this has not been seen
- * before. Furthermore, if the application does not have privilege to write
- * to the system settings, it will store this bit locally in a shared
- * preference.
- *
- * @hide This should only be used by our main apps--browser, maps, and
- * gallery
- */
- public static void showZoomTutorialOnce(Context context) {
- ContentResolver cr = context.getContentResolver();
- if (Settings.System.getInt(cr, SETTING_NAME_SHOWN_TOAST, 0) == 1) {
- return;
- }
-
- SharedPreferences sp = context.getSharedPreferences("_zoom", Context.MODE_PRIVATE);
- if (sp.getInt(SETTING_NAME_SHOWN_TOAST, 0) == 1) {
- return;
- }
-
- if (sTutorialDialog != null && sTutorialDialog.isShowing()) {
- sTutorialDialog.dismiss();
- }
-
- sTutorialDialog = new AlertDialog.Builder(context)
- .setMessage(
- com.android.internal.R.string.tutorial_double_tap_to_zoom_message_short)
- .setIcon(0)
- .create();
-
- Window window = sTutorialDialog.getWindow();
- window.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
- window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND |
- WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
- window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
- WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
-
- sTutorialDialog.show();
- sTutorialShowTime = SystemClock.elapsedRealtime();
- }
-
- public void finishZoomTutorial() {
- if (sTutorialDialog == null) return;
-
- sTutorialDialog.dismiss();
- sTutorialDialog = null;
-
- // Record that they have seen the tutorial
- try {
- Settings.System.putInt(mContext.getContentResolver(), SETTING_NAME_SHOWN_TOAST, 1);
- } catch (SecurityException e) {
- /*
- * The app does not have permission to clear this global flag, make
- * sure the user does not see the message when he comes back to this
- * same app at least.
- */
- SharedPreferences sp = mContext.getSharedPreferences("_zoom", Context.MODE_PRIVATE);
- sp.edit().putInt(SETTING_NAME_SHOWN_TOAST, 1).commit();
- }
- }
-
- public void setPannerStartVelocity(float startVelocity) {
- mPanner.mStartVelocity = startVelocity;
- }
-
- public void setPannerAcceleration(float acceleration) {
- mPanner.mAcceleration = acceleration;
- }
-
- public void setPannerMaxVelocity(float maxVelocity) {
- mPanner.mMaxVelocity = maxVelocity;
- }
-
- public void setPannerStartAcceleratingDuration(int duration) {
- mPanner.mStartAcceleratingDuration = duration;
- }
-
- private class Panner implements Runnable {
- private static final int RUN_DELAY = 15;
- private static final float STOP_SLOWDOWN = 0.8f;
-
- private final Handler mUiHandler = new Handler();
-
- private int mVerticalStrength;
- private int mHorizontalStrength;
-
- private boolean mStopping;
-
- /** The time this current pan started. */
- private long mStartTime;
-
- /** The time of the last callback to pan the map/browser/etc. */
- private long mPreviousCallbackTime;
-
- // TODO Adjust to be DPI safe
- private float mStartVelocity = 135;
- private float mAcceleration = 160;
- private float mMaxVelocity = 1000;
- private int mStartAcceleratingDuration = 700;
- private float mVelocity;
-
- /** -100 (full left) to 0 (none) to 100 (full right) */
- public void setHorizontalStrength(int horizontalStrength) {
- if (mHorizontalStrength == 0 && mVerticalStrength == 0 && horizontalStrength != 0) {
- start();
- } else if (mVerticalStrength == 0 && horizontalStrength == 0) {
- stop();
- }
-
- mHorizontalStrength = horizontalStrength;
- mStopping = false;
- }
-
- /** -100 (full up) to 0 (none) to 100 (full down) */
- public void setVerticalStrength(int verticalStrength) {
- if (mHorizontalStrength == 0 && mVerticalStrength == 0 && verticalStrength != 0) {
- start();
- } else if (mHorizontalStrength == 0 && verticalStrength == 0) {
- stop();
- }
-
- mVerticalStrength = verticalStrength;
- mStopping = false;
- }
-
- private void start() {
- mUiHandler.post(this);
- mPreviousCallbackTime = 0;
- mStartTime = 0;
- }
-
- public void stop() {
- mStopping = true;
- }
-
- public void run() {
- if (mStopping) {
- mHorizontalStrength *= STOP_SLOWDOWN;
- mVerticalStrength *= STOP_SLOWDOWN;
- }
-
- if (mHorizontalStrength == 0 && mVerticalStrength == 0) {
- return;
- }
-
- boolean firstRun = mPreviousCallbackTime == 0;
- long curTime = SystemClock.elapsedRealtime();
- int panAmount = getPanAmount(mPreviousCallbackTime, curTime);
- mPreviousCallbackTime = curTime;
-
- if (firstRun) {
- mStartTime = curTime;
- mVelocity = mStartVelocity;
- } else {
- int panX = panAmount * mHorizontalStrength / 100;
- int panY = panAmount * mVerticalStrength / 100;
-
- if (mCallback != null) {
- mCallback.onPan(panX, panY);
- }
- }
-
- mUiHandler.postDelayed(this, RUN_DELAY);
- }
-
- private int getPanAmount(long previousTime, long currentTime) {
- if (mVelocity > mMaxVelocity) {
- mVelocity = mMaxVelocity;
- } else if (mVelocity < mMaxVelocity) {
- // See if it's time to add in some acceleration
- if (currentTime - mStartTime > mStartAcceleratingDuration) {
- mVelocity += (currentTime - previousTime) * mAcceleration / 1000;
- }
- }
-
- return (int) ((currentTime - previousTime) * mVelocity) / 1000;
- }
-
- }
-
-
-
- public interface OnZoomListener {
- void onBeginDrag();
- boolean onDragZoom(int deltaZoomLevel, int centerX, int centerY, float startAngle,
- float curAngle);
- void onEndDrag();
- void onSimpleZoom(boolean deltaZoomLevel);
- void onBeginPan();
- boolean onPan(int deltaX, int deltaY);
- void onEndPan();
- void onCenter(int x, int y);
- void onVisibilityChanged(boolean visible);
- }
-}
diff --git a/core/java/android/widget/package.html b/core/java/android/widget/package.html
deleted file mode 100644
index 7d94a4b..0000000
--- a/core/java/android/widget/package.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<HTML>
-<BODY>
-The widget package contains (mostly visual) UI elements to use
-on your Application screen. You can design your own <p>
-To create your own widget, extend {@link android.view.View} or a subclass. To
-use your widget in layout XML, there are two additional files for you to
-create. Here is a list of files you'll need to create to implement a custom
-widget:
-<ul>
-<li><b>Java implementation file</b> - This is the file that implements the
-behavior of the widget. If you can instantiate the object from layout XML,
-you will also have to code a constructor that retrieves all the attribute
-values from the layout XML file.</li>
-<li><b>XML definition file</b> - An XML file in res/values/ that defines
-the XML element used to instantiate your widget, and the attributes that it
-supports. Other applications will use this element and attributes in their in
-another in their layout XML.</li>
-<li><b>Layout XML</b> [<em>optional</em>]- An optional XML file inside
-res/layout/ that describes the layout of your widget. You could also do
-this in code in your Java file.</li>
-</ul>
-ApiDemos sample application has an example of creating a custom layout XML
-tag, LabelView. See the following files that demonstrate implementing and using
-a custom widget:</p>
-<ul>
- <li><strong>LabelView.java</strong> - The implentation file</li>
- <li><strong>res/values/attrs.xml</strong> - Definition file</li>
- <li><strong>res/layout/custom_view_1.xml</strong> - Layout
-file</li>
-</ul>
-</BODY>
-</HTML>
diff --git a/core/java/com/android/internal/app/AlertActivity.java b/core/java/com/android/internal/app/AlertActivity.java
deleted file mode 100644
index 7251256..0000000
--- a/core/java/com/android/internal/app/AlertActivity.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import android.app.Activity;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.view.KeyEvent;
-
-/**
- * An activity that follows the visual style of an AlertDialog.
- *
- * @see #mAlert
- * @see #mAlertParams
- * @see #setupAlert()
- */
-public abstract class AlertActivity extends Activity implements DialogInterface {
-
- /**
- * The model for the alert.
- *
- * @see #mAlertParams
- */
- protected AlertController mAlert;
-
- /**
- * The parameters for the alert.
- */
- protected AlertController.AlertParams mAlertParams;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mAlert = new AlertController(this, this, getWindow());
- mAlertParams = new AlertController.AlertParams(this);
- }
-
- public void cancel() {
- finish();
- }
-
- public void dismiss() {
- // This is called after the click, since we finish when handling the
- // click, don't do that again here.
- if (!isFinishing()) {
- finish();
- }
- }
-
- /**
- * Sets up the alert, including applying the parameters to the alert model,
- * and installing the alert's content.
- *
- * @see #mAlert
- * @see #mAlertParams
- */
- protected void setupAlert() {
- mAlertParams.apply(mAlert);
- mAlert.installContent();
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (mAlert.onKeyDown(keyCode, event)) return true;
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (mAlert.onKeyUp(keyCode, event)) return true;
- return super.onKeyUp(keyCode, event);
- }
-
-
-}
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
deleted file mode 100644
index 5c44b2d..0000000
--- a/core/java/com/android/internal/app/AlertController.java
+++ /dev/null
@@ -1,888 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import static android.view.ViewGroup.LayoutParams.FILL_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.res.TypedArray;
-import android.database.Cursor;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.Message;
-import android.text.TextUtils;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.CheckedTextView;
-import android.widget.CursorAdapter;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-import android.widget.ScrollView;
-import android.widget.SimpleCursorAdapter;
-import android.widget.TextView;
-import android.widget.AdapterView.OnItemClickListener;
-
-import com.android.internal.R;
-
-import java.lang.ref.WeakReference;
-
-public class AlertController {
-
- private final Context mContext;
- private final DialogInterface mDialogInterface;
- private final Window mWindow;
-
- private CharSequence mTitle;
-
- private CharSequence mMessage;
-
- private ListView mListView;
-
- private View mView;
-
- private int mViewSpacingLeft;
-
- private int mViewSpacingTop;
-
- private int mViewSpacingRight;
-
- private int mViewSpacingBottom;
-
- private boolean mViewSpacingSpecified = false;
-
- private Button mButtonPositive;
-
- private CharSequence mButtonPositiveText;
-
- private Message mButtonPositiveMessage;
-
- private Button mButtonNegative;
-
- private CharSequence mButtonNegativeText;
-
- private Message mButtonNegativeMessage;
-
- private Button mButtonNeutral;
-
- private CharSequence mButtonNeutralText;
-
- private Message mButtonNeutralMessage;
-
- private ScrollView mScrollView;
-
- private int mIconId = -1;
-
- private Drawable mIcon;
-
- private ImageView mIconView;
-
- private TextView mTitleView;
-
- private TextView mMessageView;
-
- private View mCustomTitleView;
-
- private boolean mForceInverseBackground;
-
- private ListAdapter mAdapter;
-
- private int mCheckedItem = -1;
-
- private Handler mHandler;
-
- View.OnClickListener mButtonHandler = new View.OnClickListener() {
- public void onClick(View v) {
- Message m = null;
- if (v == mButtonPositive && mButtonPositiveMessage != null) {
- m = Message.obtain(mButtonPositiveMessage);
- } else if (v == mButtonNegative && mButtonNegativeMessage != null) {
- m = Message.obtain(mButtonNegativeMessage);
- } else if (v == mButtonNeutral && mButtonNeutralMessage != null) {
- m = Message.obtain(mButtonNeutralMessage);
- }
- if (m != null) {
- m.sendToTarget();
- }
-
- // Post a message so we dismiss after the above handlers are executed
- mHandler.obtainMessage(ButtonHandler.MSG_DISMISS_DIALOG, mDialogInterface)
- .sendToTarget();
- }
- };
-
- private static final class ButtonHandler extends Handler {
- // Button clicks have Message.what as the BUTTON{1,2,3} constant
- private static final int MSG_DISMISS_DIALOG = 1;
-
- private WeakReference<DialogInterface> mDialog;
-
- public ButtonHandler(DialogInterface dialog) {
- mDialog = new WeakReference<DialogInterface>(dialog);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
-
- case DialogInterface.BUTTON_POSITIVE:
- case DialogInterface.BUTTON_NEGATIVE:
- case DialogInterface.BUTTON_NEUTRAL:
- ((DialogInterface.OnClickListener) msg.obj).onClick(mDialog.get(), msg.what);
- break;
-
- case MSG_DISMISS_DIALOG:
- ((DialogInterface) msg.obj).dismiss();
- }
- }
- }
-
- public AlertController(Context context, DialogInterface di, Window window) {
- mContext = context;
- mDialogInterface = di;
- mWindow = window;
- mHandler = new ButtonHandler(di);
- }
-
- static boolean canTextInput(View v) {
- if (v.onCheckIsTextEditor()) {
- return true;
- }
-
- if (!(v instanceof ViewGroup)) {
- return false;
- }
-
- ViewGroup vg = (ViewGroup)v;
- int i = vg.getChildCount();
- while (i > 0) {
- i--;
- v = vg.getChildAt(i);
- if (canTextInput(v)) {
- return true;
- }
- }
-
- return false;
- }
-
- public void installContent() {
- /* We use a custom title so never request a window title */
- mWindow.requestFeature(Window.FEATURE_NO_TITLE);
-
- if (mView == null || !canTextInput(mView)) {
- mWindow.setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
- WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
- }
- mWindow.setContentView(com.android.internal.R.layout.alert_dialog);
- setupView();
- }
-
- public void setTitle(CharSequence title) {
- mTitle = title;
- if (mTitleView != null) {
- mTitleView.setText(title);
- }
- }
-
- /**
- * @see AlertDialog.Builder#setCustomTitle(View)
- */
- public void setCustomTitle(View customTitleView) {
- mCustomTitleView = customTitleView;
- }
-
- public void setMessage(CharSequence message) {
- mMessage = message;
- if (mMessageView != null) {
- mMessageView.setText(message);
- }
- }
-
- /**
- * Set the view to display in the dialog.
- */
- public void setView(View view) {
- mView = view;
- mViewSpacingSpecified = false;
- }
-
- /**
- * Set the view to display in the dialog along with the spacing around that view
- */
- public void setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight,
- int viewSpacingBottom) {
- mView = view;
- mViewSpacingSpecified = true;
- mViewSpacingLeft = viewSpacingLeft;
- mViewSpacingTop = viewSpacingTop;
- mViewSpacingRight = viewSpacingRight;
- mViewSpacingBottom = viewSpacingBottom;
- }
-
- /**
- * Sets a click listener or a message to be sent when the button is clicked.
- * You only need to pass one of {@code listener} or {@code msg}.
- *
- * @param whichButton Which button, can be one of
- * {@link DialogInterface#BUTTON_POSITIVE},
- * {@link DialogInterface#BUTTON_NEGATIVE}, or
- * {@link DialogInterface#BUTTON_NEUTRAL}
- * @param text The text to display in positive button.
- * @param listener The {@link DialogInterface.OnClickListener} to use.
- * @param msg The {@link Message} to be sent when clicked.
- */
- public void setButton(int whichButton, CharSequence text,
- DialogInterface.OnClickListener listener, Message msg) {
-
- if (msg == null && listener != null) {
- msg = mHandler.obtainMessage(whichButton, listener);
- }
-
- switch (whichButton) {
-
- case DialogInterface.BUTTON_POSITIVE:
- mButtonPositiveText = text;
- mButtonPositiveMessage = msg;
- break;
-
- case DialogInterface.BUTTON_NEGATIVE:
- mButtonNegativeText = text;
- mButtonNegativeMessage = msg;
- break;
-
- case DialogInterface.BUTTON_NEUTRAL:
- mButtonNeutralText = text;
- mButtonNeutralMessage = msg;
- break;
-
- default:
- throw new IllegalArgumentException("Button does not exist");
- }
- }
-
- /**
- * Set resId to 0 if you don't want an icon.
- * @param resId the resourceId of the drawable to use as the icon or 0
- * if you don't want an icon.
- */
- public void setIcon(int resId) {
- mIconId = resId;
- if (mIconView != null) {
- if (resId > 0) {
- mIconView.setImageResource(mIconId);
- } else if (resId == 0) {
- mIconView.setVisibility(View.GONE);
- }
- }
- }
-
- public void setIcon(Drawable icon) {
- mIcon = icon;
- if ((mIconView != null) && (mIcon != null)) {
- mIconView.setImageDrawable(icon);
- }
- }
-
- public void setInverseBackgroundForced(boolean forceInverseBackground) {
- mForceInverseBackground = forceInverseBackground;
- }
-
- public ListView getListView() {
- return mListView;
- }
-
- public Button getButton(int whichButton) {
- switch (whichButton) {
- case DialogInterface.BUTTON_POSITIVE:
- return mButtonPositiveMessage != null ? mButtonPositive : null;
- case DialogInterface.BUTTON_NEGATIVE:
- return mButtonNegativeMessage != null ? mButtonNegative : null;
- case DialogInterface.BUTTON_NEUTRAL:
- return mButtonNeutralMessage != null ? mButtonNeutral : null;
- default:
- return null;
- }
- }
-
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (mScrollView != null && mScrollView.executeKeyEvent(event)) return true;
- return false;
- }
-
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (mScrollView != null && mScrollView.executeKeyEvent(event)) return true;
- return false;
- }
-
- private void setupView() {
- LinearLayout contentPanel = (LinearLayout) mWindow.findViewById(R.id.contentPanel);
- setupContent(contentPanel);
- boolean hasButtons = setupButtons();
-
- LinearLayout topPanel = (LinearLayout) mWindow.findViewById(R.id.topPanel);
- TypedArray a = mContext.obtainStyledAttributes(
- null, com.android.internal.R.styleable.AlertDialog, com.android.internal.R.attr.alertDialogStyle, 0);
- boolean hasTitle = setupTitle(topPanel);
-
- View buttonPanel = mWindow.findViewById(R.id.buttonPanel);
- if (!hasButtons) {
- buttonPanel.setVisibility(View.GONE);
- }
-
- FrameLayout customPanel = null;
- if (mView != null) {
- customPanel = (FrameLayout) mWindow.findViewById(R.id.customPanel);
- FrameLayout custom = (FrameLayout) mWindow.findViewById(R.id.custom);
- custom.addView(mView, new LayoutParams(FILL_PARENT, WRAP_CONTENT));
- if (mViewSpacingSpecified) {
- custom.setPadding(mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight,
- mViewSpacingBottom);
- }
- } else {
- mWindow.findViewById(R.id.customPanel).setVisibility(View.GONE);
- }
-
- /* Only display the divider if we have a title and a
- * custom view or a message.
- */
- if (hasTitle && ((mMessage != null) || (mView != null))) {
- View divider = mWindow.findViewById(R.id.titleDivider);
- divider.setVisibility(View.VISIBLE);
- }
-
- setBackground(topPanel, contentPanel, customPanel, hasButtons, a, hasTitle, buttonPanel);
- a.recycle();
- }
-
- private boolean setupTitle(LinearLayout topPanel) {
- boolean hasTitle = true;
-
- if (mCustomTitleView != null) {
- // Add the custom title view directly to the topPanel layout
- LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
- LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
-
- topPanel.addView(mCustomTitleView, lp);
-
- // Hide the title template
- View titleTemplate = mWindow.findViewById(R.id.title_template);
- titleTemplate.setVisibility(View.GONE);
- } else {
- final boolean hasTextTitle = !TextUtils.isEmpty(mTitle);
-
- mIconView = (ImageView) mWindow.findViewById(R.id.icon);
- if (hasTextTitle) {
-
- /* Display the title if a title is supplied, else hide it */
- mTitleView = (TextView) mWindow.findViewById(R.id.alertTitle);
-
- mTitleView.setText(mTitle);
- mIconView.setImageResource(R.drawable.ic_dialog_menu_generic);
-
- /* Do this last so that if the user has supplied any
- * icons we use them instead of the default ones. If the
- * user has specified 0 then make it disappear.
- */
- if (mIconId > 0) {
- mIconView.setImageResource(mIconId);
- } else if (mIcon != null) {
- mIconView.setImageDrawable(mIcon);
- } else if (mIconId == 0) {
-
- /* Apply the padding from the icon to ensure the
- * title is aligned correctly.
- */
- mTitleView.setPadding(mIconView.getPaddingLeft(),
- mIconView.getPaddingTop(),
- mIconView.getPaddingRight(),
- mIconView.getPaddingBottom());
- mIconView.setVisibility(View.GONE);
- }
- } else {
-
- // Hide the title template
- View titleTemplate = mWindow.findViewById(R.id.title_template);
- titleTemplate.setVisibility(View.GONE);
- mIconView.setVisibility(View.GONE);
- hasTitle = false;
- }
- }
- return hasTitle;
- }
-
- private void setupContent(LinearLayout contentPanel) {
- mScrollView = (ScrollView) mWindow.findViewById(R.id.scrollView);
- mScrollView.setFocusable(false);
-
- // Special case for users that only want to display a String
- mMessageView = (TextView) mWindow.findViewById(R.id.message);
- if (mMessageView == null) {
- return;
- }
-
- if (mMessage != null) {
- mMessageView.setText(mMessage);
- } else {
- mMessageView.setVisibility(View.GONE);
- mScrollView.removeView(mMessageView);
-
- if (mListView != null) {
- contentPanel.removeView(mWindow.findViewById(R.id.scrollView));
- contentPanel.addView(mListView, new LinearLayout.LayoutParams(FILL_PARENT, WRAP_CONTENT));
- } else {
- contentPanel.setVisibility(View.GONE);
- }
- }
- }
-
- private boolean setupButtons() {
- View defaultButton = null;
- int BIT_BUTTON_POSITIVE = 1;
- int BIT_BUTTON_NEGATIVE = 2;
- int BIT_BUTTON_NEUTRAL = 4;
- int whichButtons = 0;
- mButtonPositive = (Button) mWindow.findViewById(R.id.button1);
- mButtonPositive.setOnClickListener(mButtonHandler);
-
- if (TextUtils.isEmpty(mButtonPositiveText)) {
- mButtonPositive.setVisibility(View.GONE);
- } else {
- mButtonPositive.setText(mButtonPositiveText);
- mButtonPositive.setVisibility(View.VISIBLE);
- defaultButton = mButtonPositive;
- whichButtons = whichButtons | BIT_BUTTON_POSITIVE;
- }
-
- mButtonNegative = (Button) mWindow.findViewById(R.id.button2);
- mButtonNegative.setOnClickListener(mButtonHandler);
-
- if (TextUtils.isEmpty(mButtonNegativeText)) {
- mButtonNegative.setVisibility(View.GONE);
- } else {
- mButtonNegative.setText(mButtonNegativeText);
- mButtonNegative.setVisibility(View.VISIBLE);
-
- if (defaultButton == null) {
- defaultButton = mButtonNegative;
- }
- whichButtons = whichButtons | BIT_BUTTON_NEGATIVE;
- }
-
- mButtonNeutral = (Button) mWindow.findViewById(R.id.button3);
- mButtonNeutral.setOnClickListener(mButtonHandler);
-
- if (TextUtils.isEmpty(mButtonNeutralText)) {
- mButtonNeutral.setVisibility(View.GONE);
- } else {
- mButtonNeutral.setText(mButtonNeutralText);
- mButtonNeutral.setVisibility(View.VISIBLE);
-
- if (defaultButton == null) {
- defaultButton = mButtonNeutral;
- }
- whichButtons = whichButtons | BIT_BUTTON_NEUTRAL;
- }
-
- /*
- * If we only have 1 button it should be centered on the layout and
- * expand to fill 50% of the available space.
- */
- if (whichButtons == BIT_BUTTON_POSITIVE) {
- centerButton(mButtonPositive);
- } else if (whichButtons == BIT_BUTTON_NEGATIVE) {
- centerButton(mButtonNeutral);
- } else if (whichButtons == BIT_BUTTON_NEUTRAL) {
- centerButton(mButtonNeutral);
- }
-
- return whichButtons != 0;
- }
-
- private void centerButton(Button button) {
- LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) button.getLayoutParams();
- params.gravity = Gravity.CENTER_HORIZONTAL;
- params.weight = 0.5f;
- button.setLayoutParams(params);
- View leftSpacer = mWindow.findViewById(R.id.leftSpacer);
- leftSpacer.setVisibility(View.VISIBLE);
- View rightSpacer = mWindow.findViewById(R.id.rightSpacer);
- rightSpacer.setVisibility(View.VISIBLE);
- }
-
- private void setBackground(LinearLayout topPanel, LinearLayout contentPanel,
- View customPanel, boolean hasButtons, TypedArray a, boolean hasTitle,
- View buttonPanel) {
-
- /* Get all the different background required */
- int fullDark = a.getResourceId(
- R.styleable.AlertDialog_fullDark, R.drawable.popup_full_dark);
- int topDark = a.getResourceId(
- R.styleable.AlertDialog_topDark, R.drawable.popup_top_dark);
- int centerDark = a.getResourceId(
- R.styleable.AlertDialog_centerDark, R.drawable.popup_center_dark);
- int bottomDark = a.getResourceId(
- R.styleable.AlertDialog_bottomDark, R.drawable.popup_bottom_dark);
- int fullBright = a.getResourceId(
- R.styleable.AlertDialog_fullBright, R.drawable.popup_full_bright);
- int topBright = a.getResourceId(
- R.styleable.AlertDialog_topBright, R.drawable.popup_top_bright);
- int centerBright = a.getResourceId(
- R.styleable.AlertDialog_centerBright, R.drawable.popup_center_bright);
- int bottomBright = a.getResourceId(
- R.styleable.AlertDialog_bottomBright, R.drawable.popup_bottom_bright);
- int bottomMedium = a.getResourceId(
- R.styleable.AlertDialog_bottomMedium, R.drawable.popup_bottom_medium);
- int centerMedium = a.getResourceId(
- R.styleable.AlertDialog_centerMedium, R.drawable.popup_center_medium);
-
- /*
- * We now set the background of all of the sections of the alert.
- * First collect together each section that is being displayed along
- * with whether it is on a light or dark background, then run through
- * them setting their backgrounds. This is complicated because we need
- * to correctly use the full, top, middle, and bottom graphics depending
- * on how many views they are and where they appear.
- */
-
- View[] views = new View[4];
- boolean[] light = new boolean[4];
- View lastView = null;
- boolean lastLight = false;
-
- int pos = 0;
- if (hasTitle) {
- views[pos] = topPanel;
- light[pos] = false;
- pos++;
- }
-
- /* The contentPanel displays either a custom text message or
- * a ListView. If it's text we should use the dark background
- * for ListView we should use the light background. If neither
- * are there the contentPanel will be hidden so set it as null.
- */
- views[pos] = (contentPanel.getVisibility() == View.GONE)
- ? null : contentPanel;
- light[pos] = mListView == null ? false : true;
- pos++;
- if (customPanel != null) {
- views[pos] = customPanel;
- light[pos] = mForceInverseBackground;
- pos++;
- }
- if (hasButtons) {
- views[pos] = buttonPanel;
- light[pos] = true;
- }
-
- boolean setView = false;
- for (pos=0; pos<views.length; pos++) {
- View v = views[pos];
- if (v == null) {
- continue;
- }
- if (lastView != null) {
- if (!setView) {
- lastView.setBackgroundResource(lastLight ? topBright : topDark);
- } else {
- lastView.setBackgroundResource(lastLight ? centerBright : centerDark);
- }
- setView = true;
- }
- lastView = v;
- lastLight = light[pos];
- }
-
- if (lastView != null) {
- if (setView) {
-
- /* ListViews will use the Bright background but buttons use
- * the Medium background.
- */
- lastView.setBackgroundResource(
- lastLight ? (hasButtons ? bottomMedium : bottomBright) : bottomDark);
- } else {
- lastView.setBackgroundResource(lastLight ? fullBright : fullDark);
- }
- }
-
- /* TODO: uncomment section below. The logic for this should be if
- * it's a Contextual menu being displayed AND only a Cancel button
- * is shown then do this.
- */
-// if (hasButtons && (mListView != null)) {
-
- /* Yet another *special* case. If there is a ListView with buttons
- * don't put the buttons on the bottom but instead put them in the
- * footer of the ListView this will allow more items to be
- * displayed.
- */
-
- /*
- contentPanel.setBackgroundResource(bottomBright);
- buttonPanel.setBackgroundResource(centerMedium);
- ViewGroup parent = (ViewGroup) mWindow.findViewById(R.id.parentPanel);
- parent.removeView(buttonPanel);
- AbsListView.LayoutParams params = new AbsListView.LayoutParams(
- AbsListView.LayoutParams.FILL_PARENT,
- AbsListView.LayoutParams.FILL_PARENT);
- buttonPanel.setLayoutParams(params);
- mListView.addFooterView(buttonPanel);
- */
-// }
-
- if ((mListView != null) && (mAdapter != null)) {
- mListView.setAdapter(mAdapter);
- if (mCheckedItem > -1) {
- mListView.setItemChecked(mCheckedItem, true);
- mListView.setSelection(mCheckedItem);
- }
- }
- }
-
- public static class AlertParams {
- public final Context mContext;
- public final LayoutInflater mInflater;
-
- public int mIconId = -1;
- public Drawable mIcon;
- public CharSequence mTitle;
- public View mCustomTitleView;
- public CharSequence mMessage;
- public CharSequence mPositiveButtonText;
- public DialogInterface.OnClickListener mPositiveButtonListener;
- public CharSequence mNegativeButtonText;
- public DialogInterface.OnClickListener mNegativeButtonListener;
- public CharSequence mNeutralButtonText;
- public DialogInterface.OnClickListener mNeutralButtonListener;
- public boolean mCancelable;
- public DialogInterface.OnCancelListener mOnCancelListener;
- public DialogInterface.OnKeyListener mOnKeyListener;
- public CharSequence[] mItems;
- public ListAdapter mAdapter;
- public DialogInterface.OnClickListener mOnClickListener;
- public View mView;
- public int mViewSpacingLeft;
- public int mViewSpacingTop;
- public int mViewSpacingRight;
- public int mViewSpacingBottom;
- public boolean mViewSpacingSpecified = false;
- public boolean[] mCheckedItems;
- public boolean mIsMultiChoice;
- public boolean mIsSingleChoice;
- public int mCheckedItem = -1;
- public DialogInterface.OnMultiChoiceClickListener mOnCheckboxClickListener;
- public Cursor mCursor;
- public String mLabelColumn;
- public String mIsCheckedColumn;
- public boolean mForceInverseBackground;
- public AdapterView.OnItemSelectedListener mOnItemSelectedListener;
- public OnPrepareListViewListener mOnPrepareListViewListener;
-
- /**
- * Interface definition for a callback to be invoked before the ListView
- * will be bound to an adapter.
- */
- public interface OnPrepareListViewListener {
-
- /**
- * Called before the ListView is bound to an adapter.
- * @param listView The ListView that will be shown in the dialog.
- */
- void onPrepareListView(ListView listView);
- }
-
- public AlertParams(Context context) {
- mContext = context;
- mCancelable = true;
- mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
-
- public void apply(AlertController dialog) {
- if (mCustomTitleView != null) {
- dialog.setCustomTitle(mCustomTitleView);
- } else {
- if (mTitle != null) {
- dialog.setTitle(mTitle);
- }
- if (mIcon != null) {
- dialog.setIcon(mIcon);
- }
- if (mIconId >= 0) {
- dialog.setIcon(mIconId);
- }
- }
- if (mMessage != null) {
- dialog.setMessage(mMessage);
- }
- if (mPositiveButtonText != null) {
- dialog.setButton(DialogInterface.BUTTON_POSITIVE, mPositiveButtonText,
- mPositiveButtonListener, null);
- }
- if (mNegativeButtonText != null) {
- dialog.setButton(DialogInterface.BUTTON_NEGATIVE, mNegativeButtonText,
- mNegativeButtonListener, null);
- }
- if (mNeutralButtonText != null) {
- dialog.setButton(DialogInterface.BUTTON_NEUTRAL, mNeutralButtonText,
- mNeutralButtonListener, null);
- }
- if (mForceInverseBackground) {
- dialog.setInverseBackgroundForced(true);
- }
- // For a list, the client can either supply an array of items or an
- // adapter or a cursor
- if ((mItems != null) || (mCursor != null) || (mAdapter != null)) {
- createListView(dialog);
- }
- if (mView != null) {
- if (mViewSpacingSpecified) {
- dialog.setView(mView, mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight,
- mViewSpacingBottom);
- } else {
- dialog.setView(mView);
- }
- }
-
- /*
- dialog.setCancelable(mCancelable);
- dialog.setOnCancelListener(mOnCancelListener);
- if (mOnKeyListener != null) {
- dialog.setOnKeyListener(mOnKeyListener);
- }
- */
- }
-
- private void createListView(final AlertController dialog) {
- final ListView listView = (ListView) mInflater.inflate(R.layout.select_dialog, null);
- ListAdapter adapter;
-
- if (mIsMultiChoice) {
- if (mCursor == null) {
- adapter = new ArrayAdapter<CharSequence>(
- mContext, R.layout.select_dialog_multichoice, R.id.text1, mItems) {
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- View view = super.getView(position, convertView, parent);
- if (mCheckedItems != null) {
- boolean isItemChecked = mCheckedItems[position];
- if (isItemChecked) {
- listView.setItemChecked(position, true);
- }
- }
- return view;
- }
- };
- } else {
- adapter = new CursorAdapter(mContext, mCursor, false) {
- private final int mLabelIndex;
- private final int mIsCheckedIndex;
-
- {
- final Cursor cursor = getCursor();
- mLabelIndex = cursor.getColumnIndexOrThrow(mLabelColumn);
- mIsCheckedIndex = cursor.getColumnIndexOrThrow(mIsCheckedColumn);
- }
-
- @Override
- public void bindView(View view, Context context, Cursor cursor) {
- CheckedTextView text = (CheckedTextView) view.findViewById(R.id.text1);
- text.setText(cursor.getString(mLabelIndex));
- listView.setItemChecked(cursor.getPosition(),
- cursor.getInt(mIsCheckedIndex) == 1);
- }
-
- @Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- return mInflater.inflate(R.layout.select_dialog_multichoice,
- parent, false);
- }
-
- };
- }
- } else {
- int layout = mIsSingleChoice
- ? R.layout.select_dialog_singlechoice : R.layout.select_dialog_item;
- if (mCursor == null) {
- adapter = (mAdapter != null) ? mAdapter
- : new ArrayAdapter<CharSequence>(mContext, layout, R.id.text1, mItems);
- } else {
- adapter = new SimpleCursorAdapter(mContext, layout,
- mCursor, new String[]{mLabelColumn}, new int[]{R.id.text1});
- }
- }
-
- if (mOnPrepareListViewListener != null) {
- mOnPrepareListViewListener.onPrepareListView(listView);
- }
-
- /* Don't directly set the adapter on the ListView as we might
- * want to add a footer to the ListView later.
- */
- dialog.mAdapter = adapter;
- dialog.mCheckedItem = mCheckedItem;
-
- if (mOnClickListener != null) {
- listView.setOnItemClickListener(new OnItemClickListener() {
- public void onItemClick(AdapterView parent, View v, int position, long id) {
- mOnClickListener.onClick(dialog.mDialogInterface, position);
- if (!mIsSingleChoice) {
- dialog.mDialogInterface.dismiss();
- }
- }
- });
- } else if (mOnCheckboxClickListener != null) {
- listView.setOnItemClickListener(new OnItemClickListener() {
- public void onItemClick(AdapterView parent, View v, int position, long id) {
- if (mCheckedItems != null) {
- mCheckedItems[position] = listView.isItemChecked(position);
- }
- mOnCheckboxClickListener.onClick(
- dialog.mDialogInterface, position, listView.isItemChecked(position));
- }
- });
- }
-
- // Attach a given OnItemSelectedListener to the ListView
- if (mOnItemSelectedListener != null) {
- listView.setOnItemSelectedListener(mOnItemSelectedListener);
- }
-
- if (mIsSingleChoice) {
- listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
- } else if (mIsMultiChoice) {
- listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
- }
- dialog.mListView = listView;
- }
- }
-
-}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
deleted file mode 100644
index 1697df2..0000000
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import android.content.Intent;
-import android.os.Bundle;
-
-public class ChooserActivity extends ResolverActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- Intent intent = getIntent();
- Intent target = (Intent)intent.getParcelableExtra(Intent.EXTRA_INTENT);
- CharSequence title = intent.getCharSequenceExtra(Intent.EXTRA_TITLE);
- if (title == null) {
- title = getResources().getText(com.android.internal.R.string.chooseActivity);
- }
- super.onCreate(savedInstanceState, target, title, false);
- }
-}
diff --git a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java
deleted file mode 100644
index 000f6c4..0000000
--- a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2007 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import android.app.AlertDialog;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IMountService;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.Environment;
-import android.widget.Toast;
-import android.util.Log;
-
-/**
- * This activity is shown to the user to confirm formatting of external media.
- * It uses the alert dialog style. It will be launched from a notification, or from settings
- */
-public class ExternalMediaFormatActivity extends AlertActivity implements DialogInterface.OnClickListener {
-
- private static final int POSITIVE_BUTTON = AlertDialog.BUTTON1;
-
- /** Used to detect when the media state changes, in case we need to call finish() */
- private BroadcastReceiver mStorageReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- Log.d("ExternalMediaFormatActivity", "got action " + action);
-
- if (action == Intent.ACTION_MEDIA_REMOVED ||
- action == Intent.ACTION_MEDIA_CHECKING ||
- action == Intent.ACTION_MEDIA_MOUNTED ||
- action == Intent.ACTION_MEDIA_SHARED) {
- finish();
- }
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- Log.d("ExternalMediaFormatActivity", "onCreate!");
- // Set up the "dialog"
- final AlertController.AlertParams p = mAlertParams;
- p.mIconId = com.android.internal.R.drawable.stat_sys_warning;
- p.mTitle = getString(com.android.internal.R.string.extmedia_format_title);
- p.mMessage = getString(com.android.internal.R.string.extmedia_format_message);
- p.mPositiveButtonText = getString(com.android.internal.R.string.extmedia_format_button_format);
- p.mPositiveButtonListener = this;
- p.mNegativeButtonText = getString(com.android.internal.R.string.cancel);
- p.mNegativeButtonListener = this;
- setupAlert();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_MEDIA_REMOVED);
- filter.addAction(Intent.ACTION_MEDIA_CHECKING);
- filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
- filter.addAction(Intent.ACTION_MEDIA_SHARED);
- registerReceiver(mStorageReceiver, filter);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- unregisterReceiver(mStorageReceiver);
- }
-
- /**
- * {@inheritDoc}
- */
- public void onClick(DialogInterface dialog, int which) {
-
- if (which == POSITIVE_BUTTON) {
- IMountService mountService = IMountService.Stub.asInterface(ServiceManager
- .getService("mount"));
- if (mountService != null) {
- try {
- mountService.formatMedia(Environment.getExternalStorageDirectory().toString());
- } catch (RemoteException e) {
- }
- }
- }
-
- // No matter what, finish the activity
- finish();
- }
-}
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
deleted file mode 100644
index b502a6c..0000000
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import com.android.internal.os.BatteryStatsImpl;
-
-interface IBatteryStats {
- byte[] getStatistics();
- void noteStartWakelock(int uid, String name, int type);
- void noteStopWakelock(int uid, String name, int type);
- void noteStartSensor(int uid, int sensor);
- void noteStopSensor(int uid, int sensor);
- void noteStartGps(int uid);
- void noteStopGps(int uid);
- void noteScreenOn();
- void noteScreenOff();
- void setOnBattery(boolean onBattery);
- long getAwakeTimeBattery();
- long getAwakeTimePlugged();
-}
diff --git a/core/java/com/android/internal/app/IUsageStats.aidl b/core/java/com/android/internal/app/IUsageStats.aidl
deleted file mode 100755
index 6b053d5..0000000
--- a/core/java/com/android/internal/app/IUsageStats.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import android.content.ComponentName;
-import com.android.internal.os.PkgUsageStats;
-
-interface IUsageStats {
- void noteResumeComponent(in ComponentName componentName);
- void notePauseComponent(in ComponentName componentName);
- PkgUsageStats getPkgUsageStats(in ComponentName componentName);
- PkgUsageStats[] getAllPkgUsageStats();
-}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
deleted file mode 100644
index e907a04..0000000
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import com.android.internal.R;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.PatternMatcher;
-import android.util.Config;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.LayoutInflater;
-import android.widget.BaseAdapter;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
-import android.widget.ImageView;
-import android.widget.TextView;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-/**
- * This activity is displayed when the system attempts to start an Intent for
- * which there is more than one matching activity, allowing the user to decide
- * which to go to. It is not normally used directly by application developers.
- */
-public class ResolverActivity extends AlertActivity implements
- DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener {
- private ResolveListAdapter mAdapter;
- private CheckBox mAlwaysCheck;
- private TextView mClearDefaultHint;
- private PackageManager mPm;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- onCreate(savedInstanceState, new Intent(getIntent()),
- getResources().getText(com.android.internal.R.string.whichApplication),
- true);
- }
-
- protected void onCreate(Bundle savedInstanceState, Intent intent,
- CharSequence title, boolean alwaysUseOption) {
- super.onCreate(savedInstanceState);
- mPm = getPackageManager();
- intent.setComponent(null);
-
- AlertController.AlertParams ap = mAlertParams;
-
- ap.mTitle = title;
- ap.mOnClickListener = this;
-
- if (alwaysUseOption) {
- LayoutInflater inflater = (LayoutInflater) getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- ap.mView = inflater.inflate(R.layout.always_use_checkbox, null);
- mAlwaysCheck = (CheckBox)ap.mView.findViewById(com.android.internal.R.id.alwaysUse);
- mAlwaysCheck.setText(R.string.alwaysUse);
- mAlwaysCheck.setOnCheckedChangeListener(this);
- mClearDefaultHint = (TextView)ap.mView.findViewById(
- com.android.internal.R.id.clearDefaultHint);
- mClearDefaultHint.setVisibility(View.GONE);
- }
- mAdapter = new ResolveListAdapter(this, intent);
- if (mAdapter.getCount() > 1) {
- ap.mAdapter = mAdapter;
- } else if (mAdapter.getCount() == 1) {
- startActivity(mAdapter.intentForPosition(0));
- finish();
- return;
- } else {
- ap.mMessage = getResources().getText(com.android.internal.R.string.noApplications);
- }
-
- setupAlert();
- }
-
- public void onClick(DialogInterface dialog, int which) {
- ResolveInfo ri = mAdapter.resolveInfoForPosition(which);
- Intent intent = mAdapter.intentForPosition(which);
-
- if ((mAlwaysCheck != null) && mAlwaysCheck.isChecked()) {
- // Build a reasonable intent filter, based on what matched.
- IntentFilter filter = new IntentFilter();
-
- if (intent.getAction() != null) {
- filter.addAction(intent.getAction());
- }
- Set<String> categories = intent.getCategories();
- if (categories != null) {
- for (String cat : categories) {
- filter.addCategory(cat);
- }
- }
- filter.addCategory(Intent.CATEGORY_DEFAULT);
-
- int cat = ri.match&IntentFilter.MATCH_CATEGORY_MASK;
- Uri data = intent.getData();
- if (cat == IntentFilter.MATCH_CATEGORY_TYPE) {
- String mimeType = intent.resolveType(this);
- if (mimeType != null) {
- try {
- filter.addDataType(mimeType);
- } catch (IntentFilter.MalformedMimeTypeException e) {
- Log.w("ResolverActivity", e);
- filter = null;
- }
- }
- } else if (data != null && data.getScheme() != null) {
- filter.addDataScheme(data.getScheme());
-
- // Look through the resolved filter to determine which part
- // of it matched the original Intent.
- Iterator<IntentFilter.AuthorityEntry> aIt = ri.filter.authoritiesIterator();
- if (aIt != null) {
- while (aIt.hasNext()) {
- IntentFilter.AuthorityEntry a = aIt.next();
- if (a.match(data) >= 0) {
- int port = a.getPort();
- filter.addDataAuthority(a.getHost(),
- port >= 0 ? Integer.toString(port) : null);
- break;
- }
- }
- }
- Iterator<PatternMatcher> pIt = ri.filter.pathsIterator();
- if (pIt != null) {
- String path = data.getPath();
- while (path != null && pIt.hasNext()) {
- PatternMatcher p = pIt.next();
- if (p.match(path)) {
- filter.addDataPath(p.getPath(), p.getType());
- break;
- }
- }
- }
- }
-
- if (filter != null) {
- final int N = mAdapter.mList.size();
- ComponentName[] set = new ComponentName[N];
- int bestMatch = 0;
- for (int i=0; i<N; i++) {
- ResolveInfo r = mAdapter.mList.get(i).ri;
- set[i] = new ComponentName(r.activityInfo.packageName,
- r.activityInfo.name);
- if (r.match > bestMatch) bestMatch = r.match;
- }
- getPackageManager().addPreferredActivity(filter, bestMatch, set,
- intent.getComponent());
- }
- }
-
- if (intent != null) {
- startActivity(intent);
- }
- finish();
- }
-
- private final class DisplayResolveInfo {
- ResolveInfo ri;
- CharSequence displayLabel;
- CharSequence extendedInfo;
-
- DisplayResolveInfo(ResolveInfo pri, CharSequence pLabel, CharSequence pInfo) {
- ri = pri;
- displayLabel = pLabel;
- extendedInfo = pInfo;
- }
- }
-
- private final class ResolveListAdapter extends BaseAdapter {
- private final Intent mIntent;
- private final LayoutInflater mInflater;
-
- private List<DisplayResolveInfo> mList;
-
- public ResolveListAdapter(Context context, Intent intent) {
- mIntent = new Intent(intent);
- mIntent.setComponent(null);
- mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- List<ResolveInfo> rList = mPm.queryIntentActivities(
- intent, PackageManager.MATCH_DEFAULT_ONLY
- | (mAlwaysCheck != null ? PackageManager.GET_RESOLVED_FILTER : 0));
- int N;
- if ((rList != null) && ((N = rList.size()) > 0)) {
- // Only display the first matches that are either of equal
- // priority or have asked to be default options.
- ResolveInfo r0 = rList.get(0);
- for (int i=1; i<N; i++) {
- ResolveInfo ri = rList.get(i);
- if (Config.LOGV) Log.v(
- "ResolveListActivity",
- r0.activityInfo.name + "=" +
- r0.priority + "/" + r0.isDefault + " vs " +
- ri.activityInfo.name + "=" +
- ri.priority + "/" + ri.isDefault);
- if (r0.priority != ri.priority ||
- r0.isDefault != ri.isDefault) {
- while (i < N) {
- rList.remove(i);
- N--;
- }
- }
- }
- if (N > 1) {
- ResolveInfo.DisplayNameComparator rComparator =
- new ResolveInfo.DisplayNameComparator(mPm);
- Collections.sort(rList, rComparator);
- }
- // Check for applications with same name and use application name or
- // package name if necessary
- mList = new ArrayList<DisplayResolveInfo>();
- r0 = rList.get(0);
- int start = 0;
- CharSequence r0Label = r0.loadLabel(mPm);
- for (int i = 1; i < N; i++) {
- if (r0Label == null) {
- r0Label = r0.activityInfo.packageName;
- }
- ResolveInfo ri = rList.get(i);
- CharSequence riLabel = ri.loadLabel(mPm);
- if (riLabel == null) {
- riLabel = ri.activityInfo.packageName;
- }
- if (riLabel.equals(r0Label)) {
- continue;
- }
- processGroup(rList, start, (i-1), r0, r0Label);
- r0 = ri;
- r0Label = riLabel;
- start = i;
- }
- // Process last group
- processGroup(rList, start, (N-1), r0, r0Label);
- }
- }
-
- private void processGroup(List<ResolveInfo> rList, int start, int end, ResolveInfo ro,
- CharSequence roLabel) {
- // Process labels from start to i
- int num = end - start+1;
- if (num == 1) {
- // No duplicate labels. Use label for entry at start
- mList.add(new DisplayResolveInfo(ro, roLabel, null));
- } else {
- boolean usePkg = false;
- CharSequence startApp = ro.activityInfo.applicationInfo.loadLabel(mPm);
- if (startApp == null) {
- usePkg = true;
- }
- if (!usePkg) {
- // Use HashSet to track duplicates
- HashSet<CharSequence> duplicates =
- new HashSet<CharSequence>();
- duplicates.add(startApp);
- for (int j = start+1; j <= end ; j++) {
- ResolveInfo jRi = rList.get(j);
- CharSequence jApp = jRi.activityInfo.applicationInfo.loadLabel(mPm);
- if ( (jApp == null) || (duplicates.contains(jApp))) {
- usePkg = true;
- break;
- } else {
- duplicates.add(jApp);
- }
- }
- // Clear HashSet for later use
- duplicates.clear();
- }
- for (int k = start; k <= end; k++) {
- ResolveInfo add = rList.get(k);
- if (usePkg) {
- // Use application name for all entries from start to end-1
- mList.add(new DisplayResolveInfo(add, roLabel,
- add.activityInfo.packageName));
- } else {
- // Use package name for all entries from start to end-1
- mList.add(new DisplayResolveInfo(add, roLabel,
- add.activityInfo.applicationInfo.loadLabel(mPm)));
- }
- }
- }
- }
-
- public ResolveInfo resolveInfoForPosition(int position) {
- if (mList == null) {
- return null;
- }
-
- return mList.get(position).ri;
- }
-
- public Intent intentForPosition(int position) {
- if (mList == null) {
- return null;
- }
-
- Intent intent = new Intent(mIntent);
- intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
- |Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
- ActivityInfo ai = mList.get(position).ri.activityInfo;
- intent.setComponent(new ComponentName(
- ai.applicationInfo.packageName, ai.name));
- return intent;
- }
-
- public int getCount() {
- return mList != null ? mList.size() : 0;
- }
-
- public Object getItem(int position) {
- return position;
- }
-
- public long getItemId(int position) {
- return position;
- }
-
- public View getView(int position, View convertView, ViewGroup parent) {
- View view;
- if (convertView == null) {
- view = mInflater.inflate(
- com.android.internal.R.layout.resolve_list_item, parent, false);
- } else {
- view = convertView;
- }
- bindView(view, mList.get(position));
- return view;
- }
-
- private final void bindView(View view, DisplayResolveInfo info) {
- TextView text = (TextView)view.findViewById(com.android.internal.R.id.text1);
- TextView text2 = (TextView)view.findViewById(com.android.internal.R.id.text2);
- ImageView icon = (ImageView)view.findViewById(R.id.icon);
- text.setText(info.displayLabel);
- if (info.extendedInfo != null) {
- text2.setVisibility(View.VISIBLE);
- text2.setText(info.extendedInfo);
- } else {
- text2.setVisibility(View.GONE);
- }
- icon.setImageDrawable(info.ri.loadIcon(mPm));
- }
- }
-
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (mClearDefaultHint == null) return;
-
- if(isChecked) {
- mClearDefaultHint.setVisibility(View.VISIBLE);
- } else {
- mClearDefaultHint.setVisibility(View.GONE);
- }
- }
-}
-
diff --git a/core/java/com/android/internal/app/RingtonePickerActivity.java b/core/java/com/android/internal/app/RingtonePickerActivity.java
deleted file mode 100644
index 1f8e6f0..0000000
--- a/core/java/com/android/internal/app/RingtonePickerActivity.java
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
-
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.database.Cursor;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.provider.MediaStore;
-import android.provider.Settings;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ListView;
-import android.widget.TextView;
-
-/**
- * The {@link RingtonePickerActivity} allows the user to choose one from all of the
- * available ringtones. The chosen ringtone's URI will be persisted as a string.
- *
- * @see RingtoneManager#ACTION_RINGTONE_PICKER
- */
-public final class RingtonePickerActivity extends AlertActivity implements
- AdapterView.OnItemSelectedListener, Runnable, DialogInterface.OnClickListener,
- AlertController.AlertParams.OnPrepareListViewListener {
-
- private static final String TAG = "RingtonePickerActivity";
-
- private static final int DELAY_MS_SELECTION_PLAYED = 300;
-
- private RingtoneManager mRingtoneManager;
-
- private Cursor mCursor;
- private Handler mHandler;
-
- /** The position in the list of the 'Silent' item. */
- private int mSilentPos = -1;
-
- /** The position in the list of the 'Default' item. */
- private int mDefaultRingtonePos = -1;
-
- /** The position in the list of the last clicked item. */
- private int mClickedPos = -1;
-
- /** The position in the list of the ringtone to sample. */
- private int mSampleRingtonePos = -1;
-
- /** Whether this list has the 'Silent' item. */
- private boolean mHasSilentItem;
-
- /** The Uri to place a checkmark next to. */
- private Uri mExistingUri;
-
- /** The number of static items in the list. */
- private int mStaticItemCount;
-
- /** Whether this list has the 'Default' item. */
- private boolean mHasDefaultItem;
-
- /** The Uri to play when the 'Default' item is clicked. */
- private Uri mUriForDefaultItem;
-
- /**
- * A Ringtone for the default ringtone. In most cases, the RingtoneManager
- * will stop the previous ringtone. However, the RingtoneManager doesn't
- * manage the default ringtone for us, so we should stop this one manually.
- */
- private Ringtone mDefaultRingtone;
-
- private DialogInterface.OnClickListener mRingtoneClickListener =
- new DialogInterface.OnClickListener() {
-
- /*
- * On item clicked
- */
- public void onClick(DialogInterface dialog, int which) {
- // Save the position of most recently clicked item
- mClickedPos = which;
-
- // Play clip
- playRingtone(which, 0);
- }
-
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mHandler = new Handler();
-
- Intent intent = getIntent();
-
- /*
- * Get whether to show the 'Default' item, and the URI to play when the
- * default is clicked
- */
- mHasDefaultItem = intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
- mUriForDefaultItem = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI);
- if (mUriForDefaultItem == null) {
- mUriForDefaultItem = Settings.System.DEFAULT_RINGTONE_URI;
- }
-
- // Get whether to show the 'Silent' item
- mHasSilentItem = intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true);
-
- // Give the Activity so it can do managed queries
- mRingtoneManager = new RingtoneManager(this);
-
- // Get whether to include DRM ringtones
- boolean includeDrm = intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_INCLUDE_DRM,
- true);
- mRingtoneManager.setIncludeDrm(includeDrm);
-
- // Get the types of ringtones to show
- int types = intent.getIntExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, -1);
- if (types != -1) {
- mRingtoneManager.setType(types);
- }
-
- mCursor = mRingtoneManager.getCursor();
-
- // The volume keys will control the stream that we are choosing a ringtone for
- setVolumeControlStream(mRingtoneManager.inferStreamType());
-
- // Get the URI whose list item should have a checkmark
- mExistingUri = intent
- .getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI);
-
- final AlertController.AlertParams p = mAlertParams;
- p.mCursor = mCursor;
- p.mOnClickListener = mRingtoneClickListener;
- p.mLabelColumn = MediaStore.Audio.Media.TITLE;
- p.mIsSingleChoice = true;
- p.mOnItemSelectedListener = this;
- p.mPositiveButtonText = getString(com.android.internal.R.string.ok);
- p.mPositiveButtonListener = this;
- p.mNegativeButtonText = getString(com.android.internal.R.string.cancel);
- p.mPositiveButtonListener = this;
- p.mOnPrepareListViewListener = this;
-
- p.mTitle = intent.getCharSequenceExtra(RingtoneManager.EXTRA_RINGTONE_TITLE);
- if (p.mTitle == null) {
- p.mTitle = getString(com.android.internal.R.string.ringtone_picker_title);
- }
-
- setupAlert();
- }
-
- public void onPrepareListView(ListView listView) {
-
- if (mHasDefaultItem) {
- mDefaultRingtonePos = addDefaultRingtoneItem(listView);
-
- if (RingtoneManager.isDefault(mExistingUri)) {
- mClickedPos = mDefaultRingtonePos;
- }
- }
-
- if (mHasSilentItem) {
- mSilentPos = addSilentItem(listView);
-
- // The 'Silent' item should use a null Uri
- if (mExistingUri == null) {
- mClickedPos = mSilentPos;
- }
- }
-
- if (mClickedPos == -1) {
- mClickedPos = getListPosition(mRingtoneManager.getRingtonePosition(mExistingUri));
- }
-
- // Put a checkmark next to an item.
- mAlertParams.mCheckedItem = mClickedPos;
- }
-
- /**
- * Adds a static item to the top of the list. A static item is one that is not from the
- * RingtoneManager.
- *
- * @param listView The ListView to add to.
- * @param textResId The resource ID of the text for the item.
- * @return The position of the inserted item.
- */
- private int addStaticItem(ListView listView, int textResId) {
- TextView textView = (TextView) getLayoutInflater().inflate(
- com.android.internal.R.layout.select_dialog_singlechoice, listView, false);
- textView.setText(textResId);
- listView.addHeaderView(textView);
- mStaticItemCount++;
- return listView.getHeaderViewsCount() - 1;
- }
-
- private int addDefaultRingtoneItem(ListView listView) {
- return addStaticItem(listView, com.android.internal.R.string.ringtone_default);
- }
-
- private int addSilentItem(ListView listView) {
- return addStaticItem(listView, com.android.internal.R.string.ringtone_silent);
- }
-
- /*
- * On click of Ok/Cancel buttons
- */
- public void onClick(DialogInterface dialog, int which) {
- boolean positiveResult = which == BUTTON1;
-
- // Stop playing the previous ringtone
- mRingtoneManager.stopPreviousRingtone();
-
- if (positiveResult) {
- Intent resultIntent = new Intent();
- Uri uri = null;
-
- if (mClickedPos == mDefaultRingtonePos) {
- // Set it to the default Uri that they originally gave us
- uri = mUriForDefaultItem;
- } else if (mClickedPos == mSilentPos) {
- // A null Uri is for the 'Silent' item
- uri = null;
- } else {
- uri = mRingtoneManager.getRingtoneUri(getRingtoneManagerPosition(mClickedPos));
- }
-
- resultIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI, uri);
- setResult(RESULT_OK, resultIntent);
- } else {
- setResult(RESULT_CANCELED);
- }
-
- mCursor.deactivate();
-
- finish();
- }
-
- /*
- * On item selected via keys
- */
- public void onItemSelected(AdapterView parent, View view, int position, long id) {
- playRingtone(position, DELAY_MS_SELECTION_PLAYED);
- }
-
- public void onNothingSelected(AdapterView parent) {
- }
-
- private void playRingtone(int position, int delayMs) {
- mHandler.removeCallbacks(this);
- mSampleRingtonePos = position;
- mHandler.postDelayed(this, delayMs);
- }
-
- public void run() {
-
- if (mSampleRingtonePos == mSilentPos) {
- return;
- }
-
- /*
- * Stop the default ringtone, if it's playing (other ringtones will be
- * stopped by the RingtoneManager when we get another Ringtone from it.
- */
- if (mDefaultRingtone != null && mDefaultRingtone.isPlaying()) {
- mDefaultRingtone.stop();
- mDefaultRingtone = null;
- }
-
- Ringtone ringtone;
- if (mSampleRingtonePos == mDefaultRingtonePos) {
- if (mDefaultRingtone == null) {
- mDefaultRingtone = RingtoneManager.getRingtone(this, mUriForDefaultItem);
- }
- ringtone = mDefaultRingtone;
-
- /*
- * Normally the non-static RingtoneManager.getRingtone stops the
- * previous ringtone, but we're getting the default ringtone outside
- * of the RingtoneManager instance, so let's stop the previous
- * ringtone manually.
- */
- mRingtoneManager.stopPreviousRingtone();
-
- } else {
- ringtone = mRingtoneManager.getRingtone(getRingtoneManagerPosition(mSampleRingtonePos));
- }
-
- if (ringtone != null) {
- ringtone.play();
- }
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- stopAnyPlayingRingtone();
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- stopAnyPlayingRingtone();
- }
-
- private void stopAnyPlayingRingtone() {
-
- if (mDefaultRingtone != null && mDefaultRingtone.isPlaying()) {
- mDefaultRingtone.stop();
- }
-
- if (mRingtoneManager != null) {
- mRingtoneManager.stopPreviousRingtone();
- }
- }
-
- private int getRingtoneManagerPosition(int listPos) {
- return listPos - mStaticItemCount;
- }
-
- private int getListPosition(int ringtoneManagerPos) {
-
- // If the manager position is -1 (for not found), return that
- if (ringtoneManagerPos < 0) return ringtoneManagerPos;
-
- return ringtoneManagerPos + mStaticItemCount;
- }
-
-}
diff --git a/core/java/com/android/internal/app/UsbStorageActivity.java b/core/java/com/android/internal/app/UsbStorageActivity.java
deleted file mode 100644
index b8a2136..0000000
--- a/core/java/com/android/internal/app/UsbStorageActivity.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2007 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import android.app.AlertDialog;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IMountService;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.widget.Toast;
-
-/**
- * This activity is shown to the user for him/her to enable USB mass storage
- * on-demand (that is, when the USB cable is connected). It uses the alert
- * dialog style. It will be launched from a notification.
- */
-public class UsbStorageActivity extends AlertActivity implements DialogInterface.OnClickListener {
-
- private static final int POSITIVE_BUTTON = AlertDialog.BUTTON1;
-
- /** Used to detect when the USB cable is unplugged, so we can call finish() */
- private BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction() == Intent.ACTION_BATTERY_CHANGED) {
- handleBatteryChanged(intent);
- }
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Set up the "dialog"
- final AlertController.AlertParams p = mAlertParams;
- p.mIconId = com.android.internal.R.drawable.ic_dialog_usb;
- p.mTitle = getString(com.android.internal.R.string.usb_storage_title);
- p.mMessage = getString(com.android.internal.R.string.usb_storage_message);
- p.mPositiveButtonText = getString(com.android.internal.R.string.usb_storage_button_mount);
- p.mPositiveButtonListener = this;
- p.mNegativeButtonText = getString(com.android.internal.R.string.usb_storage_button_unmount);
- p.mNegativeButtonListener = this;
- setupAlert();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- registerReceiver(mBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- unregisterReceiver(mBatteryReceiver);
- }
-
- /**
- * {@inheritDoc}
- */
- public void onClick(DialogInterface dialog, int which) {
-
- if (which == POSITIVE_BUTTON) {
- mountAsUsbStorage();
- }
-
- // No matter what, finish the activity
- finish();
- }
-
- private void mountAsUsbStorage() {
- IMountService mountService = IMountService.Stub.asInterface(ServiceManager
- .getService("mount"));
- if (mountService == null) {
- showSharingError();
- return;
- }
-
- try {
- mountService.setMassStorageEnabled(true);
- } catch (RemoteException e) {
- showSharingError();
- return;
- }
- }
-
- private void handleBatteryChanged(Intent intent) {
- int pluggedType = intent.getIntExtra("plugged", 0);
- if (pluggedType == 0) {
- // It was disconnected from the plug, so finish
- finish();
- }
- }
-
- private void showSharingError() {
- Toast.makeText(this, com.android.internal.R.string.usb_storage_error_message,
- Toast.LENGTH_LONG).show();
- }
-
-}
diff --git a/core/java/com/android/internal/app/UsbStorageStopActivity.java b/core/java/com/android/internal/app/UsbStorageStopActivity.java
deleted file mode 100644
index 557a523..0000000
--- a/core/java/com/android/internal/app/UsbStorageStopActivity.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2007 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import android.app.AlertDialog;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IMountService;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.widget.Toast;
-
-/**
- * This activity is shown to the user for him/her to disable USB mass storage.
- * It uses the alert dialog style. It will be launched from a notification.
- */
-public class UsbStorageStopActivity extends AlertActivity implements DialogInterface.OnClickListener {
-
- private static final int POSITIVE_BUTTON = AlertDialog.BUTTON1;
-
- /** Used to detect when the USB cable is unplugged, so we can call finish() */
- private BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction() == Intent.ACTION_BATTERY_CHANGED) {
- handleBatteryChanged(intent);
- }
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Set up the "dialog"
- final AlertController.AlertParams p = mAlertParams;
- p.mIconId = com.android.internal.R.drawable.ic_dialog_alert;
- p.mTitle = getString(com.android.internal.R.string.usb_storage_stop_title);
- p.mMessage = getString(com.android.internal.R.string.usb_storage_stop_message);
- p.mPositiveButtonText = getString(com.android.internal.R.string.usb_storage_stop_button_mount);
- p.mPositiveButtonListener = this;
- p.mNegativeButtonText = getString(com.android.internal.R.string.usb_storage_stop_button_unmount);
- p.mNegativeButtonListener = this;
- setupAlert();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- registerReceiver(mBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- unregisterReceiver(mBatteryReceiver);
- }
-
- /**
- * {@inheritDoc}
- */
- public void onClick(DialogInterface dialog, int which) {
-
- if (which == POSITIVE_BUTTON) {
- stopUsbStorage();
- }
-
- // No matter what, finish the activity
- finish();
- }
-
- private void stopUsbStorage() {
- IMountService mountService = IMountService.Stub.asInterface(ServiceManager
- .getService("mount"));
- if (mountService == null) {
- showStoppingError();
- return;
- }
-
- try {
- mountService.setMassStorageEnabled(false);
- } catch (RemoteException e) {
- showStoppingError();
- return;
- }
- }
-
- private void handleBatteryChanged(Intent intent) {
- int pluggedType = intent.getIntExtra("plugged", 0);
- if (pluggedType == 0) {
- // It was disconnected from the plug, so finish
- finish();
- }
- }
-
- private void showStoppingError() {
- Toast.makeText(this, com.android.internal.R.string.usb_storage_stop_error_message,
- Toast.LENGTH_LONG).show();
- }
-
-}
diff --git a/core/java/com/android/internal/app/package.html b/core/java/com/android/internal/app/package.html
deleted file mode 100644
index db6f78b..0000000
--- a/core/java/com/android/internal/app/package.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<body>
-{@hide}
-</body> \ No newline at end of file
diff --git a/core/java/com/android/internal/database/ArrayListCursor.java b/core/java/com/android/internal/database/ArrayListCursor.java
deleted file mode 100644
index 2e1d8f1..0000000
--- a/core/java/com/android/internal/database/ArrayListCursor.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.database;
-
-import android.database.AbstractCursor;
-import android.database.CursorWindow;
-
-import java.lang.System;
-import java.util.ArrayList;
-
-/**
- * A convenience class that presents a two-dimensional ArrayList
- * as a Cursor.
- */
-public class ArrayListCursor extends AbstractCursor {
- private String[] mColumnNames;
- private ArrayList<Object>[] mRows;
-
- @SuppressWarnings({"unchecked"})
- public ArrayListCursor(String[] columnNames, ArrayList<ArrayList> rows) {
- int colCount = columnNames.length;
- boolean foundID = false;
- // Add an _id column if not in columnNames
- for (int i = 0; i < colCount; ++i) {
- if (columnNames[i].compareToIgnoreCase("_id") == 0) {
- mColumnNames = columnNames;
- foundID = true;
- break;
- }
- }
-
- if (!foundID) {
- mColumnNames = new String[colCount + 1];
- System.arraycopy(columnNames, 0, mColumnNames, 0, columnNames.length);
- mColumnNames[colCount] = "_id";
- }
-
- int rowCount = rows.size();
- mRows = new ArrayList[rowCount];
-
- for (int i = 0; i < rowCount; ++i) {
- mRows[i] = rows.get(i);
- if (!foundID) {
- mRows[i].add(i);
- }
- }
- }
-
- @Override
- public void fillWindow(int position, CursorWindow window) {
- if (position < 0 || position > getCount()) {
- return;
- }
-
- window.acquireReference();
- try {
- int oldpos = mPos;
- mPos = position - 1;
- window.clear();
- window.setStartPosition(position);
- int columnNum = getColumnCount();
- window.setNumColumns(columnNum);
- while (moveToNext() && window.allocRow()) {
- for (int i = 0; i < columnNum; i++) {
- final Object data = mRows[mPos].get(i);
- if (data != null) {
- if (data instanceof byte[]) {
- byte[] field = (byte[]) data;
- if (!window.putBlob(field, mPos, i)) {
- window.freeLastRow();
- break;
- }
- } else {
- String field = data.toString();
- if (!window.putString(field, mPos, i)) {
- window.freeLastRow();
- break;
- }
- }
- } else {
- if (!window.putNull(mPos, i)) {
- window.freeLastRow();
- break;
- }
- }
- }
- }
-
- mPos = oldpos;
- } catch (IllegalStateException e){
- // simply ignore it
- } finally {
- window.releaseReference();
- }
- }
-
- @Override
- public int getCount() {
- return mRows.length;
- }
-
- @Override
- public boolean deleteRow() {
- return false;
- }
-
- @Override
- public String[] getColumnNames() {
- return mColumnNames;
- }
-
- @Override
- public byte[] getBlob(int columnIndex) {
- return (byte[]) mRows[mPos].get(columnIndex);
- }
-
- @Override
- public String getString(int columnIndex) {
- Object cell = mRows[mPos].get(columnIndex);
- return (cell == null) ? null : cell.toString();
- }
-
- @Override
- public short getShort(int columnIndex) {
- Number num = (Number) mRows[mPos].get(columnIndex);
- return num.shortValue();
- }
-
- @Override
- public int getInt(int columnIndex) {
- Number num = (Number) mRows[mPos].get(columnIndex);
- return num.intValue();
- }
-
- @Override
- public long getLong(int columnIndex) {
- Number num = (Number) mRows[mPos].get(columnIndex);
- return num.longValue();
- }
-
- @Override
- public float getFloat(int columnIndex) {
- Number num = (Number) mRows[mPos].get(columnIndex);
- return num.floatValue();
- }
-
- @Override
- public double getDouble(int columnIndex) {
- Number num = (Number) mRows[mPos].get(columnIndex);
- return num.doubleValue();
- }
-
- @Override
- public boolean isNull(int columnIndex) {
- return mRows[mPos].get(columnIndex) == null;
- }
-}
diff --git a/core/java/com/android/internal/database/SortCursor.java b/core/java/com/android/internal/database/SortCursor.java
deleted file mode 100644
index af0efc9..0000000
--- a/core/java/com/android/internal/database/SortCursor.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.database;
-
-import android.database.AbstractCursor;
-import android.database.Cursor;
-import android.database.DataSetObserver;
-import android.util.Log;
-
-/**
- * A variant of MergeCursor that sorts the cursors being merged. If decent
- * performance is ever obtained, it can be put back under android.database.
- */
-public class SortCursor extends AbstractCursor
-{
- private static final String TAG = "SortCursor";
- private Cursor mCursor; // updated in onMove
- private Cursor[] mCursors;
- private int [] mSortColumns;
- private final int ROWCACHESIZE = 64;
- private int mRowNumCache[] = new int[ROWCACHESIZE];
- private int mCursorCache[] = new int[ROWCACHESIZE];
- private int mCurRowNumCache[][];
- private int mLastCacheHit = -1;
-
- private DataSetObserver mObserver = new DataSetObserver() {
-
- @Override
- public void onChanged() {
- // Reset our position so the optimizations in move-related code
- // don't screw us over
- mPos = -1;
- }
-
- @Override
- public void onInvalidated() {
- mPos = -1;
- }
- };
-
- public SortCursor(Cursor[] cursors, String sortcolumn)
- {
- mCursors = cursors;
-
- int length = mCursors.length;
- mSortColumns = new int[length];
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] == null) continue;
-
- // Register ourself as a data set observer
- mCursors[i].registerDataSetObserver(mObserver);
-
- mCursors[i].moveToFirst();
-
- // We don't catch the exception
- mSortColumns[i] = mCursors[i].getColumnIndexOrThrow(sortcolumn);
- }
- mCursor = null;
- String smallest = "";
- for (int j = 0 ; j < length; j++) {
- if (mCursors[j] == null || mCursors[j].isAfterLast())
- continue;
- String current = mCursors[j].getString(mSortColumns[j]);
- if (mCursor == null || current.compareToIgnoreCase(smallest) < 0) {
- smallest = current;
- mCursor = mCursors[j];
- }
- }
-
- for (int i = mRowNumCache.length - 1; i >= 0; i--) {
- mRowNumCache[i] = -2;
- }
- mCurRowNumCache = new int[ROWCACHESIZE][length];
- }
-
- @Override
- public int getCount()
- {
- int count = 0;
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] != null) {
- count += mCursors[i].getCount();
- }
- }
- return count;
- }
-
- @Override
- public boolean onMove(int oldPosition, int newPosition)
- {
- if (oldPosition == newPosition)
- return true;
-
- /* Find the right cursor
- * Because the client of this cursor (the listadapter/view) tends
- * to jump around in the cursor somewhat, a simple cache strategy
- * is used to avoid having to search all cursors from the start.
- * TODO: investigate strategies for optimizing random access and
- * reverse-order access.
- */
-
- int cache_entry = newPosition % ROWCACHESIZE;
-
- if (mRowNumCache[cache_entry] == newPosition) {
- int which = mCursorCache[cache_entry];
- mCursor = mCursors[which];
- if (mCursor == null) {
- Log.w(TAG, "onMove: cache results in a null cursor.");
- return false;
- }
- mCursor.moveToPosition(mCurRowNumCache[cache_entry][which]);
- mLastCacheHit = cache_entry;
- return true;
- }
-
- mCursor = null;
- int length = mCursors.length;
-
- if (mLastCacheHit >= 0) {
- for (int i = 0; i < length; i++) {
- if (mCursors[i] == null) continue;
- mCursors[i].moveToPosition(mCurRowNumCache[mLastCacheHit][i]);
- }
- }
-
- if (newPosition < oldPosition || oldPosition == -1) {
- for (int i = 0 ; i < length; i++) {
- if (mCursors[i] == null) continue;
- mCursors[i].moveToFirst();
- }
- oldPosition = 0;
- }
- if (oldPosition < 0) {
- oldPosition = 0;
- }
-
- // search forward to the new position
- int smallestIdx = -1;
- for(int i = oldPosition; i <= newPosition; i++) {
- String smallest = "";
- smallestIdx = -1;
- for (int j = 0 ; j < length; j++) {
- if (mCursors[j] == null || mCursors[j].isAfterLast()) {
- continue;
- }
- String current = mCursors[j].getString(mSortColumns[j]);
- if (smallestIdx < 0 || current.compareToIgnoreCase(smallest) < 0) {
- smallest = current;
- smallestIdx = j;
- }
- }
- if (i == newPosition) break;
- if (mCursors[smallestIdx] != null) {
- mCursors[smallestIdx].moveToNext();
- }
- }
- mCursor = mCursors[smallestIdx];
- mRowNumCache[cache_entry] = newPosition;
- mCursorCache[cache_entry] = smallestIdx;
- for (int i = 0; i < length; i++) {
- if (mCursors[i] != null) {
- mCurRowNumCache[cache_entry][i] = mCursors[i].getPosition();
- }
- }
- mLastCacheHit = -1;
- return true;
- }
-
- @Override
- public boolean deleteRow()
- {
- return mCursor.deleteRow();
- }
-
- @Override
- public boolean commitUpdates() {
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] != null) {
- mCursors[i].commitUpdates();
- }
- }
- onChange(true);
- return true;
- }
-
- @Override
- public String getString(int column)
- {
- return mCursor.getString(column);
- }
-
- @Override
- public short getShort(int column)
- {
- return mCursor.getShort(column);
- }
-
- @Override
- public int getInt(int column)
- {
- return mCursor.getInt(column);
- }
-
- @Override
- public long getLong(int column)
- {
- return mCursor.getLong(column);
- }
-
- @Override
- public float getFloat(int column)
- {
- return mCursor.getFloat(column);
- }
-
- @Override
- public double getDouble(int column)
- {
- return mCursor.getDouble(column);
- }
-
- @Override
- public boolean isNull(int column)
- {
- return mCursor.isNull(column);
- }
-
- @Override
- public byte[] getBlob(int column)
- {
- return mCursor.getBlob(column);
- }
-
- @Override
- public String[] getColumnNames()
- {
- if (mCursor != null) {
- return mCursor.getColumnNames();
- } else {
- return new String[0];
- }
- }
-
- @Override
- public void deactivate()
- {
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] == null) continue;
- mCursors[i].deactivate();
- }
- }
-
- @Override
- public void close() {
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] == null) continue;
- mCursors[i].close();
- }
- }
-
- @Override
- public void registerDataSetObserver(DataSetObserver observer) {
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] != null) {
- mCursors[i].registerDataSetObserver(observer);
- }
- }
- }
-
- @Override
- public void unregisterDataSetObserver(DataSetObserver observer) {
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] != null) {
- mCursors[i].unregisterDataSetObserver(observer);
- }
- }
- }
-
- @Override
- public boolean requery()
- {
- int length = mCursors.length;
- for (int i = 0 ; i < length ; i++) {
- if (mCursors[i] == null) continue;
-
- if (mCursors[i].requery() == false) {
- return false;
- }
- }
-
- return true;
- }
-}
diff --git a/core/java/com/android/internal/gadget/IGadgetHost.aidl b/core/java/com/android/internal/gadget/IGadgetHost.aidl
deleted file mode 100644
index e7b5a1e..0000000
--- a/core/java/com/android/internal/gadget/IGadgetHost.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.gadget;
-
-import android.content.ComponentName;
-import android.gadget.GadgetProviderInfo;
-import android.widget.RemoteViews;
-
-/** {@hide} */
-oneway interface IGadgetHost {
- void updateGadget(int gadgetId, in RemoteViews views);
- void providerChanged(int gadgetId, in GadgetProviderInfo info);
-}
-
diff --git a/core/java/com/android/internal/gadget/IGadgetService.aidl b/core/java/com/android/internal/gadget/IGadgetService.aidl
deleted file mode 100644
index a22f3f3..0000000
--- a/core/java/com/android/internal/gadget/IGadgetService.aidl
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.gadget;
-
-import android.content.ComponentName;
-import android.gadget.GadgetProviderInfo;
-import com.android.internal.gadget.IGadgetHost;
-import android.widget.RemoteViews;
-
-/** {@hide} */
-interface IGadgetService {
-
- //
- // for GadgetHost
- //
- int[] startListening(IGadgetHost host, String packageName, int hostId,
- out List<RemoteViews> updatedViews);
- void stopListening(int hostId);
- int allocateGadgetId(String packageName, int hostId);
- void deleteGadgetId(int gadgetId);
- void deleteHost(int hostId);
- void deleteAllHosts();
- RemoteViews getGadgetViews(int gadgetId);
-
- //
- // for GadgetManager
- //
- void updateGadgetIds(in int[] gadgetIds, in RemoteViews views);
- void updateGadgetProvider(in ComponentName provider, in RemoteViews views);
- List<GadgetProviderInfo> getInstalledProviders();
- GadgetProviderInfo getGadgetInfo(int gadgetId);
- void bindGadgetId(int gadgetId, in ComponentName provider);
-
-}
-
diff --git a/core/java/com/android/internal/gadget/package.html b/core/java/com/android/internal/gadget/package.html
deleted file mode 100644
index db6f78b..0000000
--- a/core/java/com/android/internal/gadget/package.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<body>
-{@hide}
-</body> \ No newline at end of file
diff --git a/core/java/com/android/internal/http/multipart/ByteArrayPartSource.java b/core/java/com/android/internal/http/multipart/ByteArrayPartSource.java
deleted file mode 100644
index faaac7f..0000000
--- a/core/java/com/android/internal/http/multipart/ByteArrayPartSource.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/ByteArrayPartSource.java,v 1.7 2004/04/18 23:51:37 jsdever Exp $
- * $Revision: 480424 $
- * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-
-/**
- * A PartSource that reads from a byte array. This class should be used when
- * the data to post is already loaded into memory.
- *
- * @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
- *
- * @since 2.0
- */
-public class ByteArrayPartSource implements PartSource {
-
- /** Name of the source file. */
- private String fileName;
-
- /** Byte array of the source file. */
- private byte[] bytes;
-
- /**
- * Constructor for ByteArrayPartSource.
- *
- * @param fileName the name of the file these bytes represent
- * @param bytes the content of this part
- */
- public ByteArrayPartSource(String fileName, byte[] bytes) {
-
- this.fileName = fileName;
- this.bytes = bytes;
-
- }
-
- /**
- * @see PartSource#getLength()
- */
- public long getLength() {
- return bytes.length;
- }
-
- /**
- * @see PartSource#getFileName()
- */
- public String getFileName() {
- return fileName;
- }
-
- /**
- * @see PartSource#createInputStream()
- */
- public InputStream createInputStream() {
- return new ByteArrayInputStream(bytes);
- }
-
-}
diff --git a/core/java/com/android/internal/http/multipart/FilePart.java b/core/java/com/android/internal/http/multipart/FilePart.java
deleted file mode 100644
index bfcda00..0000000
--- a/core/java/com/android/internal/http/multipart/FilePart.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/FilePart.java,v 1.19 2004/04/18 23:51:37 jsdever Exp $
- * $Revision: 480424 $
- * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import org.apache.http.util.EncodingUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * This class implements a part of a Multipart post object that
- * consists of a file.
- *
- * @author <a href="mailto:mattalbright@yahoo.com">Matthew Albright</a>
- * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
- * @author <a href="mailto:adrian@ephox.com">Adrian Sutton</a>
- * @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
- * @author <a href="mailto:mdiggory@latte.harvard.edu">Mark Diggory</a>
- * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
- * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
- *
- * @since 2.0
- *
- */
-public class FilePart extends PartBase {
-
- /** Default content encoding of file attachments. */
- public static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";
-
- /** Default charset of file attachments. */
- public static final String DEFAULT_CHARSET = "ISO-8859-1";
-
- /** Default transfer encoding of file attachments. */
- public static final String DEFAULT_TRANSFER_ENCODING = "binary";
-
- /** Log object for this class. */
- private static final Log LOG = LogFactory.getLog(FilePart.class);
-
- /** Attachment's file name */
- protected static final String FILE_NAME = "; filename=";
-
- /** Attachment's file name as a byte array */
- private static final byte[] FILE_NAME_BYTES =
- EncodingUtils.getAsciiBytes(FILE_NAME);
-
- /** Source of the file part. */
- private PartSource source;
-
- /**
- * FilePart Constructor.
- *
- * @param name the name for this part
- * @param partSource the source for this part
- * @param contentType the content type for this part, if <code>null</code> the
- * {@link #DEFAULT_CONTENT_TYPE default} is used
- * @param charset the charset encoding for this part, if <code>null</code> the
- * {@link #DEFAULT_CHARSET default} is used
- */
- public FilePart(String name, PartSource partSource, String contentType, String charset) {
-
- super(
- name,
- contentType == null ? DEFAULT_CONTENT_TYPE : contentType,
- charset == null ? "ISO-8859-1" : charset,
- DEFAULT_TRANSFER_ENCODING
- );
-
- if (partSource == null) {
- throw new IllegalArgumentException("Source may not be null");
- }
- this.source = partSource;
- }
-
- /**
- * FilePart Constructor.
- *
- * @param name the name for this part
- * @param partSource the source for this part
- */
- public FilePart(String name, PartSource partSource) {
- this(name, partSource, null, null);
- }
-
- /**
- * FilePart Constructor.
- *
- * @param name the name of the file part
- * @param file the file to post
- *
- * @throws FileNotFoundException if the <i>file</i> is not a normal
- * file or if it is not readable.
- */
- public FilePart(String name, File file)
- throws FileNotFoundException {
- this(name, new FilePartSource(file), null, null);
- }
-
- /**
- * FilePart Constructor.
- *
- * @param name the name of the file part
- * @param file the file to post
- * @param contentType the content type for this part, if <code>null</code> the
- * {@link #DEFAULT_CONTENT_TYPE default} is used
- * @param charset the charset encoding for this part, if <code>null</code> the
- * {@link #DEFAULT_CHARSET default} is used
- *
- * @throws FileNotFoundException if the <i>file</i> is not a normal
- * file or if it is not readable.
- */
- public FilePart(String name, File file, String contentType, String charset)
- throws FileNotFoundException {
- this(name, new FilePartSource(file), contentType, charset);
- }
-
- /**
- * FilePart Constructor.
- *
- * @param name the name of the file part
- * @param fileName the file name
- * @param file the file to post
- *
- * @throws FileNotFoundException if the <i>file</i> is not a normal
- * file or if it is not readable.
- */
- public FilePart(String name, String fileName, File file)
- throws FileNotFoundException {
- this(name, new FilePartSource(fileName, file), null, null);
- }
-
- /**
- * FilePart Constructor.
- *
- * @param name the name of the file part
- * @param fileName the file name
- * @param file the file to post
- * @param contentType the content type for this part, if <code>null</code> the
- * {@link #DEFAULT_CONTENT_TYPE default} is used
- * @param charset the charset encoding for this part, if <code>null</code> the
- * {@link #DEFAULT_CHARSET default} is used
- *
- * @throws FileNotFoundException if the <i>file</i> is not a normal
- * file or if it is not readable.
- */
- public FilePart(String name, String fileName, File file, String contentType, String charset)
- throws FileNotFoundException {
- this(name, new FilePartSource(fileName, file), contentType, charset);
- }
-
- /**
- * Write the disposition header to the output stream
- * @param out The output stream
- * @throws IOException If an IO problem occurs
- * @see Part#sendDispositionHeader(OutputStream)
- */
- @Override
- protected void sendDispositionHeader(OutputStream out)
- throws IOException {
- LOG.trace("enter sendDispositionHeader(OutputStream out)");
- super.sendDispositionHeader(out);
- String filename = this.source.getFileName();
- if (filename != null) {
- out.write(FILE_NAME_BYTES);
- out.write(QUOTE_BYTES);
- out.write(EncodingUtils.getAsciiBytes(filename));
- out.write(QUOTE_BYTES);
- }
- }
-
- /**
- * Write the data in "source" to the specified stream.
- * @param out The output stream.
- * @throws IOException if an IO problem occurs.
- * @see Part#sendData(OutputStream)
- */
- @Override
- protected void sendData(OutputStream out) throws IOException {
- LOG.trace("enter sendData(OutputStream out)");
- if (lengthOfData() == 0) {
-
- // this file contains no data, so there is nothing to send.
- // we don't want to create a zero length buffer as this will
- // cause an infinite loop when reading.
- LOG.debug("No data to send.");
- return;
- }
-
- byte[] tmp = new byte[4096];
- InputStream instream = source.createInputStream();
- try {
- int len;
- while ((len = instream.read(tmp)) >= 0) {
- out.write(tmp, 0, len);
- }
- } finally {
- // we're done with the stream, close it
- instream.close();
- }
- }
-
- /**
- * Returns the source of the file part.
- *
- * @return The source.
- */
- protected PartSource getSource() {
- LOG.trace("enter getSource()");
- return this.source;
- }
-
- /**
- * Return the length of the data.
- * @return The length.
- * @see Part#lengthOfData()
- */
- @Override
- protected long lengthOfData() {
- LOG.trace("enter lengthOfData()");
- return source.getLength();
- }
-
-}
diff --git a/core/java/com/android/internal/http/multipart/FilePartSource.java b/core/java/com/android/internal/http/multipart/FilePartSource.java
deleted file mode 100644
index eb5cc0f..0000000
--- a/core/java/com/android/internal/http/multipart/FilePartSource.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/FilePartSource.java,v 1.10 2004/04/18 23:51:37 jsdever Exp $
- * $Revision: 480424 $
- * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * A PartSource that reads from a File.
- *
- * @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
- * @author <a href="mailto:mdiggory@latte.harvard.edu">Mark Diggory</a>
- * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
- *
- * @since 2.0
- */
-public class FilePartSource implements PartSource {
-
- /** File part file. */
- private File file = null;
-
- /** File part file name. */
- private String fileName = null;
-
- /**
- * Constructor for FilePartSource.
- *
- * @param file the FilePart source File.
- *
- * @throws FileNotFoundException if the file does not exist or
- * cannot be read
- */
- public FilePartSource(File file) throws FileNotFoundException {
- this.file = file;
- if (file != null) {
- if (!file.isFile()) {
- throw new FileNotFoundException("File is not a normal file.");
- }
- if (!file.canRead()) {
- throw new FileNotFoundException("File is not readable.");
- }
- this.fileName = file.getName();
- }
- }
-
- /**
- * Constructor for FilePartSource.
- *
- * @param fileName the file name of the FilePart
- * @param file the source File for the FilePart
- *
- * @throws FileNotFoundException if the file does not exist or
- * cannot be read
- */
- public FilePartSource(String fileName, File file)
- throws FileNotFoundException {
- this(file);
- if (fileName != null) {
- this.fileName = fileName;
- }
- }
-
- /**
- * Return the length of the file
- * @return the length of the file.
- * @see PartSource#getLength()
- */
- public long getLength() {
- if (this.file != null) {
- return this.file.length();
- } else {
- return 0;
- }
- }
-
- /**
- * Return the current filename
- * @return the filename.
- * @see PartSource#getFileName()
- */
- public String getFileName() {
- return (fileName == null) ? "noname" : fileName;
- }
-
- /**
- * Return a new {@link FileInputStream} for the current filename.
- * @return the new input stream.
- * @throws IOException If an IO problem occurs.
- * @see PartSource#createInputStream()
- */
- public InputStream createInputStream() throws IOException {
- if (this.file != null) {
- return new FileInputStream(this.file);
- } else {
- return new ByteArrayInputStream(new byte[] {});
- }
- }
-
-}
diff --git a/core/java/com/android/internal/http/multipart/MultipartEntity.java b/core/java/com/android/internal/http/multipart/MultipartEntity.java
deleted file mode 100644
index 2c5e7f6..0000000
--- a/core/java/com/android/internal/http/multipart/MultipartEntity.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/MultipartRequestEntity.java,v 1.1 2004/10/06 03:39:59 mbecke Exp $
- * $Revision: 502647 $
- * $Date: 2007-02-02 17:22:54 +0100 (Fri, 02 Feb 2007) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Random;
-
-import org.apache.http.Header;
-import org.apache.http.entity.AbstractHttpEntity;
-import org.apache.http.message.BasicHeader;
-import org.apache.http.params.HttpParams;
-import org.apache.http.protocol.HTTP;
-import org.apache.http.util.EncodingUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Implements a request entity suitable for an HTTP multipart POST method.
- * <p>
- * The HTTP multipart POST method is defined in section 3.3 of
- * <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC1867</a>:
- * <blockquote>
- * The media-type multipart/form-data follows the rules of all multipart
- * MIME data streams as outlined in RFC 1521. The multipart/form-data contains
- * a series of parts. Each part is expected to contain a content-disposition
- * header where the value is "form-data" and a name attribute specifies
- * the field name within the form, e.g., 'content-disposition: form-data;
- * name="xxxxx"', where xxxxx is the field name corresponding to that field.
- * Field names originally in non-ASCII character sets may be encoded using
- * the method outlined in RFC 1522.
- * </blockquote>
- * </p>
- * <p>This entity is designed to be used in conjunction with the
- * {@link org.apache.http.HttpRequest} to provide
- * multipart posts. Example usage:</p>
- * <pre>
- * File f = new File("/path/fileToUpload.txt");
- * HttpRequest request = new HttpRequest("http://host/some_path");
- * Part[] parts = {
- * new StringPart("param_name", "value"),
- * new FilePart(f.getName(), f)
- * };
- * filePost.setEntity(
- * new MultipartRequestEntity(parts, filePost.getParams())
- * );
- * HttpClient client = new HttpClient();
- * int status = client.executeMethod(filePost);
- * </pre>
- *
- * @since 3.0
- */
-public class MultipartEntity extends AbstractHttpEntity {
-
- private static final Log log = LogFactory.getLog(MultipartEntity.class);
-
- /** The Content-Type for multipart/form-data. */
- private static final String MULTIPART_FORM_CONTENT_TYPE = "multipart/form-data";
-
- /**
- * Sets the value to use as the multipart boundary.
- * <p>
- * This parameter expects a value if type {@link String}.
- * </p>
- */
- public static final String MULTIPART_BOUNDARY = "http.method.multipart.boundary";
-
- /**
- * The pool of ASCII chars to be used for generating a multipart boundary.
- */
- private static byte[] MULTIPART_CHARS = EncodingUtils.getAsciiBytes(
- "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
-
- /**
- * Generates a random multipart boundary string.
- */
- private static byte[] generateMultipartBoundary() {
- Random rand = new Random();
- byte[] bytes = new byte[rand.nextInt(11) + 30]; // a random size from 30 to 40
- for (int i = 0; i < bytes.length; i++) {
- bytes[i] = MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)];
- }
- return bytes;
- }
-
- /** The MIME parts as set by the constructor */
- protected Part[] parts;
-
- private byte[] multipartBoundary;
-
- private HttpParams params;
-
- private boolean contentConsumed = false;
-
- /**
- * Creates a new multipart entity containing the given parts.
- * @param parts The parts to include.
- * @param params The params of the HttpMethod using this entity.
- */
- public MultipartEntity(Part[] parts, HttpParams params) {
- if (parts == null) {
- throw new IllegalArgumentException("parts cannot be null");
- }
- if (params == null) {
- throw new IllegalArgumentException("params cannot be null");
- }
- this.parts = parts;
- this.params = params;
- }
-
- public MultipartEntity(Part[] parts) {
- setContentType(MULTIPART_FORM_CONTENT_TYPE);
- if (parts == null) {
- throw new IllegalArgumentException("parts cannot be null");
- }
- this.parts = parts;
- this.params = null;
- }
-
- /**
- * Returns the MIME boundary string that is used to demarcate boundaries of
- * this part. The first call to this method will implicitly create a new
- * boundary string. To create a boundary string first the
- * HttpMethodParams.MULTIPART_BOUNDARY parameter is considered. Otherwise
- * a random one is generated.
- *
- * @return The boundary string of this entity in ASCII encoding.
- */
- protected byte[] getMultipartBoundary() {
- if (multipartBoundary == null) {
- String temp = null;
- if (params != null) {
- temp = (String) params.getParameter(MULTIPART_BOUNDARY);
- }
- if (temp != null) {
- multipartBoundary = EncodingUtils.getAsciiBytes(temp);
- } else {
- multipartBoundary = generateMultipartBoundary();
- }
- }
- return multipartBoundary;
- }
-
- /**
- * Returns <code>true</code> if all parts are repeatable, <code>false</code> otherwise.
- */
- public boolean isRepeatable() {
- for (int i = 0; i < parts.length; i++) {
- if (!parts[i].isRepeatable()) {
- return false;
- }
- }
- return true;
- }
-
- /* (non-Javadoc)
- */
- public void writeTo(OutputStream out) throws IOException {
- Part.sendParts(out, parts, getMultipartBoundary());
- }
- /* (non-Javadoc)
- * @see org.apache.commons.http.AbstractHttpEntity.#getContentType()
- */
- @Override
- public Header getContentType() {
- StringBuffer buffer = new StringBuffer(MULTIPART_FORM_CONTENT_TYPE);
- buffer.append("; boundary=");
- buffer.append(EncodingUtils.getAsciiString(getMultipartBoundary()));
- return new BasicHeader(HTTP.CONTENT_TYPE, buffer.toString());
-
- }
-
- /* (non-Javadoc)
- */
- public long getContentLength() {
- try {
- return Part.getLengthOfParts(parts, getMultipartBoundary());
- } catch (Exception e) {
- log.error("An exception occurred while getting the length of the parts", e);
- return 0;
- }
- }
-
- public InputStream getContent() throws IOException, IllegalStateException {
- if(!isRepeatable() && this.contentConsumed ) {
- throw new IllegalStateException("Content has been consumed");
- }
- this.contentConsumed = true;
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- Part.sendParts(baos, this.parts, this.multipartBoundary);
- ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
- return bais;
- }
-
- public boolean isStreaming() {
- return false;
- }
-}
diff --git a/core/java/com/android/internal/http/multipart/Part.java b/core/java/com/android/internal/http/multipart/Part.java
deleted file mode 100644
index cb1b546..0000000
--- a/core/java/com/android/internal/http/multipart/Part.java
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/Part.java,v 1.16 2005/01/14 21:16:40 olegk Exp $
- * $Revision: 480424 $
- * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.apache.http.util.EncodingUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Abstract class for one Part of a multipart post object.
- *
- * @author <a href="mailto:mattalbright@yahoo.com">Matthew Albright</a>
- * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
- * @author <a href="mailto:adrian@ephox.com">Adrian Sutton</a>
- * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
- * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
- *
- * @since 2.0
- */
-public abstract class Part {
-
- /** Log object for this class. */
- private static final Log LOG = LogFactory.getLog(Part.class);
-
- /**
- * The boundary
- * @deprecated use {@link org.apache.http.client.methods.multipart#MULTIPART_BOUNDARY}
- */
- protected static final String BOUNDARY = "----------------314159265358979323846";
-
- /**
- * The boundary as a byte array.
- * @deprecated
- */
- protected static final byte[] BOUNDARY_BYTES = EncodingUtils.getAsciiBytes(BOUNDARY);
-
- /**
- * The default boundary to be used if {@link #setPartBoundary(byte[])} has not
- * been called.
- */
- private static final byte[] DEFAULT_BOUNDARY_BYTES = BOUNDARY_BYTES;
-
- /** Carriage return/linefeed */
- protected static final String CRLF = "\r\n";
-
- /** Carriage return/linefeed as a byte array */
- protected static final byte[] CRLF_BYTES = EncodingUtils.getAsciiBytes(CRLF);
-
- /** Content dispostion characters */
- protected static final String QUOTE = "\"";
-
- /** Content dispostion as a byte array */
- protected static final byte[] QUOTE_BYTES =
- EncodingUtils.getAsciiBytes(QUOTE);
-
- /** Extra characters */
- protected static final String EXTRA = "--";
-
- /** Extra characters as a byte array */
- protected static final byte[] EXTRA_BYTES =
- EncodingUtils.getAsciiBytes(EXTRA);
-
- /** Content dispostion characters */
- protected static final String CONTENT_DISPOSITION = "Content-Disposition: form-data; name=";
-
- /** Content dispostion as a byte array */
- protected static final byte[] CONTENT_DISPOSITION_BYTES =
- EncodingUtils.getAsciiBytes(CONTENT_DISPOSITION);
-
- /** Content type header */
- protected static final String CONTENT_TYPE = "Content-Type: ";
-
- /** Content type header as a byte array */
- protected static final byte[] CONTENT_TYPE_BYTES =
- EncodingUtils.getAsciiBytes(CONTENT_TYPE);
-
- /** Content charset */
- protected static final String CHARSET = "; charset=";
-
- /** Content charset as a byte array */
- protected static final byte[] CHARSET_BYTES =
- EncodingUtils.getAsciiBytes(CHARSET);
-
- /** Content type header */
- protected static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding: ";
-
- /** Content type header as a byte array */
- protected static final byte[] CONTENT_TRANSFER_ENCODING_BYTES =
- EncodingUtils.getAsciiBytes(CONTENT_TRANSFER_ENCODING);
-
- /**
- * Return the boundary string.
- * @return the boundary string
- * @deprecated uses a constant string. Rather use {@link #getPartBoundary}
- */
- public static String getBoundary() {
- return BOUNDARY;
- }
-
- /**
- * The ASCII bytes to use as the multipart boundary.
- */
- private byte[] boundaryBytes;
-
- /**
- * Return the name of this part.
- * @return The name.
- */
- public abstract String getName();
-
- /**
- * Returns the content type of this part.
- * @return the content type, or <code>null</code> to exclude the content type header
- */
- public abstract String getContentType();
-
- /**
- * Return the character encoding of this part.
- * @return the character encoding, or <code>null</code> to exclude the character
- * encoding header
- */
- public abstract String getCharSet();
-
- /**
- * Return the transfer encoding of this part.
- * @return the transfer encoding, or <code>null</code> to exclude the transfer encoding header
- */
- public abstract String getTransferEncoding();
-
- /**
- * Gets the part boundary to be used.
- * @return the part boundary as an array of bytes.
- *
- * @since 3.0
- */
- protected byte[] getPartBoundary() {
- if (boundaryBytes == null) {
- // custom boundary bytes have not been set, use the default.
- return DEFAULT_BOUNDARY_BYTES;
- } else {
- return boundaryBytes;
- }
- }
-
- /**
- * Sets the part boundary. Only meant to be used by
- * {@link Part#sendParts(OutputStream, Part[], byte[])}
- * and {@link Part#getLengthOfParts(Part[], byte[])}
- * @param boundaryBytes An array of ASCII bytes.
- * @since 3.0
- */
- void setPartBoundary(byte[] boundaryBytes) {
- this.boundaryBytes = boundaryBytes;
- }
-
- /**
- * Tests if this part can be sent more than once.
- * @return <code>true</code> if {@link #sendData(OutputStream)} can be successfully called
- * more than once.
- * @since 3.0
- */
- public boolean isRepeatable() {
- return true;
- }
-
- /**
- * Write the start to the specified output stream
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- protected void sendStart(OutputStream out) throws IOException {
- LOG.trace("enter sendStart(OutputStream out)");
- out.write(EXTRA_BYTES);
- out.write(getPartBoundary());
- out.write(CRLF_BYTES);
- }
-
- /**
- * Write the content disposition header to the specified output stream
- *
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- protected void sendDispositionHeader(OutputStream out) throws IOException {
- LOG.trace("enter sendDispositionHeader(OutputStream out)");
- out.write(CONTENT_DISPOSITION_BYTES);
- out.write(QUOTE_BYTES);
- out.write(EncodingUtils.getAsciiBytes(getName()));
- out.write(QUOTE_BYTES);
- }
-
- /**
- * Write the content type header to the specified output stream
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- protected void sendContentTypeHeader(OutputStream out) throws IOException {
- LOG.trace("enter sendContentTypeHeader(OutputStream out)");
- String contentType = getContentType();
- if (contentType != null) {
- out.write(CRLF_BYTES);
- out.write(CONTENT_TYPE_BYTES);
- out.write(EncodingUtils.getAsciiBytes(contentType));
- String charSet = getCharSet();
- if (charSet != null) {
- out.write(CHARSET_BYTES);
- out.write(EncodingUtils.getAsciiBytes(charSet));
- }
- }
- }
-
- /**
- * Write the content transfer encoding header to the specified
- * output stream
- *
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- protected void sendTransferEncodingHeader(OutputStream out) throws IOException {
- LOG.trace("enter sendTransferEncodingHeader(OutputStream out)");
- String transferEncoding = getTransferEncoding();
- if (transferEncoding != null) {
- out.write(CRLF_BYTES);
- out.write(CONTENT_TRANSFER_ENCODING_BYTES);
- out.write(EncodingUtils.getAsciiBytes(transferEncoding));
- }
- }
-
- /**
- * Write the end of the header to the output stream
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- protected void sendEndOfHeader(OutputStream out) throws IOException {
- LOG.trace("enter sendEndOfHeader(OutputStream out)");
- out.write(CRLF_BYTES);
- out.write(CRLF_BYTES);
- }
-
- /**
- * Write the data to the specified output stream
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- protected abstract void sendData(OutputStream out) throws IOException;
-
- /**
- * Return the length of the main content
- *
- * @return long The length.
- * @throws IOException If an IO problem occurs
- */
- protected abstract long lengthOfData() throws IOException;
-
- /**
- * Write the end data to the output stream.
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- protected void sendEnd(OutputStream out) throws IOException {
- LOG.trace("enter sendEnd(OutputStream out)");
- out.write(CRLF_BYTES);
- }
-
- /**
- * Write all the data to the output stream.
- * If you override this method make sure to override
- * #length() as well
- *
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- public void send(OutputStream out) throws IOException {
- LOG.trace("enter send(OutputStream out)");
- sendStart(out);
- sendDispositionHeader(out);
- sendContentTypeHeader(out);
- sendTransferEncodingHeader(out);
- sendEndOfHeader(out);
- sendData(out);
- sendEnd(out);
- }
-
-
- /**
- * Return the full length of all the data.
- * If you override this method make sure to override
- * #send(OutputStream) as well
- *
- * @return long The length.
- * @throws IOException If an IO problem occurs
- */
- public long length() throws IOException {
- LOG.trace("enter length()");
- if (lengthOfData() < 0) {
- return -1;
- }
- ByteArrayOutputStream overhead = new ByteArrayOutputStream();
- sendStart(overhead);
- sendDispositionHeader(overhead);
- sendContentTypeHeader(overhead);
- sendTransferEncodingHeader(overhead);
- sendEndOfHeader(overhead);
- sendEnd(overhead);
- return overhead.size() + lengthOfData();
- }
-
- /**
- * Return a string representation of this object.
- * @return A string representation of this object.
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- return this.getName();
- }
-
- /**
- * Write all parts and the last boundary to the specified output stream.
- *
- * @param out The stream to write to.
- * @param parts The parts to write.
- *
- * @throws IOException If an I/O error occurs while writing the parts.
- */
- public static void sendParts(OutputStream out, final Part[] parts)
- throws IOException {
- sendParts(out, parts, DEFAULT_BOUNDARY_BYTES);
- }
-
- /**
- * Write all parts and the last boundary to the specified output stream.
- *
- * @param out The stream to write to.
- * @param parts The parts to write.
- * @param partBoundary The ASCII bytes to use as the part boundary.
- *
- * @throws IOException If an I/O error occurs while writing the parts.
- *
- * @since 3.0
- */
- public static void sendParts(OutputStream out, Part[] parts, byte[] partBoundary)
- throws IOException {
-
- if (parts == null) {
- throw new IllegalArgumentException("Parts may not be null");
- }
- if (partBoundary == null || partBoundary.length == 0) {
- throw new IllegalArgumentException("partBoundary may not be empty");
- }
- for (int i = 0; i < parts.length; i++) {
- // set the part boundary before the part is sent
- parts[i].setPartBoundary(partBoundary);
- parts[i].send(out);
- }
- out.write(EXTRA_BYTES);
- out.write(partBoundary);
- out.write(EXTRA_BYTES);
- out.write(CRLF_BYTES);
- }
-
- /**
- * Return the total sum of all parts and that of the last boundary
- *
- * @param parts The parts.
- * @return The total length
- *
- * @throws IOException If an I/O error occurs while writing the parts.
- */
- public static long getLengthOfParts(Part[] parts)
- throws IOException {
- return getLengthOfParts(parts, DEFAULT_BOUNDARY_BYTES);
- }
-
- /**
- * Gets the length of the multipart message including the given parts.
- *
- * @param parts The parts.
- * @param partBoundary The ASCII bytes to use as the part boundary.
- * @return The total length
- *
- * @throws IOException If an I/O error occurs while writing the parts.
- *
- * @since 3.0
- */
- public static long getLengthOfParts(Part[] parts, byte[] partBoundary) throws IOException {
- LOG.trace("getLengthOfParts(Parts[])");
- if (parts == null) {
- throw new IllegalArgumentException("Parts may not be null");
- }
- long total = 0;
- for (int i = 0; i < parts.length; i++) {
- // set the part boundary before we calculate the part's length
- parts[i].setPartBoundary(partBoundary);
- long l = parts[i].length();
- if (l < 0) {
- return -1;
- }
- total += l;
- }
- total += EXTRA_BYTES.length;
- total += partBoundary.length;
- total += EXTRA_BYTES.length;
- total += CRLF_BYTES.length;
- return total;
- }
-}
diff --git a/core/java/com/android/internal/http/multipart/PartBase.java b/core/java/com/android/internal/http/multipart/PartBase.java
deleted file mode 100644
index 876d15d..0000000
--- a/core/java/com/android/internal/http/multipart/PartBase.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/PartBase.java,v 1.5 2004/04/18 23:51:37 jsdever Exp $
- * $Revision: 480424 $
- * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-
-/**
- * Provides setters and getters for the basic Part properties.
- *
- * @author Michael Becke
- */
-public abstract class PartBase extends Part {
-
- /** Name of the file part. */
- private String name;
-
- /** Content type of the file part. */
- private String contentType;
-
- /** Content encoding of the file part. */
- private String charSet;
-
- /** The transfer encoding. */
- private String transferEncoding;
-
- /**
- * Constructor.
- *
- * @param name The name of the part
- * @param contentType The content type, or <code>null</code>
- * @param charSet The character encoding, or <code>null</code>
- * @param transferEncoding The transfer encoding, or <code>null</code>
- */
- public PartBase(String name, String contentType, String charSet, String transferEncoding) {
-
- if (name == null) {
- throw new IllegalArgumentException("Name must not be null");
- }
- this.name = name;
- this.contentType = contentType;
- this.charSet = charSet;
- this.transferEncoding = transferEncoding;
- }
-
- /**
- * Returns the name.
- * @return The name.
- * @see Part#getName()
- */
- @Override
- public String getName() {
- return this.name;
- }
-
- /**
- * Returns the content type of this part.
- * @return String The name.
- */
- @Override
- public String getContentType() {
- return this.contentType;
- }
-
- /**
- * Return the character encoding of this part.
- * @return String The name.
- */
- @Override
- public String getCharSet() {
- return this.charSet;
- }
-
- /**
- * Returns the transfer encoding of this part.
- * @return String The name.
- */
- @Override
- public String getTransferEncoding() {
- return transferEncoding;
- }
-
- /**
- * Sets the character encoding.
- *
- * @param charSet the character encoding, or <code>null</code> to exclude the character
- * encoding header
- */
- public void setCharSet(String charSet) {
- this.charSet = charSet;
- }
-
- /**
- * Sets the content type.
- *
- * @param contentType the content type, or <code>null</code> to exclude the content type header
- */
- public void setContentType(String contentType) {
- this.contentType = contentType;
- }
-
- /**
- * Sets the part name.
- *
- * @param name
- */
- public void setName(String name) {
- if (name == null) {
- throw new IllegalArgumentException("Name must not be null");
- }
- this.name = name;
- }
-
- /**
- * Sets the transfer encoding.
- *
- * @param transferEncoding the transfer encoding, or <code>null</code> to exclude the
- * transfer encoding header
- */
- public void setTransferEncoding(String transferEncoding) {
- this.transferEncoding = transferEncoding;
- }
-
-}
diff --git a/core/java/com/android/internal/http/multipart/PartSource.java b/core/java/com/android/internal/http/multipart/PartSource.java
deleted file mode 100644
index 3740696..0000000
--- a/core/java/com/android/internal/http/multipart/PartSource.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/PartSource.java,v 1.6 2004/04/18 23:51:37 jsdever Exp $
- * $Revision: 480424 $
- * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * An interface for providing access to data when posting MultiPart messages.
- *
- * @see FilePart
- *
- * @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
- *
- * @since 2.0
- */
-public interface PartSource {
-
- /**
- * Gets the number of bytes contained in this source.
- *
- * @return a value >= 0
- */
- long getLength();
-
- /**
- * Gets the name of the file this source represents.
- *
- * @return the fileName used for posting a MultiPart file part
- */
- String getFileName();
-
- /**
- * Gets a new InputStream for reading this source. This method can be
- * called more than once and should therefore return a new stream every
- * time.
- *
- * @return a new InputStream
- *
- * @throws IOException if an error occurs when creating the InputStream
- */
- InputStream createInputStream() throws IOException;
-
-}
diff --git a/core/java/com/android/internal/http/multipart/StringPart.java b/core/java/com/android/internal/http/multipart/StringPart.java
deleted file mode 100644
index c98257e..0000000
--- a/core/java/com/android/internal/http/multipart/StringPart.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/StringPart.java,v 1.11 2004/04/18 23:51:37 jsdever Exp $
- * $Revision: 480424 $
- * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-import java.io.OutputStream;
-import java.io.IOException;
-
-import org.apache.http.util.EncodingUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Simple string parameter for a multipart post
- *
- * @author <a href="mailto:mattalbright@yahoo.com">Matthew Albright</a>
- * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
- * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
- * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
- *
- * @since 2.0
- */
-public class StringPart extends PartBase {
-
- /** Log object for this class. */
- private static final Log LOG = LogFactory.getLog(StringPart.class);
-
- /** Default content encoding of string parameters. */
- public static final String DEFAULT_CONTENT_TYPE = "text/plain";
-
- /** Default charset of string parameters*/
- public static final String DEFAULT_CHARSET = "US-ASCII";
-
- /** Default transfer encoding of string parameters*/
- public static final String DEFAULT_TRANSFER_ENCODING = "8bit";
-
- /** Contents of this StringPart. */
- private byte[] content;
-
- /** The String value of this part. */
- private String value;
-
- /**
- * Constructor.
- *
- * @param name The name of the part
- * @param value the string to post
- * @param charset the charset to be used to encode the string, if <code>null</code>
- * the {@link #DEFAULT_CHARSET default} is used
- */
- public StringPart(String name, String value, String charset) {
-
- super(
- name,
- DEFAULT_CONTENT_TYPE,
- charset == null ? DEFAULT_CHARSET : charset,
- DEFAULT_TRANSFER_ENCODING
- );
- if (value == null) {
- throw new IllegalArgumentException("Value may not be null");
- }
- if (value.indexOf(0) != -1) {
- // See RFC 2048, 2.8. "8bit Data"
- throw new IllegalArgumentException("NULs may not be present in string parts");
- }
- this.value = value;
- }
-
- /**
- * Constructor.
- *
- * @param name The name of the part
- * @param value the string to post
- */
- public StringPart(String name, String value) {
- this(name, value, null);
- }
-
- /**
- * Gets the content in bytes. Bytes are lazily created to allow the charset to be changed
- * after the part is created.
- *
- * @return the content in bytes
- */
- private byte[] getContent() {
- if (content == null) {
- content = EncodingUtils.getBytes(value, getCharSet());
- }
- return content;
- }
-
- /**
- * Writes the data to the given OutputStream.
- * @param out the OutputStream to write to
- * @throws IOException if there is a write error
- */
- @Override
- protected void sendData(OutputStream out) throws IOException {
- LOG.trace("enter sendData(OutputStream)");
- out.write(getContent());
- }
-
- /**
- * Return the length of the data.
- * @return The length of the data.
- * @see Part#lengthOfData()
- */
- @Override
- protected long lengthOfData() {
- LOG.trace("enter lengthOfData()");
- return getContent().length;
- }
-
- /* (non-Javadoc)
- * @see org.apache.commons.httpclient.methods.multipart.BasePart#setCharSet(java.lang.String)
- */
- @Override
- public void setCharSet(String charSet) {
- super.setCharSet(charSet);
- this.content = null;
- }
-
-}
diff --git a/core/java/com/android/internal/logging/AndroidConfig.java b/core/java/com/android/internal/logging/AndroidConfig.java
deleted file mode 100644
index d8be889..0000000
--- a/core/java/com/android/internal/logging/AndroidConfig.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.logging;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Implements the java.util.logging configuration for Android. Activates a log
- * handler that writes to the Android log.
- */
-public class AndroidConfig {
-
- /**
- * This looks a bit weird, but it's the way the logging config works: A
- * named class is instantiated, the constructor is assumed to tweak the
- * configuration, the instance itself is of no interest.
- */
- public AndroidConfig() {
- super();
-
- try {
- Logger.global.addHandler(new AndroidHandler());
- Logger.global.setLevel(Level.ALL);
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
-
-}
diff --git a/core/java/com/android/internal/logging/AndroidHandler.java b/core/java/com/android/internal/logging/AndroidHandler.java
deleted file mode 100644
index a6a4c64..0000000
--- a/core/java/com/android/internal/logging/AndroidHandler.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.logging;
-
-import android.util.Log;
-
-import java.util.logging.Formatter;
-import java.util.logging.Handler;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-import java.util.logging.SimpleFormatter;
-
-/**
- * Implements a {@link java.util.Logger} handler that writes to the Android log. The
- * implementation is rather straightforward. The name of the logger serves as
- * the log tag. Only the log levels need to be converted appropriately. For
- * this purpose, the following mapping is being used:
- *
- * <table>
- * <tr>
- * <th>logger level</th>
- * <th>Android level</th>
- * </tr>
- * <tr>
- * <td>
- * SEVERE
- * </td>
- * <td>
- * ERROR
- * </td>
- * </tr>
- * <tr>
- * <td>
- * WARNING
- * </td>
- * <td>
- * WARN
- * </td>
- * </tr>
- * <tr>
- * <td>
- * INFO
- * </td>
- * <td>
- * INFO
- * </td>
- * </tr>
- * <tr>
- * <td>
- * CONFIG
- * </td>
- * <td>
- * DEBUG
- * </td>
- * </tr>
- * <tr>
- * <td>
- * FINE, FINER, FINEST
- * </td>
- * <td>
- * VERBOSE
- * </td>
- * </tr>
- * </table>
- */
-public class AndroidHandler extends Handler {
- /**
- * Holds the formatter for all Android log handlers.
- */
- private static final Formatter THE_FORMATTER = new SimpleFormatter();
-
- /**
- * Constructs a new instance of the Android log handler.
- */
- public AndroidHandler() {
- setFormatter(THE_FORMATTER);
- }
-
- @Override
- public void close() {
- // No need to close, but must implement abstract method.
- }
-
- @Override
- public void flush() {
- // No need to flush, but must implement abstract method.
- }
-
- @Override
- public void publish(LogRecord record) {
- try {
- int level = getAndroidLevel(record.getLevel());
- String tag = record.getLoggerName();
-
- if (!Log.isLoggable(tag, level)) {
- return;
- }
-
- String msg;
- try {
- msg = getFormatter().format(record);
- } catch (RuntimeException e) {
- Log.e("AndroidHandler", "Error formatting log record", e);
- msg = record.getMessage();
- }
- Log.println(level, tag, msg);
- } catch (RuntimeException e) {
- Log.e("AndroidHandler", "Error publishing log record", e);
- }
- }
-
- /**
- * Converts a {@link java.util.Logger} logging level into an Android one.
- *
- * @param level The {@link java.util.Logger} logging level.
- *
- * @return The resulting Android logging level.
- */
- static int getAndroidLevel(Level level)
- {
- int value = level.intValue();
-
- if (value >= Level.SEVERE.intValue()) {
- return Log.ERROR;
- } else if (value >= Level.WARNING.intValue()) {
- return Log.WARN;
- } else if (value >= Level.INFO.intValue()) {
- return Log.INFO;
- } else if (value >= Level.CONFIG.intValue()) {
- return Log.DEBUG;
- } else {
- return Log.VERBOSE;
- }
- }
-
-}
diff --git a/core/java/com/android/internal/os/AndroidPrintStream.java b/core/java/com/android/internal/os/AndroidPrintStream.java
deleted file mode 100644
index 7f4807a..0000000
--- a/core/java/com/android/internal/os/AndroidPrintStream.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.os;
-
-import android.util.Log;
-
-/**
- * Print stream which log lines using Android's logging system.
- *
- * {@hide}
- */
-class AndroidPrintStream extends LoggingPrintStream {
-
- private final int priority;
- private final String tag;
-
- /**
- * Constructs a new logging print stream.
- *
- * @param priority from {@link android.util.Log}
- * @param tag to log
- */
- public AndroidPrintStream(int priority, String tag) {
- if (tag == null) {
- throw new NullPointerException("tag");
- }
-
- this.priority = priority;
- this.tag = tag;
- }
-
- protected void log(String line) {
- Log.println(priority, tag, line);
- }
-}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.aidl b/core/java/com/android/internal/os/BatteryStatsImpl.aidl
deleted file mode 100644
index 0c26a3c..0000000
--- a/core/java/com/android/internal/os/BatteryStatsImpl.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.os;
-
-parcelable BatteryStatsImpl;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
deleted file mode 100644
index 558a122..0000000
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ /dev/null
@@ -1,1983 +0,0 @@
-/*
- * Copyright (C) 2006-2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.os;
-
-import android.os.BatteryStats;
-import android.os.NetStat;
-import android.os.Parcel;
-import android.os.ParcelFormatException;
-import android.os.Parcelable;
-import android.os.SystemClock;
-import android.util.Log;
-import android.util.SparseArray;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * All information we are collecting about things that can happen that impact
- * battery life. All times are represented in microseconds except where indicated
- * otherwise.
- */
-public final class BatteryStatsImpl extends BatteryStats {
-
- private static final String TAG = "BatteryStatsImpl";
-
- // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
- private static final int MAGIC = 0xBA757475; // 'BATSTATS'
-
- // Current on-disk Parcel version
- private static final int VERSION = 23;
-
- private final File mFile;
- private final File mBackupFile;
-
- /**
- * The statistics we have collected organized by uids.
- */
- final SparseArray<BatteryStatsImpl.Uid> mUidStats =
- new SparseArray<BatteryStatsImpl.Uid>();
-
- // A set of pools of currently active timers. When a timer is queried, we will divide the
- // elapsed time by the number of active timers to arrive at that timer's share of the time.
- // In order to do this, we must refresh each timer whenever the number of active timers
- // changes.
- final ArrayList<Timer> mPartialTimers = new ArrayList<Timer>();
- final ArrayList<Timer> mFullTimers = new ArrayList<Timer>();
- final ArrayList<Timer> mWindowTimers = new ArrayList<Timer>();
- final SparseArray<ArrayList<Timer>> mSensorTimers
- = new SparseArray<ArrayList<Timer>>();
-
- // These are the objects that will want to do something when the device
- // is unplugged from power.
- final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>();
-
- int mStartCount;
-
- long mBatteryUptime;
- long mBatteryLastUptime;
- long mBatteryRealtime;
- long mBatteryLastRealtime;
-
- long mUptime;
- long mUptimeStart;
- long mLastUptime;
- long mRealtime;
- long mRealtimeStart;
- long mLastRealtime;
-
- boolean mScreenOn;
- long mLastScreenOnTimeMillis;
- long mBatteryScreenOnTimeMillis;
- long mPluggedScreenOnTimeMillis;
- /**
- * These provide time bases that discount the time the device is plugged
- * in to power.
- */
- boolean mOnBattery;
- boolean mOnBatteryInternal;
- long mTrackBatteryPastUptime;
- long mTrackBatteryUptimeStart;
- long mTrackBatteryPastRealtime;
- long mTrackBatteryRealtimeStart;
-
- long mUnpluggedBatteryUptime;
- long mUnpluggedBatteryRealtime;
-
- long mLastWriteTime = 0; // Milliseconds
-
- // For debugging
- public BatteryStatsImpl() {
- mFile = mBackupFile = null;
- }
-
- public static interface Unpluggable {
- void unplug(long batteryUptime, long batteryRealtime);
- void plug(long batteryUptime, long batteryRealtime);
- }
-
- /**
- * State for keeping track of timing information.
- */
- public static final class Timer extends BatteryStats.Timer implements Unpluggable {
- final int mType;
- final ArrayList<Timer> mTimerPool;
-
- int mNesting;
-
- int mCount;
- int mLoadedCount;
- int mLastCount;
- int mUnpluggedCount;
-
- // Times are in microseconds for better accuracy when dividing by the
- // lock count, and are in "battery realtime" units.
-
- long mTotalTime;
- long mLoadedTotalTime;
- long mLastTotalTime;
- long mUpdateTime;
-
- /**
- * The value of mTotalTime when unplug() was last called, initially 0.
- */
- long mUnpluggedTotalTime;
-
- Timer(int type, ArrayList<Timer> timerPool,
- ArrayList<Unpluggable> unpluggables, Parcel in) {
- mType = type;
- mTimerPool = timerPool;
- mCount = in.readInt();
- mLoadedCount = in.readInt();
- mLastCount = in.readInt();
- mUnpluggedCount = in.readInt();
- mTotalTime = in.readLong();
- mLoadedTotalTime = in.readLong();
- mLastTotalTime = in.readLong();
- mUpdateTime = in.readLong();
- mUnpluggedTotalTime = in.readLong();
- unpluggables.add(this);
- }
-
- Timer(int type, ArrayList<Timer> timerPool,
- ArrayList<Unpluggable> unpluggables) {
- mType = type;
- mTimerPool = timerPool;
- unpluggables.add(this);
- }
-
- public void writeToParcel(Parcel out, long batteryRealtime) {
- out.writeInt(mCount);
- out.writeInt(mLoadedCount);
- out.writeInt(mLastCount);
- out.writeInt(mUnpluggedCount);
- out.writeLong(computeRunTimeLocked(batteryRealtime));
- out.writeLong(mLoadedTotalTime);
- out.writeLong(mLastTotalTime);
- out.writeLong(mUpdateTime);
- out.writeLong(mUnpluggedTotalTime);
- }
-
- public void unplug(long batteryUptime, long batteryRealtime) {
- mUnpluggedTotalTime = computeRunTimeLocked(batteryRealtime);
- mUnpluggedCount = mCount;
- }
-
- public void plug(long batteryUptime, long batteryRealtime) {
- if (mNesting > 0) {
- mTotalTime = computeRunTimeLocked(batteryRealtime);
- mUpdateTime = batteryRealtime;
- }
- }
-
- /**
- * Writes a possibly null Timer to a Parcel.
- *
- * @param out the Parcel to be written to.
- * @param timer a Timer, or null.
- */
- public static void writeTimerToParcel(Parcel out, Timer timer,
- long batteryRealtime) {
- if (timer == null) {
- out.writeInt(0); // indicates null
- return;
- }
- out.writeInt(1); // indicates non-null
-
- timer.writeToParcel(out, batteryRealtime);
- }
-
- @Override
- public long getTotalTime(long now, int which) {
- long val;
- if (which == STATS_LAST) {
- val = mLastTotalTime;
- } else {
- val = computeRunTimeLocked(now);
- if (which == STATS_UNPLUGGED) {
- val -= mUnpluggedTotalTime;
- } else if (which != STATS_TOTAL) {
- val -= mLoadedTotalTime;
- }
- }
-
- return val;
- }
-
- @Override
- public int getCount(int which) {
- int val;
- if (which == STATS_LAST) {
- val = mLastCount;
- } else {
- val = mCount;
- if (which == STATS_UNPLUGGED) {
- val -= mUnpluggedCount;
- } else if (which != STATS_TOTAL) {
- val -= mLoadedCount;
- }
- }
-
- return val;
- }
-
- public void logState() {
- Log.i("foo", "mNesting=" + mNesting + " mCount=" + mCount
- + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
- + " mUnpluggedCount=" + mUnpluggedCount);
- Log.i("foo", "mTotalTime=" + mTotalTime
- + " mLoadedTotalTime=" + mLoadedTotalTime);
- Log.i("foo", "mLastTotalTime=" + mLastTotalTime
- + " mUpdateTime=" + mUpdateTime);
- }
-
- void startRunningLocked(BatteryStatsImpl stats) {
- if (mNesting++ == 0) {
- mUpdateTime = stats.getBatteryRealtimeLocked(
- SystemClock.elapsedRealtime() * 1000);
- // Accumulate time to all currently active timers before adding
- // this new one to the pool.
- refreshTimersLocked(stats, mTimerPool);
- // Add this timer to the active pool
- mTimerPool.add(this);
- // Increment the count
- mCount++;
- }
- }
-
- void stopRunningLocked(BatteryStatsImpl stats) {
- // Ignore attempt to stop a timer that isn't running
- if (mNesting == 0) {
- return;
- }
- if (--mNesting == 0) {
- // Accumulate time to all active counters, scaled by the total
- // active in the pool, before taking this one out of the pool.
- refreshTimersLocked(stats, mTimerPool);
- // Remove this timer from the active pool
- mTimerPool.remove(this);
- }
- }
-
- // Update the total time for all other running Timers with the same type as this Timer
- // due to a change in timer count
- private static void refreshTimersLocked(final BatteryStatsImpl stats,
- final ArrayList<Timer> pool) {
- final long realtime = SystemClock.elapsedRealtime() * 1000;
- final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
- final int N = pool.size();
- for (int i=N-1; i>= 0; i--) {
- final Timer t = pool.get(i);
- long heldTime = batteryRealtime - t.mUpdateTime;
- if (heldTime > 0) {
- t.mTotalTime += heldTime / N;
- }
- t.mUpdateTime = batteryRealtime;
- }
- }
-
- private long computeRunTimeLocked(long curBatteryRealtime) {
- return mTotalTime + (mNesting > 0
- ? (curBatteryRealtime - mUpdateTime) / mTimerPool.size() : 0);
- }
-
- void writeSummaryFromParcelLocked(Parcel out, long curBatteryUptime) {
- long runTime = computeRunTimeLocked(curBatteryUptime);
- // Divide by 1000 for backwards compatibility
- out.writeLong((runTime + 500) / 1000);
- out.writeLong(((runTime - mLoadedTotalTime) + 500) / 1000);
- out.writeInt(mCount);
- out.writeInt(mCount - mLoadedCount);
- }
-
- void readSummaryFromParcelLocked(Parcel in) {
- // Multiply by 1000 for backwards compatibility
- mTotalTime = mLoadedTotalTime = in.readLong() * 1000;
- mLastTotalTime = in.readLong();
- mCount = mLoadedCount = in.readInt();
- mLastCount = in.readInt();
- mNesting = 0;
- }
- }
-
- public void doUnplug(long batteryUptime, long batteryRealtime) {
- for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
- Uid u = mUidStats.valueAt(iu);
- u.mStartedTcpBytesReceived = NetStat.getUidRxBytes(u.mUid);
- u.mStartedTcpBytesSent = NetStat.getUidTxBytes(u.mUid);
- u.mTcpBytesReceivedAtLastUnplug = u.mCurrentTcpBytesReceived;
- u.mTcpBytesSentAtLastUnplug = u.mCurrentTcpBytesSent;
- }
- for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
- mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime);
- }
- }
-
- public void doPlug(long batteryUptime, long batteryRealtime) {
- for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
- Uid u = mUidStats.valueAt(iu);
- if (u.mStartedTcpBytesReceived >= 0) {
- u.mCurrentTcpBytesReceived = u.computeCurrentTcpBytesReceived();
- u.mStartedTcpBytesReceived = -1;
- }
- if (u.mStartedTcpBytesSent >= 0) {
- u.mCurrentTcpBytesSent = u.computeCurrentTcpBytesSent();
- u.mStartedTcpBytesSent = -1;
- }
- }
- for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
- mUnpluggables.get(i).plug(batteryUptime, batteryRealtime);
- }
- }
-
- public void noteStartGps(int uid) {
- mUidStats.get(uid).noteStartGps();
- }
-
- public void noteStopGps(int uid) {
- mUidStats.get(uid).noteStopGps();
- }
-
- /**
- * When the device screen or battery state changes, update the appropriate "screen on time"
- * counter.
- */
- private void updateScreenOnTimeLocked(boolean screenOn) {
- if (!mScreenOn) {
- Log.w(TAG, "updateScreenOnTime without mScreenOn, ignored");
- return;
- }
- long now = SystemClock.elapsedRealtime();
- long elapsed = now - mLastScreenOnTimeMillis;
- if (mOnBattery) {
- mBatteryScreenOnTimeMillis += elapsed;
- } else {
- mPluggedScreenOnTimeMillis += elapsed;
- }
- if (screenOn) {
- mLastScreenOnTimeMillis = now;
- }
- }
-
- public void noteScreenOnLocked() {
- mScreenOn = true;
- mLastScreenOnTimeMillis = SystemClock.elapsedRealtime();
- }
-
- public void noteScreenOffLocked() {
- if (!mScreenOn) {
- Log.w(TAG, "noteScreenOff without mScreenOn, ignored");
- return;
- }
- updateScreenOnTimeLocked(false);
- mScreenOn = false;
- }
-
- @Override public long getBatteryScreenOnTime() {
- return mBatteryScreenOnTimeMillis;
- }
-
- @Override public long getPluggedScreenOnTime() {
- return mPluggedScreenOnTimeMillis;
- }
-
- @Override public boolean getIsOnBattery() {
- return mOnBattery;
- }
-
- @Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
- return mUidStats;
- }
-
- /**
- * The statistics associated with a particular uid.
- */
- public final class Uid extends BatteryStats.Uid {
-
- final int mUid;
- long mLoadedTcpBytesReceived;
- long mLoadedTcpBytesSent;
- long mCurrentTcpBytesReceived;
- long mCurrentTcpBytesSent;
- long mTcpBytesReceivedAtLastUnplug;
- long mTcpBytesSentAtLastUnplug;
-
- // These are not saved/restored when parcelling, since we want
- // to return from the parcel with a snapshot of the state.
- long mStartedTcpBytesReceived = -1;
- long mStartedTcpBytesSent = -1;
-
- /**
- * The statistics we have collected for this uid's wake locks.
- */
- final HashMap<String, Wakelock> mWakelockStats = new HashMap<String, Wakelock>();
-
- /**
- * The statistics we have collected for this uid's sensor activations.
- */
- final HashMap<Integer, Sensor> mSensorStats = new HashMap<Integer, Sensor>();
-
- /**
- * The statistics we have collected for this uid's processes.
- */
- final HashMap<String, Proc> mProcessStats = new HashMap<String, Proc>();
-
- /**
- * The statistics we have collected for this uid's processes.
- */
- final HashMap<String, Pkg> mPackageStats = new HashMap<String, Pkg>();
-
- public Uid(int uid) {
- mUid = uid;
- }
-
- @Override
- public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
- return mWakelockStats;
- }
-
- @Override
- public Map<Integer, ? extends BatteryStats.Uid.Sensor> getSensorStats() {
- return mSensorStats;
- }
-
- @Override
- public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
- return mProcessStats;
- }
-
- @Override
- public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
- return mPackageStats;
- }
-
- public int getUid() {
- return mUid;
- }
-
- public long getTcpBytesReceived(int which) {
- if (which == STATS_LAST) {
- return mLoadedTcpBytesReceived;
- } else {
- long current = computeCurrentTcpBytesReceived();
- if (which == STATS_UNPLUGGED) {
- current -= mTcpBytesReceivedAtLastUnplug;
- } else if (which == STATS_TOTAL) {
- current += mLoadedTcpBytesReceived;
- }
- return current;
- }
- }
-
- public long computeCurrentTcpBytesReceived() {
- return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0
- ? (NetStat.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0);
- }
-
- public long getTcpBytesSent(int which) {
- if (which == STATS_LAST) {
- return mLoadedTcpBytesSent;
- } else {
- long current = computeCurrentTcpBytesSent();
- if (which == STATS_UNPLUGGED) {
- current -= mTcpBytesSentAtLastUnplug;
- } else if (which == STATS_TOTAL) {
- current += mLoadedTcpBytesSent;
- }
- return current;
- }
- }
-
- public long computeCurrentTcpBytesSent() {
- return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0
- ? (NetStat.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0);
- }
-
- void writeToParcelLocked(Parcel out, long batteryRealtime) {
- out.writeInt(mWakelockStats.size());
- for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) {
- out.writeString(wakelockEntry.getKey());
- Uid.Wakelock wakelock = wakelockEntry.getValue();
- wakelock.writeToParcelLocked(out, batteryRealtime);
- }
-
- out.writeInt(mSensorStats.size());
- for (Map.Entry<Integer, Uid.Sensor> sensorEntry : mSensorStats.entrySet()) {
- out.writeInt(sensorEntry.getKey());
- Uid.Sensor sensor = sensorEntry.getValue();
- sensor.writeToParcelLocked(out, batteryRealtime);
- }
-
- out.writeInt(mProcessStats.size());
- for (Map.Entry<String, Uid.Proc> procEntry : mProcessStats.entrySet()) {
- out.writeString(procEntry.getKey());
- Uid.Proc proc = procEntry.getValue();
- proc.writeToParcelLocked(out);
- }
-
- out.writeInt(mPackageStats.size());
- for (Map.Entry<String, Uid.Pkg> pkgEntry : mPackageStats.entrySet()) {
- out.writeString(pkgEntry.getKey());
- Uid.Pkg pkg = pkgEntry.getValue();
- pkg.writeToParcelLocked(out);
- }
-
- out.writeLong(mLoadedTcpBytesReceived);
- out.writeLong(mLoadedTcpBytesSent);
- out.writeLong(computeCurrentTcpBytesReceived());
- out.writeLong(computeCurrentTcpBytesSent());
- out.writeLong(mTcpBytesReceivedAtLastUnplug);
- out.writeLong(mTcpBytesSentAtLastUnplug);
- }
-
- void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
- int numWakelocks = in.readInt();
- mWakelockStats.clear();
- for (int j = 0; j < numWakelocks; j++) {
- String wakelockName = in.readString();
- Uid.Wakelock wakelock = new Wakelock();
- wakelock.readFromParcelLocked(unpluggables, in);
- mWakelockStats.put(wakelockName, wakelock);
- }
-
- int numSensors = in.readInt();
- mSensorStats.clear();
- for (int k = 0; k < numSensors; k++) {
- int sensorNumber = in.readInt();
- Uid.Sensor sensor = new Sensor(sensorNumber);
- sensor.readFromParcelLocked(mUnpluggables, in);
- mSensorStats.put(sensorNumber, sensor);
- }
-
- int numProcs = in.readInt();
- mProcessStats.clear();
- for (int k = 0; k < numProcs; k++) {
- String processName = in.readString();
- Uid.Proc proc = new Proc();
- proc.readFromParcelLocked(in);
- mProcessStats.put(processName, proc);
- }
-
- int numPkgs = in.readInt();
- mPackageStats.clear();
- for (int l = 0; l < numPkgs; l++) {
- String packageName = in.readString();
- Uid.Pkg pkg = new Pkg();
- pkg.readFromParcelLocked(in);
- mPackageStats.put(packageName, pkg);
- }
-
- mLoadedTcpBytesReceived = in.readLong();
- mLoadedTcpBytesSent = in.readLong();
- mCurrentTcpBytesReceived = in.readLong();
- mCurrentTcpBytesSent = in.readLong();
- mTcpBytesReceivedAtLastUnplug = in.readLong();
- mTcpBytesSentAtLastUnplug = in.readLong();
- }
-
- /**
- * The statistics associated with a particular wake lock.
- */
- public final class Wakelock extends BatteryStats.Uid.Wakelock {
- /**
- * How long (in ms) this uid has been keeping the device partially awake.
- */
- Timer mTimerPartial;
-
- /**
- * How long (in ms) this uid has been keeping the device fully awake.
- */
- Timer mTimerFull;
-
- /**
- * How long (in ms) this uid has had a window keeping the device awake.
- */
- Timer mTimerWindow;
-
- /**
- * Reads a possibly null Timer from a Parcel. The timer is associated with the
- * proper timer pool from the given BatteryStatsImpl object.
- *
- * @param in the Parcel to be read from.
- * return a new Timer, or null.
- */
- private Timer readTimerFromParcel(int type, ArrayList<Timer> pool,
- ArrayList<Unpluggable> unpluggables, Parcel in) {
- if (in.readInt() == 0) {
- return null;
- }
-
- return new Timer(type, pool, unpluggables, in);
- }
-
- void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
- mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL,
- mPartialTimers, unpluggables, in);
- mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL,
- mFullTimers, unpluggables, in);
- mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW,
- mWindowTimers, unpluggables, in);
- }
-
- void writeToParcelLocked(Parcel out, long batteryRealtime) {
- Timer.writeTimerToParcel(out, mTimerPartial, batteryRealtime);
- Timer.writeTimerToParcel(out, mTimerFull, batteryRealtime);
- Timer.writeTimerToParcel(out, mTimerWindow, batteryRealtime);
- }
-
- @Override
- public Timer getWakeTime(int type) {
- switch (type) {
- case WAKE_TYPE_FULL: return mTimerFull;
- case WAKE_TYPE_PARTIAL: return mTimerPartial;
- case WAKE_TYPE_WINDOW: return mTimerWindow;
- default: throw new IllegalArgumentException("type = " + type);
- }
- }
- }
-
- public final class Sensor extends BatteryStats.Uid.Sensor {
- final int mHandle;
- Timer mTimer;
-
- public Sensor(int handle) {
- mHandle = handle;
- }
-
- private Timer readTimerFromParcel(ArrayList<Unpluggable> unpluggables,
- Parcel in) {
- if (in.readInt() == 0) {
- return null;
- }
-
- ArrayList<Timer> pool = mSensorTimers.get(mHandle);
- if (pool == null) {
- pool = new ArrayList<Timer>();
- mSensorTimers.put(mHandle, pool);
- }
- return new Timer(0, pool, unpluggables, in);
- }
-
- void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
- mTimer = readTimerFromParcel(unpluggables, in);
- }
-
- void writeToParcelLocked(Parcel out, long batteryRealtime) {
- Timer.writeTimerToParcel(out, mTimer, batteryRealtime);
- }
-
- @Override
- public Timer getSensorTime() {
- return mTimer;
- }
-
- public int getHandle() {
- return mHandle;
- }
- }
-
- /**
- * The statistics associated with a particular process.
- */
- public final class Proc extends BatteryStats.Uid.Proc implements Unpluggable {
- /**
- * Total time (in 1/100 sec) spent executing in user code.
- */
- long mUserTime;
-
- /**
- * Total time (in 1/100 sec) spent executing in kernel code.
- */
- long mSystemTime;
-
- /**
- * Number of times the process has been started.
- */
- int mStarts;
-
- /**
- * The amount of user time loaded from a previous save.
- */
- long mLoadedUserTime;
-
- /**
- * The amount of system time loaded from a previous save.
- */
- long mLoadedSystemTime;
-
- /**
- * The number of times the process has started from a previous save.
- */
- int mLoadedStarts;
-
- /**
- * The amount of user time loaded from the previous run.
- */
- long mLastUserTime;
-
- /**
- * The amount of system time loaded from the previous run.
- */
- long mLastSystemTime;
-
- /**
- * The number of times the process has started from the previous run.
- */
- int mLastStarts;
-
- /**
- * The amount of user time when last unplugged.
- */
- long mUnpluggedUserTime;
-
- /**
- * The amount of system time when last unplugged.
- */
- long mUnpluggedSystemTime;
-
- /**
- * The number of times the process has started before unplugged.
- */
- int mUnpluggedStarts;
-
- Proc() {
- mUnpluggables.add(this);
- }
-
- public void unplug(long batteryUptime, long batteryRealtime) {
- mUnpluggedUserTime = mUserTime;
- mUnpluggedSystemTime = mSystemTime;
- mUnpluggedStarts = mStarts;
- }
-
- public void plug(long batteryUptime, long batteryRealtime) {
- }
-
- void writeToParcelLocked(Parcel out) {
- out.writeLong(mUserTime);
- out.writeLong(mSystemTime);
- out.writeInt(mStarts);
- out.writeLong(mLoadedUserTime);
- out.writeLong(mLoadedSystemTime);
- out.writeInt(mLoadedStarts);
- out.writeLong(mLastUserTime);
- out.writeLong(mLastSystemTime);
- out.writeInt(mLastStarts);
- out.writeLong(mUnpluggedUserTime);
- out.writeLong(mUnpluggedSystemTime);
- out.writeInt(mUnpluggedStarts);
- }
-
- void readFromParcelLocked(Parcel in) {
- mUserTime = in.readLong();
- mSystemTime = in.readLong();
- mStarts = in.readInt();
- mLoadedUserTime = in.readLong();
- mLoadedSystemTime = in.readLong();
- mLoadedStarts = in.readInt();
- mLastUserTime = in.readLong();
- mLastSystemTime = in.readLong();
- mLastStarts = in.readInt();
- mUnpluggedUserTime = in.readLong();
- mUnpluggedSystemTime = in.readLong();
- mUnpluggedStarts = in.readInt();
- }
-
- public BatteryStatsImpl getBatteryStats() {
- return BatteryStatsImpl.this;
- }
-
- public void addCpuTimeLocked(int utime, int stime) {
- mUserTime += utime;
- mSystemTime += stime;
- }
-
- public void incStartsLocked() {
- mStarts++;
- }
-
- @Override
- public long getUserTime(int which) {
- long val;
- if (which == STATS_LAST) {
- val = mLastUserTime;
- } else {
- val = mUserTime;
- if (which == STATS_CURRENT) {
- val -= mLoadedUserTime;
- } else if (which == STATS_UNPLUGGED) {
- val -= mUnpluggedUserTime;
- }
- }
- return val;
- }
-
- @Override
- public long getSystemTime(int which) {
- long val;
- if (which == STATS_LAST) {
- val = mLastSystemTime;
- } else {
- val = mSystemTime;
- if (which == STATS_CURRENT) {
- val -= mLoadedSystemTime;
- } else if (which == STATS_UNPLUGGED) {
- val -= mUnpluggedSystemTime;
- }
- }
- return val;
- }
-
- @Override
- public int getStarts(int which) {
- int val;
- if (which == STATS_LAST) {
- val = mLastStarts;
- } else {
- val = mStarts;
- if (which == STATS_CURRENT) {
- val -= mLoadedStarts;
- } else if (which == STATS_UNPLUGGED) {
- val -= mUnpluggedStarts;
- }
- }
- return val;
- }
- }
-
- /**
- * The statistics associated with a particular package.
- */
- public final class Pkg extends BatteryStats.Uid.Pkg implements Unpluggable {
- /**
- * Number of times this package has done something that could wake up the
- * device from sleep.
- */
- int mWakeups;
-
- /**
- * Number of things that could wake up the device loaded from a
- * previous save.
- */
- int mLoadedWakeups;
-
- /**
- * Number of things that could wake up the device as of the
- * last run.
- */
- int mLastWakeups;
-
- /**
- * Number of things that could wake up the device as of the
- * last run.
- */
- int mUnpluggedWakeups;
-
- /**
- * The statics we have collected for this package's services.
- */
- final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>();
-
- Pkg() {
- mUnpluggables.add(this);
- }
-
- public void unplug(long batteryUptime, long batteryRealtime) {
- mUnpluggedWakeups = mWakeups;
- }
-
- public void plug(long batteryUptime, long batteryRealtime) {
- }
-
- void readFromParcelLocked(Parcel in) {
- mWakeups = in.readInt();
- mLoadedWakeups = in.readInt();
- mLastWakeups = in.readInt();
- mUnpluggedWakeups = in.readInt();
-
- int numServs = in.readInt();
- mServiceStats.clear();
- for (int m = 0; m < numServs; m++) {
- String serviceName = in.readString();
- Uid.Pkg.Serv serv = new Serv();
- mServiceStats.put(serviceName, serv);
-
- serv.readFromParcelLocked(in);
- }
- }
-
- void writeToParcelLocked(Parcel out) {
- out.writeInt(mWakeups);
- out.writeInt(mLoadedWakeups);
- out.writeInt(mLastWakeups);
- out.writeInt(mUnpluggedWakeups);
-
- out.writeInt(mServiceStats.size());
- for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) {
- out.writeString(servEntry.getKey());
- Uid.Pkg.Serv serv = servEntry.getValue();
-
- serv.writeToParcelLocked(out);
- }
- }
-
- @Override
- public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
- return mServiceStats;
- }
-
- @Override
- public int getWakeups(int which) {
- int val;
- if (which == STATS_LAST) {
- val = mLastWakeups;
- } else {
- val = mWakeups;
- if (which == STATS_CURRENT) {
- val -= mLoadedWakeups;
- } else if (which == STATS_UNPLUGGED) {
- val -= mUnpluggedWakeups;
- }
- }
-
- return val;
- }
-
- /**
- * The statistics associated with a particular service.
- */
- public final class Serv extends BatteryStats.Uid.Pkg.Serv implements Unpluggable {
- /**
- * Total time (ms in battery uptime) the service has been left started.
- */
- long mStartTime;
-
- /**
- * If service has been started and not yet stopped, this is
- * when it was started.
- */
- long mRunningSince;
-
- /**
- * True if we are currently running.
- */
- boolean mRunning;
-
- /**
- * Total number of times startService() has been called.
- */
- int mStarts;
-
- /**
- * Total time (ms in battery uptime) the service has been left launched.
- */
- long mLaunchedTime;
-
- /**
- * If service has been launched and not yet exited, this is
- * when it was launched (ms in battery uptime).
- */
- long mLaunchedSince;
-
- /**
- * True if we are currently launched.
- */
- boolean mLaunched;
-
- /**
- * Total number times the service has been launched.
- */
- int mLaunches;
-
- /**
- * The amount of time spent started loaded from a previous save
- * (ms in battery uptime).
- */
- long mLoadedStartTime;
-
- /**
- * The number of starts loaded from a previous save.
- */
- int mLoadedStarts;
-
- /**
- * The number of launches loaded from a previous save.
- */
- int mLoadedLaunches;
-
- /**
- * The amount of time spent started as of the last run (ms
- * in battery uptime).
- */
- long mLastStartTime;
-
- /**
- * The number of starts as of the last run.
- */
- int mLastStarts;
-
- /**
- * The number of launches as of the last run.
- */
- int mLastLaunches;
-
- /**
- * The amount of time spent started when last unplugged (ms
- * in battery uptime).
- */
- long mUnpluggedStartTime;
-
- /**
- * The number of starts when last unplugged.
- */
- int mUnpluggedStarts;
-
- /**
- * The number of launches when last unplugged.
- */
- int mUnpluggedLaunches;
-
- Serv() {
- mUnpluggables.add(this);
- }
-
- public void unplug(long batteryUptime, long batteryRealtime) {
- mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime);
- mUnpluggedStarts = mStarts;
- mUnpluggedLaunches = mLaunches;
- }
-
- public void plug(long batteryUptime, long batteryRealtime) {
- }
-
- void readFromParcelLocked(Parcel in) {
- mStartTime = in.readLong();
- mRunningSince = in.readLong();
- mRunning = in.readInt() != 0;
- mStarts = in.readInt();
- mLaunchedTime = in.readLong();
- mLaunchedSince = in.readLong();
- mLaunched = in.readInt() != 0;
- mLaunches = in.readInt();
- mLoadedStartTime = in.readLong();
- mLoadedStarts = in.readInt();
- mLoadedLaunches = in.readInt();
- mLastStartTime = in.readLong();
- mLastStarts = in.readInt();
- mLastLaunches = in.readInt();
- mUnpluggedStartTime = in.readLong();
- mUnpluggedStarts = in.readInt();
- mUnpluggedLaunches = in.readInt();
- }
-
- void writeToParcelLocked(Parcel out) {
- out.writeLong(mStartTime);
- out.writeLong(mRunningSince);
- out.writeInt(mRunning ? 1 : 0);
- out.writeInt(mStarts);
- out.writeLong(mLaunchedTime);
- out.writeLong(mLaunchedSince);
- out.writeInt(mLaunched ? 1 : 0);
- out.writeInt(mLaunches);
- out.writeLong(mLoadedStartTime);
- out.writeInt(mLoadedStarts);
- out.writeInt(mLoadedLaunches);
- out.writeLong(mLastStartTime);
- out.writeInt(mLastStarts);
- out.writeInt(mLastLaunches);
- out.writeLong(mUnpluggedStartTime);
- out.writeInt(mUnpluggedStarts);
- out.writeInt(mUnpluggedLaunches);
- }
-
- long getLaunchTimeToNowLocked(long batteryUptime) {
- if (!mLaunched) return mLaunchedTime;
- return mLaunchedTime + batteryUptime - mLaunchedSince;
- }
-
- long getStartTimeToNowLocked(long batteryUptime) {
- if (!mRunning) return mStartTime;
- return mStartTime + batteryUptime - mRunningSince;
- }
-
- public void startLaunchedLocked() {
- if (!mLaunched) {
- mLaunches++;
- mLaunchedSince = getBatteryUptimeLocked();
- mLaunched = true;
- }
- }
-
- public void stopLaunchedLocked() {
- if (mLaunched) {
- long time = getBatteryUptimeLocked() - mLaunchedSince;
- if (time > 0) {
- mLaunchedTime += time;
- } else {
- mLaunches--;
- }
- mLaunched = false;
- }
- }
-
- public void startRunningLocked() {
- if (!mRunning) {
- mStarts++;
- mRunningSince = getBatteryUptimeLocked();
- mRunning = true;
- }
- }
-
- public void stopRunningLocked() {
- if (mRunning) {
- long time = getBatteryUptimeLocked() - mRunningSince;
- if (time > 0) {
- mStartTime += time;
- } else {
- mStarts--;
- }
- mRunning = false;
- }
- }
-
- public BatteryStatsImpl getBatteryStats() {
- return BatteryStatsImpl.this;
- }
-
- @Override
- public int getLaunches(int which) {
- int val;
-
- if (which == STATS_LAST) {
- val = mLastLaunches;
- } else {
- val = mLaunches;
- if (which == STATS_CURRENT) {
- val -= mLoadedLaunches;
- } else if (which == STATS_UNPLUGGED) {
- val -= mUnpluggedLaunches;
- }
- }
-
- return val;
- }
-
- @Override
- public long getStartTime(long now, int which) {
- long val;
- if (which == STATS_LAST) {
- val = mLastStartTime;
- } else {
- val = getStartTimeToNowLocked(now);
- if (which == STATS_CURRENT) {
- val -= mLoadedStartTime;
- } else if (which == STATS_UNPLUGGED) {
- val -= mUnpluggedStartTime;
- }
- }
-
- return val;
- }
-
- @Override
- public int getStarts(int which) {
- int val;
- if (which == STATS_LAST) {
- val = mLastStarts;
- } else {
- val = mStarts;
- if (which == STATS_CURRENT) {
- val -= mLoadedStarts;
- } else if (which == STATS_UNPLUGGED) {
- val -= mUnpluggedStarts;
- }
- }
-
- return val;
- }
- }
-
- public BatteryStatsImpl getBatteryStats() {
- return BatteryStatsImpl.this;
- }
-
- public void incWakeupsLocked() {
- mWakeups++;
- }
-
- final Serv newServiceStatsLocked() {
- return new Serv();
- }
- }
-
- /**
- * Retrieve the statistics object for a particular process, creating
- * if needed.
- */
- public Proc getProcessStatsLocked(String name) {
- Proc ps = mProcessStats.get(name);
- if (ps == null) {
- ps = new Proc();
- mProcessStats.put(name, ps);
- }
-
- return ps;
- }
-
- /**
- * Retrieve the statistics object for a particular service, creating
- * if needed.
- */
- public Pkg getPackageStatsLocked(String name) {
- Pkg ps = mPackageStats.get(name);
- if (ps == null) {
- ps = new Pkg();
- mPackageStats.put(name, ps);
- }
-
- return ps;
- }
-
- /**
- * Retrieve the statistics object for a particular service, creating
- * if needed.
- */
- public Pkg.Serv getServiceStatsLocked(String pkg, String serv) {
- Pkg ps = getPackageStatsLocked(pkg);
- Pkg.Serv ss = ps.mServiceStats.get(serv);
- if (ss == null) {
- ss = ps.newServiceStatsLocked();
- ps.mServiceStats.put(serv, ss);
- }
-
- return ss;
- }
-
- public Timer getWakeTimerLocked(String name, int type) {
- Wakelock wl = mWakelockStats.get(name);
- if (wl == null) {
- wl = new Wakelock();
- mWakelockStats.put(name, wl);
- }
- Timer t = null;
- switch (type) {
- case WAKE_TYPE_PARTIAL:
- t = wl.mTimerPartial;
- if (t == null) {
- t = new Timer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables);
- wl.mTimerPartial = t;
- }
- return t;
- case WAKE_TYPE_FULL:
- t = wl.mTimerFull;
- if (t == null) {
- t = new Timer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables);
- wl.mTimerFull = t;
- }
- return t;
- case WAKE_TYPE_WINDOW:
- t = wl.mTimerWindow;
- if (t == null) {
- t = new Timer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables);
- wl.mTimerWindow = t;
- }
- return t;
- default:
- throw new IllegalArgumentException("type=" + type);
- }
- }
-
- public Timer getSensorTimerLocked(int sensor, boolean create) {
- Sensor se = mSensorStats.get(sensor);
- if (se == null) {
- if (!create) {
- return null;
- }
- se = new Sensor(sensor);
- mSensorStats.put(sensor, se);
- }
- Timer t = se.mTimer;
- if (t != null) {
- return t;
- }
- ArrayList<Timer> timers = mSensorTimers.get(sensor);
- if (timers == null) {
- timers = new ArrayList<Timer>();
- mSensorTimers.put(sensor, timers);
- }
- t = new Timer(BatteryStats.SENSOR, timers, mUnpluggables);
- se.mTimer = t;
- return t;
- }
-
- public void noteStartWakeLocked(String name, int type) {
- Timer t = getWakeTimerLocked(name, type);
- if (t != null) {
- t.startRunningLocked(BatteryStatsImpl.this);
- }
- }
-
- public void noteStopWakeLocked(String name, int type) {
- Timer t = getWakeTimerLocked(name, type);
- if (t != null) {
- t.stopRunningLocked(BatteryStatsImpl.this);
- }
- }
-
- public void noteStartSensor(int sensor) {
- Timer t = getSensorTimerLocked(sensor, true);
- if (t != null) {
- t.startRunningLocked(BatteryStatsImpl.this);
- }
- }
-
- public void noteStopSensor(int sensor) {
- // Don't create a timer if one doesn't already exist
- Timer t = getSensorTimerLocked(sensor, false);
- if (t != null) {
- t.stopRunningLocked(BatteryStatsImpl.this);
- }
- }
-
- public void noteStartGps() {
- Timer t = getSensorTimerLocked(Sensor.GPS, true);
- if (t != null) {
- t.startRunningLocked(BatteryStatsImpl.this);
- }
- }
-
- public void noteStopGps() {
- Timer t = getSensorTimerLocked(Sensor.GPS, false);
- if (t != null) {
- t.stopRunningLocked(BatteryStatsImpl.this);
- }
- }
-
- public BatteryStatsImpl getBatteryStats() {
- return BatteryStatsImpl.this;
- }
- }
-
- public BatteryStatsImpl(String filename) {
- mFile = new File(filename);
- mBackupFile = new File(filename + ".bak");
- mStartCount++;
- mOnBattery = mOnBatteryInternal = false;
- mTrackBatteryPastUptime = 0;
- mTrackBatteryPastRealtime = 0;
- mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000;
- mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000;
- mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart);
- mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart);
- }
-
- public BatteryStatsImpl(Parcel p) {
- mFile = mBackupFile = null;
- readFromParcel(p);
- }
-
- @Override
- public int getStartCount() {
- return mStartCount;
- }
-
- public boolean isOnBattery() {
- return mOnBattery;
- }
-
- public void setOnBattery(boolean onBattery) {
- synchronized(this) {
- if (mOnBattery != onBattery) {
- if (mScreenOn) {
- updateScreenOnTimeLocked(true);
- }
-
- mOnBattery = mOnBatteryInternal = onBattery;
-
- long uptime = SystemClock.uptimeMillis() * 1000;
- long mSecRealtime = SystemClock.elapsedRealtime();
- long realtime = mSecRealtime * 1000;
- if (onBattery) {
- mTrackBatteryUptimeStart = uptime;
- mTrackBatteryRealtimeStart = realtime;
- mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime);
- mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime);
- doUnplug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
- } else {
- mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart;
- mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart;
- doPlug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
- }
- if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) {
- if (mFile != null) {
- writeLocked();
- }
- }
- }
- }
- }
-
- public long getAwakeTimeBattery() {
- return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
- }
-
- public long getAwakeTimePlugged() {
- return (SystemClock.uptimeMillis() * 1000) - getAwakeTimeBattery();
- }
-
- @Override
- public long computeUptime(long curTime, int which) {
- switch (which) {
- case STATS_TOTAL: return mUptime + (curTime-mUptimeStart);
- case STATS_LAST: return mLastUptime;
- case STATS_CURRENT: return (curTime-mUptimeStart);
- case STATS_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart);
- }
- return 0;
- }
-
- @Override
- public long computeRealtime(long curTime, int which) {
- switch (which) {
- case STATS_TOTAL: return mRealtime + (curTime-mRealtimeStart);
- case STATS_LAST: return mLastRealtime;
- case STATS_CURRENT: return (curTime-mRealtimeStart);
- case STATS_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart);
- }
- return 0;
- }
-
- @Override
- public long computeBatteryUptime(long curTime, int which) {
- long uptime = getBatteryUptime(curTime);
- switch (which) {
- case STATS_TOTAL:
- return mBatteryUptime + uptime;
- case STATS_LAST:
- return mBatteryLastUptime;
- case STATS_CURRENT:
- return uptime;
- case STATS_UNPLUGGED:
- return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime;
- }
- return 0;
- }
-
- @Override
- public long computeBatteryRealtime(long curTime, int which) {
- switch (which) {
- case STATS_TOTAL:
- return mBatteryRealtime + getBatteryRealtimeLocked(curTime);
- case STATS_LAST:
- return mBatteryLastRealtime;
- case STATS_CURRENT:
- return getBatteryRealtimeLocked(curTime);
- case STATS_UNPLUGGED:
- return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime;
- }
- return 0;
- }
-
- long getBatteryUptimeLocked(long curTime) {
- long time = mTrackBatteryPastUptime;
- if (mOnBatteryInternal) {
- time += curTime - mTrackBatteryUptimeStart;
- }
- return time;
- }
-
- long getBatteryUptimeLocked() {
- return getBatteryUptime(SystemClock.uptimeMillis() * 1000);
- }
-
- @Override
- public long getBatteryUptime(long curTime) {
- return getBatteryUptimeLocked(curTime);
- }
-
- long getBatteryRealtimeLocked(long curTime) {
- long time = mTrackBatteryPastRealtime;
- if (mOnBatteryInternal) {
- time += curTime - mTrackBatteryRealtimeStart;
- }
- return time;
- }
-
- @Override
- public long getBatteryRealtime(long curTime) {
- return getBatteryRealtimeLocked(curTime);
- }
-
- /**
- * Retrieve the statistics object for a particular uid, creating if needed.
- */
- public Uid getUidStatsLocked(int uid) {
- Uid u = mUidStats.get(uid);
- if (u == null) {
- u = new Uid(uid);
- mUidStats.put(uid, u);
- }
- return u;
- }
-
- /**
- * Remove the statistics object for a particular uid.
- */
- public void removeUidStatsLocked(int uid) {
- mUidStats.remove(uid);
- }
-
- /**
- * Retrieve the statistics object for a particular process, creating
- * if needed.
- */
- public Uid.Proc getProcessStatsLocked(int uid, String name) {
- Uid u = getUidStatsLocked(uid);
- return u.getProcessStatsLocked(name);
- }
-
- /**
- * Retrieve the statistics object for a particular process, creating
- * if needed.
- */
- public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
- Uid u = getUidStatsLocked(uid);
- return u.getPackageStatsLocked(pkg);
- }
-
- /**
- * Retrieve the statistics object for a particular service, creating
- * if needed.
- */
- public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
- Uid u = getUidStatsLocked(uid);
- return u.getServiceStatsLocked(pkg, name);
- }
-
- public void writeLocked() {
- if ((mFile == null) || (mBackupFile == null)) {
- Log.w("BatteryStats", "writeLocked: no file associated with this instance");
- return;
- }
-
- // Keep the old file around until we know the new one has
- // been successfully written.
- if (mFile.exists()) {
- if (mBackupFile.exists()) {
- mBackupFile.delete();
- }
- mFile.renameTo(mBackupFile);
- }
-
- try {
- FileOutputStream stream = new FileOutputStream(mFile);
- Parcel out = Parcel.obtain();
- writeSummaryToParcel(out);
- stream.write(out.marshall());
- out.recycle();
-
- stream.flush();
- stream.close();
- mBackupFile.delete();
-
- mLastWriteTime = SystemClock.elapsedRealtime();
- } catch (IOException e) {
- Log.e("BatteryStats", "Error writing battery statistics", e);
- }
- }
-
- static byte[] readFully(FileInputStream stream) throws java.io.IOException {
- int pos = 0;
- int avail = stream.available();
- byte[] data = new byte[avail];
- while (true) {
- int amt = stream.read(data, pos, data.length-pos);
- //Log.i("foo", "Read " + amt + " bytes at " + pos
- // + " of avail " + data.length);
- if (amt <= 0) {
- //Log.i("foo", "**** FINISHED READING: pos=" + pos
- // + " len=" + data.length);
- return data;
- }
- pos += amt;
- avail = stream.available();
- if (avail > data.length-pos) {
- byte[] newData = new byte[pos+avail];
- System.arraycopy(data, 0, newData, 0, pos);
- data = newData;
- }
- }
- }
-
- public void readLocked() {
- if ((mFile == null) || (mBackupFile == null)) {
- Log.w("BatteryStats", "readLocked: no file associated with this instance");
- return;
- }
-
- mUidStats.clear();
-
- FileInputStream stream = null;
- if (mBackupFile.exists()) {
- try {
- stream = new FileInputStream(mBackupFile);
- } catch (java.io.IOException e) {
- // We'll try for the normal settings file.
- }
- }
-
- try {
- if (stream == null) {
- if (!mFile.exists()) {
- return;
- }
- stream = new FileInputStream(mFile);
- }
-
- byte[] raw = readFully(stream);
- Parcel in = Parcel.obtain();
- in.unmarshall(raw, 0, raw.length);
- in.setDataPosition(0);
- stream.close();
-
- readSummaryFromParcel(in);
- } catch(java.io.IOException e) {
- Log.e("BatteryStats", "Error reading battery statistics", e);
- }
- }
-
- public int describeContents() {
- return 0;
- }
-
- private void readSummaryFromParcel(Parcel in) {
- final int version = in.readInt();
- if (version != VERSION) {
- Log.w("BatteryStats", "readFromParcel: version got " + version
- + ", expected " + VERSION + "; erasing old stats");
- return;
- }
-
- mStartCount = in.readInt();
- mBatteryUptime = in.readLong();
- mBatteryLastUptime = in.readLong();
- mBatteryRealtime = in.readLong();
- mBatteryLastRealtime = in.readLong();
- mUptime = in.readLong();
- mLastUptime = in.readLong();
- mRealtime = in.readLong();
- mLastRealtime = in.readLong();
- mStartCount++;
-
- mBatteryScreenOnTimeMillis = in.readLong();
- mPluggedScreenOnTimeMillis = in.readLong();
- mScreenOn = false;
-
- final int NU = in.readInt();
- for (int iu = 0; iu < NU; iu++) {
- int uid = in.readInt();
- Uid u = new Uid(uid);
- mUidStats.put(uid, u);
-
- int NW = in.readInt();
- for (int iw = 0; iw < NW; iw++) {
- String wlName = in.readString();
- if (in.readInt() != 0) {
- u.getWakeTimerLocked(wlName, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
- }
- if (in.readInt() != 0) {
- u.getWakeTimerLocked(wlName, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
- }
- if (in.readInt() != 0) {
- u.getWakeTimerLocked(wlName, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
- }
- }
-
- int NP = in.readInt();
- for (int is = 0; is < NP; is++) {
- int seNumber = in.readInt();
- if (in.readInt() != 0) {
- u.getSensorTimerLocked(seNumber, true)
- .readSummaryFromParcelLocked(in);
- }
- }
-
- NP = in.readInt();
- for (int ip = 0; ip < NP; ip++) {
- String procName = in.readString();
- Uid.Proc p = u.getProcessStatsLocked(procName);
- p.mUserTime = p.mLoadedUserTime = in.readLong();
- p.mLastUserTime = in.readLong();
- p.mSystemTime = p.mLoadedSystemTime = in.readLong();
- p.mLastSystemTime = in.readLong();
- p.mStarts = p.mLoadedStarts = in.readInt();
- p.mLastStarts = in.readInt();
- }
-
- NP = in.readInt();
- for (int ip = 0; ip < NP; ip++) {
- String pkgName = in.readString();
- Uid.Pkg p = u.getPackageStatsLocked(pkgName);
- p.mWakeups = p.mLoadedWakeups = in.readInt();
- p.mLastWakeups = in.readInt();
- final int NS = in.readInt();
- for (int is = 0; is < NS; is++) {
- String servName = in.readString();
- Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName);
- s.mStartTime = s.mLoadedStartTime = in.readLong();
- s.mLastStartTime = in.readLong();
- s.mStarts = s.mLoadedStarts = in.readInt();
- s.mLastStarts = in.readInt();
- s.mLaunches = s.mLoadedLaunches = in.readInt();
- s.mLastLaunches = in.readInt();
- }
- }
-
- u.mLoadedTcpBytesReceived = in.readLong();
- u.mLoadedTcpBytesSent = in.readLong();
- }
- }
-
- /**
- * Writes a summary of the statistics to a Parcel, in a format suitable to be written to
- * disk. This format does not allow a lossless round-trip.
- *
- * @param out the Parcel to be written to.
- */
- public void writeSummaryToParcel(Parcel out) {
- final long NOW = getBatteryUptimeLocked();
- final long NOW_SYS = SystemClock.uptimeMillis() * 1000;
- final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000;
-
- out.writeInt(VERSION);
-
- out.writeInt(mStartCount);
- out.writeLong(computeBatteryUptime(NOW_SYS, STATS_TOTAL));
- out.writeLong(computeBatteryUptime(NOW_SYS, STATS_CURRENT));
- out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_TOTAL));
- out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_CURRENT));
- out.writeLong(computeUptime(NOW_SYS, STATS_TOTAL));
- out.writeLong(computeUptime(NOW_SYS, STATS_CURRENT));
- out.writeLong(computeRealtime(NOWREAL_SYS, STATS_TOTAL));
- out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT));
-
- out.writeLong(mBatteryScreenOnTimeMillis);
- out.writeLong(mPluggedScreenOnTimeMillis);
-
- final int NU = mUidStats.size();
- out.writeInt(NU);
- for (int iu = 0; iu < NU; iu++) {
- out.writeInt(mUidStats.keyAt(iu));
- Uid u = mUidStats.valueAt(iu);
-
- int NW = u.mWakelockStats.size();
- out.writeInt(NW);
- if (NW > 0) {
- for (Map.Entry<String, BatteryStatsImpl.Uid.Wakelock> ent
- : u.mWakelockStats.entrySet()) {
- out.writeString(ent.getKey());
- Uid.Wakelock wl = ent.getValue();
- if (wl.mTimerFull != null) {
- out.writeInt(1);
- wl.mTimerFull.writeSummaryFromParcelLocked(out, NOW);
- } else {
- out.writeInt(0);
- }
- if (wl.mTimerPartial != null) {
- out.writeInt(1);
- wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOW);
- } else {
- out.writeInt(0);
- }
- if (wl.mTimerWindow != null) {
- out.writeInt(1);
- wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOW);
- } else {
- out.writeInt(0);
- }
- }
- }
-
- int NSE = u.mSensorStats.size();
- out.writeInt(NSE);
- if (NSE > 0) {
- for (Map.Entry<Integer, BatteryStatsImpl.Uid.Sensor> ent
- : u.mSensorStats.entrySet()) {
- out.writeInt(ent.getKey());
- Uid.Sensor se = ent.getValue();
- if (se.mTimer != null) {
- out.writeInt(1);
- se.mTimer.writeSummaryFromParcelLocked(out, NOW);
- } else {
- out.writeInt(0);
- }
- }
- }
-
- int NP = u.mProcessStats.size();
- out.writeInt(NP);
- if (NP > 0) {
- for (Map.Entry<String, BatteryStatsImpl.Uid.Proc> ent
- : u.mProcessStats.entrySet()) {
- out.writeString(ent.getKey());
- Uid.Proc ps = ent.getValue();
- out.writeLong(ps.mUserTime);
- out.writeLong(ps.mUserTime - ps.mLoadedUserTime);
- out.writeLong(ps.mSystemTime);
- out.writeLong(ps.mSystemTime - ps.mLoadedSystemTime);
- out.writeInt(ps.mStarts);
- out.writeInt(ps.mStarts - ps.mLoadedStarts);
- }
- }
-
- NP = u.mPackageStats.size();
- out.writeInt(NP);
- if (NP > 0) {
- for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg> ent
- : u.mPackageStats.entrySet()) {
- out.writeString(ent.getKey());
- Uid.Pkg ps = ent.getValue();
- out.writeInt(ps.mWakeups);
- out.writeInt(ps.mWakeups - ps.mLoadedWakeups);
- final int NS = ps.mServiceStats.size();
- out.writeInt(NS);
- if (NS > 0) {
- for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent
- : ps.mServiceStats.entrySet()) {
- out.writeString(sent.getKey());
- BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue();
- long time = ss.getStartTimeToNowLocked(NOW);
- out.writeLong(time);
- out.writeLong(time - ss.mLoadedStartTime);
- out.writeInt(ss.mStarts);
- out.writeInt(ss.mStarts - ss.mLoadedStarts);
- out.writeInt(ss.mLaunches);
- out.writeInt(ss.mLaunches - ss.mLoadedLaunches);
- }
- }
- }
- }
-
- out.writeLong(u.getTcpBytesReceived(STATS_TOTAL));
- out.writeLong(u.getTcpBytesSent(STATS_TOTAL));
- }
- }
-
- public void readFromParcel(Parcel in) {
- readFromParcelLocked(in);
- }
-
- void readFromParcelLocked(Parcel in) {
- int magic = in.readInt();
- if (magic != MAGIC) {
- throw new ParcelFormatException("Bad magic number");
- }
-
- mStartCount = in.readInt();
- mBatteryUptime = in.readLong();
- mBatteryLastUptime = in.readLong();
- mBatteryRealtime = in.readLong();
- mBatteryLastRealtime = in.readLong();
- mBatteryScreenOnTimeMillis = in.readLong();
- mPluggedScreenOnTimeMillis = in.readLong();
- mScreenOn = false;
- mUptime = in.readLong();
- mUptimeStart = in.readLong();
- mLastUptime = in.readLong();
- mRealtime = in.readLong();
- mRealtimeStart = in.readLong();
- mLastRealtime = in.readLong();
- mOnBattery = in.readInt() != 0;
- mOnBatteryInternal = false; // we are no longer really running.
- mTrackBatteryPastUptime = in.readLong();
- mTrackBatteryUptimeStart = in.readLong();
- mTrackBatteryPastRealtime = in.readLong();
- mTrackBatteryRealtimeStart = in.readLong();
- mLastWriteTime = in.readLong();
-
- mPartialTimers.clear();
- mFullTimers.clear();
- mWindowTimers.clear();
-
- int numUids = in.readInt();
- mUidStats.clear();
- for (int i = 0; i < numUids; i++) {
- int uid = in.readInt();
- Uid u = new Uid(uid);
- u.readFromParcelLocked(mUnpluggables, in);
- mUidStats.append(uid, u);
- }
- }
-
- public void writeToParcel(Parcel out, int flags) {
- writeToParcelLocked(out, flags);
- }
-
- @SuppressWarnings("unused")
- void writeToParcelLocked(Parcel out, int flags) {
- final long uSecUptime = SystemClock.uptimeMillis() * 1000;
- final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
- final long batteryUptime = getBatteryUptimeLocked(uSecUptime);
- final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime);
-
- out.writeInt(MAGIC);
- out.writeInt(mStartCount);
- out.writeLong(mBatteryUptime);
- out.writeLong(mBatteryLastUptime);
- out.writeLong(mBatteryRealtime);
- out.writeLong(mBatteryLastRealtime);
- out.writeLong(mBatteryScreenOnTimeMillis);
- out.writeLong(mPluggedScreenOnTimeMillis);
- out.writeLong(mUptime);
- out.writeLong(mUptimeStart);
- out.writeLong(mLastUptime);
- out.writeLong(mRealtime);
- out.writeLong(mRealtimeStart);
- out.writeLong(mLastRealtime);
- out.writeInt(mOnBattery ? 1 : 0);
- out.writeLong(mTrackBatteryPastUptime);
- out.writeLong(mTrackBatteryUptimeStart);
- out.writeLong(mTrackBatteryPastRealtime);
- out.writeLong(mTrackBatteryRealtimeStart);
- out.writeLong(mLastWriteTime);
-
- int size = mUidStats.size();
- out.writeInt(size);
- for (int i = 0; i < size; i++) {
- out.writeInt(mUidStats.keyAt(i));
- Uid uid = mUidStats.valueAt(i);
-
- uid.writeToParcelLocked(out, batteryRealtime);
- }
- }
-
- public static final Parcelable.Creator<BatteryStatsImpl> CREATOR =
- new Parcelable.Creator<BatteryStatsImpl>() {
- public BatteryStatsImpl createFromParcel(Parcel in) {
- return new BatteryStatsImpl(in);
- }
-
- public BatteryStatsImpl[] newArray(int size) {
- return new BatteryStatsImpl[size];
- }
- };
-}
diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java
deleted file mode 100644
index eacf0ce..0000000
--- a/core/java/com/android/internal/os/BinderInternal.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.os;
-
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.SystemClock;
-import android.util.Config;
-import android.util.EventLog;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.Modifier;
-
-/**
- * Private and debugging Binder APIs.
- *
- * @see IBinder
- */
-public class BinderInternal {
- static WeakReference<GcWatcher> mGcWatcher
- = new WeakReference<GcWatcher>(new GcWatcher());
- static long mLastGcTime;
-
- static final class GcWatcher {
- @Override
- protected void finalize() throws Throwable {
- handleGc();
- mLastGcTime = SystemClock.uptimeMillis();
- mGcWatcher = new WeakReference<GcWatcher>(new GcWatcher());
- }
- }
-
- /**
- * Add the calling thread to the IPC thread pool. This function does
- * not return until the current process is exiting.
- */
- public static final native void joinThreadPool();
-
- /**
- * Return the system time (as reported by {@link SystemClock#uptimeMillis
- * SystemClock.uptimeMillis()}) that the last garbage collection occurred
- * in this process. This is not for general application use, and the
- * meaning of "when a garbage collection occurred" will change as the
- * garbage collector evolves.
- *
- * @return Returns the time as per {@link SystemClock#uptimeMillis
- * SystemClock.uptimeMillis()} of the last garbage collection.
- */
- public static long getLastGcTime() {
- return mLastGcTime;
- }
-
- /**
- * Return the global "context object" of the system. This is usually
- * an implementation of IServiceManager, which you can use to find
- * other services.
- */
- public static final native IBinder getContextObject();
-
- static native final void handleGc();
-
- public static void forceGc(String reason) {
- EventLog.writeEvent(2741, reason);
- Runtime.getRuntime().gc();
- }
-
- static void forceBinderGc() {
- forceGc("Binder");
- }
-}
diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java
deleted file mode 100644
index bab1e21..0000000
--- a/core/java/com/android/internal/os/HandlerCaller.java
+++ /dev/null
@@ -1,195 +0,0 @@
-package com.android.internal.os;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-
-public class HandlerCaller {
- private static final String TAG = "HandlerCaller";
- private static final boolean DEBUG = false;
-
- public final Context mContext;
-
- final Looper mMainLooper;
- final Handler mH;
-
- final Callback mCallback;
-
- public static class SomeArgs {
- SomeArgs next;
-
- public Object arg1;
- public Object arg2;
- public Object arg3;
- public Object arg4;
- public int argi1;
- public int argi2;
- public int argi3;
- public int argi4;
- public int argi5;
- public int argi6;
- }
-
- static final int ARGS_POOL_MAX_SIZE = 10;
- int mArgsPoolSize;
- SomeArgs mArgsPool;
-
- class MyHandler extends Handler {
- MyHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- mCallback.executeMessage(msg);
- }
- }
-
- public interface Callback {
- public void executeMessage(Message msg);
- }
-
- public HandlerCaller(Context context, Callback callback) {
- mContext = context;
- mMainLooper = context.getMainLooper();
- mH = new MyHandler(mMainLooper);
- mCallback = callback;
- }
-
- public SomeArgs obtainArgs() {
- synchronized (mH) {
- SomeArgs args = mArgsPool;
- if (args != null) {
- mArgsPool = args.next;
- args.next = null;
- mArgsPoolSize--;
- return args;
- }
- }
- return new SomeArgs();
- }
-
- public void recycleArgs(SomeArgs args) {
- synchronized (mH) {
- if (mArgsPoolSize < ARGS_POOL_MAX_SIZE) {
- args.next = mArgsPool;
- mArgsPool = args;
- mArgsPoolSize++;
- }
- }
- }
-
- public void executeOrSendMessage(Message msg) {
- // If we are calling this from the main thread, then we can call
- // right through. Otherwise, we need to send the message to the
- // main thread.
- if (Looper.myLooper() == mMainLooper) {
- mCallback.executeMessage(msg);
- msg.recycle();
- return;
- }
-
- mH.sendMessage(msg);
- }
-
- public void sendMessage(Message msg) {
- mH.sendMessage(msg);
- }
-
- public Message obtainMessage(int what) {
- return mH.obtainMessage(what);
- }
-
- public Message obtainMessageBO(int what, boolean arg1, Object arg2) {
- return mH.obtainMessage(what, arg1 ? 1 : 0, 0, arg2);
- }
-
- public Message obtainMessageBOO(int what, boolean arg1, Object arg2, Object arg3) {
- SomeArgs args = obtainArgs();
- args.arg1 = arg2;
- args.arg2 = arg3;
- return mH.obtainMessage(what, arg1 ? 1 : 0, 0, args);
- }
-
- public Message obtainMessageO(int what, Object arg1) {
- return mH.obtainMessage(what, 0, 0, arg1);
- }
-
- public Message obtainMessageI(int what, int arg1) {
- return mH.obtainMessage(what, arg1, 0);
- }
-
- public Message obtainMessageIO(int what, int arg1, Object arg2) {
- return mH.obtainMessage(what, arg1, 0, arg2);
- }
-
- public Message obtainMessageIIO(int what, int arg1, int arg2, Object arg3) {
- return mH.obtainMessage(what, arg1, arg2, arg3);
- }
-
- public Message obtainMessageIOO(int what, int arg1, Object arg2, Object arg3) {
- SomeArgs args = obtainArgs();
- args.arg1 = arg2;
- args.arg2 = arg3;
- return mH.obtainMessage(what, arg1, 0, args);
- }
-
- public Message obtainMessageOO(int what, Object arg1, Object arg2) {
- SomeArgs args = obtainArgs();
- args.arg1 = arg1;
- args.arg2 = arg2;
- return mH.obtainMessage(what, 0, 0, args);
- }
-
- public Message obtainMessageOOO(int what, Object arg1, Object arg2, Object arg3) {
- SomeArgs args = obtainArgs();
- args.arg1 = arg1;
- args.arg2 = arg2;
- args.arg3 = arg3;
- return mH.obtainMessage(what, 0, 0, args);
- }
-
- public Message obtainMessageOOOO(int what, Object arg1, Object arg2,
- Object arg3, Object arg4) {
- SomeArgs args = obtainArgs();
- args.arg1 = arg1;
- args.arg2 = arg2;
- args.arg3 = arg3;
- args.arg4 = arg4;
- return mH.obtainMessage(what, 0, 0, args);
- }
-
- public Message obtainMessageIIII(int what, int arg1, int arg2,
- int arg3, int arg4) {
- SomeArgs args = obtainArgs();
- args.argi1 = arg1;
- args.argi2 = arg2;
- args.argi3 = arg3;
- args.argi4 = arg4;
- return mH.obtainMessage(what, 0, 0, args);
- }
-
- public Message obtainMessageIIIIII(int what, int arg1, int arg2,
- int arg3, int arg4, int arg5, int arg6) {
- SomeArgs args = obtainArgs();
- args.argi1 = arg1;
- args.argi2 = arg2;
- args.argi3 = arg3;
- args.argi4 = arg4;
- args.argi5 = arg5;
- args.argi6 = arg6;
- return mH.obtainMessage(what, 0, 0, args);
- }
-
- public Message obtainMessageIIIIO(int what, int arg1, int arg2,
- int arg3, int arg4, Object arg5) {
- SomeArgs args = obtainArgs();
- args.arg1 = arg5;
- args.argi1 = arg1;
- args.argi2 = arg2;
- args.argi3 = arg3;
- args.argi4 = arg4;
- return mH.obtainMessage(what, 0, 0, args);
- }
-}
diff --git a/core/java/com/android/internal/os/LoggingPrintStream.java b/core/java/com/android/internal/os/LoggingPrintStream.java
deleted file mode 100644
index b3d6f20..0000000
--- a/core/java/com/android/internal/os/LoggingPrintStream.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.os;
-
-import java.io.PrintStream;
-import java.io.OutputStream;
-import java.io.IOException;
-import java.util.Locale;
-import java.util.Formatter;
-
-/**
- * A print stream which logs output line by line.
- *
- * {@hide}
- */
-abstract class LoggingPrintStream extends PrintStream {
-
- private final StringBuilder builder = new StringBuilder();
-
- protected LoggingPrintStream() {
- super(new OutputStream() {
- public void write(int oneByte) throws IOException {
- throw new AssertionError();
- }
- });
- }
-
- /**
- * Logs the given line.
- */
- protected abstract void log(String line);
-
- @Override
- public synchronized void flush() {
- flush(true);
- }
-
- /**
- * Searches buffer for line breaks and logs a message for each one.
- *
- * @param completely true if the ending chars should be treated as a line
- * even though they don't end in a line break
- */
- private void flush(boolean completely) {
- int length = builder.length();
-
- int start = 0;
- int nextBreak;
-
- // Log one line for each line break.
- while (start < length
- && (nextBreak = builder.indexOf("\n", start)) != -1) {
- log(builder.substring(start, nextBreak));
- start = nextBreak + 1;
- }
-
- if (completely) {
- // Log the remainder of the buffer.
- if (start < length) {
- log(builder.substring(start));
- }
- builder.setLength(0);
- } else {
- // Delete characters leading up to the next starting point.
- builder.delete(0, start);
- }
- }
-
- /*
- * We have no idea of how these bytes are encoded, so just ignore them.
- */
-
- /** Ignored. */
- public void write(int oneByte) {}
-
- /** Ignored. */
- @Override
- public void write(byte buffer[]) {}
-
- /** Ignored. */
- @Override
- public void write(byte bytes[], int start, int count) {}
-
- /** Always returns false. */
- @Override
- public boolean checkError() {
- return false;
- }
-
- /** Ignored. */
- @Override
- protected void setError() { /* ignored */ }
-
- /** Ignored. */
- @Override
- public void close() { /* ignored */ }
-
- @Override
- public PrintStream format(String format, Object... args) {
- return format(Locale.getDefault(), format, args);
- }
-
- @Override
- public PrintStream printf(String format, Object... args) {
- return format(format, args);
- }
-
- @Override
- public PrintStream printf(Locale l, String format, Object... args) {
- return format(l, format, args);
- }
-
- private final Formatter formatter = new Formatter(builder, null);
-
- @Override
- public synchronized PrintStream format(
- Locale l, String format, Object... args) {
- if (format == null) {
- throw new NullPointerException("format");
- }
-
- formatter.format(l, format, args);
- flush(false);
- return this;
- }
-
- @Override
- public synchronized void print(char[] charArray) {
- builder.append(charArray);
- flush(false);
- }
-
- @Override
- public synchronized void print(char ch) {
- builder.append(ch);
- if (ch == '\n') {
- flush(false);
- }
- }
-
- @Override
- public synchronized void print(double dnum) {
- builder.append(dnum);
- }
-
- @Override
- public synchronized void print(float fnum) {
- builder.append(fnum);
- }
-
- @Override
- public synchronized void print(int inum) {
- builder.append(inum);
- }
-
- @Override
- public synchronized void print(long lnum) {
- builder.append(lnum);
- }
-
- @Override
- public synchronized void print(Object obj) {
- builder.append(obj);
- flush(false);
- }
-
- @Override
- public synchronized void print(String str) {
- builder.append(str);
- flush(false);
- }
-
- @Override
- public synchronized void print(boolean bool) {
- builder.append(bool);
- }
-
- @Override
- public synchronized void println() {
- flush(true);
- }
-
- @Override
- public synchronized void println(char[] charArray) {
- builder.append(charArray);
- flush(true);
- }
-
- @Override
- public synchronized void println(char ch) {
- builder.append(ch);
- flush(true);
- }
-
- @Override
- public synchronized void println(double dnum) {
- builder.append(dnum);
- flush(true);
- }
-
- @Override
- public synchronized void println(float fnum) {
- builder.append(fnum);
- flush(true);
- }
-
- @Override
- public synchronized void println(int inum) {
- builder.append(inum);
- flush(true);
- }
-
- @Override
- public synchronized void println(long lnum) {
- builder.append(lnum);
- flush(true);
- }
-
- @Override
- public synchronized void println(Object obj) {
- builder.append(obj);
- flush(true);
- }
-
- @Override
- public synchronized void println(String s) {
- if (builder.length() == 0) {
- // Optimization for a simple println.
- int length = s.length();
-
- int start = 0;
- int nextBreak;
-
- // Log one line for each line break.
- while (start < length
- && (nextBreak = s.indexOf('\n', start)) != -1) {
- log(s.substring(start, nextBreak));
- start = nextBreak + 1;
- }
-
- if (start < length) {
- log(s.substring(start));
- }
- } else {
- builder.append(s);
- flush(true);
- }
- }
-
- @Override
- public synchronized void println(boolean bool) {
- builder.append(bool);
- flush(true);
- }
-
- @Override
- public synchronized PrintStream append(char c) {
- print(c);
- return this;
- }
-
- @Override
- public synchronized PrintStream append(CharSequence csq) {
- builder.append(csq);
- flush(false);
- return this;
- }
-
- @Override
- public synchronized PrintStream append(
- CharSequence csq, int start, int end) {
- builder.append(csq, start, end);
- flush(false);
- return this;
- }
-}
diff --git a/core/java/com/android/internal/os/PkgUsageStats.aidl b/core/java/com/android/internal/os/PkgUsageStats.aidl
deleted file mode 100755
index 8305271..0000000
--- a/core/java/com/android/internal/os/PkgUsageStats.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/content/Intent.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package com.android.internal.os;
-
-parcelable PkgUsageStats;
diff --git a/core/java/com/android/internal/os/PkgUsageStats.java b/core/java/com/android/internal/os/PkgUsageStats.java
deleted file mode 100755
index e847878..0000000
--- a/core/java/com/android/internal/os/PkgUsageStats.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.android.internal.os;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * implementation of PkgUsageStats associated with an
- * application package.
- * @hide
- */
-public class PkgUsageStats implements Parcelable {
- public String packageName;
- public int launchCount;
- public long usageTime;
-
- public static final Parcelable.Creator<PkgUsageStats> CREATOR
- = new Parcelable.Creator<PkgUsageStats>() {
- public PkgUsageStats createFromParcel(Parcel in) {
- return new PkgUsageStats(in);
- }
-
- public PkgUsageStats[] newArray(int size) {
- return new PkgUsageStats[size];
- }
- };
-
- public String toString() {
- return "PkgUsageStats{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + packageName + "}";
- }
-
- public PkgUsageStats(String pkgName, int count, long time) {
- packageName = pkgName;
- launchCount = count;
- usageTime = time;
- }
-
- public PkgUsageStats(Parcel source) {
- packageName = source.readString();
- launchCount = source.readInt();
- usageTime = source.readLong();
- }
-
- public PkgUsageStats(PkgUsageStats pStats) {
- packageName = pStats.packageName;
- launchCount = pStats.launchCount;
- usageTime = pStats.usageTime;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags){
- dest.writeString(packageName);
- dest.writeInt(launchCount);
- dest.writeLong(usageTime);
- }
-}
diff --git a/core/java/com/android/internal/os/RecoverySystem.java b/core/java/com/android/internal/os/RecoverySystem.java
deleted file mode 100644
index c938610..0000000
--- a/core/java/com/android/internal/os/RecoverySystem.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.os;
-
-import android.os.FileUtils;
-import android.os.Power;
-import android.util.Log;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * Utility class for interacting with the Android recovery partition.
- * The recovery partition is a small standalone system which can perform
- * operations that are difficult while the main system is running, like
- * upgrading system software or reformatting the data partition.
- * Note that most of these operations must be run as root.
- *
- * @hide
- */
-public class RecoverySystem {
- private static final String TAG = "RecoverySystem"; // for logging
-
- // Used to communicate with recovery. See commands/recovery/recovery.c.
- private static File RECOVERY_DIR = new File("/cache/recovery");
- private static File COMMAND_FILE = new File(RECOVERY_DIR, "command");
- private static File LOG_FILE = new File(RECOVERY_DIR, "log");
-
- // Length limits for reading files.
- private static int LOG_FILE_MAX_LENGTH = 8 * 1024;
-
- /**
- * Reboot into the recovery system to install a system update.
- * @param update package to install (must be in /cache or /data).
- * @throws IOException if something goes wrong.
- */
- public static void rebootAndUpdate(File update) throws IOException {
- String path = update.getCanonicalPath();
- if (path.startsWith("/cache/")) {
- path = "CACHE:" + path.substring(7);
- } else if (path.startsWith("/data/")) {
- path = "DATA:" + path.substring(6);
- } else {
- throw new IllegalArgumentException(
- "Must start with /cache or /data: " + path);
- }
- bootCommand("--update_package=" + path);
- }
-
- /**
- * Reboot into the recovery system to wipe the /data partition.
- * @param extras to add to the RECOVERY_COMPLETED intent after rebooting.
- * @throws IOException if something goes wrong.
- */
- public static void rebootAndWipe() throws IOException {
- bootCommand("--wipe_data");
- }
-
- /**
- * Reboot into the recovery system with the supplied argument.
- * @param arg to pass to the recovery utility.
- * @throws IOException if something goes wrong.
- */
- private static void bootCommand(String arg) throws IOException {
- RECOVERY_DIR.mkdirs(); // In case we need it
- COMMAND_FILE.delete(); // In case it's not writable
- LOG_FILE.delete();
-
- FileWriter command = new FileWriter(COMMAND_FILE);
- try {
- command.write(arg);
- command.write("\n");
- } finally {
- command.close();
- }
-
- // Having written the command file, go ahead and reboot
- Power.reboot("recovery");
- throw new IOException("Reboot failed (no permissions?)");
- }
-
- /**
- * Called after booting to process and remove recovery-related files.
- * @return the log file from recovery, or null if none was found.
- */
- public static String handleAftermath() {
- // Record the tail of the LOG_FILE
- String log = null;
- try {
- log = FileUtils.readTextFile(LOG_FILE, -LOG_FILE_MAX_LENGTH, "...\n");
- } catch (FileNotFoundException e) {
- Log.i(TAG, "No recovery log file");
- } catch (IOException e) {
- Log.e(TAG, "Error reading recovery log", e);
- }
-
- // Delete everything in RECOVERY_DIR
- String[] names = RECOVERY_DIR.list();
- for (int i = 0; names != null && i < names.length; i++) {
- File f = new File(RECOVERY_DIR, names[i]);
- if (!f.delete()) {
- Log.e(TAG, "Can't delete: " + f);
- } else {
- Log.i(TAG, "Deleted: " + f);
- }
- }
-
- return log;
- }
-}
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
deleted file mode 100644
index 8486272..0000000
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.os;
-
-import android.app.ActivityManagerNative;
-import android.app.IActivityManager;
-import android.os.Debug;
-import android.os.IBinder;
-import android.os.ICheckinService;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemProperties;
-import android.server.data.CrashData;
-import android.util.Config;
-import android.util.Log;
-
-import com.android.internal.logging.AndroidConfig;
-
-import dalvik.system.VMRuntime;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.logging.LogManager;
-import java.util.TimeZone;
-
-import org.apache.harmony.luni.internal.util.TimezoneGetter;
-
-/**
- * Main entry point for runtime initialization. Not for
- * public consumption.
- * @hide
- */
-public class RuntimeInit {
- private final static String TAG = "AndroidRuntime";
-
- /** true if commonInit() has been called */
- private static boolean initialized;
-
- /**
- * Use this to log a message when a thread exits due to an uncaught
- * exception. The framework catches these for the main threads, so
- * this should only matter for threads created by applications.
- */
- private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {
- public void uncaughtException(Thread t, Throwable e) {
- try {
- Log.e(TAG, "Uncaught handler: thread " + t.getName()
- + " exiting due to uncaught exception");
- } catch (Throwable error) {
- // Ignore the throwable, since we're in the process of crashing anyway.
- // If we don't, the crash won't happen properly and the process will
- // be left around in a bad state.
- }
- crash(TAG, e);
- }
- }
-
- private static final void commonInit() {
- if (Config.LOGV) Log.d(TAG, "Entered RuntimeInit!");
-
- /* set default handler; this applies to all threads in the VM */
- Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
-
- int hasQwerty = getQwertyKeyboard();
-
- if (Config.LOGV) Log.d(TAG, ">>>>> qwerty keyboard = " + hasQwerty);
- if (hasQwerty == 1) {
- System.setProperty("qwerty", "1");
- }
-
- /*
- * Install a TimezoneGetter subclass for ZoneInfo.db
- */
- TimezoneGetter.setInstance(new TimezoneGetter() {
- @Override
- public String getId() {
- return SystemProperties.get("persist.sys.timezone");
- }
- });
- TimeZone.setDefault(null);
-
- /*
- * Sets handler for java.util.logging to use Android log facilities.
- * The odd "new instance-and-then-throw-away" is a mirror of how
- * the "java.util.logging.config.class" system property works. We
- * can't use the system property here since the logger has almost
- * certainly already been initialized.
- */
- LogManager.getLogManager().reset();
- new AndroidConfig();
-
- /*
- * If we're running in an emulator launched with "-trace", put the
- * VM into emulator trace profiling mode so that the user can hit
- * F9/F10 at any time to capture traces. This has performance
- * consequences, so it's not something you want to do always.
- */
- String trace = SystemProperties.get("ro.kernel.android.tracing");
- if (trace.equals("1")) {
- Log.i(TAG, "NOTE: emulator trace profiling enabled");
- Debug.enableEmulatorTraceOutput();
- }
-
- initialized = true;
- }
-
- /**
- * Invokes a static "main(argv[]) method on class "className".
- * Converts various failing exceptions into RuntimeExceptions, with
- * the assumption that they will then cause the VM instance to exit.
- *
- * @param className Fully-qualified class name
- * @param argv Argument vector for main()
- */
- private static void invokeStaticMain(String className, String[] argv)
- throws ZygoteInit.MethodAndArgsCaller {
-
- // We want to be fairly aggressive about heap utilization, to avoid
- // holding on to a lot of memory that isn't needed.
- VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
-
- Class<?> cl;
-
- try {
- cl = Class.forName(className);
- } catch (ClassNotFoundException ex) {
- throw new RuntimeException(
- "Missing class when invoking static main " + className,
- ex);
- }
-
- Method m;
- try {
- m = cl.getMethod("main", new Class[] { String[].class });
- } catch (NoSuchMethodException ex) {
- throw new RuntimeException(
- "Missing static main on " + className, ex);
- } catch (SecurityException ex) {
- throw new RuntimeException(
- "Problem getting static main on " + className, ex);
- }
-
- int modifiers = m.getModifiers();
- if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
- throw new RuntimeException(
- "Main method is not public and static on " + className);
- }
-
- /*
- * This throw gets caught in ZygoteInit.main(), which responds
- * by invoking the exception's run() method. This arrangement
- * clears up all the stack frames that were required in setting
- * up the process.
- */
- throw new ZygoteInit.MethodAndArgsCaller(m, argv);
- }
-
- public static final void main(String[] argv) {
- commonInit();
-
- /*
- * Now that we're running in interpreted code, call back into native code
- * to run the system.
- */
- finishInit();
-
- if (Config.LOGV) Log.d(TAG, "Leaving RuntimeInit!");
- }
-
- public static final native void finishInit();
-
- /**
- * The main function called when started through the zygote process. This
- * could be unified with main(), if the native code in finishInit()
- * were rationalized with Zygote startup.<p>
- *
- * Current recognized args:
- * <ul>
- * <li> --nice-name=<i>nice name to appear in ps</i>
- * <li> <code> [--] &lt;start class name&gt; &lt;args&gt;
- * </ul>
- *
- * @param argv arg strings
- */
- public static final void zygoteInit(String[] argv)
- throws ZygoteInit.MethodAndArgsCaller {
- // TODO: Doing this here works, but it seems kind of arbitrary. Find
- // a better place. The goal is to set it up for applications, but not
- // tools like am.
- System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
- System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
-
- commonInit();
- zygoteInitNative();
-
- int curArg = 0;
- for ( /* curArg */ ; curArg < argv.length; curArg++) {
- String arg = argv[curArg];
-
- if (arg.equals("--")) {
- curArg++;
- break;
- } else if (!arg.startsWith("--")) {
- break;
- } else if (arg.startsWith("--nice-name=")) {
- String niceName = arg.substring(arg.indexOf('=') + 1);
- Process.setArgV0(niceName);
- }
- }
-
- if (curArg == argv.length) {
- Log.e(TAG, "Missing classname argument to RuntimeInit!");
- // let the process exit
- return;
- }
-
- // Remaining arguments are passed to the start class's static main
-
- String startClass = argv[curArg++];
- String[] startArgs = new String[argv.length - curArg];
-
- System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
- invokeStaticMain(startClass, startArgs);
- }
-
- public static final native void zygoteInitNative();
-
- /**
- * Returns 1 if the computer is on. If the computer isn't on, the value returned by this method is undefined.
- */
- public static final native int isComputerOn();
-
- /**
- * Turns the computer on if the computer is off. If the computer is on, the behavior of this method is undefined.
- */
- public static final native void turnComputerOn();
-
- /**
- *
- * @return 1 if the device has a qwerty keyboard
- */
- public static native int getQwertyKeyboard();
-
- /**
- * Report a fatal error in the current process. If this is a user-process,
- * a dialog may be displayed informing the user of the error. This
- * function does not return; it forces the current process to exit.
- *
- * @param tag to use when logging the error
- * @param t exception that was generated by the error
- */
- public static void crash(String tag, Throwable t) {
- if (mApplicationObject != null) {
- byte[] crashData = null;
- try {
- // Log exception.
- Log.e(TAG, Log.getStackTraceString(t));
- crashData = marshallException(tag, t);
- if (crashData == null) {
- throw new NullPointerException("Can't marshall crash data");
- }
- } catch (Throwable t2) {
- try {
- // Log exception as a string so we don't get in an infinite loop.
- Log.e(TAG, "Error reporting crash: "
- + Log.getStackTraceString(t2));
- } catch (Throwable t3) {
- // Do nothing, must be OOM so we can't format the message
- }
- }
-
- try {
- // Display user-visible error message.
- String msg = t.getMessage();
- if (msg == null) {
- msg = t.toString();
- }
-
- IActivityManager am = ActivityManagerNative.getDefault();
- try {
- int res = am.handleApplicationError(mApplicationObject,
- 0, tag, msg, t.toString(), crashData);
- // Is waiting for the debugger the right thing?
- // For now I have turned off the Debug button, because
- // I'm not sure what we should do if it is actually
- // selected.
- //Log.i(TAG, "Got app error result: " + res);
- if (res == 1) {
- Debug.waitForDebugger();
- return;
- }
- } catch (RemoteException e) {
- }
- } catch (Throwable t2) {
- try {
- // Log exception as a string so we don't get in an infinite loop.
- Log.e(TAG, "Error reporting crash: "
- + Log.getStackTraceString(t2));
- } catch (Throwable t3) {
- // Do nothing, must be OOM so we can't format the message
- }
- } finally {
- // Try everything to make sure this process goes away.
- Process.killProcess(Process.myPid());
- System.exit(10);
- }
- } else {
- try {
- Log.e(TAG, "*** EXCEPTION IN SYSTEM PROCESS. System will crash.");
- Log.e(tag, Log.getStackTraceString(t));
- reportException(tag, t, true); // synchronous
- } catch (Throwable t2) {
- // Do nothing, must be OOM so we can't format the message
- } finally {
- // Try everything to make sure this process goes away.
- Process.killProcess(Process.myPid());
- System.exit(10);
- }
- }
- }
-
- /** Counter used to prevent reentrancy in {@link #reportException}. */
- private static final AtomicInteger sInReportException = new AtomicInteger();
-
- /**
- * Report an error in the current process. The exception information will
- * be handed off to the checkin service and eventually uploaded for analysis.
- * This is expensive! Only use this when the exception indicates a programming
- * error ("should not happen").
- *
- * @param tag to use when logging the error
- * @param t exception that was generated by the error
- * @param sync true to wait for the report, false to "fire and forget"
- */
- public static void reportException(String tag, Throwable t, boolean sync) {
- if (!initialized) {
- // Exceptions during, eg, zygote cannot use this mechanism
- return;
- }
-
- // It's important to prevent an infinite crash-reporting loop:
- // while this function is running, don't let it be called again.
- int reenter = sInReportException.getAndIncrement();
- if (reenter != 0) {
- sInReportException.decrementAndGet();
- Log.e(TAG, "Crash logging skipped, already logging another crash");
- return;
- }
-
- // TODO: Enable callers to specify a level (i.e. warn or error).
- try {
- // Submit crash data to statistics service.
- byte[] crashData = marshallException(tag, t);
- ICheckinService checkin = ICheckinService.Stub.asInterface(
- ServiceManager.getService("checkin"));
- if (checkin == null) {
- Log.e(TAG, "Crash logging skipped, no checkin service");
- } else if (sync) {
- checkin.reportCrashSync(crashData);
- } else {
- checkin.reportCrashAsync(crashData);
- }
- } catch (Throwable t2) {
- // Log exception as a string so we don't get in an infinite loop.
- Log.e(TAG, "Crash logging failed: " + t2);
- } finally {
- sInReportException.decrementAndGet();
- }
- }
-
- private static byte[] marshallException(String tag, Throwable t) {
- // Convert crash data to bytes.
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- DataOutputStream dout = new DataOutputStream(bout);
- try {
- new CrashData(tag, t).write(dout);
- dout.close();
- } catch (IOException e) {
- return null;
- }
- return bout.toByteArray();
- }
-
- /**
- * Replay an encoded CrashData record back into a useable CrashData record. This can be
- * helpful for providing debugging output after a process error.
- *
- * @param crashDataBytes The byte array containing the encoded crash record
- * @return new CrashData record, or null if could not create one.
- */
- public static CrashData unmarshallException(byte[] crashDataBytes) {
- try {
- ByteArrayInputStream bin = new ByteArrayInputStream(crashDataBytes);
- DataInputStream din = new DataInputStream(bin);
- return new CrashData(din);
- } catch (IOException e) {
- return null;
- }
- }
-
- /**
- * Set the object identifying this application/process, for reporting VM
- * errors.
- */
- public static final void setApplicationObject(IBinder app) {
- mApplicationObject = app;
- }
-
- /**
- * Enable debugging features.
- */
- static {
- // Register handlers for DDM messages.
- android.ddm.DdmRegister.registerHandlers();
- }
-
- private static IBinder mApplicationObject;
-
-}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
deleted file mode 100644
index 631e7d8..0000000
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ /dev/null
@@ -1,834 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.os;
-
-import android.net.Credentials;
-import android.net.LocalSocket;
-import android.os.Process;
-import android.os.SystemProperties;
-import android.util.Log;
-
-import dalvik.system.PathClassLoader;
-import dalvik.system.Zygote;
-
-import java.io.BufferedReader;
-import java.io.DataOutputStream;
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintStream;
-import java.util.ArrayList;
-
-/**
- * A connection that can make spawn requests.
- */
-class ZygoteConnection {
- private static final String TAG = "Zygote";
-
- /** a prototype instance for a future List.toArray() */
- private static final int[][] intArray2d = new int[0][0];
-
- /**
- * {@link android.net.LocalSocket#setSoTimeout} value for connections.
- * Effectively, the amount of time a requestor has between the start of
- * the request and the completed request. The select-loop mode Zygote
- * doesn't have the logic to return to the select loop in the middle of
- * a request, so we need to time out here to avoid being denial-of-serviced.
- */
- private static final int CONNECTION_TIMEOUT_MILLIS = 1000;
-
- /** max number of arguments that a connection can specify */
- private static final int MAX_ZYGOTE_ARGC=1024;
-
- /**
- * The command socket.
- *
- * mSocket is retained in the child process in "peer wait" mode, so
- * that it closes when the child process terminates. In other cases,
- * it is closed in the peer.
- */
- private final LocalSocket mSocket;
- private final DataOutputStream mSocketOutStream;
- private final BufferedReader mSocketReader;
- private final Credentials peer;
-
- /**
- * A long-lived reference to the original command socket used to launch
- * this peer. If "peer wait" mode is specified, the process that requested
- * the new VM instance intends to track the lifetime of the spawned instance
- * via the command socket. In this case, the command socket is closed
- * in the Zygote and placed here in the spawned instance so that it will
- * not be collected and finalized. This field remains null at all times
- * in the original Zygote process, and in all spawned processes where
- * "peer-wait" mode was not requested.
- */
- private static LocalSocket sPeerWaitSocket = null;
-
- /**
- * Constructs instance from connected socket.
- *
- * @param socket non-null; connected socket
- * @throws IOException
- */
- ZygoteConnection(LocalSocket socket) throws IOException {
- mSocket = socket;
-
- mSocketOutStream
- = new DataOutputStream(socket.getOutputStream());
-
- mSocketReader = new BufferedReader(
- new InputStreamReader(socket.getInputStream()), 256);
-
- mSocket.setSoTimeout(CONNECTION_TIMEOUT_MILLIS);
-
- try {
- peer = mSocket.getPeerCredentials();
- } catch (IOException ex) {
- Log.e(TAG, "Cannot read peer credentials", ex);
- throw ex;
- }
- }
-
- /**
- * Returns the file descriptor of the associated socket.
- *
- * @return null-ok; file descriptor
- */
- FileDescriptor getFileDesciptor() {
- return mSocket.getFileDescriptor();
- }
-
- /**
- * Reads start commands from an open command socket.
- * Start commands are presently a pair of newline-delimited lines
- * indicating a) class to invoke main() on b) nice name to set argv[0] to.
- * Continues to read commands and forkAndSpecialize children until
- * the socket is closed. This method is used in ZYGOTE_FORK_MODE
- *
- * @throws ZygoteInit.MethodAndArgsCaller trampoline to invoke main()
- * method in child process
- */
- void run() throws ZygoteInit.MethodAndArgsCaller {
-
- int loopCount = ZygoteInit.GC_LOOP_COUNT;
-
- while (true) {
- /*
- * Call gc() before we block in readArgumentList().
- * It's work that has to be done anyway, and it's better
- * to avoid making every child do it. It will also
- * madvise() any free memory as a side-effect.
- *
- * Don't call it every time, because walking the entire
- * heap is a lot of overhead to free a few hundred bytes.
- */
- if (loopCount <= 0) {
- ZygoteInit.gc();
- loopCount = ZygoteInit.GC_LOOP_COUNT;
- } else {
- loopCount--;
- }
-
- if (runOnce()) {
- break;
- }
- }
- }
-
- /**
- * Reads one start command from the command socket. If successful,
- * a child is forked and a {@link ZygoteInit.MethodAndArgsCaller}
- * exception is thrown in that child while in the parent process,
- * the method returns normally. On failure, the child is not
- * spawned and messages are printed to the log and stderr. Returns
- * a boolean status value indicating whether an end-of-file on the command
- * socket has been encountered.
- *
- * @return false if command socket should continue to be read from, or
- * true if an end-of-file has been encountered.
- * @throws ZygoteInit.MethodAndArgsCaller trampoline to invoke main()
- * method in child process
- */
- boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
-
- String args[];
- Arguments parsedArgs = null;
- FileDescriptor[] descriptors;
-
- try {
- args = readArgumentList();
- descriptors = mSocket.getAncillaryFileDescriptors();
- } catch (IOException ex) {
- Log.w(TAG, "IOException on command socket " + ex.getMessage());
- closeSocket();
- return true;
- }
-
- if (args == null) {
- // EOF reached.
- closeSocket();
- return true;
- }
-
- /** the stderr of the most recent request, if avail */
- PrintStream newStderr = null;
-
- if (descriptors != null && descriptors.length >= 3) {
- newStderr = new PrintStream(
- new FileOutputStream(descriptors[2]));
- }
-
- int pid;
-
- try {
- parsedArgs = new Arguments(args);
-
- applyUidSecurityPolicy(parsedArgs, peer);
- applyDebuggerSecurityPolicy(parsedArgs);
- applyRlimitSecurityPolicy(parsedArgs, peer);
- applyCapabilitiesSecurityPolicy(parsedArgs, peer);
-
- int[][] rlimits = null;
-
- if (parsedArgs.rlimits != null) {
- rlimits = parsedArgs.rlimits.toArray(intArray2d);
- }
-
- pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
- parsedArgs.gids, parsedArgs.debugFlags, rlimits);
- } catch (IllegalArgumentException ex) {
- logAndPrintError (newStderr, "Invalid zygote arguments", ex);
- pid = -1;
- } catch (ZygoteSecurityException ex) {
- logAndPrintError(newStderr,
- "Zygote security policy prevents request: ", ex);
- pid = -1;
- }
-
- if (pid == 0) {
- // in child
- handleChildProc(parsedArgs, descriptors, newStderr);
- // should never happen
- return true;
- } else { /* pid != 0 */
- // in parent...pid of < 0 means failure
- return handleParentProc(pid, descriptors, parsedArgs);
- }
- }
-
- /**
- * Closes socket associated with this connection.
- */
- void closeSocket() {
- try {
- mSocket.close();
- } catch (IOException ex) {
- Log.e(TAG, "Exception while closing command "
- + "socket in parent", ex);
- }
- }
-
- /**
- * Handles argument parsing for args related to the zygote spawner.<p>
-
- * Current recognized args:
- * <ul>
- * <li> --setuid=<i>uid of child process, defaults to 0</i>
- * <li> --setgid=<i>gid of child process, defaults to 0</i>
- * <li> --setgroups=<i>comma-separated list of supplimentary gid's</i>
- * <li> --capabilities=<i>a pair of comma-separated integer strings
- * indicating Linux capabilities(2) set for child. The first string
- * represents the <code>permitted</code> set, and the second the
- * <code>effective</code> set. Precede each with 0 or
- * 0x for octal or hexidecimal value. If unspecified, both default to 0.
- * This parameter is only applied if the uid of the new process will
- * be non-0. </i>
- * <li> --rlimit=r,c,m<i>tuple of values for setrlimit() call.
- * <code>r</code> is the resource, <code>c</code> and <code>m</code>
- * are the settings for current and max value.</i>
- * <li> --peer-wait indicates that the command socket should
- * be inherited by (and set to close-on-exec in) the spawned process
- * and used to track the lifetime of that process. The spawning process
- * then exits. Without this flag, it is retained by the spawning process
- * (and closed in the child) in expectation of a new spawn request.
- * <li> --classpath=<i>colon-separated classpath</i> indicates
- * that the specified class (which must b first non-flag argument) should
- * be loaded from jar files in the specified classpath. Incompatible with
- * --runtime-init
- * <li> --runtime-init indicates that the remaining arg list should
- * be handed off to com.android.internal.os.RuntimeInit, rather than
- * processed directly
- * Android runtime startup (eg, Binder initialization) is also eschewed.
- * <li> If <code>--runtime-init</code> is present:
- * [--] &lt;args for RuntimeInit &gt;
- * <li> If <code>--runtime-init</code> is absent:
- * [--] &lt;classname&gt; [args...]
- * </ul>
- */
- static class Arguments {
- /** from --setuid */
- int uid = 0;
- boolean uidSpecified;
-
- /** from --setgid */
- int gid = 0;
- boolean gidSpecified;
-
- /** from --setgroups */
- int[] gids;
-
- /** from --peer-wait */
- boolean peerWait;
-
- /** from --enable-debugger, --enable-checkjni, --enable-assert */
- int debugFlags;
-
- /** from --classpath */
- String classpath;
-
- /** from --runtime-init */
- boolean runtimeInit;
-
- /** from --capabilities */
- boolean capabilitiesSpecified;
- long permittedCapabilities;
- long effectiveCapabilities;
-
- /** from all --rlimit=r,c,m */
- ArrayList<int[]> rlimits;
-
- /**
- * Any args after and including the first non-option arg
- * (or after a '--')
- */
- String remainingArgs[];
-
- /**
- * Constructs instance and parses args
- * @param args zygote command-line args
- * @throws IllegalArgumentException
- */
- Arguments(String args[]) throws IllegalArgumentException {
- parseArgs(args);
- }
-
- /**
- * Parses the commandline arguments intended for the Zygote spawner
- * (such as "--setuid=" and "--setgid=") and creates an array
- * containing the remaining args.
- *
- * Per security review bug #1112214, duplicate args are disallowed in
- * critical cases to make injection harder.
- */
- private void parseArgs(String args[])
- throws IllegalArgumentException {
- int curArg = 0;
-
- for ( /* curArg */ ; curArg < args.length; curArg++) {
- String arg = args[curArg];
-
- if (arg.equals("--")) {
- curArg++;
- break;
- } else if (arg.startsWith("--setuid=")) {
- if (uidSpecified) {
- throw new IllegalArgumentException(
- "Duplicate arg specified");
- }
- uidSpecified = true;
- uid = Integer.parseInt(
- arg.substring(arg.indexOf('=') + 1));
- } else if (arg.startsWith("--setgid=")) {
- if (gidSpecified) {
- throw new IllegalArgumentException(
- "Duplicate arg specified");
- }
- gidSpecified = true;
- gid = Integer.parseInt(
- arg.substring(arg.indexOf('=') + 1));
- } else if (arg.equals("--enable-debugger")) {
- debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
- } else if (arg.equals("--enable-checkjni")) {
- debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
- } else if (arg.equals("--enable-assert")) {
- debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
- } else if (arg.equals("--peer-wait")) {
- peerWait = true;
- } else if (arg.equals("--runtime-init")) {
- runtimeInit = true;
- } else if (arg.startsWith("--capabilities=")) {
- if (capabilitiesSpecified) {
- throw new IllegalArgumentException(
- "Duplicate arg specified");
- }
- capabilitiesSpecified = true;
- String capString = arg.substring(arg.indexOf('=')+1);
-
- String[] capStrings = capString.split(",", 2);
-
- if (capStrings.length == 1) {
- effectiveCapabilities = Long.decode(capStrings[0]);
- permittedCapabilities = effectiveCapabilities;
- } else {
- permittedCapabilities = Long.decode(capStrings[0]);
- effectiveCapabilities = Long.decode(capStrings[1]);
- }
- } else if (arg.startsWith("--rlimit=")) {
- // Duplicate --rlimit arguments are specifically allowed.
- String[] limitStrings
- = arg.substring(arg.indexOf('=')+1).split(",");
-
- if (limitStrings.length != 3) {
- throw new IllegalArgumentException(
- "--rlimit= should have 3 comma-delimited ints");
- }
- int[] rlimitTuple = new int[limitStrings.length];
-
- for(int i=0; i < limitStrings.length; i++) {
- rlimitTuple[i] = Integer.parseInt(limitStrings[i]);
- }
-
- if (rlimits == null) {
- rlimits = new ArrayList();
- }
-
- rlimits.add(rlimitTuple);
- } else if (arg.equals("-classpath")) {
- if (classpath != null) {
- throw new IllegalArgumentException(
- "Duplicate arg specified");
- }
- try {
- classpath = args[++curArg];
- } catch (IndexOutOfBoundsException ex) {
- throw new IllegalArgumentException(
- "-classpath requires argument");
- }
- } else if (arg.startsWith("--setgroups=")) {
- if (gids != null) {
- throw new IllegalArgumentException(
- "Duplicate arg specified");
- }
-
- String[] params
- = arg.substring(arg.indexOf('=') + 1).split(",");
-
- gids = new int[params.length];
-
- for (int i = params.length - 1; i >= 0 ; i--) {
- gids[i] = Integer.parseInt(params[i]);
- }
- } else {
- break;
- }
- }
-
- if (runtimeInit && classpath != null) {
- throw new IllegalArgumentException(
- "--runtime-init and -classpath are incompatible");
- }
-
- remainingArgs = new String[args.length - curArg];
-
- System.arraycopy(args, curArg, remainingArgs, 0,
- remainingArgs.length);
- }
- }
-
- /**
- * Reads an argument list from the command socket/
- * @return Argument list or null if EOF is reached
- * @throws IOException passed straight through
- */
- private String[] readArgumentList()
- throws IOException {
-
- /**
- * See android.os.Process.zygoteSendArgsAndGetPid()
- * Presently the wire format to the zygote process is:
- * a) a count of arguments (argc, in essence)
- * b) a number of newline-separated argument strings equal to count
- *
- * After the zygote process reads these it will write the pid of
- * the child or -1 on failure.
- */
-
- int argc;
-
- try {
- String s = mSocketReader.readLine();
-
- if (s == null) {
- // EOF reached.
- return null;
- }
- argc = Integer.parseInt(s);
- } catch (NumberFormatException ex) {
- Log.e(TAG, "invalid Zygote wire format: non-int at argc");
- throw new IOException("invalid wire format");
- }
-
- // See bug 1092107: large argc can be used for a DOS attack
- if (argc > MAX_ZYGOTE_ARGC) {
- throw new IOException("max arg count exceeded");
- }
-
- String[] result = new String[argc];
- for (int i = 0; i < argc; i++) {
- result[i] = mSocketReader.readLine();
- if (result[i] == null) {
- // We got an unexpected EOF.
- throw new IOException("truncated request");
- }
- }
-
- return result;
- }
-
- /**
- * Applies zygote security policy per bugs #875058 and #1082165.
- * Based on the credentials of the process issuing a zygote command:
- * <ol>
- * <li> uid 0 (root) may specify any uid, gid, and setgroups() list
- * <li> uid 1000 (Process.SYSTEM_UID) may specify any uid &gt; 1000 in normal
- * operation. It may also specify any gid and setgroups() list it chooses.
- * In factory test mode, it may specify any UID.
- * <li> Any other uid may not specify any uid, gid, or setgroups list. The
- * uid and gid will be inherited from the requesting process.
- * </ul>
- *
- * @param args non-null; zygote spawner arguments
- * @param peer non-null; peer credentials
- * @throws ZygoteSecurityException
- */
- private static void applyUidSecurityPolicy(Arguments args, Credentials peer)
- throws ZygoteSecurityException {
-
- int peerUid = peer.getUid();
-
- if (peerUid == 0) {
- // Root can do what it wants
- } else if (peerUid == Process.SYSTEM_UID ) {
- // System UID is restricted, except in factory test mode
- String factoryTest = SystemProperties.get("ro.factorytest");
- boolean uidRestricted;
-
- /* In normal operation, SYSTEM_UID can only specify a restricted
- * set of UIDs. In factory test mode, SYSTEM_UID may specify any uid.
- */
- uidRestricted
- = !(factoryTest.equals("1") || factoryTest.equals("2"));
-
- if (uidRestricted
- && args.uidSpecified && (args.uid < Process.SYSTEM_UID)) {
- throw new ZygoteSecurityException(
- "System UID may not launch process with UID < "
- + Process.SYSTEM_UID);
- }
- } else {
- // Everything else
- if (args.uidSpecified || args.gidSpecified
- || args.gids != null) {
- throw new ZygoteSecurityException(
- "App UIDs may not specify uid's or gid's");
- }
- }
-
- // If not otherwise specified, uid and gid are inherited from peer
- if (!args.uidSpecified) {
- args.uid = peer.getUid();
- args.uidSpecified = true;
- }
- if (!args.gidSpecified) {
- args.gid = peer.getGid();
- args.gidSpecified = true;
- }
- }
-
-
- /**
- * Applies debugger security policy.
- * If "ro.debuggable" is "1", all apps are debuggable. Otherwise,
- * the debugger state is specified via the "--enable-debugger" flag
- * in the spawn request.
- *
- * @param args non-null; zygote spawner args
- */
- private static void applyDebuggerSecurityPolicy(Arguments args) {
- if ("1".equals(SystemProperties.get("ro.debuggable"))) {
- args.debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
- }
- }
-
- /**
- * Applies zygote security policy per bug #1042973. Based on the credentials
- * of the process issuing a zygote command:
- * <ol>
- * <li> peers of uid 0 (root) and uid 1000 (Process.SYSTEM_UID)
- * may specify any rlimits.
- * <li> All other uids may not specify rlimits.
- * </ul>
- * @param args non-null; zygote spawner arguments
- * @param peer non-null; peer credentials
- * @throws ZygoteSecurityException
- */
- private static void applyRlimitSecurityPolicy(
- Arguments args, Credentials peer)
- throws ZygoteSecurityException {
-
- int peerUid = peer.getUid();
-
- if (!(peerUid == 0 || peerUid == Process.SYSTEM_UID)) {
- // All peers with UID other than root or SYSTEM_UID
- if (args.rlimits != null) {
- throw new ZygoteSecurityException(
- "This UID may not specify rlimits.");
- }
- }
- }
-
- /**
- * Applies zygote security policy per bug #1042973. A root peer may
- * spawn an instance with any capabilities. All other uids may spawn
- * instances with any of the capabilities in the peer's permitted set
- * but no more.
- *
- * @param args non-null; zygote spawner arguments
- * @param peer non-null; peer credentials
- * @throws ZygoteSecurityException
- */
- private static void applyCapabilitiesSecurityPolicy(
- Arguments args, Credentials peer)
- throws ZygoteSecurityException {
-
- if (args.permittedCapabilities == 0
- && args.effectiveCapabilities == 0) {
- // nothing to check
- return;
- }
-
- if (peer.getUid() == 0) {
- // root may specify anything
- return;
- }
-
- long permittedCaps;
-
- try {
- permittedCaps = ZygoteInit.capgetPermitted(peer.getPid());
- } catch (IOException ex) {
- throw new ZygoteSecurityException(
- "Error retrieving peer's capabilities.");
- }
-
- /*
- * Ensure that the client did not specify an effective set larger
- * than the permitted set. The kernel will enforce this too, but we
- * do it here to make the following check easier.
- */
- if (((~args.permittedCapabilities) & args.effectiveCapabilities) != 0) {
- throw new ZygoteSecurityException(
- "Effective capabilities cannot be superset of "
- + " permitted capabilities" );
- }
-
- /*
- * Ensure that the new permitted (and thus the new effective) set is
- * a subset of the peer process's permitted set
- */
-
- if (((~permittedCaps) & args.permittedCapabilities) != 0) {
- throw new ZygoteSecurityException(
- "Peer specified unpermitted capabilities" );
- }
- }
-
- /**
- * Handles post-fork setup of child proc, closing sockets as appropriate,
- * reopen stdio as appropriate, and ultimately throwing MethodAndArgsCaller
- * if successful or returning if failed.
- *
- * @param parsedArgs non-null; zygote args
- * @param descriptors null-ok; new file descriptors for stdio if available.
- * @param newStderr null-ok; stream to use for stderr until stdio
- * is reopened.
- *
- * @throws ZygoteInit.MethodAndArgsCaller on success to
- * trampoline to code that invokes static main.
- */
- private void handleChildProc(Arguments parsedArgs,
- FileDescriptor[] descriptors, PrintStream newStderr)
- throws ZygoteInit.MethodAndArgsCaller {
-
- /*
- * First, set the capabilities if necessary
- */
-
- if (parsedArgs.uid != 0) {
- try {
- ZygoteInit.setCapabilities(parsedArgs.permittedCapabilities,
- parsedArgs.effectiveCapabilities);
- } catch (IOException ex) {
- Log.e(TAG, "Error setting capabilities", ex);
- }
- }
-
- /*
- * Close the socket, unless we're in "peer wait" mode, in which
- * case it's used to track the liveness of this process.
- */
-
- if (parsedArgs.peerWait) {
- try {
- ZygoteInit.setCloseOnExec(mSocket.getFileDescriptor(), true);
- sPeerWaitSocket = mSocket;
- } catch (IOException ex) {
- Log.e(TAG, "Zygote Child: error setting peer wait "
- + "socket to be close-on-exec", ex);
- }
- } else {
- closeSocket();
- ZygoteInit.closeServerSocket();
- }
-
- if (descriptors != null) {
- try {
- ZygoteInit.reopenStdio(descriptors[0],
- descriptors[1], descriptors[2]);
-
- for (FileDescriptor fd: descriptors) {
- ZygoteInit.closeDescriptor(fd);
- }
- newStderr = System.err;
- } catch (IOException ex) {
- Log.e(TAG, "Error reopening stdio", ex);
- }
- }
-
- if (parsedArgs.runtimeInit) {
- RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
- } else {
- ClassLoader cloader;
-
- if (parsedArgs.classpath != null) {
- cloader
- = new PathClassLoader(parsedArgs.classpath,
- ClassLoader.getSystemClassLoader());
- } else {
- cloader = ClassLoader.getSystemClassLoader();
- }
-
- String className;
- try {
- className = parsedArgs.remainingArgs[0];
- } catch (ArrayIndexOutOfBoundsException ex) {
- logAndPrintError (newStderr,
- "Missing required class name argument", null);
- return;
- }
- String[] mainArgs
- = new String[parsedArgs.remainingArgs.length - 1];
-
- System.arraycopy(parsedArgs.remainingArgs, 1,
- mainArgs, 0, mainArgs.length);
-
- try {
- ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
- } catch (RuntimeException ex) {
- logAndPrintError (newStderr, "Error starting. ", ex);
- }
- }
- }
-
- /**
- * Handles post-fork cleanup of parent proc
- *
- * @param pid != 0; pid of child if &gt; 0 or indication of failed fork
- * if &lt; 0;
- * @param descriptors null-ok; file descriptors for child's new stdio if
- * specified.
- * @param parsedArgs non-null; zygote args
- * @return true for "exit command loop" and false for "continue command
- * loop"
- */
- private boolean handleParentProc(int pid,
- FileDescriptor[] descriptors, Arguments parsedArgs) {
-
- if(pid > 0) {
- // Try to move the new child into the peer's process group.
- try {
- ZygoteInit.setpgid(pid, ZygoteInit.getpgid(peer.getPid()));
- } catch (IOException ex) {
- // This exception is expected in the case where
- // the peer is not in our session
- // TODO get rid of this log message in the case where
- // getsid(0) != getsid(peer.getPid())
- Log.i(TAG, "Zygote: setpgid failed. This is "
- + "normal if peer is not in our session");
- }
- }
-
- try {
- if (descriptors != null) {
- for (FileDescriptor fd: descriptors) {
- ZygoteInit.closeDescriptor(fd);
- }
- }
- } catch (IOException ex) {
- Log.e(TAG, "Error closing passed descriptors in "
- + "parent process", ex);
- }
-
- try {
- mSocketOutStream.writeInt(pid);
- } catch (IOException ex) {
- Log.e(TAG, "Error reading from command socket", ex);
- return true;
- }
-
- /*
- * If the peer wants to use the socket to wait on the
- * newly spawned process, then we're all done.
- */
- if (parsedArgs.peerWait) {
- try {
- mSocket.close();
- } catch (IOException ex) {
- Log.e(TAG, "Zygote: error closing sockets", ex);
- }
- return true;
- }
- return false;
- }
-
- /**
- * Logs an error message and prints it to the specified stream, if
- * provided
- *
- * @param newStderr null-ok; a standard error stream
- * @param message non-null; error message
- * @param ex null-ok an exception
- */
- private static void logAndPrintError (PrintStream newStderr,
- String message, Throwable ex) {
- Log.e(TAG, message, ex);
- if (newStderr != null) {
- newStderr.println(message + (ex == null ? "" : ex));
- }
- }
-}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
deleted file mode 100644
index f21b62f..0000000
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ /dev/null
@@ -1,759 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.os;
-
-import android.content.pm.ActivityInfo;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.net.LocalServerSocket;
-import android.os.Debug;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.util.Config;
-import android.util.EventLog;
-import android.util.Log;
-
-import dalvik.system.VMRuntime;
-import dalvik.system.Zygote;
-
-import java.io.BufferedReader;
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-
-/**
- * Startup class for the zygote process.
- *
- * Pre-initializes some classes, and then waits for commands on a UNIX domain
- * socket. Based on these commands, forks of child processes that inherit
- * the initial state of the VM.
- *
- * Please see {@link ZygoteConnection.Arguments} for documentation on the
- * client protocol.
- *
- * @hide
- */
-public class ZygoteInit {
-
- private static final String TAG = "Zygote";
-
- private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";
-
- private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020;
- private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030;
-
- /** when preloading, GC after allocating this many bytes */
- private static final int PRELOAD_GC_THRESHOLD = 50000;
-
- private static LocalServerSocket sServerSocket;
-
- /**
- * Used to pre-load resources. We hold a global reference on it so it
- * never gets destroyed.
- */
- private static Resources mResources;
-
- /**
- * The number of times that the main Zygote loop
- * should run before calling gc() again.
- */
- static final int GC_LOOP_COUNT = 10;
-
- /**
- * If true, zygote forks for each peer. If false, a select loop is used
- * inside a single process. The latter is preferred.
- */
- private static final boolean ZYGOTE_FORK_MODE = false;
-
- /**
- * The name of a resource file that contains classes to preload.
- */
- private static final String PRELOADED_CLASSES = "preloaded-classes";
-
- /** Controls whether we should preload resources during zygote init. */
- private static final boolean PRELOAD_RESOURCES = true;
-
- /**
- * Invokes a static "main(argv[]) method on class "className".
- * Converts various failing exceptions into RuntimeExceptions, with
- * the assumption that they will then cause the VM instance to exit.
- *
- * @param loader class loader to use
- * @param className Fully-qualified class name
- * @param argv Argument vector for main()
- */
- static void invokeStaticMain(ClassLoader loader,
- String className, String[] argv)
- throws ZygoteInit.MethodAndArgsCaller {
- Class<?> cl;
-
- try {
- cl = loader.loadClass(className);
- } catch (ClassNotFoundException ex) {
- throw new RuntimeException(
- "Missing class when invoking static main " + className,
- ex);
- }
-
- Method m;
- try {
- m = cl.getMethod("main", new Class[] { String[].class });
- } catch (NoSuchMethodException ex) {
- throw new RuntimeException(
- "Missing static main on " + className, ex);
- } catch (SecurityException ex) {
- throw new RuntimeException(
- "Problem getting static main on " + className, ex);
- }
-
- int modifiers = m.getModifiers();
- if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
- throw new RuntimeException(
- "Main method is not public and static on " + className);
- }
-
- /*
- * This throw gets caught in ZygoteInit.main(), which responds
- * by invoking the exception's run() method. This arrangement
- * clears up all the stack frames that were required in setting
- * up the process.
- */
- throw new ZygoteInit.MethodAndArgsCaller(m, argv);
- }
-
- /**
- * Registers a server socket for zygote command connections
- *
- * @throws RuntimeException when open fails
- */
- private static void registerZygoteSocket() {
- if (sServerSocket == null) {
- int fileDesc;
- try {
- String env = System.getenv(ANDROID_SOCKET_ENV);
- fileDesc = Integer.parseInt(env);
- } catch (RuntimeException ex) {
- throw new RuntimeException(
- ANDROID_SOCKET_ENV + " unset or invalid", ex);
- }
-
- try {
- sServerSocket = new LocalServerSocket(
- createFileDescriptor(fileDesc));
- } catch (IOException ex) {
- throw new RuntimeException(
- "Error binding to local socket '" + fileDesc + "'", ex);
- }
- }
- }
-
- /**
- * Waits for and accepts a single command connection. Throws
- * RuntimeException on failure.
- */
- private static ZygoteConnection acceptCommandPeer() {
- try {
- return new ZygoteConnection(sServerSocket.accept());
- } catch (IOException ex) {
- throw new RuntimeException(
- "IOException during accept()", ex);
- }
- }
-
- /**
- * Close and clean up zygote sockets. Called on shutdown and on the
- * child's exit path.
- */
- static void closeServerSocket() {
- try {
- if (sServerSocket != null) {
- sServerSocket.close();
- }
- } catch (IOException ex) {
- Log.e(TAG, "Zygote: error closing sockets", ex);
- }
-
- sServerSocket = null;
- }
-
- private static final int UNPRIVILEGED_UID = 9999;
- private static final int UNPRIVILEGED_GID = 9999;
-
- private static final int ROOT_UID = 0;
- private static final int ROOT_GID = 0;
-
- /**
- * Sets effective user ID.
- */
- private static void setEffectiveUser(int uid) {
- int errno = setreuid(ROOT_UID, uid);
- if (errno != 0) {
- Log.e(TAG, "setreuid() failed. errno: " + errno);
- }
- }
-
- /**
- * Sets effective group ID.
- */
- private static void setEffectiveGroup(int gid) {
- int errno = setregid(ROOT_GID, gid);
- if (errno != 0) {
- Log.e(TAG, "setregid() failed. errno: " + errno);
- }
- }
-
- /**
- * Performs Zygote process initialization. Loads and initializes
- * commonly used classes.
- *
- * Most classes only cause a few hundred bytes to be allocated, but
- * a few will allocate a dozen Kbytes (in one case, 500+K).
- */
- private static void preloadClasses() {
- final VMRuntime runtime = VMRuntime.getRuntime();
-
- InputStream is = ZygoteInit.class.getClassLoader().getResourceAsStream(
- PRELOADED_CLASSES);
- if (is == null) {
- Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
- } else {
- Log.i(TAG, "Preloading classes...");
- long startTime = SystemClock.uptimeMillis();
-
- // Drop root perms while running static initializers.
- setEffectiveGroup(UNPRIVILEGED_GID);
- setEffectiveUser(UNPRIVILEGED_UID);
-
- // Alter the target heap utilization. With explicit GCs this
- // is not likely to have any effect.
- float defaultUtilization = runtime.getTargetHeapUtilization();
- runtime.setTargetHeapUtilization(0.8f);
-
- // Start with a clean slate.
- runtime.gcSoftReferences();
- runtime.runFinalizationSync();
- Debug.startAllocCounting();
-
- try {
- BufferedReader br
- = new BufferedReader(new InputStreamReader(is), 256);
-
- int count = 0;
- String line;
- String missingClasses = null;
- while ((line = br.readLine()) != null) {
- // Skip comments and blank lines.
- line = line.trim();
- if (line.startsWith("#") || line.equals("")) {
- continue;
- }
-
- try {
- if (Config.LOGV) {
- Log.v(TAG, "Preloading " + line + "...");
- }
- Class.forName(line);
- if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
- if (Config.LOGV) {
- Log.v(TAG,
- " GC at " + Debug.getGlobalAllocSize());
- }
- runtime.gcSoftReferences();
- runtime.runFinalizationSync();
- Debug.resetGlobalAllocSize();
- }
- count++;
- } catch (ClassNotFoundException e) {
- Log.e(TAG, "Class not found for preloading: " + line);
- if (missingClasses == null) {
- missingClasses = line;
- } else {
- missingClasses += " " + line;
- }
- }
- }
-
- if (missingClasses != null &&
- "1".equals(SystemProperties.get("persist.service.adb.enable"))) {
- throw new IllegalStateException(
- "Missing class(es) for preloading, update preloaded-classes ["
- + missingClasses + "]");
- }
-
- Log.i(TAG, "...preloaded " + count + " classes in "
- + (SystemClock.uptimeMillis()-startTime) + "ms.");
- } catch (IOException e) {
- Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
- } finally {
- // Restore default.
- runtime.setTargetHeapUtilization(defaultUtilization);
-
- Debug.stopAllocCounting();
-
- // Bring back root. We'll need it later.
- setEffectiveUser(ROOT_UID);
- setEffectiveGroup(ROOT_GID);
- }
- }
- }
-
- /**
- * Load in commonly used resources, so they can be shared across
- * processes.
- *
- * These tend to be a few Kbytes, but are frequently in the 20-40K
- * range, and occasionally even larger.
- */
- private static void preloadResources() {
- final VMRuntime runtime = VMRuntime.getRuntime();
-
- Debug.startAllocCounting();
- try {
- runtime.gcSoftReferences();
- runtime.runFinalizationSync();
- mResources = Resources.getSystem();
- mResources.startPreloading();
- if (PRELOAD_RESOURCES) {
- Log.i(TAG, "Preloading resources...");
- long startTime = SystemClock.uptimeMillis();
- TypedArray ar = mResources.obtainTypedArray(
- com.android.internal.R.array.preloaded_drawables);
- int N = ar.length();
- for (int i=0; i<N; i++) {
- if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
- if (Config.LOGV) {
- Log.v(TAG, " GC at " + Debug.getGlobalAllocSize());
- }
- runtime.gcSoftReferences();
- runtime.runFinalizationSync();
- Debug.resetGlobalAllocSize();
- }
- int id = ar.getResourceId(i, 0);
- if (Config.LOGV) {
- Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
- }
- if (id != 0) {
- Drawable dr = mResources.getDrawable(id);
- if ((dr.getChangingConfigurations()&~ActivityInfo.CONFIG_FONT_SCALE) != 0) {
- Log.w(TAG, "Preloaded drawable resource #0x"
- + Integer.toHexString(id)
- + " that varies with configuration!!");
- }
- }
- }
- Log.i(TAG, "...preloaded " + N + " resources in "
- + (SystemClock.uptimeMillis()-startTime) + "ms.");
- }
- mResources.finishPreloading();
- } catch (RuntimeException e) {
- Log.w(TAG, "Failure preloading resources", e);
- } finally {
- Debug.stopAllocCounting();
- }
- }
-
- /**
- * Runs several special GCs to try to clean up a few generations of
- * softly- and final-reachable objects, along with any other garbage.
- * This is only useful just before a fork().
- */
- /*package*/ static void gc() {
- final VMRuntime runtime = VMRuntime.getRuntime();
-
- /* runFinalizationSync() lets finalizers be called in Zygote,
- * which doesn't have a HeapWorker thread.
- */
- runtime.gcSoftReferences();
- runtime.runFinalizationSync();
- runtime.gcSoftReferences();
- runtime.runFinalizationSync();
- runtime.gcSoftReferences();
- runtime.runFinalizationSync();
- }
-
- /**
- * Finish remaining work for the newly forked system server process.
- */
- private static void handleSystemServerProcess(
- ZygoteConnection.Arguments parsedArgs)
- throws ZygoteInit.MethodAndArgsCaller {
- /*
- * First, set the capabilities if necessary
- */
-
- if (parsedArgs.uid != 0) {
- try {
- setCapabilities(parsedArgs.permittedCapabilities,
- parsedArgs.effectiveCapabilities);
- } catch (IOException ex) {
- Log.e(TAG, "Error setting capabilities", ex);
- }
- }
-
- closeServerSocket();
-
- /*
- * Pass the remaining arguments to SystemServer.
- * "--nice-name=system_server com.android.server.SystemServer"
- */
- RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
- /* should never reach here */
- }
-
- /**
- * Prepare the arguments and fork for the system server process.
- */
- private static boolean startSystemServer()
- throws MethodAndArgsCaller, RuntimeException {
- /* Hardcoded command line to start the system server */
- String args[] = {
- "--setuid=1000",
- "--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",
- "--capabilities=121715744,121715744",
- "--runtime-init",
- "--nice-name=system_server",
- "com.android.server.SystemServer",
- };
- ZygoteConnection.Arguments parsedArgs = null;
-
- int pid;
-
- try {
- parsedArgs = new ZygoteConnection.Arguments(args);
-
- /*
- * Enable debugging of the system process if *either* the command line flags
- * indicate it should be debuggable or the ro.debuggable system property
- * is set to "1"
- */
- int debugFlags = parsedArgs.debugFlags;
- if ("1".equals(SystemProperties.get("ro.debuggable")))
- debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
-
- /* Request to fork the system server process */
- pid = Zygote.forkSystemServer(
- parsedArgs.uid, parsedArgs.gid,
- parsedArgs.gids, debugFlags, null);
- } catch (IllegalArgumentException ex) {
- throw new RuntimeException(ex);
- }
-
- /* For child process */
- if (pid == 0) {
- handleSystemServerProcess(parsedArgs);
- }
-
- return true;
- }
-
- public static void main(String argv[]) {
- try {
- registerZygoteSocket();
- EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
- SystemClock.uptimeMillis());
- preloadClasses();
- preloadResources();
- EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
- SystemClock.uptimeMillis());
-
- // Do an initial gc to clean up after startup
- gc();
-
- // If requested, start system server directly from Zygote
- if (argv.length != 2) {
- throw new RuntimeException(
- "ZygoteInit.main expects two arguments");
- }
-
- if (argv[1].equals("true")) {
- startSystemServer();
- }
-
- Log.i(TAG, "Accepting command socket connections");
-
- if (ZYGOTE_FORK_MODE) {
- runForkMode();
- } else {
- runSelectLoopMode();
- }
-
- closeServerSocket();
- } catch (MethodAndArgsCaller caller) {
- caller.run();
- } catch (RuntimeException ex) {
- Log.e(TAG, "Zygote died with exception", ex);
- closeServerSocket();
- throw ex;
- }
- }
-
- /**
- * Runs the zygote in accept-and-fork mode. In this mode, each peer
- * gets its own zygote spawner process. This code is retained for
- * reference only.
- *
- * @throws MethodAndArgsCaller in a child process when a main() should
- * be executed.
- */
- private static void runForkMode() throws MethodAndArgsCaller {
- while (true) {
- ZygoteConnection peer = acceptCommandPeer();
-
- int pid;
-
- pid = Zygote.fork();
-
- if (pid == 0) {
- // The child process should handle the peer requests
-
- // The child does not accept any more connections
- try {
- sServerSocket.close();
- } catch (IOException ex) {
- Log.e(TAG, "Zygote Child: error closing sockets", ex);
- } finally {
- sServerSocket = null;
- }
-
- peer.run();
- break;
- } else if (pid > 0) {
- peer.closeSocket();
- } else {
- throw new RuntimeException("Error invoking fork()");
- }
- }
- }
-
- /**
- * Runs the zygote process's select loop. Accepts new connections as
- * they happen, and reads commands from connections one spawn-request's
- * worth at a time.
- *
- * @throws MethodAndArgsCaller in a child process when a main() should
- * be executed.
- */
- private static void runSelectLoopMode() throws MethodAndArgsCaller {
- ArrayList<FileDescriptor> fds = new ArrayList();
- ArrayList<ZygoteConnection> peers = new ArrayList();
- FileDescriptor[] fdArray = new FileDescriptor[4];
-
- fds.add(sServerSocket.getFileDescriptor());
- peers.add(null);
-
- int loopCount = GC_LOOP_COUNT;
- while (true) {
- int index;
-
- /*
- * Call gc() before we block in select().
- * It's work that has to be done anyway, and it's better
- * to avoid making every child do it. It will also
- * madvise() any free memory as a side-effect.
- *
- * Don't call it every time, because walking the entire
- * heap is a lot of overhead to free a few hundred bytes.
- */
- if (loopCount <= 0) {
- gc();
- loopCount = GC_LOOP_COUNT;
- } else {
- loopCount--;
- }
-
-
- try {
- fdArray = fds.toArray(fdArray);
- index = selectReadable(fdArray);
- } catch (IOException ex) {
- throw new RuntimeException("Error in select()", ex);
- }
-
- if (index < 0) {
- throw new RuntimeException("Error in select()");
- } else if (index == 0) {
- ZygoteConnection newPeer = acceptCommandPeer();
- peers.add(newPeer);
- fds.add(newPeer.getFileDesciptor());
- } else {
- boolean done;
- done = peers.get(index).runOnce();
-
- if (done) {
- peers.remove(index);
- fds.remove(index);
- }
- }
- }
- }
-
- /**
- * The Linux syscall "setreuid()"
- * @param ruid real uid
- * @param euid effective uid
- * @return 0 on success, non-zero errno on fail
- */
- static native int setreuid(int ruid, int euid);
-
- /**
- * The Linux syscall "setregid()"
- * @param rgid real gid
- * @param egid effective gid
- * @return 0 on success, non-zero errno on fail
- */
- static native int setregid(int rgid, int egid);
-
- /**
- * Invokes the linux syscall "setpgid"
- *
- * @param pid pid to change
- * @param pgid new process group of pid
- * @return 0 on success or non-zero errno on fail
- */
- static native int setpgid(int pid, int pgid);
-
- /**
- * Invokes the linux syscall "getpgid"
- *
- * @param pid pid to query
- * @return pgid of pid in question
- * @throws IOException on error
- */
- static native int getpgid(int pid) throws IOException;
-
- /**
- * Invokes the syscall dup2() to copy the specified descriptors into
- * stdin, stdout, and stderr. The existing stdio descriptors will be
- * closed and errors during close will be ignored. The specified
- * descriptors will also remain open at their original descriptor numbers,
- * so the caller may want to close the original descriptors.
- *
- * @param in new stdin
- * @param out new stdout
- * @param err new stderr
- * @throws IOException
- */
- static native void reopenStdio(FileDescriptor in,
- FileDescriptor out, FileDescriptor err) throws IOException;
-
- /**
- * Calls close() on a file descriptor
- *
- * @param fd descriptor to close
- * @throws IOException
- */
- static native void closeDescriptor(FileDescriptor fd)
- throws IOException;
-
- /**
- * Toggles the close-on-exec flag for the specified file descriptor.
- *
- * @param fd non-null; file descriptor
- * @param flag desired close-on-exec flag state
- * @throws IOException
- */
- static native void setCloseOnExec(FileDescriptor fd, boolean flag)
- throws IOException;
-
- /**
- * Retrieves the permitted capability set from another process.
- *
- * @param pid &gt;=0 process ID or 0 for this process
- * @throws IOException on error
- */
- static native long capgetPermitted(int pid)
- throws IOException;
-
- /**
- * Sets the permitted and effective capability sets of this process.
- *
- * @param permittedCapabilities permitted set
- * @param effectiveCapabilities effective set
- * @throws IOException on error
- */
- static native void setCapabilities(
- long permittedCapabilities,
- long effectiveCapabilities) throws IOException;
-
- /**
- * Invokes select() on the provider array of file descriptors (selecting
- * for readability only). Array elements of null are ignored.
- *
- * @param fds non-null; array of readable file descriptors
- * @return index of descriptor that is now readable or -1 for empty array.
- * @throws IOException if an error occurs
- */
- static native int selectReadable(FileDescriptor[] fds) throws IOException;
-
- /**
- * Creates a file descriptor from an int fd.
- *
- * @param fd integer OS file descriptor
- * @return non-null; FileDescriptor instance
- * @throws IOException if fd is invalid
- */
- static native FileDescriptor createFileDescriptor(int fd)
- throws IOException;
-
- /**
- * Class not instantiable.
- */
- private ZygoteInit() {
- }
-
- /**
- * Helper exception class which holds a method and arguments and
- * can call them. This is used as part of a trampoline to get rid of
- * the initial process setup stack frames.
- */
- public static class MethodAndArgsCaller extends Exception
- implements Runnable {
- /** method to call */
- private final Method mMethod;
-
- /** argument array */
- private final String[] mArgs;
-
- public MethodAndArgsCaller(Method method, String[] args) {
- mMethod = method;
- mArgs = args;
- }
-
- public void run() {
- try {
- mMethod.invoke(null, new Object[] { mArgs });
- } catch (IllegalAccessException ex) {
- throw new RuntimeException(ex);
- } catch (InvocationTargetException ex) {
- Throwable cause = ex.getCause();
- if (cause instanceof RuntimeException) {
- throw (RuntimeException) cause;
- } else if (cause instanceof Error) {
- throw (Error) cause;
- }
- throw new RuntimeException(ex);
- }
- }
- }
-}
diff --git a/core/java/com/android/internal/os/ZygoteSecurityException.java b/core/java/com/android/internal/os/ZygoteSecurityException.java
deleted file mode 100644
index 13b4759..0000000
--- a/core/java/com/android/internal/os/ZygoteSecurityException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.os;
-
-/**
- * Exception thrown when a security policy is violated.
- */
-class ZygoteSecurityException extends RuntimeException {
- ZygoteSecurityException(String message) {
- super(message);
- }
-}
diff --git a/core/java/com/android/internal/package.html b/core/java/com/android/internal/package.html
deleted file mode 100644
index db6f78b..0000000
--- a/core/java/com/android/internal/package.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<body>
-{@hide}
-</body> \ No newline at end of file
diff --git a/core/java/com/android/internal/policy/IPolicy.java b/core/java/com/android/internal/policy/IPolicy.java
deleted file mode 100644
index 73db0b7..0000000
--- a/core/java/com/android/internal/policy/IPolicy.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.policy;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.Window;
-import android.view.WindowManagerPolicy;
-
-/**
- * {@hide}
- */
-
-/* The implementation of this interface must be called Policy and contained
- * within the com.android.internal.policy.impl package */
-public interface IPolicy {
- public Window makeNewWindow(Context context);
-
- public LayoutInflater makeNewLayoutInflater(Context context);
-
- public WindowManagerPolicy makeNewWindowManager();
-}
diff --git a/core/java/com/android/internal/policy/PolicyManager.java b/core/java/com/android/internal/policy/PolicyManager.java
deleted file mode 100644
index 4ed5a14..0000000
--- a/core/java/com/android/internal/policy/PolicyManager.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.policy;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.Window;
-import android.view.WindowManagerPolicy;
-
-import com.android.internal.policy.IPolicy;
-
-/**
- * {@hide}
- */
-
-public final class PolicyManager {
- private static final String POLICY_IMPL_CLASS_NAME =
- "com.android.internal.policy.impl.Policy";
-
- private static final IPolicy sPolicy;
-
- static {
- // Pull in the actual implementation of the policy at run-time
- try {
- Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
- sPolicy = (IPolicy)policyClass.newInstance();
- } catch (ClassNotFoundException ex) {
- throw new RuntimeException(
- POLICY_IMPL_CLASS_NAME + " could not be loaded", ex);
- } catch (InstantiationException ex) {
- throw new RuntimeException(
- POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex);
- } catch (IllegalAccessException ex) {
- throw new RuntimeException(
- POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex);
- }
- }
-
- // Cannot instantiate this class
- private PolicyManager() {}
-
- // The static methods to spawn new policy-specific objects
- public static Window makeNewWindow(Context context) {
- return sPolicy.makeNewWindow(context);
- }
-
- public static LayoutInflater makeNewLayoutInflater(Context context) {
- return sPolicy.makeNewLayoutInflater(context);
- }
-
- public static WindowManagerPolicy makeNewWindowManager() {
- return sPolicy.makeNewWindowManager();
- }
-}
diff --git a/core/java/com/android/internal/policy/package.html b/core/java/com/android/internal/policy/package.html
deleted file mode 100644
index c9f96a6..0000000
--- a/core/java/com/android/internal/policy/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>
diff --git a/core/java/com/android/internal/preference/YesNoPreference.java b/core/java/com/android/internal/preference/YesNoPreference.java
deleted file mode 100644
index cf68a58..0000000
--- a/core/java/com/android/internal/preference/YesNoPreference.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.preference;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.preference.DialogPreference;
-import android.util.AttributeSet;
-
-/**
- * The {@link YesNoPreference} is a preference to show a dialog with Yes and No
- * buttons.
- * <p>
- * This preference will store a boolean into the SharedPreferences.
- */
-public class YesNoPreference extends DialogPreference {
- private boolean mWasPositiveResult;
-
- public YesNoPreference(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- public YesNoPreference(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.yesNoPreferenceStyle);
- }
-
- public YesNoPreference(Context context) {
- this(context, null);
- }
-
- @Override
- protected void onDialogClosed(boolean positiveResult) {
- super.onDialogClosed(positiveResult);
-
- if (callChangeListener(positiveResult)) {
- setValue(positiveResult);
- }
- }
-
- /**
- * Sets the value of this preference, and saves it to the persistent store
- * if required.
- *
- * @param value The value of the preference.
- */
- public void setValue(boolean value) {
- mWasPositiveResult = value;
-
- persistBoolean(value);
-
- notifyDependencyChange(!value);
- }
-
- /**
- * Gets the value of this preference.
- *
- * @return The value of the preference.
- */
- public boolean getValue() {
- return mWasPositiveResult;
- }
-
- @Override
- protected Object onGetDefaultValue(TypedArray a, int index) {
- return a.getBoolean(index, false);
- }
-
- @Override
- protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
- setValue(restorePersistedValue ? getPersistedBoolean(mWasPositiveResult) :
- (Boolean) defaultValue);
- }
-
- @Override
- public boolean shouldDisableDependents() {
- return !mWasPositiveResult || super.shouldDisableDependents();
- }
-
- @Override
- protected Parcelable onSaveInstanceState() {
- final Parcelable superState = super.onSaveInstanceState();
- if (isPersistent()) {
- // No need to save instance state since it's persistent
- return superState;
- }
-
- final SavedState myState = new SavedState(superState);
- myState.wasPositiveResult = getValue();
- return myState;
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- if (!state.getClass().equals(SavedState.class)) {
- // Didn't save state for us in onSaveInstanceState
- super.onRestoreInstanceState(state);
- return;
- }
-
- SavedState myState = (SavedState) state;
- super.onRestoreInstanceState(myState.getSuperState());
- setValue(myState.wasPositiveResult);
- }
-
- private static class SavedState extends BaseSavedState {
- boolean wasPositiveResult;
-
- public SavedState(Parcel source) {
- super(source);
- wasPositiveResult = source.readInt() == 1;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(wasPositiveResult ? 1 : 0);
- }
-
- public SavedState(Parcelable superState) {
- super(superState);
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR =
- new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
-}
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
deleted file mode 100644
index 159929b..0000000
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-import java.lang.reflect.Array;
-import java.util.Collection;
-
-// XXX these should be changed to reflect the actual memory allocator we use.
-// it looks like right now objects want to be powers of 2 minus 8
-// and the array size eats another 4 bytes
-
-/**
- * ArrayUtils contains some methods that you can call to find out
- * the most efficient increments by which to grow arrays.
- */
-public class ArrayUtils
-{
- private static Object[] EMPTY = new Object[0];
- private static final int CACHE_SIZE = 73;
- private static Object[] sCache = new Object[CACHE_SIZE];
-
- private ArrayUtils() { /* cannot be instantiated */ }
-
- public static int idealByteArraySize(int need) {
- for (int i = 4; i < 32; i++)
- if (need <= (1 << i) - 12)
- return (1 << i) - 12;
-
- return need;
- }
-
- public static int idealBooleanArraySize(int need) {
- return idealByteArraySize(need);
- }
-
- public static int idealShortArraySize(int need) {
- return idealByteArraySize(need * 2) / 2;
- }
-
- public static int idealCharArraySize(int need) {
- return idealByteArraySize(need * 2) / 2;
- }
-
- public static int idealIntArraySize(int need) {
- return idealByteArraySize(need * 4) / 4;
- }
-
- public static int idealFloatArraySize(int need) {
- return idealByteArraySize(need * 4) / 4;
- }
-
- public static int idealObjectArraySize(int need) {
- return idealByteArraySize(need * 4) / 4;
- }
-
- public static int idealLongArraySize(int need) {
- return idealByteArraySize(need * 8) / 8;
- }
-
- /**
- * Checks if the beginnings of two byte arrays are equal.
- *
- * @param array1 the first byte array
- * @param array2 the second byte array
- * @param length the number of bytes to check
- * @return true if they're equal, false otherwise
- */
- public static boolean equals(byte[] array1, byte[] array2, int length) {
- if (array1 == array2) {
- return true;
- }
- if (array1 == null || array2 == null || array1.length < length || array2.length < length) {
- return false;
- }
- for (int i = 0; i < length; i++) {
- if (array1[i] != array2[i]) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Returns an empty array of the specified type. The intent is that
- * it will return the same empty array every time to avoid reallocation,
- * although this is not guaranteed.
- */
- public static <T> T[] emptyArray(Class<T> kind) {
- if (kind == Object.class) {
- return (T[]) EMPTY;
- }
-
- int bucket = ((System.identityHashCode(kind) / 8) & 0x7FFFFFFF) % CACHE_SIZE;
- Object cache = sCache[bucket];
-
- if (cache == null || cache.getClass().getComponentType() != kind) {
- cache = Array.newInstance(kind, 0);
- sCache[bucket] = cache;
-
- // Log.e("cache", "new empty " + kind.getName() + " at " + bucket);
- }
-
- return (T[]) cache;
- }
-
- /**
- * Checks that value is present as at least one of the elements of the array.
- * @param array the array to check in
- * @param value the value to check for
- * @return true if the value is present in the array
- */
- public static <T> boolean contains(T[] array, T value) {
- for (T element : array) {
- if (element == null) {
- if (value == null) return true;
- } else {
- if (value != null && element.equals(value)) return true;
- }
- }
- return false;
- }
-}
diff --git a/core/java/com/android/internal/util/CharSequences.java b/core/java/com/android/internal/util/CharSequences.java
deleted file mode 100644
index fdaa4bc..0000000
--- a/core/java/com/android/internal/util/CharSequences.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-/**
- * {@link CharSequence} utility methods.
- */
-public class CharSequences {
-
- /**
- * Adapts {@link CharSequence} to an array of ASCII (7-bits per character)
- * bytes.
- *
- * @param bytes ASCII bytes
- */
- public static CharSequence forAsciiBytes(final byte[] bytes) {
- return new CharSequence() {
- public char charAt(int index) {
- return (char) bytes[index];
- }
-
- public int length() {
- return bytes.length;
- }
-
- public CharSequence subSequence(int start, int end) {
- return forAsciiBytes(bytes, start, end);
- }
-
- public String toString() {
- return new String(bytes);
- }
- };
- }
-
- /**
- * Adapts {@link CharSequence} to an array of ASCII (7-bits per character)
- * bytes.
- *
- * @param bytes ASCII bytes
- * @param start index, inclusive
- * @param end index, exclusive
- *
- * @throws IndexOutOfBoundsException if start or end are negative, if end
- * is greater than length(), or if start is greater than end
- */
- public static CharSequence forAsciiBytes(final byte[] bytes,
- final int start, final int end) {
- validate(start, end, bytes.length);
- return new CharSequence() {
- public char charAt(int index) {
- return (char) bytes[index + start];
- }
-
- public int length() {
- return end - start;
- }
-
- public CharSequence subSequence(int newStart, int newEnd) {
- newStart -= start;
- newEnd -= start;
- validate(newStart, newEnd, length());
- return forAsciiBytes(bytes, newStart, newEnd);
- }
-
- public String toString() {
- return new String(bytes, start, length());
- }
- };
- }
-
- static void validate(int start, int end, int length) {
- if (start < 0) throw new IndexOutOfBoundsException();
- if (end < 0) throw new IndexOutOfBoundsException();
- if (end > length) throw new IndexOutOfBoundsException();
- if (start > end) throw new IndexOutOfBoundsException();
- }
-
- /**
- * Compares two character sequences for equality.
- */
- public static boolean equals(CharSequence a, CharSequence b) {
- if (a.length() != b.length()) {
- return false;
- }
-
- int length = a.length();
- for (int i = 0; i < length; i++) {
- if (a.charAt(i) != b.charAt(i)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Compares two character sequences with API like {@link Comparable#compareTo}.
- *
- * @param me The CharSequence that receives the compareTo call.
- * @param another The other CharSequence.
- * @return See {@link Comparable#compareTo}.
- */
- public static int compareToIgnoreCase(CharSequence me, CharSequence another) {
- // Code adapted from String#compareTo
- int myLen = me.length(), anotherLen = another.length();
- int myPos = 0, anotherPos = 0, result;
- int end = (myLen < anotherLen) ? myLen : anotherLen;
-
- while (myPos < end) {
- if ((result = Character.toLowerCase(me.charAt(myPos++))
- - Character.toLowerCase(another.charAt(anotherPos++))) != 0) {
- return result;
- }
- }
- return myLen - anotherLen;
- }
-}
diff --git a/core/java/com/android/internal/util/FastMath.java b/core/java/com/android/internal/util/FastMath.java
deleted file mode 100644
index efd0871..0000000
--- a/core/java/com/android/internal/util/FastMath.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-/**
- * Fast and loose math routines.
- */
-public class FastMath {
-
- /**
- * Fast round from float to int. This is faster than Math.round()
- * thought it may return slightly different results. It does not try to
- * handle (in any meaningful way) NaN or infinities.
- */
- public static int round(float x) {
- long lx = (long)(x * (65536 * 256f));
- return (int)((lx + 0x800000) >> 24);
- }
-}
diff --git a/core/java/com/android/internal/util/FastXmlSerializer.java b/core/java/com/android/internal/util/FastXmlSerializer.java
deleted file mode 100644
index 592a8fa..0000000
--- a/core/java/com/android/internal/util/FastXmlSerializer.java
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CoderResult;
-import java.nio.charset.IllegalCharsetNameException;
-import java.nio.charset.UnsupportedCharsetException;
-
-/**
- * This is a quick and dirty implementation of XmlSerializer that isn't horribly
- * painfully slow like the normal one. It only does what is needed for the
- * specific XML files being written with it.
- */
-public class FastXmlSerializer implements XmlSerializer {
- private static final String ESCAPE_TABLE[] = new String[] {
- null, null, null, null, null, null, null, null, // 0-7
- null, null, null, null, null, null, null, null, // 8-15
- null, null, null, null, null, null, null, null, // 16-23
- null, null, null, null, null, null, null, null, // 24-31
- null, null, "&quot;", null, null, null, "&amp;", null, // 32-39
- null, null, null, null, null, null, null, null, // 40-47
- null, null, null, null, null, null, null, null, // 48-55
- null, null, null, null, "&lt;", null, "&gt;", null, // 56-63
- };
-
- private static final int BUFFER_LEN = 8192;
-
- private final char[] mText = new char[BUFFER_LEN];
- private int mPos;
-
- private Writer mWriter;
-
- private OutputStream mOutputStream;
- private CharsetEncoder mCharset;
- private ByteBuffer mBytes = ByteBuffer.allocate(BUFFER_LEN);
-
- private boolean mInTag;
-
- private void append(char c) throws IOException {
- int pos = mPos;
- if (pos >= (BUFFER_LEN-1)) {
- flush();
- pos = mPos;
- }
- mText[pos] = c;
- mPos = pos+1;
- }
-
- private void append(String str, int i, final int length) throws IOException {
- if (length > BUFFER_LEN) {
- final int end = i + length;
- while (i < end) {
- int next = i + BUFFER_LEN;
- append(str, i, next<end ? BUFFER_LEN : (end-i));
- i = next;
- }
- return;
- }
- int pos = mPos;
- if ((pos+length) > BUFFER_LEN) {
- flush();
- pos = mPos;
- }
- str.getChars(i, i+length, mText, pos);
- mPos = pos + length;
- }
-
- private void append(char[] buf, int i, final int length) throws IOException {
- if (length > BUFFER_LEN) {
- final int end = i + length;
- while (i < end) {
- int next = i + BUFFER_LEN;
- append(buf, i, next<end ? BUFFER_LEN : (end-i));
- i = next;
- }
- return;
- }
- int pos = mPos;
- if ((pos+length) > BUFFER_LEN) {
- flush();
- pos = mPos;
- }
- System.arraycopy(buf, i, mText, pos, length);
- mPos = pos + length;
- }
-
- private void append(String str) throws IOException {
- append(str, 0, str.length());
- }
-
- private void escapeAndAppendString(final String string) throws IOException {
- final int N = string.length();
- final char NE = (char)ESCAPE_TABLE.length;
- final String[] escapes = ESCAPE_TABLE;
- int lastPos = 0;
- int pos;
- for (pos=0; pos<N; pos++) {
- char c = string.charAt(pos);
- if (c >= NE) continue;
- String escape = escapes[c];
- if (escape == null) continue;
- if (lastPos < pos) append(string, lastPos, pos-lastPos);
- lastPos = pos + 1;
- append(escape);
- }
- if (lastPos < pos) append(string, lastPos, pos-lastPos);
- }
-
- private void escapeAndAppendString(char[] buf, int start, int len) throws IOException {
- final char NE = (char)ESCAPE_TABLE.length;
- final String[] escapes = ESCAPE_TABLE;
- int end = start+len;
- int lastPos = start;
- int pos;
- for (pos=start; pos<end; pos++) {
- char c = buf[pos];
- if (c >= NE) continue;
- String escape = escapes[c];
- if (escape == null) continue;
- if (lastPos < pos) append(buf, lastPos, pos-lastPos);
- lastPos = pos + 1;
- append(escape);
- }
- if (lastPos < pos) append(buf, lastPos, pos-lastPos);
- }
-
- public XmlSerializer attribute(String namespace, String name, String value) throws IOException,
- IllegalArgumentException, IllegalStateException {
- append(' ');
- if (namespace != null) {
- append(namespace);
- append(':');
- }
- append(name);
- append("=\"");
-
- escapeAndAppendString(value);
- append('"');
- return this;
- }
-
- public void cdsect(String text) throws IOException, IllegalArgumentException,
- IllegalStateException {
- throw new UnsupportedOperationException();
- }
-
- public void comment(String text) throws IOException, IllegalArgumentException,
- IllegalStateException {
- throw new UnsupportedOperationException();
- }
-
- public void docdecl(String text) throws IOException, IllegalArgumentException,
- IllegalStateException {
- throw new UnsupportedOperationException();
- }
-
- public void endDocument() throws IOException, IllegalArgumentException, IllegalStateException {
- flush();
- }
-
- public XmlSerializer endTag(String namespace, String name) throws IOException,
- IllegalArgumentException, IllegalStateException {
- if (mInTag) {
- append(" />\n");
- } else {
- append("</");
- if (namespace != null) {
- append(namespace);
- append(':');
- }
- append(name);
- append(">\n");
- }
- mInTag = false;
- return this;
- }
-
- public void entityRef(String text) throws IOException, IllegalArgumentException,
- IllegalStateException {
- throw new UnsupportedOperationException();
- }
-
- private void flushBytes() throws IOException {
- int position;
- if ((position = mBytes.position()) > 0) {
- mBytes.flip();
- mOutputStream.write(mBytes.array(), 0, position);
- mBytes.clear();
- }
- }
-
- public void flush() throws IOException {
- //Log.i("PackageManager", "flush mPos=" + mPos);
- if (mPos > 0) {
- if (mOutputStream != null) {
- CharBuffer charBuffer = CharBuffer.wrap(mText, 0, mPos);
- CoderResult result = mCharset.encode(charBuffer, mBytes, true);
- while (true) {
- if (result.isError()) {
- throw new IOException(result.toString());
- } else if (result.isOverflow()) {
- flushBytes();
- result = mCharset.encode(charBuffer, mBytes, true);
- continue;
- }
- break;
- }
- flushBytes();
- mOutputStream.flush();
- } else {
- mWriter.write(mText, 0, mPos);
- mWriter.flush();
- }
- mPos = 0;
- }
- }
-
- public int getDepth() {
- throw new UnsupportedOperationException();
- }
-
- public boolean getFeature(String name) {
- throw new UnsupportedOperationException();
- }
-
- public String getName() {
- throw new UnsupportedOperationException();
- }
-
- public String getNamespace() {
- throw new UnsupportedOperationException();
- }
-
- public String getPrefix(String namespace, boolean generatePrefix)
- throws IllegalArgumentException {
- throw new UnsupportedOperationException();
- }
-
- public Object getProperty(String name) {
- throw new UnsupportedOperationException();
- }
-
- public void ignorableWhitespace(String text) throws IOException, IllegalArgumentException,
- IllegalStateException {
- throw new UnsupportedOperationException();
- }
-
- public void processingInstruction(String text) throws IOException, IllegalArgumentException,
- IllegalStateException {
- throw new UnsupportedOperationException();
- }
-
- public void setFeature(String name, boolean state) throws IllegalArgumentException,
- IllegalStateException {
- if (name.equals("http://xmlpull.org/v1/doc/features.html#indent-output")) {
- return;
- }
- throw new UnsupportedOperationException();
- }
-
- public void setOutput(OutputStream os, String encoding) throws IOException,
- IllegalArgumentException, IllegalStateException {
- if (os == null)
- throw new IllegalArgumentException();
- if (true) {
- try {
- mCharset = Charset.forName(encoding).newEncoder();
- } catch (IllegalCharsetNameException e) {
- throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
- encoding).initCause(e));
- } catch (UnsupportedCharsetException e) {
- throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
- encoding).initCause(e));
- }
- mOutputStream = os;
- } else {
- setOutput(
- encoding == null
- ? new OutputStreamWriter(os)
- : new OutputStreamWriter(os, encoding));
- }
- }
-
- public void setOutput(Writer writer) throws IOException, IllegalArgumentException,
- IllegalStateException {
- mWriter = writer;
- }
-
- public void setPrefix(String prefix, String namespace) throws IOException,
- IllegalArgumentException, IllegalStateException {
- throw new UnsupportedOperationException();
- }
-
- public void setProperty(String name, Object value) throws IllegalArgumentException,
- IllegalStateException {
- throw new UnsupportedOperationException();
- }
-
- public void startDocument(String encoding, Boolean standalone) throws IOException,
- IllegalArgumentException, IllegalStateException {
- append("<?xml version='1.0' encoding='utf-8' standalone='"
- + (standalone ? "yes" : "no") + "' ?>\n");
- }
-
- public XmlSerializer startTag(String namespace, String name) throws IOException,
- IllegalArgumentException, IllegalStateException {
- if (mInTag) {
- append(">\n");
- }
- append('<');
- if (namespace != null) {
- append(namespace);
- append(':');
- }
- append(name);
- mInTag = true;
- return this;
- }
-
- public XmlSerializer text(char[] buf, int start, int len) throws IOException,
- IllegalArgumentException, IllegalStateException {
- if (mInTag) {
- append(">");
- mInTag = false;
- }
- escapeAndAppendString(buf, start, len);
- return this;
- }
-
- public XmlSerializer text(String text) throws IOException, IllegalArgumentException,
- IllegalStateException {
- if (mInTag) {
- append(">");
- mInTag = false;
- }
- escapeAndAppendString(text);
- return this;
- }
-
-}
diff --git a/core/java/com/android/internal/util/HexDump.java b/core/java/com/android/internal/util/HexDump.java
deleted file mode 100644
index 3c7b7ac..0000000
--- a/core/java/com/android/internal/util/HexDump.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-public class HexDump
-{
- private final static char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-
- public static String dumpHexString(byte[] array)
- {
- return dumpHexString(array, 0, array.length);
- }
-
- public static String dumpHexString(byte[] array, int offset, int length)
- {
- StringBuilder result = new StringBuilder();
-
- byte[] line = new byte[16];
- int lineIndex = 0;
-
- result.append("\n0x");
- result.append(toHexString(offset));
-
- for (int i = offset ; i < offset + length ; i++)
- {
- if (lineIndex == 16)
- {
- result.append(" ");
-
- for (int j = 0 ; j < 16 ; j++)
- {
- if (line[j] > ' ' && line[j] < '~')
- {
- result.append(new String(line, j, 1));
- }
- else
- {
- result.append(".");
- }
- }
-
- result.append("\n0x");
- result.append(toHexString(i));
- lineIndex = 0;
- }
-
- byte b = array[i];
- result.append(" ");
- result.append(HEX_DIGITS[(b >>> 4) & 0x0F]);
- result.append(HEX_DIGITS[b & 0x0F]);
-
- line[lineIndex++] = b;
- }
-
- if (lineIndex != 16)
- {
- int count = (16 - lineIndex) * 3;
- count++;
- for (int i = 0 ; i < count ; i++)
- {
- result.append(" ");
- }
-
- for (int i = 0 ; i < lineIndex ; i++)
- {
- if (line[i] > ' ' && line[i] < '~')
- {
- result.append(new String(line, i, 1));
- }
- else
- {
- result.append(".");
- }
- }
- }
-
- return result.toString();
- }
-
- public static String toHexString(byte b)
- {
- return toHexString(toByteArray(b));
- }
-
- public static String toHexString(byte[] array)
- {
- return toHexString(array, 0, array.length);
- }
-
- public static String toHexString(byte[] array, int offset, int length)
- {
- char[] buf = new char[length * 2];
-
- int bufIndex = 0;
- for (int i = offset ; i < offset + length; i++)
- {
- byte b = array[i];
- buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
- buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
- }
-
- return new String(buf);
- }
-
- public static String toHexString(int i)
- {
- return toHexString(toByteArray(i));
- }
-
- public static byte[] toByteArray(byte b)
- {
- byte[] array = new byte[1];
- array[0] = b;
- return array;
- }
-
- public static byte[] toByteArray(int i)
- {
- byte[] array = new byte[4];
-
- array[3] = (byte)(i & 0xFF);
- array[2] = (byte)((i >> 8) & 0xFF);
- array[1] = (byte)((i >> 16) & 0xFF);
- array[0] = (byte)((i >> 24) & 0xFF);
-
- return array;
- }
-
- private static int toByte(char c)
- {
- if (c >= '0' && c <= '9') return (c - '0');
- if (c >= 'A' && c <= 'F') return (c - 'A' + 10);
- if (c >= 'a' && c <= 'f') return (c - 'a' + 10);
-
- throw new RuntimeException ("Invalid hex char '" + c + "'");
- }
-
- public static byte[] hexStringToByteArray(String hexString)
- {
- int length = hexString.length();
- byte[] buffer = new byte[length / 2];
-
- for (int i = 0 ; i < length ; i += 2)
- {
- buffer[i / 2] = (byte)((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i+1)));
- }
-
- return buffer;
- }
-}
diff --git a/core/java/com/android/internal/util/Objects.java b/core/java/com/android/internal/util/Objects.java
deleted file mode 100644
index 598a079..0000000
--- a/core/java/com/android/internal/util/Objects.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-/**
- * Object utility methods.
- */
-public class Objects {
-
- /**
- * Ensures the given object isn't {@code null}.
- *
- * @return the given object
- * @throws NullPointerException if the object is null
- */
- public static <T> T nonNull(T t) {
- if (t == null) {
- throw new NullPointerException();
- }
- return t;
- }
-
- /**
- * Ensures the given object isn't {@code null}.
- *
- * @return the given object
- * @throws NullPointerException if the object is null
- */
- public static <T> T nonNull(T t, String message) {
- if (t == null) {
- throw new NullPointerException(message);
- }
- return t;
- }
-}
diff --git a/core/java/com/android/internal/util/Predicate.java b/core/java/com/android/internal/util/Predicate.java
deleted file mode 100644
index bc6d6b3..0000000
--- a/core/java/com/android/internal/util/Predicate.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-/**
- * A Predicate can determine a true or false value for any input of its
- * parameterized type. For example, a {@code RegexPredicate} might implement
- * {@code Predicate<String>}, and return true for any String that matches its
- * given regular expression.
- * <p/>
- * <p/>
- * Implementors of Predicate which may cause side effects upon evaluation are
- * strongly encouraged to state this fact clearly in their API documentation.
- */
-public interface Predicate<T> {
-
- boolean apply(T t);
-}
diff --git a/core/java/com/android/internal/util/Predicates.java b/core/java/com/android/internal/util/Predicates.java
deleted file mode 100644
index f5051e4..0000000
--- a/core/java/com/android/internal/util/Predicates.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-import java.util.Arrays;
-
-/**
- * Predicates contains static methods for creating the standard set of
- * {@code Predicate} objects.
- */
-public class Predicates {
-
- private Predicates() {
- }
-
- /**
- * Returns a Predicate that evaluates to true iff each of its components
- * evaluates to true. The components are evaluated in order, and evaluation
- * will be "short-circuited" as soon as the answer is determined.
- */
- public static <T> Predicate<T> and(Predicate<? super T>... components) {
- return and(Arrays.asList(components));
- }
-
- /**
- * Returns a Predicate that evaluates to true iff each of its components
- * evaluates to true. The components are evaluated in order, and evaluation
- * will be "short-circuited" as soon as the answer is determined. Does not
- * defensively copy the iterable passed in, so future changes to it will alter
- * the behavior of this Predicate. If components is empty, the returned
- * Predicate will always evaluate to true.
- */
- public static <T> Predicate<T> and(Iterable<? extends Predicate<? super T>> components) {
- return new AndPredicate(components);
- }
-
- /**
- * Returns a Predicate that evaluates to true iff any one of its components
- * evaluates to true. The components are evaluated in order, and evaluation
- * will be "short-circuited" as soon as the answer is determined.
- */
- public static <T> Predicate<T> or(Predicate<? super T>... components) {
- return or(Arrays.asList(components));
- }
-
- /**
- * Returns a Predicate that evaluates to true iff any one of its components
- * evaluates to true. The components are evaluated in order, and evaluation
- * will be "short-circuited" as soon as the answer is determined. Does not
- * defensively copy the iterable passed in, so future changes to it will alter
- * the behavior of this Predicate. If components is empty, the returned
- * Predicate will always evaluate to false.
- */
- public static <T> Predicate<T> or(Iterable<? extends Predicate<? super T>> components) {
- return new OrPredicate(components);
- }
-
- /**
- * Returns a Predicate that evaluates to true iff the given Predicate
- * evaluates to false.
- */
- public static <T> Predicate<T> not(Predicate<? super T> predicate) {
- return new NotPredicate<T>(predicate);
- }
-
- private static class AndPredicate<T> implements Predicate<T> {
- private final Iterable<? extends Predicate<? super T>> components;
-
- private AndPredicate(Iterable<? extends Predicate<? super T>> components) {
- this.components = components;
- }
-
- public boolean apply(T t) {
- for (Predicate<? super T> predicate : components) {
- if (!predicate.apply(t)) {
- return false;
- }
- }
- return true;
- }
- }
-
- private static class OrPredicate<T> implements Predicate<T> {
- private final Iterable<? extends Predicate<? super T>> components;
-
- private OrPredicate(Iterable<? extends Predicate<? super T>> components) {
- this.components = components;
- }
-
- public boolean apply(T t) {
- for (Predicate<? super T> predicate : components) {
- if (predicate.apply(t)) {
- return true;
- }
- }
- return false;
- }
- }
-
- private static class NotPredicate<T> implements Predicate<T> {
- private final Predicate<? super T> predicate;
-
- private NotPredicate(Predicate<? super T> predicate) {
- this.predicate = predicate;
- }
-
- public boolean apply(T t) {
- return !predicate.apply(t);
- }
- }
-}
diff --git a/core/java/com/android/internal/util/WithFramework.java b/core/java/com/android/internal/util/WithFramework.java
deleted file mode 100644
index 7d8596f..0000000
--- a/core/java/com/android/internal/util/WithFramework.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-import java.lang.reflect.Method;
-
-/**
- * Binds native framework methods and then invokes a main class with the
- * remaining arguments.
- */
-class WithFramework {
-
- /**
- * Invokes main(String[]) method on class in args[0] with args[1..n].
- */
- public static void main(String[] args) throws Exception {
- if (args.length == 0) {
- printUsage();
- return;
- }
-
- Class<?> mainClass = Class.forName(args[0]);
-
- System.loadLibrary("android_runtime");
- if (registerNatives() < 0) {
- throw new RuntimeException("Error registering natives.");
- }
-
- String[] newArgs = new String[args.length - 1];
- System.arraycopy(args, 1, newArgs, 0, newArgs.length);
- Method mainMethod = mainClass.getMethod("main", String[].class);
- mainMethod.invoke(null, new Object[] { newArgs });
- }
-
- private static void printUsage() {
- System.err.println("Usage: dalvikvm " + WithFramework.class.getName()
- + " [main class] [args]");
- }
-
- /**
- * Registers native functions. See AndroidRuntime.cpp.
- */
- static native int registerNatives();
-}
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
deleted file mode 100644
index 948e313..0000000
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ /dev/null
@@ -1,796 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import android.util.Xml;
-
-/** {@hide} */
-public class XmlUtils
-{
-
- public static void skipCurrentTag(XmlPullParser parser)
- throws XmlPullParserException, IOException {
- int outerDepth = parser.getDepth();
- int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG
- || parser.getDepth() > outerDepth)) {
- }
- }
-
- public static final int
- convertValueToList(CharSequence value, String[] options, int defaultValue)
- {
- if (null != value) {
- for (int i = 0; i < options.length; i++) {
- if (value.equals(options[i]))
- return i;
- }
- }
-
- return defaultValue;
- }
-
- public static final boolean
- convertValueToBoolean(CharSequence value, boolean defaultValue)
- {
- boolean result = false;
-
- if (null == value)
- return defaultValue;
-
- if (value.equals("1")
- || value.equals("true")
- || value.equals("TRUE"))
- result = true;
-
- return result;
- }
-
- public static final int
- convertValueToInt(CharSequence charSeq, int defaultValue)
- {
- if (null == charSeq)
- return defaultValue;
-
- String nm = charSeq.toString();
-
- // XXX This code is copied from Integer.decode() so we don't
- // have to instantiate an Integer!
-
- int value;
- int sign = 1;
- int index = 0;
- int len = nm.length();
- int base = 10;
-
- if ('-' == nm.charAt(0)) {
- sign = -1;
- index++;
- }
-
- if ('0' == nm.charAt(index)) {
- // Quick check for a zero by itself
- if (index == (len - 1))
- return 0;
-
- char c = nm.charAt(index + 1);
-
- if ('x' == c || 'X' == c) {
- index += 2;
- base = 16;
- } else {
- index++;
- base = 8;
- }
- }
- else if ('#' == nm.charAt(index))
- {
- index++;
- base = 16;
- }
-
- return Integer.parseInt(nm.substring(index), base) * sign;
- }
-
- public static final int
- convertValueToUnsignedInt(String value, int defaultValue)
- {
- if (null == value)
- return defaultValue;
-
- return parseUnsignedIntAttribute(value);
- }
-
- public static final int
- parseUnsignedIntAttribute(CharSequence charSeq)
- {
- String value = charSeq.toString();
-
- long bits;
- int index = 0;
- int len = value.length();
- int base = 10;
-
- if ('0' == value.charAt(index)) {
- // Quick check for zero by itself
- if (index == (len - 1))
- return 0;
-
- char c = value.charAt(index + 1);
-
- if ('x' == c || 'X' == c) { // check for hex
- index += 2;
- base = 16;
- } else { // check for octal
- index++;
- base = 8;
- }
- } else if ('#' == value.charAt(index)) {
- index++;
- base = 16;
- }
-
- return (int) Long.parseLong(value.substring(index), base);
- }
-
- /**
- * Flatten a Map into an output stream as XML. The map can later be
- * read back with readMapXml().
- *
- * @param val The map to be flattened.
- * @param out Where to write the XML data.
- *
- * @see #writeMapXml(Map, String, XmlSerializer)
- * @see #writeListXml
- * @see #writeValueXml
- * @see #readMapXml
- */
- public static final void writeMapXml(Map val, OutputStream out)
- throws XmlPullParserException, java.io.IOException {
- XmlSerializer serializer = new FastXmlSerializer();
- serializer.setOutput(out, "utf-8");
- serializer.startDocument(null, true);
- serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
- writeMapXml(val, null, serializer);
- serializer.endDocument();
- }
-
- /**
- * Flatten a List into an output stream as XML. The list can later be
- * read back with readListXml().
- *
- * @param val The list to be flattened.
- * @param out Where to write the XML data.
- *
- * @see #writeListXml(List, String, XmlSerializer)
- * @see #writeMapXml
- * @see #writeValueXml
- * @see #readListXml
- */
- public static final void writeListXml(List val, OutputStream out)
- throws XmlPullParserException, java.io.IOException
- {
- XmlSerializer serializer = Xml.newSerializer();
- serializer.setOutput(out, "utf-8");
- serializer.startDocument(null, true);
- serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
- writeListXml(val, null, serializer);
- serializer.endDocument();
- }
-
- /**
- * Flatten a Map into an XmlSerializer. The map can later be read back
- * with readThisMapXml().
- *
- * @param val The map to be flattened.
- * @param name Name attribute to include with this list's tag, or null for
- * none.
- * @param out XmlSerializer to write the map into.
- *
- * @see #writeMapXml(Map, OutputStream)
- * @see #writeListXml
- * @see #writeValueXml
- * @see #readMapXml
- */
- public static final void writeMapXml(Map val, String name, XmlSerializer out)
- throws XmlPullParserException, java.io.IOException
- {
- if (val == null) {
- out.startTag(null, "null");
- out.endTag(null, "null");
- return;
- }
-
- Set s = val.entrySet();
- Iterator i = s.iterator();
-
- out.startTag(null, "map");
- if (name != null) {
- out.attribute(null, "name", name);
- }
-
- while (i.hasNext()) {
- Map.Entry e = (Map.Entry)i.next();
- writeValueXml(e.getValue(), (String)e.getKey(), out);
- }
-
- out.endTag(null, "map");
- }
-
- /**
- * Flatten a List into an XmlSerializer. The list can later be read back
- * with readThisListXml().
- *
- * @param val The list to be flattened.
- * @param name Name attribute to include with this list's tag, or null for
- * none.
- * @param out XmlSerializer to write the list into.
- *
- * @see #writeListXml(List, OutputStream)
- * @see #writeMapXml
- * @see #writeValueXml
- * @see #readListXml
- */
- public static final void writeListXml(List val, String name, XmlSerializer out)
- throws XmlPullParserException, java.io.IOException
- {
- if (val == null) {
- out.startTag(null, "null");
- out.endTag(null, "null");
- return;
- }
-
- out.startTag(null, "list");
- if (name != null) {
- out.attribute(null, "name", name);
- }
-
- int N = val.size();
- int i=0;
- while (i < N) {
- writeValueXml(val.get(i), null, out);
- i++;
- }
-
- out.endTag(null, "list");
- }
-
- /**
- * Flatten a byte[] into an XmlSerializer. The list can later be read back
- * with readThisByteArrayXml().
- *
- * @param val The byte array to be flattened.
- * @param name Name attribute to include with this array's tag, or null for
- * none.
- * @param out XmlSerializer to write the array into.
- *
- * @see #writeMapXml
- * @see #writeValueXml
- */
- public static final void writeByteArrayXml(byte[] val, String name,
- XmlSerializer out)
- throws XmlPullParserException, java.io.IOException {
-
- if (val == null) {
- out.startTag(null, "null");
- out.endTag(null, "null");
- return;
- }
-
- out.startTag(null, "byte-array");
- if (name != null) {
- out.attribute(null, "name", name);
- }
-
- final int N = val.length;
- out.attribute(null, "num", Integer.toString(N));
-
- StringBuilder sb = new StringBuilder(val.length*2);
- for (int i=0; i<N; i++) {
- int b = val[i];
- int h = b>>4;
- sb.append(h >= 10 ? ('a'+h-10) : ('0'+h));
- h = b&0xff;
- sb.append(h >= 10 ? ('a'+h-10) : ('0'+h));
- }
-
- out.text(sb.toString());
-
- out.endTag(null, "byte-array");
- }
-
- /**
- * Flatten an int[] into an XmlSerializer. The list can later be read back
- * with readThisIntArrayXml().
- *
- * @param val The int array to be flattened.
- * @param name Name attribute to include with this array's tag, or null for
- * none.
- * @param out XmlSerializer to write the array into.
- *
- * @see #writeMapXml
- * @see #writeValueXml
- * @see #readThisIntArrayXml
- */
- public static final void writeIntArrayXml(int[] val, String name,
- XmlSerializer out)
- throws XmlPullParserException, java.io.IOException {
-
- if (val == null) {
- out.startTag(null, "null");
- out.endTag(null, "null");
- return;
- }
-
- out.startTag(null, "int-array");
- if (name != null) {
- out.attribute(null, "name", name);
- }
-
- final int N = val.length;
- out.attribute(null, "num", Integer.toString(N));
-
- for (int i=0; i<N; i++) {
- out.startTag(null, "item");
- out.attribute(null, "value", Integer.toString(val[i]));
- out.endTag(null, "item");
- }
-
- out.endTag(null, "int-array");
- }
-
- /**
- * Flatten an object's value into an XmlSerializer. The value can later
- * be read back with readThisValueXml().
- *
- * Currently supported value types are: null, String, Integer, Long,
- * Float, Double Boolean, Map, List.
- *
- * @param v The object to be flattened.
- * @param name Name attribute to include with this value's tag, or null
- * for none.
- * @param out XmlSerializer to write the object into.
- *
- * @see #writeMapXml
- * @see #writeListXml
- * @see #readValueXml
- */
- public static final void writeValueXml(Object v, String name, XmlSerializer out)
- throws XmlPullParserException, java.io.IOException
- {
- String typeStr;
- if (v == null) {
- out.startTag(null, "null");
- if (name != null) {
- out.attribute(null, "name", name);
- }
- out.endTag(null, "null");
- return;
- } else if (v instanceof String) {
- out.startTag(null, "string");
- if (name != null) {
- out.attribute(null, "name", name);
- }
- out.text(v.toString());
- out.endTag(null, "string");
- return;
- } else if (v instanceof Integer) {
- typeStr = "int";
- } else if (v instanceof Long) {
- typeStr = "long";
- } else if (v instanceof Float) {
- typeStr = "float";
- } else if (v instanceof Double) {
- typeStr = "double";
- } else if (v instanceof Boolean) {
- typeStr = "boolean";
- } else if (v instanceof byte[]) {
- writeByteArrayXml((byte[])v, name, out);
- return;
- } else if (v instanceof int[]) {
- writeIntArrayXml((int[])v, name, out);
- return;
- } else if (v instanceof Map) {
- writeMapXml((Map)v, name, out);
- return;
- } else if (v instanceof List) {
- writeListXml((List)v, name, out);
- return;
- } else if (v instanceof CharSequence) {
- // XXX This is to allow us to at least write something if
- // we encounter styled text... but it means we will drop all
- // of the styling information. :(
- out.startTag(null, "string");
- if (name != null) {
- out.attribute(null, "name", name);
- }
- out.text(v.toString());
- out.endTag(null, "string");
- return;
- } else {
- throw new RuntimeException("writeValueXml: unable to write value " + v);
- }
-
- out.startTag(null, typeStr);
- if (name != null) {
- out.attribute(null, "name", name);
- }
- out.attribute(null, "value", v.toString());
- out.endTag(null, typeStr);
- }
-
- /**
- * Read a HashMap from an InputStream containing XML. The stream can
- * previously have been written by writeMapXml().
- *
- * @param in The InputStream from which to read.
- *
- * @return HashMap The resulting map.
- *
- * @see #readListXml
- * @see #readValueXml
- * @see #readThisMapXml
- * #see #writeMapXml
- */
- public static final HashMap readMapXml(InputStream in)
- throws XmlPullParserException, java.io.IOException
- {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(in, null);
- return (HashMap)readValueXml(parser, new String[1]);
- }
-
- /**
- * Read an ArrayList from an InputStream containing XML. The stream can
- * previously have been written by writeListXml().
- *
- * @param in The InputStream from which to read.
- *
- * @return HashMap The resulting list.
- *
- * @see #readMapXml
- * @see #readValueXml
- * @see #readThisListXml
- * @see #writeListXml
- */
- public static final ArrayList readListXml(InputStream in)
- throws XmlPullParserException, java.io.IOException
- {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(in, null);
- return (ArrayList)readValueXml(parser, new String[1]);
- }
-
- /**
- * Read a HashMap object from an XmlPullParser. The XML data could
- * previously have been generated by writeMapXml(). The XmlPullParser
- * must be positioned <em>after</em> the tag that begins the map.
- *
- * @param parser The XmlPullParser from which to read the map data.
- * @param endTag Name of the tag that will end the map, usually "map".
- * @param name An array of one string, used to return the name attribute
- * of the map's tag.
- *
- * @return HashMap The newly generated map.
- *
- * @see #readMapXml
- */
- public static final HashMap readThisMapXml(XmlPullParser parser, String endTag, String[] name)
- throws XmlPullParserException, java.io.IOException
- {
- HashMap map = new HashMap();
-
- int eventType = parser.getEventType();
- do {
- if (eventType == parser.START_TAG) {
- Object val = readThisValueXml(parser, name);
- if (name[0] != null) {
- //System.out.println("Adding to map: " + name + " -> " + val);
- map.put(name[0], val);
- } else {
- throw new XmlPullParserException(
- "Map value without name attribute: " + parser.getName());
- }
- } else if (eventType == parser.END_TAG) {
- if (parser.getName().equals(endTag)) {
- return map;
- }
- throw new XmlPullParserException(
- "Expected " + endTag + " end tag at: " + parser.getName());
- }
- eventType = parser.next();
- } while (eventType != parser.END_DOCUMENT);
-
- throw new XmlPullParserException(
- "Document ended before " + endTag + " end tag");
- }
-
- /**
- * Read an ArrayList object from an XmlPullParser. The XML data could
- * previously have been generated by writeListXml(). The XmlPullParser
- * must be positioned <em>after</em> the tag that begins the list.
- *
- * @param parser The XmlPullParser from which to read the list data.
- * @param endTag Name of the tag that will end the list, usually "list".
- * @param name An array of one string, used to return the name attribute
- * of the list's tag.
- *
- * @return HashMap The newly generated list.
- *
- * @see #readListXml
- */
- public static final ArrayList readThisListXml(XmlPullParser parser, String endTag, String[] name)
- throws XmlPullParserException, java.io.IOException
- {
- ArrayList list = new ArrayList();
-
- int eventType = parser.getEventType();
- do {
- if (eventType == parser.START_TAG) {
- Object val = readThisValueXml(parser, name);
- list.add(val);
- //System.out.println("Adding to list: " + val);
- } else if (eventType == parser.END_TAG) {
- if (parser.getName().equals(endTag)) {
- return list;
- }
- throw new XmlPullParserException(
- "Expected " + endTag + " end tag at: " + parser.getName());
- }
- eventType = parser.next();
- } while (eventType != parser.END_DOCUMENT);
-
- throw new XmlPullParserException(
- "Document ended before " + endTag + " end tag");
- }
-
- /**
- * Read an int[] object from an XmlPullParser. The XML data could
- * previously have been generated by writeIntArrayXml(). The XmlPullParser
- * must be positioned <em>after</em> the tag that begins the list.
- *
- * @param parser The XmlPullParser from which to read the list data.
- * @param endTag Name of the tag that will end the list, usually "list".
- * @param name An array of one string, used to return the name attribute
- * of the list's tag.
- *
- * @return Returns a newly generated int[].
- *
- * @see #readListXml
- */
- public static final int[] readThisIntArrayXml(XmlPullParser parser,
- String endTag, String[] name)
- throws XmlPullParserException, java.io.IOException {
-
- int num;
- try {
- num = Integer.parseInt(parser.getAttributeValue(null, "num"));
- } catch (NullPointerException e) {
- throw new XmlPullParserException(
- "Need num attribute in byte-array");
- } catch (NumberFormatException e) {
- throw new XmlPullParserException(
- "Not a number in num attribute in byte-array");
- }
-
- int[] array = new int[num];
- int i = 0;
-
- int eventType = parser.getEventType();
- do {
- if (eventType == parser.START_TAG) {
- if (parser.getName().equals("item")) {
- try {
- array[i] = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
- } catch (NullPointerException e) {
- throw new XmlPullParserException(
- "Need value attribute in item");
- } catch (NumberFormatException e) {
- throw new XmlPullParserException(
- "Not a number in value attribute in item");
- }
- } else {
- throw new XmlPullParserException(
- "Expected item tag at: " + parser.getName());
- }
- } else if (eventType == parser.END_TAG) {
- if (parser.getName().equals(endTag)) {
- return array;
- } else if (parser.getName().equals("item")) {
- i++;
- } else {
- throw new XmlPullParserException(
- "Expected " + endTag + " end tag at: "
- + parser.getName());
- }
- }
- eventType = parser.next();
- } while (eventType != parser.END_DOCUMENT);
-
- throw new XmlPullParserException(
- "Document ended before " + endTag + " end tag");
- }
-
- /**
- * Read a flattened object from an XmlPullParser. The XML data could
- * previously have been written with writeMapXml(), writeListXml(), or
- * writeValueXml(). The XmlPullParser must be positioned <em>at</em> the
- * tag that defines the value.
- *
- * @param parser The XmlPullParser from which to read the object.
- * @param name An array of one string, used to return the name attribute
- * of the value's tag.
- *
- * @return Object The newly generated value object.
- *
- * @see #readMapXml
- * @see #readListXml
- * @see #writeValueXml
- */
- public static final Object readValueXml(XmlPullParser parser, String[] name)
- throws XmlPullParserException, java.io.IOException
- {
- int eventType = parser.getEventType();
- do {
- if (eventType == parser.START_TAG) {
- return readThisValueXml(parser, name);
- } else if (eventType == parser.END_TAG) {
- throw new XmlPullParserException(
- "Unexpected end tag at: " + parser.getName());
- } else if (eventType == parser.TEXT) {
- throw new XmlPullParserException(
- "Unexpected text: " + parser.getText());
- }
- eventType = parser.next();
- } while (eventType != parser.END_DOCUMENT);
-
- throw new XmlPullParserException(
- "Unexpected end of document");
- }
-
- private static final Object readThisValueXml(XmlPullParser parser, String[] name)
- throws XmlPullParserException, java.io.IOException
- {
- final String valueName = parser.getAttributeValue(null, "name");
- final String tagName = parser.getName();
-
- //System.out.println("Reading this value tag: " + tagName + ", name=" + valueName);
-
- Object res;
-
- if (tagName.equals("null")) {
- res = null;
- } else if (tagName.equals("string")) {
- String value = "";
- int eventType;
- while ((eventType = parser.next()) != parser.END_DOCUMENT) {
- if (eventType == parser.END_TAG) {
- if (parser.getName().equals("string")) {
- name[0] = valueName;
- //System.out.println("Returning value for " + valueName + ": " + value);
- return value;
- }
- throw new XmlPullParserException(
- "Unexpected end tag in <string>: " + parser.getName());
- } else if (eventType == parser.TEXT) {
- value += parser.getText();
- } else if (eventType == parser.START_TAG) {
- throw new XmlPullParserException(
- "Unexpected start tag in <string>: " + parser.getName());
- }
- }
- throw new XmlPullParserException(
- "Unexpected end of document in <string>");
- } else if (tagName.equals("int")) {
- res = Integer.parseInt(parser.getAttributeValue(null, "value"));
- } else if (tagName.equals("long")) {
- res = Long.valueOf(parser.getAttributeValue(null, "value"));
- } else if (tagName.equals("float")) {
- res = new Float(parser.getAttributeValue(null, "value"));
- } else if (tagName.equals("double")) {
- res = new Double(parser.getAttributeValue(null, "value"));
- } else if (tagName.equals("boolean")) {
- res = Boolean.valueOf(parser.getAttributeValue(null, "value"));
- } else if (tagName.equals("int-array")) {
- parser.next();
- res = readThisIntArrayXml(parser, "int-array", name);
- name[0] = valueName;
- //System.out.println("Returning value for " + valueName + ": " + res);
- return res;
- } else if (tagName.equals("map")) {
- parser.next();
- res = readThisMapXml(parser, "map", name);
- name[0] = valueName;
- //System.out.println("Returning value for " + valueName + ": " + res);
- return res;
- } else if (tagName.equals("list")) {
- parser.next();
- res = readThisListXml(parser, "list", name);
- name[0] = valueName;
- //System.out.println("Returning value for " + valueName + ": " + res);
- return res;
- } else {
- throw new XmlPullParserException(
- "Unknown tag: " + tagName);
- }
-
- // Skip through to end tag.
- int eventType;
- while ((eventType = parser.next()) != parser.END_DOCUMENT) {
- if (eventType == parser.END_TAG) {
- if (parser.getName().equals(tagName)) {
- name[0] = valueName;
- //System.out.println("Returning value for " + valueName + ": " + res);
- return res;
- }
- throw new XmlPullParserException(
- "Unexpected end tag in <" + tagName + ">: " + parser.getName());
- } else if (eventType == parser.TEXT) {
- throw new XmlPullParserException(
- "Unexpected text in <" + tagName + ">: " + parser.getName());
- } else if (eventType == parser.START_TAG) {
- throw new XmlPullParserException(
- "Unexpected start tag in <" + tagName + ">: " + parser.getName());
- }
- }
- throw new XmlPullParserException(
- "Unexpected end of document in <" + tagName + ">");
- }
-
- public static final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException
- {
- int type;
- while ((type=parser.next()) != parser.START_TAG
- && type != parser.END_DOCUMENT) {
- ;
- }
-
- if (type != parser.START_TAG) {
- throw new XmlPullParserException("No start tag found");
- }
-
- if (!parser.getName().equals(firstElementName)) {
- throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
- ", expected " + firstElementName);
- }
- }
-
- public static final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException
- {
- int type;
- while ((type=parser.next()) != parser.START_TAG
- && type != parser.END_DOCUMENT) {
- ;
- }
- }
-}
diff --git a/core/java/com/android/internal/view/IInputConnectionCallback.aidl b/core/java/com/android/internal/view/IInputConnectionCallback.aidl
deleted file mode 100644
index 5b5b3df..0000000
--- a/core/java/com/android/internal/view/IInputConnectionCallback.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view;
-
-import android.graphics.Rect;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.inputmethod.TextBoxAttribute;
-import com.android.internal.view.IInputContext;
-import android.os.IBinder;
-
-/**
- * {@hide}
- */
-oneway interface IInputMethodCallback {
- void finishedEvent(int seq, boolean handled);
-}
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
deleted file mode 100644
index 4f98cee..0000000
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ /dev/null
@@ -1,388 +0,0 @@
-package com.android.internal.view;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.ExtractedTextRequest;
-import android.view.inputmethod.InputConnection;
-
-import java.lang.ref.WeakReference;
-
-public class IInputConnectionWrapper extends IInputContext.Stub {
- static final String TAG = "IInputConnectionWrapper";
-
- private static final int DO_GET_TEXT_AFTER_CURSOR = 10;
- private static final int DO_GET_TEXT_BEFORE_CURSOR = 20;
- private static final int DO_GET_CURSOR_CAPS_MODE = 30;
- private static final int DO_GET_EXTRACTED_TEXT = 40;
- private static final int DO_COMMIT_TEXT = 50;
- private static final int DO_COMMIT_COMPLETION = 55;
- private static final int DO_SET_SELECTION = 57;
- private static final int DO_PERFORM_CONTEXT_MENU_ACTION = 58;
- private static final int DO_SET_COMPOSING_TEXT = 60;
- private static final int DO_FINISH_COMPOSING_TEXT = 65;
- private static final int DO_SEND_KEY_EVENT = 70;
- private static final int DO_DELETE_SURROUNDING_TEXT = 80;
- private static final int DO_BEGIN_BATCH_EDIT = 90;
- private static final int DO_END_BATCH_EDIT = 95;
- private static final int DO_REPORT_FULLSCREEN_MODE = 100;
- private static final int DO_PERFORM_PRIVATE_COMMAND = 120;
- private static final int DO_CLEAR_META_KEY_STATES = 130;
-
- private WeakReference<InputConnection> mInputConnection;
-
- private Looper mMainLooper;
- private Handler mH;
-
- static class SomeArgs {
- Object arg1;
- Object arg2;
- IInputContextCallback callback;
- int seq;
- }
-
- class MyHandler extends Handler {
- MyHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- executeMessage(msg);
- }
- }
-
- public IInputConnectionWrapper(Looper mainLooper, InputConnection conn) {
- mInputConnection = new WeakReference<InputConnection>(conn);
- mMainLooper = mainLooper;
- mH = new MyHandler(mMainLooper);
- }
-
- public boolean isActive() {
- return true;
- }
-
- public void getTextAfterCursor(int length, int flags, int seq, IInputContextCallback callback) {
- dispatchMessage(obtainMessageIISC(DO_GET_TEXT_AFTER_CURSOR, length, flags, seq, callback));
- }
-
- public void getTextBeforeCursor(int length, int flags, int seq, IInputContextCallback callback) {
- dispatchMessage(obtainMessageIISC(DO_GET_TEXT_BEFORE_CURSOR, length, flags, seq, callback));
- }
-
- public void getCursorCapsMode(int reqModes, int seq, IInputContextCallback callback) {
- dispatchMessage(obtainMessageISC(DO_GET_CURSOR_CAPS_MODE, reqModes, seq, callback));
- }
-
- public void getExtractedText(ExtractedTextRequest request,
- int flags, int seq, IInputContextCallback callback) {
- dispatchMessage(obtainMessageIOSC(DO_GET_EXTRACTED_TEXT, flags,
- request, seq, callback));
- }
-
- public void commitText(CharSequence text, int newCursorPosition) {
- dispatchMessage(obtainMessageIO(DO_COMMIT_TEXT, newCursorPosition, text));
- }
-
- public void commitCompletion(CompletionInfo text) {
- dispatchMessage(obtainMessageO(DO_COMMIT_COMPLETION, text));
- }
-
- public void setSelection(int start, int end) {
- dispatchMessage(obtainMessageII(DO_SET_SELECTION, start, end));
- }
-
- public void performContextMenuAction(int id) {
- dispatchMessage(obtainMessageII(DO_PERFORM_CONTEXT_MENU_ACTION, id, 0));
- }
-
- public void setComposingText(CharSequence text, int newCursorPosition) {
- dispatchMessage(obtainMessageIO(DO_SET_COMPOSING_TEXT, newCursorPosition, text));
- }
-
- public void finishComposingText() {
- dispatchMessage(obtainMessage(DO_FINISH_COMPOSING_TEXT));
- }
-
- public void sendKeyEvent(KeyEvent event) {
- dispatchMessage(obtainMessageO(DO_SEND_KEY_EVENT, event));
- }
-
- public void clearMetaKeyStates(int states) {
- dispatchMessage(obtainMessageII(DO_CLEAR_META_KEY_STATES, states, 0));
- }
-
- public void deleteSurroundingText(int leftLength, int rightLength) {
- dispatchMessage(obtainMessageII(DO_DELETE_SURROUNDING_TEXT,
- leftLength, rightLength));
- }
-
- public void beginBatchEdit() {
- dispatchMessage(obtainMessage(DO_BEGIN_BATCH_EDIT));
- }
-
- public void endBatchEdit() {
- dispatchMessage(obtainMessage(DO_END_BATCH_EDIT));
- }
-
- public void reportFullscreenMode(boolean enabled) {
- dispatchMessage(obtainMessageII(DO_REPORT_FULLSCREEN_MODE, enabled ? 1 : 0, 0));
- }
-
- public void performPrivateCommand(String action, Bundle data) {
- dispatchMessage(obtainMessageOO(DO_PERFORM_PRIVATE_COMMAND, action, data));
- }
-
- void dispatchMessage(Message msg) {
- // If we are calling this from the main thread, then we can call
- // right through. Otherwise, we need to send the message to the
- // main thread.
- if (Looper.myLooper() == mMainLooper) {
- executeMessage(msg);
- msg.recycle();
- return;
- }
-
- mH.sendMessage(msg);
- }
-
- void executeMessage(Message msg) {
- switch (msg.what) {
- case DO_GET_TEXT_AFTER_CURSOR: {
- SomeArgs args = (SomeArgs)msg.obj;
- try {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "getTextAfterCursor on inactive InputConnection");
- args.callback.setTextAfterCursor(null, args.seq);
- return;
- }
- args.callback.setTextAfterCursor(ic.getTextAfterCursor(
- msg.arg1, msg.arg2), args.seq);
- } catch (RemoteException e) {
- Log.w(TAG, "Got RemoteException calling setTextAfterCursor", e);
- }
- return;
- }
- case DO_GET_TEXT_BEFORE_CURSOR: {
- SomeArgs args = (SomeArgs)msg.obj;
- try {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "getTextBeforeCursor on inactive InputConnection");
- args.callback.setTextBeforeCursor(null, args.seq);
- return;
- }
- args.callback.setTextBeforeCursor(ic.getTextBeforeCursor(
- msg.arg1, msg.arg2), args.seq);
- } catch (RemoteException e) {
- Log.w(TAG, "Got RemoteException calling setTextBeforeCursor", e);
- }
- return;
- }
- case DO_GET_CURSOR_CAPS_MODE: {
- SomeArgs args = (SomeArgs)msg.obj;
- try {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "getCursorCapsMode on inactive InputConnection");
- args.callback.setCursorCapsMode(0, args.seq);
- return;
- }
- args.callback.setCursorCapsMode(ic.getCursorCapsMode(msg.arg1),
- args.seq);
- } catch (RemoteException e) {
- Log.w(TAG, "Got RemoteException calling setCursorCapsMode", e);
- }
- return;
- }
- case DO_GET_EXTRACTED_TEXT: {
- SomeArgs args = (SomeArgs)msg.obj;
- try {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "getExtractedText on inactive InputConnection");
- args.callback.setExtractedText(null, args.seq);
- return;
- }
- args.callback.setExtractedText(ic.getExtractedText(
- (ExtractedTextRequest)args.arg1, msg.arg1), args.seq);
- } catch (RemoteException e) {
- Log.w(TAG, "Got RemoteException calling setExtractedText", e);
- }
- return;
- }
- case DO_COMMIT_TEXT: {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "commitText on inactive InputConnection");
- return;
- }
- ic.commitText((CharSequence)msg.obj, msg.arg1);
- return;
- }
- case DO_SET_SELECTION: {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "setSelection on inactive InputConnection");
- return;
- }
- ic.setSelection(msg.arg1, msg.arg2);
- return;
- }
- case DO_PERFORM_CONTEXT_MENU_ACTION: {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "performContextMenuAction on inactive InputConnection");
- return;
- }
- ic.performContextMenuAction(msg.arg1);
- return;
- }
- case DO_COMMIT_COMPLETION: {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "commitCompletion on inactive InputConnection");
- return;
- }
- ic.commitCompletion((CompletionInfo)msg.obj);
- return;
- }
- case DO_SET_COMPOSING_TEXT: {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "setComposingText on inactive InputConnection");
- return;
- }
- ic.setComposingText((CharSequence)msg.obj, msg.arg1);
- return;
- }
- case DO_FINISH_COMPOSING_TEXT: {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "finishComposingText on inactive InputConnection");
- return;
- }
- ic.finishComposingText();
- return;
- }
- case DO_SEND_KEY_EVENT: {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "sendKeyEvent on inactive InputConnection");
- return;
- }
- ic.sendKeyEvent((KeyEvent)msg.obj);
- return;
- }
- case DO_CLEAR_META_KEY_STATES: {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "clearMetaKeyStates on inactive InputConnection");
- return;
- }
- ic.clearMetaKeyStates(msg.arg1);
- return;
- }
- case DO_DELETE_SURROUNDING_TEXT: {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "deleteSurroundingText on inactive InputConnection");
- return;
- }
- ic.deleteSurroundingText(msg.arg1, msg.arg2);
- return;
- }
- case DO_BEGIN_BATCH_EDIT: {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "beginBatchEdit on inactive InputConnection");
- return;
- }
- ic.beginBatchEdit();
- return;
- }
- case DO_END_BATCH_EDIT: {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "endBatchEdit on inactive InputConnection");
- return;
- }
- ic.endBatchEdit();
- return;
- }
- case DO_REPORT_FULLSCREEN_MODE: {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "showStatusIcon on inactive InputConnection");
- return;
- }
- ic.reportFullscreenMode(msg.arg1 == 1);
- return;
- }
- case DO_PERFORM_PRIVATE_COMMAND: {
- InputConnection ic = mInputConnection.get();
- if (ic == null || !isActive()) {
- Log.w(TAG, "performPrivateCommand on inactive InputConnection");
- return;
- }
- SomeArgs args = (SomeArgs)msg.obj;
- ic.performPrivateCommand((String)args.arg1,
- (Bundle)args.arg2);
- return;
- }
- }
- Log.w(TAG, "Unhandled message code: " + msg.what);
- }
-
- Message obtainMessage(int what) {
- return mH.obtainMessage(what);
- }
-
- Message obtainMessageII(int what, int arg1, int arg2) {
- return mH.obtainMessage(what, arg1, arg2);
- }
-
- Message obtainMessageO(int what, Object arg1) {
- return mH.obtainMessage(what, 0, 0, arg1);
- }
-
- Message obtainMessageISC(int what, int arg1, int seq, IInputContextCallback callback) {
- SomeArgs args = new SomeArgs();
- args.callback = callback;
- args.seq = seq;
- return mH.obtainMessage(what, arg1, 0, args);
- }
-
- Message obtainMessageIISC(int what, int arg1, int arg2, int seq, IInputContextCallback callback) {
- SomeArgs args = new SomeArgs();
- args.callback = callback;
- args.seq = seq;
- return mH.obtainMessage(what, arg1, arg2, args);
- }
-
- Message obtainMessageIOSC(int what, int arg1, Object arg2, int seq,
- IInputContextCallback callback) {
- SomeArgs args = new SomeArgs();
- args.arg1 = arg2;
- args.callback = callback;
- args.seq = seq;
- return mH.obtainMessage(what, arg1, 0, args);
- }
-
- Message obtainMessageIO(int what, int arg1, Object arg2) {
- return mH.obtainMessage(what, arg1, 0, arg2);
- }
-
- Message obtainMessageOO(int what, Object arg1, Object arg2) {
- SomeArgs args = new SomeArgs();
- args.arg1 = arg1;
- args.arg2 = arg2;
- return mH.obtainMessage(what, 0, 0, args);
- }
-}
diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl
deleted file mode 100644
index 02b6044..0000000
--- a/core/java/com/android/internal/view/IInputContext.aidl
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view;
-
-import android.os.Bundle;
-import android.view.KeyEvent;
-import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.ExtractedTextRequest;
-
-import com.android.internal.view.IInputContextCallback;
-
-/**
- * Interface from an input method to the application, allowing it to perform
- * edits on the current input field and other interactions with the application.
- * {@hide}
- */
- oneway interface IInputContext {
- void getTextBeforeCursor(int length, int flags, int seq, IInputContextCallback callback);
-
- void getTextAfterCursor(int length, int flags, int seq, IInputContextCallback callback);
-
- void getCursorCapsMode(int reqModes, int seq, IInputContextCallback callback);
-
- void getExtractedText(in ExtractedTextRequest request, int flags, int seq,
- IInputContextCallback callback);
-
- void deleteSurroundingText(int leftLength, int rightLength);
-
- void setComposingText(CharSequence text, int newCursorPosition);
-
- void finishComposingText();
-
- void commitText(CharSequence text, int newCursorPosition);
-
- void commitCompletion(in CompletionInfo completion);
-
- void setSelection(int start, int end);
-
- void performContextMenuAction(int id);
-
- void beginBatchEdit();
-
- void endBatchEdit();
-
- void reportFullscreenMode(boolean enabled);
-
- void sendKeyEvent(in KeyEvent event);
-
- void clearMetaKeyStates(int states);
-
- void performPrivateCommand(String action, in Bundle data);
-}
diff --git a/core/java/com/android/internal/view/IInputContextCallback.aidl b/core/java/com/android/internal/view/IInputContextCallback.aidl
deleted file mode 100644
index 9b8c43c..0000000
--- a/core/java/com/android/internal/view/IInputContextCallback.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view;
-
-import android.view.inputmethod.ExtractedText;
-
-/**
- * {@hide}
- */
-oneway interface IInputContextCallback {
- void setTextBeforeCursor(CharSequence textBeforeCursor, int seq);
- void setTextAfterCursor(CharSequence textAfterCursor, int seq);
- void setCursorCapsMode(int capsMode, int seq);
- void setExtractedText(in ExtractedText extractedText, int seq);
-}
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
deleted file mode 100644
index 9b00402..0000000
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view;
-
-import android.graphics.Rect;
-import android.os.IBinder;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputBinding;
-import com.android.internal.view.IInputContext;
-import com.android.internal.view.IInputMethodCallback;
-import com.android.internal.view.IInputMethodSession;
-
-/**
- * Top-level interface to an input method component (implemented in a
- * Service).
- * {@hide}
- */
-oneway interface IInputMethod {
- void attachToken(IBinder token);
-
- void bindInput(in InputBinding binding);
-
- void unbindInput();
-
- void startInput(in IInputContext inputContext, in EditorInfo attribute);
-
- void restartInput(in IInputContext inputContext, in EditorInfo attribute);
-
- void createSession(IInputMethodCallback callback);
-
- void setSessionEnabled(IInputMethodSession session, boolean enabled);
-
- void revokeSession(IInputMethodSession session);
-
- void showSoftInput(int flags);
-
- void hideSoftInput();
-}
diff --git a/core/java/com/android/internal/view/IInputMethodCallback.aidl b/core/java/com/android/internal/view/IInputMethodCallback.aidl
deleted file mode 100644
index 480cc0e..0000000
--- a/core/java/com/android/internal/view/IInputMethodCallback.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view;
-
-import android.graphics.Rect;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import com.android.internal.view.IInputContext;
-import com.android.internal.view.IInputMethodSession;
-import android.os.IBinder;
-
-/**
- * Helper interface for IInputMethod to allow the input method to call back
- * to its client with results from incoming calls.
- * {@hide}
- */
-oneway interface IInputMethodCallback {
- void finishedEvent(int seq, boolean handled);
- void sessionCreated(IInputMethodSession session);
-}
diff --git a/core/java/com/android/internal/view/IInputMethodClient.aidl b/core/java/com/android/internal/view/IInputMethodClient.aidl
deleted file mode 100644
index ce4312d..0000000
--- a/core/java/com/android/internal/view/IInputMethodClient.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view;
-
-import com.android.internal.view.InputBindResult;
-
-/**
- * Interface a client of the IInputMethodManager implements, to identify
- * itself and receive information about changes to the global manager state.
- */
-oneway interface IInputMethodClient {
- void setUsingInputMethod(boolean state);
- void onBindMethod(in InputBindResult res);
- void onUnbindMethod(int sequence);
- void setActive(boolean active);
-}
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
deleted file mode 100644
index 1b1c7f7..0000000
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view;
-
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.EditorInfo;
-import com.android.internal.view.InputBindResult;
-import com.android.internal.view.IInputContext;
-import com.android.internal.view.IInputMethodClient;
-
-/**
- * Public interface to the global input method manager, used by all client
- * applications.
- */
-interface IInputMethodManager {
- List<InputMethodInfo> getInputMethodList();
- List<InputMethodInfo> getEnabledInputMethodList();
-
- void addClient(in IInputMethodClient client,
- in IInputContext inputContext, int uid, int pid);
- void removeClient(in IInputMethodClient client);
-
- InputBindResult startInput(in IInputMethodClient client,
- IInputContext inputContext, in EditorInfo attribute,
- boolean initial, boolean needResult);
- void finishInput(in IInputMethodClient client);
- void showSoftInput(in IInputMethodClient client, int flags);
- void hideSoftInput(in IInputMethodClient client, int flags);
- void windowGainedFocus(in IInputMethodClient client,
- boolean viewHasFocus, boolean isTextEditor,
- int softInputMode, boolean first, int windowFlags);
-
- void showInputMethodPickerFromClient(in IInputMethodClient client);
- void setInputMethod(in IBinder token, String id);
- void hideMySoftInput(in IBinder token, int flags);
- void updateStatusIcon(in IBinder token, String packageName, int iconId);
-
- boolean setInputMethodEnabled(String id, boolean enabled);
-}
-
diff --git a/core/java/com/android/internal/view/IInputMethodSession.aidl b/core/java/com/android/internal/view/IInputMethodSession.aidl
deleted file mode 100644
index 8a44976..0000000
--- a/core/java/com/android/internal/view/IInputMethodSession.aidl
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view;
-
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.ExtractedText;
-import com.android.internal.view.IInputMethodCallback;
-
-/**
- * Sub-interface of IInputMethod which is safe to give to client applications.
- * {@hide}
- */
-oneway interface IInputMethodSession {
- void finishInput();
-
- void updateExtractedText(int token, in ExtractedText text);
-
- void updateSelection(int oldSelStart, int oldSelEnd,
- int newSelStart, int newSelEnd,
- int candidatesStart, int candidatesEnd);
-
- void updateCursor(in Rect newCursor);
-
- void displayCompletions(in CompletionInfo[] completions);
-
- void dispatchKeyEvent(int seq, in KeyEvent event, IInputMethodCallback callback);
-
- void dispatchTrackballEvent(int seq, in MotionEvent event, IInputMethodCallback callback);
-
- void appPrivateCommand(String action, in Bundle data);
-}
diff --git a/core/java/com/android/internal/view/InputBindResult.aidl b/core/java/com/android/internal/view/InputBindResult.aidl
deleted file mode 100644
index 7ff5c4e..0000000
--- a/core/java/com/android/internal/view/InputBindResult.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view;
-
-parcelable InputBindResult;
diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java
deleted file mode 100644
index 658f098..0000000
--- a/core/java/com/android/internal/view/InputBindResult.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.internal.view;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Bundle of information returned by input method manager about a successful
- * binding to an input method.
- */
-public final class InputBindResult implements Parcelable {
- static final String TAG = "InputBindResult";
-
- /**
- * The input method service.
- */
- public final IInputMethodSession method;
-
- /**
- * The ID for this input method, as found in InputMethodInfo; null if
- * no input method will be bound.
- */
- public final String id;
-
- /**
- * Sequence number of this binding.
- */
- public final int sequence;
-
- public InputBindResult(IInputMethodSession _method, String _id, int _sequence) {
- method = _method;
- id = _id;
- sequence = _sequence;
- }
-
- InputBindResult(Parcel source) {
- method = IInputMethodSession.Stub.asInterface(source.readStrongBinder());
- id = source.readString();
- sequence = source.readInt();
- }
-
- @Override
- public String toString() {
- return "InputBindResult{" + method + " " + id
- + " #" + sequence + "}";
- }
-
- /**
- * Used to package this object into a {@link Parcel}.
- *
- * @param dest The {@link Parcel} to be written.
- * @param flags The flags used for parceling.
- */
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeStrongInterface(method);
- dest.writeString(id);
- dest.writeInt(sequence);
- }
-
- /**
- * Used to make this class parcelable.
- */
- public static final Parcelable.Creator<InputBindResult> CREATOR = new Parcelable.Creator<InputBindResult>() {
- public InputBindResult createFromParcel(Parcel source) {
- return new InputBindResult(source);
- }
-
- public InputBindResult[] newArray(int size) {
- return new InputBindResult[size];
- }
- };
-
- public int describeContents() {
- return 0;
- }
-}
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
deleted file mode 100644
index 32d9f3d..0000000
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ /dev/null
@@ -1,342 +0,0 @@
-package com.android.internal.view;
-
-import com.android.internal.view.IInputContext;
-
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.ExtractedText;
-import android.view.inputmethod.ExtractedTextRequest;
-import android.view.inputmethod.InputConnection;
-
-public class InputConnectionWrapper implements InputConnection {
- private static final int MAX_WAIT_TIME_MILLIS = 2000;
- private final IInputContext mIInputContext;
-
- static class InputContextCallback extends IInputContextCallback.Stub {
- private static final String TAG = "InputConnectionWrapper.ICC";
- public int mSeq;
- public boolean mHaveValue;
- public CharSequence mTextBeforeCursor;
- public CharSequence mTextAfterCursor;
- public ExtractedText mExtractedText;
- public int mCursorCapsMode;
-
- // A 'pool' of one InputContextCallback. Each ICW request will attempt to gain
- // exclusive access to this object.
- private static InputContextCallback sInstance = new InputContextCallback();
- private static int sSequenceNumber = 1;
-
- /**
- * Returns an InputContextCallback object that is guaranteed not to be in use by
- * any other thread. The returned object's 'have value' flag is cleared and its expected
- * sequence number is set to a new integer. We use a sequence number so that replies that
- * occur after a timeout has expired are not interpreted as replies to a later request.
- */
- private static InputContextCallback getInstance() {
- synchronized (InputContextCallback.class) {
- // Return sInstance if it's non-null, otherwise construct a new callback
- InputContextCallback callback;
- if (sInstance != null) {
- callback = sInstance;
- sInstance = null;
-
- // Reset the callback
- callback.mHaveValue = false;
- } else {
- callback = new InputContextCallback();
- }
-
- // Set the sequence number
- callback.mSeq = sSequenceNumber++;
- return callback;
- }
- }
-
- /**
- * Makes the given InputContextCallback available for use in the future.
- */
- private void dispose() {
- synchronized (InputContextCallback.class) {
- // If sInstance is non-null, just let this object be garbage-collected
- if (sInstance == null) {
- // Allow any objects being held to be gc'ed
- mTextAfterCursor = null;
- mTextBeforeCursor = null;
- mExtractedText = null;
- sInstance = this;
- }
- }
- }
-
- public void setTextBeforeCursor(CharSequence textBeforeCursor, int seq) {
- synchronized (this) {
- if (seq == mSeq) {
- mTextBeforeCursor = textBeforeCursor;
- mHaveValue = true;
- notifyAll();
- } else {
- Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
- + ") in setTextBeforeCursor, ignoring.");
- }
- }
- }
-
- public void setTextAfterCursor(CharSequence textAfterCursor, int seq) {
- synchronized (this) {
- if (seq == mSeq) {
- mTextAfterCursor = textAfterCursor;
- mHaveValue = true;
- notifyAll();
- } else {
- Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
- + ") in setTextAfterCursor, ignoring.");
- }
- }
- }
-
- public void setCursorCapsMode(int capsMode, int seq) {
- synchronized (this) {
- if (seq == mSeq) {
- mCursorCapsMode = capsMode;
- mHaveValue = true;
- notifyAll();
- } else {
- Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
- + ") in setCursorCapsMode, ignoring.");
- }
- }
- }
-
- public void setExtractedText(ExtractedText extractedText, int seq) {
- synchronized (this) {
- if (seq == mSeq) {
- mExtractedText = extractedText;
- mHaveValue = true;
- notifyAll();
- } else {
- Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
- + ") in setExtractedText, ignoring.");
- }
- }
- }
-
- /**
- * Waits for a result for up to {@link #MAX_WAIT_TIME_MILLIS} milliseconds.
- *
- * <p>The caller must be synchronized on this callback object.
- */
- void waitForResultLocked() {
- long startTime = SystemClock.uptimeMillis();
- long endTime = startTime + MAX_WAIT_TIME_MILLIS;
-
- while (!mHaveValue) {
- long remainingTime = endTime - SystemClock.uptimeMillis();
- if (remainingTime <= 0) {
- Log.w(TAG, "Timed out waiting on IInputContextCallback");
- return;
- }
- try {
- wait(remainingTime);
- } catch (InterruptedException e) {
- }
- }
- }
- }
-
- public InputConnectionWrapper(IInputContext inputContext) {
- mIInputContext = inputContext;
- }
-
- public CharSequence getTextAfterCursor(int length, int flags) {
- CharSequence value = null;
- try {
- InputContextCallback callback = InputContextCallback.getInstance();
- mIInputContext.getTextAfterCursor(length, flags, callback.mSeq, callback);
- synchronized (callback) {
- callback.waitForResultLocked();
- if (callback.mHaveValue) {
- value = callback.mTextAfterCursor;
- }
- }
- callback.dispose();
- } catch (RemoteException e) {
- return null;
- }
- return value;
- }
-
- public CharSequence getTextBeforeCursor(int length, int flags) {
- CharSequence value = null;
- try {
- InputContextCallback callback = InputContextCallback.getInstance();
- mIInputContext.getTextBeforeCursor(length, flags, callback.mSeq, callback);
- synchronized (callback) {
- callback.waitForResultLocked();
- if (callback.mHaveValue) {
- value = callback.mTextBeforeCursor;
- }
- }
- callback.dispose();
- } catch (RemoteException e) {
- return null;
- }
- return value;
- }
-
- public int getCursorCapsMode(int reqModes) {
- int value = 0;
- try {
- InputContextCallback callback = InputContextCallback.getInstance();
- mIInputContext.getCursorCapsMode(reqModes, callback.mSeq, callback);
- synchronized (callback) {
- callback.waitForResultLocked();
- if (callback.mHaveValue) {
- value = callback.mCursorCapsMode;
- }
- }
- callback.dispose();
- } catch (RemoteException e) {
- return 0;
- }
- return value;
- }
-
- public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
- ExtractedText value = null;
- try {
- InputContextCallback callback = InputContextCallback.getInstance();
- mIInputContext.getExtractedText(request, flags, callback.mSeq, callback);
- synchronized (callback) {
- callback.waitForResultLocked();
- if (callback.mHaveValue) {
- value = callback.mExtractedText;
- }
- }
- callback.dispose();
- } catch (RemoteException e) {
- return null;
- }
- return value;
- }
-
- public boolean commitText(CharSequence text, int newCursorPosition) {
- try {
- mIInputContext.commitText(text, newCursorPosition);
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- public boolean commitCompletion(CompletionInfo text) {
- try {
- mIInputContext.commitCompletion(text);
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- public boolean setSelection(int start, int end) {
- try {
- mIInputContext.setSelection(start, end);
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- public boolean performContextMenuAction(int id) {
- try {
- mIInputContext.performContextMenuAction(id);
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- public boolean setComposingText(CharSequence text, int newCursorPosition) {
- try {
- mIInputContext.setComposingText(text, newCursorPosition);
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- public boolean finishComposingText() {
- try {
- mIInputContext.finishComposingText();
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- public boolean beginBatchEdit() {
- try {
- mIInputContext.beginBatchEdit();
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- public boolean endBatchEdit() {
- try {
- mIInputContext.endBatchEdit();
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- public boolean sendKeyEvent(KeyEvent event) {
- try {
- mIInputContext.sendKeyEvent(event);
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- public boolean clearMetaKeyStates(int states) {
- try {
- mIInputContext.clearMetaKeyStates(states);
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- public boolean deleteSurroundingText(int leftLength, int rightLength) {
- try {
- mIInputContext.deleteSurroundingText(leftLength, rightLength);
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- public boolean reportFullscreenMode(boolean enabled) {
- try {
- mIInputContext.reportFullscreenMode(enabled);
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- public boolean performPrivateCommand(String action, Bundle data) {
- try {
- mIInputContext.performPrivateCommand(action, data);
- return true;
- } catch (RemoteException e) {
- return false;
- }
- }
-}
diff --git a/core/java/com/android/internal/view/menu/ContextMenuBuilder.java b/core/java/com/android/internal/view/menu/ContextMenuBuilder.java
deleted file mode 100644
index bf44d51..0000000
--- a/core/java/com/android/internal/view/menu/ContextMenuBuilder.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view.menu;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.os.IBinder;
-import android.util.EventLog;
-import android.view.ContextMenu;
-import android.view.View;
-
-/**
- * Implementation of the {@link android.view.ContextMenu} interface.
- * <p>
- * Most clients of the menu framework will never need to touch this
- * class. However, if the client has a window that
- * is not a content view of a Dialog or Activity (for example, the
- * view was added directly to the window manager) and needs to show
- * context menus, it will use this class.
- * <p>
- * To use this class, instantiate it via {@link #ContextMenuBuilder(Context)},
- * and optionally populate it with any of your custom items. Finally,
- * call {@link #show(View, IBinder)} which will populate the menu
- * with a view's context menu items and show the context menu.
- */
-public class ContextMenuBuilder extends MenuBuilder implements ContextMenu {
-
- public ContextMenuBuilder(Context context) {
- super(context);
- }
-
- public ContextMenu setHeaderIcon(Drawable icon) {
- return (ContextMenu) super.setHeaderIconInt(icon);
- }
-
- public ContextMenu setHeaderIcon(int iconRes) {
- return (ContextMenu) super.setHeaderIconInt(iconRes);
- }
-
- public ContextMenu setHeaderTitle(CharSequence title) {
- return (ContextMenu) super.setHeaderTitleInt(title);
- }
-
- public ContextMenu setHeaderTitle(int titleRes) {
- return (ContextMenu) super.setHeaderTitleInt(titleRes);
- }
-
- public ContextMenu setHeaderView(View view) {
- return (ContextMenu) super.setHeaderViewInt(view);
- }
-
- /**
- * Shows this context menu, allowing the optional original view (and its
- * ancestors) to add items.
- *
- * @param originalView Optional, the original view that triggered the
- * context menu.
- * @param token Optional, the window token that should be set on the context
- * menu's window.
- * @return If the context menu was shown, the {@link MenuDialogHelper} for
- * dismissing it. Otherwise, null.
- */
- public MenuDialogHelper show(View originalView, IBinder token) {
- if (originalView != null) {
- // Let relevant views and their populate context listeners populate
- // the context menu
- originalView.createContextMenu(this);
- }
-
- if (getVisibleItems().size() > 0) {
- EventLog.writeEvent(50001, 1);
-
- MenuDialogHelper helper = new MenuDialogHelper(this);
- helper.show(token);
-
- return helper;
- }
-
- return null;
- }
-
-}
diff --git a/core/java/com/android/internal/view/menu/ExpandedMenuView.java b/core/java/com/android/internal/view/menu/ExpandedMenuView.java
deleted file mode 100644
index c16c165..0000000
--- a/core/java/com/android/internal/view/menu/ExpandedMenuView.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view.menu;
-
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-import android.widget.AdapterView.OnItemClickListener;
-
-import com.android.internal.view.menu.MenuBuilder.ItemInvoker;
-
-/**
- * The expanded menu view is a list-like menu with all of the available menu items. It is opened
- * by the user clicking no the 'More' button on the icon menu view.
- */
-public final class ExpandedMenuView extends ListView implements ItemInvoker, MenuView, OnItemClickListener {
- private MenuBuilder mMenu;
-
- /** Default animations for this menu */
- private int mAnimations;
-
- /**
- * Instantiates the ExpandedMenuView that is linked with the provided MenuBuilder.
- * @param menu The model for the menu which this MenuView will display
- */
- public ExpandedMenuView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.MenuView, 0, 0);
- mAnimations = a.getResourceId(com.android.internal.R.styleable.MenuView_windowAnimationStyle, 0);
- a.recycle();
-
- setOnItemClickListener(this);
- }
-
- public void initialize(MenuBuilder menu, int menuType) {
- mMenu = menu;
-
- setAdapter(menu.new MenuAdapter(menuType));
- }
-
- public void updateChildren(boolean cleared) {
- ListAdapter adapter = getAdapter();
- // Tell adapter of the change, it will notify the mListView
- if (adapter != null) {
- if (cleared) {
- ((BaseAdapter)adapter).notifyDataSetInvalidated();
- }
- else {
- ((BaseAdapter)adapter).notifyDataSetChanged();
- }
- }
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
- // Clear the cached bitmaps of children
- setChildrenDrawingCacheEnabled(false);
- }
-
- public boolean invokeItem(MenuItemImpl item) {
- return mMenu.performItemAction(item, 0);
- }
-
- public void onItemClick(AdapterView parent, View v, int position, long id) {
- invokeItem((MenuItemImpl) getAdapter().getItem(position));
- }
-
- public int getWindowAnimations() {
- return mAnimations;
- }
-
-}
diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java
deleted file mode 100644
index 9e1f2ae..0000000
--- a/core/java/com/android/internal/view/menu/IconMenuItemView.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view.menu;
-
-import com.android.internal.view.menu.MenuBuilder.ItemInvoker;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.SoundEffectConstants;
-import android.view.View;
-import android.view.ViewDebug;
-import android.widget.TextView;
-
-/**
- * The item view for each item in the {@link IconMenuView}.
- */
-public final class IconMenuItemView extends TextView implements MenuView.ItemView {
-
- private static final int NO_ALPHA = 0xFF;
-
- private IconMenuView mIconMenuView;
-
- private ItemInvoker mItemInvoker;
- private MenuItemImpl mItemData;
-
- private Drawable mIcon;
-
- private int mTextAppearance;
- private Context mTextAppearanceContext;
-
- private float mDisabledAlpha;
-
- private Rect mPositionIconAvailable = new Rect();
- private Rect mPositionIconOutput = new Rect();
-
- private boolean mShortcutCaptionMode;
- private String mShortcutCaption;
-
- private static String sPrependShortcutLabel;
-
- public IconMenuItemView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs);
-
- if (sPrependShortcutLabel == null) {
- /*
- * Views should only be constructed from the UI thread, so no
- * synchronization needed
- */
- sPrependShortcutLabel = getResources().getString(
- com.android.internal.R.string.prepend_shortcut_label);
- }
-
- TypedArray a =
- context.obtainStyledAttributes(
- attrs, com.android.internal.R.styleable.MenuView, defStyle, 0);
-
- mDisabledAlpha = a.getFloat(
- com.android.internal.R.styleable.MenuView_itemIconDisabledAlpha, 0.8f);
- mTextAppearance = a.getResourceId(com.android.internal.R.styleable.
- MenuView_itemTextAppearance, -1);
- mTextAppearanceContext = context;
-
- a.recycle();
- }
-
- public IconMenuItemView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- /**
- * Initializes with the provided title and icon
- * @param title The title of this item
- * @param icon The icon of this item
- */
- void initialize(CharSequence title, Drawable icon) {
- setClickable(true);
- setFocusable(true);
-
- if (mTextAppearance != -1) {
- setTextAppearance(mTextAppearanceContext, mTextAppearance);
- }
-
- setTitle(title);
- setIcon(icon);
- }
-
- public void initialize(MenuItemImpl itemData, int menuType) {
- mItemData = itemData;
-
- initialize(itemData.getTitleForItemView(this), itemData.getIcon());
-
- setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
- setEnabled(itemData.isEnabled());
- }
-
- @Override
- public boolean performClick() {
- // Let the view's click listener have top priority (the More button relies on this)
- if (super.performClick()) {
- return true;
- }
-
- if ((mItemInvoker != null) && (mItemInvoker.invokeItem(mItemData))) {
- playSoundEffect(SoundEffectConstants.CLICK);
- return true;
- } else {
- return false;
- }
- }
-
- public void setTitle(CharSequence title) {
-
- if (mShortcutCaptionMode) {
- /*
- * Don't set the title directly since it will replace the
- * shortcut+title being shown. Instead, re-set the shortcut caption
- * mode so the new title is shown.
- */
- setCaptionMode(true);
-
- } else if (title != null) {
- setText(title);
- }
- }
-
- void setCaptionMode(boolean shortcut) {
- /*
- * If there is no item model, don't do any of the below (for example,
- * the 'More' item doesn't have a model)
- */
- if (mItemData == null) {
- return;
- }
-
- mShortcutCaptionMode = shortcut && (mItemData.shouldShowShortcut());
-
- CharSequence text = mItemData.getTitleForItemView(this);
-
- if (mShortcutCaptionMode) {
-
- if (mShortcutCaption == null) {
- mShortcutCaption = mItemData.getShortcutLabel();
- }
-
- text = mShortcutCaption;
- }
-
- setText(text);
- }
-
- public void setIcon(Drawable icon) {
- mIcon = icon;
-
- if (icon != null) {
-
- /* Set the bounds of the icon since setCompoundDrawables needs it. */
- icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
-
- // Set the compound drawables
- setCompoundDrawables(null, icon, null, null);
-
- // When there is an icon, make sure the text is at the bottom
- setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
-
- /*
- * Request a layout to reposition the icon. The positioning of icon
- * depends on this TextView's line bounds, which is only available
- * after a layout.
- */
- requestLayout();
- } else {
- setCompoundDrawables(null, null, null, null);
-
- // When there is no icon, make sure the text is centered vertically
- setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
- }
- }
-
- public void setItemInvoker(ItemInvoker itemInvoker) {
- mItemInvoker = itemInvoker;
- }
-
- @ViewDebug.CapturedViewProperty(retrieveReturn = true)
- public MenuItemImpl getItemData() {
- return mItemData;
- }
-
- @Override
- public void setVisibility(int v) {
- super.setVisibility(v);
-
- if (mIconMenuView != null) {
- // On visibility change, mark the IconMenuView to refresh itself eventually
- mIconMenuView.markStaleChildren();
- }
- }
-
- void setIconMenuView(IconMenuView iconMenuView) {
- mIconMenuView = iconMenuView;
- }
-
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
-
- if (mItemData != null && mIcon != null) {
- // When disabled, the not-focused state and the pressed state should
- // drop alpha on the icon
- final boolean isInAlphaState = !mItemData.isEnabled() && (isPressed() || !isFocused());
- mIcon.setAlpha(isInAlphaState ? (int) (mDisabledAlpha * NO_ALPHA) : NO_ALPHA);
- }
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
-
- positionIcon();
- }
-
- /**
- * Positions the icon vertically (horizontal centering is taken care of by
- * the TextView's gravity).
- */
- private void positionIcon() {
-
- if (mIcon == null) {
- return;
- }
-
- // We reuse the output rectangle as a temp rect
- Rect tmpRect = mPositionIconOutput;
- getLineBounds(0, tmpRect);
- mPositionIconAvailable.set(0, 0, getWidth(), tmpRect.top);
- Gravity.apply(Gravity.CENTER_VERTICAL | Gravity.LEFT, mIcon.getIntrinsicWidth(), mIcon
- .getIntrinsicHeight(), mPositionIconAvailable, mPositionIconOutput);
- mIcon.setBounds(mPositionIconOutput);
- }
-
- public void setCheckable(boolean checkable) {
- }
-
- public void setChecked(boolean checked) {
- }
-
- public void setShortcut(boolean showShortcut, char shortcutKey) {
-
- if (mShortcutCaptionMode) {
- /*
- * Shortcut has changed and we're showing it right now, need to
- * update (clear the old one first).
- */
- mShortcutCaption = null;
- setCaptionMode(true);
- }
- }
-
- public boolean prefersCondensedTitle() {
- return true;
- }
-
- public boolean showsIcon() {
- return true;
- }
-
-}
diff --git a/core/java/com/android/internal/view/menu/IconMenuView.java b/core/java/com/android/internal/view/menu/IconMenuView.java
deleted file mode 100644
index 781c608..0000000
--- a/core/java/com/android/internal/view/menu/IconMenuView.java
+++ /dev/null
@@ -1,822 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view.menu;
-
-import com.android.internal.view.menu.MenuBuilder.ItemInvoker;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.Layout;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.LayoutInflater;
-
-import java.util.ArrayList;
-
-/**
- * The icon menu view is an icon-based menu usually with a subset of all the menu items.
- * It is opened as the default menu, and shows either the first five or all six of the menu items
- * with text and icon. In the situation of there being more than six items, the first five items
- * will be accompanied with a 'More' button that opens an {@link ExpandedMenuView} which lists
- * all the menu items.
- *
- * @attr ref android.R.styleable#IconMenuView_rowHeight
- * @attr ref android.R.styleable#IconMenuView_maxRows
- * @attr ref android.R.styleable#IconMenuView_maxItemsPerRow
- *
- * @hide
- */
-public final class IconMenuView extends ViewGroup implements ItemInvoker, MenuView, Runnable {
- private static final int ITEM_CAPTION_CYCLE_DELAY = 1000;
-
- private MenuBuilder mMenu;
-
- /** Height of each row */
- private int mRowHeight;
- /** Maximum number of rows to be shown */
- private int mMaxRows;
- /** Maximum number of items to show in the icon menu. */
- private int mMaxItems;
- /** Maximum number of items per row */
- private int mMaxItemsPerRow;
- /** Actual number of items (the 'More' view does not count as an item) shown */
- private int mNumActualItemsShown;
-
- /** Divider that is drawn between all rows */
- private Drawable mHorizontalDivider;
- /** Height of the horizontal divider */
- private int mHorizontalDividerHeight;
- /** Set of horizontal divider positions where the horizontal divider will be drawn */
- private ArrayList<Rect> mHorizontalDividerRects;
-
- /** Divider that is drawn between all columns */
- private Drawable mVerticalDivider;
- /** Width of the vertical divider */
- private int mVerticalDividerWidth;
- /** Set of vertical divider positions where the vertical divider will be drawn */
- private ArrayList<Rect> mVerticalDividerRects;
-
- /** Icon for the 'More' button */
- private Drawable mMoreIcon;
-
- /** Item view for the 'More' button */
- private IconMenuItemView mMoreItemView;
-
- /** Background of each item (should contain the selected and focused states) */
- private Drawable mItemBackground;
-
- /** Default animations for this menu */
- private int mAnimations;
-
- /**
- * Whether this IconMenuView has stale children and needs to update them.
- * Set true by {@link #markStaleChildren()} and reset to false by
- * {@link #onMeasure(int, int)}
- */
- private boolean mHasStaleChildren;
-
- /**
- * Longpress on MENU (while this is shown) switches to shortcut caption
- * mode. When the user releases the longpress, we do not want to pass the
- * key-up event up since that will dismiss the menu.
- */
- private boolean mMenuBeingLongpressed = false;
-
- /**
- * While {@link #mMenuBeingLongpressed}, we toggle the children's caption
- * mode between each's title and its shortcut. This is the last caption mode
- * we broadcasted to children.
- */
- private boolean mLastChildrenCaptionMode;
-
- /**
- * The layout to use for menu items. Each index is the row number (0 is the
- * top-most). Each value contains the number of items in that row.
- * <p>
- * The length of this array should not be used to get the number of rows in
- * the current layout, instead use {@link #mLayoutNumRows}.
- */
- private int[] mLayout;
-
- /**
- * The number of rows in the current layout.
- */
- private int mLayoutNumRows;
-
- /**
- * Instantiates the IconMenuView that is linked with the provided MenuBuilder.
- */
- public IconMenuView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a =
- context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.IconMenuView, 0, 0);
- mRowHeight = a.getDimensionPixelSize(com.android.internal.R.styleable.IconMenuView_rowHeight, 64);
- mMaxRows = a.getInt(com.android.internal.R.styleable.IconMenuView_maxRows, 2);
- mMaxItems = a.getInt(com.android.internal.R.styleable.IconMenuView_maxItems, 6);
- mMaxItemsPerRow = a.getInt(com.android.internal.R.styleable.IconMenuView_maxItemsPerRow, 3);
- mMoreIcon = a.getDrawable(com.android.internal.R.styleable.IconMenuView_moreIcon);
- a.recycle();
-
- a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.MenuView, 0, 0);
- mItemBackground = a.getDrawable(com.android.internal.R.styleable.MenuView_itemBackground);
- mHorizontalDivider = a.getDrawable(com.android.internal.R.styleable.MenuView_horizontalDivider);
- mHorizontalDividerRects = new ArrayList<Rect>();
- mVerticalDivider = a.getDrawable(com.android.internal.R.styleable.MenuView_verticalDivider);
- mVerticalDividerRects = new ArrayList<Rect>();
- mAnimations = a.getResourceId(com.android.internal.R.styleable.MenuView_windowAnimationStyle, 0);
- a.recycle();
-
- if (mHorizontalDivider != null) {
- mHorizontalDividerHeight = mHorizontalDivider.getIntrinsicHeight();
- // Make sure to have some height for the divider
- if (mHorizontalDividerHeight == -1) mHorizontalDividerHeight = 1;
- }
-
- if (mVerticalDivider != null) {
- mVerticalDividerWidth = mVerticalDivider.getIntrinsicWidth();
- // Make sure to have some width for the divider
- if (mVerticalDividerWidth == -1) mVerticalDividerWidth = 1;
- }
-
- mLayout = new int[mMaxRows];
-
- // This view will be drawing the dividers
- setWillNotDraw(false);
-
- // This is so we'll receive the MENU key in touch mode
- setFocusableInTouchMode(true);
- // This is so our children can still be arrow-key focused
- setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
- }
-
- /**
- * Figures out the layout for the menu items.
- *
- * @param width The available width for the icon menu.
- */
- private void layoutItems(int width) {
- int numItems = getChildCount();
-
- // Start with the least possible number of rows
- int curNumRows =
- Math.min((int) Math.ceil(numItems / (float) mMaxItemsPerRow), mMaxRows);
-
- /*
- * Increase the number of rows until we find a configuration that fits
- * all of the items' titles. Worst case, we use mMaxRows.
- */
- for (; curNumRows <= mMaxRows; curNumRows++) {
- layoutItemsUsingGravity(curNumRows, numItems);
-
- if (curNumRows >= numItems) {
- // Can't have more rows than items
- break;
- }
-
- if (doItemsFit()) {
- // All the items fit, so this is a good configuration
- break;
- }
- }
- }
-
- /**
- * Figures out the layout for the menu items by equally distributing, and
- * adding any excess items equally to lower rows.
- *
- * @param numRows The total number of rows for the menu view
- * @param numItems The total number of items (across all rows) contained in
- * the menu view
- * @return int[] Where the value of index i contains the number of items for row i
- */
- private void layoutItemsUsingGravity(int numRows, int numItems) {
- int numBaseItemsPerRow = numItems / numRows;
- int numLeftoverItems = numItems % numRows;
- /**
- * The bottom rows will each get a leftover item. Rows (indexed at 0)
- * that are >= this get a leftover item. Note: if there are 0 leftover
- * items, no rows will get them since this value will be greater than
- * the last row.
- */
- int rowsThatGetALeftoverItem = numRows - numLeftoverItems;
-
- int[] layout = mLayout;
- for (int i = 0; i < numRows; i++) {
- layout[i] = numBaseItemsPerRow;
-
- // Fill the bottom rows with a leftover item each
- if (i >= rowsThatGetALeftoverItem) {
- layout[i]++;
- }
- }
-
- mLayoutNumRows = numRows;
- }
-
- /**
- * Checks whether each item's title is fully visible using the current
- * layout.
- *
- * @return True if the items fit (each item's text is fully visible), false
- * otherwise.
- */
- private boolean doItemsFit() {
- int itemPos = 0;
-
- int[] layout = mLayout;
- int numRows = mLayoutNumRows;
- for (int row = 0; row < numRows; row++) {
- int numItemsOnRow = layout[row];
-
- /*
- * If there is only one item on this row, increasing the
- * number of rows won't help.
- */
- if (numItemsOnRow == 1) {
- itemPos++;
- continue;
- }
-
- for (int itemsOnRowCounter = numItemsOnRow; itemsOnRowCounter > 0;
- itemsOnRowCounter--) {
- View child = getChildAt(itemPos++);
- LayoutParams lp = (LayoutParams) child.getLayoutParams();
- if (lp.maxNumItemsOnRow < numItemsOnRow) {
- return false;
- }
- }
- }
-
- return true;
- }
-
- /**
- * Adds an IconMenuItemView to this icon menu view.
- * @param itemView The item's view to add
- */
- private void addItemView(IconMenuItemView itemView) {
- LayoutParams lp = (LayoutParams) itemView.getLayoutParams();
-
- if (lp == null) {
- // Default layout parameters
- lp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
- }
-
- // Set ourselves on the item view
- itemView.setIconMenuView(this);
-
- // Apply the background to the item view
- itemView.setBackgroundDrawable(mItemBackground.getConstantState().newDrawable());
-
- // This class is the invoker for all its item views
- itemView.setItemInvoker(this);
-
- // Set the desired width of item
- lp.desiredWidth = (int) Layout.getDesiredWidth(itemView.getText(), itemView.getPaint());
-
- addView(itemView, lp);
- }
-
- /**
- * Creates the item view for the 'More' button which is used to switch to
- * the expanded menu view. This button is a special case since it does not
- * have a MenuItemData backing it.
- * @return The IconMenuItemView for the 'More' button
- */
- private IconMenuItemView createMoreItemView() {
- LayoutInflater inflater = mMenu.getMenuType(MenuBuilder.TYPE_ICON).getInflater();
-
- final IconMenuItemView itemView = (IconMenuItemView) inflater.inflate(
- com.android.internal.R.layout.icon_menu_item_layout, null);
-
- Resources r = getContext().getResources();
- itemView.initialize(r.getText(com.android.internal.R.string.more_item_label), mMoreIcon);
-
- // Set up a click listener on the view since there will be no invocation sequence
- // due to the lack of a MenuItemData this view
- itemView.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- // Switches the menu to expanded mode
- MenuBuilder.Callback cb = mMenu.getCallback();
- if (cb != null) {
- // Call callback
- cb.onMenuModeChange(mMenu);
- }
- }
- });
-
- return itemView;
- }
-
-
- public void initialize(MenuBuilder menu, int menuType) {
- mMenu = menu;
- updateChildren(true);
- }
-
- public void updateChildren(boolean cleared) {
- // This method does a clear refresh of children
- removeAllViews();
-
- final ArrayList<MenuItemImpl> itemsToShow = mMenu.getVisibleItems();
- final int numItems = itemsToShow.size();
- final int numItemsThatCanFit = mMaxItems;
- // Minimum of the num that can fit and the num that we have
- final int minFitMinus1AndNumItems = Math.min(numItemsThatCanFit - 1, numItems);
-
- MenuItemImpl itemData;
- // Traverse through all but the last item that can fit since that last item can either
- // be a 'More' button or a sixth item
- for (int i = 0; i < minFitMinus1AndNumItems; i++) {
- itemData = itemsToShow.get(i);
- addItemView((IconMenuItemView) itemData.getItemView(MenuBuilder.TYPE_ICON, this));
- }
-
- if (numItems > numItemsThatCanFit) {
- // If there are more items than we can fit, show the 'More' button to
- // switch to expanded mode
- if (mMoreItemView == null) {
- mMoreItemView = createMoreItemView();
- }
-
- addItemView(mMoreItemView);
-
- // The last view is the more button, so the actual number of items is one less than
- // the number that can fit
- mNumActualItemsShown = numItemsThatCanFit - 1;
- } else if (numItems == numItemsThatCanFit) {
- // There are exactly the number we can show, so show the last item
- final MenuItemImpl lastItemData = itemsToShow.get(numItemsThatCanFit - 1);
- addItemView((IconMenuItemView) lastItemData.getItemView(MenuBuilder.TYPE_ICON, this));
-
- // The items shown fit exactly
- mNumActualItemsShown = numItemsThatCanFit;
- }
- }
-
- /**
- * The positioning algorithm that gets called from onMeasure. It
- * just computes positions for each child, and then stores them in the child's layout params.
- * @param menuWidth The width of this menu to assume for positioning
- * @param menuHeight The height of this menu to assume for positioning
- */
- private void positionChildren(int menuWidth, int menuHeight) {
- // Clear the containers for the positions where the dividers should be drawn
- if (mHorizontalDivider != null) mHorizontalDividerRects.clear();
- if (mVerticalDivider != null) mVerticalDividerRects.clear();
-
- // Get the minimum number of rows needed
- final int numRows = mLayoutNumRows;
- final int numRowsMinus1 = numRows - 1;
- final int numItemsForRow[] = mLayout;
-
- // The item position across all rows
- int itemPos = 0;
- View child;
- IconMenuView.LayoutParams childLayoutParams = null;
-
- // Use float for this to get precise positions (uniform item widths
- // instead of last one taking any slack), and then convert to ints at last opportunity
- float itemLeft;
- float itemTop = 0;
- // Since each row can have a different number of items, this will be computed per row
- float itemWidth;
- // Subtract the space needed for the horizontal dividers
- final float itemHeight = (menuHeight - mHorizontalDividerHeight * (numRows - 1))
- / (float)numRows;
-
- for (int row = 0; row < numRows; row++) {
- // Start at the left
- itemLeft = 0;
-
- // Subtract the space needed for the vertical dividers, and divide by the number of items
- itemWidth = (menuWidth - mVerticalDividerWidth * (numItemsForRow[row] - 1))
- / (float)numItemsForRow[row];
-
- for (int itemPosOnRow = 0; itemPosOnRow < numItemsForRow[row]; itemPosOnRow++) {
- // Tell the child to be exactly this size
- child = getChildAt(itemPos);
- child.measure(MeasureSpec.makeMeasureSpec((int) itemWidth, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec((int) itemHeight, MeasureSpec.EXACTLY));
-
- // Remember the child's position for layout
- childLayoutParams = (IconMenuView.LayoutParams) child.getLayoutParams();
- childLayoutParams.left = (int) itemLeft;
- childLayoutParams.right = (int) (itemLeft + itemWidth);
- childLayoutParams.top = (int) itemTop;
- childLayoutParams.bottom = (int) (itemTop + itemHeight);
-
- // Increment by item width
- itemLeft += itemWidth;
- itemPos++;
-
- // Add a vertical divider to draw
- if (mVerticalDivider != null) {
- mVerticalDividerRects.add(new Rect((int) itemLeft,
- (int) itemTop, (int) (itemLeft + mVerticalDividerWidth),
- (int) (itemTop + itemHeight)));
- }
-
- // Increment by divider width (even if we're not computing
- // dividers, since we need to leave room for them when
- // calculating item positions)
- itemLeft += mVerticalDividerWidth;
- }
-
- // Last child on each row should extend to very right edge
- if (childLayoutParams != null) {
- childLayoutParams.right = menuWidth;
- }
-
- itemTop += itemHeight;
-
- // Add a horizontal divider to draw
- if ((mHorizontalDivider != null) && (row < numRowsMinus1)) {
- mHorizontalDividerRects.add(new Rect(0, (int) itemTop, menuWidth,
- (int) (itemTop + mHorizontalDividerHeight)));
-
- itemTop += mHorizontalDividerHeight;
- }
- }
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (mHasStaleChildren) {
- mHasStaleChildren = false;
-
- // If we have stale data, resync with the menu
- updateChildren(false);
- }
-
- int measuredWidth = resolveSize(Integer.MAX_VALUE, widthMeasureSpec);
- calculateItemFittingMetadata(measuredWidth);
- layoutItems(measuredWidth);
-
- // Get the desired height of the icon menu view (last row of items does
- // not have a divider below)
- final int desiredHeight = (mRowHeight + mHorizontalDividerHeight) *
- mLayoutNumRows - mHorizontalDividerHeight;
-
- // Maximum possible width and desired height
- setMeasuredDimension(measuredWidth,
- resolveSize(desiredHeight, heightMeasureSpec));
-
- // Position the children
- positionChildren(mMeasuredWidth, mMeasuredHeight);
- }
-
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- View child;
- IconMenuView.LayoutParams childLayoutParams;
-
- for (int i = getChildCount() - 1; i >= 0; i--) {
- child = getChildAt(i);
- childLayoutParams = (IconMenuView.LayoutParams)child
- .getLayoutParams();
-
- // Layout children according to positions set during the measure
- child.layout(childLayoutParams.left, childLayoutParams.top, childLayoutParams.right,
- childLayoutParams.bottom);
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- if (mHorizontalDivider != null) {
- // If we have a horizontal divider to draw, draw it at the remembered positions
- for (int i = mHorizontalDividerRects.size() - 1; i >= 0; i--) {
- mHorizontalDivider.setBounds(mHorizontalDividerRects.get(i));
- mHorizontalDivider.draw(canvas);
- }
- }
-
- if (mVerticalDivider != null) {
- // If we have a vertical divider to draw, draw it at the remembered positions
- for (int i = mVerticalDividerRects.size() - 1; i >= 0; i--) {
- mVerticalDivider.setBounds(mVerticalDividerRects.get(i));
- mVerticalDivider.draw(canvas);
- }
- }
- }
-
- public boolean invokeItem(MenuItemImpl item) {
- return mMenu.performItemAction(item, 0);
- }
-
- @Override
- public LayoutParams generateLayoutParams(AttributeSet attrs)
- {
- return new IconMenuView.LayoutParams(getContext(), attrs);
- }
-
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p)
- {
- // Override to allow type-checking of LayoutParams.
- return p instanceof IconMenuView.LayoutParams;
- }
-
- /**
- * Marks as having stale children.
- */
- void markStaleChildren() {
- if (!mHasStaleChildren) {
- mHasStaleChildren = true;
- requestLayout();
- }
- }
-
- /**
- * @return The number of actual items shown (those that are backed by an
- * {@link MenuView.ItemView} implementation--eg: excludes More
- * item).
- */
- int getNumActualItemsShown() {
- return mNumActualItemsShown;
- }
-
-
- public int getWindowAnimations() {
- return mAnimations;
- }
-
- /**
- * Returns the number of items per row.
- * <p>
- * This should only be used for testing.
- *
- * @return The length of the array is the number of rows. A value at a
- * position is the number of items in that row.
- * @hide
- */
- public int[] getLayout() {
- return mLayout;
- }
-
- /**
- * Returns the number of rows in the layout.
- * <p>
- * This should only be used for testing.
- *
- * @return The length of the array is the number of rows. A value at a
- * position is the number of items in that row.
- * @hide
- */
- public int getLayoutNumRows() {
- return mLayoutNumRows;
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
-
- if (event.getKeyCode() == KeyEvent.KEYCODE_MENU) {
- if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
- removeCallbacks(this);
- postDelayed(this, ViewConfiguration.getLongPressTimeout());
- } else if (event.getAction() == KeyEvent.ACTION_UP) {
-
- if (mMenuBeingLongpressed) {
- // It was in cycle mode, so reset it (will also remove us
- // from being called back)
- setCycleShortcutCaptionMode(false);
- return true;
-
- } else {
- // Just remove us from being called back
- removeCallbacks(this);
- // Fall through to normal processing too
- }
- }
- }
-
- return super.dispatchKeyEvent(event);
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- requestFocus();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- setCycleShortcutCaptionMode(false);
- super.onDetachedFromWindow();
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasWindowFocus) {
-
- if (!hasWindowFocus) {
- setCycleShortcutCaptionMode(false);
- }
-
- super.onWindowFocusChanged(hasWindowFocus);
- }
-
- /**
- * Sets the shortcut caption mode for IconMenuView. This mode will
- * continuously cycle between a child's shortcut and its title.
- *
- * @param cycleShortcutAndNormal Whether to go into cycling shortcut mode,
- * or to go back to normal.
- */
- private void setCycleShortcutCaptionMode(boolean cycleShortcutAndNormal) {
-
- if (!cycleShortcutAndNormal) {
- /*
- * We're setting back to title, so remove any callbacks for setting
- * to shortcut
- */
- removeCallbacks(this);
- setChildrenCaptionMode(false);
- mMenuBeingLongpressed = false;
-
- } else {
-
- // Set it the first time (the cycle will be started in run()).
- setChildrenCaptionMode(true);
- }
-
- }
-
- /**
- * When this method is invoked if the menu is currently not being
- * longpressed, it means that the longpress has just been reached (so we set
- * longpress flag, and start cycling). If it is being longpressed, we cycle
- * to the next mode.
- */
- public void run() {
-
- if (mMenuBeingLongpressed) {
-
- // Cycle to other caption mode on the children
- setChildrenCaptionMode(!mLastChildrenCaptionMode);
-
- } else {
-
- // Switch ourselves to continuously cycle the items captions
- mMenuBeingLongpressed = true;
- setCycleShortcutCaptionMode(true);
- }
-
- // We should run again soon to cycle to the other caption mode
- postDelayed(this, ITEM_CAPTION_CYCLE_DELAY);
- }
-
- /**
- * Iterates children and sets the desired shortcut mode. Only
- * {@link #setCycleShortcutCaptionMode(boolean)} and {@link #run()} should call
- * this.
- *
- * @param shortcut Whether to show shortcut or the title.
- */
- private void setChildrenCaptionMode(boolean shortcut) {
-
- // Set the last caption mode pushed to children
- mLastChildrenCaptionMode = shortcut;
-
- for (int i = getChildCount() - 1; i >= 0; i--) {
- ((IconMenuItemView) getChildAt(i)).setCaptionMode(shortcut);
- }
- }
-
- /**
- * For each item, calculates the most dense row that fully shows the item's
- * title.
- *
- * @param width The available width of the icon menu.
- */
- private void calculateItemFittingMetadata(int width) {
- int maxNumItemsPerRow = mMaxItemsPerRow;
- int numItems = getChildCount();
- for (int i = 0; i < numItems; i++) {
- LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
- // Start with 1, since that case does not get covered in the loop below
- lp.maxNumItemsOnRow = 1;
- for (int curNumItemsPerRow = maxNumItemsPerRow; curNumItemsPerRow > 0;
- curNumItemsPerRow--) {
- // Check whether this item can fit into a row containing curNumItemsPerRow
- if (lp.desiredWidth < width / curNumItemsPerRow) {
- // It can, mark this value as the most dense row it can fit into
- lp.maxNumItemsOnRow = curNumItemsPerRow;
- break;
- }
- }
- }
- }
-
- @Override
- protected Parcelable onSaveInstanceState() {
- Parcelable superState = super.onSaveInstanceState();
-
- View focusedView = getFocusedChild();
-
- for (int i = getChildCount() - 1; i >= 0; i--) {
- if (getChildAt(i) == focusedView) {
- return new SavedState(superState, i);
- }
- }
-
- return new SavedState(superState, -1);
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
- super.onRestoreInstanceState(ss.getSuperState());
-
- if (ss.focusedPosition >= getChildCount()) {
- return;
- }
-
- View v = getChildAt(ss.focusedPosition);
- if (v != null) {
- v.requestFocus();
- }
- }
-
- private static class SavedState extends BaseSavedState {
- int focusedPosition;
-
- /**
- * Constructor called from {@link IconMenuView#onSaveInstanceState()}
- */
- public SavedState(Parcelable superState, int focusedPosition) {
- super(superState);
- this.focusedPosition = focusedPosition;
- }
-
- /**
- * Constructor called from {@link #CREATOR}
- */
- private SavedState(Parcel in) {
- super(in);
- focusedPosition = in.readInt();
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(focusedPosition);
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
-
- }
-
- /**
- * Layout parameters specific to IconMenuView (stores the left, top, right, bottom from the
- * measure pass).
- */
- public static class LayoutParams extends ViewGroup.MarginLayoutParams
- {
- int left, top, right, bottom;
- int desiredWidth;
- int maxNumItemsOnRow;
-
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
- }
-
- public LayoutParams(int width, int height) {
- super(width, height);
- }
- }
-}
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
deleted file mode 100644
index e155875..0000000
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view.menu;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.RadioButton;
-import android.widget.TextView;
-
-/**
- * The item view for each item in the ListView-based MenuViews.
- */
-public class ListMenuItemView extends LinearLayout implements MenuView.ItemView {
- private MenuItemImpl mItemData;
-
- private ImageView mIconView;
- private RadioButton mRadioButton;
- private TextView mTitleView;
- private CheckBox mCheckBox;
- private TextView mShortcutView;
-
- private Drawable mBackground;
- private int mTextAppearance;
- private Context mTextAppearanceContext;
-
- private int mMenuType;
-
- public ListMenuItemView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs);
-
- TypedArray a =
- context.obtainStyledAttributes(
- attrs, com.android.internal.R.styleable.MenuView, defStyle, 0);
-
- mBackground = a.getDrawable(com.android.internal.R.styleable.MenuView_itemBackground);
- mTextAppearance = a.getResourceId(com.android.internal.R.styleable.
- MenuView_itemTextAppearance, -1);
- mTextAppearanceContext = context;
-
- a.recycle();
- }
-
- public ListMenuItemView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- setBackgroundDrawable(mBackground);
-
- mTitleView = (TextView) findViewById(com.android.internal.R.id.title);
- if (mTextAppearance != -1) {
- mTitleView.setTextAppearance(mTextAppearanceContext,
- mTextAppearance);
- }
-
- mShortcutView = (TextView) findViewById(com.android.internal.R.id.shortcut);
- }
-
- public void initialize(MenuItemImpl itemData, int menuType) {
- mItemData = itemData;
- mMenuType = menuType;
-
- setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
-
- setTitle(itemData.getTitleForItemView(this));
- setCheckable(itemData.isCheckable());
- setShortcut(itemData.shouldShowShortcut(), itemData.getShortcut());
- setIcon(itemData.getIcon());
- setEnabled(itemData.isEnabled());
- }
-
- public void setTitle(CharSequence title) {
- if (title != null) {
- mTitleView.setText(title);
-
- if (mTitleView.getVisibility() != VISIBLE) mTitleView.setVisibility(VISIBLE);
- } else {
- if (mTitleView.getVisibility() != GONE) mTitleView.setVisibility(GONE);
- }
- }
-
- public MenuItemImpl getItemData() {
- return mItemData;
- }
-
- public void setCheckable(boolean checkable) {
-
- if (!checkable && mRadioButton == null && mCheckBox == null) {
- return;
- }
-
- if (mRadioButton == null) {
- insertRadioButton();
- }
- if (mCheckBox == null) {
- insertCheckBox();
- }
-
- // Depending on whether its exclusive check or not, the checkbox or
- // radio button will be the one in use (and the other will be otherCompoundButton)
- final CompoundButton compoundButton;
- final CompoundButton otherCompoundButton;
-
- if (mItemData.isExclusiveCheckable()) {
- compoundButton = mRadioButton;
- otherCompoundButton = mCheckBox;
- } else {
- compoundButton = mCheckBox;
- otherCompoundButton = mRadioButton;
- }
-
- if (checkable) {
- compoundButton.setChecked(mItemData.isChecked());
-
- final int newVisibility = checkable ? VISIBLE : GONE;
- if (compoundButton.getVisibility() != newVisibility) {
- compoundButton.setVisibility(newVisibility);
- }
-
- // Make sure the other compound button isn't visible
- if (otherCompoundButton.getVisibility() != GONE) {
- otherCompoundButton.setVisibility(GONE);
- }
- } else {
- mCheckBox.setVisibility(GONE);
- mRadioButton.setVisibility(GONE);
- }
- }
-
- public void setChecked(boolean checked) {
- CompoundButton compoundButton;
-
- if (mItemData.isExclusiveCheckable()) {
- if (mRadioButton == null) {
- insertRadioButton();
- }
- compoundButton = mRadioButton;
- } else {
- if (mCheckBox == null) {
- insertCheckBox();
- }
- compoundButton = mCheckBox;
- }
-
- compoundButton.setChecked(checked);
- }
-
- public void setShortcut(boolean showShortcut, char shortcutKey) {
- final int newVisibility = (showShortcut && mItemData.shouldShowShortcut())
- ? VISIBLE : GONE;
-
- if (newVisibility == VISIBLE) {
- mShortcutView.setText(mItemData.getShortcutLabel());
- }
-
- if (mShortcutView.getVisibility() != newVisibility) {
- mShortcutView.setVisibility(newVisibility);
- }
- }
-
- public void setIcon(Drawable icon) {
-
- if (!mItemData.shouldShowIcon(mMenuType)) {
- return;
- }
-
- if (mIconView == null && icon == null) {
- return;
- }
-
- if (mIconView == null) {
- insertIconView();
- }
-
- if (icon != null) {
- mIconView.setImageDrawable(icon);
-
- if (mIconView.getVisibility() != VISIBLE) {
- mIconView.setVisibility(VISIBLE);
- }
- } else {
- mIconView.setVisibility(GONE);
- }
- }
-
- private void insertIconView() {
- LayoutInflater inflater = mItemData.getLayoutInflater(mMenuType);
- mIconView = (ImageView) inflater.inflate(com.android.internal.R.layout.list_menu_item_icon,
- this, false);
- addView(mIconView, 0);
- }
-
- private void insertRadioButton() {
- LayoutInflater inflater = mItemData.getLayoutInflater(mMenuType);
- mRadioButton =
- (RadioButton) inflater.inflate(com.android.internal.R.layout.list_menu_item_radio,
- this, false);
- addView(mRadioButton);
- }
-
- private void insertCheckBox() {
- LayoutInflater inflater = mItemData.getLayoutInflater(mMenuType);
- mCheckBox =
- (CheckBox) inflater.inflate(com.android.internal.R.layout.list_menu_item_checkbox,
- this, false);
- addView(mCheckBox);
- }
-
- public boolean prefersCondensedTitle() {
- return false;
- }
-
- public boolean showsIcon() {
- return false;
- }
-
-}
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
deleted file mode 100644
index cbc4e9f..0000000
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ /dev/null
@@ -1,1120 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view.menu;
-
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.util.SparseArray;
-import android.view.ContextThemeWrapper;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.SubMenu;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.LayoutInflater;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Implementation of the {@link android.view.Menu} interface for creating a
- * standard menu UI.
- */
-public class MenuBuilder implements Menu {
- private static final String LOGTAG = "MenuBuilder";
-
- /** The number of different menu types */
- public static final int NUM_TYPES = 3;
- /** The menu type that represents the icon menu view */
- public static final int TYPE_ICON = 0;
- /** The menu type that represents the expanded menu view */
- public static final int TYPE_EXPANDED = 1;
- /**
- * The menu type that represents a menu dialog. Examples are context and sub
- * menus. This menu type will not have a corresponding MenuView, but it will
- * have an ItemView.
- */
- public static final int TYPE_DIALOG = 2;
-
- private static final String VIEWS_TAG = "android:views";
-
- // Order must be the same order as the TYPE_*
- static final int THEME_RES_FOR_TYPE[] = new int[] {
- com.android.internal.R.style.Theme_IconMenu,
- com.android.internal.R.style.Theme_ExpandedMenu,
- 0,
- };
-
- // Order must be the same order as the TYPE_*
- static final int LAYOUT_RES_FOR_TYPE[] = new int[] {
- com.android.internal.R.layout.icon_menu_layout,
- com.android.internal.R.layout.expanded_menu_layout,
- 0,
- };
-
- // Order must be the same order as the TYPE_*
- static final int ITEM_LAYOUT_RES_FOR_TYPE[] = new int[] {
- com.android.internal.R.layout.icon_menu_item_layout,
- com.android.internal.R.layout.list_menu_item_layout,
- com.android.internal.R.layout.list_menu_item_layout,
- };
-
- private static final int[] sCategoryToOrder = new int[] {
- 1, /* No category */
- 4, /* CONTAINER */
- 5, /* SYSTEM */
- 3, /* SECONDARY */
- 2, /* ALTERNATIVE */
- 0, /* SELECTED_ALTERNATIVE */
- };
-
- private final Context mContext;
- private final Resources mResources;
-
- /**
- * Whether the shortcuts should be qwerty-accessible. Use isQwertyMode()
- * instead of accessing this directly.
- */
- private boolean mQwertyMode;
-
- /**
- * Whether the shortcuts should be visible on menus. Use isShortcutsVisible()
- * instead of accessing this directly.
- */
- private boolean mShortcutsVisible;
-
- /**
- * Callback that will receive the various menu-related events generated by
- * this class. Use getCallback to get a reference to the callback.
- */
- private Callback mCallback;
-
- /** Contains all of the items for this menu */
- private ArrayList<MenuItemImpl> mItems;
-
- /** Contains only the items that are currently visible. This will be created/refreshed from
- * {@link #getVisibleItems()} */
- private ArrayList<MenuItemImpl> mVisibleItems;
- /**
- * Whether or not the items (or any one item's shown state) has changed since it was last
- * fetched from {@link #getVisibleItems()}
- */
- private boolean mIsVisibleItemsStale;
-
- /**
- * Current use case is Context Menus: As Views populate the context menu, each one has
- * extra information that should be passed along. This is the current menu info that
- * should be set on all items added to this menu.
- */
- private ContextMenuInfo mCurrentMenuInfo;
-
- /** Header title for menu types that have a header (context and submenus) */
- CharSequence mHeaderTitle;
- /** Header icon for menu types that have a header and support icons (context) */
- Drawable mHeaderIcon;
- /** Header custom view for menu types that have a header and support custom views (context) */
- View mHeaderView;
-
- /**
- * Contains the state of the View hierarchy for all menu views when the menu
- * was frozen.
- */
- private SparseArray<Parcelable> mFrozenViewStates;
-
- /**
- * Prevents onItemsChanged from doing its junk, useful for batching commands
- * that may individually call onItemsChanged.
- */
- private boolean mPreventDispatchingItemsChanged = false;
-
- private boolean mOptionalIconsVisible = false;
-
- private MenuType[] mMenuTypes;
- class MenuType {
- private int mMenuType;
-
- /** The layout inflater that uses the menu type's theme */
- private LayoutInflater mInflater;
-
- /** The lazily loaded {@link MenuView} */
- private WeakReference<MenuView> mMenuView;
-
- MenuType(int menuType) {
- mMenuType = menuType;
- }
-
- LayoutInflater getInflater() {
- // Create an inflater that uses the given theme for the Views it inflates
- if (mInflater == null) {
- Context wrappedContext = new ContextThemeWrapper(mContext,
- THEME_RES_FOR_TYPE[mMenuType]);
- mInflater = (LayoutInflater) wrappedContext
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
-
- return mInflater;
- }
-
- MenuView getMenuView(ViewGroup parent) {
- if (LAYOUT_RES_FOR_TYPE[mMenuType] == 0) {
- return null;
- }
-
- synchronized (this) {
- MenuView menuView = mMenuView != null ? mMenuView.get() : null;
-
- if (menuView == null) {
- menuView = (MenuView) getInflater().inflate(
- LAYOUT_RES_FOR_TYPE[mMenuType], parent, false);
- menuView.initialize(MenuBuilder.this, mMenuType);
-
- // Cache the view
- mMenuView = new WeakReference<MenuView>(menuView);
-
- if (mFrozenViewStates != null) {
- View view = (View) menuView;
- view.restoreHierarchyState(mFrozenViewStates);
-
- // Clear this menu type's frozen state, since we just restored it
- mFrozenViewStates.remove(view.getId());
- }
- }
-
- return menuView;
- }
- }
-
- boolean hasMenuView() {
- return mMenuView != null && mMenuView.get() != null;
- }
- }
-
- /**
- * Called by menu to notify of close and selection changes
- */
- public interface Callback {
- /**
- * Called when a menu item is selected.
- * @param menu The menu that is the parent of the item
- * @param item The menu item that is selected
- * @return whether the menu item selection was handled
- */
- public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item);
-
- /**
- * Called when a menu is closed.
- * @param menu The menu that was closed.
- * @param allMenusAreClosing Whether the menus are completely closing (true),
- * or whether there is another menu opening shortly
- * (false). For example, if the menu is closing because a
- * sub menu is about to be shown, <var>allMenusAreClosing</var>
- * is false.
- */
- public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing);
-
- /**
- * Called when a sub menu is selected. This is a cue to open the given sub menu's decor.
- * @param subMenu the sub menu that is being opened
- * @return whether the sub menu selection was handled by the callback
- */
- public boolean onSubMenuSelected(SubMenuBuilder subMenu);
-
- /**
- * Called when a sub menu is closed
- * @param menu the sub menu that was closed
- */
- public void onCloseSubMenu(SubMenuBuilder menu);
-
- /**
- * Called when the mode of the menu changes (for example, from icon to expanded).
- *
- * @param menu the menu that has changed modes
- */
- public void onMenuModeChange(MenuBuilder menu);
- }
-
- /**
- * Called by menu items to execute their associated action
- */
- public interface ItemInvoker {
- public boolean invokeItem(MenuItemImpl item);
- }
-
- public MenuBuilder(Context context) {
- mMenuTypes = new MenuType[NUM_TYPES];
-
- mContext = context;
- mResources = context.getResources();
-
- mItems = new ArrayList<MenuItemImpl>();
-
- mVisibleItems = new ArrayList<MenuItemImpl>();
- mIsVisibleItemsStale = true;
-
- mShortcutsVisible =
- (mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS);
- }
-
- public void setCallback(Callback callback) {
- mCallback = callback;
- }
-
- MenuType getMenuType(int menuType) {
- if (mMenuTypes[menuType] == null) {
- mMenuTypes[menuType] = new MenuType(menuType);
- }
-
- return mMenuTypes[menuType];
- }
-
- /**
- * Gets a menu View that contains this menu's items.
- *
- * @param menuType The type of menu to get a View for (must be one of
- * {@link #TYPE_ICON}, {@link #TYPE_EXPANDED},
- * {@link #TYPE_DIALOG}).
- * @param parent The ViewGroup that provides a set of LayoutParams values
- * for this menu view
- * @return A View for the menu of type <var>menuType</var>
- */
- public View getMenuView(int menuType, ViewGroup parent) {
- // The expanded menu depends on the number if items shown in the icon menu (which
- // is adjustable as setters/XML attributes on IconMenuView [imagine a larger LCD
- // wanting to show more icons]). If, for example, the activity goes through
- // an orientation change while the expanded menu is open, the icon menu's view
- // won't have an instance anymore; so here we make sure we have an icon menu view (matching
- // the same parent so the layout parameters from the XML are used). This
- // will create the icon menu view and cache it (if it doesn't already exist).
- if (menuType == TYPE_EXPANDED
- && (mMenuTypes[TYPE_ICON] == null || !mMenuTypes[TYPE_ICON].hasMenuView())) {
- getMenuType(TYPE_ICON).getMenuView(parent);
- }
-
- return (View) getMenuType(menuType).getMenuView(parent);
- }
-
- private int getNumIconMenuItemsShown() {
- ViewGroup parent = null;
-
- if (!mMenuTypes[TYPE_ICON].hasMenuView()) {
- /*
- * There isn't an icon menu view instantiated, so when we get it
- * below, it will lazily instantiate it. We should pass a proper
- * parent so it uses the layout_ attributes present in the XML
- * layout file.
- */
- if (mMenuTypes[TYPE_EXPANDED].hasMenuView()) {
- View expandedMenuView = (View) mMenuTypes[TYPE_EXPANDED].getMenuView(null);
- parent = (ViewGroup) expandedMenuView.getParent();
- }
- }
-
- return ((IconMenuView) getMenuView(TYPE_ICON, parent)).getNumActualItemsShown();
- }
-
- /**
- * Clears the cached menu views. Call this if the menu views need to another
- * layout (for example, if the screen size has changed).
- */
- public void clearMenuViews() {
- for (int i = NUM_TYPES - 1; i >= 0; i--) {
- if (mMenuTypes[i] != null) {
- mMenuTypes[i].mMenuView = null;
- }
- }
-
- for (int i = mItems.size() - 1; i >= 0; i--) {
- MenuItemImpl item = mItems.get(i);
- if (item.hasSubMenu()) {
- ((SubMenuBuilder) item.getSubMenu()).clearMenuViews();
- }
- item.clearItemViews();
- }
- }
-
- /**
- * Adds an item to the menu. The other add methods funnel to this.
- */
- private MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) {
- final int ordering = getOrdering(categoryOrder);
-
- final MenuItemImpl item = new MenuItemImpl(this, group, id, categoryOrder, ordering, title);
-
- if (mCurrentMenuInfo != null) {
- // Pass along the current menu info
- item.setMenuInfo(mCurrentMenuInfo);
- }
-
- mItems.add(findInsertIndex(mItems, ordering), item);
- onItemsChanged(false);
-
- return item;
- }
-
- public MenuItem add(CharSequence title) {
- return addInternal(0, 0, 0, title);
- }
-
- public MenuItem add(int titleRes) {
- return addInternal(0, 0, 0, mResources.getString(titleRes));
- }
-
- public MenuItem add(int group, int id, int categoryOrder, CharSequence title) {
- return addInternal(group, id, categoryOrder, title);
- }
-
- public MenuItem add(int group, int id, int categoryOrder, int title) {
- return addInternal(group, id, categoryOrder, mResources.getString(title));
- }
-
- public SubMenu addSubMenu(CharSequence title) {
- return addSubMenu(0, 0, 0, title);
- }
-
- public SubMenu addSubMenu(int titleRes) {
- return addSubMenu(0, 0, 0, mResources.getString(titleRes));
- }
-
- public SubMenu addSubMenu(int group, int id, int categoryOrder, CharSequence title) {
- final MenuItemImpl item = (MenuItemImpl) addInternal(group, id, categoryOrder, title);
- final SubMenuBuilder subMenu = new SubMenuBuilder(mContext, this, item);
- item.setSubMenu(subMenu);
-
- return subMenu;
- }
-
- public SubMenu addSubMenu(int group, int id, int categoryOrder, int title) {
- return addSubMenu(group, id, categoryOrder, mResources.getString(title));
- }
-
- public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller,
- Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) {
- PackageManager pm = mContext.getPackageManager();
- final List<ResolveInfo> lri =
- pm.queryIntentActivityOptions(caller, specifics, intent, 0);
- final int N = lri != null ? lri.size() : 0;
-
- if ((flags & FLAG_APPEND_TO_GROUP) == 0) {
- removeGroup(group);
- }
-
- for (int i=0; i<N; i++) {
- final ResolveInfo ri = lri.get(i);
- Intent rintent = new Intent(
- ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]);
- rintent.setComponent(new ComponentName(
- ri.activityInfo.applicationInfo.packageName,
- ri.activityInfo.name));
- final MenuItem item = add(group, id, categoryOrder, ri.loadLabel(pm))
- .setIcon(ri.loadIcon(pm))
- .setIntent(rintent);
- if (outSpecificItems != null && ri.specificIndex >= 0) {
- outSpecificItems[ri.specificIndex] = item;
- }
- }
-
- return N;
- }
-
- public void removeItem(int id) {
- removeItemAtInt(findItemIndex(id), true);
- }
-
- public void removeGroup(int group) {
- final int i = findGroupIndex(group);
-
- if (i >= 0) {
- final int maxRemovable = mItems.size() - i;
- int numRemoved = 0;
- while ((numRemoved++ < maxRemovable) && (mItems.get(i).getGroupId() == group)) {
- // Don't force update for each one, this method will do it at the end
- removeItemAtInt(i, false);
- }
-
- // Notify menu views
- onItemsChanged(false);
- }
- }
-
- /**
- * Remove the item at the given index and optionally forces menu views to
- * update.
- *
- * @param index The index of the item to be removed. If this index is
- * invalid an exception is thrown.
- * @param updateChildrenOnMenuViews Whether to force update on menu views.
- * Please make sure you eventually call this after your batch of
- * removals.
- */
- private void removeItemAtInt(int index, boolean updateChildrenOnMenuViews) {
- if ((index < 0) || (index >= mItems.size())) return;
-
- mItems.remove(index);
-
- if (updateChildrenOnMenuViews) onItemsChanged(false);
- }
-
- public void removeItemAt(int index) {
- removeItemAtInt(index, true);
- }
-
- public void clearAll() {
- mPreventDispatchingItemsChanged = true;
- clear();
- clearHeader();
- mPreventDispatchingItemsChanged = false;
- onItemsChanged(true);
- }
-
- public void clear() {
- mItems.clear();
-
- onItemsChanged(true);
- }
-
- void setExclusiveItemChecked(MenuItem item) {
- final int group = item.getGroupId();
-
- final int N = mItems.size();
- for (int i = 0; i < N; i++) {
- MenuItemImpl curItem = mItems.get(i);
- if (curItem.getGroupId() == group) {
- if (!curItem.isExclusiveCheckable()) continue;
- if (!curItem.isCheckable()) continue;
-
- // Check the item meant to be checked, uncheck the others (that are in the group)
- curItem.setCheckedInt(curItem == item);
- }
- }
- }
-
- public void setGroupCheckable(int group, boolean checkable, boolean exclusive) {
- final int N = mItems.size();
-
- for (int i = 0; i < N; i++) {
- MenuItemImpl item = mItems.get(i);
- if (item.getGroupId() == group) {
- item.setExclusiveCheckable(exclusive);
- item.setCheckable(checkable);
- }
- }
- }
-
- public void setGroupVisible(int group, boolean visible) {
- final int N = mItems.size();
-
- // We handle the notification of items being changed ourselves, so we use setVisibleInt rather
- // than setVisible and at the end notify of items being changed
-
- boolean changedAtLeastOneItem = false;
- for (int i = 0; i < N; i++) {
- MenuItemImpl item = mItems.get(i);
- if (item.getGroupId() == group) {
- if (item.setVisibleInt(visible)) changedAtLeastOneItem = true;
- }
- }
-
- if (changedAtLeastOneItem) onItemsChanged(false);
- }
-
- public void setGroupEnabled(int group, boolean enabled) {
- final int N = mItems.size();
-
- for (int i = 0; i < N; i++) {
- MenuItemImpl item = mItems.get(i);
- if (item.getGroupId() == group) {
- item.setEnabled(enabled);
- }
- }
- }
-
- public boolean hasVisibleItems() {
- final int size = size();
-
- for (int i = 0; i < size; i++) {
- MenuItemImpl item = mItems.get(i);
- if (item.isVisible()) {
- return true;
- }
- }
-
- return false;
- }
-
- public MenuItem findItem(int id) {
- final int size = size();
- for (int i = 0; i < size; i++) {
- MenuItemImpl item = mItems.get(i);
- if (item.getItemId() == id) {
- return item;
- } else if (item.hasSubMenu()) {
- MenuItem possibleItem = item.getSubMenu().findItem(id);
-
- if (possibleItem != null) {
- return possibleItem;
- }
- }
- }
-
- return null;
- }
-
- public int findItemIndex(int id) {
- final int size = size();
-
- for (int i = 0; i < size; i++) {
- MenuItemImpl item = mItems.get(i);
- if (item.getItemId() == id) {
- return i;
- }
- }
-
- return -1;
- }
-
- public int findGroupIndex(int group) {
- return findGroupIndex(group, 0);
- }
-
- public int findGroupIndex(int group, int start) {
- final int size = size();
-
- if (start < 0) {
- start = 0;
- }
-
- for (int i = start; i < size; i++) {
- final MenuItemImpl item = mItems.get(i);
-
- if (item.getGroupId() == group) {
- return i;
- }
- }
-
- return -1;
- }
-
- public int size() {
- return mItems.size();
- }
-
- /** {@inheritDoc} */
- public MenuItem getItem(int index) {
- return mItems.get(index);
- }
-
- public boolean isShortcutKey(int keyCode, KeyEvent event) {
- return findItemWithShortcutForKey(keyCode, event) != null;
- }
-
- public void setQwertyMode(boolean isQwerty) {
- mQwertyMode = isQwerty;
-
- refreshShortcuts(isShortcutsVisible(), isQwerty);
- }
-
- /**
- * Returns the ordering across all items. This will grab the category from
- * the upper bits, find out how to order the category with respect to other
- * categories, and combine it with the lower bits.
- *
- * @param categoryOrder The category order for a particular item (if it has
- * not been or/add with a category, the default category is
- * assumed).
- * @return An ordering integer that can be used to order this item across
- * all the items (even from other categories).
- */
- private static int getOrdering(int categoryOrder)
- {
- final int index = (categoryOrder & CATEGORY_MASK) >> CATEGORY_SHIFT;
-
- if (index < 0 || index >= sCategoryToOrder.length) {
- throw new IllegalArgumentException("order does not contain a valid category.");
- }
-
- return (sCategoryToOrder[index] << CATEGORY_SHIFT) | (categoryOrder & USER_MASK);
- }
-
- /**
- * @return whether the menu shortcuts are in qwerty mode or not
- */
- boolean isQwertyMode() {
- return mQwertyMode;
- }
-
- /**
- * Refreshes the shortcut labels on each of the displayed items. Passes the arguments
- * so submenus don't need to call their parent menu for the same values.
- */
- private void refreshShortcuts(boolean shortcutsVisible, boolean qwertyMode) {
- MenuItemImpl item;
- for (int i = mItems.size() - 1; i >= 0; i--) {
- item = mItems.get(i);
-
- if (item.hasSubMenu()) {
- ((MenuBuilder) item.getSubMenu()).refreshShortcuts(shortcutsVisible, qwertyMode);
- }
-
- item.refreshShortcutOnItemViews(shortcutsVisible, qwertyMode);
- }
- }
-
- /**
- * Sets whether the shortcuts should be visible on menus. Devices without hardware
- * key input will never make shortcuts visible even if this method is passed 'true'.
- *
- * @param shortcutsVisible Whether shortcuts should be visible (if true and a
- * menu item does not have a shortcut defined, that item will
- * still NOT show a shortcut)
- */
- public void setShortcutsVisible(boolean shortcutsVisible) {
- if (mShortcutsVisible == shortcutsVisible) return;
-
- mShortcutsVisible =
- (mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS)
- && shortcutsVisible;
-
- refreshShortcuts(mShortcutsVisible, isQwertyMode());
- }
-
- /**
- * @return Whether shortcuts should be visible on menus.
- */
- public boolean isShortcutsVisible() {
- return mShortcutsVisible;
- }
-
- Resources getResources() {
- return mResources;
- }
-
- public Callback getCallback() {
- return mCallback;
- }
-
- public Context getContext() {
- return mContext;
- }
-
- private static int findInsertIndex(ArrayList<MenuItemImpl> items, int ordering) {
- for (int i = items.size() - 1; i >= 0; i--) {
- MenuItemImpl item = items.get(i);
- if (item.getOrdering() <= ordering) {
- return i + 1;
- }
- }
-
- return 0;
- }
-
- public boolean performShortcut(int keyCode, KeyEvent event, int flags) {
- final MenuItemImpl item = findItemWithShortcutForKey(keyCode, event);
-
- boolean handled = false;
-
- if (item != null) {
- handled = performItemAction(item, flags);
- }
-
- if ((flags & FLAG_ALWAYS_PERFORM_CLOSE) != 0) {
- close(true);
- }
-
- return handled;
- }
-
- MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) {
- final boolean qwerty = isQwertyMode();
- final int metaState = event.getMetaState();
- final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
- // Get the chars associated with the keyCode (i.e using any chording combo)
- final boolean isKeyCodeMapped = event.getKeyData(possibleChars);
- // The delete key is not mapped to '\b' so we treat it specially
- if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) {
- return null;
- }
-
- // Look for an item whose shortcut is this key.
- final int N = mItems.size();
- for (int i = 0; i < N; i++) {
- MenuItemImpl item = mItems.get(i);
- if (item.hasSubMenu()) {
- MenuItemImpl subMenuItem = ((MenuBuilder)item.getSubMenu())
- .findItemWithShortcutForKey(keyCode, event);
- if (subMenuItem != null) {
- return subMenuItem;
- }
- }
- if (qwerty) {
- final char shortcutAlphaChar = item.getAlphabeticShortcut();
- if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
- (shortcutAlphaChar != 0) &&
- (shortcutAlphaChar == possibleChars.meta[0]
- || shortcutAlphaChar == possibleChars.meta[2]
- || (shortcutAlphaChar == '\b' && keyCode == KeyEvent.KEYCODE_DEL)) &&
- item.isEnabled()) {
- return item;
- }
- } else {
- final char shortcutNumericChar = item.getNumericShortcut();
- if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
- (shortcutNumericChar != 0) &&
- (shortcutNumericChar == possibleChars.meta[0]
- || shortcutNumericChar == possibleChars.meta[2]) &&
- item.isEnabled()) {
- return item;
- }
- }
- }
- return null;
- }
-
- public boolean performIdentifierAction(int id, int flags) {
- // Look for an item whose identifier is the id.
- return performItemAction(findItem(id), flags);
- }
-
- public boolean performItemAction(MenuItem item, int flags) {
- MenuItemImpl itemImpl = (MenuItemImpl) item;
-
- if (itemImpl == null || !itemImpl.isEnabled()) {
- return false;
- }
-
- boolean invoked = itemImpl.invoke();
-
- if (item.hasSubMenu()) {
- close(false);
-
- if (mCallback != null) {
- // Return true if the sub menu was invoked or the item was invoked previously
- invoked = mCallback.onSubMenuSelected((SubMenuBuilder) item.getSubMenu())
- || invoked;
- }
- } else {
- if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) {
- close(true);
- }
- }
-
- return invoked;
- }
-
- /**
- * Closes the visible menu.
- *
- * @param allMenusAreClosing Whether the menus are completely closing (true),
- * or whether there is another menu coming in this menu's place
- * (false). For example, if the menu is closing because a
- * sub menu is about to be shown, <var>allMenusAreClosing</var>
- * is false.
- */
- final void close(boolean allMenusAreClosing) {
- Callback callback = getCallback();
- if (callback != null) {
- callback.onCloseMenu(this, allMenusAreClosing);
- }
- }
-
- /** {@inheritDoc} */
- public void close() {
- close(true);
- }
-
- /**
- * Called when an item is added or removed.
- *
- * @param cleared Whether the items were cleared or just changed.
- */
- private void onItemsChanged(boolean cleared) {
- if (!mPreventDispatchingItemsChanged) {
- if (mIsVisibleItemsStale == false) mIsVisibleItemsStale = true;
-
- MenuType[] menuTypes = mMenuTypes;
- for (int i = 0; i < NUM_TYPES; i++) {
- if ((menuTypes[i] != null) && (menuTypes[i].hasMenuView())) {
- MenuView menuView = menuTypes[i].mMenuView.get();
- menuView.updateChildren(cleared);
- }
- }
- }
- }
-
- /**
- * Called by {@link MenuItemImpl} when its visible flag is changed.
- * @param item The item that has gone through a visibility change.
- */
- void onItemVisibleChanged(MenuItemImpl item) {
- // Notify of items being changed
- onItemsChanged(false);
- }
-
- ArrayList<MenuItemImpl> getVisibleItems() {
- if (!mIsVisibleItemsStale) return mVisibleItems;
-
- // Refresh the visible items
- mVisibleItems.clear();
-
- final int itemsSize = mItems.size();
- MenuItemImpl item;
- for (int i = 0; i < itemsSize; i++) {
- item = mItems.get(i);
- if (item.isVisible()) mVisibleItems.add(item);
- }
-
- mIsVisibleItemsStale = false;
-
- return mVisibleItems;
- }
-
- public void clearHeader() {
- mHeaderIcon = null;
- mHeaderTitle = null;
- mHeaderView = null;
-
- onItemsChanged(false);
- }
-
- private void setHeaderInternal(final int titleRes, final CharSequence title, final int iconRes,
- final Drawable icon, final View view) {
- final Resources r = getResources();
-
- if (view != null) {
- mHeaderView = view;
-
- // If using a custom view, then the title and icon aren't used
- mHeaderTitle = null;
- mHeaderIcon = null;
- } else {
- if (titleRes > 0) {
- mHeaderTitle = r.getText(titleRes);
- } else if (title != null) {
- mHeaderTitle = title;
- }
-
- if (iconRes > 0) {
- mHeaderIcon = r.getDrawable(iconRes);
- } else if (icon != null) {
- mHeaderIcon = icon;
- }
-
- // If using the title or icon, then a custom view isn't used
- mHeaderView = null;
- }
-
- // Notify of change
- onItemsChanged(false);
- }
-
- /**
- * Sets the header's title. This replaces the header view. Called by the
- * builder-style methods of subclasses.
- *
- * @param title The new title.
- * @return This MenuBuilder so additional setters can be called.
- */
- protected MenuBuilder setHeaderTitleInt(CharSequence title) {
- setHeaderInternal(0, title, 0, null, null);
- return this;
- }
-
- /**
- * Sets the header's title. This replaces the header view. Called by the
- * builder-style methods of subclasses.
- *
- * @param titleRes The new title (as a resource ID).
- * @return This MenuBuilder so additional setters can be called.
- */
- protected MenuBuilder setHeaderTitleInt(int titleRes) {
- setHeaderInternal(titleRes, null, 0, null, null);
- return this;
- }
-
- /**
- * Sets the header's icon. This replaces the header view. Called by the
- * builder-style methods of subclasses.
- *
- * @param icon The new icon.
- * @return This MenuBuilder so additional setters can be called.
- */
- protected MenuBuilder setHeaderIconInt(Drawable icon) {
- setHeaderInternal(0, null, 0, icon, null);
- return this;
- }
-
- /**
- * Sets the header's icon. This replaces the header view. Called by the
- * builder-style methods of subclasses.
- *
- * @param iconRes The new icon (as a resource ID).
- * @return This MenuBuilder so additional setters can be called.
- */
- protected MenuBuilder setHeaderIconInt(int iconRes) {
- setHeaderInternal(0, null, iconRes, null, null);
- return this;
- }
-
- /**
- * Sets the header's view. This replaces the title and icon. Called by the
- * builder-style methods of subclasses.
- *
- * @param view The new view.
- * @return This MenuBuilder so additional setters can be called.
- */
- protected MenuBuilder setHeaderViewInt(View view) {
- setHeaderInternal(0, null, 0, null, view);
- return this;
- }
-
- public CharSequence getHeaderTitle() {
- return mHeaderTitle;
- }
-
- public Drawable getHeaderIcon() {
- return mHeaderIcon;
- }
-
- public View getHeaderView() {
- return mHeaderView;
- }
-
- /**
- * Gets the root menu (if this is a submenu, find its root menu).
- * @return The root menu.
- */
- public MenuBuilder getRootMenu() {
- return this;
- }
-
- /**
- * Sets the current menu info that is set on all items added to this menu
- * (until this is called again with different menu info, in which case that
- * one will be added to all subsequent item additions).
- *
- * @param menuInfo The extra menu information to add.
- */
- public void setCurrentMenuInfo(ContextMenuInfo menuInfo) {
- mCurrentMenuInfo = menuInfo;
- }
-
- /**
- * Gets an adapter for providing items and their views.
- *
- * @param menuType The type of menu to get an adapter for.
- * @return A {@link MenuAdapter} for this menu with the given menu type.
- */
- public MenuAdapter getMenuAdapter(int menuType) {
- return new MenuAdapter(menuType);
- }
-
- void setOptionalIconsVisible(boolean visible) {
- mOptionalIconsVisible = visible;
- }
-
- boolean getOptionalIconsVisible() {
- return mOptionalIconsVisible;
- }
-
- public void saveHierarchyState(Bundle outState) {
- SparseArray<Parcelable> viewStates = new SparseArray<Parcelable>();
-
- MenuType[] menuTypes = mMenuTypes;
- for (int i = NUM_TYPES - 1; i >= 0; i--) {
- if (menuTypes[i] == null) {
- continue;
- }
-
- if (menuTypes[i].hasMenuView()) {
- ((View) menuTypes[i].getMenuView(null)).saveHierarchyState(viewStates);
- }
- }
-
- outState.putSparseParcelableArray(VIEWS_TAG, viewStates);
- }
-
- public void restoreHierarchyState(Bundle inState) {
- // Save this for menu views opened later
- SparseArray<Parcelable> viewStates = mFrozenViewStates = inState
- .getSparseParcelableArray(VIEWS_TAG);
-
- // Thaw those menu views already open
- MenuType[] menuTypes = mMenuTypes;
- for (int i = NUM_TYPES - 1; i >= 0; i--) {
- if (menuTypes[i] == null) {
- continue;
- }
-
- if (menuTypes[i].hasMenuView()) {
- ((View) menuTypes[i].getMenuView(null)).restoreHierarchyState(viewStates);
- }
- }
- }
-
- /**
- * An adapter that allows an {@link AdapterView} to use this {@link MenuBuilder} as a data
- * source. This adapter will use only the visible/shown items from the menu.
- */
- public class MenuAdapter extends BaseAdapter {
- private int mMenuType;
-
- public MenuAdapter(int menuType) {
- mMenuType = menuType;
- }
-
- public int getOffset() {
- if (mMenuType == TYPE_EXPANDED) {
- return getNumIconMenuItemsShown();
- } else {
- return 0;
- }
- }
-
- public int getCount() {
- return getVisibleItems().size() - getOffset();
- }
-
- public MenuItemImpl getItem(int position) {
- return getVisibleItems().get(position + getOffset());
- }
-
- public long getItemId(int position) {
- // Since a menu item's ID is optional, we'll use the position as an
- // ID for the item in the AdapterView
- return position;
- }
-
- public View getView(int position, View convertView, ViewGroup parent) {
- return ((MenuItemImpl) getItem(position)).getItemView(mMenuType, parent);
- }
-
- }
-}
diff --git a/core/java/com/android/internal/view/menu/MenuDialogHelper.java b/core/java/com/android/internal/view/menu/MenuDialogHelper.java
deleted file mode 100644
index bc51cf3..0000000
--- a/core/java/com/android/internal/view/menu/MenuDialogHelper.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view.menu;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.os.IBinder;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.ListAdapter;
-
-/**
- * Helper for menus that appear as Dialogs (context and submenus).
- *
- * @hide
- */
-public class MenuDialogHelper implements DialogInterface.OnKeyListener, DialogInterface.OnClickListener {
- private MenuBuilder mMenu;
- private ListAdapter mAdapter;
- private AlertDialog mDialog;
-
- public MenuDialogHelper(MenuBuilder menu) {
- mMenu = menu;
- }
-
- /**
- * Shows menu as a dialog.
- *
- * @param windowToken Optional token to assign to the window.
- */
- public void show(IBinder windowToken) {
- // Many references to mMenu, create local reference
- final MenuBuilder menu = mMenu;
-
- // Get an adapter for the menu item views
- mAdapter = menu.getMenuAdapter(MenuBuilder.TYPE_DIALOG);
-
- // Get the builder for the dialog
- final AlertDialog.Builder builder = new AlertDialog.Builder(menu.getContext())
- .setAdapter(mAdapter, this);
-
- // Set the title
- final View headerView = menu.getHeaderView();
- if (headerView != null) {
- // Menu's client has given a custom header view, use it
- builder.setCustomTitle(headerView);
- } else {
- // Otherwise use the (text) title and icon
- builder.setIcon(menu.getHeaderIcon()).setTitle(menu.getHeaderTitle());
- }
-
- // Set the key listener
- builder.setOnKeyListener(this);
-
- // Show the menu
- mDialog = builder.create();
-
- WindowManager.LayoutParams lp = mDialog.getWindow().getAttributes();
- lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
- if (windowToken != null) {
- lp.token = windowToken;
- }
- lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-
- mDialog.show();
- }
-
- public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
- /*
- * Close menu on key down (more responsive, and there's no way to cancel
- * a key press so no point having it on key up. Note: This is also
- * needed because when a top-level menu item that shows a submenu is
- * invoked by chording, this onKey method will be called with the menu
- * up event.
- */
- if (event.getAction() == KeyEvent.ACTION_DOWN && (keyCode == KeyEvent.KEYCODE_MENU)
- || (keyCode == KeyEvent.KEYCODE_BACK)) {
- mMenu.close(true);
- dialog.dismiss();
- return true;
- }
-
- // Menu shortcut matching
- if (mMenu.performShortcut(keyCode, event, 0)) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Dismisses the menu's dialog.
- *
- * @see Dialog#dismiss()
- */
- public void dismiss() {
- if (mDialog != null) {
- mDialog.dismiss();
- }
- }
-
- public void onClick(DialogInterface dialog, int which) {
- mMenu.performItemAction((MenuItemImpl) mAdapter.getItem(which), 0);
- }
-
-}
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
deleted file mode 100644
index 1543b62..0000000
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ /dev/null
@@ -1,625 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view.menu;
-
-import com.android.internal.view.menu.MenuView.ItemView;
-
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.view.LayoutInflater;
-import android.view.MenuItem;
-import android.view.SubMenu;
-import android.view.View;
-import android.view.ViewDebug;
-import android.view.ViewGroup;
-import android.view.ContextMenu.ContextMenuInfo;
-
-import java.lang.ref.WeakReference;
-
-/**
- * @hide
- */
-public final class MenuItemImpl implements MenuItem {
- private final int mId;
- private final int mGroup;
- private final int mCategoryOrder;
- private final int mOrdering;
- private CharSequence mTitle;
- private CharSequence mTitleCondensed;
- private Intent mIntent;
- private char mShortcutNumericChar;
- private char mShortcutAlphabeticChar;
-
- /** The icon's drawable which is only created as needed */
- private Drawable mIconDrawable;
- /**
- * The icon's resource ID which is used to get the Drawable when it is
- * needed (if the Drawable isn't already obtained--only one of the two is
- * needed).
- */
- private int mIconResId = NO_ICON;
-
- /** The (cached) menu item views for this item */
- private WeakReference<ItemView> mItemViews[];
-
- /** The menu to which this item belongs */
- private MenuBuilder mMenu;
- /** If this item should launch a sub menu, this is the sub menu to launch */
- private SubMenuBuilder mSubMenu;
-
- private Runnable mItemCallback;
- private MenuItem.OnMenuItemClickListener mClickListener;
-
- private int mFlags = ENABLED;
- private static final int CHECKABLE = 0x00000001;
- private static final int CHECKED = 0x00000002;
- private static final int EXCLUSIVE = 0x00000004;
- private static final int HIDDEN = 0x00000008;
- private static final int ENABLED = 0x00000010;
-
- /** Used for the icon resource ID if this item does not have an icon */
- static final int NO_ICON = 0;
-
- /**
- * Current use case is for context menu: Extra information linked to the
- * View that added this item to the context menu.
- */
- private ContextMenuInfo mMenuInfo;
-
- private static String sPrependShortcutLabel;
- private static String sEnterShortcutLabel;
- private static String sDeleteShortcutLabel;
- private static String sSpaceShortcutLabel;
-
-
- /**
- * Instantiates this menu item. The constructor
- * {@link #MenuItemData(MenuBuilder, int, int, int, CharSequence, int)} is
- * preferred due to lazy loading of the icon Drawable.
- *
- * @param menu
- * @param group Item ordering grouping control. The item will be added after
- * all other items whose order is <= this number, and before any
- * that are larger than it. This can also be used to define
- * groups of items for batch state changes. Normally use 0.
- * @param id Unique item ID. Use 0 if you do not need a unique ID.
- * @param categoryOrder The ordering for this item.
- * @param title The text to display for the item.
- */
- MenuItemImpl(MenuBuilder menu, int group, int id, int categoryOrder, int ordering,
- CharSequence title) {
-
- if (sPrependShortcutLabel == null) {
- // This is instantiated from the UI thread, so no chance of sync issues
- sPrependShortcutLabel = menu.getContext().getResources().getString(
- com.android.internal.R.string.prepend_shortcut_label);
- sEnterShortcutLabel = menu.getContext().getResources().getString(
- com.android.internal.R.string.menu_enter_shortcut_label);
- sDeleteShortcutLabel = menu.getContext().getResources().getString(
- com.android.internal.R.string.menu_delete_shortcut_label);
- sSpaceShortcutLabel = menu.getContext().getResources().getString(
- com.android.internal.R.string.menu_space_shortcut_label);
- }
-
- mItemViews = new WeakReference[MenuBuilder.NUM_TYPES];
- mMenu = menu;
- mId = id;
- mGroup = group;
- mCategoryOrder = categoryOrder;
- mOrdering = ordering;
- mTitle = title;
- }
-
- /**
- * Invokes the item by calling various listeners or callbacks.
- *
- * @return true if the invocation was handled, false otherwise
- */
- public boolean invoke() {
- if (mClickListener != null &&
- mClickListener.onMenuItemClick(this)) {
- return true;
- }
-
- MenuBuilder.Callback callback = mMenu.getCallback();
- if (callback != null &&
- callback.onMenuItemSelected(mMenu.getRootMenu(), this)) {
- return true;
- }
-
- if (mItemCallback != null) {
- mItemCallback.run();
- return true;
- }
-
- if (mIntent != null) {
- mMenu.getContext().startActivity(mIntent);
- return true;
- }
-
- return false;
- }
-
- private boolean hasItemView(int menuType) {
- return mItemViews[menuType] != null && mItemViews[menuType].get() != null;
- }
-
- public boolean isEnabled() {
- return (mFlags & ENABLED) != 0;
- }
-
- public MenuItem setEnabled(boolean enabled) {
- if (enabled) {
- mFlags |= ENABLED;
- } else {
- mFlags &= ~ENABLED;
- }
-
- for (int i = MenuBuilder.NUM_TYPES - 1; i >= 0; i--) {
- // If the item view prefers a condensed title, only set this title if there
- // is no condensed title for this item
- if (hasItemView(i)) {
- mItemViews[i].get().setEnabled(enabled);
- }
- }
-
- return this;
- }
-
- public int getGroupId() {
- return mGroup;
- }
-
- @ViewDebug.CapturedViewProperty
- public int getItemId() {
- return mId;
- }
-
- public int getOrder() {
- return mCategoryOrder;
- }
-
- public int getOrdering() {
- return mOrdering;
- }
-
- public Intent getIntent() {
- return mIntent;
- }
-
- public MenuItem setIntent(Intent intent) {
- mIntent = intent;
- return this;
- }
-
- Runnable getCallback() {
- return mItemCallback;
- }
-
- public MenuItem setCallback(Runnable callback) {
- mItemCallback = callback;
- return this;
- }
-
- public char getAlphabeticShortcut() {
- return mShortcutAlphabeticChar;
- }
-
- public MenuItem setAlphabeticShortcut(char alphaChar) {
- if (mShortcutAlphabeticChar == alphaChar) return this;
-
- mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
-
- refreshShortcutOnItemViews();
-
- return this;
- }
-
- public char getNumericShortcut() {
- return mShortcutNumericChar;
- }
-
- public MenuItem setNumericShortcut(char numericChar) {
- if (mShortcutNumericChar == numericChar) return this;
-
- mShortcutNumericChar = numericChar;
-
- refreshShortcutOnItemViews();
-
- return this;
- }
-
- public MenuItem setShortcut(char numericChar, char alphaChar) {
- mShortcutNumericChar = numericChar;
- mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
-
- refreshShortcutOnItemViews();
-
- return this;
- }
-
- /**
- * @return The active shortcut (based on QWERTY-mode of the menu).
- */
- char getShortcut() {
- return (mMenu.isQwertyMode() ? mShortcutAlphabeticChar : mShortcutNumericChar);
- }
-
- /**
- * @return The label to show for the shortcut. This includes the chording
- * key (for example 'Menu+a'). Also, any non-human readable
- * characters should be human readable (for example 'Menu+enter').
- */
- String getShortcutLabel() {
-
- char shortcut = getShortcut();
- if (shortcut == 0) {
- return "";
- }
-
- StringBuilder sb = new StringBuilder(sPrependShortcutLabel);
- switch (shortcut) {
-
- case '\n':
- sb.append(sEnterShortcutLabel);
- break;
-
- case '\b':
- sb.append(sDeleteShortcutLabel);
- break;
-
- case ' ':
- sb.append(sSpaceShortcutLabel);
- break;
-
- default:
- sb.append(shortcut);
- break;
- }
-
- return sb.toString();
- }
-
- /**
- * @return Whether this menu item should be showing shortcuts (depends on
- * whether the menu should show shortcuts and whether this item has
- * a shortcut defined)
- */
- boolean shouldShowShortcut() {
- // Show shortcuts if the menu is supposed to show shortcuts AND this item has a shortcut
- return mMenu.isShortcutsVisible() && (getShortcut() != 0);
- }
-
- /**
- * Refreshes the shortcut shown on the ItemViews. This method retrieves current
- * shortcut state (mode and shown) from the menu that contains this item.
- */
- private void refreshShortcutOnItemViews() {
- refreshShortcutOnItemViews(mMenu.isShortcutsVisible(), mMenu.isQwertyMode());
- }
-
- /**
- * Refreshes the shortcut shown on the ItemViews. This is usually called by
- * the {@link MenuBuilder} when it is refreshing the shortcuts on all item
- * views, so it passes arguments rather than each item calling a method on the menu to get
- * the same values.
- *
- * @param menuShortcutShown The menu's shortcut shown mode. In addition,
- * this method will ensure this item has a shortcut before it
- * displays the shortcut.
- * @param isQwertyMode Whether the shortcut mode is qwerty mode
- */
- void refreshShortcutOnItemViews(boolean menuShortcutShown, boolean isQwertyMode) {
- final char shortcutKey = (isQwertyMode) ? mShortcutAlphabeticChar : mShortcutNumericChar;
-
- // Show shortcuts if the menu is supposed to show shortcuts AND this item has a shortcut
- final boolean showShortcut = menuShortcutShown && (shortcutKey != 0);
-
- for (int i = MenuBuilder.NUM_TYPES - 1; i >= 0; i--) {
- if (hasItemView(i)) {
- mItemViews[i].get().setShortcut(showShortcut, shortcutKey);
- }
- }
- }
-
- public SubMenu getSubMenu() {
- return mSubMenu;
- }
-
- public boolean hasSubMenu() {
- return mSubMenu != null;
- }
-
- void setSubMenu(SubMenuBuilder subMenu) {
- if ((mMenu != null) && (mMenu instanceof SubMenu)) {
- throw new UnsupportedOperationException(
- "Attempt to add a sub-menu to a sub-menu.");
- }
-
- mSubMenu = subMenu;
-
- subMenu.setHeaderTitle(getTitle());
- }
-
- @ViewDebug.CapturedViewProperty
- public CharSequence getTitle() {
- return mTitle;
- }
-
- /**
- * Gets the title for a particular {@link ItemView}
- *
- * @param itemView The ItemView that is receiving the title
- * @return Either the title or condensed title based on what the ItemView
- * prefers
- */
- CharSequence getTitleForItemView(MenuView.ItemView itemView) {
- return ((itemView != null) && itemView.prefersCondensedTitle())
- ? getTitleCondensed()
- : getTitle();
- }
-
- public MenuItem setTitle(CharSequence title) {
- mTitle = title;
-
- for (int i = MenuBuilder.NUM_TYPES - 1; i >= 0; i--) {
- // If the item view prefers a condensed title, only set this title if there
- // is no condensed title for this item
- if (!hasItemView(i)) {
- continue;
- }
-
- ItemView itemView = mItemViews[i].get();
- if (!itemView.prefersCondensedTitle() || mTitleCondensed == null) {
- itemView.setTitle(title);
- }
- }
-
- if (mSubMenu != null) {
- mSubMenu.setHeaderTitle(title);
- }
-
- return this;
- }
-
- public MenuItem setTitle(int title) {
- return setTitle(mMenu.getContext().getString(title));
- }
-
- public CharSequence getTitleCondensed() {
- return mTitleCondensed != null ? mTitleCondensed : mTitle;
- }
-
- public MenuItem setTitleCondensed(CharSequence title) {
- mTitleCondensed = title;
-
- // Could use getTitle() in the loop below, but just cache what it would do here
- if (title == null) {
- title = mTitle;
- }
-
- for (int i = MenuBuilder.NUM_TYPES - 1; i >= 0; i--) {
- // Refresh those item views that prefer a condensed title
- if (hasItemView(i) && (mItemViews[i].get().prefersCondensedTitle())) {
- mItemViews[i].get().setTitle(title);
- }
- }
-
- return this;
- }
-
- public Drawable getIcon() {
-
- if (mIconDrawable != null) {
- return mIconDrawable;
- }
-
- if (mIconResId != NO_ICON) {
- return mMenu.getResources().getDrawable(mIconResId);
- }
-
- return null;
- }
-
- public MenuItem setIcon(Drawable icon) {
- mIconResId = NO_ICON;
- mIconDrawable = icon;
- setIconOnViews(icon);
-
- return this;
- }
-
- public MenuItem setIcon(int iconResId) {
- mIconDrawable = null;
- mIconResId = iconResId;
-
- // If we have a view, we need to push the Drawable to them
- if (haveAnyOpenedIconCapableItemViews()) {
- Drawable drawable = iconResId != NO_ICON ? mMenu.getResources().getDrawable(iconResId)
- : null;
- setIconOnViews(drawable);
- }
-
- return this;
- }
-
- private void setIconOnViews(Drawable icon) {
- for (int i = MenuBuilder.NUM_TYPES - 1; i >= 0; i--) {
- // Refresh those item views that are able to display an icon
- if (hasItemView(i) && mItemViews[i].get().showsIcon()) {
- mItemViews[i].get().setIcon(icon);
- }
- }
- }
-
- private boolean haveAnyOpenedIconCapableItemViews() {
- for (int i = MenuBuilder.NUM_TYPES - 1; i >= 0; i--) {
- if (hasItemView(i) && mItemViews[i].get().showsIcon()) {
- return true;
- }
- }
-
- return false;
- }
-
- public boolean isCheckable() {
- return (mFlags & CHECKABLE) == CHECKABLE;
- }
-
- public MenuItem setCheckable(boolean checkable) {
- final int oldFlags = mFlags;
- mFlags = (mFlags & ~CHECKABLE) | (checkable ? CHECKABLE : 0);
- if (oldFlags != mFlags) {
- for (int i = MenuBuilder.NUM_TYPES - 1; i >= 0; i--) {
- if (hasItemView(i)) {
- mItemViews[i].get().setCheckable(checkable);
- }
- }
- }
-
- return this;
- }
-
- public void setExclusiveCheckable(boolean exclusive)
- {
- mFlags = (mFlags&~EXCLUSIVE) | (exclusive ? EXCLUSIVE : 0);
- }
-
- public boolean isExclusiveCheckable() {
- return (mFlags & EXCLUSIVE) != 0;
- }
-
- public boolean isChecked() {
- return (mFlags & CHECKED) == CHECKED;
- }
-
- public MenuItem setChecked(boolean checked) {
- if ((mFlags & EXCLUSIVE) != 0) {
- // Call the method on the Menu since it knows about the others in this
- // exclusive checkable group
- mMenu.setExclusiveItemChecked(this);
- } else {
- setCheckedInt(checked);
- }
-
- return this;
- }
-
- void setCheckedInt(boolean checked) {
- final int oldFlags = mFlags;
- mFlags = (mFlags & ~CHECKED) | (checked ? CHECKED : 0);
- if (oldFlags != mFlags) {
- for (int i = MenuBuilder.NUM_TYPES - 1; i >= 0; i--) {
- if (hasItemView(i)) {
- mItemViews[i].get().setChecked(checked);
- }
- }
- }
- }
-
- public boolean isVisible() {
- return (mFlags & HIDDEN) == 0;
- }
-
- /**
- * Changes the visibility of the item. This method DOES NOT notify the
- * parent menu of a change in this item, so this should only be called from
- * methods that will eventually trigger this change. If unsure, use {@link #setVisible(boolean)}
- * instead.
- *
- * @param shown Whether to show (true) or hide (false).
- * @return Whether the item's shown state was changed
- */
- boolean setVisibleInt(boolean shown) {
- final int oldFlags = mFlags;
- mFlags = (mFlags & ~HIDDEN) | (shown ? 0 : HIDDEN);
- return oldFlags != mFlags;
- }
-
- public MenuItem setVisible(boolean shown) {
- // Try to set the shown state to the given state. If the shown state was changed
- // (i.e. the previous state isn't the same as given state), notify the parent menu that
- // the shown state has changed for this item
- if (setVisibleInt(shown)) mMenu.onItemVisibleChanged(this);
-
- return this;
- }
-
- public MenuItem setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener clickListener) {
- mClickListener = clickListener;
- return this;
- }
-
- View getItemView(int menuType, ViewGroup parent) {
- if (!hasItemView(menuType)) {
- mItemViews[menuType] = new WeakReference<ItemView>(createItemView(menuType, parent));
- }
-
- return (View) mItemViews[menuType].get();
- }
-
- /**
- * Create and initializes a menu item view that implements {@link MenuView.ItemView}.
- * @param menuType The type of menu to get a View for (must be one of
- * {@link MenuBuilder#TYPE_ICON}, {@link MenuBuilder#TYPE_EXPANDED},
- * {@link MenuBuilder#TYPE_SUB}, {@link MenuBuilder#TYPE_CONTEXT}).
- * @return The inflated {@link MenuView.ItemView} that is ready for use
- */
- private MenuView.ItemView createItemView(int menuType, ViewGroup parent) {
- // Create the MenuView
- MenuView.ItemView itemView = (MenuView.ItemView) getLayoutInflater(menuType)
- .inflate(MenuBuilder.ITEM_LAYOUT_RES_FOR_TYPE[menuType], parent, false);
- itemView.initialize(this, menuType);
- return itemView;
- }
-
- void clearItemViews() {
- for (int i = mItemViews.length - 1; i >= 0; i--) {
- mItemViews[i] = null;
- }
- }
-
- @Override
- public String toString() {
- return mTitle.toString();
- }
-
- void setMenuInfo(ContextMenuInfo menuInfo) {
- mMenuInfo = menuInfo;
- }
-
- public ContextMenuInfo getMenuInfo() {
- return mMenuInfo;
- }
-
- /**
- * Returns a LayoutInflater that is themed for the given menu type.
- *
- * @param menuType The type of menu.
- * @return A LayoutInflater.
- */
- public LayoutInflater getLayoutInflater(int menuType) {
- return mMenu.getMenuType(menuType).getInflater();
- }
-
- /**
- * @return Whether the given menu type should show icons for menu items.
- */
- public boolean shouldShowIcon(int menuType) {
- return menuType == MenuBuilder.TYPE_ICON || mMenu.getOptionalIconsVisible();
- }
-}
diff --git a/core/java/com/android/internal/view/menu/MenuView.java b/core/java/com/android/internal/view/menu/MenuView.java
deleted file mode 100644
index 5090400..0000000
--- a/core/java/com/android/internal/view/menu/MenuView.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view.menu;
-
-import com.android.internal.view.menu.MenuBuilder;
-import com.android.internal.view.menu.MenuItemImpl;
-
-import android.graphics.drawable.Drawable;
-
-/**
- * Minimal interface for a menu view. {@link #initialize(MenuBuilder, int)} must be called for the
- * menu to be functional.
- *
- * @hide
- */
-public interface MenuView {
- /**
- * Initializes the menu to the given menu. This should be called after the
- * view is inflated.
- *
- * @param menu The menu that this MenuView should display.
- * @param menuType The type of this menu, one of
- * {@link MenuBuilder#TYPE_ICON}, {@link MenuBuilder#TYPE_EXPANDED},
- * {@link MenuBuilder#TYPE_DIALOG}).
- */
- public void initialize(MenuBuilder menu, int menuType);
-
- /**
- * Forces the menu view to update its view to reflect the new state of the menu.
- *
- * @param cleared Whether the menu was cleared or just modified.
- */
- public void updateChildren(boolean cleared);
-
- /**
- * Returns the default animations to be used for this menu when entering/exiting.
- * @return A resource ID for the default animations to be used for this menu.
- */
- public int getWindowAnimations();
-
- /**
- * Minimal interface for a menu item view. {@link #initialize(MenuItemImpl, int)} must be called
- * for the item to be functional.
- */
- public interface ItemView {
- /**
- * Initializes with the provided MenuItemData. This should be called after the view is
- * inflated.
- * @param itemData The item that this ItemView should display.
- * @param menuType The type of this menu, one of
- * {@link MenuBuilder#TYPE_ICON}, {@link MenuBuilder#TYPE_EXPANDED},
- * {@link MenuBuilder#TYPE_DIALOG}).
- */
- public void initialize(MenuItemImpl itemData, int menuType);
-
- /**
- * Gets the item data that this view is displaying.
- * @return the item data, or null if there is not one
- */
- public MenuItemImpl getItemData();
-
- /**
- * Sets the title of the item view.
- * @param title The title to set.
- */
- public void setTitle(CharSequence title);
-
- /**
- * Sets the enabled state of the item view.
- * @param enabled Whether the item view should be enabled.
- */
- public void setEnabled(boolean enabled);
-
- /**
- * Displays the checkbox for the item view. This does not ensure the item view will be
- * checked, for that use {@link #setChecked}.
- * @param checkable Whether to display the checkbox or to hide it
- */
- public void setCheckable(boolean checkable);
-
- /**
- * Checks the checkbox for the item view. If the checkbox is hidden, it will NOT be
- * made visible, call {@link #setCheckable(boolean)} for that.
- * @param checked Whether the checkbox should be checked
- */
- public void setChecked(boolean checked);
-
- /**
- * Sets the shortcut for the item.
- * @param showShortcut Whether a shortcut should be shown(if false, the value of
- * shortcutKey should be ignored).
- * @param shortcutKey The shortcut key that should be shown on the ItemView.
- */
- public void setShortcut(boolean showShortcut, char shortcutKey);
-
- /**
- * Set the icon of this item view.
- * @param icon The icon of this item. null to hide the icon.
- */
- public void setIcon(Drawable icon);
-
- /**
- * Whether this item view prefers displaying the condensed title rather
- * than the normal title. If a condensed title is not available, the
- * normal title will be used.
- *
- * @return Whether this item view prefers displaying the condensed
- * title.
- */
- public boolean prefersCondensedTitle();
-
- /**
- * Whether this item view shows an icon.
- *
- * @return Whether this item view shows an icon.
- */
- public boolean showsIcon();
- }
-}
diff --git a/core/java/com/android/internal/view/menu/SubMenuBuilder.java b/core/java/com/android/internal/view/menu/SubMenuBuilder.java
deleted file mode 100644
index af1b996..0000000
--- a/core/java/com/android/internal/view/menu/SubMenuBuilder.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view.menu;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.SubMenu;
-import android.view.View;
-
-/**
- * The model for a sub menu, which is an extension of the menu. Most methods are proxied to
- * the parent menu.
- */
-public class SubMenuBuilder extends MenuBuilder implements SubMenu {
- private MenuBuilder mParentMenu;
- private MenuItemImpl mItem;
-
- public SubMenuBuilder(Context context, MenuBuilder parentMenu, MenuItemImpl item) {
- super(context);
-
- mParentMenu = parentMenu;
- mItem = item;
- }
-
- @Override
- public void setQwertyMode(boolean isQwerty) {
- mParentMenu.setQwertyMode(isQwerty);
- }
-
- @Override
- public boolean isQwertyMode() {
- return mParentMenu.isQwertyMode();
- }
-
- @Override
- public void setShortcutsVisible(boolean shortcutsVisible) {
- mParentMenu.setShortcutsVisible(shortcutsVisible);
- }
-
- @Override
- public boolean isShortcutsVisible() {
- return mParentMenu.isShortcutsVisible();
- }
-
- public Menu getParentMenu() {
- return mParentMenu;
- }
-
- public MenuItem getItem() {
- return mItem;
- }
-
- @Override
- public Callback getCallback() {
- return mParentMenu.getCallback();
- }
-
- @Override
- public void setCallback(Callback callback) {
- mParentMenu.setCallback(callback);
- }
-
- @Override
- public MenuBuilder getRootMenu() {
- return mParentMenu;
- }
-
- public SubMenu setIcon(Drawable icon) {
- mItem.setIcon(icon);
- return this;
- }
-
- public SubMenu setIcon(int iconRes) {
- mItem.setIcon(iconRes);
- return this;
- }
-
- public SubMenu setHeaderIcon(Drawable icon) {
- return (SubMenu) super.setHeaderIconInt(icon);
- }
-
- public SubMenu setHeaderIcon(int iconRes) {
- return (SubMenu) super.setHeaderIconInt(iconRes);
- }
-
- public SubMenu setHeaderTitle(CharSequence title) {
- return (SubMenu) super.setHeaderTitleInt(title);
- }
-
- public SubMenu setHeaderTitle(int titleRes) {
- return (SubMenu) super.setHeaderTitleInt(titleRes);
- }
-
- public SubMenu setHeaderView(View view) {
- return (SubMenu) super.setHeaderViewInt(view);
- }
-
-}
diff --git a/core/java/com/android/internal/view/package.html b/core/java/com/android/internal/view/package.html
deleted file mode 100644
index 783d0a1..0000000
--- a/core/java/com/android/internal/view/package.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<body>
-{@hide}
-</body>
diff --git a/core/java/com/android/internal/widget/DialogTitle.java b/core/java/com/android/internal/widget/DialogTitle.java
deleted file mode 100644
index 2eef0b6..0000000
--- a/core/java/com/android/internal/widget/DialogTitle.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.text.Layout;
-import android.util.AttributeSet;
-import android.util.TypedValue;
-import android.widget.TextView;
-
-/**
- * Used by dialogs to change the font size and number of lines to try to fit
- * the text to the available space.
- */
-public class DialogTitle extends TextView {
-
- public DialogTitle(Context context, AttributeSet attrs,
- int defStyle) {
- super(context, attrs, defStyle);
- }
-
- public DialogTitle(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public DialogTitle(Context context) {
- super(context);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
- final Layout layout = getLayout();
- if (layout != null) {
- final int lineCount = layout.getLineCount();
- if (lineCount > 0) {
- final int ellipsisCount = layout.getEllipsisCount(lineCount - 1);
- if (ellipsisCount > 0) {
- setSingleLine(false);
-
- TypedArray a = mContext.obtainStyledAttributes(
- android.R.style.TextAppearance_Medium,
- android.R.styleable.TextAppearance);
- final int textSize = a.getDimensionPixelSize(
- android.R.styleable.TextAppearance_textSize, 20);
-
- setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
- setMaxLines(2);
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
- }
- }
- }
-
-} \ No newline at end of file
diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java
deleted file mode 100644
index 44cf0ed..0000000
--- a/core/java/com/android/internal/widget/EditableInputConnection.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.internal.widget;
-
-import android.os.Bundle;
-import android.text.Editable;
-import android.text.method.KeyListener;
-import android.util.Log;
-import android.view.inputmethod.BaseInputConnection;
-import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.ExtractedText;
-import android.view.inputmethod.ExtractedTextRequest;
-import android.widget.TextView;
-
-public class EditableInputConnection extends BaseInputConnection {
- private static final boolean DEBUG = false;
- private static final String TAG = "EditableInputConnection";
-
- private final TextView mTextView;
-
- public EditableInputConnection(TextView textview) {
- super(textview, false);
- mTextView = textview;
- }
-
- public Editable getEditable() {
- TextView tv = mTextView;
- if (tv != null) {
- return tv.getEditableText();
- }
- return null;
- }
-
- public boolean beginBatchEdit() {
- mTextView.beginBatchEdit();
- return true;
- }
-
- public boolean endBatchEdit() {
- mTextView.endBatchEdit();
- return true;
- }
-
- public boolean clearMetaKeyStates(int states) {
- final Editable content = getEditable();
- if (content == null) return false;
- KeyListener kl = mTextView.getKeyListener();
- if (kl != null) kl.clearMetaKeyState(mTextView, content, states);
- return true;
- }
-
- public boolean commitCompletion(CompletionInfo text) {
- if (DEBUG) Log.v(TAG, "commitCompletion " + text);
- mTextView.beginBatchEdit();
- mTextView.onCommitCompletion(text);
- mTextView.endBatchEdit();
- return true;
- }
-
- public boolean performContextMenuAction(int id) {
- if (DEBUG) Log.v(TAG, "performContextMenuAction " + id);
- mTextView.beginBatchEdit();
- mTextView.onTextContextMenuItem(id);
- mTextView.endBatchEdit();
- return true;
- }
-
- public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
- if (mTextView != null) {
- ExtractedText et = new ExtractedText();
- if (mTextView.extractText(request, et)) {
- if ((flags&GET_EXTRACTED_TEXT_MONITOR) != 0) {
- mTextView.setExtracting(request);
- }
- return et;
- }
- }
- return null;
- }
-
- public boolean performPrivateCommand(String action, Bundle data) {
- mTextView.onPrivateIMECommand(action, data);
- return true;
- }
-
- @Override
- public boolean commitText(CharSequence text, int newCursorPosition) {
- if (mTextView == null) {
- return super.commitText(text, newCursorPosition);
- }
-
- CharSequence errorBefore = mTextView.getError();
- boolean success = super.commitText(text, newCursorPosition);
- CharSequence errorAfter = mTextView.getError();
-
- if (errorAfter != null && errorBefore == errorAfter) {
- mTextView.setError(null, null);
- }
-
- return success;
- }
-}
diff --git a/core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java b/core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java
deleted file mode 100644
index b2001cb..0000000
--- a/core/java/com/android/internal/widget/LinearLayoutWithDefaultTouchRecepient.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.MotionEvent;
-import android.widget.LinearLayout;
-
-
-/**
- * Like a normal linear layout, but supports dispatching all otherwise unhandled
- * touch events to a particular descendant. This is for the unlock screen, so
- * that a wider range of touch events than just the lock pattern widget can kick
- * off a lock pattern if the finger is eventually dragged into the bounds of the
- * lock pattern view.
- */
-public class LinearLayoutWithDefaultTouchRecepient extends LinearLayout {
-
- private final Rect mTempRect = new Rect();
- private View mDefaultTouchRecepient;
-
- public LinearLayoutWithDefaultTouchRecepient(Context context) {
- super(context);
- }
-
- public LinearLayoutWithDefaultTouchRecepient(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public void setDefaultTouchRecepient(View defaultTouchRecepient) {
- mDefaultTouchRecepient = defaultTouchRecepient;
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- if (mDefaultTouchRecepient == null) {
- return super.dispatchTouchEvent(ev);
- }
-
- if (super.dispatchTouchEvent(ev)) {
- return true;
- }
- mTempRect.set(0, 0, 0, 0);
- offsetRectIntoDescendantCoords(mDefaultTouchRecepient, mTempRect);
- ev.setLocation(ev.getX() + mTempRect.left, ev.getY() + mTempRect.top);
- return mDefaultTouchRecepient.dispatchTouchEvent(ev);
- }
-
-}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
deleted file mode 100644
index c8b3ad4..0000000
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import android.content.ContentResolver;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.security.MessageDigest;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.google.android.collect.Lists;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Utilities for the lock patten and its settings.
- */
-public class LockPatternUtils {
-
- private static final String TAG = "LockPatternUtils";
-
- private static final String LOCK_PATTERN_FILE = "/system/gesture.key";
-
- /**
- * The maximum number of incorrect attempts before the user is prevented
- * from trying again for {@link #FAILED_ATTEMPT_TIMEOUT_MS}.
- */
- public static final int FAILED_ATTEMPTS_BEFORE_TIMEOUT = 5;
-
- /**
- * The number of incorrect attempts before which we fall back on an alternative
- * method of verifying the user, and resetting their lock pattern.
- */
- public static final int FAILED_ATTEMPTS_BEFORE_RESET = 20;
-
- /**
- * How long the user is prevented from trying again after entering the
- * wrong pattern too many times.
- */
- public static final long FAILED_ATTEMPT_TIMEOUT_MS = 30000L;
-
- /**
- * The interval of the countdown for showing progress of the lockout.
- */
- public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L;
-
- /**
- * The minimum number of dots in a valid pattern.
- */
- public static final int MIN_LOCK_PATTERN_SIZE = 4;
-
- /**
- * The minimum number of dots the user must include in a wrong pattern
- * attempt for it to be counted against the counts that affect
- * {@link #FAILED_ATTEMPTS_BEFORE_TIMEOUT} and {@link #FAILED_ATTEMPTS_BEFORE_RESET}
- */
- public static final int MIN_PATTERN_REGISTER_FAIL = 3;
-
- private final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
- private final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
-
- private final ContentResolver mContentResolver;
-
- private static String sLockPatternFilename;
-
- /**
- * @param contentResolver Used to look up and save settings.
- */
- public LockPatternUtils(ContentResolver contentResolver) {
- mContentResolver = contentResolver;
- // Initialize the location of gesture lock file
- if (sLockPatternFilename == null) {
- sLockPatternFilename = android.os.Environment.getDataDirectory()
- .getAbsolutePath() + LOCK_PATTERN_FILE;
- }
- }
-
- /**
- * Check to see if a pattern matches the saved pattern. If no pattern exists,
- * always returns true.
- * @param pattern The pattern to check.
- * @return Whether the pattern matchees the stored one.
- */
- public boolean checkPattern(List<LockPatternView.Cell> pattern) {
- try {
- // Read all the bytes from the file
- RandomAccessFile raf = new RandomAccessFile(sLockPatternFilename, "r");
- final byte[] stored = new byte[(int) raf.length()];
- int got = raf.read(stored, 0, stored.length);
- raf.close();
- if (got <= 0) {
- return true;
- }
- // Compare the hash from the file with the entered pattern's hash
- return Arrays.equals(stored, LockPatternUtils.patternToHash(pattern));
- } catch (FileNotFoundException fnfe) {
- return true;
- } catch (IOException ioe) {
- return true;
- }
- }
-
- /**
- * Check to see if the user has stored a lock pattern.
- * @return Whether a saved pattern exists.
- */
- public boolean savedPatternExists() {
- try {
- // Check if we can read a byte from the file
- RandomAccessFile raf = new RandomAccessFile(sLockPatternFilename, "r");
- byte first = raf.readByte();
- raf.close();
- return true;
- } catch (FileNotFoundException fnfe) {
- return false;
- } catch (IOException ioe) {
- return false;
- }
- }
-
- /**
- * Save a lock pattern.
- * @param pattern The new pattern to save.
- */
- public void saveLockPattern(List<LockPatternView.Cell> pattern) {
- // Compute the hash
- final byte[] hash = LockPatternUtils.patternToHash(pattern);
- try {
- // Write the hash to file
- RandomAccessFile raf = new RandomAccessFile(sLockPatternFilename, "rw");
- // Truncate the file if pattern is null, to clear the lock
- if (pattern == null) {
- raf.setLength(0);
- } else {
- raf.write(hash, 0, hash.length);
- }
- raf.close();
- } catch (FileNotFoundException fnfe) {
- // Cant do much, unless we want to fail over to using the settings provider
- Log.e(TAG, "Unable to save lock pattern to " + sLockPatternFilename);
- } catch (IOException ioe) {
- // Cant do much
- Log.e(TAG, "Unable to save lock pattern to " + sLockPatternFilename);
- }
- }
-
- /**
- * Deserialize a pattern.
- * @param string The pattern serialized with {@link #patternToString}
- * @return The pattern.
- */
- public static List<LockPatternView.Cell> stringToPattern(String string) {
- List<LockPatternView.Cell> result = Lists.newArrayList();
-
- final byte[] bytes = string.getBytes();
- for (int i = 0; i < bytes.length; i++) {
- byte b = bytes[i];
- result.add(LockPatternView.Cell.of(b / 3, b % 3));
- }
- return result;
- }
-
- /**
- * Serialize a pattern.
- * @param pattern The pattern.
- * @return The pattern in string form.
- */
- public static String patternToString(List<LockPatternView.Cell> pattern) {
- if (pattern == null) {
- return "";
- }
- final int patternSize = pattern.size();
-
- byte[] res = new byte[patternSize];
- for (int i = 0; i < patternSize; i++) {
- LockPatternView.Cell cell = pattern.get(i);
- res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
- }
- return new String(res);
- }
-
- /*
- * Generate an SHA-1 hash for the pattern. Not the most secure, but it is
- * at least a second level of protection. First level is that the file
- * is in a location only readable by the system process.
- * @param pattern the gesture pattern.
- * @return the hash of the pattern in a byte array.
- */
- static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
- if (pattern == null) {
- return null;
- }
-
- final int patternSize = pattern.size();
- byte[] res = new byte[patternSize];
- for (int i = 0; i < patternSize; i++) {
- LockPatternView.Cell cell = pattern.get(i);
- res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
- }
- try {
- MessageDigest md = MessageDigest.getInstance("SHA-1");
- byte[] hash = md.digest(res);
- return hash;
- } catch (NoSuchAlgorithmException nsa) {
- return res;
- }
- }
-
- /**
- * @return Whether the lock pattern is enabled.
- */
- public boolean isLockPatternEnabled() {
- return getBoolean(Settings.System.LOCK_PATTERN_ENABLED);
- }
-
- /**
- * Set whether the lock pattern is enabled.
- */
- public void setLockPatternEnabled(boolean enabled) {
- setBoolean(Settings.System.LOCK_PATTERN_ENABLED, enabled);
- }
-
- /**
- * @return Whether the visible pattern is enabled.
- */
- public boolean isVisiblePatternEnabled() {
- return getBoolean(Settings.System.LOCK_PATTERN_VISIBLE);
- }
-
- /**
- * Set whether the visible pattern is enabled.
- */
- public void setVisiblePatternEnabled(boolean enabled) {
- setBoolean(Settings.System.LOCK_PATTERN_VISIBLE, enabled);
- }
-
- /**
- * @return Whether tactile feedback for the pattern is enabled.
- */
- public boolean isTactileFeedbackEnabled() {
- return getBoolean(Settings.System.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED);
- }
-
- /**
- * Set whether tactile feedback for the pattern is enabled.
- */
- public void setTactileFeedbackEnabled(boolean enabled) {
- setBoolean(Settings.System.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, enabled);
- }
-
- /**
- * Set and store the lockout deadline, meaning the user can't attempt his/her unlock
- * pattern until the deadline has passed.
- * @return the chosen deadline.
- */
- public long setLockoutAttemptDeadline() {
- final long deadline = SystemClock.elapsedRealtime() + FAILED_ATTEMPT_TIMEOUT_MS;
- setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline);
- return deadline;
- }
-
- /**
- * @return The elapsed time in millis in the future when the user is allowed to
- * attempt to enter his/her lock pattern, or 0 if the user is welcome to
- * enter a pattern.
- */
- public long getLockoutAttemptDeadline() {
- final long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L);
- final long now = SystemClock.elapsedRealtime();
- if (deadline < now || deadline > (now + FAILED_ATTEMPT_TIMEOUT_MS)) {
- return 0L;
- }
- return deadline;
- }
-
- /**
- * @return Whether the user is permanently locked out until they verify their
- * credentials. Occurs after {@link #FAILED_ATTEMPTS_BEFORE_RESET} failed
- * attempts.
- */
- public boolean isPermanentlyLocked() {
- return getBoolean(LOCKOUT_PERMANENT_KEY);
- }
-
- /**
- * Set the state of whether the device is permanently locked, meaning the user
- * must authenticate via other means. If false, that means the user has gone
- * out of permanent lock, so the existing (forgotten) lock pattern needs to
- * be cleared.
- * @param locked Whether the user is permanently locked out until they verify their
- * credentials. Occurs after {@link #FAILED_ATTEMPTS_BEFORE_RESET} failed
- * attempts.
- */
- public void setPermanentlyLocked(boolean locked) {
- setBoolean(LOCKOUT_PERMANENT_KEY, locked);
-
- if (!locked) {
- setLockPatternEnabled(false);
- saveLockPattern(null);
- }
- }
-
- /**
- * @return A formatted string of the next alarm (for showing on the lock screen),
- * or null if there is no next alarm.
- */
- public String getNextAlarm() {
- String nextAlarm = Settings.System.getString(mContentResolver,
- Settings.System.NEXT_ALARM_FORMATTED);
- if (nextAlarm == null || TextUtils.isEmpty(nextAlarm)) {
- return null;
- }
- return nextAlarm;
- }
-
- private boolean getBoolean(String systemSettingKey) {
- return 1 ==
- android.provider.Settings.System.getInt(
- mContentResolver,
- systemSettingKey, 0);
- }
-
- private void setBoolean(String systemSettingKey, boolean enabled) {
- android.provider.Settings.System.putInt(
- mContentResolver,
- systemSettingKey,
- enabled ? 1 : 0);
- }
-
- private long getLong(String systemSettingKey, long def) {
- return android.provider.Settings.System.getLong(mContentResolver, systemSettingKey, def);
- }
-
- private void setLong(String systemSettingKey, long value) {
- android.provider.Settings.System.putLong(mContentResolver, systemSettingKey, value);
- }
-
-
-}
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
deleted file mode 100644
index 7f99ac8..0000000
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ /dev/null
@@ -1,1024 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-
-import com.android.internal.R;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Rect;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.SystemClock;
-import android.os.Debug;
-import android.os.Vibrator;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.WindowManager;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Displays and detects the user's unlock attempt, which is a drag of a finger
- * across 9 regions of the screen.
- *
- * Is also capable of displaying a static pattern in "in progress", "wrong" or
- * "correct" states.
- */
-public class LockPatternView extends View {
- // Vibrator pattern for creating a tactile bump
- private static final long[] VIBE_PATTERN = {0, 1, 40, 41};
-
- private static final boolean PROFILE_DRAWING = false;
- private boolean mDrawingProfilingStarted = false;
-
- private Paint mPaint = new Paint();
- private Paint mPathPaint = new Paint();
-
- // TODO: make this common with PhoneWindow
- static final int STATUS_BAR_HEIGHT = 25;
-
- /**
- * How many milliseconds we spend animating each circle of a lock pattern
- * if the animating mode is set. The entire animation should take this
- * constant * the length of the pattern to complete.
- */
- private static final int MILLIS_PER_CIRCLE_ANIMATING = 700;
-
- private OnPatternListener mOnPatternListener;
- private ArrayList<Cell> mPattern = new ArrayList<Cell>(9);
-
- /**
- * Lookup table for the circles of the pattern we are currently drawing.
- * This will be the cells of the complete pattern unless we are animating,
- * in which case we use this to hold the cells we are drawing for the in
- * progress animation.
- */
- private boolean[][] mPatternDrawLookup = new boolean[3][3];
-
- /**
- * the in progress point:
- * - during interaction: where the user's finger is
- * - during animation: the current tip of the animating line
- */
- private float mInProgressX = -1;
- private float mInProgressY = -1;
-
- private long mAnimatingPeriodStart;
-
- private DisplayMode mPatternDisplayMode = DisplayMode.Correct;
- private boolean mInputEnabled = true;
- private boolean mInStealthMode = false;
- private boolean mTactileFeedbackEnabled = true;
- private boolean mPatternInProgress = false;
-
- private float mDiameterFactor = 0.5f;
- private float mHitFactor = 0.6f;
-
- private float mSquareWidth;
- private float mSquareHeight;
-
- private Bitmap mBitmapBtnDefault;
- private Bitmap mBitmapBtnTouched;
- private Bitmap mBitmapCircleDefault;
- private Bitmap mBitmapCircleGreen;
- private Bitmap mBitmapCircleRed;
-
- private Bitmap mBitmapArrowGreenUp;
- private Bitmap mBitmapArrowRedUp;
-
- private final Path mCurrentPath = new Path();
- private final Rect mInvalidate = new Rect();
-
- private int mBitmapWidth;
- private int mBitmapHeight;
-
-
- private Vibrator vibe; // Vibrator for creating tactile feedback
-
- /**
- * Represents a cell in the 3 X 3 matrix of the unlock pattern view.
- */
- public static class Cell {
- int row;
- int column;
-
- // keep # objects limited to 9
- static Cell[][] sCells = new Cell[3][3];
- static {
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- sCells[i][j] = new Cell(i, j);
- }
- }
- }
-
- /**
- * @param row The row of the cell.
- * @param column The column of the cell.
- */
- private Cell(int row, int column) {
- checkRange(row, column);
- this.row = row;
- this.column = column;
- }
-
- public int getRow() {
- return row;
- }
-
- public int getColumn() {
- return column;
- }
-
- /**
- * @param row The row of the cell.
- * @param column The column of the cell.
- */
- public static synchronized Cell of(int row, int column) {
- checkRange(row, column);
- return sCells[row][column];
- }
-
- private static void checkRange(int row, int column) {
- if (row < 0 || row > 2) {
- throw new IllegalArgumentException("row must be in range 0-2");
- }
- if (column < 0 || column > 2) {
- throw new IllegalArgumentException("column must be in range 0-2");
- }
- }
-
- public String toString() {
- return "(row=" + row + ",clmn=" + column + ")";
- }
- }
-
- /**
- * How to display the current pattern.
- */
- public enum DisplayMode {
-
- /**
- * The pattern drawn is correct (i.e draw it in a friendly color)
- */
- Correct,
-
- /**
- * Animate the pattern (for demo, and help).
- */
- Animate,
-
- /**
- * The pattern is wrong (i.e draw a foreboding color)
- */
- Wrong
- }
-
- /**
- * The call back interface for detecting patterns entered by the user.
- */
- public static interface OnPatternListener {
-
- /**
- * A new pattern has begun.
- */
- void onPatternStart();
-
- /**
- * The pattern was cleared.
- */
- void onPatternCleared();
-
- /**
- * A pattern was detected from the user.
- * @param pattern The pattern.
- */
- void onPatternDetected(List<Cell> pattern);
- }
-
- public LockPatternView(Context context) {
- this(context, null);
- }
-
- public LockPatternView(Context context, AttributeSet attrs) {
- super(context, attrs);
- vibe = new Vibrator();
-
- setClickable(true);
-
- mPathPaint.setAntiAlias(true);
- mPathPaint.setDither(true);
- mPathPaint.setColor(Color.WHITE); // TODO this should be from the style
- mPathPaint.setAlpha(128);
- mPathPaint.setStyle(Paint.Style.STROKE);
- mPathPaint.setStrokeJoin(Paint.Join.ROUND);
- mPathPaint.setStrokeCap(Paint.Cap.ROUND);
-
- // lot's of bitmaps!
- mBitmapBtnDefault = getBitmapFor(R.drawable.btn_code_lock_default);
- mBitmapBtnTouched = getBitmapFor(R.drawable.btn_code_lock_touched);
- mBitmapCircleDefault = getBitmapFor(R.drawable.indicator_code_lock_point_area_default);
- mBitmapCircleGreen = getBitmapFor(R.drawable.indicator_code_lock_point_area_green);
- mBitmapCircleRed = getBitmapFor(R.drawable.indicator_code_lock_point_area_red);
-
- mBitmapArrowGreenUp = getBitmapFor(R.drawable.indicator_code_lock_drag_direction_green_up);
- mBitmapArrowRedUp = getBitmapFor(R.drawable.indicator_code_lock_drag_direction_red_up);
-
- // we assume all bitmaps have the same size
- mBitmapWidth = mBitmapBtnDefault.getWidth();
- mBitmapHeight = mBitmapBtnDefault.getHeight();
- }
-
- private Bitmap getBitmapFor(int resId) {
- return BitmapFactory.decodeResource(getContext().getResources(), resId);
- }
-
- /**
- * @return Whether the view is in stealth mode.
- */
- public boolean isInStealthMode() {
- return mInStealthMode;
- }
-
- /**
- * @return Whether the view has tactile feedback enabled.
- */
- public boolean isTactileFeedbackEnabled() {
- return mTactileFeedbackEnabled;
- }
-
- /**
- * Set whether the view is in stealth mode. If true, there will be no
- * visible feedback as the user enters the pattern.
- *
- * @param inStealthMode Whether in stealth mode.
- */
- public void setInStealthMode(boolean inStealthMode) {
- mInStealthMode = inStealthMode;
- }
-
- /**
- * Set whether the view will use tactile feedback. If true, there will be
- * tactile feedback as the user enters the pattern.
- *
- * @param tactileFeedbackEnabled Whether tactile feedback is enabled
- */
- public void setTactileFeedbackEnabled(boolean tactileFeedbackEnabled) {
- mTactileFeedbackEnabled = tactileFeedbackEnabled;
- }
-
- /**
- * Set the call back for pattern detection.
- * @param onPatternListener The call back.
- */
- public void setOnPatternListener(
- OnPatternListener onPatternListener) {
- mOnPatternListener = onPatternListener;
- }
-
- /**
- * Set the pattern explicitely (rather than waiting for the user to input
- * a pattern).
- * @param displayMode How to display the pattern.
- * @param pattern The pattern.
- */
- public void setPattern(DisplayMode displayMode, List<Cell> pattern) {
- mPattern.clear();
- mPattern.addAll(pattern);
- clearPatternDrawLookup();
- for (Cell cell : pattern) {
- mPatternDrawLookup[cell.getRow()][cell.getColumn()] = true;
- }
-
- setDisplayMode(displayMode);
- }
-
- /**
- * Set the display mode of the current pattern. This can be useful, for
- * instance, after detecting a pattern to tell this view whether change the
- * in progress result to correct or wrong.
- * @param displayMode The display mode.
- */
- public void setDisplayMode(DisplayMode displayMode) {
- mPatternDisplayMode = displayMode;
- if (displayMode == DisplayMode.Animate) {
- if (mPattern.size() == 0) {
- throw new IllegalStateException("you must have a pattern to "
- + "animate if you want to set the display mode to animate");
- }
- mAnimatingPeriodStart = SystemClock.elapsedRealtime();
- final Cell first = mPattern.get(0);
- mInProgressX = getCenterXForColumn(first.getColumn());
- mInProgressY = getCenterYForRow(first.getRow());
- clearPatternDrawLookup();
- }
- invalidate();
- }
-
- /**
- * Clear the pattern.
- */
- public void clearPattern() {
- resetPattern();
- }
-
- /**
- * Reset all pattern state.
- */
- private void resetPattern() {
- mPattern.clear();
- clearPatternDrawLookup();
- mPatternDisplayMode = DisplayMode.Correct;
- invalidate();
- }
-
- /**
- * Clear the pattern lookup table.
- */
- private void clearPatternDrawLookup() {
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- mPatternDrawLookup[i][j] = false;
- }
- }
- }
-
- /**
- * Disable input (for instance when displaying a message that will
- * timeout so user doesn't get view into messy state).
- */
- public void disableInput() {
- mInputEnabled = false;
- }
-
- /**
- * Enable input.
- */
- public void enableInput() {
- mInputEnabled = true;
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- final int width = w - mPaddingLeft - mPaddingRight;
- mSquareWidth = width / 3.0f;
-
- final int height = h - mPaddingTop - mPaddingBottom;
- mSquareHeight = height / 3.0f;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final WindowManager wm = (WindowManager) getContext()
- .getSystemService(Context.WINDOW_SERVICE);
- final int width = wm.getDefaultDisplay().getWidth();
- final int height = wm.getDefaultDisplay().getHeight();
- int squareSide = Math.min(width, height);
-
- // if in landscape...
- if (width > height) {
- squareSide -= STATUS_BAR_HEIGHT;
- }
-
- setMeasuredDimension(squareSide, squareSide);
- }
-
- /**
- * Determines whether the point x, y will add a new point to the current
- * pattern (in addition to finding the cell, also makes heuristic choices
- * such as filling in gaps based on current pattern).
- * @param x The x coordinate.
- * @param y The y coordinate.
- */
- private Cell detectAndAddHit(float x, float y) {
- final Cell cell = checkForNewHit(x, y);
- if (cell != null) {
-
- // check for gaps in existing pattern
- Cell fillInGapCell = null;
- final ArrayList<Cell> pattern = mPattern;
- if (!pattern.isEmpty()) {
- final Cell lastCell = pattern.get(pattern.size() - 1);
- int dRow = cell.row - lastCell.row;
- int dColumn = cell.column - lastCell.column;
-
- int fillInRow = lastCell.row;
- int fillInColumn = lastCell.column;
-
- if (Math.abs(dRow) == 2 && Math.abs(dColumn) != 1) {
- fillInRow = lastCell.row + ((dRow > 0) ? 1 : -1);
- }
-
- if (Math.abs(dColumn) == 2 && Math.abs(dRow) != 1) {
- fillInColumn = lastCell.column + ((dColumn > 0) ? 1 : -1);
- }
-
- fillInGapCell = Cell.of(fillInRow, fillInColumn);
- }
-
- if (fillInGapCell != null &&
- !mPatternDrawLookup[fillInGapCell.row][fillInGapCell.column]) {
- addCellToPattern(fillInGapCell);
- }
- addCellToPattern(cell);
- if (mTactileFeedbackEnabled){
- vibe.vibrate(VIBE_PATTERN, -1); // Generate tactile feedback
- }
- return cell;
- }
- return null;
- }
-
- private void addCellToPattern(Cell newCell) {
- mPatternDrawLookup[newCell.getRow()][newCell.getColumn()] = true;
- mPattern.add(newCell);
- }
-
- // helper method to find which cell a point maps to
- private Cell checkForNewHit(float x, float y) {
-
- final int rowHit = getRowHit(y);
- if (rowHit < 0) {
- return null;
- }
- final int columnHit = getColumnHit(x);
- if (columnHit < 0) {
- return null;
- }
-
- if (mPatternDrawLookup[rowHit][columnHit]) {
- return null;
- }
- return Cell.of(rowHit, columnHit);
- }
-
- /**
- * Helper method to find the row that y falls into.
- * @param y The y coordinate
- * @return The row that y falls in, or -1 if it falls in no row.
- */
- private int getRowHit(float y) {
-
- final float squareHeight = mSquareHeight;
- float hitSize = squareHeight * mHitFactor;
-
- float offset = mPaddingTop + (squareHeight - hitSize) / 2f;
- for (int i = 0; i < 3; i++) {
-
- final float hitTop = offset + squareHeight * i;
- if (y >= hitTop && y <= hitTop + hitSize) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Helper method to find the column x fallis into.
- * @param x The x coordinate.
- * @return The column that x falls in, or -1 if it falls in no column.
- */
- private int getColumnHit(float x) {
- final float squareWidth = mSquareWidth;
- float hitSize = squareWidth * mHitFactor;
-
- float offset = mPaddingLeft + (squareWidth - hitSize) / 2f;
- for (int i = 0; i < 3; i++) {
-
- final float hitLeft = offset + squareWidth * i;
- if (x >= hitLeft && x <= hitLeft + hitSize) {
- return i;
- }
- }
- return -1;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent motionEvent) {
- if (!mInputEnabled || !isEnabled()) {
- return false;
- }
-
- final float x = motionEvent.getX();
- final float y = motionEvent.getY();
- Cell hitCell;
- switch(motionEvent.getAction()) {
- case MotionEvent.ACTION_DOWN:
- resetPattern();
- hitCell = detectAndAddHit(x, y);
- if (hitCell != null && mOnPatternListener != null) {
- mPatternInProgress = true;
- mPatternDisplayMode = DisplayMode.Correct;
- mOnPatternListener.onPatternStart();
- } else if (mOnPatternListener != null) {
- mPatternInProgress = false;
- mOnPatternListener.onPatternCleared();
- }
- if (hitCell != null) {
- final float startX = getCenterXForColumn(hitCell.column);
- final float startY = getCenterYForRow(hitCell.row);
-
- final float widthOffset = mSquareWidth / 2f;
- final float heightOffset = mSquareHeight / 2f;
-
- invalidate((int) (startX - widthOffset), (int) (startY - heightOffset),
- (int) (startX + widthOffset), (int) (startY + heightOffset));
- }
- mInProgressX = x;
- mInProgressY = y;
- if (PROFILE_DRAWING) {
- if (!mDrawingProfilingStarted) {
- Debug.startMethodTracing("LockPatternDrawing");
- mDrawingProfilingStarted = true;
- }
- }
- return true;
- case MotionEvent.ACTION_UP:
- // report pattern detected
- if (!mPattern.isEmpty() && mOnPatternListener != null) {
- mPatternInProgress = false;
- mOnPatternListener.onPatternDetected(mPattern);
- invalidate();
- }
- if (PROFILE_DRAWING) {
- if (mDrawingProfilingStarted) {
- Debug.stopMethodTracing();
- mDrawingProfilingStarted = false;
- }
- }
- return true;
- case MotionEvent.ACTION_MOVE:
- final int patternSizePreHitDetect = mPattern.size();
- hitCell = detectAndAddHit(x, y);
- final int patternSize = mPattern.size();
- if (hitCell != null && (mOnPatternListener != null) && (patternSize == 1)) {
- mPatternInProgress = true;
- mOnPatternListener.onPatternStart();
- }
- // note current x and y for rubber banding of in progress
- // patterns
- final float dx = Math.abs(x - mInProgressX);
- final float dy = Math.abs(y - mInProgressY);
- if (dx + dy > mSquareWidth * 0.01f) {
- float oldX = mInProgressX;
- float oldY = mInProgressY;
-
- mInProgressX = x;
- mInProgressY = y;
-
- if (mPatternInProgress) {
- final ArrayList<Cell> pattern = mPattern;
- final float radius = mSquareWidth * mDiameterFactor * 0.5f;
-
- Cell cell = pattern.get(patternSize - 1);
-
- float startX = getCenterXForColumn(cell.column);
- float startY = getCenterYForRow(cell.row);
-
- float left;
- float top;
- float right;
- float bottom;
-
- final Rect invalidateRect = mInvalidate;
-
- if (startX < x) {
- left = startX;
- right = x;
- } else {
- left = x;
- right = startX;
- }
-
- if (startY < y) {
- top = startY;
- bottom = y;
- } else {
- top = y;
- bottom = startY;
- }
-
- // Invalidate between the pattern's last cell and the current location
- invalidateRect.set((int) (left - radius), (int) (top - radius),
- (int) (right + radius), (int) (bottom + radius));
-
- if (startX < oldX) {
- left = startX;
- right = oldX;
- } else {
- left = oldX;
- right = startX;
- }
-
- if (startY < oldY) {
- top = startY;
- bottom = oldY;
- } else {
- top = oldY;
- bottom = startY;
- }
-
- // Invalidate between the pattern's last cell and the previous location
- invalidateRect.union((int) (left - radius), (int) (top - radius),
- (int) (right + radius), (int) (bottom + radius));
-
- // Invalidate between the pattern's new cell and the pattern's previous cell
- if (hitCell != null) {
- startX = getCenterXForColumn(hitCell.column);
- startY = getCenterYForRow(hitCell.row);
-
- if (patternSize >= 2) {
- // (re-using hitcell for old cell)
- hitCell = pattern.get(patternSize - 1 - (patternSize - patternSizePreHitDetect));
- oldX = getCenterXForColumn(hitCell.column);
- oldY = getCenterYForRow(hitCell.row);
-
- if (startX < oldX) {
- left = startX;
- right = oldX;
- } else {
- left = oldX;
- right = startX;
- }
-
- if (startY < oldY) {
- top = startY;
- bottom = oldY;
- } else {
- top = oldY;
- bottom = startY;
- }
- } else {
- left = right = startX;
- top = bottom = startY;
- }
-
- final float widthOffset = mSquareWidth / 2f;
- final float heightOffset = mSquareHeight / 2f;
-
- invalidateRect.set((int) (left - widthOffset),
- (int) (top - heightOffset), (int) (right + widthOffset),
- (int) (bottom + heightOffset));
- }
-
- invalidate(invalidateRect);
- } else {
- invalidate();
- }
- }
- return true;
- case MotionEvent.ACTION_CANCEL:
- resetPattern();
- if (mOnPatternListener != null) {
- mPatternInProgress = false;
- mOnPatternListener.onPatternCleared();
- }
- if (PROFILE_DRAWING) {
- if (mDrawingProfilingStarted) {
- Debug.stopMethodTracing();
- mDrawingProfilingStarted = false;
- }
- }
- return true;
- }
- return false;
- }
-
- private float getCenterXForColumn(int column) {
- return mPaddingLeft + column * mSquareWidth + mSquareWidth / 2f;
- }
-
- private float getCenterYForRow(int row) {
- return mPaddingTop + row * mSquareHeight + mSquareHeight / 2f;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- final ArrayList<Cell> pattern = mPattern;
- final int count = pattern.size();
- final boolean[][] drawLookup = mPatternDrawLookup;
-
- if (mPatternDisplayMode == DisplayMode.Animate) {
-
- // figure out which circles to draw
-
- // + 1 so we pause on complete pattern
- final int oneCycle = (count + 1) * MILLIS_PER_CIRCLE_ANIMATING;
- final int spotInCycle = (int) (SystemClock.elapsedRealtime() -
- mAnimatingPeriodStart) % oneCycle;
- final int numCircles = spotInCycle / MILLIS_PER_CIRCLE_ANIMATING;
-
- clearPatternDrawLookup();
- for (int i = 0; i < numCircles; i++) {
- final Cell cell = pattern.get(i);
- drawLookup[cell.getRow()][cell.getColumn()] = true;
- }
-
- // figure out in progress portion of ghosting line
-
- final boolean needToUpdateInProgressPoint = numCircles > 0
- && numCircles < count;
-
- if (needToUpdateInProgressPoint) {
- final float percentageOfNextCircle =
- ((float) (spotInCycle % MILLIS_PER_CIRCLE_ANIMATING)) /
- MILLIS_PER_CIRCLE_ANIMATING;
-
- final Cell currentCell = pattern.get(numCircles - 1);
- final float centerX = getCenterXForColumn(currentCell.column);
- final float centerY = getCenterYForRow(currentCell.row);
-
- final Cell nextCell = pattern.get(numCircles);
- final float dx = percentageOfNextCircle *
- (getCenterXForColumn(nextCell.column) - centerX);
- final float dy = percentageOfNextCircle *
- (getCenterYForRow(nextCell.row) - centerY);
- mInProgressX = centerX + dx;
- mInProgressY = centerY + dy;
- }
- // TODO: Infinite loop here...
- invalidate();
- }
-
- final float squareWidth = mSquareWidth;
- final float squareHeight = mSquareHeight;
-
- float radius = (squareWidth * mDiameterFactor * 0.5f);
- mPathPaint.setStrokeWidth(radius);
-
- final Path currentPath = mCurrentPath;
- currentPath.rewind();
-
- // TODO: the path should be created and cached every time we hit-detect a cell
- // only the last segment of the path should be computed here
- // draw the path of the pattern (unless the user is in progress, and
- // we are in stealth mode)
- final boolean drawPath = (!mInStealthMode || mPatternDisplayMode == DisplayMode.Wrong);
- if (drawPath) {
- boolean anyCircles = false;
- for (int i = 0; i < count; i++) {
- Cell cell = pattern.get(i);
-
- // only draw the part of the pattern stored in
- // the lookup table (this is only different in the case
- // of animation).
- if (!drawLookup[cell.row][cell.column]) {
- break;
- }
- anyCircles = true;
-
- float centerX = getCenterXForColumn(cell.column);
- float centerY = getCenterYForRow(cell.row);
- if (i == 0) {
- currentPath.moveTo(centerX, centerY);
- } else {
- currentPath.lineTo(centerX, centerY);
- }
- }
-
- // add last in progress section
- if ((mPatternInProgress || mPatternDisplayMode == DisplayMode.Animate)
- && anyCircles) {
- currentPath.lineTo(mInProgressX, mInProgressY);
- }
- canvas.drawPath(currentPath, mPathPaint);
- }
-
- // draw the circles
- final int paddingTop = mPaddingTop;
- final int paddingLeft = mPaddingLeft;
-
- for (int i = 0; i < 3; i++) {
- float topY = paddingTop + i * squareHeight;
- //float centerY = mPaddingTop + i * mSquareHeight + (mSquareHeight / 2);
- for (int j = 0; j < 3; j++) {
- float leftX = paddingLeft + j * squareWidth;
- drawCircle(canvas, (int) leftX, (int) topY, drawLookup[i][j]);
- }
- }
-
- // draw the arrows associated with the path (unless the user is in progress, and
- // we are in stealth mode)
- boolean oldFlag = (mPaint.getFlags() & Paint.FILTER_BITMAP_FLAG) != 0;
- mPaint.setFilterBitmap(true); // draw with higher quality since we render with transforms
- if (drawPath) {
- for (int i = 0; i < count - 1; i++) {
- Cell cell = pattern.get(i);
- Cell next = pattern.get(i + 1);
-
- // only draw the part of the pattern stored in
- // the lookup table (this is only different in the case
- // of animation).
- if (!drawLookup[next.row][next.column]) {
- break;
- }
-
- float leftX = paddingLeft + cell.column * squareWidth;
- float topY = paddingTop + cell.row * squareHeight;
-
- drawArrow(canvas, leftX, topY, cell, next);
- }
- }
- mPaint.setFilterBitmap(oldFlag); // restore default flag
- }
-
- private void drawArrow(Canvas canvas, float leftX, float topY, Cell start, Cell end) {
- boolean green = mPatternDisplayMode != DisplayMode.Wrong;
-
- final int endRow = end.row;
- final int startRow = start.row;
- final int endColumn = end.column;
- final int startColumn = start.column;
-
- // offsets for centering the bitmap in the cell
- final int offsetX = ((int) mSquareWidth - mBitmapWidth) / 2;
- final int offsetY = ((int) mSquareHeight - mBitmapHeight) / 2;
-
- // compute transform to place arrow bitmaps at correct angle inside circle.
- // This assumes that the arrow image is drawn at 12:00 with it's top edge
- // coincident with the circle bitmap's top edge.
- Bitmap arrow = green ? mBitmapArrowGreenUp : mBitmapArrowRedUp;
- Matrix matrix = new Matrix();
- final int cellWidth = mBitmapCircleDefault.getWidth();
- final int cellHeight = mBitmapCircleDefault.getHeight();
-
- // the up arrow bitmap is at 12:00, so find the rotation from x axis and add 90 degrees.
- final float theta = (float) Math.atan2(
- (double) (endRow - startRow), (double) (endColumn - startColumn));
- final float angle = (float) Math.toDegrees(theta) + 90.0f;
-
- // compose matrix
- matrix.setTranslate(leftX + offsetX, topY + offsetY); // transform to cell position
- matrix.preRotate(angle, cellWidth / 2.0f, cellHeight / 2.0f); // rotate about cell center
- matrix.preTranslate((cellWidth - arrow.getWidth()) / 2.0f, 0.0f); // translate to 12:00 pos
- canvas.drawBitmap(arrow, matrix, mPaint);
- }
-
- /**
- * @param canvas
- * @param leftX
- * @param topY
- * @param partOfPattern Whether this circle is part of the pattern.
- */
- private void drawCircle(Canvas canvas, int leftX, int topY, boolean partOfPattern) {
- Bitmap outerCircle;
- Bitmap innerCircle;
-
- if (!partOfPattern || (mInStealthMode && mPatternDisplayMode != DisplayMode.Wrong)) {
- // unselected circle
- outerCircle = mBitmapCircleDefault;
- innerCircle = mBitmapBtnDefault;
- } else if (mPatternInProgress) {
- // user is in middle of drawing a pattern
- outerCircle = mBitmapCircleGreen;
- innerCircle = mBitmapBtnTouched;
- } else if (mPatternDisplayMode == DisplayMode.Wrong) {
- // the pattern is wrong
- outerCircle = mBitmapCircleRed;
- innerCircle = mBitmapBtnDefault;
- } else if (mPatternDisplayMode == DisplayMode.Correct ||
- mPatternDisplayMode == DisplayMode.Animate) {
- // the pattern is correct
- outerCircle = mBitmapCircleGreen;
- innerCircle = mBitmapBtnDefault;
- } else {
- throw new IllegalStateException("unknown display mode " + mPatternDisplayMode);
- }
-
- final int width = mBitmapWidth;
- final int height = mBitmapHeight;
-
- final float squareWidth = mSquareWidth;
- final float squareHeight = mSquareHeight;
-
- int offsetX = (int) ((squareWidth - width) / 2f);
- int offsetY = (int) ((squareHeight - height) / 2f);
-
- canvas.drawBitmap(outerCircle, leftX + offsetX, topY + offsetY, mPaint);
- canvas.drawBitmap(innerCircle, leftX + offsetX, topY + offsetY, mPaint);
- }
-
- @Override
- protected Parcelable onSaveInstanceState() {
- Parcelable superState = super.onSaveInstanceState();
- return new SavedState(superState,
- LockPatternUtils.patternToString(mPattern),
- mPatternDisplayMode.ordinal(),
- mInputEnabled, mInStealthMode, mTactileFeedbackEnabled);
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- final SavedState ss = (SavedState) state;
- super.onRestoreInstanceState(ss.getSuperState());
- setPattern(
- DisplayMode.Correct,
- LockPatternUtils.stringToPattern(ss.getSerializedPattern()));
- mPatternDisplayMode = DisplayMode.values()[ss.getDisplayMode()];
- mInputEnabled = ss.isInputEnabled();
- mInStealthMode = ss.isInStealthMode();
- mTactileFeedbackEnabled = ss.isTactileFeedbackEnabled();
- }
-
- /**
- * The parecelable for saving and restoring a lock pattern view.
- */
- private static class SavedState extends BaseSavedState {
-
- private final String mSerializedPattern;
- private final int mDisplayMode;
- private final boolean mInputEnabled;
- private final boolean mInStealthMode;
- private final boolean mTactileFeedbackEnabled;
-
- /**
- * Constructor called from {@link LockPatternView#onSaveInstanceState()}
- */
- private SavedState(Parcelable superState, String serializedPattern, int displayMode,
- boolean inputEnabled, boolean inStealthMode, boolean tactileFeedbackEnabled) {
- super(superState);
- mSerializedPattern = serializedPattern;
- mDisplayMode = displayMode;
- mInputEnabled = inputEnabled;
- mInStealthMode = inStealthMode;
- mTactileFeedbackEnabled = tactileFeedbackEnabled;
- }
-
- /**
- * Constructor called from {@link #CREATOR}
- */
- private SavedState(Parcel in) {
- super(in);
- mSerializedPattern = in.readString();
- mDisplayMode = in.readInt();
- mInputEnabled = (Boolean) in.readValue(null);
- mInStealthMode = (Boolean) in.readValue(null);
- mTactileFeedbackEnabled = (Boolean) in.readValue(null);
- }
-
- public String getSerializedPattern() {
- return mSerializedPattern;
- }
-
- public int getDisplayMode() {
- return mDisplayMode;
- }
-
- public boolean isInputEnabled() {
- return mInputEnabled;
- }
-
- public boolean isInStealthMode() {
- return mInStealthMode;
- }
-
- public boolean isTactileFeedbackEnabled(){
- return mTactileFeedbackEnabled;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeString(mSerializedPattern);
- dest.writeInt(mDisplayMode);
- dest.writeValue(mInputEnabled);
- dest.writeValue(mInStealthMode);
- dest.writeValue(mTactileFeedbackEnabled);
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR =
- new Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-}
diff --git a/core/java/com/android/internal/widget/NumberPicker.java b/core/java/com/android/internal/widget/NumberPicker.java
deleted file mode 100644
index 1647c20..0000000
--- a/core/java/com/android/internal/widget/NumberPicker.java
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import android.content.Context;
-import android.os.Handler;
-import android.text.InputFilter;
-import android.text.InputType;
-import android.text.Spanned;
-import android.text.method.NumberKeyListener;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.View.OnFocusChangeListener;
-import android.view.View.OnLongClickListener;
-import android.widget.TextView;
-import android.widget.LinearLayout;
-
-import com.android.internal.R;
-
-public class NumberPicker extends LinearLayout implements OnClickListener,
- OnFocusChangeListener, OnLongClickListener {
-
- public interface OnChangedListener {
- void onChanged(NumberPicker picker, int oldVal, int newVal);
- }
-
- public interface Formatter {
- String toString(int value);
- }
-
- /*
- * Use a custom NumberPicker formatting callback to use two-digit
- * minutes strings like "01". Keeping a static formatter etc. is the
- * most efficient way to do this; it avoids creating temporary objects
- * on every call to format().
- */
- public static final NumberPicker.Formatter TWO_DIGIT_FORMATTER =
- new NumberPicker.Formatter() {
- final StringBuilder mBuilder = new StringBuilder();
- final java.util.Formatter mFmt = new java.util.Formatter(mBuilder);
- final Object[] mArgs = new Object[1];
- public String toString(int value) {
- mArgs[0] = value;
- mBuilder.delete(0, mBuilder.length());
- mFmt.format("%02d", mArgs);
- return mFmt.toString();
- }
- };
-
- private final Handler mHandler;
- private final Runnable mRunnable = new Runnable() {
- public void run() {
- if (mIncrement) {
- changeCurrent(mCurrent + 1);
- mHandler.postDelayed(this, mSpeed);
- } else if (mDecrement) {
- changeCurrent(mCurrent - 1);
- mHandler.postDelayed(this, mSpeed);
- }
- }
- };
-
- private final TextView mText;
- private final InputFilter mNumberInputFilter;
-
- private String[] mDisplayedValues;
- private int mStart;
- private int mEnd;
- private int mCurrent;
- private int mPrevious;
- private OnChangedListener mListener;
- private Formatter mFormatter;
- private long mSpeed = 300;
-
- private boolean mIncrement;
- private boolean mDecrement;
-
- public NumberPicker(Context context) {
- this(context, null);
- }
-
- public NumberPicker(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- @SuppressWarnings({"UnusedDeclaration"})
- public NumberPicker(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs);
- setOrientation(VERTICAL);
- LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(R.layout.number_picker, this, true);
- mHandler = new Handler();
- InputFilter inputFilter = new NumberPickerInputFilter();
- mNumberInputFilter = new NumberRangeKeyListener();
- mIncrementButton = (NumberPickerButton) findViewById(R.id.increment);
- mIncrementButton.setOnClickListener(this);
- mIncrementButton.setOnLongClickListener(this);
- mIncrementButton.setNumberPicker(this);
- mDecrementButton = (NumberPickerButton) findViewById(R.id.decrement);
- mDecrementButton.setOnClickListener(this);
- mDecrementButton.setOnLongClickListener(this);
- mDecrementButton.setNumberPicker(this);
-
- mText = (TextView) findViewById(R.id.timepicker_input);
- mText.setOnFocusChangeListener(this);
- mText.setFilters(new InputFilter[] {inputFilter});
- mText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
-
- if (!isEnabled()) {
- setEnabled(false);
- }
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- super.setEnabled(enabled);
- mIncrementButton.setEnabled(enabled);
- mDecrementButton.setEnabled(enabled);
- mText.setEnabled(enabled);
- }
-
- public void setOnChangeListener(OnChangedListener listener) {
- mListener = listener;
- }
-
- public void setFormatter(Formatter formatter) {
- mFormatter = formatter;
- }
-
- /**
- * Set the range of numbers allowed for the number picker. The current
- * value will be automatically set to the start.
- *
- * @param start the start of the range (inclusive)
- * @param end the end of the range (inclusive)
- */
- public void setRange(int start, int end) {
- mStart = start;
- mEnd = end;
- mCurrent = start;
- updateView();
- }
-
- /**
- * Set the range of numbers allowed for the number picker. The current
- * value will be automatically set to the start. Also provide a mapping
- * for values used to display to the user.
- *
- * @param start the start of the range (inclusive)
- * @param end the end of the range (inclusive)
- * @param displayedValues the values displayed to the user.
- */
- public void setRange(int start, int end, String[] displayedValues) {
- mDisplayedValues = displayedValues;
- mStart = start;
- mEnd = end;
- mCurrent = start;
- updateView();
- }
-
- public void setCurrent(int current) {
- mCurrent = current;
- updateView();
- }
-
- /**
- * The speed (in milliseconds) at which the numbers will scroll
- * when the the +/- buttons are longpressed. Default is 300ms.
- */
- public void setSpeed(long speed) {
- mSpeed = speed;
- }
-
- public void onClick(View v) {
-
- /* The text view may still have focus so clear it's focus which will
- * trigger the on focus changed and any typed values to be pulled.
- */
- mText.clearFocus();
-
- // now perform the increment/decrement
- if (R.id.increment == v.getId()) {
- changeCurrent(mCurrent + 1);
- } else if (R.id.decrement == v.getId()) {
- changeCurrent(mCurrent - 1);
- }
- }
-
- private String formatNumber(int value) {
- return (mFormatter != null)
- ? mFormatter.toString(value)
- : String.valueOf(value);
- }
-
- private void changeCurrent(int current) {
-
- // Wrap around the values if we go past the start or end
- if (current > mEnd) {
- current = mStart;
- } else if (current < mStart) {
- current = mEnd;
- }
- mPrevious = mCurrent;
- mCurrent = current;
- notifyChange();
- updateView();
- }
-
- private void notifyChange() {
- if (mListener != null) {
- mListener.onChanged(this, mPrevious, mCurrent);
- }
- }
-
- private void updateView() {
-
- /* If we don't have displayed values then use the
- * current number else find the correct value in the
- * displayed values for the current number.
- */
- if (mDisplayedValues == null) {
- mText.setText(formatNumber(mCurrent));
- } else {
- mText.setText(mDisplayedValues[mCurrent - mStart]);
- }
- }
-
- private void validateCurrentView(CharSequence str) {
- int val = getSelectedPos(str.toString());
- if ((val >= mStart) && (val <= mEnd)) {
- mPrevious = mCurrent;
- mCurrent = val;
- notifyChange();
- }
- updateView();
- }
-
- public void onFocusChange(View v, boolean hasFocus) {
-
- /* When focus is lost check that the text field
- * has valid values.
- */
- if (!hasFocus) {
- String str = String.valueOf(((TextView) v).getText());
- if ("".equals(str)) {
-
- // Restore to the old value as we don't allow empty values
- updateView();
- } else {
-
- // Check the new value and ensure it's in range
- validateCurrentView(str);
- }
- }
- }
-
- /**
- * We start the long click here but rely on the {@link NumberPickerButton}
- * to inform us when the long click has ended.
- */
- public boolean onLongClick(View v) {
-
- /* The text view may still have focus so clear it's focus which will
- * trigger the on focus changed and any typed values to be pulled.
- */
- mText.clearFocus();
-
- if (R.id.increment == v.getId()) {
- mIncrement = true;
- mHandler.post(mRunnable);
- } else if (R.id.decrement == v.getId()) {
- mDecrement = true;
- mHandler.post(mRunnable);
- }
- return true;
- }
-
- public void cancelIncrement() {
- mIncrement = false;
- }
-
- public void cancelDecrement() {
- mDecrement = false;
- }
-
- private static final char[] DIGIT_CHARACTERS = new char[] {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
- };
-
- private NumberPickerButton mIncrementButton;
- private NumberPickerButton mDecrementButton;
-
- private class NumberPickerInputFilter implements InputFilter {
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend) {
- if (mDisplayedValues == null) {
- return mNumberInputFilter.filter(source, start, end, dest, dstart, dend);
- }
- CharSequence filtered = String.valueOf(source.subSequence(start, end));
- String result = String.valueOf(dest.subSequence(0, dstart))
- + filtered
- + dest.subSequence(dend, dest.length());
- String str = String.valueOf(result).toLowerCase();
- for (String val : mDisplayedValues) {
- val = val.toLowerCase();
- if (val.startsWith(str)) {
- return filtered;
- }
- }
- return "";
- }
- }
-
- private class NumberRangeKeyListener extends NumberKeyListener {
-
- // XXX This doesn't allow for range limits when controlled by a
- // soft input method!
- public int getInputType() {
- return InputType.TYPE_CLASS_NUMBER;
- }
-
- @Override
- protected char[] getAcceptedChars() {
- return DIGIT_CHARACTERS;
- }
-
- @Override
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend) {
-
- CharSequence filtered = super.filter(source, start, end, dest, dstart, dend);
- if (filtered == null) {
- filtered = source.subSequence(start, end);
- }
-
- String result = String.valueOf(dest.subSequence(0, dstart))
- + filtered
- + dest.subSequence(dend, dest.length());
-
- if ("".equals(result)) {
- return result;
- }
- int val = getSelectedPos(result);
-
- /* Ensure the user can't type in a value greater
- * than the max allowed. We have to allow less than min
- * as the user might want to delete some numbers
- * and then type a new number.
- */
- if (val > mEnd) {
- return "";
- } else {
- return filtered;
- }
- }
- }
-
- private int getSelectedPos(String str) {
- if (mDisplayedValues == null) {
- return Integer.parseInt(str);
- } else {
- for (int i = 0; i < mDisplayedValues.length; i++) {
-
- /* Don't force the user to type in jan when ja will do */
- str = str.toLowerCase();
- if (mDisplayedValues[i].toLowerCase().startsWith(str)) {
- return mStart + i;
- }
- }
-
- /* The user might have typed in a number into the month field i.e.
- * 10 instead of OCT so support that too.
- */
- try {
- return Integer.parseInt(str);
- } catch (NumberFormatException e) {
-
- /* Ignore as if it's not a number we don't care */
- }
- }
- return mStart;
- }
-
- /**
- * @return the current value.
- */
- public int getCurrent() {
- return mCurrent;
- }
-} \ No newline at end of file
diff --git a/core/java/com/android/internal/widget/NumberPickerButton.java b/core/java/com/android/internal/widget/NumberPickerButton.java
deleted file mode 100644
index 39f1e2c..0000000
--- a/core/java/com/android/internal/widget/NumberPickerButton.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.widget.ImageButton;
-
-import com.android.internal.R;
-
-/**
- * This class exists purely to cancel long click events.
- */
-public class NumberPickerButton extends ImageButton {
-
- private NumberPicker mNumberPicker;
-
- public NumberPickerButton(Context context, AttributeSet attrs,
- int defStyle) {
- super(context, attrs, defStyle);
- }
-
- public NumberPickerButton(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public NumberPickerButton(Context context) {
- super(context);
- }
-
- public void setNumberPicker(NumberPicker picker) {
- mNumberPicker = picker;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- cancelLongpressIfRequired(event);
- return super.onTouchEvent(event);
- }
-
- @Override
- public boolean onTrackballEvent(MotionEvent event) {
- cancelLongpressIfRequired(event);
- return super.onTrackballEvent(event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if ((keyCode == KeyEvent.KEYCODE_DPAD_CENTER)
- || (keyCode == KeyEvent.KEYCODE_ENTER)) {
- cancelLongpress();
- }
- return super.onKeyUp(keyCode, event);
- }
-
- private void cancelLongpressIfRequired(MotionEvent event) {
- if ((event.getAction() == MotionEvent.ACTION_CANCEL)
- || (event.getAction() == MotionEvent.ACTION_UP)) {
- cancelLongpress();
- }
- }
-
- private void cancelLongpress() {
- if (R.id.increment == getId()) {
- mNumberPicker.cancelIncrement();
- } else if (R.id.decrement == getId()) {
- mNumberPicker.cancelDecrement();
- }
- }
-}
diff --git a/core/java/com/android/internal/widget/TextProgressBar.java b/core/java/com/android/internal/widget/TextProgressBar.java
deleted file mode 100644
index 5bf4601..0000000
--- a/core/java/com/android/internal/widget/TextProgressBar.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import android.content.Context;
-import android.os.SystemClock;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Chronometer;
-import android.widget.Chronometer.OnChronometerTickListener;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-import android.widget.RemoteViews.RemoteView;
-
-/**
- * Container that links together a {@link ProgressBar} and {@link Chronometer}
- * as children. It subscribes to {@link Chronometer#OnChronometerTickListener}
- * and updates the {@link ProgressBar} based on a preset finishing time.
- * <p>
- * This widget expects to contain two children with specific ids
- * {@link android.R.id.progress} and {@link android.R.id.text1}.
- * <p>
- * If the {@link Chronometer} {@link android.R.attr#layout_width} is
- * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}, then the
- * {@link android.R.attr#gravity} will be used to automatically move it with
- * respect to the {@link ProgressBar} position. For example, if
- * {@link android.view.Gravity#LEFT} then the {@link Chronometer} will be placed
- * just ahead of the leading edge of the {@link ProgressBar} position.
- */
-@RemoteView
-public class TextProgressBar extends RelativeLayout implements OnChronometerTickListener {
- public static final String TAG = "TextProgressBar";
-
- static final int CHRONOMETER_ID = android.R.id.text1;
- static final int PROGRESSBAR_ID = android.R.id.progress;
-
- Chronometer mChronometer = null;
- ProgressBar mProgressBar = null;
-
- long mDurationBase = -1;
- int mDuration = -1;
-
- boolean mChronometerFollow = false;
- int mChronometerGravity = Gravity.NO_GRAVITY;
-
- public TextProgressBar(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- public TextProgressBar(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public TextProgressBar(Context context) {
- super(context);
- }
-
- /**
- * Catch any interesting children when they are added.
- */
- @Override
- public void addView(View child, int index, ViewGroup.LayoutParams params) {
- super.addView(child, index, params);
-
- int childId = child.getId();
- if (childId == CHRONOMETER_ID && child instanceof Chronometer) {
- mChronometer = (Chronometer) child;
- mChronometer.setOnChronometerTickListener(this);
-
- // Check if Chronometer should move with with ProgressBar
- mChronometerFollow = (params.width == ViewGroup.LayoutParams.WRAP_CONTENT);
- mChronometerGravity = (mChronometer.getGravity() & Gravity.HORIZONTAL_GRAVITY_MASK);
-
- } else if (childId == PROGRESSBAR_ID && child instanceof ProgressBar) {
- mProgressBar = (ProgressBar) child;
- }
- }
-
- /**
- * Set the expected termination time of the running {@link Chronometer}.
- * This value is used to adjust the {@link ProgressBar} against the elapsed
- * time.
- * <p>
- * Call this <b>after</b> adjusting the {@link Chronometer} base, if
- * necessary.
- *
- * @param durationBase Use the {@link SystemClock#elapsedRealtime} time
- * base.
- */
- @android.view.RemotableViewMethod
- public void setDurationBase(long durationBase) {
- mDurationBase = durationBase;
-
- if (mProgressBar == null || mChronometer == null) {
- throw new RuntimeException("Expecting child ProgressBar with id " +
- "'android.R.id.progress' and Chronometer id 'android.R.id.text1'");
- }
-
- // Update the ProgressBar maximum relative to Chronometer base
- mDuration = (int) (durationBase - mChronometer.getBase());
- mProgressBar.setMax(mDuration);
-
- }
-
- /**
- * Callback when {@link Chronometer} changes, indicating that we should
- * update the {@link ProgressBar} and change the layout if necessary.
- */
- public void onChronometerTick(Chronometer chronometer) {
- if (mProgressBar == null) {
- throw new RuntimeException(
- "Expecting child ProgressBar with id 'android.R.id.progress'");
- }
-
- // Stop Chronometer if we're past duration
- long now = SystemClock.elapsedRealtime();
- if (now >= mDurationBase) {
- mChronometer.stop();
- }
-
- // Update the ProgressBar status
- int remaining = (int) (mDurationBase - now);
- mProgressBar.setProgress(mDuration - remaining);
-
- // Move the Chronometer if gravity is set correctly
- if (mChronometerFollow) {
- RelativeLayout.LayoutParams params;
-
- // Calculate estimate of ProgressBar leading edge position
- params = (RelativeLayout.LayoutParams) mProgressBar.getLayoutParams();
- int contentWidth = mProgressBar.getWidth() - (params.leftMargin + params.rightMargin);
- int leadingEdge = ((contentWidth * mProgressBar.getProgress()) /
- mProgressBar.getMax()) + params.leftMargin;
-
- // Calculate any adjustment based on gravity
- int adjustLeft = 0;
- int textWidth = mChronometer.getWidth();
- if (mChronometerGravity == Gravity.RIGHT) {
- adjustLeft = -textWidth;
- } else if (mChronometerGravity == Gravity.CENTER_HORIZONTAL) {
- adjustLeft = -(textWidth / 2);
- }
-
- // Limit margin to keep text inside ProgressBar bounds
- leadingEdge += adjustLeft;
- int rightLimit = contentWidth - params.rightMargin - textWidth;
- if (leadingEdge < params.leftMargin) {
- leadingEdge = params.leftMargin;
- } else if (leadingEdge > rightLimit) {
- leadingEdge = rightLimit;
- }
-
- params = (RelativeLayout.LayoutParams) mChronometer.getLayoutParams();
- params.leftMargin = leadingEdge;
-
- // Request layout to move Chronometer
- mChronometer.requestLayout();
-
- }
- }
-}
diff --git a/core/java/com/android/internal/widget/VerticalTextSpinner.java b/core/java/com/android/internal/widget/VerticalTextSpinner.java
deleted file mode 100644
index 50c528c..0000000
--- a/core/java/com/android/internal/widget/VerticalTextSpinner.java
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.text.TextPaint;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-
-
-public class VerticalTextSpinner extends View {
-
- private static final int SELECTOR_ARROW_HEIGHT = 15;
-
- private static final int TEXT_SPACING = 18;
- private static final int TEXT_MARGIN_RIGHT = 25;
- private static final int TEXT_SIZE = 22;
-
- /* Keep the calculations as this is really a for loop from
- * -2 to 2 but precalculated so we don't have to do in the onDraw.
- */
- private static final int TEXT1_Y = (TEXT_SIZE * (-2 + 2)) + (TEXT_SPACING * (-2 + 1));
- private static final int TEXT2_Y = (TEXT_SIZE * (-1 + 2)) + (TEXT_SPACING * (-1 + 1));
- private static final int TEXT3_Y = (TEXT_SIZE * (0 + 2)) + (TEXT_SPACING * (0 + 1));
- private static final int TEXT4_Y = (TEXT_SIZE * (1 + 2)) + (TEXT_SPACING * (1 + 1));
- private static final int TEXT5_Y = (TEXT_SIZE * (2 + 2)) + (TEXT_SPACING * (2 + 1));
-
- private static final int SCROLL_MODE_NONE = 0;
- private static final int SCROLL_MODE_UP = 1;
- private static final int SCROLL_MODE_DOWN = 2;
-
- private static final long DEFAULT_SCROLL_INTERVAL_MS = 400;
- private static final int SCROLL_DISTANCE = TEXT_SIZE + TEXT_SPACING;
- private static final int MIN_ANIMATIONS = 4;
-
- private final Drawable mBackgroundFocused;
- private final Drawable mSelectorFocused;
- private final Drawable mSelectorNormal;
- private final int mSelectorDefaultY;
- private final int mSelectorMinY;
- private final int mSelectorMaxY;
- private final int mSelectorHeight;
- private final TextPaint mTextPaintDark;
- private final TextPaint mTextPaintLight;
-
- private int mSelectorY;
- private Drawable mSelector;
- private int mDownY;
- private boolean isDraggingSelector;
- private int mScrollMode;
- private long mScrollInterval;
- private boolean mIsAnimationRunning;
- private boolean mStopAnimation;
- private boolean mWrapAround = true;
-
- private int mTotalAnimatedDistance;
- private int mNumberOfAnimations;
- private long mDelayBetweenAnimations;
- private int mDistanceOfEachAnimation;
-
- private String[] mTextList;
- private int mCurrentSelectedPos;
- private OnChangedListener mListener;
-
- private String mText1;
- private String mText2;
- private String mText3;
- private String mText4;
- private String mText5;
-
- public interface OnChangedListener {
- void onChanged(
- VerticalTextSpinner spinner, int oldPos, int newPos, String[] items);
- }
-
- public VerticalTextSpinner(Context context) {
- this(context, null);
- }
-
- public VerticalTextSpinner(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public VerticalTextSpinner(Context context, AttributeSet attrs,
- int defStyle) {
- super(context, attrs, defStyle);
-
- mBackgroundFocused = context.getResources().getDrawable(com.android.internal.R.drawable.pickerbox_background);
- mSelectorFocused = context.getResources().getDrawable(com.android.internal.R.drawable.pickerbox_selected);
- mSelectorNormal = context.getResources().getDrawable(com.android.internal.R.drawable.pickerbox_unselected);
-
- mSelectorHeight = mSelectorFocused.getIntrinsicHeight();
- mSelectorDefaultY = (mBackgroundFocused.getIntrinsicHeight() - mSelectorHeight) / 2;
- mSelectorMinY = 0;
- mSelectorMaxY = mBackgroundFocused.getIntrinsicHeight() - mSelectorHeight;
-
- mSelector = mSelectorNormal;
- mSelectorY = mSelectorDefaultY;
-
- mTextPaintDark = new TextPaint(Paint.ANTI_ALIAS_FLAG);
- mTextPaintDark.setTextSize(TEXT_SIZE);
- mTextPaintDark.setColor(context.getResources().getColor(com.android.internal.R.color.primary_text_light));
-
- mTextPaintLight = new TextPaint(Paint.ANTI_ALIAS_FLAG);
- mTextPaintLight.setTextSize(TEXT_SIZE);
- mTextPaintLight.setColor(context.getResources().getColor(com.android.internal.R.color.secondary_text_dark));
-
- mScrollMode = SCROLL_MODE_NONE;
- mScrollInterval = DEFAULT_SCROLL_INTERVAL_MS;
- calculateAnimationValues();
- }
-
- public void setOnChangeListener(OnChangedListener listener) {
- mListener = listener;
- }
-
- public void setItems(String[] textList) {
- mTextList = textList;
- calculateTextPositions();
- }
-
- public void setSelectedPos(int selectedPos) {
- mCurrentSelectedPos = selectedPos;
- calculateTextPositions();
- postInvalidate();
- }
-
- public void setScrollInterval(long interval) {
- mScrollInterval = interval;
- calculateAnimationValues();
- }
-
- public void setWrapAround(boolean wrap) {
- mWrapAround = wrap;
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
-
- /* This is a bit confusing, when we get the key event
- * DPAD_DOWN we actually roll the spinner up. When the
- * key event is DPAD_UP we roll the spinner down.
- */
- if ((keyCode == KeyEvent.KEYCODE_DPAD_UP) && canScrollDown()) {
- mScrollMode = SCROLL_MODE_DOWN;
- scroll();
- mStopAnimation = true;
- return true;
- } else if ((keyCode == KeyEvent.KEYCODE_DPAD_DOWN) && canScrollUp()) {
- mScrollMode = SCROLL_MODE_UP;
- scroll();
- mStopAnimation = true;
- return true;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- private boolean canScrollDown() {
- return (mCurrentSelectedPos > 0) || mWrapAround;
- }
-
- private boolean canScrollUp() {
- return ((mCurrentSelectedPos < (mTextList.length - 1)) || mWrapAround);
- }
-
- @Override
- protected void onFocusChanged(boolean gainFocus, int direction,
- Rect previouslyFocusedRect) {
- if (gainFocus) {
- setBackgroundDrawable(mBackgroundFocused);
- mSelector = mSelectorFocused;
- } else {
- setBackgroundDrawable(null);
- mSelector = mSelectorNormal;
- mSelectorY = mSelectorDefaultY;
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- final int action = event.getAction();
- final int y = (int) event.getY();
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- requestFocus();
- mDownY = y;
- isDraggingSelector = (y >= mSelectorY) && (y <= (mSelectorY + mSelector.getIntrinsicHeight()));
- break;
-
- case MotionEvent.ACTION_MOVE:
- if (isDraggingSelector) {
- int top = mSelectorDefaultY + (y - mDownY);
- if (top <= mSelectorMinY && canScrollDown()) {
- mSelectorY = mSelectorMinY;
- mStopAnimation = false;
- if (mScrollMode != SCROLL_MODE_DOWN) {
- mScrollMode = SCROLL_MODE_DOWN;
- scroll();
- }
- } else if (top >= mSelectorMaxY && canScrollUp()) {
- mSelectorY = mSelectorMaxY;
- mStopAnimation = false;
- if (mScrollMode != SCROLL_MODE_UP) {
- mScrollMode = SCROLL_MODE_UP;
- scroll();
- }
- } else {
- mSelectorY = top;
- mStopAnimation = true;
- }
- }
- break;
-
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- default:
- mSelectorY = mSelectorDefaultY;
- mStopAnimation = true;
- invalidate();
- break;
- }
- return true;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
-
- /* The bounds of the selector */
- final int selectorLeft = 0;
- final int selectorTop = mSelectorY;
- final int selectorRight = mMeasuredWidth;
- final int selectorBottom = mSelectorY + mSelectorHeight;
-
- /* Draw the selector */
- mSelector.setBounds(selectorLeft, selectorTop, selectorRight, selectorBottom);
- mSelector.draw(canvas);
-
- if (mTextList == null) {
-
- /* We're not setup with values so don't draw anything else */
- return;
- }
-
- final TextPaint textPaintDark = mTextPaintDark;
- if (hasFocus()) {
-
- /* The bounds of the top area where the text should be light */
- final int topLeft = 0;
- final int topTop = 0;
- final int topRight = selectorRight;
- final int topBottom = selectorTop + SELECTOR_ARROW_HEIGHT;
-
- /* Assign a bunch of local finals for performance */
- final String text1 = mText1;
- final String text2 = mText2;
- final String text3 = mText3;
- final String text4 = mText4;
- final String text5 = mText5;
- final TextPaint textPaintLight = mTextPaintLight;
-
- /*
- * Draw the 1st, 2nd and 3rd item in light only, clip it so it only
- * draws in the area above the selector
- */
- canvas.save();
- canvas.clipRect(topLeft, topTop, topRight, topBottom);
- drawText(canvas, text1, TEXT1_Y
- + mTotalAnimatedDistance, textPaintLight);
- drawText(canvas, text2, TEXT2_Y
- + mTotalAnimatedDistance, textPaintLight);
- drawText(canvas, text3,
- TEXT3_Y + mTotalAnimatedDistance, textPaintLight);
- canvas.restore();
-
- /*
- * Draw the 2nd, 3rd and 4th clipped to the selector bounds in dark
- * paint
- */
- canvas.save();
- canvas.clipRect(selectorLeft, selectorTop + SELECTOR_ARROW_HEIGHT,
- selectorRight, selectorBottom - SELECTOR_ARROW_HEIGHT);
- drawText(canvas, text2, TEXT2_Y
- + mTotalAnimatedDistance, textPaintDark);
- drawText(canvas, text3,
- TEXT3_Y + mTotalAnimatedDistance, textPaintDark);
- drawText(canvas, text4,
- TEXT4_Y + mTotalAnimatedDistance, textPaintDark);
- canvas.restore();
-
- /* The bounds of the bottom area where the text should be light */
- final int bottomLeft = 0;
- final int bottomTop = selectorBottom - SELECTOR_ARROW_HEIGHT;
- final int bottomRight = selectorRight;
- final int bottomBottom = mMeasuredHeight;
-
- /*
- * Draw the 3rd, 4th and 5th in white text, clip it so it only draws
- * in the area below the selector.
- */
- canvas.save();
- canvas.clipRect(bottomLeft, bottomTop, bottomRight, bottomBottom);
- drawText(canvas, text3,
- TEXT3_Y + mTotalAnimatedDistance, textPaintLight);
- drawText(canvas, text4,
- TEXT4_Y + mTotalAnimatedDistance, textPaintLight);
- drawText(canvas, text5,
- TEXT5_Y + mTotalAnimatedDistance, textPaintLight);
- canvas.restore();
-
- } else {
- drawText(canvas, mText3, TEXT3_Y, textPaintDark);
- }
- if (mIsAnimationRunning) {
- if ((Math.abs(mTotalAnimatedDistance) + mDistanceOfEachAnimation) > SCROLL_DISTANCE) {
- mTotalAnimatedDistance = 0;
- if (mScrollMode == SCROLL_MODE_UP) {
- int oldPos = mCurrentSelectedPos;
- int newPos = getNewIndex(1);
- if (newPos >= 0) {
- mCurrentSelectedPos = newPos;
- if (mListener != null) {
- mListener.onChanged(this, oldPos, mCurrentSelectedPos, mTextList);
- }
- }
- if (newPos < 0 || ((newPos >= mTextList.length - 1) && !mWrapAround)) {
- mStopAnimation = true;
- }
- calculateTextPositions();
- } else if (mScrollMode == SCROLL_MODE_DOWN) {
- int oldPos = mCurrentSelectedPos;
- int newPos = getNewIndex(-1);
- if (newPos >= 0) {
- mCurrentSelectedPos = newPos;
- if (mListener != null) {
- mListener.onChanged(this, oldPos, mCurrentSelectedPos, mTextList);
- }
- }
- if (newPos < 0 || (newPos == 0 && !mWrapAround)) {
- mStopAnimation = true;
- }
- calculateTextPositions();
- }
- if (mStopAnimation) {
- final int previousScrollMode = mScrollMode;
-
- /* No longer scrolling, we wait till the current animation
- * completes then we stop.
- */
- mIsAnimationRunning = false;
- mStopAnimation = false;
- mScrollMode = SCROLL_MODE_NONE;
-
- /* If the current selected item is an empty string
- * scroll past it.
- */
- if ("".equals(mTextList[mCurrentSelectedPos])) {
- mScrollMode = previousScrollMode;
- scroll();
- mStopAnimation = true;
- }
- }
- } else {
- if (mScrollMode == SCROLL_MODE_UP) {
- mTotalAnimatedDistance -= mDistanceOfEachAnimation;
- } else if (mScrollMode == SCROLL_MODE_DOWN) {
- mTotalAnimatedDistance += mDistanceOfEachAnimation;
- }
- }
- if (mDelayBetweenAnimations > 0) {
- postInvalidateDelayed(mDelayBetweenAnimations);
- } else {
- invalidate();
- }
- }
- }
-
- /**
- * Called every time the text items or current position
- * changes. We calculate store we don't have to calculate
- * onDraw.
- */
- private void calculateTextPositions() {
- mText1 = getTextToDraw(-2);
- mText2 = getTextToDraw(-1);
- mText3 = getTextToDraw(0);
- mText4 = getTextToDraw(1);
- mText5 = getTextToDraw(2);
- }
-
- private String getTextToDraw(int offset) {
- int index = getNewIndex(offset);
- if (index < 0) {
- return "";
- }
- return mTextList[index];
- }
-
- private int getNewIndex(int offset) {
- int index = mCurrentSelectedPos + offset;
- if (index < 0) {
- if (mWrapAround) {
- index += mTextList.length;
- } else {
- return -1;
- }
- } else if (index >= mTextList.length) {
- if (mWrapAround) {
- index -= mTextList.length;
- } else {
- return -1;
- }
- }
- return index;
- }
-
- private void scroll() {
- if (mIsAnimationRunning) {
- return;
- }
- mTotalAnimatedDistance = 0;
- mIsAnimationRunning = true;
- invalidate();
- }
-
- private void calculateAnimationValues() {
- mNumberOfAnimations = (int) mScrollInterval / SCROLL_DISTANCE;
- if (mNumberOfAnimations < MIN_ANIMATIONS) {
- mNumberOfAnimations = MIN_ANIMATIONS;
- mDistanceOfEachAnimation = SCROLL_DISTANCE / mNumberOfAnimations;
- mDelayBetweenAnimations = 0;
- } else {
- mDistanceOfEachAnimation = SCROLL_DISTANCE / mNumberOfAnimations;
- mDelayBetweenAnimations = mScrollInterval / mNumberOfAnimations;
- }
- }
-
- private void drawText(Canvas canvas, String text, int y, TextPaint paint) {
- int width = (int) paint.measureText(text);
- int x = getMeasuredWidth() - width - TEXT_MARGIN_RIGHT;
- canvas.drawText(text, x, y, paint);
- }
-
- public int getCurrentSelectedPos() {
- return mCurrentSelectedPos;
- }
-}
diff --git a/core/java/com/android/server/ResettableTimeout.java b/core/java/com/android/server/ResettableTimeout.java
deleted file mode 100644
index ac5b160..0000000
--- a/core/java/com/android/server/ResettableTimeout.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.os.SystemClock;
-
-import android.os.ConditionVariable;
-
-/**
- * Utility class that you can call on with a timeout, and get called back
- * after a given time, dealing correctly with restarting the timeout.
- *
- * <p>For example, this class is used by the android.os.Vibrator class.
- */
-abstract class ResettableTimeout
-{
- /**
- * Override this do what you need to do when it's starting
- * This is called with the monitor on this method held, so be careful.
- *
- * @param alreadyOn is true if it's currently running
- */
- public abstract void on(boolean alreadyOn);
-
- /**
- * Override this to do what you need to do when it's stopping.
- * This is called with the monitor on this method held, so be careful.
- */
- public abstract void off();
-
- /**
- * Does the following steps.
- * <p>1. Call on()</p>
- * <p>2. Start the timer.</p>
- * <p>3. At the timeout, calls off()<p>
- * <p>If you call this again, the timeout is reset to the new one</p>
- */
- public void go(long milliseconds)
- {
- synchronized (this) {
- mOffAt = SystemClock.uptimeMillis() + milliseconds;
-
- boolean alreadyOn;
-
- // By starting the thread first and waiting, we ensure that if the
- // thread to stop it can't start, we don't turn the vibrator on
- // forever. This still isn't really sufficient, because we don't
- // have another processor watching us. We really should have a
- // service for this in case our process crashes.
- if (mThread == null) {
- alreadyOn = false;
- mLock.close();
- mThread = new T();
- mThread.start();
- mLock.block();
- mOffCalled = false;
- } else {
- alreadyOn = true;
- // poke the thread so it gets the new timeout.
- mThread.interrupt();
- }
- on(alreadyOn);
- }
- }
-
- /**
- * Cancel the timeout and call off now.
- */
- public void cancel()
- {
- synchronized (this) {
- mOffAt = 0;
- if (mThread != null) {
- mThread.interrupt();
- mThread = null;
- }
- if (!mOffCalled) {
- mOffCalled = true;
- off();
- }
- }
- }
-
- private class T extends Thread
- {
- public void run()
- {
- mLock.open();
- while (true) {
- long diff;
- synchronized (this) {
- diff = mOffAt - SystemClock.uptimeMillis();
- if (diff <= 0) {
- mOffCalled = true;
- off();
- mThread = null;
- break;
- }
- }
- try {
- sleep(diff);
- }
- catch (InterruptedException e) {
- }
- }
- }
- }
-
- private ConditionVariable mLock = new ConditionVariable();
-
- // turn it off at this time.
- private volatile long mOffAt;
- private volatile boolean mOffCalled;
-
- private Thread mThread;
-
-}
-
diff --git a/core/java/com/google/android/collect/Lists.java b/core/java/com/google/android/collect/Lists.java
deleted file mode 100644
index c029bb2..0000000
--- a/core/java/com/google/android/collect/Lists.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.collect;
-
-import java.util.ArrayList;
-import java.util.Collections;
-
-/**
- * Provides static methods for creating {@code List} instances easily, and other
- * utility methods for working with lists.
- */
-public class Lists {
-
- /**
- * Creates an empty {@code ArrayList} instance.
- *
- * <p><b>Note:</b> if you only need an <i>immutable</i> empty List, use
- * {@link Collections#emptyList} instead.
- *
- * @return a newly-created, initially-empty {@code ArrayList}
- */
- public static <E> ArrayList<E> newArrayList() {
- return new ArrayList<E>();
- }
-
- /**
- * Creates a resizable {@code ArrayList} instance containing the given
- * elements.
- *
- * <p><b>Note:</b> due to a bug in javac 1.5.0_06, we cannot support the
- * following:
- *
- * <p>{@code List<Base> list = Lists.newArrayList(sub1, sub2);}
- *
- * <p>where {@code sub1} and {@code sub2} are references to subtypes of
- * {@code Base}, not of {@code Base} itself. To get around this, you must
- * use:
- *
- * <p>{@code List<Base> list = Lists.<Base>newArrayList(sub1, sub2);}
- *
- * @param elements the elements that the list should contain, in order
- * @return a newly-created {@code ArrayList} containing those elements
- */
- public static <E> ArrayList<E> newArrayList(E... elements) {
- int capacity = (elements.length * 110) / 100 + 5;
- ArrayList<E> list = new ArrayList<E>(capacity);
- Collections.addAll(list, elements);
- return list;
- }
-}
diff --git a/core/java/com/google/android/collect/Maps.java b/core/java/com/google/android/collect/Maps.java
deleted file mode 100644
index d537e0c..0000000
--- a/core/java/com/google/android/collect/Maps.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.collect;
-
-import java.util.HashMap;
-
-/**
- * Provides static methods for creating mutable {@code Maps} instances easily.
- */
-public class Maps {
- /**
- * Creates a {@code HashMap} instance.
- *
- * @return a newly-created, initially-empty {@code HashMap}
- */
- public static <K, V> HashMap<K, V> newHashMap() {
- return new HashMap<K, V>();
- }
-}
diff --git a/core/java/com/google/android/collect/Sets.java b/core/java/com/google/android/collect/Sets.java
deleted file mode 100644
index f5be0ec..0000000
--- a/core/java/com/google/android/collect/Sets.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.collect;
-
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-/**
- * Provides static methods for creating mutable {@code Set} instances easily and
- * other static methods for working with Sets.
- *
- */
-public class Sets {
-
- /**
- * Creates an empty {@code HashSet} instance.
- *
- * <p><b>Note:</b> if {@code E} is an {@link Enum} type, use {@link
- * EnumSet#noneOf} instead.
- *
- * <p><b>Note:</b> if you only need an <i>immutable</i> empty Set,
- * use {@link Collections#emptySet} instead.
- *
- * @return a newly-created, initially-empty {@code HashSet}
- */
- public static <K> HashSet<K> newHashSet() {
- return new HashSet<K>();
- }
-
- /**
- * Creates a {@code HashSet} instance containing the given elements.
- *
- * <p><b>Note:</b> due to a bug in javac 1.5.0_06, we cannot support the
- * following:
- *
- * <p>{@code Set<Base> set = Sets.newHashSet(sub1, sub2);}
- *
- * <p>where {@code sub1} and {@code sub2} are references to subtypes of {@code
- * Base}, not of {@code Base} itself. To get around this, you must use:
- *
- * <p>{@code Set<Base> set = Sets.<Base>newHashSet(sub1, sub2);}
- *
- * @param elements the elements that the set should contain
- * @return a newly-created {@code HashSet} containing those elements (minus
- * duplicates)
- */
- public static <E> HashSet<E> newHashSet(E... elements) {
- int capacity = elements.length * 4 / 3 + 1;
- HashSet<E> set = new HashSet<E>(capacity);
- Collections.addAll(set, elements);
- return set;
- }
-
- /**
- * Creates a {@code SortedSet} instance containing the given elements.
- *
- * @param elements the elements that the set should contain
- * @return a newly-created {@code SortedSet} containing those elements (minus
- * duplicates)
- */
- public static <E> SortedSet<E> newSortedSet(E... elements) {
- SortedSet<E> set = new TreeSet<E>();
- Collections.addAll(set, elements);
- return set;
- }
-
-}
diff --git a/core/java/com/google/android/gdata/client/AndroidGDataClient.java b/core/java/com/google/android/gdata/client/AndroidGDataClient.java
deleted file mode 100644
index 1d8e9c5..0000000
--- a/core/java/com/google/android/gdata/client/AndroidGDataClient.java
+++ /dev/null
@@ -1,467 +0,0 @@
-// Copyright 2007 The Android Open Source Project
-
-package com.google.android.gdata.client;
-
-import com.google.android.net.GoogleHttpClient;
-import com.google.wireless.gdata.client.GDataClient;
-import com.google.wireless.gdata.client.HttpException;
-import com.google.wireless.gdata.client.QueryParams;
-import com.google.wireless.gdata.data.StringUtils;
-import com.google.wireless.gdata.parser.ParseException;
-import com.google.wireless.gdata.serializer.GDataSerializer;
-
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.StatusLine;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.entity.InputStreamEntity;
-import org.apache.http.entity.AbstractHttpEntity;
-
-import android.content.ContentResolver;
-import android.net.http.AndroidHttpClient;
-import android.text.TextUtils;
-import android.util.Config;
-import android.util.Log;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.io.BufferedInputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URLEncoder;
-
-/**
- * Implementation of a GDataClient using GoogleHttpClient to make HTTP
- * requests. Always issues GETs and POSTs, using the X-HTTP-Method-Override
- * header when a PUT or DELETE is desired, to avoid issues with firewalls, etc.,
- * that do not allow methods other than GET or POST.
- */
-public class AndroidGDataClient implements GDataClient {
-
- private static final String TAG = "GDataClient";
- private static final boolean DEBUG = false;
- private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
-
- private static final String X_HTTP_METHOD_OVERRIDE =
- "X-HTTP-Method-Override";
-
- private static final String USER_AGENT_APP_VERSION = "Android-GData/1.0";
-
- private static final int MAX_REDIRECTS = 10;
-
- private final GoogleHttpClient mHttpClient;
- private ContentResolver mResolver;
-
- /**
- * Interface for creating HTTP requests. Used by
- * {@link AndroidGDataClient#createAndExecuteMethod}, since HttpUriRequest does not allow for
- * changing the URI after creation, e.g., when you want to follow a redirect.
- */
- private interface HttpRequestCreator {
- HttpUriRequest createRequest(URI uri);
- }
-
- private static class GetRequestCreator implements HttpRequestCreator {
- public GetRequestCreator() {
- }
-
- public HttpUriRequest createRequest(URI uri) {
- HttpGet get = new HttpGet(uri);
- return get;
- }
- }
-
- private static class PostRequestCreator implements HttpRequestCreator {
- private final String mMethodOverride;
- private final HttpEntity mEntity;
- public PostRequestCreator(String methodOverride, HttpEntity entity) {
- mMethodOverride = methodOverride;
- mEntity = entity;
- }
-
- public HttpUriRequest createRequest(URI uri) {
- HttpPost post = new HttpPost(uri);
- if (mMethodOverride != null) {
- post.addHeader(X_HTTP_METHOD_OVERRIDE, mMethodOverride);
- }
- post.setEntity(mEntity);
- return post;
- }
- }
-
- // MAJOR TODO: make this work across redirects (if we can reset the InputStream).
- // OR, read the bits into a local buffer (yuck, the media could be large).
- private static class MediaPutRequestCreator implements HttpRequestCreator {
- private final InputStream mMediaInputStream;
- private final String mContentType;
- public MediaPutRequestCreator(InputStream mediaInputStream, String contentType) {
- mMediaInputStream = mediaInputStream;
- mContentType = contentType;
- }
-
- public HttpUriRequest createRequest(URI uri) {
- HttpPost post = new HttpPost(uri);
- post.addHeader(X_HTTP_METHOD_OVERRIDE, "PUT");
- // mMediaInputStream.reset();
- InputStreamEntity entity = new InputStreamEntity(mMediaInputStream,
- -1 /* read until EOF */);
- entity.setContentType(mContentType);
- post.setEntity(entity);
- return post;
- }
- }
-
- /**
- * Creates a new AndroidGDataClient.
- *
- * @param resolver The ContentResolver to get URL rewriting rules from
- * through the Android proxy server, using null to indicate not using proxy.
- */
- public AndroidGDataClient(ContentResolver resolver) {
- mHttpClient = new GoogleHttpClient(resolver, USER_AGENT_APP_VERSION,
- true /* gzip capable */);
- mHttpClient.enableCurlLogging(TAG, Log.VERBOSE);
- mResolver = resolver;
- }
-
- public void close() {
- mHttpClient.close();
- }
-
- /*
- * (non-Javadoc)
- * @see GDataClient#encodeUri(java.lang.String)
- */
- public String encodeUri(String uri) {
- String encodedUri;
- try {
- encodedUri = URLEncoder.encode(uri, "UTF-8");
- } catch (UnsupportedEncodingException uee) {
- // should not happen.
- Log.e("JakartaGDataClient",
- "UTF-8 not supported -- should not happen. "
- + "Using default encoding.", uee);
- encodedUri = URLEncoder.encode(uri);
- }
- return encodedUri;
- }
-
- /*
- * (non-Javadoc)
- * @see com.google.wireless.gdata.client.GDataClient#createQueryParams()
- */
- public QueryParams createQueryParams() {
- return new QueryParamsImpl();
- }
-
- // follows redirects
- private InputStream createAndExecuteMethod(HttpRequestCreator creator,
- String uriString,
- String authToken)
- throws HttpException, IOException {
-
- HttpResponse response = null;
- int status = 500;
- int redirectsLeft = MAX_REDIRECTS;
-
- URI uri;
- try {
- uri = new URI(uriString);
- } catch (URISyntaxException use) {
- Log.w(TAG, "Unable to parse " + uriString + " as URI.", use);
- throw new IOException("Unable to parse " + uriString + " as URI: "
- + use.getMessage());
- }
-
- // we follow redirects ourselves, since we want to follow redirects even on POSTs, which
- // the HTTP library does not do. following redirects ourselves also allows us to log
- // the redirects using our own logging.
- while (redirectsLeft > 0) {
-
- HttpUriRequest request = creator.createRequest(uri);
-
- AndroidHttpClient.modifyRequestToAcceptGzipResponse(request);
- // only add the auth token if not null (to allow for GData feeds that do not require
- // authentication.)
- if (!TextUtils.isEmpty(authToken)) {
- request.addHeader("Authorization", "GoogleLogin auth=" + authToken);
- }
- if (LOCAL_LOGV) {
- for (Header h : request.getAllHeaders()) {
- Log.v(TAG, h.getName() + ": " + h.getValue());
- }
- }
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Executing " + request.getRequestLine().toString());
- }
-
- response = null;
-
- try {
- response = mHttpClient.execute(request);
- } catch (IOException ioe) {
- Log.w(TAG, "Unable to execute HTTP request." + ioe);
- throw ioe;
- }
-
- StatusLine statusLine = response.getStatusLine();
- if (statusLine == null) {
- Log.w(TAG, "StatusLine is null.");
- throw new NullPointerException("StatusLine is null -- should not happen.");
- }
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, response.getStatusLine().toString());
- for (Header h : response.getAllHeaders()) {
- Log.d(TAG, h.getName() + ": " + h.getValue());
- }
- }
- status = statusLine.getStatusCode();
-
- HttpEntity entity = response.getEntity();
-
- if ((status >= 200) && (status < 300) && entity != null) {
- InputStream in = AndroidHttpClient.getUngzippedContent(entity);
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- in = logInputStreamContents(in);
- }
- return in;
- }
-
- // TODO: handle 301, 307?
- // TODO: let the http client handle the redirects, if we can be sure we'll never get a
- // redirect on POST.
- if (status == 302) {
- // consume the content, so the connection can be closed.
- entity.consumeContent();
- Header location = response.getFirstHeader("Location");
- if (location == null) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Redirect requested but no Location "
- + "specified.");
- }
- break;
- }
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Following redirect to " + location.getValue());
- }
- try {
- uri = new URI(location.getValue());
- } catch (URISyntaxException use) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Unable to parse " + location.getValue() + " as URI.", use);
- throw new IOException("Unable to parse " + location.getValue()
- + " as URI.");
- }
- break;
- }
- --redirectsLeft;
- } else {
- break;
- }
- }
-
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Received " + status + " status code.");
- }
- String errorMessage = null;
- HttpEntity entity = response.getEntity();
- try {
- if (response != null && entity != null) {
- InputStream in = AndroidHttpClient.getUngzippedContent(entity);
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- byte[] buf = new byte[8192];
- int bytesRead = -1;
- while ((bytesRead = in.read(buf)) != -1) {
- baos.write(buf, 0, bytesRead);
- }
- // TODO: use appropriate encoding, picked up from Content-Type.
- errorMessage = new String(baos.toByteArray());
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, errorMessage);
- }
- }
- } finally {
- if (entity != null) {
- entity.consumeContent();
- }
- }
- String exceptionMessage = "Received " + status + " status code";
- if (errorMessage != null) {
- exceptionMessage += (": " + errorMessage);
- }
- throw new HttpException(exceptionMessage, status, null /* InputStream */);
- }
-
- /*
- * (non-Javadoc)
- * @see GDataClient#getFeedAsStream(java.lang.String, java.lang.String)
- */
- public InputStream getFeedAsStream(String feedUrl,
- String authToken)
- throws HttpException, IOException {
-
- InputStream in = createAndExecuteMethod(new GetRequestCreator(), feedUrl, authToken);
- if (in != null) {
- return in;
- }
- throw new IOException("Unable to access feed.");
- }
-
- /**
- * Log the contents of the input stream.
- * The original input stream is consumed, so the caller must use the
- * BufferedInputStream that is returned.
- * @param in InputStream
- * @return replacement input stream for caller to use
- * @throws IOException
- */
- private InputStream logInputStreamContents(InputStream in) throws IOException {
- if (in == null) {
- return in;
- }
- // bufferSize is the (arbitrary) maximum amount to log.
- // The original InputStream is wrapped in a
- // BufferedInputStream with a 16K buffer. This lets
- // us read up to 16K, write it to the log, and then
- // reset the stream so the the original client can
- // then read the data. The BufferedInputStream
- // provides the mark and reset support, even when
- // the original InputStream does not.
- final int bufferSize = 16384;
- BufferedInputStream bin = new BufferedInputStream(in, bufferSize);
- bin.mark(bufferSize);
- int wanted = bufferSize;
- int totalReceived = 0;
- byte buf[] = new byte[wanted];
- while (wanted > 0) {
- int got = bin.read(buf, totalReceived, wanted);
- if (got <= 0) break; // EOF
- wanted -= got;
- totalReceived += got;
- }
- Log.d(TAG, new String(buf, 0, totalReceived, "UTF-8"));
- bin.reset();
- return bin;
- }
-
- public InputStream getMediaEntryAsStream(String mediaEntryUrl, String authToken)
- throws HttpException, IOException {
-
- InputStream in = createAndExecuteMethod(new GetRequestCreator(), mediaEntryUrl, authToken);
-
- if (in != null) {
- return in;
- }
- throw new IOException("Unable to access media entry.");
- }
-
- /* (non-Javadoc)
- * @see GDataClient#createEntry
- */
- public InputStream createEntry(String feedUrl,
- String authToken,
- GDataSerializer entry)
- throws HttpException, IOException {
-
- HttpEntity entity = createEntityForEntry(entry, GDataSerializer.FORMAT_CREATE);
- InputStream in = createAndExecuteMethod(
- new PostRequestCreator(null /* override */, entity),
- feedUrl,
- authToken);
- if (in != null) {
- return in;
- }
- throw new IOException("Unable to create entry.");
- }
-
- /* (non-Javadoc)
- * @see GDataClient#updateEntry
- */
- public InputStream updateEntry(String editUri,
- String authToken,
- GDataSerializer entry)
- throws HttpException, IOException {
- HttpEntity entity = createEntityForEntry(entry, GDataSerializer.FORMAT_UPDATE);
- InputStream in = createAndExecuteMethod(
- new PostRequestCreator("PUT", entity),
- editUri,
- authToken);
- if (in != null) {
- return in;
- }
- throw new IOException("Unable to update entry.");
- }
-
- /* (non-Javadoc)
- * @see GDataClient#deleteEntry
- */
- public void deleteEntry(String editUri, String authToken)
- throws HttpException, IOException {
- if (StringUtils.isEmpty(editUri)) {
- throw new IllegalArgumentException(
- "you must specify an non-empty edit url");
- }
- InputStream in =
- createAndExecuteMethod(
- new PostRequestCreator("DELETE", null /* entity */),
- editUri,
- authToken);
- if (in == null) {
- throw new IOException("Unable to delete entry.");
- }
- try {
- in.close();
- } catch (IOException ioe) {
- // ignore
- }
- }
-
- public InputStream updateMediaEntry(String editUri, String authToken,
- InputStream mediaEntryInputStream, String contentType)
- throws HttpException, IOException {
- InputStream in = createAndExecuteMethod(
- new MediaPutRequestCreator(mediaEntryInputStream, contentType),
- editUri,
- authToken);
- if (in != null) {
- return in;
- }
- throw new IOException("Unable to write media entry.");
- }
-
- private HttpEntity createEntityForEntry(GDataSerializer entry, int format) throws IOException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- try {
- entry.serialize(baos, format);
- } catch (IOException ioe) {
- Log.e(TAG, "Unable to serialize entry.", ioe);
- throw ioe;
- } catch (ParseException pe) {
- Log.e(TAG, "Unable to serialize entry.", pe);
- throw new IOException("Unable to serialize entry: " + pe.getMessage());
- }
-
- byte[] entryBytes = baos.toByteArray();
-
- if (entryBytes != null && Log.isLoggable(TAG, Log.DEBUG)) {
- try {
- Log.d(TAG, "Serialized entry: " + new String(entryBytes, "UTF-8"));
- } catch (UnsupportedEncodingException uee) {
- // should not happen
- throw new IllegalStateException("UTF-8 should be supported!",
- uee);
- }
- }
-
- AbstractHttpEntity entity = AndroidHttpClient.getCompressedEntity(entryBytes, mResolver);
- entity.setContentType(entry.getContentType());
- return entity;
- }
-}
diff --git a/core/java/com/google/android/gdata/client/AndroidXmlParserFactory.java b/core/java/com/google/android/gdata/client/AndroidXmlParserFactory.java
deleted file mode 100644
index a308fc0..0000000
--- a/core/java/com/google/android/gdata/client/AndroidXmlParserFactory.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.google.android.gdata.client;
-
-import com.google.wireless.gdata.parser.xml.XmlParserFactory;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import android.util.Xml;
-
-/**
- * XmlParserFactory for the Android platform.
- */
-public class AndroidXmlParserFactory implements XmlParserFactory {
-
- /*
- * (non-javadoc)
- * @see XmlParserFactory#createParser
- */
- public XmlPullParser createParser() throws XmlPullParserException {
- return Xml.newPullParser();
- }
-
- /*
- * (non-javadoc)
- * @see XmlParserFactory#createSerializer
- */
- public XmlSerializer createSerializer() throws XmlPullParserException {
- return Xml.newSerializer();
- }
-}
diff --git a/core/java/com/google/android/gdata/client/QueryParamsImpl.java b/core/java/com/google/android/gdata/client/QueryParamsImpl.java
deleted file mode 100644
index e27b36f..0000000
--- a/core/java/com/google/android/gdata/client/QueryParamsImpl.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.google.android.gdata.client;
-
-import com.google.wireless.gdata.client.QueryParams;
-
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Simple implementation of the QueryParams interface.
- */
-// TODO: deal with categories
-public class QueryParamsImpl extends QueryParams {
-
- private final Map<String,String> mParams = new HashMap<String,String>();
-
- /**
- * Creates a new empty QueryParamsImpl.
- */
- public QueryParamsImpl() {
- }
-
- @Override
- public void clear() {
- setEntryId(null);
- mParams.clear();
- }
-
- @Override
- public String generateQueryUrl(String feedUrl) {
-
- if (TextUtils.isEmpty(getEntryId()) &&
- mParams.isEmpty()) {
- // nothing to do
- return feedUrl;
- }
-
- // handle entry IDs
- if (!TextUtils.isEmpty(getEntryId())) {
- if (!mParams.isEmpty()) {
- throw new IllegalStateException("Cannot set both an entry ID "
- + "and other query paramters.");
- }
- return feedUrl + '/' + getEntryId();
- }
-
- // otherwise, append the querystring params.
- StringBuilder sb = new StringBuilder();
- sb.append(feedUrl);
- Set<String> params = mParams.keySet();
- boolean first = true;
- if (feedUrl.contains("?")) {
- first = false;
- } else {
- sb.append('?');
- }
- for (String param : params) {
- if (first) {
- first = false;
- } else {
- sb.append('&');
- }
- sb.append(param);
- sb.append('=');
- String value = mParams.get(param);
- String encodedValue = null;
-
- try {
- encodedValue = URLEncoder.encode(value, "UTF-8");
- } catch (UnsupportedEncodingException uee) {
- // should not happen.
- Log.w("QueryParamsImpl",
- "UTF-8 not supported -- should not happen. "
- + "Using default encoding.", uee);
- encodedValue = URLEncoder.encode(value);
- }
- sb.append(encodedValue);
- }
- return sb.toString();
- }
-
- @Override
- public String getParamValue(String param) {
- if (!(mParams.containsKey(param))) {
- return null;
- }
- return mParams.get(param);
- }
-
- @Override
- public void setParamValue(String param, String value) {
- mParams.put(param, value);
- }
-
-}
diff --git a/core/java/com/google/android/mms/ContentType.java b/core/java/com/google/android/mms/ContentType.java
deleted file mode 100644
index 94bc9fd..0000000
--- a/core/java/com/google/android/mms/ContentType.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2007-2008 Esmertec AG.
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms;
-
-import java.util.ArrayList;
-
-public class ContentType {
- public static final String MMS_MESSAGE = "application/vnd.wap.mms-message";
- // The phony content type for generic PDUs (e.g. ReadOrig.ind,
- // Notification.ind, Delivery.ind).
- public static final String MMS_GENERIC = "application/vnd.wap.mms-generic";
- public static final String MULTIPART_MIXED = "application/vnd.wap.multipart.mixed";
- public static final String MULTIPART_RELATED = "application/vnd.wap.multipart.related";
-
- public static final String TEXT_PLAIN = "text/plain";
- public static final String TEXT_HTML = "text/html";
- public static final String TEXT_VCALENDAR = "text/x-vCalendar";
- public static final String TEXT_VCARD = "text/x-vCard";
-
- public static final String IMAGE_UNSPECIFIED = "image/*";
- public static final String IMAGE_JPEG = "image/jpeg";
- public static final String IMAGE_JPG = "image/jpg";
- public static final String IMAGE_GIF = "image/gif";
- public static final String IMAGE_WBMP = "image/vnd.wap.wbmp";
- public static final String IMAGE_PNG = "image/png";
-
- public static final String AUDIO_UNSPECIFIED = "audio/*";
- public static final String AUDIO_AAC = "audio/aac";
- public static final String AUDIO_AMR = "audio/amr";
- public static final String AUDIO_IMELODY = "audio/imelody";
- public static final String AUDIO_MID = "audio/mid";
- public static final String AUDIO_MIDI = "audio/midi";
- public static final String AUDIO_MP3 = "audio/mp3";
- public static final String AUDIO_MPEG3 = "audio/mpeg3";
- public static final String AUDIO_MPEG = "audio/mpeg";
- public static final String AUDIO_MPG = "audio/mpg";
- public static final String AUDIO_MP4 = "audio/mp4";
- public static final String AUDIO_X_MID = "audio/x-mid";
- public static final String AUDIO_X_MIDI = "audio/x-midi";
- public static final String AUDIO_X_MP3 = "audio/x-mp3";
- public static final String AUDIO_X_MPEG3 = "audio/x-mpeg3";
- public static final String AUDIO_X_MPEG = "audio/x-mpeg";
- public static final String AUDIO_X_MPG = "audio/x-mpg";
- public static final String AUDIO_3GPP = "audio/3gpp";
- public static final String AUDIO_OGG = "application/ogg";
-
- public static final String VIDEO_UNSPECIFIED = "video/*";
- public static final String VIDEO_3GPP = "video/3gpp";
- public static final String VIDEO_3G2 = "video/3gpp2";
- public static final String VIDEO_H263 = "video/h263";
- public static final String VIDEO_MP4 = "video/mp4";
-
- public static final String APP_SMIL = "application/smil";
- public static final String APP_WAP_XHTML = "application/vnd.wap.xhtml+xml";
- public static final String APP_XHTML = "application/xhtml+xml";
-
- public static final String APP_DRM_CONTENT = "application/vnd.oma.drm.content";
- public static final String APP_DRM_MESSAGE = "application/vnd.oma.drm.message";
-
- private static final ArrayList<String> sSupportedContentTypes = new ArrayList<String>();
- private static final ArrayList<String> sSupportedImageTypes = new ArrayList<String>();
- private static final ArrayList<String> sSupportedAudioTypes = new ArrayList<String>();
- private static final ArrayList<String> sSupportedVideoTypes = new ArrayList<String>();
-
- static {
- sSupportedContentTypes.add(TEXT_PLAIN);
- sSupportedContentTypes.add(TEXT_HTML);
- sSupportedContentTypes.add(TEXT_VCALENDAR);
- sSupportedContentTypes.add(TEXT_VCARD);
-
- sSupportedContentTypes.add(IMAGE_JPEG);
- sSupportedContentTypes.add(IMAGE_GIF);
- sSupportedContentTypes.add(IMAGE_WBMP);
- sSupportedContentTypes.add(IMAGE_PNG);
- sSupportedContentTypes.add(IMAGE_JPG);
- //supportedContentTypes.add(IMAGE_SVG); not yet supported.
-
- sSupportedContentTypes.add(AUDIO_AAC);
- sSupportedContentTypes.add(AUDIO_AMR);
- sSupportedContentTypes.add(AUDIO_IMELODY);
- sSupportedContentTypes.add(AUDIO_MID);
- sSupportedContentTypes.add(AUDIO_MIDI);
- sSupportedContentTypes.add(AUDIO_MP3);
- sSupportedContentTypes.add(AUDIO_MPEG3);
- sSupportedContentTypes.add(AUDIO_MPEG);
- sSupportedContentTypes.add(AUDIO_MPG);
- sSupportedContentTypes.add(AUDIO_X_MID);
- sSupportedContentTypes.add(AUDIO_X_MIDI);
- sSupportedContentTypes.add(AUDIO_X_MP3);
- sSupportedContentTypes.add(AUDIO_X_MPEG3);
- sSupportedContentTypes.add(AUDIO_X_MPEG);
- sSupportedContentTypes.add(AUDIO_X_MPG);
- sSupportedContentTypes.add(AUDIO_3GPP);
- sSupportedContentTypes.add(AUDIO_OGG);
-
- sSupportedContentTypes.add(VIDEO_3GPP);
- sSupportedContentTypes.add(VIDEO_3G2);
- sSupportedContentTypes.add(VIDEO_H263);
- sSupportedContentTypes.add(VIDEO_MP4);
-
- sSupportedContentTypes.add(APP_SMIL);
- sSupportedContentTypes.add(APP_WAP_XHTML);
- sSupportedContentTypes.add(APP_XHTML);
-
- sSupportedContentTypes.add(APP_DRM_CONTENT);
- sSupportedContentTypes.add(APP_DRM_MESSAGE);
-
- // add supported image types
- sSupportedImageTypes.add(IMAGE_JPEG);
- sSupportedImageTypes.add(IMAGE_GIF);
- sSupportedImageTypes.add(IMAGE_WBMP);
- sSupportedImageTypes.add(IMAGE_PNG);
- sSupportedImageTypes.add(IMAGE_JPG);
-
- // add supported audio types
- sSupportedAudioTypes.add(AUDIO_AAC);
- sSupportedAudioTypes.add(AUDIO_AMR);
- sSupportedAudioTypes.add(AUDIO_IMELODY);
- sSupportedAudioTypes.add(AUDIO_MID);
- sSupportedAudioTypes.add(AUDIO_MIDI);
- sSupportedAudioTypes.add(AUDIO_MP3);
- sSupportedAudioTypes.add(AUDIO_MPEG3);
- sSupportedAudioTypes.add(AUDIO_MPEG);
- sSupportedAudioTypes.add(AUDIO_MPG);
- sSupportedAudioTypes.add(AUDIO_MP4);
- sSupportedAudioTypes.add(AUDIO_X_MID);
- sSupportedAudioTypes.add(AUDIO_X_MIDI);
- sSupportedAudioTypes.add(AUDIO_X_MP3);
- sSupportedAudioTypes.add(AUDIO_X_MPEG3);
- sSupportedAudioTypes.add(AUDIO_X_MPEG);
- sSupportedAudioTypes.add(AUDIO_X_MPG);
- sSupportedAudioTypes.add(AUDIO_3GPP);
- sSupportedAudioTypes.add(AUDIO_OGG);
-
- // add supported video types
- sSupportedVideoTypes.add(VIDEO_3GPP);
- sSupportedVideoTypes.add(VIDEO_3G2);
- sSupportedVideoTypes.add(VIDEO_H263);
- sSupportedVideoTypes.add(VIDEO_MP4);
- }
-
- // This class should never be instantiated.
- private ContentType() {
- }
-
- public static boolean isSupportedType(String contentType) {
- return (null != contentType) && sSupportedContentTypes.contains(contentType);
- }
-
- public static boolean isSupportedImageType(String contentType) {
- return isImageType(contentType) && isSupportedType(contentType);
- }
-
- public static boolean isSupportedAudioType(String contentType) {
- return isAudioType(contentType) && isSupportedType(contentType);
- }
-
- public static boolean isSupportedVideoType(String contentType) {
- return isVideoType(contentType) && isSupportedType(contentType);
- }
-
- public static boolean isTextType(String contentType) {
- return (null != contentType) && contentType.startsWith("text/");
- }
-
- public static boolean isImageType(String contentType) {
- return (null != contentType) && contentType.startsWith("image/");
- }
-
- public static boolean isAudioType(String contentType) {
- return (null != contentType) && contentType.startsWith("audio/");
- }
-
- public static boolean isVideoType(String contentType) {
- return (null != contentType) && contentType.startsWith("video/");
- }
-
- public static boolean isDrmType(String contentType) {
- return (null != contentType)
- && (contentType.equals(APP_DRM_CONTENT)
- || contentType.equals(APP_DRM_MESSAGE));
- }
-
- public static boolean isUnspecified(String contentType) {
- return (null != contentType) && contentType.endsWith("*");
- }
-
- @SuppressWarnings("unchecked")
- public static ArrayList<String> getImageTypes() {
- return (ArrayList<String>) sSupportedImageTypes.clone();
- }
-
- @SuppressWarnings("unchecked")
- public static ArrayList<String> getAudioTypes() {
- return (ArrayList<String>) sSupportedAudioTypes.clone();
- }
-
- @SuppressWarnings("unchecked")
- public static ArrayList<String> getVideoTypes() {
- return (ArrayList<String>) sSupportedVideoTypes.clone();
- }
-
- @SuppressWarnings("unchecked")
- public static ArrayList<String> getSupportedTypes() {
- return (ArrayList<String>) sSupportedContentTypes.clone();
- }
-}
diff --git a/core/java/com/google/android/mms/InvalidHeaderValueException.java b/core/java/com/google/android/mms/InvalidHeaderValueException.java
deleted file mode 100644
index 73d7832..0000000
--- a/core/java/com/google/android/mms/InvalidHeaderValueException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms;
-
-/**
- * Thrown when an invalid header value was set.
- */
-public class InvalidHeaderValueException extends MmsException {
- private static final long serialVersionUID = -2053384496042052262L;
-
- /**
- * Constructs an InvalidHeaderValueException with no detailed message.
- */
- public InvalidHeaderValueException() {
- super();
- }
-
- /**
- * Constructs an InvalidHeaderValueException with the specified detailed message.
- *
- * @param message the detailed message.
- */
- public InvalidHeaderValueException(String message) {
- super(message);
- }
-}
diff --git a/core/java/com/google/android/mms/MmsException.java b/core/java/com/google/android/mms/MmsException.java
deleted file mode 100644
index 6ca0c7e..0000000
--- a/core/java/com/google/android/mms/MmsException.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms;
-
-/**
- * A generic exception that is thrown by the Mms client.
- */
-public class MmsException extends Exception {
- private static final long serialVersionUID = -7323249827281485390L;
-
- /**
- * Creates a new MmsException.
- */
- public MmsException() {
- super();
- }
-
- /**
- * Creates a new MmsException with the specified detail message.
- *
- * @param message the detail message.
- */
- public MmsException(String message) {
- super(message);
- }
-
- /**
- * Creates a new MmsException with the specified cause.
- *
- * @param cause the cause.
- */
- public MmsException(Throwable cause) {
- super(cause);
- }
-
- /**
- * Creates a new MmsException with the specified detail message and cause.
- *
- * @param message the detail message.
- * @param cause the cause.
- */
- public MmsException(String message, Throwable cause) {
- super(message, cause);
- }
-}
diff --git a/core/java/com/google/android/mms/package.html b/core/java/com/google/android/mms/package.html
deleted file mode 100755
index c9f96a6..0000000
--- a/core/java/com/google/android/mms/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>
diff --git a/core/java/com/google/android/mms/pdu/AcknowledgeInd.java b/core/java/com/google/android/mms/pdu/AcknowledgeInd.java
deleted file mode 100644
index 0e96c60..0000000
--- a/core/java/com/google/android/mms/pdu/AcknowledgeInd.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import com.google.android.mms.InvalidHeaderValueException;
-
-/**
- * M-Acknowledge.ind PDU.
- */
-public class AcknowledgeInd extends GenericPdu {
- /**
- * Constructor, used when composing a M-Acknowledge.ind pdu.
- *
- * @param mmsVersion current viersion of mms
- * @param transactionId the transaction-id value
- * @throws InvalidHeaderValueException if parameters are invalid.
- * NullPointerException if transactionId is null.
- */
- public AcknowledgeInd(int mmsVersion, byte[] transactionId)
- throws InvalidHeaderValueException {
- super();
-
- setMessageType(PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND);
- setMmsVersion(mmsVersion);
- setTransactionId(transactionId);
- }
-
- /**
- * Constructor with given headers.
- *
- * @param headers Headers for this PDU.
- */
- AcknowledgeInd(PduHeaders headers) {
- super(headers);
- }
-
- /**
- * Get X-Mms-Report-Allowed field value.
- *
- * @return the X-Mms-Report-Allowed value
- */
- public int getReportAllowed() {
- return mPduHeaders.getOctet(PduHeaders.REPORT_ALLOWED);
- }
-
- /**
- * Set X-Mms-Report-Allowed field value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- */
- public void setReportAllowed(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.REPORT_ALLOWED);
- }
-
- /**
- * Get X-Mms-Transaction-Id field value.
- *
- * @return the X-Mms-Report-Allowed value
- */
- public byte[] getTransactionId() {
- return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
- }
-
- /**
- * Set X-Mms-Transaction-Id field value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setTransactionId(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
- }
-}
diff --git a/core/java/com/google/android/mms/pdu/Base64.java b/core/java/com/google/android/mms/pdu/Base64.java
deleted file mode 100644
index 604bee0..0000000
--- a/core/java/com/google/android/mms/pdu/Base64.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-public class Base64 {
- /**
- * Used to get the number of Quadruples.
- */
- static final int FOURBYTE = 4;
-
- /**
- * Byte used to pad output.
- */
- static final byte PAD = (byte) '=';
-
- /**
- * The base length.
- */
- static final int BASELENGTH = 255;
-
- // Create arrays to hold the base64 characters
- private static byte[] base64Alphabet = new byte[BASELENGTH];
-
- // Populating the character arrays
- static {
- for (int i = 0; i < BASELENGTH; i++) {
- base64Alphabet[i] = (byte) -1;
- }
- for (int i = 'Z'; i >= 'A'; i--) {
- base64Alphabet[i] = (byte) (i - 'A');
- }
- for (int i = 'z'; i >= 'a'; i--) {
- base64Alphabet[i] = (byte) (i - 'a' + 26);
- }
- for (int i = '9'; i >= '0'; i--) {
- base64Alphabet[i] = (byte) (i - '0' + 52);
- }
-
- base64Alphabet['+'] = 62;
- base64Alphabet['/'] = 63;
- }
-
- /**
- * Decodes Base64 data into octects
- *
- * @param base64Data Byte array containing Base64 data
- * @return Array containing decoded data.
- */
- public static byte[] decodeBase64(byte[] base64Data) {
- // RFC 2045 requires that we discard ALL non-Base64 characters
- base64Data = discardNonBase64(base64Data);
-
- // handle the edge case, so we don't have to worry about it later
- if (base64Data.length == 0) {
- return new byte[0];
- }
-
- int numberQuadruple = base64Data.length / FOURBYTE;
- byte decodedData[] = null;
- byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0;
-
- // Throw away anything not in base64Data
-
- int encodedIndex = 0;
- int dataIndex = 0;
- {
- // this sizes the output array properly - rlw
- int lastData = base64Data.length;
- // ignore the '=' padding
- while (base64Data[lastData - 1] == PAD) {
- if (--lastData == 0) {
- return new byte[0];
- }
- }
- decodedData = new byte[lastData - numberQuadruple];
- }
-
- for (int i = 0; i < numberQuadruple; i++) {
- dataIndex = i * 4;
- marker0 = base64Data[dataIndex + 2];
- marker1 = base64Data[dataIndex + 3];
-
- b1 = base64Alphabet[base64Data[dataIndex]];
- b2 = base64Alphabet[base64Data[dataIndex + 1]];
-
- if (marker0 != PAD && marker1 != PAD) {
- //No PAD e.g 3cQl
- b3 = base64Alphabet[marker0];
- b4 = base64Alphabet[marker1];
-
- decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
- decodedData[encodedIndex + 1] =
- (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
- decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4);
- } else if (marker0 == PAD) {
- //Two PAD e.g. 3c[Pad][Pad]
- decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
- } else if (marker1 == PAD) {
- //One PAD e.g. 3cQ[Pad]
- b3 = base64Alphabet[marker0];
-
- decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
- decodedData[encodedIndex + 1] =
- (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
- }
- encodedIndex += 3;
- }
- return decodedData;
- }
-
- /**
- * Check octect wheter it is a base64 encoding.
- *
- * @param octect to be checked byte
- * @return ture if it is base64 encoding, false otherwise.
- */
- private static boolean isBase64(byte octect) {
- if (octect == PAD) {
- return true;
- } else if (base64Alphabet[octect] == -1) {
- return false;
- } else {
- return true;
- }
- }
-
- /**
- * Discards any characters outside of the base64 alphabet, per
- * the requirements on page 25 of RFC 2045 - "Any characters
- * outside of the base64 alphabet are to be ignored in base64
- * encoded data."
- *
- * @param data The base-64 encoded data to groom
- * @return The data, less non-base64 characters (see RFC 2045).
- */
- static byte[] discardNonBase64(byte[] data) {
- byte groomedData[] = new byte[data.length];
- int bytesCopied = 0;
-
- for (int i = 0; i < data.length; i++) {
- if (isBase64(data[i])) {
- groomedData[bytesCopied++] = data[i];
- }
- }
-
- byte packedData[] = new byte[bytesCopied];
-
- System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
-
- return packedData;
- }
-}
diff --git a/core/java/com/google/android/mms/pdu/CharacterSets.java b/core/java/com/google/android/mms/pdu/CharacterSets.java
deleted file mode 100644
index 4e22ca5..0000000
--- a/core/java/com/google/android/mms/pdu/CharacterSets.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import java.io.UnsupportedEncodingException;
-import java.util.HashMap;
-
-public class CharacterSets {
- /**
- * IANA assigned MIB enum numbers.
- *
- * From wap-230-wsp-20010705-a.pdf
- * Any-charset = <Octet 128>
- * Equivalent to the special RFC2616 charset value "*"
- */
- public static final int ANY_CHARSET = 0x00;
- public static final int US_ASCII = 0x03;
- public static final int ISO_8859_1 = 0x04;
- public static final int ISO_8859_2 = 0x05;
- public static final int ISO_8859_3 = 0x06;
- public static final int ISO_8859_4 = 0x07;
- public static final int ISO_8859_5 = 0x08;
- public static final int ISO_8859_6 = 0x09;
- public static final int ISO_8859_7 = 0x0A;
- public static final int ISO_8859_8 = 0x0B;
- public static final int ISO_8859_9 = 0x0C;
- public static final int SHIFT_JIS = 0x11;
- public static final int UTF_8 = 0x6A;
- public static final int BIG5 = 0x07EA;
- public static final int UCS2 = 0x03E8;
- public static final int UTF_16 = 0x03F7;
-
- /**
- * If the encoding of given data is unsupported, use UTF_8 to decode it.
- */
- public static final int DEFAULT_CHARSET = UTF_8;
-
- /**
- * Array of MIB enum numbers.
- */
- private static final int[] MIBENUM_NUMBERS = {
- ANY_CHARSET,
- US_ASCII,
- ISO_8859_1,
- ISO_8859_2,
- ISO_8859_3,
- ISO_8859_4,
- ISO_8859_5,
- ISO_8859_6,
- ISO_8859_7,
- ISO_8859_8,
- ISO_8859_9,
- SHIFT_JIS,
- UTF_8,
- BIG5,
- UCS2,
- UTF_16,
- };
-
- /**
- * The Well-known-charset Mime name.
- */
- public static final String MIMENAME_ANY_CHARSET = "*";
- public static final String MIMENAME_US_ASCII = "us-ascii";
- public static final String MIMENAME_ISO_8859_1 = "iso-8859-1";
- public static final String MIMENAME_ISO_8859_2 = "iso-8859-2";
- public static final String MIMENAME_ISO_8859_3 = "iso-8859-3";
- public static final String MIMENAME_ISO_8859_4 = "iso-8859-4";
- public static final String MIMENAME_ISO_8859_5 = "iso-8859-5";
- public static final String MIMENAME_ISO_8859_6 = "iso-8859-6";
- public static final String MIMENAME_ISO_8859_7 = "iso-8859-7";
- public static final String MIMENAME_ISO_8859_8 = "iso-8859-8";
- public static final String MIMENAME_ISO_8859_9 = "iso-8859-9";
- public static final String MIMENAME_SHIFT_JIS = "shift_JIS";
- public static final String MIMENAME_UTF_8 = "utf-8";
- public static final String MIMENAME_BIG5 = "big5";
- public static final String MIMENAME_UCS2 = "iso-10646-ucs-2";
- public static final String MIMENAME_UTF_16 = "utf-16";
-
- public static final String DEFAULT_CHARSET_NAME = MIMENAME_UTF_8;
-
- /**
- * Array of the names of character sets.
- */
- private static final String[] MIME_NAMES = {
- MIMENAME_ANY_CHARSET,
- MIMENAME_US_ASCII,
- MIMENAME_ISO_8859_1,
- MIMENAME_ISO_8859_2,
- MIMENAME_ISO_8859_3,
- MIMENAME_ISO_8859_4,
- MIMENAME_ISO_8859_5,
- MIMENAME_ISO_8859_6,
- MIMENAME_ISO_8859_7,
- MIMENAME_ISO_8859_8,
- MIMENAME_ISO_8859_9,
- MIMENAME_SHIFT_JIS,
- MIMENAME_UTF_8,
- MIMENAME_BIG5,
- MIMENAME_UCS2,
- MIMENAME_UTF_16,
- };
-
- private static final HashMap<Integer, String> MIBENUM_TO_NAME_MAP;
- private static final HashMap<String, Integer> NAME_TO_MIBENUM_MAP;
-
- static {
- // Create the HashMaps.
- MIBENUM_TO_NAME_MAP = new HashMap<Integer, String>();
- NAME_TO_MIBENUM_MAP = new HashMap<String, Integer>();
- assert(MIBENUM_NUMBERS.length == MIME_NAMES.length);
- int count = MIBENUM_NUMBERS.length - 1;
- for(int i = 0; i <= count; i++) {
- MIBENUM_TO_NAME_MAP.put(MIBENUM_NUMBERS[i], MIME_NAMES[i]);
- NAME_TO_MIBENUM_MAP.put(MIME_NAMES[i], MIBENUM_NUMBERS[i]);
- }
- }
-
- private CharacterSets() {} // Non-instantiatable
-
- /**
- * Map an MIBEnum number to the name of the charset which this number
- * is assigned to by IANA.
- *
- * @param mibEnumValue An IANA assigned MIBEnum number.
- * @return The name string of the charset.
- * @throws UnsupportedEncodingException
- */
- public static String getMimeName(int mibEnumValue)
- throws UnsupportedEncodingException {
- String name = MIBENUM_TO_NAME_MAP.get(mibEnumValue);
- if (name == null) {
- throw new UnsupportedEncodingException();
- }
- return name;
- }
-
- /**
- * Map a well-known charset name to its assigned MIBEnum number.
- *
- * @param mimeName The charset name.
- * @return The MIBEnum number assigned by IANA for this charset.
- * @throws UnsupportedEncodingException
- */
- public static int getMibEnumValue(String mimeName)
- throws UnsupportedEncodingException {
- if(null == mimeName) {
- return -1;
- }
-
- Integer mibEnumValue = NAME_TO_MIBENUM_MAP.get(mimeName);
- if (mibEnumValue == null) {
- throw new UnsupportedEncodingException();
- }
- return mibEnumValue;
- }
-}
diff --git a/core/java/com/google/android/mms/pdu/DeliveryInd.java b/core/java/com/google/android/mms/pdu/DeliveryInd.java
deleted file mode 100644
index dafa8d1..0000000
--- a/core/java/com/google/android/mms/pdu/DeliveryInd.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import com.google.android.mms.InvalidHeaderValueException;
-
-/**
- * M-Delivery.Ind Pdu.
- */
-public class DeliveryInd extends GenericPdu {
- /**
- * Empty constructor.
- * Since the Pdu corresponding to this class is constructed
- * by the Proxy-Relay server, this class is only instantiated
- * by the Pdu Parser.
- *
- * @throws InvalidHeaderValueException if error occurs.
- */
- public DeliveryInd() throws InvalidHeaderValueException {
- super();
- setMessageType(PduHeaders.MESSAGE_TYPE_DELIVERY_IND);
- }
-
- /**
- * Constructor with given headers.
- *
- * @param headers Headers for this PDU.
- */
- DeliveryInd(PduHeaders headers) {
- super(headers);
- }
-
- /**
- * Get Date value.
- *
- * @return the value
- */
- public long getDate() {
- return mPduHeaders.getLongInteger(PduHeaders.DATE);
- }
-
- /**
- * Set Date value.
- *
- * @param value the value
- */
- public void setDate(long value) {
- mPduHeaders.setLongInteger(value, PduHeaders.DATE);
- }
-
- /**
- * Get Message-ID value.
- *
- * @return the value
- */
- public byte[] getMessageId() {
- return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
- }
-
- /**
- * Set Message-ID value.
- *
- * @param value the value, should not be null
- * @throws NullPointerException if the value is null.
- */
- public void setMessageId(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
- }
-
- /**
- * Get Status value.
- *
- * @return the value
- */
- public int getStatus() {
- return mPduHeaders.getOctet(PduHeaders.STATUS);
- }
-
- /**
- * Set Status value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- */
- public void setStatus(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.STATUS);
- }
-
- /**
- * Get To value.
- *
- * @return the value
- */
- public EncodedStringValue[] getTo() {
- return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
- }
-
- /**
- * set To value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setTo(EncodedStringValue[] value) {
- mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
- }
-
- /*
- * Optional, not supported header fields:
- *
- * public byte[] getApplicId() {return null;}
- * public void setApplicId(byte[] value) {}
- *
- * public byte[] getAuxApplicId() {return null;}
- * public void getAuxApplicId(byte[] value) {}
- *
- * public byte[] getReplyApplicId() {return 0x00;}
- * public void setReplyApplicId(byte[] value) {}
- *
- * public EncodedStringValue getStatusText() {return null;}
- * public void setStatusText(EncodedStringValue value) {}
- */
-}
diff --git a/core/java/com/google/android/mms/pdu/EncodedStringValue.java b/core/java/com/google/android/mms/pdu/EncodedStringValue.java
deleted file mode 100644
index 7696c5e..0000000
--- a/core/java/com/google/android/mms/pdu/EncodedStringValue.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (C) 2007-2008 Esmertec AG.
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import android.util.Config;
-import android.util.Log;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-
-/**
- * Encoded-string-value = Text-string | Value-length Char-set Text-string
- */
-public class EncodedStringValue implements Cloneable {
- private static final String TAG = "EncodedStringValue";
- private static final boolean DEBUG = false;
- private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
-
- /**
- * The Char-set value.
- */
- private int mCharacterSet;
-
- /**
- * The Text-string value.
- */
- private byte[] mData;
-
- /**
- * Constructor.
- *
- * @param charset the Char-set value
- * @param data the Text-string value
- * @throws NullPointerException if Text-string value is null.
- */
- public EncodedStringValue(int charset, byte[] data) {
- // TODO: CharSet needs to be validated against MIBEnum.
- if(null == data) {
- throw new NullPointerException("EncodedStringValue: Text-string is null.");
- }
-
- mCharacterSet = charset;
- mData = new byte[data.length];
- System.arraycopy(data, 0, mData, 0, data.length);
- }
-
- /**
- * Constructor.
- *
- * @param data the Text-string value
- * @throws NullPointerException if Text-string value is null.
- */
- public EncodedStringValue(byte[] data) {
- this(CharacterSets.DEFAULT_CHARSET, data);
- }
-
- public EncodedStringValue(String data) {
- try {
- mData = data.getBytes(CharacterSets.DEFAULT_CHARSET_NAME);
- mCharacterSet = CharacterSets.DEFAULT_CHARSET;
- } catch (UnsupportedEncodingException e) {
- Log.e(TAG, "Default encoding must be supported.", e);
- }
- }
-
- /**
- * Get Char-set value.
- *
- * @return the value
- */
- public int getCharacterSet() {
- return mCharacterSet;
- }
-
- /**
- * Set Char-set value.
- *
- * @param charset the Char-set value
- */
- public void setCharacterSet(int charset) {
- // TODO: CharSet needs to be validated against MIBEnum.
- mCharacterSet = charset;
- }
-
- /**
- * Get Text-string value.
- *
- * @return the value
- */
- public byte[] getTextString() {
- byte[] byteArray = new byte[mData.length];
-
- System.arraycopy(mData, 0, byteArray, 0, mData.length);
- return byteArray;
- }
-
- /**
- * Set Text-string value.
- *
- * @param textString the Text-string value
- * @throws NullPointerException if Text-string value is null.
- */
- public void setTextString(byte[] textString) {
- if(null == textString) {
- throw new NullPointerException("EncodedStringValue: Text-string is null.");
- }
-
- mData = new byte[textString.length];
- System.arraycopy(textString, 0, mData, 0, textString.length);
- }
-
- /**
- * Convert this object to a {@link java.lang.String}. If the encoding of
- * the EncodedStringValue is null or unsupported, it will be
- * treated as iso-8859-1 encoding.
- *
- * @return The decoded String.
- */
- public String getString() {
- if (CharacterSets.ANY_CHARSET == mCharacterSet) {
- return new String(mData); // system default encoding.
- } else {
- try {
- String name = CharacterSets.getMimeName(mCharacterSet);
- return new String(mData, name);
- } catch (UnsupportedEncodingException e) {
- if (LOCAL_LOGV) {
- Log.v(TAG, e.getMessage(), e);
- }
- try {
- return new String(mData, CharacterSets.MIMENAME_ISO_8859_1);
- } catch (UnsupportedEncodingException _) {
- return new String(mData); // system default encoding.
- }
- }
- }
- }
-
- /**
- * Append to Text-string.
- *
- * @param textString the textString to append
- * @throws NullPointerException if the text String is null
- * or an IOException occured.
- */
- public void appendTextString(byte[] textString) {
- if(null == textString) {
- throw new NullPointerException("Text-string is null.");
- }
-
- if(null == mData) {
- mData = new byte[textString.length];
- System.arraycopy(textString, 0, mData, 0, textString.length);
- } else {
- ByteArrayOutputStream newTextString = new ByteArrayOutputStream();
- try {
- newTextString.write(mData);
- newTextString.write(textString);
- } catch (IOException e) {
- e.printStackTrace();
- throw new NullPointerException(
- "appendTextString: failed when write a new Text-string");
- }
-
- mData = newTextString.toByteArray();
- }
- }
-
- /*
- * (non-Javadoc)
- * @see java.lang.Object#clone()
- */
- @Override
- public Object clone() throws CloneNotSupportedException {
- super.clone();
- int len = mData.length;
- byte[] dstBytes = new byte[len];
- System.arraycopy(mData, 0, dstBytes, 0, len);
-
- try {
- return new EncodedStringValue(mCharacterSet, dstBytes);
- } catch (Exception e) {
- Log.e(TAG, "failed to clone an EncodedStringValue: " + this);
- e.printStackTrace();
- throw new CloneNotSupportedException(e.getMessage());
- }
- }
-
- /**
- * Split this encoded string around matches of the given pattern.
- *
- * @param pattern the delimiting pattern
- * @return the array of encoded strings computed by splitting this encoded
- * string around matches of the given pattern
- */
- public EncodedStringValue[] split(String pattern) {
- String[] temp = getString().split(pattern);
- EncodedStringValue[] ret = new EncodedStringValue[temp.length];
- for (int i = 0; i < ret.length; ++i) {
- try {
- ret[i] = new EncodedStringValue(mCharacterSet,
- temp[i].getBytes());
- } catch (NullPointerException _) {
- // Can't arrive here
- return null;
- }
- }
- return ret;
- }
-
- /**
- * Extract an EncodedStringValue[] from a given String.
- */
- public static EncodedStringValue[] extract(String src) {
- String[] values = src.split(";");
-
- ArrayList<EncodedStringValue> list = new ArrayList<EncodedStringValue>();
- for (int i = 0; i < values.length; i++) {
- if (values[i].length() > 0) {
- list.add(new EncodedStringValue(values[i]));
- }
- }
-
- int len = list.size();
- if (len > 0) {
- return list.toArray(new EncodedStringValue[len]);
- } else {
- return null;
- }
- }
-
- /**
- * Concatenate an EncodedStringValue[] into a single String.
- */
- public static String concat(EncodedStringValue[] addr) {
- StringBuilder sb = new StringBuilder();
- int maxIndex = addr.length - 1;
- for (int i = 0; i <= maxIndex; i++) {
- sb.append(addr[i].getString());
- if (i < maxIndex) {
- sb.append(";");
- }
- }
-
- return sb.toString();
- }
-
- public static EncodedStringValue copy(EncodedStringValue value) {
- if (value == null) {
- return null;
- }
-
- return new EncodedStringValue(value.mCharacterSet, value.mData);
- }
-}
diff --git a/core/java/com/google/android/mms/pdu/GenericPdu.java b/core/java/com/google/android/mms/pdu/GenericPdu.java
deleted file mode 100644
index 46c6e00..0000000
--- a/core/java/com/google/android/mms/pdu/GenericPdu.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import com.google.android.mms.InvalidHeaderValueException;
-
-public class GenericPdu {
- /**
- * The headers of pdu.
- */
- PduHeaders mPduHeaders = null;
-
- /**
- * Constructor.
- */
- public GenericPdu() {
- mPduHeaders = new PduHeaders();
- }
-
- /**
- * Constructor.
- *
- * @param headers Headers for this PDU.
- */
- GenericPdu(PduHeaders headers) {
- mPduHeaders = headers;
- }
-
- /**
- * Get the headers of this PDU.
- *
- * @return A PduHeaders of this PDU.
- */
- PduHeaders getPduHeaders() {
- return mPduHeaders;
- }
-
- /**
- * Get X-Mms-Message-Type field value.
- *
- * @return the X-Mms-Report-Allowed value
- */
- public int getMessageType() {
- return mPduHeaders.getOctet(PduHeaders.MESSAGE_TYPE);
- }
-
- /**
- * Set X-Mms-Message-Type field value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- * RuntimeException if field's value is not Octet.
- */
- public void setMessageType(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.MESSAGE_TYPE);
- }
-
- /**
- * Get X-Mms-MMS-Version field value.
- *
- * @return the X-Mms-MMS-Version value
- */
- public int getMmsVersion() {
- return mPduHeaders.getOctet(PduHeaders.MMS_VERSION);
- }
-
- /**
- * Set X-Mms-MMS-Version field value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- * RuntimeException if field's value is not Octet.
- */
- public void setMmsVersion(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.MMS_VERSION);
- }
-}
diff --git a/core/java/com/google/android/mms/pdu/MultimediaMessagePdu.java b/core/java/com/google/android/mms/pdu/MultimediaMessagePdu.java
deleted file mode 100644
index 5a85e0e..0000000
--- a/core/java/com/google/android/mms/pdu/MultimediaMessagePdu.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import com.google.android.mms.InvalidHeaderValueException;
-
-/**
- * Multimedia message PDU.
- */
-public class MultimediaMessagePdu extends GenericPdu{
- /**
- * The body.
- */
- private PduBody mMessageBody;
-
- /**
- * Constructor.
- */
- public MultimediaMessagePdu() {
- super();
- }
-
- /**
- * Constructor.
- *
- * @param header the header of this PDU
- * @param body the body of this PDU
- */
- public MultimediaMessagePdu(PduHeaders header, PduBody body) {
- super(header);
- mMessageBody = body;
- }
-
- /**
- * Constructor with given headers.
- *
- * @param headers Headers for this PDU.
- */
- MultimediaMessagePdu(PduHeaders headers) {
- super(headers);
- }
-
- /**
- * Get body of the PDU.
- *
- * @return the body
- */
- public PduBody getBody() {
- return mMessageBody;
- }
-
- /**
- * Set body of the PDU.
- *
- * @param body the body
- */
- public void setBody(PduBody body) {
- mMessageBody = body;
- }
-
- /**
- * Get subject.
- *
- * @return the value
- */
- public EncodedStringValue getSubject() {
- return mPduHeaders.getEncodedStringValue(PduHeaders.SUBJECT);
- }
-
- /**
- * Set subject.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setSubject(EncodedStringValue value) {
- mPduHeaders.setEncodedStringValue(value, PduHeaders.SUBJECT);
- }
-
- /**
- * Get To value.
- *
- * @return the value
- */
- public EncodedStringValue[] getTo() {
- return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
- }
-
- /**
- * Add a "To" value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void addTo(EncodedStringValue value) {
- mPduHeaders.appendEncodedStringValue(value, PduHeaders.TO);
- }
-
- /**
- * Get X-Mms-Priority value.
- *
- * @return the value
- */
- public int getPriority() {
- return mPduHeaders.getOctet(PduHeaders.PRIORITY);
- }
-
- /**
- * Set X-Mms-Priority value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- */
- public void setPriority(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.PRIORITY);
- }
-
- /**
- * Get Date value.
- *
- * @return the value
- */
- public long getDate() {
- return mPduHeaders.getLongInteger(PduHeaders.DATE);
- }
-
- /**
- * Set Date value in seconds.
- *
- * @param value the value
- */
- public void setDate(long value) {
- mPduHeaders.setLongInteger(value, PduHeaders.DATE);
- }
-}
diff --git a/core/java/com/google/android/mms/pdu/NotificationInd.java b/core/java/com/google/android/mms/pdu/NotificationInd.java
deleted file mode 100644
index c56cba6..0000000
--- a/core/java/com/google/android/mms/pdu/NotificationInd.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import com.google.android.mms.InvalidHeaderValueException;
-
-/**
- * M-Notification.ind PDU.
- */
-public class NotificationInd extends GenericPdu {
- /**
- * Empty constructor.
- * Since the Pdu corresponding to this class is constructed
- * by the Proxy-Relay server, this class is only instantiated
- * by the Pdu Parser.
- *
- * @throws InvalidHeaderValueException if error occurs.
- * RuntimeException if an undeclared error occurs.
- */
- public NotificationInd() throws InvalidHeaderValueException {
- super();
- setMessageType(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND);
- }
-
- /**
- * Constructor with given headers.
- *
- * @param headers Headers for this PDU.
- */
- NotificationInd(PduHeaders headers) {
- super(headers);
- }
-
- /**
- * Get X-Mms-Content-Class Value.
- *
- * @return the value
- */
- public int getContentClass() {
- return mPduHeaders.getOctet(PduHeaders.CONTENT_CLASS);
- }
-
- /**
- * Set X-Mms-Content-Class Value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- * RuntimeException if an undeclared error occurs.
- */
- public void setContentClass(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.CONTENT_CLASS);
- }
-
- /**
- * Get X-Mms-Content-Location value.
- * When used in a PDU other than M-Mbox-Delete.conf and M-Delete.conf:
- * Content-location-value = Uri-value
- *
- * @return the value
- */
- public byte[] getContentLocation() {
- return mPduHeaders.getTextString(PduHeaders.CONTENT_LOCATION);
- }
-
- /**
- * Set X-Mms-Content-Location value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- * RuntimeException if an undeclared error occurs.
- */
- public void setContentLocation(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.CONTENT_LOCATION);
- }
-
- /**
- * Get X-Mms-Expiry value.
- *
- * Expiry-value = Value-length
- * (Absolute-token Date-value | Relative-token Delta-seconds-value)
- *
- * @return the value
- */
- public long getExpiry() {
- return mPduHeaders.getLongInteger(PduHeaders.EXPIRY);
- }
-
- /**
- * Set X-Mms-Expiry value.
- *
- * @param value the value
- * @throws RuntimeException if an undeclared error occurs.
- */
- public void setExpiry(long value) {
- mPduHeaders.setLongInteger(value, PduHeaders.EXPIRY);
- }
-
- /**
- * Get From value.
- * From-value = Value-length
- * (Address-present-token Encoded-string-value | Insert-address-token)
- *
- * @return the value
- */
- public EncodedStringValue getFrom() {
- return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
- }
-
- /**
- * Set From value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- * RuntimeException if an undeclared error occurs.
- */
- public void setFrom(EncodedStringValue value) {
- mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
- }
-
- /**
- * Get X-Mms-Message-Class value.
- * Message-class-value = Class-identifier | Token-text
- * Class-identifier = Personal | Advertisement | Informational | Auto
- *
- * @return the value
- */
- public byte[] getMessageClass() {
- return mPduHeaders.getTextString(PduHeaders.MESSAGE_CLASS);
- }
-
- /**
- * Set X-Mms-Message-Class value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- * RuntimeException if an undeclared error occurs.
- */
- public void setMessageClass(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.MESSAGE_CLASS);
- }
-
- /**
- * Get X-Mms-Message-Size value.
- * Message-size-value = Long-integer
- *
- * @return the value
- */
- public long getMessageSize() {
- return mPduHeaders.getLongInteger(PduHeaders.MESSAGE_SIZE);
- }
-
- /**
- * Set X-Mms-Message-Size value.
- *
- * @param value the value
- * @throws RuntimeException if an undeclared error occurs.
- */
- public void setMessageSize(long value) {
- mPduHeaders.setLongInteger(value, PduHeaders.MESSAGE_SIZE);
- }
-
- /**
- * Get subject.
- *
- * @return the value
- */
- public EncodedStringValue getSubject() {
- return mPduHeaders.getEncodedStringValue(PduHeaders.SUBJECT);
- }
-
- /**
- * Set subject.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- * RuntimeException if an undeclared error occurs.
- */
- public void setSubject(EncodedStringValue value) {
- mPduHeaders.setEncodedStringValue(value, PduHeaders.SUBJECT);
- }
-
- /**
- * Get X-Mms-Transaction-Id.
- *
- * @return the value
- */
- public byte[] getTransactionId() {
- return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
- }
-
- /**
- * Set X-Mms-Transaction-Id.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- * RuntimeException if an undeclared error occurs.
- */
- public void setTransactionId(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
- }
-
- /**
- * Get X-Mms-Delivery-Report Value.
- *
- * @return the value
- */
- public int getDeliveryReport() {
- return mPduHeaders.getOctet(PduHeaders.DELIVERY_REPORT);
- }
-
- /**
- * Set X-Mms-Delivery-Report Value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- * RuntimeException if an undeclared error occurs.
- */
- public void setDeliveryReport(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.DELIVERY_REPORT);
- }
-
- /*
- * Optional, not supported header fields:
- *
- * public byte[] getApplicId() {return null;}
- * public void setApplicId(byte[] value) {}
- *
- * public byte[] getAuxApplicId() {return null;}
- * public void getAuxApplicId(byte[] value) {}
- *
- * public byte getDrmContent() {return 0x00;}
- * public void setDrmContent(byte value) {}
- *
- * public byte getDistributionIndicator() {return 0x00;}
- * public void setDistributionIndicator(byte value) {}
- *
- * public ElementDescriptorValue getElementDescriptor() {return null;}
- * public void getElementDescriptor(ElementDescriptorValue value) {}
- *
- * public byte getPriority() {return 0x00;}
- * public void setPriority(byte value) {}
- *
- * public byte getRecommendedRetrievalMode() {return 0x00;}
- * public void setRecommendedRetrievalMode(byte value) {}
- *
- * public byte getRecommendedRetrievalModeText() {return 0x00;}
- * public void setRecommendedRetrievalModeText(byte value) {}
- *
- * public byte[] getReplaceId() {return 0x00;}
- * public void setReplaceId(byte[] value) {}
- *
- * public byte[] getReplyApplicId() {return 0x00;}
- * public void setReplyApplicId(byte[] value) {}
- *
- * public byte getReplyCharging() {return 0x00;}
- * public void setReplyCharging(byte value) {}
- *
- * public byte getReplyChargingDeadline() {return 0x00;}
- * public void setReplyChargingDeadline(byte value) {}
- *
- * public byte[] getReplyChargingId() {return 0x00;}
- * public void setReplyChargingId(byte[] value) {}
- *
- * public long getReplyChargingSize() {return 0;}
- * public void setReplyChargingSize(long value) {}
- *
- * public byte getStored() {return 0x00;}
- * public void setStored(byte value) {}
- */
-}
diff --git a/core/java/com/google/android/mms/pdu/NotifyRespInd.java b/core/java/com/google/android/mms/pdu/NotifyRespInd.java
deleted file mode 100644
index 2cc2fce..0000000
--- a/core/java/com/google/android/mms/pdu/NotifyRespInd.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import com.google.android.mms.InvalidHeaderValueException;
-
-/**
- * M-NofifyResp.ind PDU.
- */
-public class NotifyRespInd extends GenericPdu {
- /**
- * Constructor, used when composing a M-NotifyResp.ind pdu.
- *
- * @param mmsVersion current version of mms
- * @param transactionId the transaction-id value
- * @param status the status value
- * @throws InvalidHeaderValueException if parameters are invalid.
- * NullPointerException if transactionId is null.
- * RuntimeException if an undeclared error occurs.
- */
- public NotifyRespInd(int mmsVersion,
- byte[] transactionId,
- int status) throws InvalidHeaderValueException {
- super();
- setMessageType(PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND);
- setMmsVersion(mmsVersion);
- setTransactionId(transactionId);
- setStatus(status);
- }
-
- /**
- * Constructor with given headers.
- *
- * @param headers Headers for this PDU.
- */
- NotifyRespInd(PduHeaders headers) {
- super(headers);
- }
-
- /**
- * Get X-Mms-Report-Allowed field value.
- *
- * @return the X-Mms-Report-Allowed value
- */
- public int getReportAllowed() {
- return mPduHeaders.getOctet(PduHeaders.REPORT_ALLOWED);
- }
-
- /**
- * Set X-Mms-Report-Allowed field value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- * RuntimeException if an undeclared error occurs.
- */
- public void setReportAllowed(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.REPORT_ALLOWED);
- }
-
- /**
- * Set X-Mms-Status field value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- * RuntimeException if an undeclared error occurs.
- */
- public void setStatus(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.STATUS);
- }
-
- /**
- * GetX-Mms-Status field value.
- *
- * @return the X-Mms-Status value
- */
- public int getStatus() {
- return mPduHeaders.getOctet(PduHeaders.STATUS);
- }
-
- /**
- * Get X-Mms-Transaction-Id field value.
- *
- * @return the X-Mms-Report-Allowed value
- */
- public byte[] getTransactionId() {
- return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
- }
-
- /**
- * Set X-Mms-Transaction-Id field value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- * RuntimeException if an undeclared error occurs.
- */
- public void setTransactionId(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
- }
-}
diff --git a/core/java/com/google/android/mms/pdu/PduBody.java b/core/java/com/google/android/mms/pdu/PduBody.java
deleted file mode 100644
index fa0416c..0000000
--- a/core/java/com/google/android/mms/pdu/PduBody.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Vector;
-
-public class PduBody {
- private Vector<PduPart> mParts = null;
-
- private Map<String, PduPart> mPartMapByContentId = null;
- private Map<String, PduPart> mPartMapByContentLocation = null;
- private Map<String, PduPart> mPartMapByName = null;
- private Map<String, PduPart> mPartMapByFileName = null;
-
- /**
- * Constructor.
- */
- public PduBody() {
- mParts = new Vector<PduPart>();
-
- mPartMapByContentId = new HashMap<String, PduPart>();
- mPartMapByContentLocation = new HashMap<String, PduPart>();
- mPartMapByName = new HashMap<String, PduPart>();
- mPartMapByFileName = new HashMap<String, PduPart>();
- }
-
- private void putPartToMaps(PduPart part) {
- // Put part to mPartMapByContentId.
- byte[] contentId = part.getContentId();
- if(null != contentId) {
- mPartMapByContentId.put(new String(contentId), part);
- }
-
- // Put part to mPartMapByContentLocation.
- byte[] contentLocation = part.getContentLocation();
- if(null != contentLocation) {
- String clc = new String(contentLocation);
- mPartMapByContentLocation.put(clc, part);
- }
-
- // Put part to mPartMapByName.
- byte[] name = part.getName();
- if(null != name) {
- String clc = new String(name);
- mPartMapByName.put(clc, part);
- }
-
- // Put part to mPartMapByFileName.
- byte[] fileName = part.getFilename();
- if(null != fileName) {
- String clc = new String(fileName);
- mPartMapByFileName.put(clc, part);
- }
- }
-
- /**
- * Appends the specified part to the end of this body.
- *
- * @param part part to be appended
- * @return true when success, false when fail
- * @throws NullPointerException when part is null
- */
- public boolean addPart(PduPart part) {
- if(null == part) {
- throw new NullPointerException();
- }
-
- putPartToMaps(part);
- return mParts.add(part);
- }
-
- /**
- * Inserts the specified part at the specified position.
- *
- * @param index index at which the specified part is to be inserted
- * @param part part to be inserted
- * @throws NullPointerException when part is null
- */
- public void addPart(int index, PduPart part) {
- if(null == part) {
- throw new NullPointerException();
- }
-
- putPartToMaps(part);
- mParts.add(index, part);
- }
-
- /**
- * Removes the part at the specified position.
- *
- * @param index index of the part to return
- * @return part at the specified index
- */
- public PduPart removePart(int index) {
- return mParts.remove(index);
- }
-
- /**
- * Remove all of the parts.
- */
- public void removeAll() {
- mParts.clear();
- }
-
- /**
- * Get the part at the specified position.
- *
- * @param index index of the part to return
- * @return part at the specified index
- */
- public PduPart getPart(int index) {
- return mParts.get(index);
- }
-
- /**
- * Get the index of the specified part.
- *
- * @param part the part object
- * @return index the index of the first occurrence of the part in this body
- */
- public int getPartIndex(PduPart part) {
- return mParts.indexOf(part);
- }
-
- /**
- * Get the number of parts.
- *
- * @return the number of parts
- */
- public int getPartsNum() {
- return mParts.size();
- }
-
- /**
- * Get pdu part by content id.
- *
- * @param cid the value of content id.
- * @return the pdu part.
- */
- public PduPart getPartByContentId(String cid) {
- return mPartMapByContentId.get(cid);
- }
-
- /**
- * Get pdu part by Content-Location. Content-Location of part is
- * the same as filename and name(param of content-type).
- *
- * @param fileName the value of filename.
- * @return the pdu part.
- */
- public PduPart getPartByContentLocation(String contentLocation) {
- return mPartMapByContentLocation.get(contentLocation);
- }
-
- /**
- * Get pdu part by name.
- *
- * @param fileName the value of filename.
- * @return the pdu part.
- */
- public PduPart getPartByName(String name) {
- return mPartMapByName.get(name);
- }
-
- /**
- * Get pdu part by filename.
- *
- * @param fileName the value of filename.
- * @return the pdu part.
- */
- public PduPart getPartByFileName(String filename) {
- return mPartMapByFileName.get(filename);
- }
-}
diff --git a/core/java/com/google/android/mms/pdu/PduComposer.java b/core/java/com/google/android/mms/pdu/PduComposer.java
deleted file mode 100644
index 094e992..0000000
--- a/core/java/com/google/android/mms/pdu/PduComposer.java
+++ /dev/null
@@ -1,1163 +0,0 @@
-/*
- * Copyright (C) 2007-2008 Esmertec AG.
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import android.content.ContentResolver;
-import android.content.Context;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.HashMap;
-
-public class PduComposer {
- /**
- * Address type.
- */
- static private final int PDU_PHONE_NUMBER_ADDRESS_TYPE = 1;
- static private final int PDU_EMAIL_ADDRESS_TYPE = 2;
- static private final int PDU_IPV4_ADDRESS_TYPE = 3;
- static private final int PDU_IPV6_ADDRESS_TYPE = 4;
- static private final int PDU_UNKNOWN_ADDRESS_TYPE = 5;
-
- /**
- * Address regular expression string.
- */
- static final String REGEXP_PHONE_NUMBER_ADDRESS_TYPE = "\\+?[0-9|\\.|\\-]+";
- static final String REGEXP_EMAIL_ADDRESS_TYPE = "[a-zA-Z| ]*\\<{0,1}[a-zA-Z| ]+@{1}" +
- "[a-zA-Z| ]+\\.{1}[a-zA-Z| ]+\\>{0,1}";
- static final String REGEXP_IPV6_ADDRESS_TYPE =
- "[a-fA-F]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}" +
- "[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}" +
- "[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}";
- static final String REGEXP_IPV4_ADDRESS_TYPE = "[0-9]{1,3}\\.{1}[0-9]{1,3}\\.{1}" +
- "[0-9]{1,3}\\.{1}[0-9]{1,3}";
-
- /**
- * The postfix strings of address.
- */
- static final String STRING_PHONE_NUMBER_ADDRESS_TYPE = "/TYPE=PLMN";
- static final String STRING_IPV4_ADDRESS_TYPE = "/TYPE=IPV4";
- static final String STRING_IPV6_ADDRESS_TYPE = "/TYPE=IPV6";
-
- /**
- * Error values.
- */
- static private final int PDU_COMPOSE_SUCCESS = 0;
- static private final int PDU_COMPOSE_CONTENT_ERROR = 1;
- static private final int PDU_COMPOSE_FIELD_NOT_SET = 2;
- static private final int PDU_COMPOSE_FIELD_NOT_SUPPORTED = 3;
-
- /**
- * WAP values defined in WSP spec.
- */
- static private final int QUOTED_STRING_FLAG = 34;
- static private final int END_STRING_FLAG = 0;
- static private final int LENGTH_QUOTE = 31;
- static private final int TEXT_MAX = 127;
- static private final int SHORT_INTEGER_MAX = 127;
- static private final int LONG_INTEGER_LENGTH_MAX = 8;
-
- /**
- * Block size when read data from InputStream.
- */
- static private final int PDU_COMPOSER_BLOCK_SIZE = 1024;
-
- /**
- * The output message.
- */
- protected ByteArrayOutputStream mMessage = null;
-
- /**
- * The PDU.
- */
- private GenericPdu mPdu = null;
-
- /**
- * Current visiting position of the mMessage.
- */
- protected int mPosition = 0;
-
- /**
- * Message compose buffer stack.
- */
- private BufferStack mStack = null;
-
- /**
- * Content resolver.
- */
- private final ContentResolver mResolver;
-
- /**
- * Header of this pdu.
- */
- private PduHeaders mPduHeader = null;
-
- /**
- * Map of all content type
- */
- private static HashMap<String, Integer> mContentTypeMap = null;
-
- static {
- mContentTypeMap = new HashMap<String, Integer>();
-
- int i;
- for (i = 0; i < PduContentTypes.contentTypes.length; i++) {
- mContentTypeMap.put(PduContentTypes.contentTypes[i], i);
- }
- }
-
- /**
- * Constructor.
- *
- * @param context the context
- * @param pdu the pdu to be composed
- */
- public PduComposer(Context context, GenericPdu pdu) {
- mPdu = pdu;
- mResolver = context.getContentResolver();
- mPduHeader = pdu.getPduHeaders();
- mStack = new BufferStack();
- mMessage = new ByteArrayOutputStream();
- mPosition = 0;
- }
-
- /**
- * Make the message. No need to check whether mandatory fields are set,
- * because the constructors of outgoing pdus are taking care of this.
- *
- * @return OutputStream of maked message. Return null if
- * the PDU is invalid.
- */
- public byte[] make() {
- // Get Message-type.
- int type = mPdu.getMessageType();
-
- /* make the message */
- switch (type) {
- case PduHeaders.MESSAGE_TYPE_SEND_REQ:
- if (makeSendReqPdu() != PDU_COMPOSE_SUCCESS) {
- return null;
- }
- break;
- case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
- if (makeNotifyResp() != PDU_COMPOSE_SUCCESS) {
- return null;
- }
- break;
- case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
- if (makeAckInd() != PDU_COMPOSE_SUCCESS) {
- return null;
- }
- break;
- case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
- if (makeReadRecInd() != PDU_COMPOSE_SUCCESS) {
- return null;
- }
- break;
- default:
- return null;
- }
-
- return mMessage.toByteArray();
- }
-
- /**
- * Copy buf to mMessage.
- */
- protected void arraycopy(byte[] buf, int pos, int length) {
- mMessage.write(buf, pos, length);
- mPosition = mPosition + length;
- }
-
- /**
- * Append a byte to mMessage.
- */
- protected void append(int value) {
- mMessage.write(value);
- mPosition ++;
- }
-
- /**
- * Append short integer value to mMessage.
- * This implementation doesn't check the validity of parameter, since it
- * assumes that the values are validated in the GenericPdu setter methods.
- */
- protected void appendShortInteger(int value) {
- /*
- * From WAP-230-WSP-20010705-a:
- * Short-integer = OCTET
- * ; Integers in range 0-127 shall be encoded as a one octet value
- * ; with the most significant bit set to one (1xxx xxxx) and with
- * ; the value in the remaining least significant bits.
- * In our implementation, only low 7 bits are stored and otherwise
- * bits are ignored.
- */
- append((value | 0x80) & 0xff);
- }
-
- /**
- * Append an octet number between 128 and 255 into mMessage.
- * NOTE:
- * A value between 0 and 127 should be appended by using appendShortInteger.
- * This implementation doesn't check the validity of parameter, since it
- * assumes that the values are validated in the GenericPdu setter methods.
- */
- protected void appendOctet(int number) {
- append(number);
- }
-
- /**
- * Append a short length into mMessage.
- * This implementation doesn't check the validity of parameter, since it
- * assumes that the values are validated in the GenericPdu setter methods.
- */
- protected void appendShortLength(int value) {
- /*
- * From WAP-230-WSP-20010705-a:
- * Short-length = <Any octet 0-30>
- */
- append(value);
- }
-
- /**
- * Append long integer into mMessage. it's used for really long integers.
- * This implementation doesn't check the validity of parameter, since it
- * assumes that the values are validated in the GenericPdu setter methods.
- */
- protected void appendLongInteger(long longInt) {
- /*
- * From WAP-230-WSP-20010705-a:
- * Long-integer = Short-length Multi-octet-integer
- * ; The Short-length indicates the length of the Multi-octet-integer
- * Multi-octet-integer = 1*30 OCTET
- * ; The content octets shall be an unsigned integer value with the
- * ; most significant octet encoded first (big-endian representation).
- * ; The minimum number of octets must be used to encode the value.
- */
- int size;
- long temp = longInt;
-
- // Count the length of the long integer.
- for(size = 0; (temp != 0) && (size < LONG_INTEGER_LENGTH_MAX); size++) {
- temp = (temp >>> 8);
- }
-
- // Set Length.
- appendShortLength(size);
-
- // Count and set the long integer.
- int i;
- int shift = (size -1) * 8;
-
- for (i = 0; i < size; i++) {
- append((int)((longInt >>> shift) & 0xff));
- shift = shift - 8;
- }
- }
-
- /**
- * Append text string into mMessage.
- * This implementation doesn't check the validity of parameter, since it
- * assumes that the values are validated in the GenericPdu setter methods.
- */
- protected void appendTextString(byte[] text) {
- /*
- * From WAP-230-WSP-20010705-a:
- * Text-string = [Quote] *TEXT End-of-string
- * ; If the first character in the TEXT is in the range of 128-255,
- * ; a Quote character must precede it. Otherwise the Quote character
- * ;must be omitted. The Quote is not part of the contents.
- */
- if (((text[0])&0xff) > TEXT_MAX) { // No need to check for <= 255
- append(TEXT_MAX);
- }
-
- arraycopy(text, 0, text.length);
- append(0);
- }
-
- /**
- * Append text string into mMessage.
- * This implementation doesn't check the validity of parameter, since it
- * assumes that the values are validated in the GenericPdu setter methods.
- */
- protected void appendTextString(String str) {
- /*
- * From WAP-230-WSP-20010705-a:
- * Text-string = [Quote] *TEXT End-of-string
- * ; If the first character in the TEXT is in the range of 128-255,
- * ; a Quote character must precede it. Otherwise the Quote character
- * ;must be omitted. The Quote is not part of the contents.
- */
- appendTextString(str.getBytes());
- }
-
- /**
- * Append encoded string value to mMessage.
- * This implementation doesn't check the validity of parameter, since it
- * assumes that the values are validated in the GenericPdu setter methods.
- */
- protected void appendEncodedString(EncodedStringValue enStr) {
- /*
- * From OMA-TS-MMS-ENC-V1_3-20050927-C:
- * Encoded-string-value = Text-string | Value-length Char-set Text-string
- */
- assert(enStr != null);
-
- int charset = enStr.getCharacterSet();
- byte[] textString = enStr.getTextString();
- if (null == textString) {
- return;
- }
-
- /*
- * In the implementation of EncodedStringValue, the charset field will
- * never be 0. It will always be composed as
- * Encoded-string-value = Value-length Char-set Text-string
- */
- mStack.newbuf();
- PositionMarker start = mStack.mark();
-
- appendShortInteger(charset);
- appendTextString(textString);
-
- int len = start.getLength();
- mStack.pop();
- appendValueLength(len);
- mStack.copy();
- }
-
- /**
- * Append uintvar integer into mMessage.
- * This implementation doesn't check the validity of parameter, since it
- * assumes that the values are validated in the GenericPdu setter methods.
- */
- protected void appendUintvarInteger(long value) {
- /*
- * From WAP-230-WSP-20010705-a:
- * To encode a large unsigned integer, split it into 7-bit fragments
- * and place them in the payloads of multiple octets. The most significant
- * bits are placed in the first octets with the least significant bits
- * ending up in the last octet. All octets MUST set the Continue bit to 1
- * except the last octet, which MUST set the Continue bit to 0.
- */
- int i;
- long max = SHORT_INTEGER_MAX;
-
- for (i = 0; i < 5; i++) {
- if (value < max) {
- break;
- }
-
- max = (max << 7) | 0x7fl;
- }
-
- while(i > 0) {
- long temp = value >>> (i * 7);
- temp = temp & 0x7f;
-
- append((int)((temp | 0x80) & 0xff));
-
- i--;
- }
-
- append((int)(value & 0x7f));
- }
-
- /**
- * Append date value into mMessage.
- * This implementation doesn't check the validity of parameter, since it
- * assumes that the values are validated in the GenericPdu setter methods.
- */
- protected void appendDateValue(long date) {
- /*
- * From OMA-TS-MMS-ENC-V1_3-20050927-C:
- * Date-value = Long-integer
- */
- appendLongInteger(date);
- }
-
- /**
- * Append value length to mMessage.
- * This implementation doesn't check the validity of parameter, since it
- * assumes that the values are validated in the GenericPdu setter methods.
- */
- protected void appendValueLength(long value) {
- /*
- * From WAP-230-WSP-20010705-a:
- * Value-length = Short-length | (Length-quote Length)
- * ; Value length is used to indicate the length of the value to follow
- * Short-length = <Any octet 0-30>
- * Length-quote = <Octet 31>
- * Length = Uintvar-integer
- */
- if (value < LENGTH_QUOTE) {
- appendShortLength((int) value);
- return;
- }
-
- append(LENGTH_QUOTE);
- appendUintvarInteger(value);
- }
-
- /**
- * Append quoted string to mMessage.
- * This implementation doesn't check the validity of parameter, since it
- * assumes that the values are validated in the GenericPdu setter methods.
- */
- protected void appendQuotedString(byte[] text) {
- /*
- * From WAP-230-WSP-20010705-a:
- * Quoted-string = <Octet 34> *TEXT End-of-string
- * ;The TEXT encodes an RFC2616 Quoted-string with the enclosing
- * ;quotation-marks <"> removed.
- */
- append(QUOTED_STRING_FLAG);
- arraycopy(text, 0, text.length);
- append(END_STRING_FLAG);
- }
-
- /**
- * Append quoted string to mMessage.
- * This implementation doesn't check the validity of parameter, since it
- * assumes that the values are validated in the GenericPdu setter methods.
- */
- protected void appendQuotedString(String str) {
- /*
- * From WAP-230-WSP-20010705-a:
- * Quoted-string = <Octet 34> *TEXT End-of-string
- * ;The TEXT encodes an RFC2616 Quoted-string with the enclosing
- * ;quotation-marks <"> removed.
- */
- appendQuotedString(str.getBytes());
- }
-
- /**
- * Append header to mMessage.
- */
- private int appendHeader(int field) {
- switch (field) {
- case PduHeaders.MMS_VERSION:
- appendOctet(field);
-
- int version = mPduHeader.getOctet(field);
- if (0 == version) {
- appendShortInteger(PduHeaders.CURRENT_MMS_VERSION);
- } else {
- appendShortInteger(version);
- }
-
- break;
-
- case PduHeaders.MESSAGE_ID:
- case PduHeaders.TRANSACTION_ID:
- byte[] textString = mPduHeader.getTextString(field);
- if (null == textString) {
- return PDU_COMPOSE_FIELD_NOT_SET;
- }
-
- appendOctet(field);
- appendTextString(textString);
- break;
-
- case PduHeaders.TO:
- case PduHeaders.BCC:
- case PduHeaders.CC:
- EncodedStringValue[] addr = mPduHeader.getEncodedStringValues(field);
-
- if (null == addr) {
- return PDU_COMPOSE_FIELD_NOT_SET;
- }
-
- EncodedStringValue temp;
- for (int i = 0; i < addr.length; i++) {
- try {
- int addressType = checkAddressType(addr[i].getString());
- temp = EncodedStringValue.copy(addr[i]);
- if (PDU_PHONE_NUMBER_ADDRESS_TYPE == addressType) {
- // Phone number.
- temp.appendTextString(
- STRING_PHONE_NUMBER_ADDRESS_TYPE.getBytes());
- } else if (PDU_IPV4_ADDRESS_TYPE == addressType) {
- // Ipv4 address.
- temp.appendTextString(STRING_IPV4_ADDRESS_TYPE.getBytes());
- } else if (PDU_IPV6_ADDRESS_TYPE == addressType) {
- // Ipv6 address.
- temp.appendTextString(STRING_IPV6_ADDRESS_TYPE.getBytes());
- }
- } catch (NullPointerException e) {
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- appendOctet(field);
- appendEncodedString(temp);
- }
- break;
-
- case PduHeaders.FROM:
- // Value-length (Address-present-token Encoded-string-value | Insert-address-token)
- appendOctet(field);
-
- EncodedStringValue from = mPduHeader.getEncodedStringValue(field);
- if ((from == null)
- || new String(from.getTextString()).equals(
- PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR)) {
- // Length of from = 1
- append(1);
- // Insert-address-token = <Octet 129>
- append(PduHeaders.FROM_INSERT_ADDRESS_TOKEN);
- } else {
- mStack.newbuf();
- PositionMarker fstart = mStack.mark();
-
- // Address-present-token = <Octet 128>
- append(PduHeaders.FROM_ADDRESS_PRESENT_TOKEN);
- appendEncodedString(from);
-
- int flen = fstart.getLength();
- mStack.pop();
- appendValueLength(flen);
- mStack.copy();
- }
- break;
-
- case PduHeaders.READ_STATUS:
- case PduHeaders.STATUS:
- case PduHeaders.REPORT_ALLOWED:
- case PduHeaders.PRIORITY:
- case PduHeaders.DELIVERY_REPORT:
- case PduHeaders.READ_REPORT:
- int octet = mPduHeader.getOctet(field);
- if (0 == octet) {
- return PDU_COMPOSE_FIELD_NOT_SET;
- }
-
- appendOctet(field);
- appendOctet(octet);
- break;
-
- case PduHeaders.DATE:
- long date = mPduHeader.getLongInteger(field);
- if (-1 == date) {
- return PDU_COMPOSE_FIELD_NOT_SET;
- }
-
- appendOctet(field);
- appendDateValue(date);
- break;
-
- case PduHeaders.SUBJECT:
- EncodedStringValue enString =
- mPduHeader.getEncodedStringValue(field);
- if (null == enString) {
- return PDU_COMPOSE_FIELD_NOT_SET;
- }
-
- appendOctet(field);
- appendEncodedString(enString);
- break;
-
- case PduHeaders.MESSAGE_CLASS:
- byte[] messageClass = mPduHeader.getTextString(field);
- if (null == messageClass) {
- return PDU_COMPOSE_FIELD_NOT_SET;
- }
-
- appendOctet(field);
- if (Arrays.equals(messageClass,
- PduHeaders.MESSAGE_CLASS_ADVERTISEMENT_STR.getBytes())) {
- appendOctet(PduHeaders.MESSAGE_CLASS_ADVERTISEMENT);
- } else if (Arrays.equals(messageClass,
- PduHeaders.MESSAGE_CLASS_AUTO_STR.getBytes())) {
- appendOctet(PduHeaders.MESSAGE_CLASS_AUTO);
- } else if (Arrays.equals(messageClass,
- PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes())) {
- appendOctet(PduHeaders.MESSAGE_CLASS_PERSONAL);
- } else if (Arrays.equals(messageClass,
- PduHeaders.MESSAGE_CLASS_INFORMATIONAL_STR.getBytes())) {
- appendOctet(PduHeaders.MESSAGE_CLASS_INFORMATIONAL);
- } else {
- appendTextString(messageClass);
- }
- break;
-
- case PduHeaders.EXPIRY:
- long expiry = mPduHeader.getLongInteger(field);
- if (-1 == expiry) {
- return PDU_COMPOSE_FIELD_NOT_SET;
- }
-
- appendOctet(field);
-
- mStack.newbuf();
- PositionMarker expiryStart = mStack.mark();
-
- append(PduHeaders.VALUE_RELATIVE_TOKEN);
- appendLongInteger(expiry);
-
- int expiryLength = expiryStart.getLength();
- mStack.pop();
- appendValueLength(expiryLength);
- mStack.copy();
- break;
-
- default:
- return PDU_COMPOSE_FIELD_NOT_SUPPORTED;
- }
-
- return PDU_COMPOSE_SUCCESS;
- }
-
- /**
- * Make ReadRec.Ind.
- */
- private int makeReadRecInd() {
- if (mMessage == null) {
- mMessage = new ByteArrayOutputStream();
- mPosition = 0;
- }
-
- // X-Mms-Message-Type
- appendOctet(PduHeaders.MESSAGE_TYPE);
- appendOctet(PduHeaders.MESSAGE_TYPE_READ_REC_IND);
-
- // X-Mms-MMS-Version
- if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) {
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- // Message-ID
- if (appendHeader(PduHeaders.MESSAGE_ID) != PDU_COMPOSE_SUCCESS) {
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- // To
- if (appendHeader(PduHeaders.TO) != PDU_COMPOSE_SUCCESS) {
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- // From
- if (appendHeader(PduHeaders.FROM) != PDU_COMPOSE_SUCCESS) {
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- // Date Optional
- appendHeader(PduHeaders.DATE);
-
- // X-Mms-Read-Status
- if (appendHeader(PduHeaders.READ_STATUS) != PDU_COMPOSE_SUCCESS) {
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- // X-Mms-Applic-ID Optional(not support)
- // X-Mms-Reply-Applic-ID Optional(not support)
- // X-Mms-Aux-Applic-Info Optional(not support)
-
- return PDU_COMPOSE_SUCCESS;
- }
-
- /**
- * Make NotifyResp.Ind.
- */
- private int makeNotifyResp() {
- if (mMessage == null) {
- mMessage = new ByteArrayOutputStream();
- mPosition = 0;
- }
-
- // X-Mms-Message-Type
- appendOctet(PduHeaders.MESSAGE_TYPE);
- appendOctet(PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND);
-
- // X-Mms-Transaction-ID
- if (appendHeader(PduHeaders.TRANSACTION_ID) != PDU_COMPOSE_SUCCESS) {
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- // X-Mms-MMS-Version
- if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) {
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- // X-Mms-Status
- if (appendHeader(PduHeaders.STATUS) != PDU_COMPOSE_SUCCESS) {
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- // X-Mms-Report-Allowed Optional (not support)
- return PDU_COMPOSE_SUCCESS;
- }
-
- /**
- * Make Acknowledge.Ind.
- */
- private int makeAckInd() {
- if (mMessage == null) {
- mMessage = new ByteArrayOutputStream();
- mPosition = 0;
- }
-
- // X-Mms-Message-Type
- appendOctet(PduHeaders.MESSAGE_TYPE);
- appendOctet(PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND);
-
- // X-Mms-Transaction-ID
- if (appendHeader(PduHeaders.TRANSACTION_ID) != PDU_COMPOSE_SUCCESS) {
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- // X-Mms-MMS-Version
- if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) {
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- // X-Mms-Report-Allowed Optional
- appendHeader(PduHeaders.REPORT_ALLOWED);
-
- return PDU_COMPOSE_SUCCESS;
- }
-
- /**
- * Make Send.req.
- */
- private int makeSendReqPdu() {
- if (mMessage == null) {
- mMessage = new ByteArrayOutputStream();
- mPosition = 0;
- }
-
- // X-Mms-Message-Type
- appendOctet(PduHeaders.MESSAGE_TYPE);
- appendOctet(PduHeaders.MESSAGE_TYPE_SEND_REQ);
-
- // X-Mms-Transaction-ID
- appendOctet(PduHeaders.TRANSACTION_ID);
-
- byte[] trid = mPduHeader.getTextString(PduHeaders.TRANSACTION_ID);
- if (trid == null) {
- // Transaction-ID should be set(by Transaction) before make().
- throw new IllegalArgumentException("Transaction-ID is null.");
- }
- appendTextString(trid);
-
- // X-Mms-MMS-Version
- if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) {
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- // Date Date-value Optional.
- appendHeader(PduHeaders.DATE);
-
- // From
- if (appendHeader(PduHeaders.FROM) != PDU_COMPOSE_SUCCESS) {
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- boolean recipient = false;
-
- // To
- if (appendHeader(PduHeaders.TO) != PDU_COMPOSE_CONTENT_ERROR) {
- recipient = true;
- }
-
- // Cc
- if (appendHeader(PduHeaders.CC) != PDU_COMPOSE_CONTENT_ERROR) {
- recipient = true;
- }
-
- // Bcc
- if (appendHeader(PduHeaders.BCC) != PDU_COMPOSE_CONTENT_ERROR) {
- recipient = true;
- }
-
- // Need at least one of "cc", "bcc" and "to".
- if (false == recipient) {
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- // Subject Optional
- appendHeader(PduHeaders.SUBJECT);
-
- // X-Mms-Message-Class Optional
- // Message-class-value = Class-identifier | Token-text
- appendHeader(PduHeaders.MESSAGE_CLASS);
-
- // X-Mms-Expiry Optional
- appendHeader(PduHeaders.EXPIRY);
-
- // X-Mms-Priority Optional
- appendHeader(PduHeaders.PRIORITY);
-
- // X-Mms-Delivery-Report Optional
- appendHeader(PduHeaders.DELIVERY_REPORT);
-
- // X-Mms-Read-Report Optional
- appendHeader(PduHeaders.READ_REPORT);
-
- // Content-Type
- appendOctet(PduHeaders.CONTENT_TYPE);
-
- // Message body
- makeMessageBody();
-
- return PDU_COMPOSE_SUCCESS; // Composing the message is OK
- }
-
- /**
- * Make message body.
- */
- private int makeMessageBody() {
- // 1. add body informations
- mStack.newbuf(); // Switching buffer because we need to
-
- PositionMarker ctStart = mStack.mark();
-
- // This contentTypeIdentifier should be used for type of attachment...
- String contentType = new String(
- mPduHeader.getTextString(PduHeaders.CONTENT_TYPE));
- Integer contentTypeIdentifier = mContentTypeMap.get(contentType);
- if (contentTypeIdentifier == null) {
- // content type is mandatory
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- appendShortInteger(contentTypeIdentifier.intValue());
-
- // content-type parameter: start
- PduBody body = ((SendReq) mPdu).getBody();
- if (null == body) {
- // empty message
- appendUintvarInteger(0);
- mStack.pop();
- mStack.copy();
- return PDU_COMPOSE_SUCCESS;
- }
-
- PduPart part;
- try {
- part = body.getPart(0);
-
- byte[] start = part.getContentId();
- if (start != null) {
- appendOctet(PduPart.P_DEP_START);
- if (('<' == start[0]) && ('>' == start[start.length - 1])) {
- appendTextString(start);
- } else {
- appendTextString("<" + new String(start) + ">");
- }
- }
-
- // content-type parameter: type
- appendOctet(PduPart.P_CT_MR_TYPE);
- appendTextString(part.getContentType());
- }
- catch (ArrayIndexOutOfBoundsException e){
- e.printStackTrace();
- }
-
- int ctLength = ctStart.getLength();
- mStack.pop();
- appendValueLength(ctLength);
- mStack.copy();
-
- // 3. add content
- int partNum = body.getPartsNum();
- appendUintvarInteger(partNum);
- for (int i = 0; i < partNum; i++) {
- part = body.getPart(i);
- mStack.newbuf(); // Leaving space for header lengh and data length
- PositionMarker attachment = mStack.mark();
-
- mStack.newbuf(); // Leaving space for Content-Type length
- PositionMarker contentTypeBegin = mStack.mark();
-
- byte[] partContentType = part.getContentType();
-
- if (partContentType == null) {
- // content type is mandatory
- return PDU_COMPOSE_CONTENT_ERROR;
- }
-
- // content-type value
- Integer partContentTypeIdentifier =
- mContentTypeMap.get(new String(partContentType));
- if (partContentTypeIdentifier == null) {
- appendTextString(partContentType);
- } else {
- appendShortInteger(partContentTypeIdentifier.intValue());
- }
-
- /* Content-type parameter : name.
- * The value of name, filename, content-location is the same.
- * Just one of them is enough for this PDU.
- */
- byte[] name = part.getName();
-
- if (null == name) {
- name = part.getFilename();
-
- if (null == name) {
- name = part.getContentLocation();
-
- if (null == name) {
- /* at lease one of name, filename, Content-location
- * should be available.
- */
- return PDU_COMPOSE_CONTENT_ERROR;
- }
- }
- }
- appendOctet(PduPart.P_DEP_NAME);
- appendTextString(name);
-
- // content-type parameter : charset
- int charset = part.getCharset();
- if (charset != 0) {
- appendOctet(PduPart.P_CHARSET);
- appendShortInteger(charset);
- }
-
- int contentTypeLength = contentTypeBegin.getLength();
- mStack.pop();
- appendValueLength(contentTypeLength);
- mStack.copy();
-
- // content id
- byte[] contentId = part.getContentId();
-
- if (null != contentId) {
- appendOctet(PduPart.P_CONTENT_ID);
- if (('<' == contentId[0]) && ('>' == contentId[contentId.length - 1])) {
- appendQuotedString(contentId);
- } else {
- appendQuotedString("<" + new String(contentId) + ">");
- }
- }
-
- // content-location
- byte[] contentLocation = part.getContentLocation();
- if (null != contentLocation) {
- appendOctet(PduPart.P_CONTENT_LOCATION);
- appendTextString(contentLocation);
- }
-
- // content
- int headerLength = attachment.getLength();
-
- int dataLength = 0; // Just for safety...
- byte[] partData = part.getData();
-
- if (partData != null) {
- arraycopy(partData, 0, partData.length);
- dataLength = partData.length;
- } else {
- InputStream cr;
- try {
- byte[] buffer = new byte[PDU_COMPOSER_BLOCK_SIZE];
- cr = mResolver.openInputStream(part.getDataUri());
- int len = 0;
- while ((len = cr.read(buffer)) != -1) {
- mMessage.write(buffer, 0, len);
- mPosition += len;
- dataLength += len;
- }
- } catch (FileNotFoundException e) {
- return PDU_COMPOSE_CONTENT_ERROR;
- } catch (IOException e) {
- return PDU_COMPOSE_CONTENT_ERROR;
- } catch (RuntimeException e) {
- return PDU_COMPOSE_CONTENT_ERROR;
- }
- }
-
- if (dataLength != (attachment.getLength() - headerLength)) {
- throw new RuntimeException("BUG: Length sanity check failed");
- }
-
- mStack.pop();
- appendUintvarInteger(headerLength);
- appendUintvarInteger(dataLength);
- mStack.copy();
- }
-
- return PDU_COMPOSE_SUCCESS;
- }
-
- /**
- * Record current message informations.
- */
- static private class LengthRecordNode {
- ByteArrayOutputStream currentMessage = null;
- public int currentPosition = 0;
-
- public LengthRecordNode next = null;
- }
-
- /**
- * Mark current message position and stact size.
- */
- private class PositionMarker {
- private int c_pos; // Current position
- private int currentStackSize; // Current stack size
-
- int getLength() {
- // If these assert fails, likely that you are finding the
- // size of buffer that is deep in BufferStack you can only
- // find the length of the buffer that is on top
- if (currentStackSize != mStack.stackSize) {
- throw new RuntimeException("BUG: Invalid call to getLength()");
- }
-
- return mPosition - c_pos;
- }
- }
-
- /**
- * This implementation can be OPTIMIZED to use only
- * 2 buffers. This optimization involves changing BufferStack
- * only... Its usage (interface) will not change.
- */
- private class BufferStack {
- private LengthRecordNode stack = null;
- private LengthRecordNode toCopy = null;
-
- int stackSize = 0;
-
- /**
- * Create a new message buffer and push it into the stack.
- */
- void newbuf() {
- // You can't create a new buff when toCopy != null
- // That is after calling pop() and before calling copy()
- // If you do, it is a bug
- if (toCopy != null) {
- throw new RuntimeException("BUG: Invalid newbuf() before copy()");
- }
-
- LengthRecordNode temp = new LengthRecordNode();
-
- temp.currentMessage = mMessage;
- temp.currentPosition = mPosition;
-
- temp.next = stack;
- stack = temp;
-
- stackSize = stackSize + 1;
-
- mMessage = new ByteArrayOutputStream();
- mPosition = 0;
- }
-
- /**
- * Pop the message before and record current message in the stack.
- */
- void pop() {
- ByteArrayOutputStream currentMessage = mMessage;
- int currentPosition = mPosition;
-
- mMessage = stack.currentMessage;
- mPosition = stack.currentPosition;
-
- toCopy = stack;
- // Re using the top element of the stack to avoid memory allocation
-
- stack = stack.next;
- stackSize = stackSize - 1;
-
- toCopy.currentMessage = currentMessage;
- toCopy.currentPosition = currentPosition;
- }
-
- /**
- * Append current message to the message before.
- */
- void copy() {
- arraycopy(toCopy.currentMessage.toByteArray(), 0,
- toCopy.currentPosition);
-
- toCopy = null;
- }
-
- /**
- * Mark current message position
- */
- PositionMarker mark() {
- PositionMarker m = new PositionMarker();
-
- m.c_pos = mPosition;
- m.currentStackSize = stackSize;
-
- return m;
- }
- }
-
- /**
- * Check address type.
- *
- * @param address address string without the postfix stinng type,
- * such as "/TYPE=PLMN", "/TYPE=IPv6" and "/TYPE=IPv4"
- * @return PDU_PHONE_NUMBER_ADDRESS_TYPE if it is phone number,
- * PDU_EMAIL_ADDRESS_TYPE if it is email address,
- * PDU_IPV4_ADDRESS_TYPE if it is ipv4 address,
- * PDU_IPV6_ADDRESS_TYPE if it is ipv6 address,
- * PDU_UNKNOWN_ADDRESS_TYPE if it is unknown.
- */
- protected static int checkAddressType(String address) {
- /**
- * From OMA-TS-MMS-ENC-V1_3-20050927-C.pdf, section 8.
- * address = ( e-mail / device-address / alphanum-shortcode / num-shortcode)
- * e-mail = mailbox; to the definition of mailbox as described in
- * section 3.4 of [RFC2822], but excluding the
- * obsolete definitions as indicated by the "obs-" prefix.
- * device-address = ( global-phone-number "/TYPE=PLMN" )
- * / ( ipv4 "/TYPE=IPv4" ) / ( ipv6 "/TYPE=IPv6" )
- * / ( escaped-value "/TYPE=" address-type )
- *
- * global-phone-number = ["+"] 1*( DIGIT / written-sep )
- * written-sep =("-"/".")
- *
- * ipv4 = 1*3DIGIT 3( "." 1*3DIGIT ) ; IPv4 address value
- *
- * ipv6 = 4HEXDIG 7( ":" 4HEXDIG ) ; IPv6 address per RFC 2373
- */
-
- if (null == address) {
- return PDU_UNKNOWN_ADDRESS_TYPE;
- }
-
- if (address.matches(REGEXP_IPV4_ADDRESS_TYPE)) {
- // Ipv4 address.
- return PDU_IPV4_ADDRESS_TYPE;
- }else if (address.matches(REGEXP_PHONE_NUMBER_ADDRESS_TYPE)) {
- // Phone number.
- return PDU_PHONE_NUMBER_ADDRESS_TYPE;
- } else if (address.matches(REGEXP_EMAIL_ADDRESS_TYPE)) {
- // Email address.
- return PDU_EMAIL_ADDRESS_TYPE;
- } else if (address.matches(REGEXP_IPV6_ADDRESS_TYPE)) {
- // Ipv6 address.
- return PDU_IPV6_ADDRESS_TYPE;
- } else {
- // Unknown address.
- return PDU_UNKNOWN_ADDRESS_TYPE;
- }
- }
-}
diff --git a/core/java/com/google/android/mms/pdu/PduContentTypes.java b/core/java/com/google/android/mms/pdu/PduContentTypes.java
deleted file mode 100644
index 7799e0e..0000000
--- a/core/java/com/google/android/mms/pdu/PduContentTypes.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-public class PduContentTypes {
- /**
- * All content types. From:
- * http://www.openmobilealliance.org/tech/omna/omna-wsp-content-type.htm
- */
- static final String[] contentTypes = {
- "*/*", /* 0x00 */
- "text/*", /* 0x01 */
- "text/html", /* 0x02 */
- "text/plain", /* 0x03 */
- "text/x-hdml", /* 0x04 */
- "text/x-ttml", /* 0x05 */
- "text/x-vCalendar", /* 0x06 */
- "text/x-vCard", /* 0x07 */
- "text/vnd.wap.wml", /* 0x08 */
- "text/vnd.wap.wmlscript", /* 0x09 */
- "text/vnd.wap.wta-event", /* 0x0A */
- "multipart/*", /* 0x0B */
- "multipart/mixed", /* 0x0C */
- "multipart/form-data", /* 0x0D */
- "multipart/byterantes", /* 0x0E */
- "multipart/alternative", /* 0x0F */
- "application/*", /* 0x10 */
- "application/java-vm", /* 0x11 */
- "application/x-www-form-urlencoded", /* 0x12 */
- "application/x-hdmlc", /* 0x13 */
- "application/vnd.wap.wmlc", /* 0x14 */
- "application/vnd.wap.wmlscriptc", /* 0x15 */
- "application/vnd.wap.wta-eventc", /* 0x16 */
- "application/vnd.wap.uaprof", /* 0x17 */
- "application/vnd.wap.wtls-ca-certificate", /* 0x18 */
- "application/vnd.wap.wtls-user-certificate", /* 0x19 */
- "application/x-x509-ca-cert", /* 0x1A */
- "application/x-x509-user-cert", /* 0x1B */
- "image/*", /* 0x1C */
- "image/gif", /* 0x1D */
- "image/jpeg", /* 0x1E */
- "image/tiff", /* 0x1F */
- "image/png", /* 0x20 */
- "image/vnd.wap.wbmp", /* 0x21 */
- "application/vnd.wap.multipart.*", /* 0x22 */
- "application/vnd.wap.multipart.mixed", /* 0x23 */
- "application/vnd.wap.multipart.form-data", /* 0x24 */
- "application/vnd.wap.multipart.byteranges", /* 0x25 */
- "application/vnd.wap.multipart.alternative", /* 0x26 */
- "application/xml", /* 0x27 */
- "text/xml", /* 0x28 */
- "application/vnd.wap.wbxml", /* 0x29 */
- "application/x-x968-cross-cert", /* 0x2A */
- "application/x-x968-ca-cert", /* 0x2B */
- "application/x-x968-user-cert", /* 0x2C */
- "text/vnd.wap.si", /* 0x2D */
- "application/vnd.wap.sic", /* 0x2E */
- "text/vnd.wap.sl", /* 0x2F */
- "application/vnd.wap.slc", /* 0x30 */
- "text/vnd.wap.co", /* 0x31 */
- "application/vnd.wap.coc", /* 0x32 */
- "application/vnd.wap.multipart.related", /* 0x33 */
- "application/vnd.wap.sia", /* 0x34 */
- "text/vnd.wap.connectivity-xml", /* 0x35 */
- "application/vnd.wap.connectivity-wbxml", /* 0x36 */
- "application/pkcs7-mime", /* 0x37 */
- "application/vnd.wap.hashed-certificate", /* 0x38 */
- "application/vnd.wap.signed-certificate", /* 0x39 */
- "application/vnd.wap.cert-response", /* 0x3A */
- "application/xhtml+xml", /* 0x3B */
- "application/wml+xml", /* 0x3C */
- "text/css", /* 0x3D */
- "application/vnd.wap.mms-message", /* 0x3E */
- "application/vnd.wap.rollover-certificate", /* 0x3F */
- "application/vnd.wap.locc+wbxml", /* 0x40 */
- "application/vnd.wap.loc+xml", /* 0x41 */
- "application/vnd.syncml.dm+wbxml", /* 0x42 */
- "application/vnd.syncml.dm+xml", /* 0x43 */
- "application/vnd.syncml.notification", /* 0x44 */
- "application/vnd.wap.xhtml+xml", /* 0x45 */
- "application/vnd.wv.csp.cir", /* 0x46 */
- "application/vnd.oma.dd+xml", /* 0x47 */
- "application/vnd.oma.drm.message", /* 0x48 */
- "application/vnd.oma.drm.content", /* 0x49 */
- "application/vnd.oma.drm.rights+xml", /* 0x4A */
- "application/vnd.oma.drm.rights+wbxml", /* 0x4B */
- "application/vnd.wv.csp+xml", /* 0x4C */
- "application/vnd.wv.csp+wbxml", /* 0x4D */
- "application/vnd.syncml.ds.notification", /* 0x4E */
- "audio/*", /* 0x4F */
- "video/*", /* 0x50 */
- "application/vnd.oma.dd2+xml", /* 0x51 */
- "application/mikey" /* 0x52 */
- };
-}
diff --git a/core/java/com/google/android/mms/pdu/PduHeaders.java b/core/java/com/google/android/mms/pdu/PduHeaders.java
deleted file mode 100644
index 4313815..0000000
--- a/core/java/com/google/android/mms/pdu/PduHeaders.java
+++ /dev/null
@@ -1,721 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import com.google.android.mms.InvalidHeaderValueException;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-public class PduHeaders {
- /**
- * All pdu header fields.
- */
- public static final int BCC = 0x81;
- public static final int CC = 0x82;
- public static final int CONTENT_LOCATION = 0x83;
- public static final int CONTENT_TYPE = 0x84;
- public static final int DATE = 0x85;
- public static final int DELIVERY_REPORT = 0x86;
- public static final int DELIVERY_TIME = 0x87;
- public static final int EXPIRY = 0x88;
- public static final int FROM = 0x89;
- public static final int MESSAGE_CLASS = 0x8A;
- public static final int MESSAGE_ID = 0x8B;
- public static final int MESSAGE_TYPE = 0x8C;
- public static final int MMS_VERSION = 0x8D;
- public static final int MESSAGE_SIZE = 0x8E;
- public static final int PRIORITY = 0x8F;
-
- public static final int READ_REPLY = 0x90;
- public static final int READ_REPORT = 0x90;
- public static final int REPORT_ALLOWED = 0x91;
- public static final int RESPONSE_STATUS = 0x92;
- public static final int RESPONSE_TEXT = 0x93;
- public static final int SENDER_VISIBILITY = 0x94;
- public static final int STATUS = 0x95;
- public static final int SUBJECT = 0x96;
- public static final int TO = 0x97;
- public static final int TRANSACTION_ID = 0x98;
- public static final int RETRIEVE_STATUS = 0x99;
- public static final int RETRIEVE_TEXT = 0x9A;
- public static final int READ_STATUS = 0x9B;
- public static final int REPLY_CHARGING = 0x9C;
- public static final int REPLY_CHARGING_DEADLINE = 0x9D;
- public static final int REPLY_CHARGING_ID = 0x9E;
- public static final int REPLY_CHARGING_SIZE = 0x9F;
-
- public static final int PREVIOUSLY_SENT_BY = 0xA0;
- public static final int PREVIOUSLY_SENT_DATE = 0xA1;
- public static final int STORE = 0xA2;
- public static final int MM_STATE = 0xA3;
- public static final int MM_FLAGS = 0xA4;
- public static final int STORE_STATUS = 0xA5;
- public static final int STORE_STATUS_TEXT = 0xA6;
- public static final int STORED = 0xA7;
- public static final int ATTRIBUTES = 0xA8;
- public static final int TOTALS = 0xA9;
- public static final int MBOX_TOTALS = 0xAA;
- public static final int QUOTAS = 0xAB;
- public static final int MBOX_QUOTAS = 0xAC;
- public static final int MESSAGE_COUNT = 0xAD;
- public static final int CONTENT = 0xAE;
- public static final int START = 0xAF;
-
- public static final int ADDITIONAL_HEADERS = 0xB0;
- public static final int DISTRIBUTION_INDICATOR = 0xB1;
- public static final int ELEMENT_DESCRIPTOR = 0xB2;
- public static final int LIMIT = 0xB3;
- public static final int RECOMMENDED_RETRIEVAL_MODE = 0xB4;
- public static final int RECOMMENDED_RETRIEVAL_MODE_TEXT = 0xB5;
- public static final int STATUS_TEXT = 0xB6;
- public static final int APPLIC_ID = 0xB7;
- public static final int REPLY_APPLIC_ID = 0xB8;
- public static final int AUX_APPLIC_ID = 0xB9;
- public static final int CONTENT_CLASS = 0xBA;
- public static final int DRM_CONTENT = 0xBB;
- public static final int ADAPTATION_ALLOWED = 0xBC;
- public static final int REPLACE_ID = 0xBD;
- public static final int CANCEL_ID = 0xBE;
- public static final int CANCEL_STATUS = 0xBF;
-
- /**
- * X-Mms-Message-Type field types.
- */
- public static final int MESSAGE_TYPE_SEND_REQ = 0x80;
- public static final int MESSAGE_TYPE_SEND_CONF = 0x81;
- public static final int MESSAGE_TYPE_NOTIFICATION_IND = 0x82;
- public static final int MESSAGE_TYPE_NOTIFYRESP_IND = 0x83;
- public static final int MESSAGE_TYPE_RETRIEVE_CONF = 0x84;
- public static final int MESSAGE_TYPE_ACKNOWLEDGE_IND = 0x85;
- public static final int MESSAGE_TYPE_DELIVERY_IND = 0x86;
- public static final int MESSAGE_TYPE_READ_REC_IND = 0x87;
- public static final int MESSAGE_TYPE_READ_ORIG_IND = 0x88;
- public static final int MESSAGE_TYPE_FORWARD_REQ = 0x89;
- public static final int MESSAGE_TYPE_FORWARD_CONF = 0x8A;
- public static final int MESSAGE_TYPE_MBOX_STORE_REQ = 0x8B;
- public static final int MESSAGE_TYPE_MBOX_STORE_CONF = 0x8C;
- public static final int MESSAGE_TYPE_MBOX_VIEW_REQ = 0x8D;
- public static final int MESSAGE_TYPE_MBOX_VIEW_CONF = 0x8E;
- public static final int MESSAGE_TYPE_MBOX_UPLOAD_REQ = 0x8F;
- public static final int MESSAGE_TYPE_MBOX_UPLOAD_CONF = 0x90;
- public static final int MESSAGE_TYPE_MBOX_DELETE_REQ = 0x91;
- public static final int MESSAGE_TYPE_MBOX_DELETE_CONF = 0x92;
- public static final int MESSAGE_TYPE_MBOX_DESCR = 0x93;
- public static final int MESSAGE_TYPE_DELETE_REQ = 0x94;
- public static final int MESSAGE_TYPE_DELETE_CONF = 0x95;
- public static final int MESSAGE_TYPE_CANCEL_REQ = 0x96;
- public static final int MESSAGE_TYPE_CANCEL_CONF = 0x97;
-
- /**
- * X-Mms-Delivery-Report |
- * X-Mms-Read-Report |
- * X-Mms-Report-Allowed |
- * X-Mms-Sender-Visibility |
- * X-Mms-Store |
- * X-Mms-Stored |
- * X-Mms-Totals |
- * X-Mms-Quotas |
- * X-Mms-Distribution-Indicator |
- * X-Mms-DRM-Content |
- * X-Mms-Adaptation-Allowed |
- * field types.
- */
- public static final int VALUE_YES = 0x80;
- public static final int VALUE_NO = 0x81;
-
- /**
- * Delivery-Time |
- * Expiry and Reply-Charging-Deadline |
- * field type components.
- */
- public static final int VALUE_ABSOLUTE_TOKEN = 0x80;
- public static final int VALUE_RELATIVE_TOKEN = 0x81;
-
- /**
- * X-Mms-MMS-Version field types.
- */
- public static final int MMS_VERSION_1_3 = ((1 << 4) | 3);
- public static final int MMS_VERSION_1_2 = ((1 << 4) | 2);
- public static final int MMS_VERSION_1_1 = ((1 << 4) | 1);
- public static final int MMS_VERSION_1_0 = ((1 << 4) | 0);
-
- // Current version is 1.2.
- public static final int CURRENT_MMS_VERSION = MMS_VERSION_1_2;
-
- /**
- * From field type components.
- */
- public static final int FROM_ADDRESS_PRESENT_TOKEN = 0x80;
- public static final int FROM_INSERT_ADDRESS_TOKEN = 0x81;
-
- public static final String FROM_ADDRESS_PRESENT_TOKEN_STR = "address-present-token";
- public static final String FROM_INSERT_ADDRESS_TOKEN_STR = "insert-address-token";
-
- /**
- * X-Mms-Status Field.
- */
- public static final int STATUS_EXPIRED = 0x80;
- public static final int STATUS_RETRIEVED = 0x81;
- public static final int STATUS_REJECTED = 0x82;
- public static final int STATUS_DEFERRED = 0x83;
- public static final int STATUS_UNRECOGNIZED = 0x84;
- public static final int STATUS_INDETERMINATE = 0x85;
- public static final int STATUS_FORWARDED = 0x86;
- public static final int STATUS_UNREACHABLE = 0x87;
-
- /**
- * MM-Flags field type components.
- */
- public static final int MM_FLAGS_ADD_TOKEN = 0x80;
- public static final int MM_FLAGS_REMOVE_TOKEN = 0x81;
- public static final int MM_FLAGS_FILTER_TOKEN = 0x82;
-
- /**
- * X-Mms-Message-Class field types.
- */
- public static final int MESSAGE_CLASS_PERSONAL = 0x80;
- public static final int MESSAGE_CLASS_ADVERTISEMENT = 0x81;
- public static final int MESSAGE_CLASS_INFORMATIONAL = 0x82;
- public static final int MESSAGE_CLASS_AUTO = 0x83;
-
- public static final String MESSAGE_CLASS_PERSONAL_STR = "personal";
- public static final String MESSAGE_CLASS_ADVERTISEMENT_STR = "advertisement";
- public static final String MESSAGE_CLASS_INFORMATIONAL_STR = "informational";
- public static final String MESSAGE_CLASS_AUTO_STR = "auto";
-
- /**
- * X-Mms-Priority field types.
- */
- public static final int PRIORITY_LOW = 0x80;
- public static final int PRIORITY_NORMAL = 0x81;
- public static final int PRIORITY_HIGH = 0x82;
-
- /**
- * X-Mms-Response-Status field types.
- */
- public static final int RESPONSE_STATUS_OK = 0x80;
- public static final int RESPONSE_STATUS_ERROR_UNSPECIFIED = 0x81;
- public static final int RESPONSE_STATUS_ERROR_SERVICE_DENIED = 0x82;
-
- public static final int RESPONSE_STATUS_ERROR_MESSAGE_FORMAT_CORRUPT = 0x83;
- public static final int RESPONSE_STATUS_ERROR_SENDING_ADDRESS_UNRESOLVED = 0x84;
-
- public static final int RESPONSE_STATUS_ERROR_MESSAGE_NOT_FOUND = 0x85;
- public static final int RESPONSE_STATUS_ERROR_NETWORK_PROBLEM = 0x86;
- public static final int RESPONSE_STATUS_ERROR_CONTENT_NOT_ACCEPTED = 0x87;
- public static final int RESPONSE_STATUS_ERROR_UNSUPPORTED_MESSAGE = 0x88;
- public static final int RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE = 0xC0;
-
- public static final int RESPONSE_STATUS_ERROR_TRANSIENT_SENDNG_ADDRESS_UNRESOLVED = 0xC1;
- public static final int RESPONSE_STATUS_ERROR_TRANSIENT_MESSAGE_NOT_FOUND = 0xC2;
- public static final int RESPONSE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM = 0xC3;
- public static final int RESPONSE_STATUS_ERROR_TRANSIENT_PARTIAL_SUCCESS = 0xC4;
-
- public static final int RESPONSE_STATUS_ERROR_PERMANENT_FAILURE = 0xE0;
- public static final int RESPONSE_STATUS_ERROR_PERMANENT_SERVICE_DENIED = 0xE1;
- public static final int RESPONSE_STATUS_ERROR_PERMANENT_MESSAGE_FORMAT_CORRUPT = 0xE2;
- public static final int RESPONSE_STATUS_ERROR_PERMANENT_SENDING_ADDRESS_UNRESOLVED = 0xE3;
- public static final int RESPONSE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND = 0xE4;
- public static final int RESPONSE_STATUS_ERROR_PERMANENT_CONTENT_NOT_ACCEPTED = 0xE5;
- public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_LIMITATIONS_NOT_MET = 0xE6;
- public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_REQUEST_NOT_ACCEPTED = 0xE6;
- public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_FORWARDING_DENIED = 0xE8;
- public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_NOT_SUPPORTED = 0xE9;
- public static final int RESPONSE_STATUS_ERROR_PERMANENT_ADDRESS_HIDING_NOT_SUPPORTED = 0xEA;
- public static final int RESPONSE_STATUS_ERROR_PERMANENT_LACK_OF_PREPAID = 0xEB;
- public static final int RESPONSE_STATUS_ERROR_PERMANENT_END = 0xFF;
-
- /**
- * X-Mms-Retrieve-Status field types.
- */
- public static final int RETRIEVE_STATUS_OK = 0x80;
- public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE = 0xC0;
- public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_MESSAGE_NOT_FOUND = 0xC1;
- public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM = 0xC2;
- public static final int RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE = 0xE0;
- public static final int RETRIEVE_STATUS_ERROR_PERMANENT_SERVICE_DENIED = 0xE1;
- public static final int RETRIEVE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND = 0xE2;
- public static final int RETRIEVE_STATUS_ERROR_PERMANENT_CONTENT_UNSUPPORTED = 0xE3;
- public static final int RETRIEVE_STATUS_ERROR_END = 0xFF;
-
- /**
- * X-Mms-Sender-Visibility field types.
- */
- public static final int SENDER_VISIBILITY_HIDE = 0x80;
- public static final int SENDER_VISIBILITY_SHOW = 0x81;
-
- /**
- * X-Mms-Read-Status field types.
- */
- public static final int READ_STATUS_READ = 0x80;
- public static final int READ_STATUS__DELETED_WITHOUT_BEING_READ = 0x81;
-
- /**
- * X-Mms-Cancel-Status field types.
- */
- public static final int CANCEL_STATUS_REQUEST_SUCCESSFULLY_RECEIVED = 0x80;
- public static final int CANCEL_STATUS_REQUEST_CORRUPTED = 0x81;
-
- /**
- * X-Mms-Reply-Charging field types.
- */
- public static final int REPLY_CHARGING_REQUESTED = 0x80;
- public static final int REPLY_CHARGING_REQUESTED_TEXT_ONLY = 0x81;
- public static final int REPLY_CHARGING_ACCEPTED = 0x82;
- public static final int REPLY_CHARGING_ACCEPTED_TEXT_ONLY = 0x83;
-
- /**
- * X-Mms-MM-State field types.
- */
- public static final int MM_STATE_DRAFT = 0x80;
- public static final int MM_STATE_SENT = 0x81;
- public static final int MM_STATE_NEW = 0x82;
- public static final int MM_STATE_RETRIEVED = 0x83;
- public static final int MM_STATE_FORWARDED = 0x84;
-
- /**
- * X-Mms-Recommended-Retrieval-Mode field types.
- */
- public static final int RECOMMENDED_RETRIEVAL_MODE_MANUAL = 0x80;
-
- /**
- * X-Mms-Content-Class field types.
- */
- public static final int CONTENT_CLASS_TEXT = 0x80;
- public static final int CONTENT_CLASS_IMAGE_BASIC = 0x81;
- public static final int CONTENT_CLASS_IMAGE_RICH = 0x82;
- public static final int CONTENT_CLASS_VIDEO_BASIC = 0x83;
- public static final int CONTENT_CLASS_VIDEO_RICH = 0x84;
- public static final int CONTENT_CLASS_MEGAPIXEL = 0x85;
- public static final int CONTENT_CLASS_CONTENT_BASIC = 0x86;
- public static final int CONTENT_CLASS_CONTENT_RICH = 0x87;
-
- /**
- * X-Mms-Store-Status field types.
- */
- public static final int STORE_STATUS_SUCCESS = 0x80;
- public static final int STORE_STATUS_ERROR_TRANSIENT_FAILURE = 0xC0;
- public static final int STORE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM = 0xC1;
- public static final int STORE_STATUS_ERROR_PERMANENT_FAILURE = 0xE0;
- public static final int STORE_STATUS_ERROR_PERMANENT_SERVICE_DENIED = 0xE1;
- public static final int STORE_STATUS_ERROR_PERMANENT_MESSAGE_FORMAT_CORRUPT = 0xE2;
- public static final int STORE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND = 0xE3;
- public static final int STORE_STATUS_ERROR_PERMANENT_MMBOX_FULL = 0xE4;
- public static final int STORE_STATUS_ERROR_END = 0xFF;
-
- /**
- * The map contains the value of all headers.
- */
- private HashMap<Integer, Object> mHeaderMap = null;
-
- /**
- * Constructor of PduHeaders.
- */
- public PduHeaders() {
- mHeaderMap = new HashMap<Integer, Object>();
- }
-
- /**
- * Get octet value by header field.
- *
- * @param field the field
- * @return the octet value of the pdu header
- * with specified header field. Return 0 if
- * the value is not set.
- */
- protected int getOctet(int field) {
- Integer octet = (Integer) mHeaderMap.get(field);
- if (null == octet) {
- return 0;
- }
-
- return octet;
- }
-
- /**
- * Set octet value to pdu header by header field.
- *
- * @param value the value
- * @param field the field
- * @throws InvalidHeaderValueException if the value is invalid.
- */
- protected void setOctet(int value, int field)
- throws InvalidHeaderValueException{
- /**
- * Check whether this field can be set for specific
- * header and check validity of the field.
- */
- switch (field) {
- case REPORT_ALLOWED:
- case ADAPTATION_ALLOWED:
- case DELIVERY_REPORT:
- case DRM_CONTENT:
- case DISTRIBUTION_INDICATOR:
- case QUOTAS:
- case READ_REPORT:
- case STORE:
- case STORED:
- case TOTALS:
- case SENDER_VISIBILITY:
- if ((VALUE_YES != value) && (VALUE_NO != value)) {
- // Invalid value.
- throw new InvalidHeaderValueException("Invalid Octet value!");
- }
- break;
- case READ_STATUS:
- if ((READ_STATUS_READ != value) &&
- (READ_STATUS__DELETED_WITHOUT_BEING_READ != value)) {
- // Invalid value.
- throw new InvalidHeaderValueException("Invalid Octet value!");
- }
- break;
- case CANCEL_STATUS:
- if ((CANCEL_STATUS_REQUEST_SUCCESSFULLY_RECEIVED != value) &&
- (CANCEL_STATUS_REQUEST_CORRUPTED != value)) {
- // Invalid value.
- throw new InvalidHeaderValueException("Invalid Octet value!");
- }
- break;
- case PRIORITY:
- if ((value < PRIORITY_LOW) || (value > PRIORITY_HIGH)) {
- // Invalid value.
- throw new InvalidHeaderValueException("Invalid Octet value!");
- }
- break;
- case STATUS:
- if ((value < STATUS_EXPIRED) || (value > STATUS_UNREACHABLE)) {
- // Invalid value.
- throw new InvalidHeaderValueException("Invalid Octet value!");
- }
- break;
- case REPLY_CHARGING:
- if ((value < REPLY_CHARGING_REQUESTED)
- || (value > REPLY_CHARGING_ACCEPTED_TEXT_ONLY)) {
- // Invalid value.
- throw new InvalidHeaderValueException("Invalid Octet value!");
- }
- break;
- case MM_STATE:
- if ((value < MM_STATE_DRAFT) || (value > MM_STATE_FORWARDED)) {
- // Invalid value.
- throw new InvalidHeaderValueException("Invalid Octet value!");
- }
- break;
- case RECOMMENDED_RETRIEVAL_MODE:
- if (RECOMMENDED_RETRIEVAL_MODE_MANUAL != value) {
- // Invalid value.
- throw new InvalidHeaderValueException("Invalid Octet value!");
- }
- break;
- case CONTENT_CLASS:
- if ((value < CONTENT_CLASS_TEXT)
- || (value > CONTENT_CLASS_CONTENT_RICH)) {
- // Invalid value.
- throw new InvalidHeaderValueException("Invalid Octet value!");
- }
- break;
- case RETRIEVE_STATUS:
- // According to oma-ts-mms-enc-v1_3, section 7.3.50, we modify the invalid value.
- if ((value > RETRIEVE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM) &&
- (value < RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE)) {
- value = RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE;
- } else if ((value > RETRIEVE_STATUS_ERROR_PERMANENT_CONTENT_UNSUPPORTED) &&
- (value <= RETRIEVE_STATUS_ERROR_END)) {
- value = RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE;
- } else if ((value < RETRIEVE_STATUS_OK) ||
- ((value > RETRIEVE_STATUS_OK) &&
- (value < RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
- (value > RETRIEVE_STATUS_ERROR_END)) {
- value = RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE;
- }
- break;
- case STORE_STATUS:
- // According to oma-ts-mms-enc-v1_3, section 7.3.58, we modify the invalid value.
- if ((value > STORE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM) &&
- (value < STORE_STATUS_ERROR_PERMANENT_FAILURE)) {
- value = STORE_STATUS_ERROR_TRANSIENT_FAILURE;
- } else if ((value > STORE_STATUS_ERROR_PERMANENT_MMBOX_FULL) &&
- (value <= STORE_STATUS_ERROR_END)) {
- value = STORE_STATUS_ERROR_PERMANENT_FAILURE;
- } else if ((value < STORE_STATUS_SUCCESS) ||
- ((value > STORE_STATUS_SUCCESS) &&
- (value < STORE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
- (value > STORE_STATUS_ERROR_END)) {
- value = STORE_STATUS_ERROR_PERMANENT_FAILURE;
- }
- break;
- case RESPONSE_STATUS:
- // According to oma-ts-mms-enc-v1_3, section 7.3.48, we modify the invalid value.
- if ((value > RESPONSE_STATUS_ERROR_TRANSIENT_PARTIAL_SUCCESS) &&
- (value < RESPONSE_STATUS_ERROR_PERMANENT_FAILURE)) {
- value = RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE;
- } else if (((value > RESPONSE_STATUS_ERROR_PERMANENT_LACK_OF_PREPAID) &&
- (value <= RESPONSE_STATUS_ERROR_PERMANENT_END)) ||
- (value < RESPONSE_STATUS_OK) ||
- ((value > RESPONSE_STATUS_ERROR_UNSUPPORTED_MESSAGE) &&
- (value < RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
- (value > RESPONSE_STATUS_ERROR_PERMANENT_END)) {
- value = RESPONSE_STATUS_ERROR_PERMANENT_FAILURE;
- }
- break;
- case MMS_VERSION:
- if ((value < MMS_VERSION_1_0)|| (value > MMS_VERSION_1_3)) {
- value = CURRENT_MMS_VERSION; // Current version is the default value.
- }
- break;
- case MESSAGE_TYPE:
- if ((value < MESSAGE_TYPE_SEND_REQ) || (value > MESSAGE_TYPE_CANCEL_CONF)) {
- // Invalid value.
- throw new InvalidHeaderValueException("Invalid Octet value!");
- }
- break;
- default:
- // This header value should not be Octect.
- throw new RuntimeException("Invalid header field!");
- }
- mHeaderMap.put(field, value);
- }
-
- /**
- * Get TextString value by header field.
- *
- * @param field the field
- * @return the TextString value of the pdu header
- * with specified header field
- */
- protected byte[] getTextString(int field) {
- return (byte[]) mHeaderMap.get(field);
- }
-
- /**
- * Set TextString value to pdu header by header field.
- *
- * @param value the value
- * @param field the field
- * @return the TextString value of the pdu header
- * with specified header field
- * @throws NullPointerException if the value is null.
- */
- protected void setTextString(byte[] value, int field) {
- /**
- * Check whether this field can be set for specific
- * header and check validity of the field.
- */
- if (null == value) {
- throw new NullPointerException();
- }
-
- switch (field) {
- case TRANSACTION_ID:
- case REPLY_CHARGING_ID:
- case AUX_APPLIC_ID:
- case APPLIC_ID:
- case REPLY_APPLIC_ID:
- case MESSAGE_ID:
- case REPLACE_ID:
- case CANCEL_ID:
- case CONTENT_LOCATION:
- case MESSAGE_CLASS:
- case CONTENT_TYPE:
- break;
- default:
- // This header value should not be Text-String.
- throw new RuntimeException("Invalid header field!");
- }
- mHeaderMap.put(field, value);
- }
-
- /**
- * Get EncodedStringValue value by header field.
- *
- * @param field the field
- * @return the EncodedStringValue value of the pdu header
- * with specified header field
- */
- protected EncodedStringValue getEncodedStringValue(int field) {
- return (EncodedStringValue) mHeaderMap.get(field);
- }
-
- /**
- * Get TO, CC or BCC header value.
- *
- * @param field the field
- * @return the EncodeStringValue array of the pdu header
- * with specified header field
- */
- protected EncodedStringValue[] getEncodedStringValues(int field) {
- ArrayList<EncodedStringValue> list =
- (ArrayList<EncodedStringValue>) mHeaderMap.get(field);
- if (null == list) {
- return null;
- }
- EncodedStringValue[] values = new EncodedStringValue[list.size()];
- return list.toArray(values);
- }
-
- /**
- * Set EncodedStringValue value to pdu header by header field.
- *
- * @param value the value
- * @param field the field
- * @return the EncodedStringValue value of the pdu header
- * with specified header field
- * @throws NullPointerException if the value is null.
- */
- protected void setEncodedStringValue(EncodedStringValue value, int field) {
- /**
- * Check whether this field can be set for specific
- * header and check validity of the field.
- */
- if (null == value) {
- throw new NullPointerException();
- }
-
- switch (field) {
- case SUBJECT:
- case RECOMMENDED_RETRIEVAL_MODE_TEXT:
- case RETRIEVE_TEXT:
- case STATUS_TEXT:
- case STORE_STATUS_TEXT:
- case RESPONSE_TEXT:
- case FROM:
- case PREVIOUSLY_SENT_BY:
- case MM_FLAGS:
- break;
- default:
- // This header value should not be Encoded-String-Value.
- throw new RuntimeException("Invalid header field!");
- }
-
- mHeaderMap.put(field, value);
- }
-
- /**
- * Set TO, CC or BCC header value.
- *
- * @param value the value
- * @param field the field
- * @return the EncodedStringValue value array of the pdu header
- * with specified header field
- * @throws NullPointerException if the value is null.
- */
- protected void setEncodedStringValues(EncodedStringValue[] value, int field) {
- /**
- * Check whether this field can be set for specific
- * header and check validity of the field.
- */
- if (null == value) {
- throw new NullPointerException();
- }
-
- switch (field) {
- case BCC:
- case CC:
- case TO:
- break;
- default:
- // This header value should not be Encoded-String-Value.
- throw new RuntimeException("Invalid header field!");
- }
-
- ArrayList<EncodedStringValue> list = new ArrayList<EncodedStringValue>();
- for (int i = 0; i < value.length; i++) {
- list.add(value[i]);
- }
- mHeaderMap.put(field, list);
- }
-
- /**
- * Append one EncodedStringValue to another.
- *
- * @param value the EncodedStringValue to append
- * @param field the field
- * @throws NullPointerException if the value is null.
- */
- protected void appendEncodedStringValue(EncodedStringValue value,
- int field) {
- if (null == value) {
- throw new NullPointerException();
- }
-
- switch (field) {
- case BCC:
- case CC:
- case TO:
- break;
- default:
- throw new RuntimeException("Invalid header field!");
- }
-
- ArrayList<EncodedStringValue> list =
- (ArrayList<EncodedStringValue>) mHeaderMap.get(field);
- if (null == list) {
- list = new ArrayList<EncodedStringValue>();
- }
- list.add(value);
- mHeaderMap.put(field, list);
- }
-
- /**
- * Get LongInteger value by header field.
- *
- * @param field the field
- * @return the LongInteger value of the pdu header
- * with specified header field. if return -1, the
- * field is not existed in pdu header.
- */
- protected long getLongInteger(int field) {
- Long longInteger = (Long) mHeaderMap.get(field);
- if (null == longInteger) {
- return -1;
- }
-
- return longInteger.longValue();
- }
-
- /**
- * Set LongInteger value to pdu header by header field.
- *
- * @param value the value
- * @param field the field
- */
- protected void setLongInteger(long value, int field) {
- /**
- * Check whether this field can be set for specific
- * header and check validity of the field.
- */
- switch (field) {
- case DATE:
- case REPLY_CHARGING_SIZE:
- case MESSAGE_SIZE:
- case MESSAGE_COUNT:
- case START:
- case LIMIT:
- case DELIVERY_TIME:
- case EXPIRY:
- case REPLY_CHARGING_DEADLINE:
- case PREVIOUSLY_SENT_DATE:
- break;
- default:
- // This header value should not be LongInteger.
- throw new RuntimeException("Invalid header field!");
- }
- mHeaderMap.put(field, value);
- }
-}
diff --git a/core/java/com/google/android/mms/pdu/PduParser.java b/core/java/com/google/android/mms/pdu/PduParser.java
deleted file mode 100644
index d465c5a..0000000
--- a/core/java/com/google/android/mms/pdu/PduParser.java
+++ /dev/null
@@ -1,1868 +0,0 @@
-/*
- * Copyright (C) 2007-2008 Esmertec AG.
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import com.google.android.mms.ContentType;
-import com.google.android.mms.InvalidHeaderValueException;
-
-import android.util.Config;
-import android.util.Log;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.Arrays;
-import java.util.HashMap;
-
-public class PduParser {
- /**
- * The next are WAP values defined in WSP specification.
- */
- private static final int QUOTE = 127;
- private static final int LENGTH_QUOTE = 31;
- private static final int TEXT_MIN = 32;
- private static final int TEXT_MAX = 127;
- private static final int SHORT_INTEGER_MAX = 127;
- private static final int SHORT_LENGTH_MAX = 30;
- private static final int LONG_INTEGER_LENGTH_MAX = 8;
- private static final int QUOTED_STRING_FLAG = 34;
- private static final int END_STRING_FLAG = 0x00;
- //The next two are used by the interface "parseWapString" to
- //distinguish Text-String and Quoted-String.
- private static final int TYPE_TEXT_STRING = 0;
- private static final int TYPE_QUOTED_STRING = 1;
- private static final int TYPE_TOKEN_STRING = 2;
-
- /**
- * Specify the part position.
- */
- private static final int THE_FIRST_PART = 0;
- private static final int THE_LAST_PART = 1;
-
- /**
- * The pdu data.
- */
- private ByteArrayInputStream mPduDataStream = null;
-
- /**
- * Store pdu headers
- */
- private PduHeaders mHeaders = null;
-
- /**
- * Store pdu parts.
- */
- private PduBody mBody = null;
-
- /**
- * Store the "type" parameter in "Content-Type" header field.
- */
- private static byte[] mTypeParam = null;
-
- /**
- * Store the "start" parameter in "Content-Type" header field.
- */
- private static byte[] mStartParam = null;
-
- /**
- * The log tag.
- */
- private static final String LOG_TAG = "PduParser";
- private static final boolean DEBUG = false;
- private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
-
- /**
- * Constructor.
- *
- * @param pduDataStream pdu data to be parsed
- */
- public PduParser(byte[] pduDataStream) {
- mPduDataStream = new ByteArrayInputStream(pduDataStream);
- }
-
- /**
- * Parse the pdu.
- *
- * @return the pdu structure if parsing successfully.
- * null if parsing error happened or mandatory fields are not set.
- */
- public GenericPdu parse(){
- if (mPduDataStream == null) {
- return null;
- }
-
- /* parse headers */
- mHeaders = parseHeaders(mPduDataStream);
- if (null == mHeaders) {
- // Parse headers failed.
- return null;
- }
-
- /* get the message type */
- int messageType = mHeaders.getOctet(PduHeaders.MESSAGE_TYPE);
-
- /* check mandatory header fields */
- if (false == checkMandatoryHeader(mHeaders)) {
- log("check mandatory headers failed!");
- return null;
- }
-
- if ((PduHeaders.MESSAGE_TYPE_SEND_REQ == messageType) ||
- (PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF == messageType)) {
- /* need to parse the parts */
- mBody = parseParts(mPduDataStream);
- if (null == mBody) {
- // Parse parts failed.
- return null;
- }
- }
-
- switch (messageType) {
- case PduHeaders.MESSAGE_TYPE_SEND_REQ:
- SendReq sendReq = new SendReq(mHeaders, mBody);
- return sendReq;
- case PduHeaders.MESSAGE_TYPE_SEND_CONF:
- SendConf sendConf = new SendConf(mHeaders);
- return sendConf;
- case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
- NotificationInd notificationInd =
- new NotificationInd(mHeaders);
- return notificationInd;
- case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
- NotifyRespInd notifyRespInd =
- new NotifyRespInd(mHeaders);
- return notifyRespInd;
- case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
- RetrieveConf retrieveConf =
- new RetrieveConf(mHeaders, mBody);
-
- byte[] contentType = retrieveConf.getContentType();
- if (null == contentType) {
- return null;
- }
- String ctTypeStr = new String(contentType);
- if (ctTypeStr.equals(ContentType.MULTIPART_MIXED)
- || ctTypeStr.equals(ContentType.MULTIPART_RELATED)) {
- // The MMS content type must be "application/vnd.wap.multipart.mixed"
- // or "application/vnd.wap.multipart.related"
- return retrieveConf;
- }
- return null;
- case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
- DeliveryInd deliveryInd =
- new DeliveryInd(mHeaders);
- return deliveryInd;
- case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
- AcknowledgeInd acknowledgeInd =
- new AcknowledgeInd(mHeaders);
- return acknowledgeInd;
- case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND:
- ReadOrigInd readOrigInd =
- new ReadOrigInd(mHeaders);
- return readOrigInd;
- case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
- ReadRecInd readRecInd =
- new ReadRecInd(mHeaders);
- return readRecInd;
- default:
- log("Parser doesn't support this message type in this version!");
- return null;
- }
- }
-
- /**
- * Parse pdu headers.
- *
- * @param pduDataStream pdu data input stream
- * @return headers in PduHeaders structure, null when parse fail
- */
- protected PduHeaders parseHeaders(ByteArrayInputStream pduDataStream){
- if (pduDataStream == null) {
- return null;
- }
-
- boolean keepParsing = true;
- PduHeaders headers = new PduHeaders();
-
- while (keepParsing && (pduDataStream.available() > 0)) {
- int headerField = extractByteValue(pduDataStream);
- switch (headerField) {
- case PduHeaders.MESSAGE_TYPE:
- {
- int messageType = extractByteValue(pduDataStream);
- switch (messageType) {
- // We don't support these kind of messages now.
- case PduHeaders.MESSAGE_TYPE_FORWARD_REQ:
- case PduHeaders.MESSAGE_TYPE_FORWARD_CONF:
- case PduHeaders.MESSAGE_TYPE_MBOX_STORE_REQ:
- case PduHeaders.MESSAGE_TYPE_MBOX_STORE_CONF:
- case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_REQ:
- case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_CONF:
- case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_REQ:
- case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_CONF:
- case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_REQ:
- case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_CONF:
- case PduHeaders.MESSAGE_TYPE_MBOX_DESCR:
- case PduHeaders.MESSAGE_TYPE_DELETE_REQ:
- case PduHeaders.MESSAGE_TYPE_DELETE_CONF:
- case PduHeaders.MESSAGE_TYPE_CANCEL_REQ:
- case PduHeaders.MESSAGE_TYPE_CANCEL_CONF:
- return null;
- }
- try {
- headers.setOctet(messageType, headerField);
- } catch(InvalidHeaderValueException e) {
- log("Set invalid Octet value: " + messageType +
- " into the header filed: " + headerField);
- return null;
- } catch(RuntimeException e) {
- log(headerField + "is not Octet header field!");
- return null;
- }
- break;
- }
- /* Octect value */
- case PduHeaders.REPORT_ALLOWED:
- case PduHeaders.ADAPTATION_ALLOWED:
- case PduHeaders.DELIVERY_REPORT:
- case PduHeaders.DRM_CONTENT:
- case PduHeaders.DISTRIBUTION_INDICATOR:
- case PduHeaders.QUOTAS:
- case PduHeaders.READ_REPORT:
- case PduHeaders.STORE:
- case PduHeaders.STORED:
- case PduHeaders.TOTALS:
- case PduHeaders.SENDER_VISIBILITY:
- case PduHeaders.READ_STATUS:
- case PduHeaders.CANCEL_STATUS:
- case PduHeaders.PRIORITY:
- case PduHeaders.STATUS:
- case PduHeaders.REPLY_CHARGING:
- case PduHeaders.MM_STATE:
- case PduHeaders.RECOMMENDED_RETRIEVAL_MODE:
- case PduHeaders.CONTENT_CLASS:
- case PduHeaders.RETRIEVE_STATUS:
- case PduHeaders.STORE_STATUS:
- /**
- * The following field has a different value when
- * used in the M-Mbox-Delete.conf and M-Delete.conf PDU.
- * For now we ignore this fact, since we do not support these PDUs
- */
- case PduHeaders.RESPONSE_STATUS:
- {
- int value = extractByteValue(pduDataStream);
-
- try {
- headers.setOctet(value, headerField);
- } catch(InvalidHeaderValueException e) {
- log("Set invalid Octet value: " + value +
- " into the header filed: " + headerField);
- return null;
- } catch(RuntimeException e) {
- log(headerField + "is not Octet header field!");
- return null;
- }
- break;
- }
-
- /* Long-Integer */
- case PduHeaders.DATE:
- case PduHeaders.REPLY_CHARGING_SIZE:
- case PduHeaders.MESSAGE_SIZE:
- {
- try {
- long value = parseLongInteger(pduDataStream);
- headers.setLongInteger(value, headerField);
- } catch(RuntimeException e) {
- log(headerField + "is not Long-Integer header field!");
- return null;
- }
- break;
- }
-
- /* Integer-Value */
- case PduHeaders.MESSAGE_COUNT:
- case PduHeaders.START:
- case PduHeaders.LIMIT:
- {
- try {
- long value = parseIntegerValue(pduDataStream);
- headers.setLongInteger(value, headerField);
- } catch(RuntimeException e) {
- log(headerField + "is not Long-Integer header field!");
- return null;
- }
- break;
- }
-
- /* Text-String */
- case PduHeaders.TRANSACTION_ID:
- case PduHeaders.REPLY_CHARGING_ID:
- case PduHeaders.AUX_APPLIC_ID:
- case PduHeaders.APPLIC_ID:
- case PduHeaders.REPLY_APPLIC_ID:
- /**
- * The next three header fields are email addresses
- * as defined in RFC2822,
- * not including the characters "<" and ">"
- */
- case PduHeaders.MESSAGE_ID:
- case PduHeaders.REPLACE_ID:
- case PduHeaders.CANCEL_ID:
- /**
- * The following field has a different value when
- * used in the M-Mbox-Delete.conf and M-Delete.conf PDU.
- * For now we ignore this fact, since we do not support these PDUs
- */
- case PduHeaders.CONTENT_LOCATION:
- {
- byte[] value = parseWapString(pduDataStream, TYPE_TEXT_STRING);
- if (null != value) {
- try {
- headers.setTextString(value, headerField);
- } catch(NullPointerException e) {
- log("null pointer error!");
- } catch(RuntimeException e) {
- log(headerField + "is not Text-String header field!");
- return null;
- }
- }
- break;
- }
-
- /* Encoded-string-value */
- case PduHeaders.SUBJECT:
- case PduHeaders.RECOMMENDED_RETRIEVAL_MODE_TEXT:
- case PduHeaders.RETRIEVE_TEXT:
- case PduHeaders.STATUS_TEXT:
- case PduHeaders.STORE_STATUS_TEXT:
- /* the next one is not support
- * M-Mbox-Delete.conf and M-Delete.conf now */
- case PduHeaders.RESPONSE_TEXT:
- {
- EncodedStringValue value =
- parseEncodedStringValue(pduDataStream);
- if (null != value) {
- try {
- headers.setEncodedStringValue(value, headerField);
- } catch(NullPointerException e) {
- log("null pointer error!");
- } catch (RuntimeException e) {
- log(headerField + "is not Encoded-String-Value header field!");
- return null;
- }
- }
- break;
- }
-
- /* Addressing model */
- case PduHeaders.BCC:
- case PduHeaders.CC:
- case PduHeaders.TO:
- {
- EncodedStringValue value =
- parseEncodedStringValue(pduDataStream);
- if (null != value) {
- byte[] address = value.getTextString();
- if (null != address) {
- String str = new String(address);
- int endIndex = str.indexOf("/");
- if (endIndex > 0) {
- str = str.substring(0, endIndex);
- }
- try {
- value.setTextString(str.getBytes());
- } catch(NullPointerException e) {
- log("null pointer error!");
- return null;
- }
- }
-
- try {
- headers.appendEncodedStringValue(value, headerField);
- } catch(NullPointerException e) {
- log("null pointer error!");
- } catch(RuntimeException e) {
- log(headerField + "is not Encoded-String-Value header field!");
- return null;
- }
- }
- break;
- }
-
- /* Value-length
- * (Absolute-token Date-value | Relative-token Delta-seconds-value) */
- case PduHeaders.DELIVERY_TIME:
- case PduHeaders.EXPIRY:
- case PduHeaders.REPLY_CHARGING_DEADLINE:
- {
- /* parse Value-length */
- parseValueLength(pduDataStream);
-
- /* Absolute-token or Relative-token */
- int token = extractByteValue(pduDataStream);
-
- /* Date-value or Delta-seconds-value */
- long timeValue;
- try {
- timeValue = parseLongInteger(pduDataStream);
- } catch(RuntimeException e) {
- log(headerField + "is not Long-Integer header field!");
- return null;
- }
- if (PduHeaders.VALUE_RELATIVE_TOKEN == token) {
- /* need to convert the Delta-seconds-value
- * into Date-value */
- timeValue = System.currentTimeMillis()/1000 + timeValue;
- }
-
- try {
- headers.setLongInteger(timeValue, headerField);
- } catch(RuntimeException e) {
- log(headerField + "is not Long-Integer header field!");
- return null;
- }
- break;
- }
-
- case PduHeaders.FROM: {
- /* From-value =
- * Value-length
- * (Address-present-token Encoded-string-value | Insert-address-token)
- */
- EncodedStringValue from = null;
- parseValueLength(pduDataStream); /* parse value-length */
-
- /* Address-present-token or Insert-address-token */
- int fromToken = extractByteValue(pduDataStream);
-
- /* Address-present-token or Insert-address-token */
- if (PduHeaders.FROM_ADDRESS_PRESENT_TOKEN == fromToken) {
- /* Encoded-string-value */
- from = parseEncodedStringValue(pduDataStream);
- if (null != from) {
- byte[] address = from.getTextString();
- if (null != address) {
- String str = new String(address);
- int endIndex = str.indexOf("/");
- if (endIndex > 0) {
- str = str.substring(0, endIndex);
- }
- try {
- from.setTextString(str.getBytes());
- } catch(NullPointerException e) {
- log("null pointer error!");
- return null;
- }
- }
- }
- } else {
- try {
- from = new EncodedStringValue(
- PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.getBytes());
- } catch(NullPointerException e) {
- log(headerField + "is not Encoded-String-Value header field!");
- return null;
- }
- }
-
- try {
- headers.setEncodedStringValue(from, PduHeaders.FROM);
- } catch(NullPointerException e) {
- log("null pointer error!");
- } catch(RuntimeException e) {
- log(headerField + "is not Encoded-String-Value header field!");
- return null;
- }
- break;
- }
-
- case PduHeaders.MESSAGE_CLASS: {
- /* Message-class-value = Class-identifier | Token-text */
- pduDataStream.mark(1);
- int messageClass = extractByteValue(pduDataStream);
-
- if (messageClass >= PduHeaders.MESSAGE_CLASS_PERSONAL) {
- /* Class-identifier */
- try {
- if (PduHeaders.MESSAGE_CLASS_PERSONAL == messageClass) {
- headers.setTextString(
- PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes(),
- PduHeaders.MESSAGE_CLASS);
- } else if (PduHeaders.MESSAGE_CLASS_ADVERTISEMENT == messageClass) {
- headers.setTextString(
- PduHeaders.MESSAGE_CLASS_ADVERTISEMENT_STR.getBytes(),
- PduHeaders.MESSAGE_CLASS);
- } else if (PduHeaders.MESSAGE_CLASS_INFORMATIONAL == messageClass) {
- headers.setTextString(
- PduHeaders.MESSAGE_CLASS_INFORMATIONAL_STR.getBytes(),
- PduHeaders.MESSAGE_CLASS);
- } else if (PduHeaders.MESSAGE_CLASS_AUTO == messageClass) {
- headers.setTextString(
- PduHeaders.MESSAGE_CLASS_AUTO_STR.getBytes(),
- PduHeaders.MESSAGE_CLASS);
- }
- } catch(NullPointerException e) {
- log("null pointer error!");
- } catch(RuntimeException e) {
- log(headerField + "is not Text-String header field!");
- return null;
- }
- } else {
- /* Token-text */
- pduDataStream.reset();
- byte[] messageClassString = parseWapString(pduDataStream, TYPE_TEXT_STRING);
- if (null != messageClassString) {
- try {
- headers.setTextString(messageClassString, PduHeaders.MESSAGE_CLASS);
- } catch(NullPointerException e) {
- log("null pointer error!");
- } catch(RuntimeException e) {
- log(headerField + "is not Text-String header field!");
- return null;
- }
- }
- }
- break;
- }
-
- case PduHeaders.MMS_VERSION: {
- int version = parseShortInteger(pduDataStream);
-
- try {
- headers.setOctet(version, PduHeaders.MMS_VERSION);
- } catch(InvalidHeaderValueException e) {
- log("Set invalid Octet value: " + version +
- " into the header filed: " + headerField);
- return null;
- } catch(RuntimeException e) {
- log(headerField + "is not Octet header field!");
- return null;
- }
- break;
- }
-
- case PduHeaders.PREVIOUSLY_SENT_BY: {
- /* Previously-sent-by-value =
- * Value-length Forwarded-count-value Encoded-string-value */
- /* parse value-length */
- parseValueLength(pduDataStream);
-
- /* parse Forwarded-count-value */
- try {
- parseIntegerValue(pduDataStream);
- } catch(RuntimeException e) {
- log(headerField + " is not Integer-Value");
- return null;
- }
-
- /* parse Encoded-string-value */
- EncodedStringValue previouslySentBy =
- parseEncodedStringValue(pduDataStream);
- if (null != previouslySentBy) {
- try {
- headers.setEncodedStringValue(previouslySentBy,
- PduHeaders.PREVIOUSLY_SENT_BY);
- } catch(NullPointerException e) {
- log("null pointer error!");
- } catch(RuntimeException e) {
- log(headerField + "is not Encoded-String-Value header field!");
- return null;
- }
- }
- break;
- }
-
- case PduHeaders.PREVIOUSLY_SENT_DATE: {
- /* Previously-sent-date-value =
- * Value-length Forwarded-count-value Date-value */
- /* parse value-length */
- parseValueLength(pduDataStream);
-
- /* parse Forwarded-count-value */
- try {
- parseIntegerValue(pduDataStream);
- } catch(RuntimeException e) {
- log(headerField + " is not Integer-Value");
- return null;
- }
-
- /* Date-value */
- try {
- long perviouslySentDate = parseLongInteger(pduDataStream);
- headers.setLongInteger(perviouslySentDate,
- PduHeaders.PREVIOUSLY_SENT_DATE);
- } catch(RuntimeException e) {
- log(headerField + "is not Long-Integer header field!");
- return null;
- }
- break;
- }
-
- case PduHeaders.MM_FLAGS: {
- /* MM-flags-value =
- * Value-length
- * ( Add-token | Remove-token | Filter-token )
- * Encoded-string-value
- */
-
- /* parse Value-length */
- parseValueLength(pduDataStream);
-
- /* Add-token | Remove-token | Filter-token */
- extractByteValue(pduDataStream);
-
- /* Encoded-string-value */
- parseEncodedStringValue(pduDataStream);
-
- /* not store this header filed in "headers",
- * because now PduHeaders doesn't support it */
- break;
- }
-
- /* Value-length
- * (Message-total-token | Size-total-token) Integer-Value */
- case PduHeaders.MBOX_TOTALS:
- case PduHeaders.MBOX_QUOTAS:
- {
- /* Value-length */
- parseValueLength(pduDataStream);
-
- /* Message-total-token | Size-total-token */
- extractByteValue(pduDataStream);
-
- /*Integer-Value*/
- try {
- parseIntegerValue(pduDataStream);
- } catch(RuntimeException e) {
- log(headerField + " is not Integer-Value");
- return null;
- }
-
- /* not store these headers filed in "headers",
- because now PduHeaders doesn't support them */
- break;
- }
-
- case PduHeaders.ELEMENT_DESCRIPTOR: {
- parseContentType(pduDataStream, null);
-
- /* not store this header filed in "headers",
- because now PduHeaders doesn't support it */
- break;
- }
-
- case PduHeaders.CONTENT_TYPE: {
- HashMap<Integer, Object> map =
- new HashMap<Integer, Object>();
- byte[] contentType =
- parseContentType(pduDataStream, map);
-
- if (null != contentType) {
- try {
- headers.setTextString(contentType, PduHeaders.CONTENT_TYPE);
- } catch(NullPointerException e) {
- log("null pointer error!");
- } catch(RuntimeException e) {
- log(headerField + "is not Text-String header field!");
- return null;
- }
- }
-
- /* get start parameter */
- mStartParam = (byte[]) map.get(PduPart.P_START);
-
- /* get charset parameter */
- mTypeParam= (byte[]) map.get(PduPart.P_TYPE);
-
- keepParsing = false;
- break;
- }
-
- case PduHeaders.CONTENT:
- case PduHeaders.ADDITIONAL_HEADERS:
- case PduHeaders.ATTRIBUTES:
- default: {
- log("Unknown header");
- }
- }
- }
-
- return headers;
- }
-
- /**
- * Parse pdu parts.
- *
- * @param pduDataStream pdu data input stream
- * @return parts in PduBody structure
- */
- protected static PduBody parseParts(ByteArrayInputStream pduDataStream) {
- if (pduDataStream == null) {
- return null;
- }
-
- int count = parseUnsignedInt(pduDataStream); // get the number of parts
- PduBody body = new PduBody();
-
- for (int i = 0 ; i < count ; i++) {
- int headerLength = parseUnsignedInt(pduDataStream);
- int dataLength = parseUnsignedInt(pduDataStream);
- PduPart part = new PduPart();
- int startPos = pduDataStream.available();
- if (startPos <= 0) {
- // Invalid part.
- return null;
- }
-
- /* parse part's content-type */
- HashMap<Integer, Object> map = new HashMap<Integer, Object>();
- byte[] contentType = parseContentType(pduDataStream, map);
- if (null != contentType) {
- part.setContentType(contentType);
- } else {
- part.setContentType((PduContentTypes.contentTypes[0]).getBytes()); //"*/*"
- }
-
- /* get name parameter */
- byte[] name = (byte[]) map.get(PduPart.P_NAME);
- if (null != name) {
- part.setName(name);
- }
-
- /* get charset parameter */
- Integer charset = (Integer) map.get(PduPart.P_CHARSET);
- if (null != charset) {
- part.setCharset(charset);
- }
-
- /* parse part's headers */
- int endPos = pduDataStream.available();
- int partHeaderLen = headerLength - (startPos - endPos);
- if (partHeaderLen > 0) {
- if (false == parsePartHeaders(pduDataStream, part, partHeaderLen)) {
- // Parse part header faild.
- return null;
- }
- } else if (partHeaderLen < 0) {
- // Invalid length of content-type.
- return null;
- }
-
- /* FIXME: check content-id, name, filename and content location,
- * if not set anyone of them, generate a default content-location
- */
- if ((null == part.getContentLocation())
- && (null == part.getName())
- && (null == part.getFilename())
- && (null == part.getContentId())) {
- part.setContentLocation(Long.toOctalString(
- System.currentTimeMillis()).getBytes());
- }
-
- /* get part's data */
- if (dataLength > 0) {
- byte[] partData = new byte[dataLength];
- pduDataStream.read(partData, 0, dataLength);
- // Check Content-Transfer-Encoding.
- byte[] partDataEncoding = part.getContentTransferEncoding();
- if (null != partDataEncoding) {
- String encoding = new String(partDataEncoding);
- if (encoding.equalsIgnoreCase(PduPart.P_BASE64)) {
- // Decode "base64" into "binary".
- partData = Base64.decodeBase64(partData);
- } else if (encoding.equalsIgnoreCase(PduPart.P_QUOTED_PRINTABLE)) {
- // Decode "quoted-printable" into "binary".
- partData = QuotedPrintable.decodeQuotedPrintable(partData);
- } else {
- // "binary" is the default encoding.
- }
- }
- if (null == partData) {
- log("Decode part data error!");
- return null;
- }
- part.setData(partData);
- }
-
- /* add this part to body */
- if (THE_FIRST_PART == checkPartPosition(part)) {
- /* this is the first part */
- body.addPart(0, part);
- } else {
- /* add the part to the end */
- body.addPart(part);
- }
- }
-
- return body;
- }
-
- /**
- * Log status.
- *
- * @param text log information
- */
- private static void log(String text) {
- if (LOCAL_LOGV) {
- Log.v(LOG_TAG, text);
- }
- }
-
- /**
- * Parse unsigned integer.
- *
- * @param pduDataStream pdu data input stream
- * @return the integer, -1 when failed
- */
- protected static int parseUnsignedInt(ByteArrayInputStream pduDataStream) {
- /**
- * From wap-230-wsp-20010705-a.pdf
- * The maximum size of a uintvar is 32 bits.
- * So it will be encoded in no more than 5 octets.
- */
- assert(null != pduDataStream);
- int result = 0;
- int temp = pduDataStream.read();
- if (temp == -1) {
- return temp;
- }
-
- while((temp & 0x80) != 0) {
- result = result << 7;
- result |= temp & 0x7F;
- temp = pduDataStream.read();
- if (temp == -1) {
- return temp;
- }
- }
-
- result = result << 7;
- result |= temp & 0x7F;
-
- return result;
- }
-
- /**
- * Parse value length.
- *
- * @param pduDataStream pdu data input stream
- * @return the integer
- */
- protected static int parseValueLength(ByteArrayInputStream pduDataStream) {
- /**
- * From wap-230-wsp-20010705-a.pdf
- * Value-length = Short-length | (Length-quote Length)
- * Short-length = <Any octet 0-30>
- * Length-quote = <Octet 31>
- * Length = Uintvar-integer
- * Uintvar-integer = 1*5 OCTET
- */
- assert(null != pduDataStream);
- int temp = pduDataStream.read();
- assert(-1 != temp);
- int first = temp & 0xFF;
-
- if (first <= SHORT_LENGTH_MAX) {
- return first;
- } else if (first == LENGTH_QUOTE) {
- return parseUnsignedInt(pduDataStream);
- }
-
- throw new RuntimeException ("Value length > LENGTH_QUOTE!");
- }
-
- /**
- * Parse encoded string value.
- *
- * @param pduDataStream pdu data input stream
- * @return the EncodedStringValue
- */
- protected static EncodedStringValue parseEncodedStringValue(ByteArrayInputStream pduDataStream){
- /**
- * From OMA-TS-MMS-ENC-V1_3-20050927-C.pdf
- * Encoded-string-value = Text-string | Value-length Char-set Text-string
- */
- assert(null != pduDataStream);
- pduDataStream.mark(1);
- EncodedStringValue returnValue = null;
- int charset = 0;
- int temp = pduDataStream.read();
- assert(-1 != temp);
- int first = temp & 0xFF;
-
- pduDataStream.reset();
- if (first < TEXT_MIN) {
- parseValueLength(pduDataStream);
-
- charset = parseShortInteger(pduDataStream); //get the "Charset"
- }
-
- byte[] textString = parseWapString(pduDataStream, TYPE_TEXT_STRING);
-
- try {
- if (0 != charset) {
- returnValue = new EncodedStringValue(charset, textString);
- } else {
- returnValue = new EncodedStringValue(textString);
- }
- } catch(Exception e) {
- return null;
- }
-
- return returnValue;
- }
-
- /**
- * Parse Text-String or Quoted-String.
- *
- * @param pduDataStream pdu data input stream
- * @param stringType TYPE_TEXT_STRING or TYPE_QUOTED_STRING
- * @return the string without End-of-string in byte array
- */
- protected static byte[] parseWapString(ByteArrayInputStream pduDataStream,
- int stringType) {
- assert(null != pduDataStream);
- /**
- * From wap-230-wsp-20010705-a.pdf
- * Text-string = [Quote] *TEXT End-of-string
- * If the first character in the TEXT is in the range of 128-255,
- * a Quote character must precede it.
- * Otherwise the Quote character must be omitted.
- * The Quote is not part of the contents.
- * Quote = <Octet 127>
- * End-of-string = <Octet 0>
- *
- * Quoted-string = <Octet 34> *TEXT End-of-string
- *
- * Token-text = Token End-of-string
- */
-
- // Mark supposed beginning of Text-string
- // We will have to mark again if first char is QUOTE or QUOTED_STRING_FLAG
- pduDataStream.mark(1);
-
- // Check first char
- int temp = pduDataStream.read();
- assert(-1 != temp);
- if ((TYPE_QUOTED_STRING == stringType) &&
- (QUOTED_STRING_FLAG == temp)) {
- // Mark again if QUOTED_STRING_FLAG and ignore it
- pduDataStream.mark(1);
- } else if ((TYPE_TEXT_STRING == stringType) &&
- (QUOTE == temp)) {
- // Mark again if QUOTE and ignore it
- pduDataStream.mark(1);
- } else {
- // Otherwise go back to origin
- pduDataStream.reset();
- }
-
- // We are now definitely at the beginning of string
- /**
- * Return *TOKEN or *TEXT (Text-String without QUOTE,
- * Quoted-String without QUOTED_STRING_FLAG and without End-of-string)
- */
- return getWapString(pduDataStream, stringType);
- }
-
- /**
- * Check TOKEN data defined in RFC2616.
- * @param ch checking data
- * @return true when ch is TOKEN, false when ch is not TOKEN
- */
- protected static boolean isTokenCharacter(int ch) {
- /**
- * Token = 1*<any CHAR except CTLs or separators>
- * separators = "("(40) | ")"(41) | "<"(60) | ">"(62) | "@"(64)
- * | ","(44) | ";"(59) | ":"(58) | "\"(92) | <">(34)
- * | "/"(47) | "["(91) | "]"(93) | "?"(63) | "="(61)
- * | "{"(123) | "}"(125) | SP(32) | HT(9)
- * CHAR = <any US-ASCII character (octets 0 - 127)>
- * CTL = <any US-ASCII control character
- * (octets 0 - 31) and DEL (127)>
- * SP = <US-ASCII SP, space (32)>
- * HT = <US-ASCII HT, horizontal-tab (9)>
- */
- if((ch < 33) || (ch > 126)) {
- return false;
- }
-
- switch(ch) {
- case '"': /* '"' */
- case '(': /* '(' */
- case ')': /* ')' */
- case ',': /* ',' */
- case '/': /* '/' */
- case ':': /* ':' */
- case ';': /* ';' */
- case '<': /* '<' */
- case '=': /* '=' */
- case '>': /* '>' */
- case '?': /* '?' */
- case '@': /* '@' */
- case '[': /* '[' */
- case '\\': /* '\' */
- case ']': /* ']' */
- case '{': /* '{' */
- case '}': /* '}' */
- return false;
- }
-
- return true;
- }
-
- /**
- * Check TEXT data defined in RFC2616.
- * @param ch checking data
- * @return true when ch is TEXT, false when ch is not TEXT
- */
- protected static boolean isText(int ch) {
- /**
- * TEXT = <any OCTET except CTLs,
- * but including LWS>
- * CTL = <any US-ASCII control character
- * (octets 0 - 31) and DEL (127)>
- * LWS = [CRLF] 1*( SP | HT )
- * CRLF = CR LF
- * CR = <US-ASCII CR, carriage return (13)>
- * LF = <US-ASCII LF, linefeed (10)>
- */
- if(((ch >= 32) && (ch <= 126)) || ((ch >= 128) && (ch <= 255))) {
- return true;
- }
-
- switch(ch) {
- case '\t': /* '\t' */
- case '\n': /* '\n' */
- case '\r': /* '\r' */
- return true;
- }
-
- return false;
- }
-
- protected static byte[] getWapString(ByteArrayInputStream pduDataStream,
- int stringType) {
- assert(null != pduDataStream);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- int temp = pduDataStream.read();
- assert(-1 != temp);
- while((-1 != temp) && ('\0' != temp)) {
- // check each of the character
- if (stringType == TYPE_TOKEN_STRING) {
- if (isTokenCharacter(temp)) {
- out.write(temp);
- }
- } else {
- if (isText(temp)) {
- out.write(temp);
- }
- }
-
- temp = pduDataStream.read();
- assert(-1 != temp);
- }
-
- if (out.size() > 0) {
- return out.toByteArray();
- }
-
- return null;
- }
-
- /**
- * Extract a byte value from the input stream.
- *
- * @param pduDataStream pdu data input stream
- * @return the byte
- */
- protected static int extractByteValue(ByteArrayInputStream pduDataStream) {
- assert(null != pduDataStream);
- int temp = pduDataStream.read();
- assert(-1 != temp);
- return temp & 0xFF;
- }
-
- /**
- * Parse Short-Integer.
- *
- * @param pduDataStream pdu data input stream
- * @return the byte
- */
- protected static int parseShortInteger(ByteArrayInputStream pduDataStream) {
- /**
- * From wap-230-wsp-20010705-a.pdf
- * Short-integer = OCTET
- * Integers in range 0-127 shall be encoded as a one
- * octet value with the most significant bit set to one (1xxx xxxx)
- * and with the value in the remaining least significant bits.
- */
- assert(null != pduDataStream);
- int temp = pduDataStream.read();
- assert(-1 != temp);
- return temp & 0x7F;
- }
-
- /**
- * Parse Long-Integer.
- *
- * @param pduDataStream pdu data input stream
- * @return long integer
- */
- protected static long parseLongInteger(ByteArrayInputStream pduDataStream) {
- /**
- * From wap-230-wsp-20010705-a.pdf
- * Long-integer = Short-length Multi-octet-integer
- * The Short-length indicates the length of the Multi-octet-integer
- * Multi-octet-integer = 1*30 OCTET
- * The content octets shall be an unsigned integer value
- * with the most significant octet encoded first (big-endian representation).
- * The minimum number of octets must be used to encode the value.
- * Short-length = <Any octet 0-30>
- */
- assert(null != pduDataStream);
- int temp = pduDataStream.read();
- assert(-1 != temp);
- int count = temp & 0xFF;
-
- if (count > LONG_INTEGER_LENGTH_MAX) {
- throw new RuntimeException("Octet count greater than 8 and I can't represent that!");
- }
-
- long result = 0;
-
- for (int i = 0 ; i < count ; i++) {
- temp = pduDataStream.read();
- assert(-1 != temp);
- result <<= 8;
- result += (temp & 0xFF);
- }
-
- return result;
- }
-
- /**
- * Parse Integer-Value.
- *
- * @param pduDataStream pdu data input stream
- * @return long integer
- */
- protected static long parseIntegerValue(ByteArrayInputStream pduDataStream) {
- /**
- * From wap-230-wsp-20010705-a.pdf
- * Integer-Value = Short-integer | Long-integer
- */
- assert(null != pduDataStream);
- pduDataStream.mark(1);
- int temp = pduDataStream.read();
- assert(-1 != temp);
- pduDataStream.reset();
- if (temp > SHORT_INTEGER_MAX) {
- return parseShortInteger(pduDataStream);
- } else {
- return parseLongInteger(pduDataStream);
- }
- }
-
- /**
- * To skip length of the wap value.
- *
- * @param pduDataStream pdu data input stream
- * @param length area size
- * @return the values in this area
- */
- protected static int skipWapValue(ByteArrayInputStream pduDataStream, int length) {
- assert(null != pduDataStream);
- byte[] area = new byte[length];
- int readLen = pduDataStream.read(area, 0, length);
- if (readLen < length) { //The actually read length is lower than the length
- return -1;
- } else {
- return readLen;
- }
- }
-
- /**
- * Parse content type parameters. For now we just support
- * four parameters used in mms: "type", "start", "name", "charset".
- *
- * @param pduDataStream pdu data input stream
- * @param map to store parameters of Content-Type field
- * @param length length of all the parameters
- */
- protected static void parseContentTypeParams(ByteArrayInputStream pduDataStream,
- HashMap<Integer, Object> map, Integer length) {
- /**
- * From wap-230-wsp-20010705-a.pdf
- * Parameter = Typed-parameter | Untyped-parameter
- * Typed-parameter = Well-known-parameter-token Typed-value
- * the actual expected type of the value is implied by the well-known parameter
- * Well-known-parameter-token = Integer-value
- * the code values used for parameters are specified in the Assigned Numbers appendix
- * Typed-value = Compact-value | Text-value
- * In addition to the expected type, there may be no value.
- * If the value cannot be encoded using the expected type, it shall be encoded as text.
- * Compact-value = Integer-value |
- * Date-value | Delta-seconds-value | Q-value | Version-value |
- * Uri-value
- * Untyped-parameter = Token-text Untyped-value
- * the type of the value is unknown, but it shall be encoded as an integer,
- * if that is possible.
- * Untyped-value = Integer-value | Text-value
- */
- assert(null != pduDataStream);
- assert(length > 0);
-
- int startPos = pduDataStream.available();
- int tempPos = 0;
- int lastLen = length;
- while(0 < lastLen) {
- int param = pduDataStream.read();
- assert(-1 != param);
- lastLen--;
-
- switch (param) {
- /**
- * From rfc2387, chapter 3.1
- * The type parameter must be specified and its value is the MIME media
- * type of the "root" body part. It permits a MIME user agent to
- * determine the content-type without reference to the enclosed body
- * part. If the value of the type parameter and the root body part's
- * content-type differ then the User Agent's behavior is undefined.
- *
- * From wap-230-wsp-20010705-a.pdf
- * type = Constrained-encoding
- * Constrained-encoding = Extension-Media | Short-integer
- * Extension-media = *TEXT End-of-string
- */
- case PduPart.P_TYPE:
- case PduPart.P_CT_MR_TYPE:
- pduDataStream.mark(1);
- int first = extractByteValue(pduDataStream);
- pduDataStream.reset();
- if (first > TEXT_MAX) {
- // Short-integer (well-known type)
- int index = parseShortInteger(pduDataStream);
-
- if (index < PduContentTypes.contentTypes.length) {
- byte[] type = (PduContentTypes.contentTypes[index]).getBytes();
- map.put(PduPart.P_TYPE, type);
- } else {
- //not support this type, ignore it.
- }
- } else {
- // Text-String (extension-media)
- byte[] type = parseWapString(pduDataStream, TYPE_TEXT_STRING);
- if ((null != type) && (null != map)) {
- map.put(PduPart.P_TYPE, type);
- }
- }
-
- tempPos = pduDataStream.available();
- lastLen = length - (startPos - tempPos);
- break;
-
- /**
- * From oma-ts-mms-conf-v1_3.pdf, chapter 10.2.3.
- * Start Parameter Referring to Presentation
- *
- * From rfc2387, chapter 3.2
- * The start parameter, if given, is the content-ID of the compound
- * object's "root". If not present the "root" is the first body part in
- * the Multipart/Related entity. The "root" is the element the
- * applications processes first.
- *
- * From wap-230-wsp-20010705-a.pdf
- * start = Text-String
- */
- case PduPart.P_START:
- case PduPart.P_DEP_START:
- byte[] start = parseWapString(pduDataStream, TYPE_TEXT_STRING);
- if ((null != start) && (null != map)) {
- map.put(PduPart.P_START, start);
- }
-
- tempPos = pduDataStream.available();
- lastLen = length - (startPos - tempPos);
- break;
-
- /**
- * From oma-ts-mms-conf-v1_3.pdf
- * In creation, the character set SHALL be either us-ascii
- * (IANA MIBenum 3) or utf-8 (IANA MIBenum 106)[Unicode].
- * In retrieval, both us-ascii and utf-8 SHALL be supported.
- *
- * From wap-230-wsp-20010705-a.pdf
- * charset = Well-known-charset|Text-String
- * Well-known-charset = Any-charset | Integer-value
- * Both are encoded using values from Character Set
- * Assignments table in Assigned Numbers
- * Any-charset = <Octet 128>
- * Equivalent to the special RFC2616 charset value "*"
- */
- case PduPart.P_CHARSET:
- pduDataStream.mark(1);
- int firstValue = extractByteValue(pduDataStream);
- pduDataStream.reset();
- //Check first char
- if (((firstValue > TEXT_MIN) && (firstValue < TEXT_MAX)) ||
- (END_STRING_FLAG == firstValue)) {
- //Text-String (extension-charset)
- byte[] charsetStr = parseWapString(pduDataStream, TYPE_TEXT_STRING);
- try {
- int charsetInt = CharacterSets.getMibEnumValue(
- new String(charsetStr));
- map.put(PduPart.P_CHARSET, charsetInt);
- } catch (UnsupportedEncodingException e) {
- // Not a well-known charset, use "*".
- Log.e(LOG_TAG, Arrays.toString(charsetStr), e);
- map.put(PduPart.P_CHARSET, CharacterSets.ANY_CHARSET);
- }
- } else {
- //Well-known-charset
- int charset = (int) parseIntegerValue(pduDataStream);
- if (map != null) {
- map.put(PduPart.P_CHARSET, charset);
- }
- }
-
- tempPos = pduDataStream.available();
- lastLen = length - (startPos - tempPos);
- break;
-
- /**
- * From oma-ts-mms-conf-v1_3.pdf
- * A name for multipart object SHALL be encoded using name-parameter
- * for Content-Type header in WSP multipart headers.
- *
- * From wap-230-wsp-20010705-a.pdf
- * name = Text-String
- */
- case PduPart.P_DEP_NAME:
- case PduPart.P_NAME:
- byte[] name = parseWapString(pduDataStream, TYPE_TEXT_STRING);
- if ((null != name) && (null != map)) {
- map.put(PduPart.P_NAME, name);
- }
-
- tempPos = pduDataStream.available();
- lastLen = length - (startPos - tempPos);
- break;
- default:
- if (LOCAL_LOGV) {
- Log.v(LOG_TAG, "Not supported Content-Type parameter");
- }
- if (-1 == skipWapValue(pduDataStream, lastLen)) {
- Log.e(LOG_TAG, "Corrupt Content-Type");
- } else {
- lastLen = 0;
- }
- break;
- }
- }
-
- if (0 != lastLen) {
- Log.e(LOG_TAG, "Corrupt Content-Type");
- }
- }
-
- /**
- * Parse content type.
- *
- * @param pduDataStream pdu data input stream
- * @param map to store parameters in Content-Type header field
- * @return Content-Type value
- */
- protected static byte[] parseContentType(ByteArrayInputStream pduDataStream,
- HashMap<Integer, Object> map) {
- /**
- * From wap-230-wsp-20010705-a.pdf
- * Content-type-value = Constrained-media | Content-general-form
- * Content-general-form = Value-length Media-type
- * Media-type = (Well-known-media | Extension-Media) *(Parameter)
- */
- assert(null != pduDataStream);
-
- byte[] contentType = null;
- pduDataStream.mark(1);
- int temp = pduDataStream.read();
- assert(-1 != temp);
- pduDataStream.reset();
-
- int cur = (temp & 0xFF);
-
- if (cur < TEXT_MIN) {
- int length = parseValueLength(pduDataStream);
- int startPos = pduDataStream.available();
- pduDataStream.mark(1);
- temp = pduDataStream.read();
- assert(-1 != temp);
- pduDataStream.reset();
- int first = (temp & 0xFF);
-
- if ((first >= TEXT_MIN) && (first <= TEXT_MAX)) {
- contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING);
- } else if (first > TEXT_MAX) {
- int index = parseShortInteger(pduDataStream);
-
- if (index < PduContentTypes.contentTypes.length) { //well-known type
- contentType = (PduContentTypes.contentTypes[index]).getBytes();
- } else {
- pduDataStream.reset();
- contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING);
- }
- } else {
- Log.e(LOG_TAG, "Corrupt content-type");
- return (PduContentTypes.contentTypes[0]).getBytes(); //"*/*"
- }
-
- int endPos = pduDataStream.available();
- int parameterLen = length - (startPos - endPos);
- if (parameterLen > 0) {//have parameters
- parseContentTypeParams(pduDataStream, map, parameterLen);
- }
-
- if (parameterLen < 0) {
- Log.e(LOG_TAG, "Corrupt MMS message");
- return (PduContentTypes.contentTypes[0]).getBytes(); //"*/*"
- }
- } else if (cur <= TEXT_MAX) {
- contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING);
- } else {
- contentType =
- (PduContentTypes.contentTypes[parseShortInteger(pduDataStream)]).getBytes();
- }
-
- return contentType;
- }
-
- /**
- * Parse part's headers.
- *
- * @param pduDataStream pdu data input stream
- * @param part to store the header informations of the part
- * @param length length of the headers
- * @return true if parse successfully, false otherwise
- */
- protected static boolean parsePartHeaders(ByteArrayInputStream pduDataStream,
- PduPart part, int length) {
- assert(null != pduDataStream);
- assert(null != part);
- assert(length > 0);
-
- /**
- * From oma-ts-mms-conf-v1_3.pdf, chapter 10.2.
- * A name for multipart object SHALL be encoded using name-parameter
- * for Content-Type header in WSP multipart headers.
- * In decoding, name-parameter of Content-Type SHALL be used if available.
- * If name-parameter of Content-Type is not available,
- * filename parameter of Content-Disposition header SHALL be used if available.
- * If neither name-parameter of Content-Type header nor filename parameter
- * of Content-Disposition header is available,
- * Content-Location header SHALL be used if available.
- *
- * Within SMIL part the reference to the media object parts SHALL use
- * either Content-ID or Content-Location mechanism [RFC2557]
- * and the corresponding WSP part headers in media object parts
- * contain the corresponding definitions.
- */
- int startPos = pduDataStream.available();
- int tempPos = 0;
- int lastLen = length;
- while(0 < lastLen) {
- int header = pduDataStream.read();
- assert(-1 != header);
- lastLen--;
-
- if (header > TEXT_MAX) {
- // Number assigned headers.
- switch (header) {
- case PduPart.P_CONTENT_LOCATION:
- /**
- * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
- * Content-location-value = Uri-value
- */
- byte[] contentLocation = parseWapString(pduDataStream, TYPE_TEXT_STRING);
- if (null != contentLocation) {
- part.setContentLocation(contentLocation);
- }
-
- tempPos = pduDataStream.available();
- lastLen = length - (startPos - tempPos);
- break;
- case PduPart.P_CONTENT_ID:
- /**
- * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
- * Content-ID-value = Quoted-string
- */
- byte[] contentId = parseWapString(pduDataStream, TYPE_QUOTED_STRING);
- if (null != contentId) {
- part.setContentId(contentId);
- }
-
- tempPos = pduDataStream.available();
- lastLen = length - (startPos - tempPos);
- break;
- case PduPart.P_DEP_CONTENT_DISPOSITION:
- case PduPart.P_CONTENT_DISPOSITION:
- /**
- * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
- * Content-disposition-value = Value-length Disposition *(Parameter)
- * Disposition = Form-data | Attachment | Inline | Token-text
- * Form-data = <Octet 128>
- * Attachment = <Octet 129>
- * Inline = <Octet 130>
- */
- int len = parseValueLength(pduDataStream);
- pduDataStream.mark(1);
- int thisStartPos = pduDataStream.available();
- int thisEndPos = 0;
- int value = pduDataStream.read();
-
- if (value == PduPart.P_DISPOSITION_FROM_DATA ) {
- part.setContentDisposition(PduPart.DISPOSITION_FROM_DATA);
- } else if (value == PduPart.P_DISPOSITION_ATTACHMENT) {
- part.setContentDisposition(PduPart.DISPOSITION_ATTACHMENT);
- } else if (value == PduPart.P_DISPOSITION_INLINE) {
- part.setContentDisposition(PduPart.DISPOSITION_INLINE);
- } else {
- pduDataStream.reset();
- /* Token-text */
- part.setContentDisposition(parseWapString(pduDataStream, TYPE_TEXT_STRING));
- }
-
- /* get filename parameter and skip other parameters */
- thisEndPos = pduDataStream.available();
- if (thisStartPos - thisEndPos < len) {
- value = pduDataStream.read();
- if (value == PduPart.P_FILENAME) { //filename is text-string
- part.setFilename(parseWapString(pduDataStream, TYPE_TEXT_STRING));
- }
-
- /* skip other parameters */
- thisEndPos = pduDataStream.available();
- if (thisStartPos - thisEndPos < len) {
- int last = len - (thisStartPos - thisEndPos);
- byte[] temp = new byte[last];
- pduDataStream.read(temp, 0, last);
- }
- }
-
- tempPos = pduDataStream.available();
- lastLen = length - (startPos - tempPos);
- break;
- default:
- if (LOCAL_LOGV) {
- Log.v(LOG_TAG, "Not supported Part headers: " + header);
- }
- if (-1 == skipWapValue(pduDataStream, lastLen)) {
- Log.e(LOG_TAG, "Corrupt Part headers");
- return false;
- }
- lastLen = 0;
- break;
- }
- } else if ((header >= TEXT_MIN) && (header <= TEXT_MAX)) {
- // Not assigned header.
- byte[] tempHeader = parseWapString(pduDataStream, TYPE_TEXT_STRING);
- byte[] tempValue = parseWapString(pduDataStream, TYPE_TEXT_STRING);
-
- // Check the header whether it is "Content-Transfer-Encoding".
- if (true ==
- PduPart.CONTENT_TRANSFER_ENCODING.equalsIgnoreCase(new String(tempHeader))) {
- part.setContentTransferEncoding(tempValue);
- }
-
- tempPos = pduDataStream.available();
- lastLen = length - (startPos - tempPos);
- } else {
- if (LOCAL_LOGV) {
- Log.v(LOG_TAG, "Not supported Part headers: " + header);
- }
- // Skip all headers of this part.
- if (-1 == skipWapValue(pduDataStream, lastLen)) {
- Log.e(LOG_TAG, "Corrupt Part headers");
- return false;
- }
- lastLen = 0;
- }
- }
-
- if (0 != lastLen) {
- Log.e(LOG_TAG, "Corrupt Part headers");
- return false;
- }
-
- return true;
- }
-
- /**
- * Check the position of a specified part.
- *
- * @param part the part to be checked
- * @return part position, THE_FIRST_PART when it's the
- * first one, THE_LAST_PART when it's the last one.
- */
- private static int checkPartPosition(PduPart part) {
- assert(null != part);
- if ((null == mTypeParam) &&
- (null == mStartParam)) {
- return THE_LAST_PART;
- }
-
- /* check part's content-id */
- if (null != mStartParam) {
- byte[] contentId = part.getContentId();
- if (null != contentId) {
- if (true == Arrays.equals(mStartParam, contentId)) {
- return THE_FIRST_PART;
- }
- }
- }
-
- /* check part's content-type */
- if (null != mTypeParam) {
- byte[] contentType = part.getContentType();
- if (null != contentType) {
- if (true == Arrays.equals(mTypeParam, contentType)) {
- return THE_FIRST_PART;
- }
- }
- }
-
- return THE_LAST_PART;
- }
-
- /**
- * Check mandatory headers of a pdu.
- *
- * @param headers pdu headers
- * @return true if the pdu has all of the mandatory headers, false otherwise.
- */
- protected static boolean checkMandatoryHeader(PduHeaders headers) {
- if (null == headers) {
- return false;
- }
-
- /* get message type */
- int messageType = headers.getOctet(PduHeaders.MESSAGE_TYPE);
-
- /* check Mms-Version field */
- int mmsVersion = headers.getOctet(PduHeaders.MMS_VERSION);
- if (0 == mmsVersion) {
- // Every message should have Mms-Version field.
- return false;
- }
-
- /* check mandatory header fields */
- switch (messageType) {
- case PduHeaders.MESSAGE_TYPE_SEND_REQ:
- // Content-Type field.
- byte[] srContentType = headers.getTextString(PduHeaders.CONTENT_TYPE);
- if (null == srContentType) {
- return false;
- }
-
- // From field.
- EncodedStringValue srFrom = headers.getEncodedStringValue(PduHeaders.FROM);
- if (null == srFrom) {
- return false;
- }
-
- // Transaction-Id field.
- byte[] srTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
- if (null == srTransactionId) {
- return false;
- }
-
- break;
- case PduHeaders.MESSAGE_TYPE_SEND_CONF:
- // Response-Status field.
- int scResponseStatus = headers.getOctet(PduHeaders.RESPONSE_STATUS);
- if (0 == scResponseStatus) {
- return false;
- }
-
- // Transaction-Id field.
- byte[] scTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
- if (null == scTransactionId) {
- return false;
- }
-
- break;
- case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
- // Content-Location field.
- byte[] niContentLocation = headers.getTextString(PduHeaders.CONTENT_LOCATION);
- if (null == niContentLocation) {
- return false;
- }
-
- // Expiry field.
- long niExpiry = headers.getLongInteger(PduHeaders.EXPIRY);
- if (-1 == niExpiry) {
- return false;
- }
-
- // Message-Class field.
- byte[] niMessageClass = headers.getTextString(PduHeaders.MESSAGE_CLASS);
- if (null == niMessageClass) {
- return false;
- }
-
- // Message-Size field.
- long niMessageSize = headers.getLongInteger(PduHeaders.MESSAGE_SIZE);
- if (-1 == niMessageSize) {
- return false;
- }
-
- // Transaction-Id field.
- byte[] niTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
- if (null == niTransactionId) {
- return false;
- }
-
- break;
- case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
- // Status field.
- int nriStatus = headers.getOctet(PduHeaders.STATUS);
- if (0 == nriStatus) {
- return false;
- }
-
- // Transaction-Id field.
- byte[] nriTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
- if (null == nriTransactionId) {
- return false;
- }
-
- break;
- case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
- // Content-Type field.
- byte[] rcContentType = headers.getTextString(PduHeaders.CONTENT_TYPE);
- if (null == rcContentType) {
- return false;
- }
-
- // Date field.
- long rcDate = headers.getLongInteger(PduHeaders.DATE);
- if (-1 == rcDate) {
- return false;
- }
-
- break;
- case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
- // Date field.
- long diDate = headers.getLongInteger(PduHeaders.DATE);
- if (-1 == diDate) {
- return false;
- }
-
- // Message-Id field.
- byte[] diMessageId = headers.getTextString(PduHeaders.MESSAGE_ID);
- if (null == diMessageId) {
- return false;
- }
-
- // Status field.
- int diStatus = headers.getOctet(PduHeaders.STATUS);
- if (0 == diStatus) {
- return false;
- }
-
- // To field.
- EncodedStringValue[] diTo = headers.getEncodedStringValues(PduHeaders.TO);
- if (null == diTo) {
- return false;
- }
-
- break;
- case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
- // Transaction-Id field.
- byte[] aiTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
- if (null == aiTransactionId) {
- return false;
- }
-
- break;
- case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND:
- // Date field.
- long roDate = headers.getLongInteger(PduHeaders.DATE);
- if (-1 == roDate) {
- return false;
- }
-
- // From field.
- EncodedStringValue roFrom = headers.getEncodedStringValue(PduHeaders.FROM);
- if (null == roFrom) {
- return false;
- }
-
- // Message-Id field.
- byte[] roMessageId = headers.getTextString(PduHeaders.MESSAGE_ID);
- if (null == roMessageId) {
- return false;
- }
-
- // Read-Status field.
- int roReadStatus = headers.getOctet(PduHeaders.READ_STATUS);
- if (0 == roReadStatus) {
- return false;
- }
-
- // To field.
- EncodedStringValue[] roTo = headers.getEncodedStringValues(PduHeaders.TO);
- if (null == roTo) {
- return false;
- }
-
- break;
- case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
- // From field.
- EncodedStringValue rrFrom = headers.getEncodedStringValue(PduHeaders.FROM);
- if (null == rrFrom) {
- return false;
- }
-
- // Message-Id field.
- byte[] rrMessageId = headers.getTextString(PduHeaders.MESSAGE_ID);
- if (null == rrMessageId) {
- return false;
- }
-
- // Read-Status field.
- int rrReadStatus = headers.getOctet(PduHeaders.READ_STATUS);
- if (0 == rrReadStatus) {
- return false;
- }
-
- // To field.
- EncodedStringValue[] rrTo = headers.getEncodedStringValues(PduHeaders.TO);
- if (null == rrTo) {
- return false;
- }
-
- break;
- default:
- // Parser doesn't support this message type in this version.
- return false;
- }
-
- return true;
- }
-}
diff --git a/core/java/com/google/android/mms/pdu/PduPart.java b/core/java/com/google/android/mms/pdu/PduPart.java
deleted file mode 100644
index b43e388..0000000
--- a/core/java/com/google/android/mms/pdu/PduPart.java
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * Copyright (C) 2007-2008 Esmertec AG.
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import android.net.Uri;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * The pdu part.
- */
-public class PduPart {
- /**
- * Well-Known Parameters.
- */
- public static final int P_Q = 0x80;
- public static final int P_CHARSET = 0x81;
- public static final int P_LEVEL = 0x82;
- public static final int P_TYPE = 0x83;
- public static final int P_DEP_NAME = 0x85;
- public static final int P_DEP_FILENAME = 0x86;
- public static final int P_DIFFERENCES = 0x87;
- public static final int P_PADDING = 0x88;
- // This value of "TYPE" s used with Content-Type: multipart/related
- public static final int P_CT_MR_TYPE = 0x89;
- public static final int P_DEP_START = 0x8A;
- public static final int P_DEP_START_INFO = 0x8B;
- public static final int P_DEP_COMMENT = 0x8C;
- public static final int P_DEP_DOMAIN = 0x8D;
- public static final int P_MAX_AGE = 0x8E;
- public static final int P_DEP_PATH = 0x8F;
- public static final int P_SECURE = 0x90;
- public static final int P_SEC = 0x91;
- public static final int P_MAC = 0x92;
- public static final int P_CREATION_DATE = 0x93;
- public static final int P_MODIFICATION_DATE = 0x94;
- public static final int P_READ_DATE = 0x95;
- public static final int P_SIZE = 0x96;
- public static final int P_NAME = 0x97;
- public static final int P_FILENAME = 0x98;
- public static final int P_START = 0x99;
- public static final int P_START_INFO = 0x9A;
- public static final int P_COMMENT = 0x9B;
- public static final int P_DOMAIN = 0x9C;
- public static final int P_PATH = 0x9D;
-
- /**
- * Header field names.
- */
- public static final int P_CONTENT_TYPE = 0x91;
- public static final int P_CONTENT_LOCATION = 0x8E;
- public static final int P_CONTENT_ID = 0xC0;
- public static final int P_DEP_CONTENT_DISPOSITION = 0xAE;
- public static final int P_CONTENT_DISPOSITION = 0xC5;
- // The next header is unassigned header, use reserved header(0x48) value.
- public static final int P_CONTENT_TRANSFER_ENCODING = 0xC8;
-
- /**
- * Content=Transfer-Encoding string.
- */
- public static final String CONTENT_TRANSFER_ENCODING =
- "Content-Transfer-Encoding";
-
- /**
- * Value of Content-Transfer-Encoding.
- */
- public static final String P_BINARY = "binary";
- public static final String P_7BIT = "7bit";
- public static final String P_8BIT = "8bit";
- public static final String P_BASE64 = "base64";
- public static final String P_QUOTED_PRINTABLE = "quoted-printable";
-
- /**
- * Value of disposition can be set to PduPart when the value is octet in
- * the PDU.
- * "from-data" instead of Form-data<Octet 128>.
- * "attachment" instead of Attachment<Octet 129>.
- * "inline" instead of Inline<Octet 130>.
- */
- static final byte[] DISPOSITION_FROM_DATA = "from-data".getBytes();
- static final byte[] DISPOSITION_ATTACHMENT = "attachment".getBytes();
- static final byte[] DISPOSITION_INLINE = "inline".getBytes();
-
- /**
- * Content-Disposition value.
- */
- public static final int P_DISPOSITION_FROM_DATA = 0x80;
- public static final int P_DISPOSITION_ATTACHMENT = 0x81;
- public static final int P_DISPOSITION_INLINE = 0x82;
-
- /**
- * Header of part.
- */
- private Map<Integer, Object> mPartHeader = null;
-
- /**
- * Data uri.
- */
- private Uri mUri = null;
-
- /**
- * Part data.
- */
- private byte[] mPartData = null;
-
- private static final String TAG = "PduPart";
-
- /**
- * Empty Constructor.
- */
- public PduPart() {
- mPartHeader = new HashMap<Integer, Object>();
- }
-
- /**
- * Set part data. The data are stored as byte array.
- *
- * @param data the data
- */
- public void setData(byte[] data) {
- if(data == null) {
- return;
- }
-
- mPartData = new byte[data.length];
- System.arraycopy(data, 0, mPartData, 0, data.length);
- }
-
- /**
- * @return A copy of the part data or null if the data wasn't set or
- * the data is stored as Uri.
- * @see #getDataUri
- */
- public byte[] getData() {
- if(mPartData == null) {
- return null;
- }
-
- byte[] byteArray = new byte[mPartData.length];
- System.arraycopy(mPartData, 0, byteArray, 0, mPartData.length);
- return byteArray;
- }
-
- /**
- * Set data uri. The data are stored as Uri.
- *
- * @param uri the uri
- */
- public void setDataUri(Uri uri) {
- mUri = uri;
- }
-
- /**
- * @return The Uri of the part data or null if the data wasn't set or
- * the data is stored as byte array.
- * @see #getData
- */
- public Uri getDataUri() {
- return mUri;
- }
-
- /**
- * Set Content-id value
- *
- * @param contentId the content-id value
- * @throws NullPointerException if the value is null.
- */
- public void setContentId(byte[] contentId) {
- if((contentId == null) || (contentId.length == 0)) {
- throw new IllegalArgumentException(
- "Content-Id may not be null or empty.");
- }
-
- if ((contentId.length > 1)
- && ((char) contentId[0] == '<')
- && ((char) contentId[contentId.length - 1] == '>')) {
- mPartHeader.put(P_CONTENT_ID, contentId);
- return;
- }
-
- // Insert beginning '<' and trailing '>' for Content-Id.
- byte[] buffer = new byte[contentId.length + 2];
- buffer[0] = (byte) (0xff & '<');
- buffer[buffer.length - 1] = (byte) (0xff & '>');
- System.arraycopy(contentId, 0, buffer, 1, contentId.length);
- mPartHeader.put(P_CONTENT_ID, buffer);
- }
-
- /**
- * Get Content-id value.
- *
- * @return the value
- */
- public byte[] getContentId() {
- return (byte[]) mPartHeader.get(P_CONTENT_ID);
- }
-
- /**
- * Set Char-set value.
- *
- * @param charset the value
- */
- public void setCharset(int charset) {
- mPartHeader.put(P_CHARSET, charset);
- }
-
- /**
- * Get Char-set value
- *
- * @return the charset value. Return 0 if charset was not set.
- */
- public int getCharset() {
- Integer charset = (Integer) mPartHeader.get(P_CHARSET);
- if(charset == null) {
- return 0;
- } else {
- return charset.intValue();
- }
- }
-
- /**
- * Set Content-Location value.
- *
- * @param contentLocation the value
- * @throws NullPointerException if the value is null.
- */
- public void setContentLocation(byte[] contentLocation) {
- if(contentLocation == null) {
- throw new NullPointerException("null content-location");
- }
-
- mPartHeader.put(P_CONTENT_LOCATION, contentLocation);
- }
-
- /**
- * Get Content-Location value.
- *
- * @return the value
- * return PduPart.disposition[0] instead of <Octet 128> (Form-data).
- * return PduPart.disposition[1] instead of <Octet 129> (Attachment).
- * return PduPart.disposition[2] instead of <Octet 130> (Inline).
- */
- public byte[] getContentLocation() {
- return (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
- }
-
- /**
- * Set Content-Disposition value.
- * Use PduPart.disposition[0] instead of <Octet 128> (Form-data).
- * Use PduPart.disposition[1] instead of <Octet 129> (Attachment).
- * Use PduPart.disposition[2] instead of <Octet 130> (Inline).
- *
- * @param contentDisposition the value
- * @throws NullPointerException if the value is null.
- */
- public void setContentDisposition(byte[] contentDisposition) {
- if(contentDisposition == null) {
- throw new NullPointerException("null content-disposition");
- }
-
- mPartHeader.put(P_CONTENT_DISPOSITION, contentDisposition);
- }
-
- /**
- * Get Content-Disposition value.
- *
- * @return the value
- */
- public byte[] getContentDisposition() {
- return (byte[]) mPartHeader.get(P_CONTENT_DISPOSITION);
- }
-
- /**
- * Set Content-Type value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setContentType(byte[] contentType) {
- if(contentType == null) {
- throw new NullPointerException("null content-type");
- }
-
- mPartHeader.put(P_CONTENT_TYPE, contentType);
- }
-
- /**
- * Get Content-Type value of part.
- *
- * @return the value
- */
- public byte[] getContentType() {
- return (byte[]) mPartHeader.get(P_CONTENT_TYPE);
- }
-
- /**
- * Set Content-Transfer-Encoding value
- *
- * @param contentId the content-id value
- * @throws NullPointerException if the value is null.
- */
- public void setContentTransferEncoding(byte[] contentTransferEncoding) {
- if(contentTransferEncoding == null) {
- throw new NullPointerException("null content-transfer-encoding");
- }
-
- mPartHeader.put(P_CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
- }
-
- /**
- * Get Content-Transfer-Encoding value.
- *
- * @return the value
- */
- public byte[] getContentTransferEncoding() {
- return (byte[]) mPartHeader.get(P_CONTENT_TRANSFER_ENCODING);
- }
-
- /**
- * Set Content-type parameter: name.
- *
- * @param name the name value
- * @throws NullPointerException if the value is null.
- */
- public void setName(byte[] name) {
- if(null == name) {
- throw new NullPointerException("null content-id");
- }
-
- mPartHeader.put(P_NAME, name);
- }
-
- /**
- * Get content-type parameter: name.
- *
- * @return the name
- */
- public byte[] getName() {
- return (byte[]) mPartHeader.get(P_NAME);
- }
-
- /**
- * Get Content-disposition parameter: filename
- *
- * @param fileName the filename value
- * @throws NullPointerException if the value is null.
- */
- public void setFilename(byte[] fileName) {
- if(null == fileName) {
- throw new NullPointerException("null content-id");
- }
-
- mPartHeader.put(P_FILENAME, fileName);
- }
-
- /**
- * Set Content-disposition parameter: filename
- *
- * @return the filename
- */
- public byte[] getFilename() {
- return (byte[]) mPartHeader.get(P_FILENAME);
- }
-
- public String generateLocation() {
- // Assumption: At least one of the content-location / name / filename
- // or content-id should be set. This is guaranteed by the PduParser
- // for incoming messages and by MM composer for outgoing messages.
- byte[] location = (byte[]) mPartHeader.get(P_NAME);
- if(null == location) {
- location = (byte[]) mPartHeader.get(P_FILENAME);
-
- if (null == location) {
- location = (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
- }
- }
-
- if (null == location) {
- byte[] contentId = (byte[]) mPartHeader.get(P_CONTENT_ID);
- return "cid:" + new String(contentId);
- } else {
- return new String(location);
- }
- }
-}
-
diff --git a/core/java/com/google/android/mms/pdu/PduPersister.java b/core/java/com/google/android/mms/pdu/PduPersister.java
deleted file mode 100644
index d2a41f1..0000000
--- a/core/java/com/google/android/mms/pdu/PduPersister.java
+++ /dev/null
@@ -1,1225 +0,0 @@
-/*
- * Copyright (C) 2007-2008 Esmertec AG.
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import com.google.android.mms.ContentType;
-import com.google.android.mms.InvalidHeaderValueException;
-import com.google.android.mms.MmsException;
-import com.google.android.mms.util.PduCache;
-import com.google.android.mms.util.PduCacheEntry;
-import com.google.android.mms.util.SqliteWrapper;
-
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.net.Uri;
-import android.provider.Telephony.Mms;
-import android.provider.Telephony.MmsSms;
-import android.provider.Telephony.Threads;
-import android.provider.Telephony.Mms.Addr;
-import android.provider.Telephony.Mms.Part;
-import android.provider.Telephony.MmsSms.PendingMessages;
-import android.text.TextUtils;
-import android.util.Config;
-import android.util.Log;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
-
-/**
- * This class is the high-level manager of PDU storage.
- */
-public class PduPersister {
- private static final String TAG = "PduPersister";
- private static final boolean DEBUG = false;
- private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
-
- private static final long DUMMY_THREAD_ID = Long.MAX_VALUE;
-
- /**
- * The uri of temporary drm objects.
- */
- public static final String TEMPORARY_DRM_OBJECT_URI =
- "content://mms/" + Long.MAX_VALUE + "/part";
- /**
- * Indicate that we transiently failed to process a MM.
- */
- public static final int PROC_STATUS_TRANSIENT_FAILURE = 1;
- /**
- * Indicate that we permanently failed to process a MM.
- */
- public static final int PROC_STATUS_PERMANENTLY_FAILURE = 2;
- /**
- * Indicate that we have successfully processed a MM.
- */
- public static final int PROC_STATUS_COMPLETED = 3;
-
- private static PduPersister sPersister;
- private static final PduCache PDU_CACHE_INSTANCE;
-
- private static final int[] ADDRESS_FIELDS = new int[] {
- PduHeaders.BCC,
- PduHeaders.CC,
- PduHeaders.FROM,
- PduHeaders.TO
- };
-
- private static final String[] PDU_PROJECTION = new String[] {
- Mms._ID,
- Mms.MESSAGE_BOX,
- Mms.THREAD_ID,
- Mms.RETRIEVE_TEXT,
- Mms.SUBJECT,
- Mms.CONTENT_LOCATION,
- Mms.CONTENT_TYPE,
- Mms.MESSAGE_CLASS,
- Mms.MESSAGE_ID,
- Mms.RESPONSE_TEXT,
- Mms.TRANSACTION_ID,
- Mms.CONTENT_CLASS,
- Mms.DELIVERY_REPORT,
- Mms.MESSAGE_TYPE,
- Mms.MMS_VERSION,
- Mms.PRIORITY,
- Mms.READ_REPORT,
- Mms.READ_STATUS,
- Mms.REPORT_ALLOWED,
- Mms.RETRIEVE_STATUS,
- Mms.STATUS,
- Mms.DATE,
- Mms.DELIVERY_TIME,
- Mms.EXPIRY,
- Mms.MESSAGE_SIZE,
- Mms.SUBJECT_CHARSET,
- Mms.RETRIEVE_TEXT_CHARSET,
- };
-
- private static final int PDU_COLUMN_ID = 0;
- private static final int PDU_COLUMN_MESSAGE_BOX = 1;
- private static final int PDU_COLUMN_THREAD_ID = 2;
- private static final int PDU_COLUMN_RETRIEVE_TEXT = 3;
- private static final int PDU_COLUMN_SUBJECT = 4;
- private static final int PDU_COLUMN_CONTENT_LOCATION = 5;
- private static final int PDU_COLUMN_CONTENT_TYPE = 6;
- private static final int PDU_COLUMN_MESSAGE_CLASS = 7;
- private static final int PDU_COLUMN_MESSAGE_ID = 8;
- private static final int PDU_COLUMN_RESPONSE_TEXT = 9;
- private static final int PDU_COLUMN_TRANSACTION_ID = 10;
- private static final int PDU_COLUMN_CONTENT_CLASS = 11;
- private static final int PDU_COLUMN_DELIVERY_REPORT = 12;
- private static final int PDU_COLUMN_MESSAGE_TYPE = 13;
- private static final int PDU_COLUMN_MMS_VERSION = 14;
- private static final int PDU_COLUMN_PRIORITY = 15;
- private static final int PDU_COLUMN_READ_REPORT = 16;
- private static final int PDU_COLUMN_READ_STATUS = 17;
- private static final int PDU_COLUMN_REPORT_ALLOWED = 18;
- private static final int PDU_COLUMN_RETRIEVE_STATUS = 19;
- private static final int PDU_COLUMN_STATUS = 20;
- private static final int PDU_COLUMN_DATE = 21;
- private static final int PDU_COLUMN_DELIVERY_TIME = 22;
- private static final int PDU_COLUMN_EXPIRY = 23;
- private static final int PDU_COLUMN_MESSAGE_SIZE = 24;
- private static final int PDU_COLUMN_SUBJECT_CHARSET = 25;
- private static final int PDU_COLUMN_RETRIEVE_TEXT_CHARSET = 26;
-
- private static final String[] PART_PROJECTION = new String[] {
- Part._ID,
- Part.CHARSET,
- Part.CONTENT_DISPOSITION,
- Part.CONTENT_ID,
- Part.CONTENT_LOCATION,
- Part.CONTENT_TYPE,
- Part.FILENAME,
- Part.NAME,
- };
-
- private static final int PART_COLUMN_ID = 0;
- private static final int PART_COLUMN_CHARSET = 1;
- private static final int PART_COLUMN_CONTENT_DISPOSITION = 2;
- private static final int PART_COLUMN_CONTENT_ID = 3;
- private static final int PART_COLUMN_CONTENT_LOCATION = 4;
- private static final int PART_COLUMN_CONTENT_TYPE = 5;
- private static final int PART_COLUMN_FILENAME = 6;
- private static final int PART_COLUMN_NAME = 7;
-
- private static final HashMap<Uri, Integer> MESSAGE_BOX_MAP;
- // These map are used for convenience in persist() and load().
- private static final HashMap<Integer, Integer> CHARSET_COLUMN_INDEX_MAP;
- private static final HashMap<Integer, Integer> ENCODED_STRING_COLUMN_INDEX_MAP;
- private static final HashMap<Integer, Integer> TEXT_STRING_COLUMN_INDEX_MAP;
- private static final HashMap<Integer, Integer> OCTET_COLUMN_INDEX_MAP;
- private static final HashMap<Integer, Integer> LONG_COLUMN_INDEX_MAP;
- private static final HashMap<Integer, String> CHARSET_COLUMN_NAME_MAP;
- private static final HashMap<Integer, String> ENCODED_STRING_COLUMN_NAME_MAP;
- private static final HashMap<Integer, String> TEXT_STRING_COLUMN_NAME_MAP;
- private static final HashMap<Integer, String> OCTET_COLUMN_NAME_MAP;
- private static final HashMap<Integer, String> LONG_COLUMN_NAME_MAP;
-
- static {
- MESSAGE_BOX_MAP = new HashMap<Uri, Integer>();
- MESSAGE_BOX_MAP.put(Mms.Inbox.CONTENT_URI, Mms.MESSAGE_BOX_INBOX);
- MESSAGE_BOX_MAP.put(Mms.Sent.CONTENT_URI, Mms.MESSAGE_BOX_SENT);
- MESSAGE_BOX_MAP.put(Mms.Draft.CONTENT_URI, Mms.MESSAGE_BOX_DRAFTS);
- MESSAGE_BOX_MAP.put(Mms.Outbox.CONTENT_URI, Mms.MESSAGE_BOX_OUTBOX);
-
- CHARSET_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>();
- CHARSET_COLUMN_INDEX_MAP.put(PduHeaders.SUBJECT, PDU_COLUMN_SUBJECT_CHARSET);
- CHARSET_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_TEXT, PDU_COLUMN_RETRIEVE_TEXT_CHARSET);
-
- CHARSET_COLUMN_NAME_MAP = new HashMap<Integer, String>();
- CHARSET_COLUMN_NAME_MAP.put(PduHeaders.SUBJECT, Mms.SUBJECT_CHARSET);
- CHARSET_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_TEXT, Mms.RETRIEVE_TEXT_CHARSET);
-
- // Encoded string field code -> column index/name map.
- ENCODED_STRING_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>();
- ENCODED_STRING_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_TEXT, PDU_COLUMN_RETRIEVE_TEXT);
- ENCODED_STRING_COLUMN_INDEX_MAP.put(PduHeaders.SUBJECT, PDU_COLUMN_SUBJECT);
-
- ENCODED_STRING_COLUMN_NAME_MAP = new HashMap<Integer, String>();
- ENCODED_STRING_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_TEXT, Mms.RETRIEVE_TEXT);
- ENCODED_STRING_COLUMN_NAME_MAP.put(PduHeaders.SUBJECT, Mms.SUBJECT);
-
- // Text string field code -> column index/name map.
- TEXT_STRING_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>();
- TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_LOCATION, PDU_COLUMN_CONTENT_LOCATION);
- TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_TYPE, PDU_COLUMN_CONTENT_TYPE);
- TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_CLASS, PDU_COLUMN_MESSAGE_CLASS);
- TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_ID, PDU_COLUMN_MESSAGE_ID);
- TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.RESPONSE_TEXT, PDU_COLUMN_RESPONSE_TEXT);
- TEXT_STRING_COLUMN_INDEX_MAP.put(PduHeaders.TRANSACTION_ID, PDU_COLUMN_TRANSACTION_ID);
-
- TEXT_STRING_COLUMN_NAME_MAP = new HashMap<Integer, String>();
- TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_LOCATION, Mms.CONTENT_LOCATION);
- TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_TYPE, Mms.CONTENT_TYPE);
- TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_CLASS, Mms.MESSAGE_CLASS);
- TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_ID, Mms.MESSAGE_ID);
- TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.RESPONSE_TEXT, Mms.RESPONSE_TEXT);
- TEXT_STRING_COLUMN_NAME_MAP.put(PduHeaders.TRANSACTION_ID, Mms.TRANSACTION_ID);
-
- // Octet field code -> column index/name map.
- OCTET_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>();
- OCTET_COLUMN_INDEX_MAP.put(PduHeaders.CONTENT_CLASS, PDU_COLUMN_CONTENT_CLASS);
- OCTET_COLUMN_INDEX_MAP.put(PduHeaders.DELIVERY_REPORT, PDU_COLUMN_DELIVERY_REPORT);
- OCTET_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_TYPE, PDU_COLUMN_MESSAGE_TYPE);
- OCTET_COLUMN_INDEX_MAP.put(PduHeaders.MMS_VERSION, PDU_COLUMN_MMS_VERSION);
- OCTET_COLUMN_INDEX_MAP.put(PduHeaders.PRIORITY, PDU_COLUMN_PRIORITY);
- OCTET_COLUMN_INDEX_MAP.put(PduHeaders.READ_REPORT, PDU_COLUMN_READ_REPORT);
- OCTET_COLUMN_INDEX_MAP.put(PduHeaders.READ_STATUS, PDU_COLUMN_READ_STATUS);
- OCTET_COLUMN_INDEX_MAP.put(PduHeaders.REPORT_ALLOWED, PDU_COLUMN_REPORT_ALLOWED);
- OCTET_COLUMN_INDEX_MAP.put(PduHeaders.RETRIEVE_STATUS, PDU_COLUMN_RETRIEVE_STATUS);
- OCTET_COLUMN_INDEX_MAP.put(PduHeaders.STATUS, PDU_COLUMN_STATUS);
-
- OCTET_COLUMN_NAME_MAP = new HashMap<Integer, String>();
- OCTET_COLUMN_NAME_MAP.put(PduHeaders.CONTENT_CLASS, Mms.CONTENT_CLASS);
- OCTET_COLUMN_NAME_MAP.put(PduHeaders.DELIVERY_REPORT, Mms.DELIVERY_REPORT);
- OCTET_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_TYPE, Mms.MESSAGE_TYPE);
- OCTET_COLUMN_NAME_MAP.put(PduHeaders.MMS_VERSION, Mms.MMS_VERSION);
- OCTET_COLUMN_NAME_MAP.put(PduHeaders.PRIORITY, Mms.PRIORITY);
- OCTET_COLUMN_NAME_MAP.put(PduHeaders.READ_REPORT, Mms.READ_REPORT);
- OCTET_COLUMN_NAME_MAP.put(PduHeaders.READ_STATUS, Mms.READ_STATUS);
- OCTET_COLUMN_NAME_MAP.put(PduHeaders.REPORT_ALLOWED, Mms.REPORT_ALLOWED);
- OCTET_COLUMN_NAME_MAP.put(PduHeaders.RETRIEVE_STATUS, Mms.RETRIEVE_STATUS);
- OCTET_COLUMN_NAME_MAP.put(PduHeaders.STATUS, Mms.STATUS);
-
- // Long field code -> column index/name map.
- LONG_COLUMN_INDEX_MAP = new HashMap<Integer, Integer>();
- LONG_COLUMN_INDEX_MAP.put(PduHeaders.DATE, PDU_COLUMN_DATE);
- LONG_COLUMN_INDEX_MAP.put(PduHeaders.DELIVERY_TIME, PDU_COLUMN_DELIVERY_TIME);
- LONG_COLUMN_INDEX_MAP.put(PduHeaders.EXPIRY, PDU_COLUMN_EXPIRY);
- LONG_COLUMN_INDEX_MAP.put(PduHeaders.MESSAGE_SIZE, PDU_COLUMN_MESSAGE_SIZE);
-
- LONG_COLUMN_NAME_MAP = new HashMap<Integer, String>();
- LONG_COLUMN_NAME_MAP.put(PduHeaders.DATE, Mms.DATE);
- LONG_COLUMN_NAME_MAP.put(PduHeaders.DELIVERY_TIME, Mms.DELIVERY_TIME);
- LONG_COLUMN_NAME_MAP.put(PduHeaders.EXPIRY, Mms.EXPIRY);
- LONG_COLUMN_NAME_MAP.put(PduHeaders.MESSAGE_SIZE, Mms.MESSAGE_SIZE);
-
- PDU_CACHE_INSTANCE = PduCache.getInstance();
- }
-
- private final Context mContext;
- private final ContentResolver mContentResolver;
-
- private PduPersister(Context context) {
- mContext = context;
- mContentResolver = context.getContentResolver();
- }
-
- /** Get(or create if not exist) an instance of PduPersister */
- public static PduPersister getPduPersister(Context context) {
- if ((sPersister == null) || !context.equals(sPersister.mContext)) {
- sPersister = new PduPersister(context);
- }
-
- return sPersister;
- }
-
- private void setEncodedStringValueToHeaders(
- Cursor c, int columnIndex,
- PduHeaders headers, int mapColumn) {
- String s = c.getString(columnIndex);
- if ((s != null) && (s.length() > 0)) {
- int charsetColumnIndex = CHARSET_COLUMN_INDEX_MAP.get(mapColumn);
- int charset = c.getInt(charsetColumnIndex);
- EncodedStringValue value = new EncodedStringValue(
- charset, getBytes(s));
- headers.setEncodedStringValue(value, mapColumn);
- }
- }
-
- private void setTextStringToHeaders(
- Cursor c, int columnIndex,
- PduHeaders headers, int mapColumn) {
- String s = c.getString(columnIndex);
- if (s != null) {
- headers.setTextString(getBytes(s), mapColumn);
- }
- }
-
- private void setOctetToHeaders(
- Cursor c, int columnIndex,
- PduHeaders headers, int mapColumn) throws InvalidHeaderValueException {
- if (!c.isNull(columnIndex)) {
- int b = c.getInt(columnIndex);
- headers.setOctet(b, mapColumn);
- }
- }
-
- private void setLongToHeaders(
- Cursor c, int columnIndex,
- PduHeaders headers, int mapColumn) {
- if (!c.isNull(columnIndex)) {
- long l = c.getLong(columnIndex);
- headers.setLongInteger(l, mapColumn);
- }
- }
-
- private Integer getIntegerFromPartColumn(Cursor c, int columnIndex) {
- if (!c.isNull(columnIndex)) {
- return c.getInt(columnIndex);
- }
- return null;
- }
-
- private byte[] getByteArrayFromPartColumn(Cursor c, int columnIndex) {
- if (!c.isNull(columnIndex)) {
- return getBytes(c.getString(columnIndex));
- }
- return null;
- }
-
- private PduPart[] loadParts(long msgId) throws MmsException {
- Cursor c = SqliteWrapper.query(mContext, mContentResolver,
- Uri.parse("content://mms/" + msgId + "/part"),
- PART_PROJECTION, null, null, null);
-
- PduPart[] parts = null;
-
- try {
- if ((c == null) || (c.getCount() == 0)) {
- if (LOCAL_LOGV) {
- Log.v(TAG, "loadParts(" + msgId + "): no part to load.");
- }
- return null;
- }
-
- int partCount = c.getCount();
- int partIdx = 0;
- parts = new PduPart[partCount];
- while (c.moveToNext()) {
- PduPart part = new PduPart();
- Integer charset = getIntegerFromPartColumn(
- c, PART_COLUMN_CHARSET);
- if (charset != null) {
- part.setCharset(charset);
- }
-
- byte[] contentDisposition = getByteArrayFromPartColumn(
- c, PART_COLUMN_CONTENT_DISPOSITION);
- if (contentDisposition != null) {
- part.setContentDisposition(contentDisposition);
- }
-
- byte[] contentId = getByteArrayFromPartColumn(
- c, PART_COLUMN_CONTENT_ID);
- if (contentId != null) {
- part.setContentId(contentId);
- }
-
- byte[] contentLocation = getByteArrayFromPartColumn(
- c, PART_COLUMN_CONTENT_LOCATION);
- if (contentLocation != null) {
- part.setContentLocation(contentLocation);
- }
-
- byte[] contentType = getByteArrayFromPartColumn(
- c, PART_COLUMN_CONTENT_TYPE);
- if (contentType != null) {
- part.setContentType(contentType);
- } else {
- throw new MmsException("Content-Type must be set.");
- }
-
- byte[] fileName = getByteArrayFromPartColumn(
- c, PART_COLUMN_FILENAME);
- if (fileName != null) {
- part.setFilename(fileName);
- }
-
- byte[] name = getByteArrayFromPartColumn(
- c, PART_COLUMN_NAME);
- if (name != null) {
- part.setName(name);
- }
-
- // Construct a Uri for this part.
- long partId = c.getLong(PART_COLUMN_ID);
- Uri partURI = Uri.parse("content://mms/part/" + partId);
- part.setDataUri(partURI);
-
- // For images/audio/video, we won't keep their data in Part
- // because their renderer accept Uri as source.
- String type = toIsoString(contentType);
- if (!ContentType.isImageType(type)
- && !ContentType.isAudioType(type)
- && !ContentType.isVideoType(type)) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- InputStream is = null;
-
- try {
- is = mContentResolver.openInputStream(partURI);
-
- byte[] buffer = new byte[256];
- int len = is.read(buffer);
- while (len >= 0) {
- baos.write(buffer, 0, len);
- len = is.read(buffer);
- }
- } catch (IOException e) {
- Log.e(TAG, "Failed to load part data", e);
- c.close();
- throw new MmsException(e);
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException e) {
- Log.e(TAG, "Failed to close stream", e);
- } // Ignore
- }
- }
- part.setData(baos.toByteArray());
- }
- parts[partIdx++] = part;
- }
- } finally {
- if (c != null) {
- c.close();
- }
- }
-
- return parts;
- }
-
- private void loadAddress(long msgId, PduHeaders headers) {
- Cursor c = SqliteWrapper.query(mContext, mContentResolver,
- Uri.parse("content://mms/" + msgId + "/addr"),
- new String[] { Addr.ADDRESS, Addr.CHARSET, Addr.TYPE },
- null, null, null);
-
- if (c != null) {
- try {
- while (c.moveToNext()) {
- String addr = c.getString(0);
- if (!TextUtils.isEmpty(addr)) {
- int addrType = c.getInt(2);
- switch (addrType) {
- case PduHeaders.FROM:
- headers.setEncodedStringValue(
- new EncodedStringValue(c.getInt(1), getBytes(addr)),
- addrType);
- break;
- case PduHeaders.TO:
- case PduHeaders.CC:
- case PduHeaders.BCC:
- headers.appendEncodedStringValue(
- new EncodedStringValue(c.getInt(1), getBytes(addr)),
- addrType);
- break;
- default:
- Log.e(TAG, "Unknown address type: " + addrType);
- break;
- }
- }
- }
- } finally {
- c.close();
- }
- }
- }
-
- /**
- * Load a PDU from storage by given Uri.
- *
- * @param uri The Uri of the PDU to be loaded.
- * @return A generic PDU object, it may be cast to dedicated PDU.
- * @throws MmsException Failed to load some fields of a PDU.
- */
- public GenericPdu load(Uri uri) throws MmsException {
- PduCacheEntry cacheEntry = PDU_CACHE_INSTANCE.get(uri);
- if (cacheEntry != null) {
- return cacheEntry.getPdu();
- }
-
- Cursor c = SqliteWrapper.query(mContext, mContentResolver, uri,
- PDU_PROJECTION, null, null, null);
- PduHeaders headers = new PduHeaders();
- Set<Entry<Integer, Integer>> set;
- long msgId = ContentUris.parseId(uri);
- int msgBox;
- long threadId;
-
- try {
- if ((c == null) || (c.getCount() != 1) || !c.moveToFirst()) {
- throw new MmsException("Bad uri: " + uri);
- }
-
- msgBox = c.getInt(PDU_COLUMN_MESSAGE_BOX);
- threadId = c.getLong(PDU_COLUMN_THREAD_ID);
-
- set = ENCODED_STRING_COLUMN_INDEX_MAP.entrySet();
- for (Entry<Integer, Integer> e : set) {
- setEncodedStringValueToHeaders(
- c, e.getValue(), headers, e.getKey());
- }
-
- set = TEXT_STRING_COLUMN_INDEX_MAP.entrySet();
- for (Entry<Integer, Integer> e : set) {
- setTextStringToHeaders(
- c, e.getValue(), headers, e.getKey());
- }
-
- set = OCTET_COLUMN_INDEX_MAP.entrySet();
- for (Entry<Integer, Integer> e : set) {
- setOctetToHeaders(
- c, e.getValue(), headers, e.getKey());
- }
-
- set = LONG_COLUMN_INDEX_MAP.entrySet();
- for (Entry<Integer, Integer> e : set) {
- setLongToHeaders(
- c, e.getValue(), headers, e.getKey());
- }
- } finally {
- if (c != null) {
- c.close();
- }
- }
-
- // Check whether 'msgId' has been assigned a valid value.
- if (msgId == -1L) {
- throw new MmsException("Error! ID of the message: -1.");
- }
-
- // Load address information of the MM.
- loadAddress(msgId, headers);
-
- int msgType = headers.getOctet(PduHeaders.MESSAGE_TYPE);
- PduBody body = new PduBody();
-
- // For PDU which type is M_retrieve.conf or Send.req, we should
- // load multiparts and put them into the body of the PDU.
- if ((msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF)
- || (msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)) {
- PduPart[] parts = loadParts(msgId);
- if (parts != null) {
- int partsNum = parts.length;
- for (int i = 0; i < partsNum; i++) {
- body.addPart(parts[i]);
- }
- }
- }
-
- GenericPdu pdu = null;
- switch (msgType) {
- case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
- pdu = new NotificationInd(headers);
- break;
- case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
- pdu = new DeliveryInd(headers);
- break;
- case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND:
- pdu = new ReadOrigInd(headers);
- break;
- case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
- pdu = new RetrieveConf(headers, body);
- break;
- case PduHeaders.MESSAGE_TYPE_SEND_REQ:
- pdu = new SendReq(headers, body);
- break;
- case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
- pdu = new AcknowledgeInd(headers);
- break;
- case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
- pdu = new NotifyRespInd(headers);
- break;
- case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
- pdu = new ReadRecInd(headers);
- break;
- case PduHeaders.MESSAGE_TYPE_SEND_CONF:
- case PduHeaders.MESSAGE_TYPE_FORWARD_REQ:
- case PduHeaders.MESSAGE_TYPE_FORWARD_CONF:
- case PduHeaders.MESSAGE_TYPE_MBOX_STORE_REQ:
- case PduHeaders.MESSAGE_TYPE_MBOX_STORE_CONF:
- case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_REQ:
- case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_CONF:
- case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_REQ:
- case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_CONF:
- case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_REQ:
- case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_CONF:
- case PduHeaders.MESSAGE_TYPE_MBOX_DESCR:
- case PduHeaders.MESSAGE_TYPE_DELETE_REQ:
- case PduHeaders.MESSAGE_TYPE_DELETE_CONF:
- case PduHeaders.MESSAGE_TYPE_CANCEL_REQ:
- case PduHeaders.MESSAGE_TYPE_CANCEL_CONF:
- throw new MmsException(
- "Unsupported PDU type: " + Integer.toHexString(msgType));
-
- default:
- throw new MmsException(
- "Unrecognized PDU type: " + Integer.toHexString(msgType));
- }
-
- cacheEntry = new PduCacheEntry(pdu, msgBox, threadId);
- PDU_CACHE_INSTANCE.put(uri, cacheEntry);
- return pdu;
- }
-
- private void persistAddress(
- long msgId, int type, EncodedStringValue[] array) {
- ContentValues values = new ContentValues(3);
-
- for (EncodedStringValue addr : array) {
- values.clear(); // Clear all values first.
- values.put(Addr.ADDRESS, toIsoString(addr.getTextString()));
- values.put(Addr.CHARSET, addr.getCharacterSet());
- values.put(Addr.TYPE, type);
-
- Uri uri = Uri.parse("content://mms/" + msgId + "/addr");
- SqliteWrapper.insert(mContext, mContentResolver, uri, values);
- }
- }
-
- public Uri persistPart(PduPart part, long msgId)
- throws MmsException {
- Uri uri = Uri.parse("content://mms/" + msgId + "/part");
- ContentValues values = new ContentValues(8);
-
- int charset = part.getCharset();
- if (charset != 0 ) {
- values.put(Part.CHARSET, charset);
- }
-
- String contentType = null;
- if (part.getContentType() != null) {
- contentType = toIsoString(part.getContentType());
- values.put(Part.CONTENT_TYPE, contentType);
- // To ensure the SMIL part is always the first part.
- if (ContentType.APP_SMIL.equals(contentType)) {
- values.put(Part.SEQ, -1);
- }
- } else {
- throw new MmsException("MIME type of the part must be set.");
- }
-
- if (part.getFilename() != null) {
- String fileName = new String(part.getFilename());
- values.put(Part.FILENAME, fileName);
- }
-
- if (part.getName() != null) {
- String name = new String(part.getName());
- values.put(Part.NAME, name);
- }
-
- Object value = null;
- if (part.getContentDisposition() != null) {
- value = toIsoString(part.getContentDisposition());
- values.put(Part.CONTENT_DISPOSITION, (String) value);
- }
-
- if (part.getContentId() != null) {
- value = toIsoString(part.getContentId());
- values.put(Part.CONTENT_ID, (String) value);
- }
-
- if (part.getContentLocation() != null) {
- value = toIsoString(part.getContentLocation());
- values.put(Part.CONTENT_LOCATION, (String) value);
- }
-
- Uri res = SqliteWrapper.insert(mContext, mContentResolver, uri, values);
- if (res == null) {
- throw new MmsException("Failed to persist part, return null.");
- }
-
- persistData(part, res, contentType);
- // After successfully store the data, we should update
- // the dataUri of the part.
- part.setDataUri(res);
-
- return res;
- }
-
- /**
- * Save data of the part into storage. The source data may be given
- * by a byte[] or a Uri. If it's a byte[], directly save it
- * into storage, otherwise load source data from the dataUri and then
- * save it. If the data is an image, we may scale down it according
- * to user preference.
- *
- * @param part The PDU part which contains data to be saved.
- * @param uri The URI of the part.
- * @param contentType The MIME type of the part.
- * @throws MmsException Cannot find source data or error occurred
- * while saving the data.
- */
- private void persistData(PduPart part, Uri uri,
- String contentType)
- throws MmsException {
- OutputStream os = null;
- InputStream is = null;
-
- try {
- os = mContentResolver.openOutputStream(uri);
- byte[] data = part.getData();
- if (data == null) {
- Uri dataUri = part.getDataUri();
- if ((dataUri == null) || (dataUri == uri)) {
- Log.w(TAG, "Can't find data for this part.");
- return;
- }
- is = mContentResolver.openInputStream(dataUri);
-
- if (LOCAL_LOGV) {
- Log.v(TAG, "Saving data to: " + uri);
- }
-
- byte[] buffer = new byte[256];
- for (int len = 0; (len = is.read(buffer)) != -1; ) {
- os.write(buffer, 0, len);
- }
- } else {
- if (LOCAL_LOGV) {
- Log.v(TAG, "Saving data to: " + uri);
- }
- os.write(data);
- }
- } catch (FileNotFoundException e) {
- Log.e(TAG, "Failed to open Input/Output stream.", e);
- throw new MmsException(e);
- } catch (IOException e) {
- Log.e(TAG, "Failed to read/write data.", e);
- throw new MmsException(e);
- } finally {
- if (os != null) {
- try {
- os.close();
- } catch (IOException e) {
- Log.e(TAG, "IOException while closing: " + os, e);
- } // Ignore
- }
- if (is != null) {
- try {
- is.close();
- } catch (IOException e) {
- Log.e(TAG, "IOException while closing: " + is, e);
- } // Ignore
- }
- }
- }
-
- private void updateAddress(
- long msgId, int type, EncodedStringValue[] array) {
- // Delete old address information and then insert new ones.
- SqliteWrapper.delete(mContext, mContentResolver,
- Uri.parse("content://mms/" + msgId + "/addr"),
- Addr.TYPE + "=" + type, null);
-
- persistAddress(msgId, type, array);
- }
-
- /**
- * Update headers of a SendReq.
- *
- * @param uri The PDU which need to be updated.
- * @param pdu New headers.
- * @throws MmsException Bad URI or updating failed.
- */
- public void updateHeaders(Uri uri, SendReq sendReq) {
- PDU_CACHE_INSTANCE.purge(uri);
-
- ContentValues values = new ContentValues(9);
- byte[] contentType = sendReq.getContentType();
- if (contentType != null) {
- values.put(Mms.CONTENT_TYPE, toIsoString(contentType));
- }
-
- long date = sendReq.getDate();
- if (date != -1) {
- values.put(Mms.DATE, date);
- }
-
- int deliveryReport = sendReq.getDeliveryReport();
- if (deliveryReport != 0) {
- values.put(Mms.DELIVERY_REPORT, deliveryReport);
- }
-
- long expiry = sendReq.getExpiry();
- if (expiry != -1) {
- values.put(Mms.EXPIRY, expiry);
- }
-
- byte[] msgClass = sendReq.getMessageClass();
- if (msgClass != null) {
- values.put(Mms.MESSAGE_CLASS, toIsoString(msgClass));
- }
-
- int priority = sendReq.getPriority();
- if (priority != 0) {
- values.put(Mms.PRIORITY, priority);
- }
-
- int readReport = sendReq.getReadReport();
- if (readReport != 0) {
- values.put(Mms.READ_REPORT, readReport);
- }
-
- byte[] transId = sendReq.getTransactionId();
- if (transId != null) {
- values.put(Mms.TRANSACTION_ID, toIsoString(transId));
- }
-
- EncodedStringValue subject = sendReq.getSubject();
- if (subject != null) {
- values.put(Mms.SUBJECT, toIsoString(subject.getTextString()));
- values.put(Mms.SUBJECT_CHARSET, subject.getCharacterSet());
- }
-
- PduHeaders headers = sendReq.getPduHeaders();
- HashSet<String> recipients = new HashSet<String>();
- for (int addrType : ADDRESS_FIELDS) {
- EncodedStringValue[] array = null;
- if (addrType == PduHeaders.FROM) {
- EncodedStringValue v = headers.getEncodedStringValue(addrType);
- if (v != null) {
- array = new EncodedStringValue[1];
- array[0] = v;
- }
- } else {
- array = headers.getEncodedStringValues(addrType);
- }
-
- if (array != null) {
- long msgId = ContentUris.parseId(uri);
- updateAddress(msgId, addrType, array);
- if (addrType == PduHeaders.TO) {
- for (EncodedStringValue v : array) {
- if (v != null) {
- recipients.add(v.getString());
- }
- }
- }
- }
- }
-
- long threadId = Threads.getOrCreateThreadId(mContext, recipients);
- values.put(Mms.THREAD_ID, threadId);
-
- SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null);
- }
-
- private void updatePart(Uri uri, PduPart part) throws MmsException {
- ContentValues values = new ContentValues(7);
-
- int charset = part.getCharset();
- if (charset != 0 ) {
- values.put(Part.CHARSET, charset);
- }
-
- String contentType = null;
- if (part.getContentType() != null) {
- contentType = toIsoString(part.getContentType());
- values.put(Part.CONTENT_TYPE, contentType);
- } else {
- throw new MmsException("MIME type of the part must be set.");
- }
-
- if (part.getFilename() != null) {
- String fileName = new String(part.getFilename());
- values.put(Part.FILENAME, fileName);
- }
-
- if (part.getName() != null) {
- String name = new String(part.getName());
- values.put(Part.NAME, name);
- }
-
- Object value = null;
- if (part.getContentDisposition() != null) {
- value = toIsoString(part.getContentDisposition());
- values.put(Part.CONTENT_DISPOSITION, (String) value);
- }
-
- if (part.getContentId() != null) {
- value = toIsoString(part.getContentId());
- values.put(Part.CONTENT_ID, (String) value);
- }
-
- if (part.getContentLocation() != null) {
- value = toIsoString(part.getContentLocation());
- values.put(Part.CONTENT_LOCATION, (String) value);
- }
-
- SqliteWrapper.update(mContext, mContentResolver, uri, values, null, null);
-
- // Only update the data when:
- // 1. New binary data supplied or
- // 2. The Uri of the part is different from the current one.
- if ((part.getData() != null)
- || (uri != part.getDataUri())) {
- persistData(part, uri, contentType);
- }
- }
-
- /**
- * Update all parts of a PDU.
- *
- * @param uri The PDU which need to be updated.
- * @param body New message body of the PDU.
- * @throws MmsException Bad URI or updating failed.
- */
- public void updateParts(Uri uri, PduBody body)
- throws MmsException {
- PduCacheEntry cacheEntry = PDU_CACHE_INSTANCE.get(uri);
- if (cacheEntry != null) {
- ((MultimediaMessagePdu) cacheEntry.getPdu()).setBody(body);
- }
-
- ArrayList<PduPart> toBeCreated = new ArrayList<PduPart>();
- HashMap<Uri, PduPart> toBeUpdated = new HashMap<Uri, PduPart>();
-
- int partsNum = body.getPartsNum();
- StringBuilder filter = new StringBuilder().append('(');
- for (int i = 0; i < partsNum; i++) {
- PduPart part = body.getPart(i);
- Uri partUri = part.getDataUri();
- if ((partUri == null) || !partUri.getAuthority().startsWith("mms")) {
- toBeCreated.add(part);
- } else {
- toBeUpdated.put(partUri, part);
-
- // Don't use 'i > 0' to determine whether we should append
- // 'AND' since 'i = 0' may be skipped in another branch.
- if (filter.length() > 1) {
- filter.append(" AND ");
- }
-
- filter.append(Part._ID);
- filter.append("!=");
- DatabaseUtils.appendEscapedSQLString(filter, partUri.getLastPathSegment());
- }
- }
- filter.append(')');
-
- long msgId = ContentUris.parseId(uri);
-
- // Remove the parts which doesn't exist anymore.
- SqliteWrapper.delete(mContext, mContentResolver,
- Uri.parse(Mms.CONTENT_URI + "/" + msgId + "/part"),
- filter.length() > 2 ? filter.toString() : null, null);
-
- // Create new parts which didn't exist before.
- for (PduPart part : toBeCreated) {
- persistPart(part, msgId);
- }
-
- // Update the modified parts.
- for (Map.Entry<Uri, PduPart> e : toBeUpdated.entrySet()) {
- updatePart(e.getKey(), e.getValue());
- }
- }
-
- /**
- * Persist a PDU object to specific location in the storage.
- *
- * @param pdu The PDU object to be stored.
- * @param uri Where to store the given PDU object.
- * @return A Uri which can be used to access the stored PDU.
- */
- public Uri persist(GenericPdu pdu, Uri uri) throws MmsException {
- if (uri == null) {
- throw new MmsException("Uri may not be null.");
- }
-
- Integer msgBox = MESSAGE_BOX_MAP.get(uri);
- if (msgBox == null) {
- throw new MmsException(
- "Bad destination, must be one of "
- + "content://mms/inbox, content://mms/sent, "
- + "content://mms/drafts, content://mms/outbox, "
- + "content://mms/temp.");
- }
-
- PduHeaders header = pdu.getPduHeaders();
- PduBody body = null;
- ContentValues values = new ContentValues();
- Set<Entry<Integer, String>> set;
-
- set = ENCODED_STRING_COLUMN_NAME_MAP.entrySet();
- for (Entry<Integer, String> e : set) {
- int field = e.getKey();
- EncodedStringValue encodedString = header.getEncodedStringValue(field);
- if (encodedString != null) {
- String charsetColumn = CHARSET_COLUMN_NAME_MAP.get(field);
- values.put(e.getValue(), toIsoString(encodedString.getTextString()));
- values.put(charsetColumn, encodedString.getCharacterSet());
- }
- }
-
- set = TEXT_STRING_COLUMN_NAME_MAP.entrySet();
- for (Entry<Integer, String> e : set){
- byte[] text = header.getTextString(e.getKey());
- if (text != null) {
- values.put(e.getValue(), toIsoString(text));
- }
- }
-
- set = OCTET_COLUMN_NAME_MAP.entrySet();
- for (Entry<Integer, String> e : set){
- int b = header.getOctet(e.getKey());
- if (b != 0) {
- values.put(e.getValue(), b);
- }
- }
-
- set = LONG_COLUMN_NAME_MAP.entrySet();
- for (Entry<Integer, String> e : set){
- long l = header.getLongInteger(e.getKey());
- if (l != -1L) {
- values.put(e.getValue(), l);
- }
- }
-
- HashMap<Integer, EncodedStringValue[]> addressMap =
- new HashMap<Integer, EncodedStringValue[]>(ADDRESS_FIELDS.length);
- // Save address information.
- for (int addrType : ADDRESS_FIELDS) {
- EncodedStringValue[] array = null;
- if (addrType == PduHeaders.FROM) {
- EncodedStringValue v = header.getEncodedStringValue(addrType);
- if (v != null) {
- array = new EncodedStringValue[1];
- array[0] = v;
- }
- } else {
- array = header.getEncodedStringValues(addrType);
- }
- addressMap.put(addrType, array);
- }
-
- HashSet<String> recipients = new HashSet<String>();
- long threadId = DUMMY_THREAD_ID;
- int msgType = pdu.getMessageType();
- // Here we only allocate thread ID for M-Notification.ind,
- // M-Retrieve.conf and M-Send.req.
- // Some of other PDU types may be allocated a thread ID outside
- // this scope.
- if ((msgType == PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND)
- || (msgType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF)
- || (msgType == PduHeaders.MESSAGE_TYPE_SEND_REQ)) {
- EncodedStringValue[] array = null;
- switch (msgType) {
- case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
- case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
- array = addressMap.get(PduHeaders.FROM);
- break;
- case PduHeaders.MESSAGE_TYPE_SEND_REQ:
- array = addressMap.get(PduHeaders.TO);
- break;
- }
-
- if (array != null) {
- for (EncodedStringValue v : array) {
- if (v != null) {
- recipients.add(v.getString());
- }
- }
- }
- threadId = Threads.getOrCreateThreadId(mContext, recipients);
- }
- values.put(Mms.THREAD_ID, threadId);
-
- // Save parts first to avoid inconsistent message is loaded
- // while saving the parts.
- long dummyId = System.currentTimeMillis(); // Dummy ID of the msg.
- // Get body if the PDU is a RetrieveConf or SendReq.
- if (pdu instanceof MultimediaMessagePdu) {
- body = ((MultimediaMessagePdu) pdu).getBody();
- // Start saving parts if necessary.
- if (body != null) {
- int partsNum = body.getPartsNum();
- for (int i = 0; i < partsNum; i++) {
- PduPart part = body.getPart(i);
- persistPart(part, dummyId);
- }
- }
- }
-
- Uri res = SqliteWrapper.insert(mContext, mContentResolver, uri, values);
- if (res == null) {
- throw new MmsException("persist() failed: return null.");
- }
-
- // Get the real ID of the PDU and update all parts which were
- // saved with the dummy ID.
- long msgId = ContentUris.parseId(res);
- values = new ContentValues(1);
- values.put(Part.MSG_ID, msgId);
- SqliteWrapper.update(mContext, mContentResolver,
- Uri.parse("content://mms/" + dummyId + "/part"),
- values, null, null);
- // We should return the longest URI of the persisted PDU, for
- // example, if input URI is "content://mms/inbox" and the _ID of
- // persisted PDU is '8', we should return "content://mms/inbox/8"
- // instead of "content://mms/8".
- // FIXME: Should the MmsProvider be responsible for this???
- res = Uri.parse(uri + "/" + msgId);
-
- // Save address information.
- for (int addrType : ADDRESS_FIELDS) {
- EncodedStringValue[] array = addressMap.get(addrType);
- if (array != null) {
- persistAddress(msgId, addrType, array);
- }
- }
-
- return res;
- }
-
- /**
- * Move a PDU object from one location to another.
- *
- * @param from Specify the PDU object to be moved.
- * @param to The destination location, should be one of the following:
- * "content://mms/inbox", "content://mms/sent",
- * "content://mms/drafts", "content://mms/outbox",
- * "content://mms/trash".
- * @return New Uri of the moved PDU.
- * @throws MmsException Error occurred while moving the message.
- */
- public Uri move(Uri from, Uri to) throws MmsException {
- // Check whether the 'msgId' has been assigned a valid value.
- long msgId = ContentUris.parseId(from);
- if (msgId == -1L) {
- throw new MmsException("Error! ID of the message: -1.");
- }
-
- // Get corresponding int value of destination box.
- Integer msgBox = MESSAGE_BOX_MAP.get(to);
- if (msgBox == null) {
- throw new MmsException(
- "Bad destination, must be one of "
- + "content://mms/inbox, content://mms/sent, "
- + "content://mms/drafts, content://mms/outbox, "
- + "content://mms/temp.");
- }
-
- ContentValues values = new ContentValues(1);
- values.put(Mms.MESSAGE_BOX, msgBox);
- SqliteWrapper.update(mContext, mContentResolver, from, values, null, null);
- return ContentUris.withAppendedId(to, msgId);
- }
-
- /**
- * Wrap a byte[] into a String.
- */
- public static String toIsoString(byte[] bytes) {
- try {
- return new String(bytes, CharacterSets.MIMENAME_ISO_8859_1);
- } catch (UnsupportedEncodingException e) {
- // Impossible to reach here!
- Log.e(TAG, "ISO_8859_1 must be supported!", e);
- return "";
- }
- }
-
- /**
- * Unpack a given String into a byte[].
- */
- public static byte[] getBytes(String data) {
- try {
- return data.getBytes(CharacterSets.MIMENAME_ISO_8859_1);
- } catch (UnsupportedEncodingException e) {
- // Impossible to reach here!
- Log.e(TAG, "ISO_8859_1 must be supported!", e);
- return new byte[0];
- }
- }
-
- /**
- * Remove all objects in the temporary path.
- */
- public void release() {
- Uri uri = Uri.parse(TEMPORARY_DRM_OBJECT_URI);
- SqliteWrapper.delete(mContext, mContentResolver, uri, null, null);
- }
-
- /**
- * Find all messages to be sent or downloaded before certain time.
- */
- public Cursor getPendingMessages(long dueTime) {
- Uri.Builder uriBuilder = PendingMessages.CONTENT_URI.buildUpon();
- uriBuilder.appendQueryParameter("protocol", "mms");
-
- String selection = PendingMessages.ERROR_TYPE + " < ?"
- + " AND " + PendingMessages.DUE_TIME + " <= ?";
-
- String[] selectionArgs = new String[] {
- String.valueOf(MmsSms.ERR_TYPE_GENERIC_PERMANENT),
- String.valueOf(dueTime)
- };
-
- return SqliteWrapper.query(mContext, mContentResolver,
- uriBuilder.build(), null, selection, selectionArgs,
- PendingMessages.DUE_TIME);
- }
-}
diff --git a/core/java/com/google/android/mms/pdu/QuotedPrintable.java b/core/java/com/google/android/mms/pdu/QuotedPrintable.java
deleted file mode 100644
index a34ed12..0000000
--- a/core/java/com/google/android/mms/pdu/QuotedPrintable.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import java.io.ByteArrayOutputStream;
-
-public class QuotedPrintable {
- private static byte ESCAPE_CHAR = '=';
-
- /**
- * Decodes an array quoted-printable characters into an array of original bytes.
- * Escaped characters are converted back to their original representation.
- *
- * <p>
- * This function implements a subset of
- * quoted-printable encoding specification (rule #1 and rule #2)
- * as defined in RFC 1521.
- * </p>
- *
- * @param bytes array of quoted-printable characters
- * @return array of original bytes,
- * null if quoted-printable decoding is unsuccessful.
- */
- public static final byte[] decodeQuotedPrintable(byte[] bytes) {
- if (bytes == null) {
- return null;
- }
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
- for (int i = 0; i < bytes.length; i++) {
- int b = bytes[i];
- if (b == ESCAPE_CHAR) {
- try {
- if('\r' == (char)bytes[i + 1] &&
- '\n' == (char)bytes[i + 2]) {
- i += 2;
- continue;
- }
- int u = Character.digit((char) bytes[++i], 16);
- int l = Character.digit((char) bytes[++i], 16);
- if (u == -1 || l == -1) {
- return null;
- }
- buffer.write((char) ((u << 4) + l));
- } catch (ArrayIndexOutOfBoundsException e) {
- return null;
- }
- } else {
- buffer.write(b);
- }
- }
- return buffer.toByteArray();
- }
-}
diff --git a/core/java/com/google/android/mms/pdu/ReadOrigInd.java b/core/java/com/google/android/mms/pdu/ReadOrigInd.java
deleted file mode 100644
index 1bfc0bb..0000000
--- a/core/java/com/google/android/mms/pdu/ReadOrigInd.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import com.google.android.mms.InvalidHeaderValueException;
-
-public class ReadOrigInd extends GenericPdu {
- /**
- * Empty constructor.
- * Since the Pdu corresponding to this class is constructed
- * by the Proxy-Relay server, this class is only instantiated
- * by the Pdu Parser.
- *
- * @throws InvalidHeaderValueException if error occurs.
- */
- public ReadOrigInd() throws InvalidHeaderValueException {
- super();
- setMessageType(PduHeaders.MESSAGE_TYPE_READ_ORIG_IND);
- }
-
- /**
- * Constructor with given headers.
- *
- * @param headers Headers for this PDU.
- */
- ReadOrigInd(PduHeaders headers) {
- super(headers);
- }
-
- /**
- * Get Date value.
- *
- * @return the value
- */
- public long getDate() {
- return mPduHeaders.getLongInteger(PduHeaders.DATE);
- }
-
- /**
- * Set Date value.
- *
- * @param value the value
- */
- public void setDate(long value) {
- mPduHeaders.setLongInteger(value, PduHeaders.DATE);
- }
-
- /**
- * Get From value.
- * From-value = Value-length
- * (Address-present-token Encoded-string-value | Insert-address-token)
- *
- * @return the value
- */
- public EncodedStringValue getFrom() {
- return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
- }
-
- /**
- * Set From value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setFrom(EncodedStringValue value) {
- mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
- }
-
- /**
- * Get Message-ID value.
- *
- * @return the value
- */
- public byte[] getMessageId() {
- return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
- }
-
- /**
- * Set Message-ID value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setMessageId(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
- }
-
- /**
- * Get X-MMS-Read-status value.
- *
- * @return the value
- */
- public int getReadStatus() {
- return mPduHeaders.getOctet(PduHeaders.READ_STATUS);
- }
-
- /**
- * Set X-MMS-Read-status value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- */
- public void setReadStatus(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.READ_STATUS);
- }
-
- /**
- * Get To value.
- *
- * @return the value
- */
- public EncodedStringValue[] getTo() {
- return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
- }
-
- /**
- * Set To value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setTo(EncodedStringValue[] value) {
- mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
- }
-
- /*
- * Optional, not supported header fields:
- *
- * public byte[] getApplicId() {return null;}
- * public void setApplicId(byte[] value) {}
- *
- * public byte[] getAuxApplicId() {return null;}
- * public void getAuxApplicId(byte[] value) {}
- *
- * public byte[] getReplyApplicId() {return 0x00;}
- * public void setReplyApplicId(byte[] value) {}
- */
-}
diff --git a/core/java/com/google/android/mms/pdu/ReadRecInd.java b/core/java/com/google/android/mms/pdu/ReadRecInd.java
deleted file mode 100644
index 0a4dbf0..0000000
--- a/core/java/com/google/android/mms/pdu/ReadRecInd.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import com.google.android.mms.InvalidHeaderValueException;
-
-public class ReadRecInd extends GenericPdu {
- /**
- * Constructor, used when composing a M-ReadRec.ind pdu.
- *
- * @param from the from value
- * @param messageId the message ID value
- * @param mmsVersion current viersion of mms
- * @param readStatus the read status value
- * @param to the to value
- * @throws InvalidHeaderValueException if parameters are invalid.
- * NullPointerException if messageId or to is null.
- */
- public ReadRecInd(EncodedStringValue from,
- byte[] messageId,
- int mmsVersion,
- int readStatus,
- EncodedStringValue[] to) throws InvalidHeaderValueException {
- super();
- setMessageType(PduHeaders.MESSAGE_TYPE_READ_REC_IND);
- setFrom(from);
- setMessageId(messageId);
- setMmsVersion(mmsVersion);
- setTo(to);
- setReadStatus(readStatus);
- }
-
- /**
- * Constructor with given headers.
- *
- * @param headers Headers for this PDU.
- */
- ReadRecInd(PduHeaders headers) {
- super(headers);
- }
-
- /**
- * Get Date value.
- *
- * @return the value
- */
- public long getDate() {
- return mPduHeaders.getLongInteger(PduHeaders.DATE);
- }
-
- /**
- * Set Date value.
- *
- * @param value the value
- */
- public void setDate(long value) {
- mPduHeaders.setLongInteger(value, PduHeaders.DATE);
- }
-
- /**
- * Get From value.
- * From-value = Value-length
- * (Address-present-token Encoded-string-value | Insert-address-token)
- *
- * @return the value
- */
- public EncodedStringValue getFrom() {
- return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
- }
-
- /**
- * Set From value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setFrom(EncodedStringValue value) {
- mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
- }
-
- /**
- * Get Message-ID value.
- *
- * @return the value
- */
- public byte[] getMessageId() {
- return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
- }
-
- /**
- * Set Message-ID value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setMessageId(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
- }
-
- /**
- * Get To value.
- *
- * @return the value
- */
- public EncodedStringValue[] getTo() {
- return mPduHeaders.getEncodedStringValues(PduHeaders.TO);
- }
-
- /**
- * Set To value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setTo(EncodedStringValue[] value) {
- mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
- }
-
- /**
- * Get X-MMS-Read-status value.
- *
- * @return the value
- */
- public int getReadStatus() {
- return mPduHeaders.getOctet(PduHeaders.READ_STATUS);
- }
-
- /**
- * Set X-MMS-Read-status value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- */
- public void setReadStatus(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.READ_STATUS);
- }
-
- /*
- * Optional, not supported header fields:
- *
- * public byte[] getApplicId() {return null;}
- * public void setApplicId(byte[] value) {}
- *
- * public byte[] getAuxApplicId() {return null;}
- * public void getAuxApplicId(byte[] value) {}
- *
- * public byte[] getReplyApplicId() {return 0x00;}
- * public void setReplyApplicId(byte[] value) {}
- */
-}
diff --git a/core/java/com/google/android/mms/pdu/RetrieveConf.java b/core/java/com/google/android/mms/pdu/RetrieveConf.java
deleted file mode 100644
index 98e67c0..0000000
--- a/core/java/com/google/android/mms/pdu/RetrieveConf.java
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import com.google.android.mms.InvalidHeaderValueException;
-
-/**
- * M-Retrive.conf Pdu.
- */
-public class RetrieveConf extends MultimediaMessagePdu {
- /**
- * Empty constructor.
- * Since the Pdu corresponding to this class is constructed
- * by the Proxy-Relay server, this class is only instantiated
- * by the Pdu Parser.
- *
- * @throws InvalidHeaderValueException if error occurs.
- */
- public RetrieveConf() throws InvalidHeaderValueException {
- super();
- setMessageType(PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF);
- }
-
- /**
- * Constructor with given headers.
- *
- * @param headers Headers for this PDU.
- */
- RetrieveConf(PduHeaders headers) {
- super(headers);
- }
-
- /**
- * Constructor with given headers and body
- *
- * @param headers Headers for this PDU.
- * @param body Body of this PDu.
- */
- RetrieveConf(PduHeaders headers, PduBody body) {
- super(headers, body);
- }
-
- /**
- * Get CC value.
- *
- * @return the value
- */
- public EncodedStringValue[] getCc() {
- return mPduHeaders.getEncodedStringValues(PduHeaders.CC);
- }
-
- /**
- * Add a "CC" value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void addCc(EncodedStringValue value) {
- mPduHeaders.appendEncodedStringValue(value, PduHeaders.CC);
- }
-
- /**
- * Get Content-type value.
- *
- * @return the value
- */
- public byte[] getContentType() {
- return mPduHeaders.getTextString(PduHeaders.CONTENT_TYPE);
- }
-
- /**
- * Set Content-type value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setContentType(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.CONTENT_TYPE);
- }
-
- /**
- * Get X-Mms-Delivery-Report value.
- *
- * @return the value
- */
- public int getDeliveryReport() {
- return mPduHeaders.getOctet(PduHeaders.DELIVERY_REPORT);
- }
-
- /**
- * Set X-Mms-Delivery-Report value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- */
- public void setDeliveryReport(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.DELIVERY_REPORT);
- }
-
- /**
- * Get From value.
- * From-value = Value-length
- * (Address-present-token Encoded-string-value | Insert-address-token)
- *
- * @return the value
- */
- public EncodedStringValue getFrom() {
- return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
- }
-
- /**
- * Set From value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setFrom(EncodedStringValue value) {
- mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
- }
-
- /**
- * Get X-Mms-Message-Class value.
- * Message-class-value = Class-identifier | Token-text
- * Class-identifier = Personal | Advertisement | Informational | Auto
- *
- * @return the value
- */
- public byte[] getMessageClass() {
- return mPduHeaders.getTextString(PduHeaders.MESSAGE_CLASS);
- }
-
- /**
- * Set X-Mms-Message-Class value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setMessageClass(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.MESSAGE_CLASS);
- }
-
- /**
- * Get Message-ID value.
- *
- * @return the value
- */
- public byte[] getMessageId() {
- return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
- }
-
- /**
- * Set Message-ID value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setMessageId(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
- }
-
- /**
- * Get X-Mms-Read-Report value.
- *
- * @return the value
- */
- public int getReadReport() {
- return mPduHeaders.getOctet(PduHeaders.READ_REPORT);
- }
-
- /**
- * Set X-Mms-Read-Report value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- */
- public void setReadReport(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.READ_REPORT);
- }
-
- /**
- * Get X-Mms-Retrieve-Status value.
- *
- * @return the value
- */
- public int getRetrieveStatus() {
- return mPduHeaders.getOctet(PduHeaders.RETRIEVE_STATUS);
- }
-
- /**
- * Set X-Mms-Retrieve-Status value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- */
- public void setRetrieveStatus(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.RETRIEVE_STATUS);
- }
-
- /**
- * Get X-Mms-Retrieve-Text value.
- *
- * @return the value
- */
- public EncodedStringValue getRetrieveText() {
- return mPduHeaders.getEncodedStringValue(PduHeaders.RETRIEVE_TEXT);
- }
-
- /**
- * Set X-Mms-Retrieve-Text value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setRetrieveText(EncodedStringValue value) {
- mPduHeaders.setEncodedStringValue(value, PduHeaders.RETRIEVE_TEXT);
- }
-
- /**
- * Get X-Mms-Transaction-Id.
- *
- * @return the value
- */
- public byte[] getTransactionId() {
- return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
- }
-
- /**
- * Set X-Mms-Transaction-Id.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setTransactionId(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
- }
-
- /*
- * Optional, not supported header fields:
- *
- * public byte[] getApplicId() {return null;}
- * public void setApplicId(byte[] value) {}
- *
- * public byte[] getAuxApplicId() {return null;}
- * public void getAuxApplicId(byte[] value) {}
- *
- * public byte getContentClass() {return 0x00;}
- * public void setApplicId(byte value) {}
- *
- * public byte getDrmContent() {return 0x00;}
- * public void setDrmContent(byte value) {}
- *
- * public byte getDistributionIndicator() {return 0x00;}
- * public void setDistributionIndicator(byte value) {}
- *
- * public PreviouslySentByValue getPreviouslySentBy() {return null;}
- * public void setPreviouslySentBy(PreviouslySentByValue value) {}
- *
- * public PreviouslySentDateValue getPreviouslySentDate() {}
- * public void setPreviouslySentDate(PreviouslySentDateValue value) {}
- *
- * public MmFlagsValue getMmFlags() {return null;}
- * public void setMmFlags(MmFlagsValue value) {}
- *
- * public MmStateValue getMmState() {return null;}
- * public void getMmState(MmStateValue value) {}
- *
- * public byte[] getReplaceId() {return 0x00;}
- * public void setReplaceId(byte[] value) {}
- *
- * public byte[] getReplyApplicId() {return 0x00;}
- * public void setReplyApplicId(byte[] value) {}
- *
- * public byte getReplyCharging() {return 0x00;}
- * public void setReplyCharging(byte value) {}
- *
- * public byte getReplyChargingDeadline() {return 0x00;}
- * public void setReplyChargingDeadline(byte value) {}
- *
- * public byte[] getReplyChargingId() {return 0x00;}
- * public void setReplyChargingId(byte[] value) {}
- *
- * public long getReplyChargingSize() {return 0;}
- * public void setReplyChargingSize(long value) {}
- */
-}
diff --git a/core/java/com/google/android/mms/pdu/SendConf.java b/core/java/com/google/android/mms/pdu/SendConf.java
deleted file mode 100644
index 0568fe7..0000000
--- a/core/java/com/google/android/mms/pdu/SendConf.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import com.google.android.mms.InvalidHeaderValueException;
-
-public class SendConf extends GenericPdu {
- /**
- * Empty constructor.
- * Since the Pdu corresponding to this class is constructed
- * by the Proxy-Relay server, this class is only instantiated
- * by the Pdu Parser.
- *
- * @throws InvalidHeaderValueException if error occurs.
- */
- public SendConf() throws InvalidHeaderValueException {
- super();
- setMessageType(PduHeaders.MESSAGE_TYPE_SEND_CONF);
- }
-
- /**
- * Constructor with given headers.
- *
- * @param headers Headers for this PDU.
- */
- SendConf(PduHeaders headers) {
- super(headers);
- }
-
- /**
- * Get Message-ID value.
- *
- * @return the value
- */
- public byte[] getMessageId() {
- return mPduHeaders.getTextString(PduHeaders.MESSAGE_ID);
- }
-
- /**
- * Set Message-ID value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setMessageId(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.MESSAGE_ID);
- }
-
- /**
- * Get X-Mms-Response-Status.
- *
- * @return the value
- */
- public int getResponseStatus() {
- return mPduHeaders.getOctet(PduHeaders.RESPONSE_STATUS);
- }
-
- /**
- * Set X-Mms-Response-Status.
- *
- * @param value the values
- * @throws InvalidHeaderValueException if the value is invalid.
- */
- public void setResponseStatus(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.RESPONSE_STATUS);
- }
-
- /**
- * Get X-Mms-Transaction-Id field value.
- *
- * @return the X-Mms-Report-Allowed value
- */
- public byte[] getTransactionId() {
- return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
- }
-
- /**
- * Set X-Mms-Transaction-Id field value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setTransactionId(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
- }
-
- /*
- * Optional, not supported header fields:
- *
- * public byte[] getContentLocation() {return null;}
- * public void setContentLocation(byte[] value) {}
- *
- * public EncodedStringValue getResponseText() {return null;}
- * public void setResponseText(EncodedStringValue value) {}
- *
- * public byte getStoreStatus() {return 0x00;}
- * public void setStoreStatus(byte value) {}
- *
- * public byte[] getStoreStatusText() {return null;}
- * public void setStoreStatusText(byte[] value) {}
- */
-}
diff --git a/core/java/com/google/android/mms/pdu/SendReq.java b/core/java/com/google/android/mms/pdu/SendReq.java
deleted file mode 100644
index 9081b0c..0000000
--- a/core/java/com/google/android/mms/pdu/SendReq.java
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright (C) 2007-2008 Esmertec AG.
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.pdu;
-
-import android.util.Log;
-
-import com.google.android.mms.InvalidHeaderValueException;
-
-public class SendReq extends MultimediaMessagePdu {
- private static final String TAG = "SendReq";
-
- public SendReq() {
- super();
-
- try {
- setMessageType(PduHeaders.MESSAGE_TYPE_SEND_REQ);
- setMmsVersion(PduHeaders.CURRENT_MMS_VERSION);
- // FIXME: Content-type must be decided according to whether
- // SMIL part present.
- setContentType("application/vnd.wap.multipart.related".getBytes());
- setFrom(new EncodedStringValue(PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.getBytes()));
- setTransactionId(generateTransactionId());
- } catch (InvalidHeaderValueException e) {
- // Impossible to reach here since all headers we set above are valid.
- Log.e(TAG, "Unexpected InvalidHeaderValueException.", e);
- throw new RuntimeException(e);
- }
- }
-
- private byte[] generateTransactionId() {
- String transactionId = "T" + Long.toHexString(System.currentTimeMillis());
- return transactionId.getBytes();
- }
-
- /**
- * Constructor, used when composing a M-Send.req pdu.
- *
- * @param contentType the content type value
- * @param from the from value
- * @param mmsVersion current viersion of mms
- * @param transactionId the transaction-id value
- * @throws InvalidHeaderValueException if parameters are invalid.
- * NullPointerException if contentType, form or transactionId is null.
- */
- public SendReq(byte[] contentType,
- EncodedStringValue from,
- int mmsVersion,
- byte[] transactionId) throws InvalidHeaderValueException {
- super();
- setMessageType(PduHeaders.MESSAGE_TYPE_SEND_REQ);
- setContentType(contentType);
- setFrom(from);
- setMmsVersion(mmsVersion);
- setTransactionId(transactionId);
- }
-
- /**
- * Constructor with given headers.
- *
- * @param headers Headers for this PDU.
- */
- SendReq(PduHeaders headers) {
- super(headers);
- }
-
- /**
- * Constructor with given headers and body
- *
- * @param headers Headers for this PDU.
- * @param body Body of this PDu.
- */
- SendReq(PduHeaders headers, PduBody body) {
- super(headers, body);
- }
-
- /**
- * Get Bcc value.
- *
- * @return the value
- */
- public EncodedStringValue[] getBcc() {
- return mPduHeaders.getEncodedStringValues(PduHeaders.BCC);
- }
-
- /**
- * Add a "BCC" value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void addBcc(EncodedStringValue value) {
- mPduHeaders.appendEncodedStringValue(value, PduHeaders.BCC);
- }
-
- /**
- * Set "BCC" value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setBcc(EncodedStringValue[] value) {
- mPduHeaders.setEncodedStringValues(value, PduHeaders.BCC);
- }
-
- /**
- * Get CC value.
- *
- * @return the value
- */
- public EncodedStringValue[] getCc() {
- return mPduHeaders.getEncodedStringValues(PduHeaders.CC);
- }
-
- /**
- * Add a "CC" value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void addCc(EncodedStringValue value) {
- mPduHeaders.appendEncodedStringValue(value, PduHeaders.CC);
- }
-
- /**
- * Set "CC" value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setCc(EncodedStringValue[] value) {
- mPduHeaders.setEncodedStringValues(value, PduHeaders.CC);
- }
-
- /**
- * Get Content-type value.
- *
- * @return the value
- */
- public byte[] getContentType() {
- return mPduHeaders.getTextString(PduHeaders.CONTENT_TYPE);
- }
-
- /**
- * Set Content-type value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setContentType(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.CONTENT_TYPE);
- }
-
- /**
- * Get X-Mms-Delivery-Report value.
- *
- * @return the value
- */
- public int getDeliveryReport() {
- return mPduHeaders.getOctet(PduHeaders.DELIVERY_REPORT);
- }
-
- /**
- * Set X-Mms-Delivery-Report value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- */
- public void setDeliveryReport(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.DELIVERY_REPORT);
- }
-
- /**
- * Get X-Mms-Expiry value.
- *
- * Expiry-value = Value-length
- * (Absolute-token Date-value | Relative-token Delta-seconds-value)
- *
- * @return the value
- */
- public long getExpiry() {
- return mPduHeaders.getLongInteger(PduHeaders.EXPIRY);
- }
-
- /**
- * Set X-Mms-Expiry value.
- *
- * @param value the value
- */
- public void setExpiry(long value) {
- mPduHeaders.setLongInteger(value, PduHeaders.EXPIRY);
- }
-
- /**
- * Get From value.
- * From-value = Value-length
- * (Address-present-token Encoded-string-value | Insert-address-token)
- *
- * @return the value
- */
- public EncodedStringValue getFrom() {
- return mPduHeaders.getEncodedStringValue(PduHeaders.FROM);
- }
-
- /**
- * Set From value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setFrom(EncodedStringValue value) {
- mPduHeaders.setEncodedStringValue(value, PduHeaders.FROM);
- }
-
- /**
- * Get X-Mms-Message-Class value.
- * Message-class-value = Class-identifier | Token-text
- * Class-identifier = Personal | Advertisement | Informational | Auto
- *
- * @return the value
- */
- public byte[] getMessageClass() {
- return mPduHeaders.getTextString(PduHeaders.MESSAGE_CLASS);
- }
-
- /**
- * Set X-Mms-Message-Class value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setMessageClass(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.MESSAGE_CLASS);
- }
-
- /**
- * Get X-Mms-Read-Report value.
- *
- * @return the value
- */
- public int getReadReport() {
- return mPduHeaders.getOctet(PduHeaders.READ_REPORT);
- }
-
- /**
- * Set X-Mms-Read-Report value.
- *
- * @param value the value
- * @throws InvalidHeaderValueException if the value is invalid.
- */
- public void setReadReport(int value) throws InvalidHeaderValueException {
- mPduHeaders.setOctet(value, PduHeaders.READ_REPORT);
- }
-
- /**
- * Set "To" value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setTo(EncodedStringValue[] value) {
- mPduHeaders.setEncodedStringValues(value, PduHeaders.TO);
- }
-
- /**
- * Get X-Mms-Transaction-Id field value.
- *
- * @return the X-Mms-Report-Allowed value
- */
- public byte[] getTransactionId() {
- return mPduHeaders.getTextString(PduHeaders.TRANSACTION_ID);
- }
-
- /**
- * Set X-Mms-Transaction-Id field value.
- *
- * @param value the value
- * @throws NullPointerException if the value is null.
- */
- public void setTransactionId(byte[] value) {
- mPduHeaders.setTextString(value, PduHeaders.TRANSACTION_ID);
- }
-
- /*
- * Optional, not supported header fields:
- *
- * public byte getAdaptationAllowed() {return 0};
- * public void setAdaptationAllowed(btye value) {};
- *
- * public byte[] getApplicId() {return null;}
- * public void setApplicId(byte[] value) {}
- *
- * public byte[] getAuxApplicId() {return null;}
- * public void getAuxApplicId(byte[] value) {}
- *
- * public byte getContentClass() {return 0x00;}
- * public void setApplicId(byte value) {}
- *
- * public long getDeliveryTime() {return 0};
- * public void setDeliveryTime(long value) {};
- *
- * public byte getDrmContent() {return 0x00;}
- * public void setDrmContent(byte value) {}
- *
- * public MmFlagsValue getMmFlags() {return null;}
- * public void setMmFlags(MmFlagsValue value) {}
- *
- * public MmStateValue getMmState() {return null;}
- * public void getMmState(MmStateValue value) {}
- *
- * public byte[] getReplyApplicId() {return 0x00;}
- * public void setReplyApplicId(byte[] value) {}
- *
- * public byte getReplyCharging() {return 0x00;}
- * public void setReplyCharging(byte value) {}
- *
- * public byte getReplyChargingDeadline() {return 0x00;}
- * public void setReplyChargingDeadline(byte value) {}
- *
- * public byte[] getReplyChargingId() {return 0x00;}
- * public void setReplyChargingId(byte[] value) {}
- *
- * public long getReplyChargingSize() {return 0;}
- * public void setReplyChargingSize(long value) {}
- *
- * public byte[] getReplyApplicId() {return 0x00;}
- * public void setReplyApplicId(byte[] value) {}
- *
- * public byte getStore() {return 0x00;}
- * public void setStore(byte value) {}
- */
-}
diff --git a/core/java/com/google/android/mms/pdu/package.html b/core/java/com/google/android/mms/pdu/package.html
deleted file mode 100755
index c9f96a6..0000000
--- a/core/java/com/google/android/mms/pdu/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>
diff --git a/core/java/com/google/android/mms/util/AbstractCache.java b/core/java/com/google/android/mms/util/AbstractCache.java
deleted file mode 100644
index 670439c..0000000
--- a/core/java/com/google/android/mms/util/AbstractCache.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2008 Esmertec AG.
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.util;
-
-import android.util.Config;
-import android.util.Log;
-
-import java.util.HashMap;
-
-public abstract class AbstractCache<K, V> {
- private static final String TAG = "AbstractCache";
- private static final boolean DEBUG = false;
- private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
-
- private static final int MAX_CACHED_ITEMS = 500;
-
- private final HashMap<K, CacheEntry<V>> mCacheMap;
-
- protected AbstractCache() {
- mCacheMap = new HashMap<K, CacheEntry<V>>();
- }
-
- public boolean put(K key, V value) {
- if (LOCAL_LOGV) {
- Log.v(TAG, "Trying to put " + key + " into cache.");
- }
-
- if (mCacheMap.size() >= MAX_CACHED_ITEMS) {
- // TODO Should remove the oldest or least hit cached entry
- // and then cache the new one.
- if (LOCAL_LOGV) {
- Log.v(TAG, "Failed! size limitation reached.");
- }
- return false;
- }
-
- if (key != null) {
- CacheEntry<V> cacheEntry = new CacheEntry<V>();
- cacheEntry.value = value;
- mCacheMap.put(key, cacheEntry);
-
- if (LOCAL_LOGV) {
- Log.v(TAG, key + " cached, " + mCacheMap.size() + " items total.");
- }
- return true;
- }
- return false;
- }
-
- public V get(K key) {
- if (LOCAL_LOGV) {
- Log.v(TAG, "Trying to get " + key + " from cache.");
- }
-
- if (key != null) {
- CacheEntry<V> cacheEntry = mCacheMap.get(key);
- if (cacheEntry != null) {
- cacheEntry.hit++;
- if (LOCAL_LOGV) {
- Log.v(TAG, key + " hit " + cacheEntry.hit + " times.");
- }
- return cacheEntry.value;
- }
- }
- return null;
- }
-
- public V purge(K key) {
- if (LOCAL_LOGV) {
- Log.v(TAG, "Trying to purge " + key);
- }
-
- CacheEntry<V> v = mCacheMap.remove(key);
-
- if (LOCAL_LOGV) {
- Log.v(TAG, mCacheMap.size() + " items cached.");
- }
-
- return v != null ? v.value : null;
- }
-
- public void purgeAll() {
- if (LOCAL_LOGV) {
- Log.v(TAG, "Purging cache, " + mCacheMap.size()
- + " items dropped.");
- }
- mCacheMap.clear();
- }
-
- public int size() {
- return mCacheMap.size();
- }
-
- private static class CacheEntry<V> {
- int hit;
- V value;
- }
-}
diff --git a/core/java/com/google/android/mms/util/PduCache.java b/core/java/com/google/android/mms/util/PduCache.java
deleted file mode 100644
index 7c3fad7..0000000
--- a/core/java/com/google/android/mms/util/PduCache.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (C) 2008 Esmertec AG.
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.util;
-
-import android.content.ContentUris;
-import android.content.UriMatcher;
-import android.net.Uri;
-import android.provider.Telephony.Mms;
-import android.util.Config;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.HashSet;
-
-public final class PduCache extends AbstractCache<Uri, PduCacheEntry> {
- private static final String TAG = "PduCache";
- private static final boolean DEBUG = false;
- private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
-
- private static final int MMS_ALL = 0;
- private static final int MMS_ALL_ID = 1;
- private static final int MMS_INBOX = 2;
- private static final int MMS_INBOX_ID = 3;
- private static final int MMS_SENT = 4;
- private static final int MMS_SENT_ID = 5;
- private static final int MMS_DRAFTS = 6;
- private static final int MMS_DRAFTS_ID = 7;
- private static final int MMS_OUTBOX = 8;
- private static final int MMS_OUTBOX_ID = 9;
- private static final int MMS_CONVERSATION = 10;
- private static final int MMS_CONVERSATION_ID = 11;
-
- private static final UriMatcher URI_MATCHER;
- private static final HashMap<Integer, Integer> MATCH_TO_MSGBOX_ID_MAP;
-
- private static PduCache sInstance;
-
- static {
- URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
- URI_MATCHER.addURI("mms", null, MMS_ALL);
- URI_MATCHER.addURI("mms", "#", MMS_ALL_ID);
- URI_MATCHER.addURI("mms", "inbox", MMS_INBOX);
- URI_MATCHER.addURI("mms", "inbox/#", MMS_INBOX_ID);
- URI_MATCHER.addURI("mms", "sent", MMS_SENT);
- URI_MATCHER.addURI("mms", "sent/#", MMS_SENT_ID);
- URI_MATCHER.addURI("mms", "drafts", MMS_DRAFTS);
- URI_MATCHER.addURI("mms", "drafts/#", MMS_DRAFTS_ID);
- URI_MATCHER.addURI("mms", "outbox", MMS_OUTBOX);
- URI_MATCHER.addURI("mms", "outbox/#", MMS_OUTBOX_ID);
- URI_MATCHER.addURI("mms-sms", "conversations", MMS_CONVERSATION);
- URI_MATCHER.addURI("mms-sms", "conversations/#", MMS_CONVERSATION_ID);
-
- MATCH_TO_MSGBOX_ID_MAP = new HashMap<Integer, Integer>();
- MATCH_TO_MSGBOX_ID_MAP.put(MMS_INBOX, Mms.MESSAGE_BOX_INBOX);
- MATCH_TO_MSGBOX_ID_MAP.put(MMS_SENT, Mms.MESSAGE_BOX_SENT);
- MATCH_TO_MSGBOX_ID_MAP.put(MMS_DRAFTS, Mms.MESSAGE_BOX_DRAFTS);
- MATCH_TO_MSGBOX_ID_MAP.put(MMS_OUTBOX, Mms.MESSAGE_BOX_OUTBOX);
- }
-
- private final HashMap<Integer, HashSet<Uri>> mMessageBoxes;
- private final HashMap<Long, HashSet<Uri>> mThreads;
-
- private PduCache() {
- mMessageBoxes = new HashMap<Integer, HashSet<Uri>>();
- mThreads = new HashMap<Long, HashSet<Uri>>();
- }
-
- synchronized public static final PduCache getInstance() {
- if (sInstance == null) {
- if (LOCAL_LOGV) {
- Log.v(TAG, "Constructing new PduCache instance.");
- }
- sInstance = new PduCache();
- }
- return sInstance;
- }
-
- @Override
- synchronized public boolean put(Uri uri, PduCacheEntry entry) {
- int msgBoxId = entry.getMessageBox();
- HashSet<Uri> msgBox = mMessageBoxes.get(msgBoxId);
- if (msgBox == null) {
- msgBox = new HashSet<Uri>();
- mMessageBoxes.put(msgBoxId, msgBox);
- }
-
- long threadId = entry.getThreadId();
- HashSet<Uri> thread = mThreads.get(threadId);
- if (thread == null) {
- thread = new HashSet<Uri>();
- mThreads.put(threadId, thread);
- }
-
- Uri finalKey = normalizeKey(uri);
- boolean result = super.put(finalKey, entry);
- if (result) {
- msgBox.add(finalKey);
- thread.add(finalKey);
- }
- return result;
- }
-
- @Override
- synchronized public PduCacheEntry purge(Uri uri) {
- int match = URI_MATCHER.match(uri);
- switch (match) {
- case MMS_ALL_ID:
- return purgeSingleEntry(uri);
- case MMS_INBOX_ID:
- case MMS_SENT_ID:
- case MMS_DRAFTS_ID:
- case MMS_OUTBOX_ID:
- String msgId = uri.getLastPathSegment();
- return purgeSingleEntry(Uri.withAppendedPath(Mms.CONTENT_URI, msgId));
- // Implicit batch of purge, return null.
- case MMS_ALL:
- case MMS_CONVERSATION:
- purgeAll();
- return null;
- case MMS_INBOX:
- case MMS_SENT:
- case MMS_DRAFTS:
- case MMS_OUTBOX:
- purgeByMessageBox(MATCH_TO_MSGBOX_ID_MAP.get(match));
- return null;
- case MMS_CONVERSATION_ID:
- purgeByThreadId(ContentUris.parseId(uri));
- return null;
- default:
- return null;
- }
- }
-
- private PduCacheEntry purgeSingleEntry(Uri key) {
- PduCacheEntry entry = super.purge(key);
- if (entry != null) {
- removeFromThreads(key, entry);
- removeFromMessageBoxes(key, entry);
- return entry;
- }
- return null;
- }
-
- @Override
- synchronized public void purgeAll() {
- super.purgeAll();
-
- mMessageBoxes.clear();
- mThreads.clear();
- }
-
- /**
- * @param uri The Uri to be normalized.
- * @return Uri The normalized key of cached entry.
- */
- private Uri normalizeKey(Uri uri) {
- int match = URI_MATCHER.match(uri);
- Uri normalizedKey = null;
-
- switch (match) {
- case MMS_ALL_ID:
- normalizedKey = uri;
- break;
- case MMS_INBOX_ID:
- case MMS_SENT_ID:
- case MMS_DRAFTS_ID:
- case MMS_OUTBOX_ID:
- String msgId = uri.getLastPathSegment();
- normalizedKey = Uri.withAppendedPath(Mms.CONTENT_URI, msgId);
- break;
- default:
- return null;
- }
-
- if (LOCAL_LOGV) {
- Log.v(TAG, uri + " -> " + normalizedKey);
- }
- return normalizedKey;
- }
-
- private void purgeByMessageBox(Integer msgBoxId) {
- if (LOCAL_LOGV) {
- Log.v(TAG, "Purge cache in message box: " + msgBoxId);
- }
-
- if (msgBoxId != null) {
- HashSet<Uri> msgBox = mMessageBoxes.remove(msgBoxId);
- if (msgBox != null) {
- for (Uri key : msgBox) {
- PduCacheEntry entry = super.purge(key);
- if (entry != null) {
- removeFromThreads(key, entry);
- }
- }
- }
- }
- }
-
- private void removeFromThreads(Uri key, PduCacheEntry entry) {
- HashSet<Uri> thread = mThreads.get(entry.getThreadId());
- if (thread != null) {
- thread.remove(key);
- }
- }
-
- private void purgeByThreadId(long threadId) {
- if (LOCAL_LOGV) {
- Log.v(TAG, "Purge cache in thread: " + threadId);
- }
-
- HashSet<Uri> thread = mThreads.remove(threadId);
- if (thread != null) {
- for (Uri key : thread) {
- PduCacheEntry entry = super.purge(key);
- if (entry != null) {
- removeFromMessageBoxes(key, entry);
- }
- }
- }
- }
-
- private void removeFromMessageBoxes(Uri key, PduCacheEntry entry) {
- HashSet<Uri> msgBox = mThreads.get(entry.getMessageBox());
- if (msgBox != null) {
- msgBox.remove(key);
- }
- }
-}
diff --git a/core/java/com/google/android/mms/util/PduCacheEntry.java b/core/java/com/google/android/mms/util/PduCacheEntry.java
deleted file mode 100644
index 8b41386..0000000
--- a/core/java/com/google/android/mms/util/PduCacheEntry.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2008 Esmertec AG.
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.util;
-
-import com.google.android.mms.pdu.GenericPdu;
-
-public final class PduCacheEntry {
- private final GenericPdu mPdu;
- private final int mMessageBox;
- private final long mThreadId;
-
- public PduCacheEntry(GenericPdu pdu, int msgBox, long threadId) {
- mPdu = pdu;
- mMessageBox = msgBox;
- mThreadId = threadId;
- }
-
- public GenericPdu getPdu() {
- return mPdu;
- }
-
- public int getMessageBox() {
- return mMessageBox;
- }
-
- public long getThreadId() {
- return mThreadId;
- }
-}
diff --git a/core/java/com/google/android/mms/util/SqliteWrapper.java b/core/java/com/google/android/mms/util/SqliteWrapper.java
deleted file mode 100644
index bcdac22..0000000
--- a/core/java/com/google/android/mms/util/SqliteWrapper.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2008 Esmertec AG.
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.mms.util;
-
-import android.app.ActivityManager;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteException;
-import android.net.Uri;
-import android.util.Log;
-import android.widget.Toast;
-
-public final class SqliteWrapper {
- private static final String TAG = "SqliteWrapper";
- private static final String SQLITE_EXCEPTION_DETAIL_MESSAGE
- = "unable to open database file";
-
- private SqliteWrapper() {
- // Forbidden being instantiated.
- }
-
- // FIXME: It looks like outInfo.lowMemory does not work well as we expected.
- // after run command: adb shell fillup -p 100, outInfo.lowMemory is still false.
- private static boolean isLowMemory(Context context) {
- if (null == context) {
- return false;
- }
-
- ActivityManager am = (ActivityManager)
- context.getSystemService(Context.ACTIVITY_SERVICE);
- ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo();
- am.getMemoryInfo(outInfo);
-
- return outInfo.lowMemory;
- }
-
- // FIXME: need to optimize this method.
- private static boolean isLowMemory(SQLiteException e) {
- return e.getMessage().equals(SQLITE_EXCEPTION_DETAIL_MESSAGE);
- }
-
- public static void checkSQLiteException(Context context, SQLiteException e) {
- if (isLowMemory(e)) {
- Toast.makeText(context, com.android.internal.R.string.low_memory,
- Toast.LENGTH_SHORT).show();
- } else {
- throw e;
- }
- }
-
- public static Cursor query(Context context, ContentResolver resolver, Uri uri,
- String[] projection, String selection, String[] selectionArgs, String sortOrder) {
- try {
- return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
- } catch (SQLiteException e) {
- Log.e(TAG, "Catch a SQLiteException when query: ", e);
- checkSQLiteException(context, e);
- return null;
- }
- }
-
- public static boolean requery(Context context, Cursor cursor) {
- try {
- return cursor.requery();
- } catch (SQLiteException e) {
- Log.e(TAG, "Catch a SQLiteException when requery: ", e);
- checkSQLiteException(context, e);
- return false;
- }
- }
- public static int update(Context context, ContentResolver resolver, Uri uri,
- ContentValues values, String where, String[] selectionArgs) {
- try {
- return resolver.update(uri, values, where, selectionArgs);
- } catch (SQLiteException e) {
- Log.e(TAG, "Catch a SQLiteException when update: ", e);
- checkSQLiteException(context, e);
- return -1;
- }
- }
-
- public static int delete(Context context, ContentResolver resolver, Uri uri,
- String where, String[] selectionArgs) {
- try {
- return resolver.delete(uri, where, selectionArgs);
- } catch (SQLiteException e) {
- Log.e(TAG, "Catch a SQLiteException when delete: ", e);
- checkSQLiteException(context, e);
- return -1;
- }
- }
-
- public static Uri insert(Context context, ContentResolver resolver,
- Uri uri, ContentValues values) {
- try {
- return resolver.insert(uri, values);
- } catch (SQLiteException e) {
- Log.e(TAG, "Catch a SQLiteException when insert: ", e);
- checkSQLiteException(context, e);
- return null;
- }
- }
-}
diff --git a/core/java/com/google/android/mms/util/package.html b/core/java/com/google/android/mms/util/package.html
deleted file mode 100755
index c9f96a6..0000000
--- a/core/java/com/google/android/mms/util/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>
diff --git a/core/java/com/google/android/net/GoogleHttpClient.java b/core/java/com/google/android/net/GoogleHttpClient.java
deleted file mode 100644
index 2fcb0c3..0000000
--- a/core/java/com/google/android/net/GoogleHttpClient.java
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.net;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.net.http.AndroidHttpClient;
-import android.os.Build;
-import android.os.NetStat;
-import android.os.SystemClock;
-import android.provider.Checkin;
-import android.util.Config;
-import android.util.Log;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpEntityEnclosingRequest;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.ProtocolException;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.ResponseHandler;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.impl.client.EntityEnclosingRequestWrapper;
-import org.apache.http.impl.client.RequestWrapper;
-import org.apache.http.params.HttpParams;
-import org.apache.http.protocol.HttpContext;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-
-/**
- * {@link AndroidHttpClient} wrapper that uses {@link UrlRules} to rewrite URLs
- * and otherwise tweak HTTP requests.
- */
-public class GoogleHttpClient implements HttpClient {
-
- private static final String TAG = "GoogleHttpClient";
-
- /** Exception thrown when a request is blocked by the URL rules. */
- public static class BlockedRequestException extends IOException {
- private final UrlRules.Rule mRule;
- BlockedRequestException(UrlRules.Rule rule) {
- super("Blocked by rule: " + rule.mName);
- mRule = rule;
- }
- }
-
- private final AndroidHttpClient mClient;
- private final ContentResolver mResolver;
- private final String mUserAgent;
-
- /**
- * Create an HTTP client. Normally one client is shared throughout an app.
- * @param resolver to use for accessing URL rewriting rules.
- * @param userAgent to report in your HTTP requests.
- * @deprecated Use {@link #GoogleHttpClient(android.content.ContentResolver, String, boolean)}
- */
- public GoogleHttpClient(ContentResolver resolver, String userAgent) {
- mClient = AndroidHttpClient.newInstance(userAgent);
- mResolver = resolver;
- mUserAgent = userAgent;
- }
-
- /**
- * Create an HTTP client. Normaly this client is shared throughout an app.
- * The HTTP client will construct its User-Agent as follows:
- *
- * <appAndVersion> (<build device> <build id>)
- * or
- * <appAndVersion> (<build device> <build id>); gzip
- * (if gzip capable)
- *
- * @param resolver to use for acccessing URL rewriting rules.
- * @param appAndVersion Base app and version to use in the User-Agent.
- * e.g., "MyApp/1.0"
- * @param gzipCapable Whether or not this client is able to consume gzip'd
- * responses. Only used to modify the User-Agent, not other request
- * headers. Needed because Google servers require gzip in the User-Agent
- * in order to return gzip'd content.
- */
- public GoogleHttpClient(ContentResolver resolver, String appAndVersion,
- boolean gzipCapable) {
- String userAgent = appAndVersion
- + " (" + Build.DEVICE + " " + Build.ID + ")";
- if (gzipCapable) {
- userAgent = userAgent + "; gzip";
- }
- mClient = AndroidHttpClient.newInstance(userAgent);
- mResolver = resolver;
- mUserAgent = userAgent;
- }
-
- /**
- * Release resources associated with this client. You must call this,
- * or significant resources (sockets and memory) may be leaked.
- */
- public void close() {
- mClient.close();
- }
-
- /** Execute a request without applying and rewrite rules. */
- public HttpResponse executeWithoutRewriting(
- HttpUriRequest request, HttpContext context)
- throws IOException {
- String code = "Error";
- long start = SystemClock.elapsedRealtime();
- try {
- HttpResponse response;
- // TODO: if we're logging network stats, and if the apache library is configured
- // to follow redirects, count each redirect as an additional round trip.
-
- // see if we're logging network stats.
- boolean logNetworkStats = NetworkStatsEntity.shouldLogNetworkStats();
-
- if (logNetworkStats) {
- int uid = android.os.Process.myUid();
- long startTx = NetStat.getUidTxBytes(uid);
- long startRx = NetStat.getUidRxBytes(uid);
-
- response = mClient.execute(request, context);
- code = Integer.toString(response.getStatusLine().getStatusCode());
-
- HttpEntity origEntity = response == null ? null : response.getEntity();
- if (origEntity != null) {
- // yeah, we compute the same thing below. we do need to compute this here
- // so we can wrap the HttpEntity in the response.
- long now = SystemClock.elapsedRealtime();
- long elapsed = now - start;
- NetworkStatsEntity entity = new NetworkStatsEntity(origEntity,
- mUserAgent, uid, startTx, startRx,
- elapsed /* response latency */, now /* processing start time */);
- response.setEntity(entity);
- }
- } else {
- response = mClient.execute(request, context);
- code = Integer.toString(response.getStatusLine().getStatusCode());
- }
-
- return response;
- } catch (IOException e) {
- code = "IOException";
- throw e;
- } finally {
- // Record some statistics to the checkin service about the outcome.
- // Note that this is only describing execute(), not body download.
- try {
- long elapsed = SystemClock.elapsedRealtime() - start;
- ContentValues values = new ContentValues();
- values.put(Checkin.Stats.TAG,
- Checkin.Stats.Tag.HTTP_STATUS + ":" +
- mUserAgent + ":" + code);
- values.put(Checkin.Stats.COUNT, 1);
- values.put(Checkin.Stats.SUM, elapsed / 1000.0);
- mResolver.insert(Checkin.Stats.CONTENT_URI, values);
- } catch (Exception e) {
- Log.e(TAG, "Error recording stats", e);
- }
- }
- }
-
- public HttpResponse execute(HttpUriRequest request, HttpContext context)
- throws IOException {
- // Rewrite the supplied URL...
- URI uri = request.getURI();
- String original = uri.toString();
- UrlRules rules = UrlRules.getRules(mResolver);
- UrlRules.Rule rule = rules.matchRule(original);
- String rewritten = rule.apply(original);
-
- if (rewritten == null) {
- Log.w(TAG, "Blocked by " + rule.mName + ": " + original);
- throw new BlockedRequestException(rule);
- } else if (rewritten == original) {
- return executeWithoutRewriting(request, context); // Pass through
- }
-
- try {
- uri = new URI(rewritten);
- } catch (URISyntaxException e) {
- throw new RuntimeException("Bad URL from rule: " + rule.mName, e);
- }
-
- // Wrap request so we can replace the URI.
- RequestWrapper wrapper = wrapRequest(request);
- wrapper.setURI(uri);
- request = wrapper;
-
- if (Config.LOGV) {
- Log.v(TAG, "Rule " + rule.mName + ": " + original + " -> " + rewritten);
- }
- return executeWithoutRewriting(request, context);
- }
-
- /**
- * Wraps the request making it mutable.
- */
- private static RequestWrapper wrapRequest(HttpUriRequest request)
- throws IOException {
- try {
- // We have to wrap it with the right type. Some code performs
- // instanceof checks.
- RequestWrapper wrapped;
- if (request instanceof HttpEntityEnclosingRequest) {
- wrapped = new EntityEnclosingRequestWrapper(
- (HttpEntityEnclosingRequest) request);
- } else {
- wrapped = new RequestWrapper(request);
- }
-
- // Copy the headers from the original request into the wrapper.
- wrapped.resetHeaders();
-
- return wrapped;
- } catch (ProtocolException e) {
- throw new ClientProtocolException(e);
- }
- }
-
- /**
- * Mark a user agent as one Google will trust to handle gzipped content.
- * {@link AndroidHttpClient#modifyRequestToAcceptGzipResponse} is (also)
- * necessary but not sufficient -- many browsers claim to accept gzip but
- * have broken handling, so Google checks the user agent as well.
- *
- * @param originalUserAgent to modify (however you identify yourself)
- * @return user agent with a "yes, I really can handle gzip" token added.
- * @deprecated Use {@link #GoogleHttpClient(android.content.ContentResolver, String, boolean)}
- */
- public static String getGzipCapableUserAgent(String originalUserAgent) {
- return originalUserAgent + "; gzip";
- }
-
- // HttpClient wrapper methods.
-
- public HttpParams getParams() {
- return mClient.getParams();
- }
-
- public ClientConnectionManager getConnectionManager() {
- return mClient.getConnectionManager();
- }
-
- public HttpResponse execute(HttpUriRequest request) throws IOException {
- return execute(request, (HttpContext) null);
- }
-
- public HttpResponse execute(HttpHost target, HttpRequest request)
- throws IOException {
- return mClient.execute(target, request);
- }
-
- public HttpResponse execute(HttpHost target, HttpRequest request,
- HttpContext context) throws IOException {
- return mClient.execute(target, request, context);
- }
-
- public <T> T execute(HttpUriRequest request,
- ResponseHandler<? extends T> responseHandler)
- throws IOException, ClientProtocolException {
- return mClient.execute(request, responseHandler);
- }
-
- public <T> T execute(HttpUriRequest request,
- ResponseHandler<? extends T> responseHandler, HttpContext context)
- throws IOException, ClientProtocolException {
- return mClient.execute(request, responseHandler, context);
- }
-
- public <T> T execute(HttpHost target, HttpRequest request,
- ResponseHandler<? extends T> responseHandler) throws IOException,
- ClientProtocolException {
- return mClient.execute(target, request, responseHandler);
- }
-
- public <T> T execute(HttpHost target, HttpRequest request,
- ResponseHandler<? extends T> responseHandler, HttpContext context)
- throws IOException, ClientProtocolException {
- return mClient.execute(target, request, responseHandler, context);
- }
-
- /**
- * Enables cURL request logging for this client.
- *
- * @param name to log messages with
- * @param level at which to log messages (see {@link android.util.Log})
- */
- public void enableCurlLogging(String name, int level) {
- mClient.enableCurlLogging(name, level);
- }
-
- /**
- * Disables cURL logging for this client.
- */
- public void disableCurlLogging() {
- mClient.disableCurlLogging();
- }
-}
diff --git a/core/java/com/google/android/net/NetworkStatsEntity.java b/core/java/com/google/android/net/NetworkStatsEntity.java
deleted file mode 100644
index f5d2349..0000000
--- a/core/java/com/google/android/net/NetworkStatsEntity.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.net;
-
-import android.os.NetStat;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.util.EventLog;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.entity.HttpEntityWrapper;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-
-public class NetworkStatsEntity extends HttpEntityWrapper {
-
- private static final int HTTP_STATS_EVENT = 52001;
-
- private class NetworkStatsInputStream extends FilterInputStream {
-
- public NetworkStatsInputStream(InputStream wrapped) {
- super(wrapped);
- }
-
- @Override
- public void close() throws IOException {
- try {
- super.close();
- } finally {
- long processingTime = SystemClock.elapsedRealtime() - mProcessingStartTime;
- long tx = NetStat.getUidTxBytes(mUid);
- long rx = NetStat.getUidRxBytes(mUid);
-
- EventLog.writeEvent(HTTP_STATS_EVENT, mUa, mResponseLatency, processingTime,
- tx - mStartTx, rx - mStartRx);
- }
- }
- }
-
- private final String mUa;
- private final int mUid;
- private final long mStartTx;
- private final long mStartRx;
- private final long mResponseLatency;
- private final long mProcessingStartTime;
-
- public NetworkStatsEntity(HttpEntity orig, String ua,
- int uid, long startTx, long startRx, long responseLatency,
- long processingStartTime) {
- super(orig);
- this.mUa = ua;
- this.mUid = uid;
- this.mStartTx = startTx;
- this.mStartRx = startRx;
- this.mResponseLatency = responseLatency;
- this.mProcessingStartTime = processingStartTime;
- }
-
- public static boolean shouldLogNetworkStats() {
- return "1".equals(SystemProperties.get("googlehttpclient.logstats"));
- }
-
- @Override
- public InputStream getContent() throws IOException {
- InputStream orig = super.getContent();
- return new NetworkStatsInputStream(orig);
- }
-}
diff --git a/core/java/com/google/android/net/ParentalControl.java b/core/java/com/google/android/net/ParentalControl.java
deleted file mode 100644
index 71a3958..0000000
--- a/core/java/com/google/android/net/ParentalControl.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.net;
-
-import android.os.ICheckinService;
-import android.os.IParentalControlCallback;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.Log;
-
-public class ParentalControl {
- /**
- * Strings to identify your app. To enable parental control checking for
- * new apps, please add it here, and configure GServices accordingly.
- */
- public static final String VENDING = "vending";
- public static final String YOUTUBE = "youtube";
-
- /**
- * This interface is supplied to getParentalControlState and is callback upon with
- * the state of parental control.
- */
- public interface Callback {
- /**
- * This method will be called when the state of parental control is known. If state is
- * null, then the state of parental control is unknown.
- * @param state The state of parental control.
- */
- void onResult(ParentalControlState state);
- }
-
- private static class RemoteCallback extends IParentalControlCallback.Stub {
- private Callback mCallback;
-
- public RemoteCallback(Callback callback) {
- mCallback = callback;
- }
-
- public void onResult(ParentalControlState state) {
- if (mCallback != null) {
- mCallback.onResult(state);
- }
- }
- };
-
- public static void getParentalControlState(Callback callback,
- String requestingApp) {
- ICheckinService service =
- ICheckinService.Stub.asInterface(ServiceManager.getService("checkin"));
-
- RemoteCallback remoteCallback = new RemoteCallback(callback);
- try {
- service.getParentalControlState(remoteCallback, requestingApp);
- } catch (RemoteException e) {
- // This should never happen.
- Log.e("ParentalControl", "Failed to talk to the checkin service.");
- }
- }
-}
diff --git a/core/java/com/google/android/net/ParentalControlState.aidl b/core/java/com/google/android/net/ParentalControlState.aidl
deleted file mode 100644
index ed1326a..0000000
--- a/core/java/com/google/android/net/ParentalControlState.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Copyright (c) 2008, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.net;
-parcelable ParentalControlState;
diff --git a/core/java/com/google/android/net/ParentalControlState.java b/core/java/com/google/android/net/ParentalControlState.java
deleted file mode 100644
index 162a1f6..0000000
--- a/core/java/com/google/android/net/ParentalControlState.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.net;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-public class ParentalControlState implements Parcelable {
- public boolean isEnabled;
- public String redirectUrl;
-
- /**
- * Used to read a ParentalControlStatus from a Parcel.
- */
- public static final Parcelable.Creator<ParentalControlState> CREATOR =
- new Parcelable.Creator<ParentalControlState>() {
- public ParentalControlState createFromParcel(Parcel source) {
- ParentalControlState status = new ParentalControlState();
- status.isEnabled = (source.readInt() == 1);
- status.redirectUrl = source.readString();
- return status;
- }
-
- public ParentalControlState[] newArray(int size) {
- return new ParentalControlState[size];
- }
- };
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(isEnabled ? 1 : 0);
- dest.writeString(redirectUrl);
- }
-
- @Override
- public String toString() {
- return isEnabled + ", " + redirectUrl;
- }
-};
diff --git a/core/java/com/google/android/net/UrlRules.java b/core/java/com/google/android/net/UrlRules.java
deleted file mode 100644
index c269d1b..0000000
--- a/core/java/com/google/android/net/UrlRules.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.net;
-
-import android.content.ContentResolver;
-import android.database.Cursor;
-import android.provider.Checkin;
-import android.provider.Settings;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * A set of rules rewriting and blocking URLs. Used to offer a point of
- * control for redirecting HTTP requests, often to the Android proxy server.
- *
- * <p>Each rule has the following format:
- *
- * <pre><em>url-prefix</em> [REWRITE <em>new-prefix</em>] [BLOCK]</pre>
- *
- * <p>Any URL which starts with <em>url-prefix</em> will trigger the rule.
- * If BLOCK is specified, requests to that URL will be blocked and fail.
- * If REWRITE is specified, the matching prefix will be removed and replaced
- * with <em>new-prefix</em>. (If both are specified, BLOCK wins.) Case is
- * insensitive for the REWRITE and BLOCK keywords, but sensitive for URLs.
- *
- * <p>In Gservices, the value of any key that starts with "url:" will be
- * interpreted as a rule. The full name of the key is unimportant (but can
- * be used to document the intent of the rule, and must be unique).
- * Example gservices keys:
- *
- * <pre>
- * url:use_proxy_for_calendar = "http://www.google.com/calendar/ REWRITE http://android.clients.google.com/proxy/calendar/"
- * url:stop_crash_reports = "http://android.clients.google.com/crash/ BLOCK"
- * url:use_ssl_for_contacts = "http://www.google.com/m8/ REWRITE https://www.google.com/m8/"
- * </pre>
- */
-public class UrlRules {
- /** Thrown when the rewrite rules can't be parsed. */
- public static class RuleFormatException extends Exception {
- public RuleFormatException(String msg) { super(msg); }
- }
-
- /** A single rule specifying actions for URLs matching a certain prefix. */
- public static class Rule implements Comparable {
- /** Name assigned to the rule (for logging and debugging). */
- public final String mName;
-
- /** Prefix required to match this rule. */
- public final String mPrefix;
-
- /** Text to replace mPrefix with (null to leave alone). */
- public final String mRewrite;
-
- /** True if matching URLs should be blocked. */
- public final boolean mBlock;
-
- /** Default rule that does nothing. */
- public static final Rule DEFAULT = new Rule();
-
- /** Parse a rewrite rule as given in a Gservices value. */
- public Rule(String name, String rule) throws RuleFormatException {
- mName = name;
- String[] words = PATTERN_SPACE_PLUS.split(rule);
- if (words.length == 0) throw new RuleFormatException("Empty rule");
-
- mPrefix = words[0];
- String rewrite = null;
- boolean block = false;
- for (int pos = 1; pos < words.length; ) {
- String word = words[pos].toLowerCase();
- if (word.equals("rewrite") && pos + 1 < words.length) {
- rewrite = words[pos + 1];
- pos += 2;
- } else if (word.equals("block")) {
- block = true;
- pos += 1;
- } else {
- throw new RuleFormatException("Illegal rule: " + rule);
- }
- // TODO: Parse timeout specifications, etc.
- }
-
- mRewrite = rewrite;
- mBlock = block;
- }
-
- /** Create the default Rule. */
- private Rule() {
- mName = "DEFAULT";
- mPrefix = "";
- mRewrite = null;
- mBlock = false;
- }
-
- /**
- * Apply the rule to a particular URL (assumed to match the rule).
- * @param url to rewrite or modify.
- * @return modified URL, or null if the URL is blocked.
- */
- public String apply(String url) {
- if (mBlock) {
- return null;
- } else if (mRewrite != null) {
- return mRewrite + url.substring(mPrefix.length());
- } else {
- return url;
- }
- }
-
- /** More generic rules are greater than more specific rules. */
- public int compareTo(Object o) {
- return ((Rule) o).mPrefix.compareTo(mPrefix);
- }
- }
-
- /** Cached rule set from Gservices. */
- private static UrlRules sCachedRules = new UrlRules(new Rule[] {});
-
- private static final Pattern PATTERN_SPACE_PLUS = Pattern.compile(" +");
- private static final Pattern RULE_PATTERN = Pattern.compile("\\W");
-
- /** Gservices digest when sCachedRules was cached. */
- private static String sCachedDigest = null;
-
- /** Currently active set of Rules. */
- private final Rule[] mRules;
-
- /** Regular expression with one capturing group for each Rule. */
- private final Pattern mPattern;
-
- /**
- * Create a rewriter from an array of Rules. Normally used only for
- * testing. Instead, use {@link #getRules} to get rules from Gservices.
- * @param rules to use.
- */
- public UrlRules(Rule[] rules) {
- // Sort the rules to put the most specific rules first.
- Arrays.sort(rules);
-
- // Construct a regular expression, escaping all the prefix strings.
- StringBuilder pattern = new StringBuilder("(");
- for (int i = 0; i < rules.length; ++i) {
- if (i > 0) pattern.append(")|(");
- pattern.append(RULE_PATTERN.matcher(rules[i].mPrefix).replaceAll("\\\\$0"));
- }
- mPattern = Pattern.compile(pattern.append(")").toString());
- mRules = rules;
- }
-
- /**
- * Match a string against every Rule and find one that matches.
- * @param uri to match against the Rules in the rewriter.
- * @return the most specific matching Rule, or Rule.DEFAULT if none match.
- */
- public Rule matchRule(String url) {
- Matcher matcher = mPattern.matcher(url);
- if (matcher.lookingAt()) {
- for (int i = 0; i < mRules.length; ++i) {
- if (matcher.group(i + 1) != null) {
- return mRules[i]; // Rules are sorted most specific first.
- }
- }
- }
- return Rule.DEFAULT;
- }
-
- /**
- * Get the (possibly cached) UrlRules based on the rules in Gservices.
- * @param resolver to use for accessing the Gservices database.
- * @return an updated UrlRules instance
- */
- public static synchronized UrlRules getRules(ContentResolver resolver) {
- String digest = Settings.Gservices.getString(resolver,
- Settings.Gservices.PROVISIONING_DIGEST);
- if (sCachedDigest != null && sCachedDigest.equals(digest)) {
- // The digest is the same, so the rules are the same.
- return sCachedRules;
- }
-
- // Get all the Gservices settings with names starting with "url:".
- Cursor cursor = resolver.query(Settings.Gservices.CONTENT_URI,
- new String[] {
- Settings.Gservices.NAME,
- Settings.Gservices.VALUE
- },
- Settings.Gservices.NAME + " like \"url:%\"", null,
- Settings.Gservices.NAME);
- try {
- ArrayList<Rule> rules = new ArrayList<Rule>();
- while (cursor.moveToNext()) {
- try {
- String name = cursor.getString(0).substring(4); // "url:X"
- String value = cursor.getString(1);
- if (value == null || value.length() == 0) continue;
- rules.add(new Rule(name, value));
- } catch (RuleFormatException e) {
- // Oops, Gservices has an invalid rule! Skip it.
- Log.e("UrlRules", "Invalid rule from Gservices", e);
- Checkin.logEvent(resolver,
- Checkin.Events.Tag.GSERVICES_ERROR, e.toString());
- }
- }
- sCachedRules = new UrlRules(rules.toArray(new Rule[rules.size()]));
- sCachedDigest = digest;
- } finally {
- cursor.close();
- }
-
- return sCachedRules;
- }
-}
diff --git a/core/java/com/google/android/util/AbstractMessageParser.java b/core/java/com/google/android/util/AbstractMessageParser.java
deleted file mode 100644
index 25f6b33..0000000
--- a/core/java/com/google/android/util/AbstractMessageParser.java
+++ /dev/null
@@ -1,1496 +0,0 @@
-// Copyright 2007 The Android Open Source Project
-// All Rights Reserved.
-
-package com.google.android.util;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.Set;
-import java.util.List;
-
-/**
- *
- * Logic for parsing a text message typed by the user looking for smileys,
- * urls, acronyms,formatting (e.g., '*'s for bold), me commands
- * (e.g., "/me is asleep"), and punctuation.
- *
- * It constructs an array, which breaks the text up into its
- * constituent pieces, which we return to the client.
- *
- */
-public abstract class AbstractMessageParser {
-/**
- * Interface representing the set of resources needed by a message parser
- *
- * @author jessan (Jessan Hutchison-Quillian)
- */
- public static interface Resources {
-
- /** Get the known set of URL schemes. */
- public Set<String> getSchemes();
-
- /** Get the possible values for the last part of a domain name.
- * Values are expected to be reversed in the Trie.
- */
- public TrieNode getDomainSuffixes();
-
- /** Get the smileys accepted by the parser. */
- public TrieNode getSmileys();
-
- /** Get the acronyms accepted by the parser. */
- public TrieNode getAcronyms();
- }
-
- /**
- * Subclasses must define the schemes, domains, smileys and acronyms
- * that are necessary for parsing
- */
- protected abstract Resources getResources();
-
- /** Music note that indicates user is listening to a music track. */
- public static final String musicNote = "\u266B ";
-
- private String text;
- private int nextChar;
- private int nextClass;
- private ArrayList<Part> parts;
- private ArrayList<Token> tokens;
- private HashMap<Character,Format> formatStart;
- private boolean parseSmilies;
- private boolean parseAcronyms;
- private boolean parseFormatting;
- private boolean parseUrls;
- private boolean parseMeText;
- private boolean parseMusic;
-
- /**
- * Create a message parser to parse urls, formatting, acronyms, smileys,
- * /me text and music
- *
- * @param text the text to parse
- */
- public AbstractMessageParser(String text) {
- this(text, true, true, true, true, true, true);
- }
-
- /**
- * Create a message parser, specifying the kinds of text to parse
- *
- * @param text the text to parse
- *
- */
- public AbstractMessageParser(String text, boolean parseSmilies,
- boolean parseAcronyms, boolean parseFormatting, boolean parseUrls,
- boolean parseMusic, boolean parseMeText) {
- this.text = text;
- this.nextChar = 0;
- this.nextClass = 10;
- this.parts = new ArrayList<Part>();
- this.tokens = new ArrayList<Token>();
- this.formatStart = new HashMap<Character,Format>();
- this.parseSmilies = parseSmilies;
- this.parseAcronyms = parseAcronyms;
- this.parseFormatting = parseFormatting;
- this.parseUrls = parseUrls;
- this.parseMusic = parseMusic;
- this.parseMeText = parseMeText;
- }
-
- /** Returns the raw text being parsed. */
- public final String getRawText() { return text; }
-
- /** Return the number of parts. */
- public final int getPartCount() { return parts.size(); }
-
- /** Return the part at the given index. */
- public final Part getPart(int index) { return parts.get(index); }
-
- /** Return the list of parts from the parsed text */
- public final List<Part> getParts() { return parts; }
-
- /** Parses the text string into an internal representation. */
- public void parse() {
- // Look for music track (of which there would be only one and it'll be the
- // first token)
- if (parseMusicTrack()) {
- buildParts(null);
- return;
- }
-
- // Look for me commands.
- String meText = null;
- if (parseMeText && text.startsWith("/me") && (text.length() > 3) &&
- Character.isWhitespace(text.charAt(3))) {
- meText = text.substring(0, 4);
- text = text.substring(4);
- }
-
- // Break the text into tokens.
- boolean wasSmiley = false;
- while (nextChar < text.length()) {
- if (!isWordBreak(nextChar)) {
- if (!wasSmiley || !isSmileyBreak(nextChar)) {
- throw new AssertionError("last chunk did not end at word break");
- }
- }
-
- if (parseSmiley()) {
- wasSmiley = true;
- } else {
- wasSmiley = false;
-
- if (!parseAcronym() && !parseURL() && !parseFormatting()) {
- parseText();
- }
- }
- }
-
- // Trim the whitespace before and after media components.
- for (int i = 0; i < tokens.size(); ++i) {
- if (tokens.get(i).isMedia()) {
- if ((i > 0) && (tokens.get(i - 1) instanceof Html)) {
- ((Html)tokens.get(i - 1)).trimLeadingWhitespace();
- }
- if ((i + 1 < tokens.size()) && (tokens.get(i + 1) instanceof Html)) {
- ((Html)tokens.get(i + 1)).trimTrailingWhitespace();
- }
- }
- }
-
- // Remove any empty html tokens.
- for (int i = 0; i < tokens.size(); ++i) {
- if (tokens.get(i).isHtml() &&
- (tokens.get(i).toHtml(true).length() == 0)) {
- tokens.remove(i);
- --i; // visit this index again
- }
- }
-
- buildParts(meText);
- }
-
- /**
- * Get a the appropriate Token for a given URL
- *
- * @param text the anchor text
- * @param url the url
- *
- */
- public static Token tokenForUrl(String url, String text) {
- if(url == null) {
- return null;
- }
-
- //Look for video links
- Video video = Video.matchURL(url, text);
- if (video != null) {
- return video;
- }
-
- // Look for video links.
- YouTubeVideo ytVideo = YouTubeVideo.matchURL(url, text);
- if (ytVideo != null) {
- return ytVideo;
- }
-
- // Look for photo links.
- Photo photo = Photo.matchURL(url, text);
- if (photo != null) {
- return photo;
- }
-
- // Look for photo links.
- FlickrPhoto flickrPhoto = FlickrPhoto.matchURL(url, text);
- if (flickrPhoto != null) {
- return flickrPhoto;
- }
-
- //Not media, so must be a regular URL
- return new Link(url, text);
- }
-
- /**
- * Builds the parts list.
- *
- * @param meText any meText parsed from the message
- */
- private void buildParts(String meText) {
- for (int i = 0; i < tokens.size(); ++i) {
- Token token = tokens.get(i);
- if (token.isMedia() || (parts.size() == 0) || lastPart().isMedia()) {
- parts.add(new Part());
- }
- lastPart().add(token);
- }
-
- // The first part inherits the meText of the line.
- if (parts.size() > 0) {
- parts.get(0).setMeText(meText);
- }
- }
-
- /** Returns the last part in the list. */
- private Part lastPart() { return parts.get(parts.size() - 1); }
-
- /**
- * Looks for a music track (\u266B is first character, everything else is
- * track info).
- */
- private boolean parseMusicTrack() {
-
- if (parseMusic && text.startsWith(musicNote)) {
- addToken(new MusicTrack(text.substring(musicNote.length())));
- nextChar = text.length();
- return true;
- }
- return false;
- }
-
- /** Consumes all of the text in the next word . */
- private void parseText() {
- StringBuilder buf = new StringBuilder();
- int start = nextChar;
- do {
- char ch = text.charAt(nextChar++);
- switch (ch) {
- case '<': buf.append("&lt;"); break;
- case '>': buf.append("&gt;"); break;
- case '&': buf.append("&amp;"); break;
- case '"': buf.append("&quot;"); break;
- case '\'': buf.append("&apos;"); break;
- case '\n': buf.append("<br>"); break;
- default: buf.append(ch); break;
- }
- } while (!isWordBreak(nextChar));
-
- addToken(new Html(text.substring(start, nextChar), buf.toString()));
- }
-
- /**
- * Looks for smileys (e.g., ":)") in the text. The set of known smileys is
- * loaded from a file into a trie at server start.
- */
- private boolean parseSmiley() {
- if(!parseSmilies) {
- return false;
- }
- TrieNode match = longestMatch(getResources().getSmileys(), this, nextChar,
- true);
- if (match == null) {
- return false;
- } else {
- int previousCharClass = getCharClass(nextChar - 1);
- int nextCharClass = getCharClass(nextChar + match.getText().length());
- if ((previousCharClass == 2 || previousCharClass == 3)
- && (nextCharClass == 2 || nextCharClass == 3)) {
- return false;
- }
- addToken(new Smiley(match.getText()));
- nextChar += match.getText().length();
- return true;
- }
- }
-
- /** Looks for acronyms (e.g., "lol") in the text.
- */
- private boolean parseAcronym() {
- if(!parseAcronyms) {
- return false;
- }
- TrieNode match = longestMatch(getResources().getAcronyms(), this, nextChar);
- if (match == null) {
- return false;
- } else {
- addToken(new Acronym(match.getText(), match.getValue()));
- nextChar += match.getText().length();
- return true;
- }
- }
-
- /** Determines if this is an allowable domain character. */
- private boolean isDomainChar(char c) {
- return c == '-' || Character.isLetter(c) || Character.isDigit(c);
- }
-
- /** Determines if the given string is a valid domain. */
- private boolean isValidDomain(String domain) {
- // For hostnames, check that it ends with a known domain suffix
- if (matches(getResources().getDomainSuffixes(), reverse(domain))) {
- return true;
- }
- return false;
- }
-
- /**
- * Looks for a URL in two possible forms: either a proper URL with a known
- * scheme or a domain name optionally followed by a path, query, or query.
- */
- private boolean parseURL() {
- // Make sure this is a valid place to start a URL.
- if (!parseUrls || !isURLBreak(nextChar)) {
- return false;
- }
-
- int start = nextChar;
-
- // Search for the first block of letters.
- int index = start;
- while ((index < text.length()) && isDomainChar(text.charAt(index))) {
- index += 1;
- }
-
- String url = "";
- boolean done = false;
-
- if (index == text.length()) {
- return false;
- } else if (text.charAt(index) == ':') {
- // Make sure this is a known scheme.
- String scheme = text.substring(nextChar, index);
- if (!getResources().getSchemes().contains(scheme)) {
- return false;
- }
- } else if (text.charAt(index) == '.') {
- // Search for the end of the domain name.
- while (index < text.length()) {
- char ch = text.charAt(index);
- if ((ch != '.') && !isDomainChar(ch)) {
- break;
- } else {
- index += 1;
- }
- }
-
- // Make sure the domain name has a valid suffix. Since tries look for
- // prefix matches, we reverse all the strings to get suffix comparisons.
- String domain = text.substring(nextChar, index);
- if (!isValidDomain(domain)) {
- return false;
- }
-
- // Search for a port. We deal with this specially because a colon can
- // also be a punctuation character.
- if ((index + 1 < text.length()) && (text.charAt(index) == ':')) {
- char ch = text.charAt(index + 1);
- if (Character.isDigit(ch)) {
- index += 1;
- while ((index < text.length()) &&
- Character.isDigit(text.charAt(index))) {
- index += 1;
- }
- }
- }
-
- // The domain name should be followed by end of line, whitespace,
- // punctuation, or a colon, slash, question, or hash character. The
- // tricky part here is that some URL characters are also punctuation, so
- // we need to distinguish them. Since we looked for ports above, a colon
- // is always punctuation here. To distinguish '?' cases, we look at the
- // character that follows it.
- if (index == text.length()) {
- done = true;
- } else {
- char ch = text.charAt(index);
- if (ch == '?') {
- // If the next character is whitespace or punctuation (or missing),
- // then this question mark looks like punctuation.
- if (index + 1 == text.length()) {
- done = true;
- } else {
- char ch2 = text.charAt(index + 1);
- if (Character.isWhitespace(ch2) || isPunctuation(ch2)) {
- done = true;
- }
- }
- } else if (isPunctuation(ch)) {
- done = true;
- } else if (Character.isWhitespace(ch)) {
- done = true;
- } else if ((ch == '/') || (ch == '#')) {
- // In this case, the URL is not done. We will search for the end of
- // it below.
- } else {
- return false;
- }
- }
-
- // We will assume the user meant HTTP. (One weird case is where they
- // type a port of 443. That could mean HTTPS, but they might also want
- // HTTP. We'll let them specify if they don't want HTTP.)
- url = "http://";
- } else {
- return false;
- }
-
- // If the URL is not done, search for the end, which is just before the
- // next whitespace character.
- if (!done) {
- while ((index < text.length()) &&
- !Character.isWhitespace(text.charAt(index))) {
- index += 1;
- }
- }
-
- String urlText = text.substring(start, index);
- url += urlText;
-
- // Figure out the appropriate token type.
- addURLToken(url, urlText);
-
- nextChar = index;
- return true;
- }
-
- /**
- * Adds the appropriate token for the given URL. This might be a simple
- * link or it might be a recognized media type.
- */
- private void addURLToken(String url, String text) {
- addToken(tokenForUrl(url, text));
- }
-
- /**
- * Deal with formatting characters.
- *
- * Parsing is as follows:
- * - Treat all contiguous strings of formatting characters as one block.
- * (This method processes one block.)
- * - Only a single instance of a particular format character within a block
- * is used to determine whether to turn on/off that type of formatting;
- * other instances simply print the character itself.
- * - If the format is to be turned on, we use the _first_ instance; if it
- * is to be turned off, we use the _last_ instance (by appending the
- * format.)
- *
- * Example:
- * **string** turns into <b>*string*</b>
- */
- private boolean parseFormatting() {
- if(!parseFormatting) {
- return false;
- }
- int endChar = nextChar;
- while ((endChar < text.length()) && isFormatChar(text.charAt(endChar))) {
- endChar += 1;
- }
-
- if ((endChar == nextChar) || !isWordBreak(endChar)) {
- return false;
- }
-
- // Keeps track of whether we've seen a character (in map if we've seen it)
- // and whether we should append a closing format token (if value in
- // map is TRUE). Linked hashmap for consistent ordering.
- LinkedHashMap<Character, Boolean> seenCharacters =
- new LinkedHashMap<Character, Boolean>();
-
- for (int index = nextChar; index < endChar; ++index) {
- char ch = text.charAt(index);
- Character key = Character.valueOf(ch);
- if (seenCharacters.containsKey(key)) {
- // Already seen this character, just append an unmatched token, which
- // will print plaintext character
- addToken(new Format(ch, false));
- } else {
- Format start = formatStart.get(key);
- if (start != null) {
- // Match the start token, and ask an end token to be appended
- start.setMatched(true);
- formatStart.remove(key);
- seenCharacters.put(key, Boolean.TRUE);
- } else {
- // Append start token
- start = new Format(ch, true);
- formatStart.put(key, start);
- addToken(start);
- seenCharacters.put(key, Boolean.FALSE);
- }
- }
- }
-
- // Append any necessary end tokens
- for (Character key : seenCharacters.keySet()) {
- if (seenCharacters.get(key) == Boolean.TRUE) {
- Format end = new Format(key.charValue(), false);
- end.setMatched(true);
- addToken(end);
- }
- }
-
- nextChar = endChar;
- return true;
- }
-
- /** Determines whether the given index could be a possible word break. */
- private boolean isWordBreak(int index) {
- return getCharClass(index - 1) != getCharClass(index);
- }
-
- /** Determines whether the given index could be a possible smiley break. */
- private boolean isSmileyBreak(int index) {
- if (index > 0 && index < text.length()) {
- if (isSmileyBreak(text.charAt(index - 1), text.charAt(index))) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Verifies that the character before the given index is end of line,
- * whitespace, or punctuation.
- */
- private boolean isURLBreak(int index) {
- switch (getCharClass(index - 1)) {
- case 2:
- case 3:
- case 4:
- return false;
-
- case 0:
- case 1:
- default:
- return true;
- }
- }
-
- /** Returns the class for the character at the given index. */
- private int getCharClass(int index) {
- if ((index < 0) || (text.length() <= index)) {
- return 0;
- }
-
- char ch = text.charAt(index);
- if (Character.isWhitespace(ch)) {
- return 1;
- } else if (Character.isLetter(ch)) {
- return 2;
- } else if (Character.isDigit(ch)) {
- return 3;
- } else if (isPunctuation(ch)) {
- // For punctuation, we return a unique value every time so that they are
- // always different from any other character. Punctuation should always
- // be considered a possible word break.
- return ++nextClass;
- } else {
- return 4;
- }
- }
-
- /**
- * Returns true if <code>c1</code> could be the last character of
- * a smiley and <code>c2</code> could be the first character of
- * a different smiley, if {@link #isWordBreak} would not already
- * recognize that this is possible.
- */
- private static boolean isSmileyBreak(char c1, char c2) {
- switch (c1) {
- /*
- * These characters can end smileys, but don't normally end words.
- */
- case '$': case '&': case '*': case '+': case '-':
- case '/': case '<': case '=': case '>': case '@':
- case '[': case '\\': case ']': case '^': case '|':
- case '}': case '~':
- switch (c2) {
- /*
- * These characters can begin smileys, but don't normally
- * begin words.
- */
- case '#': case '$': case '%': case '*': case '/':
- case '<': case '=': case '>': case '@': case '[':
- case '\\': case '^': case '~':
- return true;
- }
- }
-
- return false;
- }
-
- /** Determines whether the given character is punctuation. */
- private static boolean isPunctuation(char ch) {
- switch (ch) {
- case '.': case ',': case '"': case ':': case ';':
- case '?': case '!': case '(': case ')':
- return true;
-
- default:
- return false;
- }
- }
-
- /**
- * Determines whether the given character is the beginning or end of a
- * section with special formatting.
- */
- private static boolean isFormatChar(char ch) {
- switch (ch) {
- case '*': case '_': case '^':
- return true;
-
- default:
- return false;
- }
- }
-
- /** Represents a unit of parsed output. */
- public static abstract class Token {
- public enum Type {
-
- HTML ("html"),
- FORMAT ("format"), // subtype of HTML
- LINK ("l"),
- SMILEY ("e"),
- ACRONYM ("a"),
- MUSIC ("m"),
- GOOGLE_VIDEO ("v"),
- YOUTUBE_VIDEO ("yt"),
- PHOTO ("p"),
- FLICKR ("f");
-
- //stringreps for HTML and FORMAT don't really matter
- //because they don't define getInfo(), which is where it is used
- //For the other types, code depends on their stringreps
- private String stringRep;
-
- Type(String stringRep) {
- this.stringRep = stringRep;
- }
-
- /** {@inheritDoc} */
- public String toString() {
- return this.stringRep;
- }
- }
-
- protected Type type;
- protected String text;
-
- protected Token(Type type, String text) {
- this.type = type;
- this.text = text;
- }
-
- /** Returns the type of the token. */
- public Type getType() { return type; }
-
- /**
- * Get the relevant information about a token
- *
- * @return a list of strings representing the token, not null
- * The first item is always a string representation of the type
- */
- public List<String> getInfo() {
- List<String> info = new ArrayList<String>();
- info.add(getType().toString());
- return info;
- }
-
- /** Returns the raw text of the token. */
- public String getRawText() { return text; }
-
- public boolean isMedia() { return false; }
- public abstract boolean isHtml();
- public boolean isArray() { return !isHtml(); }
-
- public String toHtml(boolean caps) { throw new AssertionError("not html"); }
-
- // The token can change the caps of the text after that point.
- public boolean controlCaps() { return false; }
- public boolean setCaps() { return false; }
- }
-
- /** Represents a simple string of html text. */
- public static class Html extends Token {
- private String html;
-
- public Html(String text, String html) {
- super(Type.HTML, text);
- this.html = html;
- }
-
- public boolean isHtml() { return true; }
- public String toHtml(boolean caps) {
- return caps ? html.toUpperCase() : html;
- }
- /**
- * Not supported. Info should not be needed for this type
- */
- public List<String> getInfo() {
- throw new UnsupportedOperationException();
- }
-
- public void trimLeadingWhitespace() {
- text = trimLeadingWhitespace(text);
- html = trimLeadingWhitespace(html);
- }
-
- public void trimTrailingWhitespace() {
- text = trimTrailingWhitespace(text);
- html = trimTrailingWhitespace(html);
- }
-
- private static String trimLeadingWhitespace(String text) {
- int index = 0;
- while ((index < text.length()) &&
- Character.isWhitespace(text.charAt(index))) {
- ++index;
- }
- return text.substring(index);
- }
-
- public static String trimTrailingWhitespace(String text) {
- int index = text.length();
- while ((index > 0) && Character.isWhitespace(text.charAt(index - 1))) {
- --index;
- }
- return text.substring(0, index);
- }
- }
-
- /** Represents a music track token at the beginning. */
- public static class MusicTrack extends Token {
- private String track;
-
- public MusicTrack(String track) {
- super(Type.MUSIC, track);
- this.track = track;
- }
-
- public String getTrack() { return track; }
-
- public boolean isHtml() { return false; }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getTrack());
- return info;
- }
- }
-
- /** Represents a link that was found in the input. */
- public static class Link extends Token {
- private String url;
-
- public Link(String url, String text) {
- super(Type.LINK, text);
- this.url = url;
- }
-
- public String getURL() { return url; }
-
- public boolean isHtml() { return false; }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getURL());
- info.add(getRawText());
- return info;
- }
- }
-
- /** Represents a link to a Google Video. */
- public static class Video extends Token {
- /** Pattern for a video URL. */
- private static final Pattern URL_PATTERN = Pattern.compile(
- "(?i)http://video\\.google\\.[a-z0-9]+(?:\\.[a-z0-9]+)?/videoplay\\?"
- + ".*?\\bdocid=(-?\\d+).*");
-
- private String docid;
-
- public Video(String docid, String text) {
- super(Type.GOOGLE_VIDEO, text);
- this.docid = docid;
- }
-
- public String getDocID() { return docid; }
-
- public boolean isHtml() { return false; }
- public boolean isMedia() { return true; }
-
- /** Returns a Video object if the given url is to a video. */
- public static Video matchURL(String url, String text) {
- Matcher m = URL_PATTERN.matcher(url);
- if (m.matches()) {
- return new Video(m.group(1), text);
- } else {
- return null;
- }
- }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getRssUrl(docid));
- info.add(getURL(docid));
- return info;
- }
-
- /** Returns the URL for the RSS description of the given video. */
- public static String getRssUrl(String docid) {
- return "http://video.google.com/videofeed"
- + "?type=docid&output=rss&sourceid=gtalk&docid=" + docid;
- }
-
- /** (For testing purposes:) Returns a video URL with the given parts. */
- public static String getURL(String docid) {
- return getURL(docid, null);
- }
-
- /** (For testing purposes:) Returns a video URL with the given parts. */
- public static String getURL(String docid, String extraParams) {
- if (extraParams == null) {
- extraParams = "";
- } else if (extraParams.length() > 0) {
- extraParams += "&";
- }
- return "http://video.google.com/videoplay?" + extraParams
- + "docid=" + docid;
- }
- }
-
- /** Represents a link to a YouTube video. */
- public static class YouTubeVideo extends Token {
- /** Pattern for a video URL. */
- private static final Pattern URL_PATTERN = Pattern.compile(
- "(?i)http://(?:[a-z0-9]+\\.)?youtube\\.[a-z0-9]+(?:\\.[a-z0-9]+)?/watch\\?"
- + ".*\\bv=([-_a-zA-Z0-9=]+).*");
-
- private String docid;
-
- public YouTubeVideo(String docid, String text) {
- super(Type.YOUTUBE_VIDEO, text);
- this.docid = docid;
- }
-
- public String getDocID() { return docid; }
-
- public boolean isHtml() { return false; }
- public boolean isMedia() { return true; }
-
- /** Returns a Video object if the given url is to a video. */
- public static YouTubeVideo matchURL(String url, String text) {
- Matcher m = URL_PATTERN.matcher(url);
- if (m.matches()) {
- return new YouTubeVideo(m.group(1), text);
- } else {
- return null;
- }
- }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getRssUrl(docid));
- info.add(getURL(docid));
- return info;
- }
-
- /** Returns the URL for the RSS description of the given video. */
- public static String getRssUrl(String docid) {
- return "http://youtube.com/watch?v=" + docid;
- }
-
- /** (For testing purposes:) Returns a video URL with the given parts. */
- public static String getURL(String docid) {
- return getURL(docid, null);
- }
-
- /** (For testing purposes:) Returns a video URL with the given parts. */
- public static String getURL(String docid, String extraParams) {
- if (extraParams == null) {
- extraParams = "";
- } else if (extraParams.length() > 0) {
- extraParams += "&";
- }
- return "http://youtube.com/watch?" + extraParams + "v=" + docid;
- }
-
- /** (For testing purposes:) Returns a video URL with the given parts.
- * @param http If true, includes http://
- * @param prefix If non-null/non-blank, adds to URL before youtube.com.
- * (e.g., prefix="br." --> "br.youtube.com")
- */
- public static String getPrefixedURL(boolean http, String prefix,
- String docid, String extraParams) {
- String protocol = "";
-
- if (http) {
- protocol = "http://";
- }
-
- if (prefix == null) {
- prefix = "";
- }
-
- if (extraParams == null) {
- extraParams = "";
- } else if (extraParams.length() > 0) {
- extraParams += "&";
- }
-
- return protocol + prefix + "youtube.com/watch?" + extraParams + "v=" +
- docid;
- }
- }
-
- /** Represents a link to a Picasa photo or album. */
- public static class Photo extends Token {
- /** Pattern for an album or photo URL. */
- // TODO (katyarogers) searchbrowse includes search lists and tags,
- // it follows a different pattern than albums - would be nice to add later
- private static final Pattern URL_PATTERN = Pattern.compile(
- "http://picasaweb.google.com/([^/?#&]+)/+((?!searchbrowse)[^/?#&]+)(?:/|/photo)?(?:\\?[^#]*)?(?:#(.*))?");
-
- private String user;
- private String album;
- private String photo; // null for albums
-
- public Photo(String user, String album, String photo, String text) {
- super(Type.PHOTO, text);
- this.user = user;
- this.album = album;
- this.photo = photo;
- }
-
- public String getUser() { return user; }
- public String getAlbum() { return album; }
- public String getPhoto() { return photo; }
-
- public boolean isHtml() { return false; }
- public boolean isMedia() { return true; }
-
- /** Returns a Photo object if the given url is to a photo or album. */
- public static Photo matchURL(String url, String text) {
- Matcher m = URL_PATTERN.matcher(url);
- if (m.matches()) {
- return new Photo(m.group(1), m.group(2), m.group(3), text);
- } else {
- return null;
- }
- }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getRssUrl(getUser()));
- info.add(getAlbumURL(getUser(), getAlbum()));
- if (getPhoto() != null) {
- info.add(getPhotoURL(getUser(), getAlbum(), getPhoto()));
- } else {
- info.add((String)null);
- }
- return info;
- }
-
- /** Returns the URL for the RSS description of the user's albums. */
- public static String getRssUrl(String user) {
- return "http://picasaweb.google.com/data/feed/api/user/" + user +
- "?category=album&alt=rss";
- }
-
- /** Returns the URL for an album. */
- public static String getAlbumURL(String user, String album) {
- return "http://picasaweb.google.com/" + user + "/" + album;
- }
-
- /** Returns the URL for a particular photo. */
- public static String getPhotoURL(String user, String album, String photo) {
- return "http://picasaweb.google.com/" + user + "/" + album + "/photo#"
- + photo;
- }
- }
-
- /** Represents a link to a Flickr photo or album. */
- public static class FlickrPhoto extends Token {
- /** Pattern for a user album or photo URL. */
- private static final Pattern URL_PATTERN = Pattern.compile(
- "http://(?:www.)?flickr.com/photos/([^/?#&]+)/?([^/?#&]+)?/?.*");
- private static final Pattern GROUPING_PATTERN = Pattern.compile(
- "http://(?:www.)?flickr.com/photos/([^/?#&]+)/(tags|sets)/" +
- "([^/?#&]+)/?");
-
- private static final String SETS = "sets";
- private static final String TAGS = "tags";
-
- private String user;
- private String photo; // null for user album
- private String grouping; // either "tags" or "sets"
- private String groupingId; // sets or tags identifier
-
- public FlickrPhoto(String user, String photo, String grouping,
- String groupingId, String text) {
- super(Type.FLICKR, text);
-
- /* System wide tags look like the URL to a Flickr user. */
- if (!TAGS.equals(user)) {
- this.user = user;
- // Don't consider slide show URL a photo
- this.photo = (!"show".equals(photo) ? photo : null);
- this.grouping = grouping;
- this.groupingId = groupingId;
- } else {
- this.user = null;
- this.photo = null;
- this.grouping = TAGS;
- this.groupingId = photo;
- }
- }
-
- public String getUser() { return user; }
- public String getPhoto() { return photo; }
- public String getGrouping() { return grouping; }
- public String getGroupingId() { return groupingId; }
-
- public boolean isHtml() { return false; }
- public boolean isMedia() { return true; }
-
- /**
- * Returns a FlickrPhoto object if the given url is to a photo or Flickr
- * user.
- */
- public static FlickrPhoto matchURL(String url, String text) {
- Matcher m = GROUPING_PATTERN.matcher(url);
- if (m.matches()) {
- return new FlickrPhoto(m.group(1), null, m.group(2), m.group(3), text);
- }
-
- m = URL_PATTERN.matcher(url);
- if (m.matches()) {
- return new FlickrPhoto(m.group(1), m.group(2), null, null, text);
- } else {
- return null;
- }
- }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getUrl());
- info.add(getUser() != null ? getUser() : "");
- info.add(getPhoto() != null ? getPhoto() : "");
- info.add(getGrouping() != null ? getGrouping() : "");
- info.add(getGroupingId() != null ? getGroupingId() : "");
- return info;
- }
-
- public String getUrl() {
- if (SETS.equals(grouping)) {
- return getUserSetsURL(user, groupingId);
- } else if (TAGS.equals(grouping)) {
- if (user != null) {
- return getUserTagsURL(user, groupingId);
- } else {
- return getTagsURL(groupingId);
- }
- } else if (photo != null) {
- return getPhotoURL(user, photo);
- } else {
- return getUserURL(user);
- }
- }
-
- /** Returns the URL for the RSS description. */
- public static String getRssUrl(String user) {
- return null;
- }
-
- /** Returns the URL for a particular tag. */
- public static String getTagsURL(String tag) {
- return "http://flickr.com/photos/tags/" + tag;
- }
-
- /** Returns the URL to the user's Flickr homepage. */
- public static String getUserURL(String user) {
- return "http://flickr.com/photos/" + user;
- }
-
- /** Returns the URL for a particular photo. */
- public static String getPhotoURL(String user, String photo) {
- return "http://flickr.com/photos/" + user + "/" + photo;
- }
-
- /** Returns the URL for a user tag photo set. */
- public static String getUserTagsURL(String user, String tagId) {
- return "http://flickr.com/photos/" + user + "/tags/" + tagId;
- }
-
- /** Returns the URL for user set. */
- public static String getUserSetsURL(String user, String setId) {
- return "http://flickr.com/photos/" + user + "/sets/" + setId;
- }
- }
-
- /** Represents a smiley that was found in the input. */
- public static class Smiley extends Token {
- // TODO: Pass the SWF URL down to the client.
-
- public Smiley(String text) {
- super(Type.SMILEY, text);
- }
-
- public boolean isHtml() { return false; }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getRawText());
- return info;
- }
- }
-
- /** Represents an acronym that was found in the input. */
- public static class Acronym extends Token {
- private String value;
- // TODO: SWF
-
- public Acronym(String text, String value) {
- super(Type.ACRONYM, text);
- this.value = value;
- }
-
- public String getValue() { return value; }
-
- public boolean isHtml() { return false; }
-
- public List<String> getInfo() {
- List<String> info = super.getInfo();
- info.add(getRawText());
- info.add(getValue());
- return info;
- }
- }
-
- /** Represents a character that changes formatting. */
- public static class Format extends Token {
- private char ch;
- private boolean start;
- private boolean matched;
-
- public Format(char ch, boolean start) {
- super(Type.FORMAT, String.valueOf(ch));
- this.ch = ch;
- this.start = start;
- }
-
- public void setMatched(boolean matched) { this.matched = matched; }
-
- public boolean isHtml() { return true; }
-
- public String toHtml(boolean caps) {
- // This character only implies special formatting if it was matched.
- // Otherwise, it was just a plain old character.
- if (matched) {
- return start ? getFormatStart(ch) : getFormatEnd(ch);
- } else {
- // We have to make sure we escape HTML characters as usual.
- return (ch == '"') ? "&quot;" : String.valueOf(ch);
- }
- }
-
- /**
- * Not supported. Info should not be needed for this type
- */
- public List<String> getInfo() {
- throw new UnsupportedOperationException();
- }
-
- public boolean controlCaps() { return (ch == '^'); }
- public boolean setCaps() { return start; }
-
- private String getFormatStart(char ch) {
- switch (ch) {
- case '*': return "<b>";
- case '_': return "<i>";
- case '^': return "<b><font color=\"#005FFF\">"; // TODO: all caps
- case '"': return "<font color=\"#999999\">\u201c";
- default: throw new AssertionError("unknown format '" + ch + "'");
- }
- }
-
- private String getFormatEnd(char ch) {
- switch (ch) {
- case '*': return "</b>";
- case '_': return "</i>";
- case '^': return "</font></b>"; // TODO: all caps
- case '"': return "\u201d</font>";
- default: throw new AssertionError("unknown format '" + ch + "'");
- }
- }
- }
-
- /** Adds the given token to the parsed output. */
- private void addToken(Token token) {
- tokens.add(token);
- }
-
- /** Converts the entire message into a single HTML display string. */
- public String toHtml() {
- StringBuilder html = new StringBuilder();
-
- for (Part part : parts) {
- boolean caps = false;
-
- html.append("<p>");
- for (Token token : part.getTokens()) {
- if (token.isHtml()) {
- html.append(token.toHtml(caps));
- } else {
- switch (token.getType()) {
- case LINK:
- html.append("<a href=\"");
- html.append(((Link)token).getURL());
- html.append("\">");
- html.append(token.getRawText());
- html.append("</a>");
- break;
-
- case SMILEY:
- // TODO: link to an appropriate image
- html.append(token.getRawText());
- break;
-
- case ACRONYM:
- html.append(token.getRawText());
- break;
-
- case MUSIC:
- // TODO: include a music glyph
- html.append(((MusicTrack)token).getTrack());
- break;
-
- case GOOGLE_VIDEO:
- // TODO: include a Google Video icon
- html.append("<a href=\"");
- html.append(((Video)token).getURL(((Video)token).getDocID()));
- html.append("\">");
- html.append(token.getRawText());
- html.append("</a>");
- break;
-
- case YOUTUBE_VIDEO:
- // TODO: include a YouTube icon
- html.append("<a href=\"");
- html.append(((YouTubeVideo)token).getURL(
- ((YouTubeVideo)token).getDocID()));
- html.append("\">");
- html.append(token.getRawText());
- html.append("</a>");
- break;
-
- case PHOTO: {
- // TODO: include a Picasa Web icon
- html.append("<a href=\"");
- html.append(Photo.getAlbumURL(
- ((Photo)token).getUser(), ((Photo)token).getAlbum()));
- html.append("\">");
- html.append(token.getRawText());
- html.append("</a>");
- break;
- }
-
- case FLICKR:
- // TODO: include a Flickr icon
- Photo p = (Photo) token;
- html.append("<a href=\"");
- html.append(((FlickrPhoto)token).getUrl());
- html.append("\">");
- html.append(token.getRawText());
- html.append("</a>");
- break;
-
- default:
- throw new AssertionError("unknown token type: " + token.getType());
- }
- }
-
- if (token.controlCaps()) {
- caps = token.setCaps();
- }
- }
- html.append("</p>\n");
- }
-
- return html.toString();
- }
-
- /** Returns the reverse of the given string. */
- protected static String reverse(String str) {
- StringBuilder buf = new StringBuilder();
- for (int i = str.length() - 1; i >= 0; --i) {
- buf.append(str.charAt(i));
- }
- return buf.toString();
- }
-
- public static class TrieNode {
- private final HashMap<Character,TrieNode> children =
- new HashMap<Character,TrieNode>();
- private String text;
- private String value;
-
- public TrieNode() { this(""); }
- public TrieNode(String text) {
- this.text = text;
- }
-
- public final boolean exists() { return value != null; }
- public final String getText() { return text; }
- public final String getValue() { return value; }
- public void setValue(String value) { this.value = value; }
-
- public TrieNode getChild(char ch) {
- return children.get(Character.valueOf(ch));
- }
-
- public TrieNode getOrCreateChild(char ch) {
- Character key = Character.valueOf(ch);
- TrieNode node = children.get(key);
- if (node == null) {
- node = new TrieNode(text + String.valueOf(ch));
- children.put(key, node);
- }
- return node;
- }
-
- /** Adds the given string into the trie. */
- public static void addToTrie(TrieNode root, String str, String value) {
- int index = 0;
- while (index < str.length()) {
- root = root.getOrCreateChild(str.charAt(index++));
- }
- root.setValue(value);
- }
- }
-
-
-
- /** Determines whether the given string is in the given trie. */
- private static boolean matches(TrieNode root, String str) {
- int index = 0;
- while (index < str.length()) {
- root = root.getChild(str.charAt(index++));
- if (root == null) {
- break;
- } else if (root.exists()) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns the longest substring of the given string, starting at the given
- * index, that exists in the trie.
- */
- private static TrieNode longestMatch(
- TrieNode root, AbstractMessageParser p, int start) {
- return longestMatch(root, p, start, false);
- }
-
- /**
- * Returns the longest substring of the given string, starting at the given
- * index, that exists in the trie, with a special tokenizing case for
- * smileys if specified.
- */
- private static TrieNode longestMatch(
- TrieNode root, AbstractMessageParser p, int start, boolean smiley) {
- int index = start;
- TrieNode bestMatch = null;
- while (index < p.getRawText().length()) {
- root = root.getChild(p.getRawText().charAt(index++));
- if (root == null) {
- break;
- } else if (root.exists()) {
- if (p.isWordBreak(index)) {
- bestMatch = root;
- } else if (smiley && p.isSmileyBreak(index)) {
- bestMatch = root;
- }
- }
- }
- return bestMatch;
- }
-
-
- /** Represents set of tokens that are delivered as a single message. */
- public static class Part {
- private String meText;
- private ArrayList<Token> tokens;
-
- public Part() {
- this.tokens = new ArrayList<Token>();
- }
-
- public String getType(boolean isSend) {
- return (isSend ? "s" : "r") + getPartType();
- }
-
- private String getPartType() {
- if (isMedia()) {
- return "d";
- } else if (meText != null) {
- return "m";
- } else {
- return "";
- }
- }
-
- public boolean isMedia() {
- return (tokens.size() == 1) && tokens.get(0).isMedia();
- }
- /**
- * Convenience method for getting the Token of a Part that represents
- * a media Token. Parts of this kind will always only have a single Token
- *
- * @return if this.isMedia(),
- * returns the Token representing the media contained in this Part,
- * otherwise returns null;
- */
- public Token getMediaToken() {
- if(isMedia()) {
- return tokens.get(0);
- }
- return null;
- }
-
- /** Adds the given token to this part. */
- public void add(Token token) {
- if (isMedia()) {
- throw new AssertionError("media ");
- }
- tokens.add(token);
- }
-
- public void setMeText(String meText) {
- this.meText = meText;
- }
-
- /** Returns the original text of this part. */
- public String getRawText() {
- StringBuilder buf = new StringBuilder();
- if (meText != null) {
- buf.append(meText);
- }
- for (int i = 0; i < tokens.size(); ++i) {
- buf.append(tokens.get(i).getRawText());
- }
- return buf.toString();
- }
-
- /** Returns the tokens in this part. */
- public ArrayList<Token> getTokens() { return tokens; }
-
- /** Adds the tokens into the given builder as an array. */
-// public void toArray(JSArrayBuilder array) {
-// if (isMedia()) {
-// // For media, we send its array (i.e., we don't wrap this in another
-// // array as we do for non-media parts).
-// tokens.get(0).toArray(array);
-// } else {
-// array.beginArray();
-// addToArray(array);
-// array.endArray();
-// }
-// }
- }
-}
diff --git a/core/java/com/google/android/util/GoogleWebContentHelper.java b/core/java/com/google/android/util/GoogleWebContentHelper.java
deleted file mode 100644
index 2911420..0000000
--- a/core/java/com/google/android/util/GoogleWebContentHelper.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.util;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.net.http.SslError;
-import android.os.Message;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.webkit.HttpAuthHandler;
-import android.webkit.SslErrorHandler;
-import android.webkit.WebSettings;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.widget.TextView;
-
-import java.util.Locale;
-
-/**
- * Helper to display Google web content, and fallback on a static message if the
- * web content is unreachable. For example, this can be used to display
- * "Legal terms".
- * <p>
- * The typical usage pattern is to have two Gservices settings defined:
- * <ul>
- * <li>A secure URL that will be displayed on the device. This should be HTTPS
- * so hotspots won't intercept it giving us a false positive that the page
- * loaded successfully.
- * <li>A pretty human-readable URL that will be displayed to the user in case we
- * cannot reach the above URL.
- * </ul>
- * <p>
- * The typical call sequence is {@link #setUrlsFromGservices(String, String)},
- * {@link #setUnsuccessfulMessage(String)}, and {@link #loadUrl()}. At some
- * point, you'll want to display the layout via {@link #getLayout()}.
- */
-public class GoogleWebContentHelper {
-
- private Context mContext;
-
- private String mSecureUrl;
- private String mPrettyUrl;
-
- private String mUnsuccessfulMessage;
-
- private ViewGroup mLayout;
- private WebView mWebView;
- private View mProgressBar;
- private TextView mTextView;
-
- private boolean mReceivedResponse;
-
- public GoogleWebContentHelper(Context context) {
- mContext = context;
- }
-
- /**
- * Fetches the URLs from Gservices.
- *
- * @param secureSetting The setting key whose value contains the HTTPS URL.
- * @param prettySetting The setting key whose value contains the pretty URL.
- * @return This {@link GoogleWebContentHelper} so methods can be chained.
- */
- public GoogleWebContentHelper setUrlsFromGservices(String secureSetting, String prettySetting) {
- ContentResolver contentResolver = mContext.getContentResolver();
- mSecureUrl = fillUrl(Settings.Gservices.getString(contentResolver, secureSetting),
- mContext);
- mPrettyUrl = fillUrl(Settings.Gservices.getString(contentResolver, prettySetting),
- mContext);
- return this;
- }
-
- /**
- * Fetch directly from provided urls.
- *
- * @param secureUrl The HTTPS URL.
- * @param prettyUrl The pretty URL.
- * @return This {@link GoogleWebContentHelper} so methods can be chained.
- */
- public GoogleWebContentHelper setUrls(String secureUrl, String prettyUrl) {
- mSecureUrl = fillUrl(secureUrl, mContext);
- mPrettyUrl = fillUrl(prettyUrl, mContext);
- return this;
- }
-
-
- /**
- * Sets the message that will be shown if we are unable to load the page.
- * <p>
- * This should be called after {@link #setUrlsFromGservices(String, String)}
- * .
- *
- * @param message The message to load. The first argument, according to
- * {@link java.util.Formatter}, will be substituted with the pretty
- * URL.
- * @return This {@link GoogleWebContentHelper} so methods can be chained.
- */
- public GoogleWebContentHelper setUnsuccessfulMessage(String message) {
- Locale locale = mContext.getResources().getConfiguration().locale;
- mUnsuccessfulMessage = String.format(locale, message, mPrettyUrl);
- return this;
- }
-
- /**
- * Begins loading the secure URL.
- *
- * @return This {@link GoogleWebContentHelper} so methods can be chained.
- */
- public GoogleWebContentHelper loadUrl() {
- ensureViews();
- mWebView.loadUrl(mSecureUrl);
- return this;
- }
-
- /**
- * Helper to handle the back key. Returns true if the back key was handled,
- * otherwise returns false.
- * @param event the key event sent to {@link Activity#dispatchKeyEvent()}
- */
- public boolean handleKey(KeyEvent event) {
- if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
- && event.getAction() == KeyEvent.ACTION_DOWN) {
- if (mWebView.canGoBack()) {
- mWebView.goBack();
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns the layout containing the web view, progress bar, and text view.
- * This class takes care of setting each one's visibility based on current
- * state.
- *
- * @return The layout you should display.
- */
- public ViewGroup getLayout() {
- ensureViews();
- return mLayout;
- }
-
- private synchronized void ensureViews() {
- if (mLayout == null) {
- initializeViews();
- }
- }
-
- /**
- * Fills the URL with the locale.
- *
- * @param url The URL in Formatter style for the extra info to be filled in.
- * @return The filled URL.
- */
- private static String fillUrl(String url, Context context) {
-
- if (TextUtils.isEmpty(url)) {
- return "";
- }
-
- /* We add another layer of indirection here to allow mcc's to fill
- * in Locales for TOS. TODO - REMOVE when needed locales supported
- * natively (when not shipping devices to country X without support
- * for their locale).
- */
- String localeReplacement = context.
- getString(com.android.internal.R.string.locale_replacement);
- if (localeReplacement != null && localeReplacement.length() != 0) {
- url = String.format(url, localeReplacement);
- }
-
- Locale locale = Locale.getDefault();
- String tmp = locale.getLanguage() + "_" + locale.getCountry().toLowerCase();
- return String.format(url, tmp);
- }
-
- private void initializeViews() {
-
- LayoutInflater inflater =
- (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- mLayout = (ViewGroup) inflater.inflate(
- com.android.internal.R.layout.google_web_content_helper_layout, null);
-
- mWebView = (WebView) mLayout.findViewById(com.android.internal.R.id.web);
- mWebView.setWebViewClient(new MyWebViewClient());
- WebSettings settings = mWebView.getSettings();
- settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
-
- mProgressBar = mLayout.findViewById(com.android.internal.R.id.progressContainer);
- TextView message = (TextView) mProgressBar.findViewById(com.android.internal.R.id.message);
- message.setText(com.android.internal.R.string.googlewebcontenthelper_loading);
-
- mTextView = (TextView) mLayout.findViewById(com.android.internal.R.id.text);
- mTextView.setText(mUnsuccessfulMessage);
- }
-
- private synchronized void handleWebViewCompletion(boolean success) {
-
- if (mReceivedResponse) {
- return;
- } else {
- mReceivedResponse = true;
- }
-
- // In both cases, remove the progress bar
- ((ViewGroup) mProgressBar.getParent()).removeView(mProgressBar);
-
- // Remove the view that isn't relevant
- View goneView = success ? mTextView : mWebView;
- ((ViewGroup) goneView.getParent()).removeView(goneView);
-
- // Show the next view, which depends on success
- View visibleView = success ? mWebView : mTextView;
- visibleView.setVisibility(View.VISIBLE);
- }
-
- private class MyWebViewClient extends WebViewClient {
-
- @Override
- public void onPageFinished(WebView view, String url) {
- handleWebViewCompletion(true);
- }
-
- @Override
- public void onReceivedError(WebView view, int errorCode,
- String description, String failingUrl) {
- handleWebViewCompletion(false);
- }
-
- @Override
- public void onReceivedHttpAuthRequest(WebView view,
- HttpAuthHandler handler, String host, String realm) {
- handleWebViewCompletion(false);
- }
-
- @Override
- public void onReceivedSslError(WebView view, SslErrorHandler handler,
- SslError error) {
- handleWebViewCompletion(false);
- }
-
- @Override
- public void onTooManyRedirects(WebView view, Message cancelMsg,
- Message continueMsg) {
- handleWebViewCompletion(false);
- }
-
- }
-
-}
diff --git a/core/java/com/google/android/util/Procedure.java b/core/java/com/google/android/util/Procedure.java
deleted file mode 100644
index 5ede2f0..0000000
--- a/core/java/com/google/android/util/Procedure.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package com.google.android.util;
-
-/**
- * A procedure.
- */
-public interface Procedure<T> {
-
- /**
- * Applies this procedure to the given parameter.
- */
- void apply(T t);
-}
diff --git a/core/java/com/google/android/util/SimplePullParser.java b/core/java/com/google/android/util/SimplePullParser.java
deleted file mode 100644
index 031790b..0000000
--- a/core/java/com/google/android/util/SimplePullParser.java
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.util;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringReader;
-import java.io.Reader;
-import java.io.Closeable;
-
-import android.util.Xml;
-import android.util.Log;
-
-/**
- * This is an abstraction of a pull parser that provides several benefits:<ul>
- * <li>it is easier to use robustly because it makes it trivial to handle unexpected tags (which
- * might have children)</li>
- * <li>it makes the handling of text (cdata) blocks more convenient</li>
- * <li>it provides convenient methods for getting a mandatory attribute (and throwing an exception
- * if it is missing) or an optional attribute (and using a default value if it is missing)
- * </ul>
- */
-public class SimplePullParser {
- public static final String TEXT_TAG = "![CDATA[";
-
- private String mLogTag = null;
- private final XmlPullParser mParser;
- private Closeable source;
- private String mCurrentStartTag;
-
- /**
- * Constructs a new SimplePullParser to parse the stream
- * @param stream stream to parse
- * @param encoding the encoding to use
- */
- public SimplePullParser(InputStream stream, String encoding)
- throws ParseException, IOException {
- try {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(stream, encoding);
- moveToStartDocument(parser);
- mParser = parser;
- mCurrentStartTag = null;
- source = stream;
- } catch (XmlPullParserException e) {
- throw new ParseException(e);
- }
- }
-
- /**
- * Constructs a new SimplePullParser to parse the xml
- * @param parser the underlying parser to use
- */
- public SimplePullParser(XmlPullParser parser) {
- mParser = parser;
- mCurrentStartTag = null;
- source = null;
- }
-
- /**
- * Constructs a new SimplePullParser to parse the xml
- * @param xml the xml to parse
- */
- public SimplePullParser(String xml) throws IOException, ParseException {
- this(new StringReader(xml));
- }
-
- /**
- * Constructs a new SimplePullParser to parse the xml
- * @param reader a reader containing the xml
- */
- public SimplePullParser(Reader reader) throws IOException, ParseException {
- try {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(reader);
- moveToStartDocument(parser);
- mParser = parser;
- mCurrentStartTag = null;
- source = reader;
- } catch (XmlPullParserException e) {
- throw new ParseException(e);
- }
- }
-
- private static void moveToStartDocument(XmlPullParser parser)
- throws XmlPullParserException, IOException {
- int eventType;
- eventType = parser.getEventType();
- if (eventType != XmlPullParser.START_DOCUMENT) {
- throw new XmlPullParserException("Not at start of response");
- }
- }
-
- /**
- * Enables logging to the provided log tag. A basic representation of the xml will be logged as
- * the xml is parsed. No logging is done unless this is called.
- *
- * @param logTag the log tag to use when logging
- */
- public void setLogTag(String logTag) {
- mLogTag = logTag;
- }
-
- /**
- * Returns the tag of the next element whose depth is parentDepth plus one
- * or null if there are no more such elements before the next start tag. When this returns,
- * getDepth() and all methods relating to attributes will refer to the element whose tag is
- * returned.
- *
- * @param parentDepth the depth of the parrent of the item to be returned
- * @param textBuilder if null then text blocks will be ignored. If
- * non-null then text blocks will be added to the builder and TEXT_TAG
- * will be returned when one is found
- * @return the next of the next child element's tag, TEXT_TAG if a text block is found, or null
- * if there are no more child elements or DATA blocks
- * @throws IOException propogated from the underlying parser
- * @throws ParseException if there was an error parsing the xml.
- */
- public String nextTagOrText(int parentDepth, StringBuilder textBuilder)
- throws IOException, ParseException {
- while (true) {
- int eventType = 0;
- try {
- eventType = mParser.next();
- } catch (XmlPullParserException e) {
- throw new ParseException(e);
- }
- int depth = mParser.getDepth();
- mCurrentStartTag = null;
-
- if (eventType == XmlPullParser.START_TAG && depth == parentDepth + 1) {
- mCurrentStartTag = mParser.getName();
- if (mLogTag != null && Log.isLoggable(mLogTag, Log.DEBUG)) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < depth; i++) sb.append(" ");
- sb.append("<").append(mParser.getName());
- int count = mParser.getAttributeCount();
- for (int i = 0; i < count; i++) {
- sb.append(" ");
- sb.append(mParser.getAttributeName(i));
- sb.append("=\"");
- sb.append(mParser.getAttributeValue(i));
- sb.append("\"");
- }
- sb.append(">");
- Log.d(mLogTag, sb.toString());
- }
- return mParser.getName();
- }
-
- if (eventType == XmlPullParser.END_TAG && depth == parentDepth) {
- if (mLogTag != null && Log.isLoggable(mLogTag, Log.DEBUG)) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < depth; i++) sb.append(" ");
- sb.append("</>"); // Not quite valid xml but it gets the job done.
- Log.d(mLogTag, sb.toString());
- }
- return null;
- }
-
- if (eventType == XmlPullParser.END_DOCUMENT && parentDepth == 0) {
- // we could just rely on the caller calling close(), which it should, but try
- // to auto-close for clients that might have missed doing so.
- if (source != null) {
- source.close();
- source = null;
- }
- return null;
- }
-
- if (eventType == XmlPullParser.TEXT && depth == parentDepth) {
- if (textBuilder == null) {
- continue;
- }
- String text = mParser.getText();
- textBuilder.append(text);
- return TEXT_TAG;
- }
- }
- }
-
- /**
- * The same as nextTagOrTexxt(int, StringBuilder) but ignores text blocks.
- */
- public String nextTag(int parentDepth) throws IOException, ParseException {
- return nextTagOrText(parentDepth, null /* ignore text */);
- }
-
- /**
- * Returns the depth of the current element. The depth is 0 before the first
- * element has been returned, 1 after that, etc.
- *
- * @return the depth of the current element
- */
- public int getDepth() {
- return mParser.getDepth();
- }
-
- /**
- * Consumes the rest of the children, accumulating any text at this level into the builder.
- *
- * @param textBuilder the builder to contain any text
- * @throws IOException propogated from the XmlPullParser
- * @throws ParseException if there was an error parsing the xml.
- */
- public void readRemainingText(int parentDepth, StringBuilder textBuilder)
- throws IOException, ParseException {
- while (nextTagOrText(parentDepth, textBuilder) != null) {
- }
- }
-
- /**
- * Returns the number of attributes on the current element.
- *
- * @return the number of attributes on the current element
- */
- public int numAttributes() {
- return mParser.getAttributeCount();
- }
-
- /**
- * Returns the name of the nth attribute on the current element.
- *
- * @return the name of the nth attribute on the current element
- */
- public String getAttributeName(int i) {
- return mParser.getAttributeName(i);
- }
-
- /**
- * Returns the namespace of the nth attribute on the current element.
- *
- * @return the namespace of the nth attribute on the current element
- */
- public String getAttributeNamespace(int i) {
- return mParser.getAttributeNamespace(i);
- }
-
- /**
- * Returns the string value of the named attribute.
- *
- * @param namespace the namespace of the attribute
- * @param name the name of the attribute
- * @param defaultValue the value to return if the attribute is not specified
- * @return the value of the attribute
- */
- public String getStringAttribute(
- String namespace, String name, String defaultValue) {
- String value = mParser.getAttributeValue(namespace, name);
- if (null == value) return defaultValue;
- return value;
- }
-
- /**
- * Returns the string value of the named attribute. An exception will
- * be thrown if the attribute is not present.
- *
- * @param namespace the namespace of the attribute
- * @param name the name of the attribute @return the value of the attribute
- * @throws ParseException thrown if the attribute is missing
- */
- public String getStringAttribute(String namespace, String name) throws ParseException {
- String value = mParser.getAttributeValue(namespace, name);
- if (null == value) {
- throw new ParseException(
- "missing '" + name + "' attribute on '" + mCurrentStartTag + "' element");
- }
- return value;
- }
-
- /**
- * Returns the string value of the named attribute. An exception will
- * be thrown if the attribute is not a valid integer.
- *
- * @param namespace the namespace of the attribute
- * @param name the name of the attribute
- * @param defaultValue the value to return if the attribute is not specified
- * @return the value of the attribute
- * @throws ParseException thrown if the attribute not a valid integer.
- */
- public int getIntAttribute(String namespace, String name, int defaultValue)
- throws ParseException {
- String value = mParser.getAttributeValue(namespace, name);
- if (null == value) return defaultValue;
- try {
- return Integer.parseInt(value);
- } catch (NumberFormatException e) {
- throw new ParseException("Cannot parse '" + value + "' as an integer");
- }
- }
-
- /**
- * Returns the string value of the named attribute. An exception will
- * be thrown if the attribute is not present or is not a valid integer.
- *
- * @param namespace the namespace of the attribute
- * @param name the name of the attribute @return the value of the attribute
- * @throws ParseException thrown if the attribute is missing or not a valid integer.
- */
- public int getIntAttribute(String namespace, String name)
- throws ParseException {
- String value = getStringAttribute(namespace, name);
- try {
- return Integer.parseInt(value);
- } catch (NumberFormatException e) {
- throw new ParseException("Cannot parse '" + value + "' as an integer");
- }
- }
-
- /**
- * Returns the string value of the named attribute. An exception will
- * be thrown if the attribute is not a valid long.
- *
- * @param namespace the namespace of the attribute
- * @param name the name of the attribute @return the value of the attribute
- * @throws ParseException thrown if the attribute is not a valid long.
- */
- public long getLongAttribute(String namespace, String name, long defaultValue)
- throws ParseException {
- String value = mParser.getAttributeValue(namespace, name);
- if (null == value) return defaultValue;
- try {
- return Long.parseLong(value);
- } catch (NumberFormatException e) {
- throw new ParseException("Cannot parse '" + value + "' as a long");
- }
- }
-
- /**
- * Close this SimplePullParser and any underlying resources (e.g., its InputStream or
- * Reader source) used by this SimplePullParser.
- */
- public void close() {
- if (source != null) {
- try {
- source.close();
- } catch (IOException ioe) {
- // ignore
- }
- }
- }
-
- /**
- * Returns the string value of the named attribute. An exception will
- * be thrown if the attribute is not present or is not a valid long.
- *
- * @param namespace the namespace of the attribute
- * @param name the name of the attribute @return the value of the attribute
- * @throws ParseException thrown if the attribute is missing or not a valid long.
- */
- public long getLongAttribute(String namespace, String name)
- throws ParseException {
- String value = getStringAttribute(namespace, name);
- try {
- return Long.parseLong(value);
- } catch (NumberFormatException e) {
- throw new ParseException("Cannot parse '" + value + "' as a long");
- }
- }
-
- public static final class ParseException extends Exception {
- public ParseException(String message) {
- super(message);
- }
-
- public ParseException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public ParseException(Throwable cause) {
- super(cause);
- }
- }
-}
diff --git a/core/java/com/google/android/util/SmileyParser.java b/core/java/com/google/android/util/SmileyParser.java
deleted file mode 100644
index ef5d2a9..0000000
--- a/core/java/com/google/android/util/SmileyParser.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.util;
-
-import android.content.Context;
-import android.text.Spannable;
-import android.text.SpannableStringBuilder;
-import android.text.style.ImageSpan;
-
-import java.util.ArrayList;
-
-/**
- * Parses a text message typed by the user looking for smileys.
- */
-public class SmileyParser extends AbstractMessageParser {
-
- private SmileyResources mRes;
-
- public SmileyParser(String text, SmileyResources res) {
- super(text,
- true, // smilies
- false, // acronyms
- false, // formatting
- false, // urls
- false, // music
- false // me text
- );
- mRes = res;
- }
-
- @Override
- protected Resources getResources() {
- return mRes;
- }
-
- /**
- * Retrieves the parsed text as a spannable string object.
- * @param context the context for fetching smiley resources.
- * @return the spannable string as CharSequence.
- */
- public CharSequence getSpannableString(Context context) {
- SpannableStringBuilder builder = new SpannableStringBuilder();
-
- if (getPartCount() == 0) {
- return "";
- }
-
- // should have only one part since we parse smiley only
- Part part = getPart(0);
- ArrayList<Token> tokens = part.getTokens();
- int len = tokens.size();
- for (int i = 0; i < len; i++) {
- Token token = tokens.get(i);
- int start = builder.length();
- builder.append(token.getRawText());
- if (token.getType() == AbstractMessageParser.Token.Type.SMILEY) {
- int resid = mRes.getSmileyRes(token.getRawText());
- if (resid != -1) {
- builder.setSpan(new ImageSpan(context, resid),
- start,
- builder.length(),
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- }
- return builder;
- }
-
-}
diff --git a/core/java/com/google/android/util/SmileyResources.java b/core/java/com/google/android/util/SmileyResources.java
deleted file mode 100644
index 789158f..0000000
--- a/core/java/com/google/android/util/SmileyResources.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.util;
-
-import com.google.android.util.AbstractMessageParser.TrieNode;
-
-import java.util.HashMap;
-import java.util.Set;
-
-/**
- * Resources for smiley parser.
- */
-public class SmileyResources implements AbstractMessageParser.Resources {
- private HashMap<String, Integer> mSmileyToRes = new HashMap<String, Integer>();
-
- /**
- *
- * @param smilies Smiley text, e.g. ":)", "8-)"
- * @param smileyResIds Resource IDs associated with the smileys.
- */
- public SmileyResources(String[] smilies, int[] smileyResIds) {
- for (int i = 0; i < smilies.length; i++) {
- TrieNode.addToTrie(smileys, smilies[i], "");
- mSmileyToRes.put(smilies[i], smileyResIds[i]);
- }
- }
-
- /**
- * Looks up the resource id of a given smiley.
- * @param smiley The smiley to look up.
- * @return the resource id of the specified smiley, or -1 if no resource
- * id is associated with it.
- */
- public int getSmileyRes(String smiley) {
- Integer i = mSmileyToRes.get(smiley);
- if (i == null) {
- return -1;
- }
- return i.intValue();
- }
-
- private final TrieNode smileys = new TrieNode();
-
- public Set<String> getSchemes() {
- return null;
- }
-
- public TrieNode getDomainSuffixes() {
- return null;
- }
-
- public TrieNode getSmileys() {
- return smileys;
- }
-
- public TrieNode getAcronyms() {
- return null;
- }
-
-}
diff --git a/core/java/jarjar-rules.txt b/core/java/jarjar-rules.txt
deleted file mode 100644
index 5fdb022..0000000
--- a/core/java/jarjar-rules.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-rule org.apache.commons com.android.internal.apache.commons
-
diff --git a/core/java/overview.html b/core/java/overview.html
deleted file mode 100644
index b3af0e0..0000000
--- a/core/java/overview.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<body>
- These are the Android APIs.
-</body>